2026-05-17 20:26:27 +08:00
2026-05-17 15:51:10 +08:00
2026-05-14 10:24:15 +08:00
2026-05-17 20:26:27 +08:00
2026-05-17 20:26:27 +08:00
2026-05-17 15:51:10 +08:00
2026-05-17 20:26:27 +08:00
2026-05-17 20:26:27 +08:00
2026-05-17 15:51:10 +08:00

ashare-data

A股数据抓取工具,以 BaoStock 为主、新浪/腾讯/东方财富为辅,保存到 MySQL 数据库。

功能概览

数据类型 说明 数据来源
股票列表 沪深A股代码、名称、上市日期 BaoStock
交易日历 1990年至今的交易日列表(自动用 stock_daily 校验节假日) BaoStock
日线行情 开高低收、成交量/额、振幅、涨跌幅、换手率(前复权) BaoStock / 新浪 / 腾讯 / 东方财富(多源轮换)
指数日线 上证/沪深300/中证500/中证1000/科创50/深证成指/创业板指/中小板指 BaoStock
涨跌停统计 每日主板(10%)/ 科创创业板(20%)涨跌停数量 stock_daily 汇总
季频财务指标 盈利能力、偿债能力、现金流(最近8个季度,JSON 存储) BaoStock
分红送转 每10股送转、派息、除权除息日(最近10年) BaoStock
分钟K线 5分钟K线(开高低收、成交量/额) 通达信本地客户端(默认) / BaoStock(可选)
概念板块 通达信本地概念板块缓存,缺失时回退同花顺 通达信本地 / 同花顺

已知限制BaoStock 不含北交所(920xxx)股票;新浪/腾讯/东方财富数据源对北交所同样不支持。

快速开始

1. 环境要求

  • Python >= 3.10
  • MySQL >= 8.0

2. 安装依赖

pip install baostock akshare pymysql sqlalchemy pyyaml pandas requests

说明:baostock 为主要数据源;akshare 用于新浪日线兜底和同花顺概念板块列表;requests 用于腾讯/同花顺概念板块抓取;通达信概念板块来自本地缓存文件。 通达信分钟缓存刷新已自动按最多 100 只股票一批拆分;--tdx-cache 会先预热本地缓存,再全历史回填分钟表。--tdx-local-cache 会在预热后自动校验是否真的可读;若只想单独确认缓存是否能被读到,请用 --tdx-verify-cache。注意通达信客户端原生只支持刷新 1m/5m 本地缓存。

通达信本地目录默认读取 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. 先抓取股票列表(其他模块依赖此数据)
python -m src.main --stock-info

# 2. 抓取交易日历(覆盖全历史,只需执行一次;此后每年末执行一次延长至未来)
python -m src.main --trading-day --start-date 19901219 --end-date 20261231

# 3. 抓取全历史日线行情(首次,耗时较长)
python -m src.main --daily --start-date 19901201 --end-date 20260511

# 4. 日常增量更新日线(默认走多源轮换:baostock/sina/tencent/eastmoney
python -m src.main --daily

# 指定单一数据源(默认 all 表示多源轮换+自动切换)
python -m src.main --daily --source baostock
python -m src.main --daily --source sina

# 抓取主要指数日线(上证/沪深300/中证500/中证1000/科创50/深证成指/创业板指/中小板指)
python -m src.main --index

# 抓取指数日线(指定日期范围)
python -m src.main --index --start-date 19901219 --end-date 20260511

# 抓取财务指标(全部股票,最近8个季度)
python -m src.main --financial

# 抓取单只股票的财务数据
python -m src.main --financial --symbol 000001

# 抓取分红送转(全部股票,最近10年)
python -m src.main --dividend

# 抓取单只股票的分红
python -m src.main --dividend --symbol 000001

# 抓取分钟K线(默认5分钟,近30天,默认走通达信本地客户端)
python -m src.main --intraday

# 使用通达信本地客户端抓取分钟K线(默认)
python -m src.main --intraday --intraday-source tdx

# 全历史回填通达信分钟数据(先预热本地缓存,再写入分钟表)
python -m src.main --tdx-cache

# 仅预热通达信本地分钟缓存,并自动校验,不写数据库(原生只刷 1m/5m)
python -m src.main --tdx-local-cache

# 只验证通达信本地分钟缓存是否可读
python -m src.main --tdx-verify-cache

# 抓取5分钟K线
python -m src.main --intraday --start-date 20260101

# 抓取概念板块及成分股(通达信本地,缺失时回退同花顺)
python -m src.main --sector

⚠️ 涨跌停统计 (market_daily) 已实现于 src/fetchers/market_daily.py,但当前 main.py 尚未挂载 --market-daily 参数,暂只能在 Python 内直接调用 fetch_market_daily(...)。详见 TODO.md

5. 命令行参数说明

数据抓取选项:
  --stock-info       抓取A股股票列表
  --trading-day      抓取交易日历
  --daily            抓取日线行情(增量;自动分析数据缺口,已完整自动跳过)
  --source           日线数据源: baostock/sina/tencent/eastmoney/all(默认 all,轮换+失败自动切换)
  --index            抓取主要指数日线
  --financial        抓取季频财务指标(增量;只抓缺失季度)
  --dividend         抓取分红送转数据(增量;只抓缺失年份)
  --intraday         抓取分钟K线行情(增量;只抓缺失日期)
  --intraday-source  分钟K线数据源:tdx/baostock(默认 tdx
  --tdx-cache        全历史回填通达信5分钟数据(先预热本地缓存,再写入分钟表)
  --tdx-local-cache  仅预热通达信本地分钟缓存,并自动校验,不写数据库(原生只刷 1m/5m
  --tdx-verify-cache  只验证通达信本地分钟缓存是否可读,不写数据库
  --freq             K线频率: 5(默认 5
  --sector           抓取概念板块及成分股(增量;本地板块已齐全时跳过)
  --market-daily     汇总每日涨跌停统计(从 stock_daily 聚合)

日期过滤(对日线行情、交易日历、分钟K线、指数生效):
  --start-date       开始日期,格式 YYYYMMDD
  --end-date         结束日期,格式 YYYYMMDD

股票过滤(对财务指标、分红送转、分钟K线生效):
  --symbol           指定单只股票代码,如 000001,默认全部股票

注:--market-daily 在历史版本中存在,当前已下线(功能代码仍保留,但未挂到 main.py)。如需重新启用,参见 TODO.md 中的 "重新挂载 market_daily 命令"。

数据库表结构

stock_info — 股票基本信息

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

stock_daily — 日线行情(前复权)

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

联合主键:(code, date)

stock_financial_income — 季频盈利能力

字段 类型 说明
code VARCHAR(10) 股票代码
report_date VARCHAR(20) 报告期
data TEXT JSON格式数据(ROE、净利率、毛利率等)

联合主键:(code, report_date)

stock_financial_balance — 季频偿债能力

字段 类型 说明
code VARCHAR(10) 股票代码
report_date VARCHAR(20) 报告期
data TEXT JSON格式数据(流动比率、资产负债率等)

联合主键:(code, report_date)

stock_financial_cashflow — 季频现金流

字段 类型 说明
code VARCHAR(10) 股票代码
report_date VARCHAR(20) 报告期
data TEXT JSON格式数据

联合主键:(code, report_date)

stock_dividend — 分红送转

字段 类型 说明
code VARCHAR(10) 股票代码
name VARCHAR(50) 股票名称
report_date VARCHAR(20) 报告期
dividend_date DATE 除权除息日
bonus_ratio FLOAT 每10股送转比例
cash_div FLOAT 每10股派息
convert_ratio FLOAT 每10股转增比例
ex_right_date DATE 除权日
dividend_yield FLOAT 股息率%

联合主键:(code, report_date)

trading_day — 交易日历

字段 类型 说明
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_concept — 概念板块及成分股

字段 类型 说明
code VARCHAR(10) 股票代码
concept_code VARCHAR(20) 概念板块代码(同花顺 BK 编码)
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.520% 板块);跌停反向。当前由 src/fetchers/market_daily.py 提供 fetch_market_daily()main.py 暂未挂载,详见 TODO.md

项目结构

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 按日滚动)
│   ├── baostock_conn.py    # BaoStock 连接管理(login/logout/线程锁/超时重连)
│   ├── db.py               # SQLAlchemy 模型 + 批量 upsert + 自动迁移
│   ├── main.py             # 命令行入口
│   └── fetchers/
│       ├── __init__.py
│       ├── stock_list.py   # 股票列表
│       ├── trading_day.py  # 交易日历
│       ├── daily.py        # 日线行情(多源轮换:baostock/sina/tencent/eastmoney
│       ├── index.py        # 主要指数日线
│       ├── market_daily.py # 每日涨跌停统计(从 stock_daily 聚合)
│       ├── financial.py    # 季频财务指标(盈利/偿债/现金流,JSON 存储)
│       ├── dividend.py     # 分红送转
│       ├── intraday.py     # 分钟K线(5/15/30/60
│       └── sector.py       # 概念板块及成分股(通达信本地 + 同花顺)
├── tests/                  # pytest 测试(48 个用例,纯函数 + mock
├── benchmarks/             # 并发度压测脚本(不在 CI 跑,需真实 MySQL+外网)
└── gzl/                    # 选股脚本(独立子项目,可选)
    ├── Selector.py
    └── select_stock.py

设计说明

  • 多数据源容灾:日线行情默认 --source all 在 BaoStock / 新浪 / 腾讯 / 东方财富之间轮换并自动切换,单源失败不影响整体进度;其他模块(财务、分红、指数)仍以 BaoStock 为主,分钟K线可选本地通达信客户端。
  • 线程安全BaoStock 的 query_xxx() 非线程安全,所有调用通过 src/baostock_conn.py 的全局锁串行化;查询超时/连接断开时自动重连。
  • 去重写入:所有表通过 db.batch_upsert() 走 MySQL INSERT ON DUPLICATE KEY UPDATE,重复执行不会产生重复数据。
  • 全量增量:所有模块均支持增量更新——日线/指数/分钟K线按交易日对比找缺口,财务按缺失季度,分红按缺失年份,概念板块在本地已齐全时跳过。
  • 停牌识别:日线行情若两端已覆盖、内部仍有缺口,则视为停牌,不再重抓。
  • 表结构自动迁移init_db() 会检查并升级旧版 stock_no_data / stock_sector / stock_intraday 的列定义,无需手动改库。
  • 进程内缓存get_stock_codes() / get_ipo_dates() 缓存全量股票代码与上市日期,避免重复扫库。
  • 日志:所有代码通过 from src.log import get_logger 输出;控制台 + logs/ashare.log(按日滚动,保留 7 天)双输出,通过 ASHARE_LOG_LEVEL=DEBUG 切换级别。BaoStock 查询签名走 DEBUG,控制台默认仅看到进度/异常。

运行测试

pip install pytest          # 或 pip install -e ".[dev]"
pytest -v

当前 59 个用例全部通过,覆盖:

  • baostock_conn.code_to_bs / daily._code_to_* 各数据源代码前缀映射
  • daily._fill_derived_fields 振幅/涨跌幅/涨跌额补算
  • _fetch_tencent / _fetch_eastmoney HTTP JSON 解析(mock requests,含空字段、异常包装、北交所短路)
  • financial._recent_quarters 季度滚动跨年
  • market_daily._is_20pct 主板/创业板/科创板/北交所判定
  • tdx_blocks.load_infoharbor_blocks 通达信本地板块缓存解析
  • sector._fetch_concept_list_ths / sector._fetch_concept_stocks_ths 同花顺概念板块解析
  • 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

S
Description
保存A股数据
Readme
336 KiB
Languages
Python 100%