Files
2026-05-22 09:34:49 +08:00

12 KiB
Raw Permalink Blame History

ashare-data

A股数据抓取工具,股票列表、交易日历使用 AKShare,日线行情使用 BaoStock,其余部分按功能分别使用通达信本地缓存或 AKShare,保存到 MySQL 数据库。

功能概览

数据类型 说明 数据来源
股票列表 沪深A股代码、名称、上市日期 AKShare
交易日历 1990年至今的交易日列表 AKShare
日线行情 开高低收、成交量/额、振幅、涨跌幅、换手率(前复权,限沪深 A 股) BaoStock 日线接口
新浪1分钟数据 最近 1 分钟K线(开高低收、成交量/额) AKShare 新浪接口
指数日线 上证/沪深300/中证500/中证1000/科创50/深证成指/创业板指/中小板指 通达信本地缓存
涨跌停统计 每日主板(10%)/ 科创创业板(20%)涨跌停数量 stock_daily 汇总
概念板块 通达信本地概念板块缓存 通达信本地缓存

初始化说明:首次运行 --stock-info / --trading-day 时会自动从 AKShare 拉取并写入数据库;--daily 现在改为 BaoStock 日线接口,只写 stock_daily--daily-no-data-only 仅更新 stock_no_data--sector / --index / --intraday 仍按通达信本地缓存工作,不再依赖 hsjday.zip 这类旧的日线初始化包。

快速开始

1. 环境要求

  • Python >= 3.10
  • MySQL >= 8.0

2. 安装依赖

pip install pymysql sqlalchemy pyyaml pandas requests baostock akshare

说明:当前只需要 pymysqlsqlalchemypyyamlpandasrequestsbaostock 等基础依赖。 如需使用 --sina-min1 命令,还需要 akshare。 通达信分钟缓存刷新已自动按最多 100 只股票一批拆分。注意通达信客户端原生只支持刷新 1m/5m 本地缓存。

--sector / --index / --intraday 等命令需要通达信本地目录,默认读取 config.yaml 里的 tdx.dir

3. 配置数据库

⚠️ 安全提示config.yaml 包含数据库密码,必须保留在 .gitignore 中(本仓库已默认忽略)。请勿在提交前删除此规则。如曾不慎提交真实密码,参见 TODO.md "清理 git 历史中的明文密码"。

复制配置文件并修改 MySQL 连接信息:

cp config.example.yaml config.yaml

编辑 config.yaml

mysql:
  host: "localhost"
  port: 3306
  user: "root"
  password: "your_password"
  database: "ashare"
  charset: "utf8mb4"

fetch:
  delay: 0.1    # 请求间隔(秒)
  retry: 2      # 失败重试次数
  workers: 1    # 并发线程数

tdx:
  dir: "C:\\new_tdx64"  # 通达信安装目录

确保 MySQL 中已创建对应数据库:

CREATE DATABASE ashare CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

4. 运行

# 1. 先抓取股票列表(数据来源: AKShare)
python -m src.main --stock-info

# 2. 抓取交易日历(数据来源: AKShare)
python -m src.main --trading-day --start-date 20100101 --end-date 20261231

# 3. 抓取全历史日线行情(数据来源: BaoStock 日线接口,限沪深 A 股)
python -m src.main --daily --start-date 20260521  --end-date 20260521

# 4. 日常增量更新日线(数据来源: BaoStock 日线接口,限沪深 A 股;只写 stock_daily
python -m src.main --daily

# 4.1 仅更新停牌/无数据记录,不写 stock_daily(数据来源: BaoStock 日线接口,限沪深 A 股)
python -m src.main --daily-no-data-only --start-date 20100101 --end-date 20260517

# 5. 下载新浪 1 分钟数据并写入 stock_min1(数据来源: AKShare 新浪接口,默认 2010 至今)
python -m src.main --sina-min1

# 6. 下载新浪 1 分钟数据并指定区间(数据来源: AKShare 新浪接口)
python -m src.main --sina-min1  --start-date 20260501 --end-date 20260517  --symbol 600519

# 7. 抓取概念板块及成分股(数据来源: 通达信本地缓存)
python -m src.main --sector

# 8. 汇总每日涨跌停统计(数据来源: stock_daily 汇总)
python -m src.main --market-daily

5. 命令行参数说明

数据抓取选项:
  --stock-info       抓取A股股票列表(数据来源: AKShare
  --trading-day      抓取交易日历(数据来源: AKShare
  --daily            抓取日线行情(数据来源: BaoStock 日线接口;限沪深 A 股;增量,自动分析数据缺口,已完整自动跳过;只写入 stock_daily,不更新 stock_no_data
  --daily-no-data-only 仅更新 stock_no_data(数据来源: BaoStock 日线接口;限沪深 A 股;不写入 stock_daily
  --sina-min1        抓取新浪 1 分钟数据并写入 stock_min1(数据来源: AKShare 新浪接口;默认全市场、默认 2010 至今,可配合 --symbol / --start-date / --end-date
  --sector           抓取概念板块及成分股(数据来源: 通达信本地缓存;增量,本地板块已齐全时跳过)
  --market-daily     汇总每日涨跌停统计(数据来源: stock_daily 聚合)
  --symbol           指定单只或多个股票代码,逗号分隔;不传则抓取全市场,供 --sina-min1 使用

日期过滤(对日线行情、交易日历、新浪1分钟生效;新浪1分钟默认 2010 至今):
  --start-date       开始日期,格式 YYYYMMDD
  --end-date         结束日期,格式 YYYYMMDD

数据库表结构

stock_info — 股票基本信息

字段 类型 说明
code VARCHAR(10) PK 股票代码
name VARCHAR(50) 股票名称
ipo_date DATE 上市日期

stock_daily — 日线行情(前复权)

字段 类型 说明
code VARCHAR(10) 股票代码
date DATE 交易日期
open FLOAT NOT NULL 开盘价
close FLOAT NOT NULL 收盘价
high FLOAT NOT NULL 最高价
low FLOAT NOT NULL 最低价
volume FLOAT NOT NULL 成交量
turnover FLOAT NOT NULL 成交额
amplitude FLOAT NOT NULL 振幅%
pct_change FLOAT NOT NULL 涨跌幅%
change FLOAT NOT NULL 涨跌额
turnover_rate FLOAT NOT NULL 换手率%

联合主键:(code, date)

trading_day — 交易日历(AKShare

字段 类型 说明
date DATE UQ 交易日期

stock_no_data — 停牌/无数据记录

字段 类型 说明
code VARCHAR(10) 股票代码
date DATE 停牌/无数据日期

联合主键:(code, date)

stock_min5 — 分钟K线

字段 类型 说明
code VARCHAR(10) 股票代码
datetime DATETIME 时间
open FLOAT 开盘价
high FLOAT 最高价
low FLOAT 最低价
close FLOAT 收盘价
volume FLOAT 成交量
amount FLOAT 成交额

联合主键:(code, datetime)

stock_min1 — 1分钟K线

字段 类型 说明
code VARCHAR(10) 股票代码
datetime DATETIME 时间
open FLOAT 开盘价
high FLOAT 最高价
low FLOAT 最低价
close FLOAT 收盘价
volume FLOAT 成交量
amount FLOAT 成交额

联合主键:(code, datetime)

stock_concept — 概念板块及成分股

字段 类型 说明
code VARCHAR(10) 股票代码
concept_code VARCHAR(20) 概念板块代码
concept_name VARCHAR(100) 概念板块名称

联合主键:(code, concept_code)

index_daily — 指数日线行情

字段 类型 说明
code VARCHAR(10) 指数代码
date DATE 交易日期
open FLOAT 开盘价
high FLOAT 最高价
low FLOAT 最低价
close FLOAT 收盘价
volume FLOAT 成交量
amount FLOAT 成交额
pct_change FLOAT 涨跌幅%

联合主键:(code, date)

market_daily — 每日涨跌停统计

字段 类型 说明
date DATE PK 交易日期
limit_up_10 INT 涨停数(10% 主板)
limit_up_20 INT 涨停数(20% 科创板/创业板)
limit_down_10 INT 跌停数(10% 主板)
limit_down_20 INT 跌停数(20% 科创板/创业板)

阈值:涨停 pct_change >= 9.8(主板)或 >= 19.5(20% 板块);跌停反向。当前可通过 python -m src.main --market-daily 运行 src/fetchers/market_daily.py 提供的 fetch_market_daily()

项目结构

ashare-data/
├── config.yaml             # MySQL 连接配置(.gitignore
├── config.example.yaml     # 配置文件模板
├── pyproject.toml          # 项目元数据
├── requirements.txt        # 运行依赖
├── README.md               # 项目说明(当前文档)
├── TODO.md                 # 已知问题与待办事项
├── src/
│   ├── __init__.py
│   ├── config.py           # 配置读取模块(YAML + 环境变量 ASHARE_CONFIG
│   ├── log.py              # 统一 logging(控制台 + logs/ashare.log 按日滚动)
│   ├── db.py               # SQLAlchemy 模型 + 批量 upsert
│   ├── main.py             # 命令行入口
│   └── fetchers/
│       ├── __init__.py
│       ├── stock_list.py   # 股票列表(AKShare
│       ├── trading_day.py  # 交易日历(AKShare
│       ├── daily.py        # 日线行情(BaoStock
│       ├── index.py        # 主要指数日线
│       ├── market_daily.py # 每日涨跌停统计(从 stock_daily 聚合)
│       ├── sina_minute.py   # 新浪 1 分钟数据(AKShare
│       └── sector.py       # 概念板块及成分股(通达信本地)
├── tests/                  # pytest 测试(66 个用例,纯函数 + mock
├── benchmarks/             # 并发度压测脚本(不在 CI 跑,需真实 MySQL+外网)
└── gzl/                    # 选股脚本(独立子项目,可选)
    ├── Selector.py
    └── select_stock.py

设计说明

  • 数据源分工:股票列表、交易日历使用 AKShare;日线行情使用 BaoStock;概念板块、指数日线、分钟线等仍按功能读取通达信本地缓存;新浪 1 分钟数据使用 AKShare 新浪接口。
  • 线程安全:通达信本地客户端调用集中在 src/fetchers/tdx_client.py
  • 去重写入:所有表通过 db.batch_upsert() 走 MySQL INSERT ON DUPLICATE KEY UPDATE,重复执行不会产生重复数据。
  • 全量增量:所有模块均支持增量更新——日线按交易日对比找缺口,概念板块在本地已齐全时跳过;新浪 1 分钟数据支持按日期过滤后落库。
  • 停牌识别:日线行情若两端已覆盖、内部仍有缺口,则视为停牌,不再重抓。
  • 表结构初始化init_db() 只负责建表。
  • 进程内缓存get_stock_codes() / get_ipo_dates() 缓存全量股票代码与上市日期,避免重复扫库。
  • 日志:所有代码通过 from src.log import get_logger 输出;控制台 + logs/ashare.log(按日滚动,保留 7 天)双输出,通过 ASHARE_LOG_LEVEL=DEBUG 切换级别。

运行测试

pip install pytest          # 或 pip install -e ".[dev]"
pytest -v
  • 当前 66 个用例全部通过,覆盖:
  • daily._ak_hist_to_rows / daily._fill_derived_fields
  • daily._fetch_one_stock BaoStock 日线读取
  • daily.fetch_daily BaoStock 日线抓取与落库
  • intraday._tdx_market_data_to_rows / intraday.fetch_intraday 通达信分钟抓取
  • market_daily._is_20pct 主板/创业板/科创板/北交所判定
  • tdx_blocks.load_infoharbor_blocks 通达信本地板块缓存解析
  • sector._fetch_concept_list / sector._fetch_concept_stocks 通达信本地概念板块解析
  • sector.fetch_sector 概念板块增量跳过逻辑
  • src.log.get_logger 命名空间、handler 幂等、env 控制 level

性能压测

python -m benchmarks.bench_daily --codes 200 --days 30 --workers 1,2,4,8

会依次以指定的并发档位跑一遍真实抓取并输出 speedup 表,用于确定 fetch.workers 的最优档位。详见 benchmarks/README.md

选股子项目 gzl/

gzl/ 目录是独立的选股策略原型(依赖 scipy + 本地 CSV,不读 MySQL)。当前与主项目 src/ 解耦,不参与 python -m src.main 的任何流程。后续是否合并到 src/strategies/TODO.md