这一步是把所有散落的数据汇总成一张”万能表”,让回测引擎和看板可以直接读取,一行一天,打开就能看到当天的全部市场状态。
strategy_data.csv 是整个策略系统的核心数据文件,一张包含 14 个字段的宽表。以 trade_date(交易日期)为主键,每一行记录了该交易日的指数行情、均线、市场广度、资金热度和 ETF 换手率。
回测引擎(backtest.py)和决策看板(dashboard.py)都直接读取这张表,不需要再去拼接多个数据源。
数据源说明:行情字段(open ~ amount)来自中证500指数(000905.SH),通过
index_daily接口获取,天然全收益口径,无需复权。只有换手率用到了 510500 ETF 的数据。
| 字段 | 类型 | 来源 / 计算方式 | 策略用途 |
|---|---|---|---|
| trade_date | 日期 | Tushare 交易日历 | 主键,时间轴 |
| open | 浮点数 | 000905.SH 指数开盘点位 | T+1 执行价格参考 |
| high | 浮点数 | 000905.SH 指数最高点位 | 记录入场最高价(entry_high) |
| low | 浮点数 | 000905.SH 指数最低点位 | K 线绘图 |
| close | 浮点数 | 000905.SH 指数收盘点位 | 均线计算、收益计算、趋势判断 |
| volume | 浮点数 | 000905.SH 指数成交量 | 辅助参考 |
| amount | 浮点数 | 000905.SH 指数成交额 | 计算 heat_z(资金热度) |
| ma_5 | 浮点数 | close.rolling(5).mean() |
近期支撑线(MA_Support) |
| ma_10 | 浮点数 | close.rolling(10).mean() |
短期趋势线(MA_Trend) |
| ma_20 | 浮点数 | close.rolling(20).mean() |
中期趋势参考 |
| ma_30 | 浮点数 | close.rolling(30).mean() |
长期趋势防守线(MA_Filter) |
| breadth | 浮点数 (0~100) | 每日成分股 close > MA20 的占比 | 冰点抄底 (<16%) / 过热逃顶 (>79%) |
| heat_z | 浮点数 | (amount - 20日均值) / 20日标准差 |
资金热度,>1.5σ 为过热 |
| etf_turnover | 浮点数 | 510500 ETF vol / fd_share_T-1 |
首阴模式入场门槛 (>1.0%) |
最初设计用 510500 ETF 数据,但 ETF 有分红导致价格跳空的问题,需要后复权处理(通过 fund_div 现金分红构造累积因子),还要处理停牌日的价格填充。改用指数(000905.SH)后,这些问题全部消失——指数数据天然就是全收益口径,不存在复权问题,数据管道大幅简化。
ETF 换手率 = 当日成交量 ÷ 基金总份额。但基金份额的变动是在盘后才公布的,所以计算当天的换手率时,分母应该用前一个交易日的份额。代码实现:先对 fd_share 做前向填充(ffill),再 shift(1)。
ma_30 需要往回看 30 个交易日,heat_z 需要往回看 20 个交易日。为了让 2019 年 1 月 1 日的数据不缺失,脚本从 2018 年 11 月 1 日就开始拉取数据(WARMUP_START = '20181101'),这段多拉的数据只用于计算指标,不出现在最终的总表中。
总表由 build_strategy_data.py(v5)一次性生成,分 4 步:
STEP 1 — 拉取指数日线
pro.index_daily(ts_code='000905.SH')STEP 2 — 计算均线和热度
close.rolling(n).mean()(amount - amount.rolling(20).mean()) / amount.rolling(20).std()STEP 3 — 计算市场广度(breadth)
csi500_components_schedule.csv 确定每天的成分股名单stocks_data/ 中各成分股的收盘价,计算 MA20STEP 4 — 计算 ETF 换手率
pro.fund_daily('510500.SH') 获取 ETF 成交量pro.fund_share('510500.SH') 获取基金份额etf_turnover = vol / fd_share.shift(1)最后截取 2019-01-01 以后的数据,输出 14 列 CSV。
总表生成后,逐条对照设计规则进行了验证:
| 规则 | 验证结果 |
|---|---|
| 数据源为 Tushare Pro | 通过 |
| 热身数据从 20181101 开始 | 通过,满足 MA30 和 rolling(20) 需求 |
| 总表 14 列、trade_date 唯一 | 通过,已按 trade_date 去重 |
| 成分股按 asof_date 正确切换 | 通过 |
| breadth 基于后复权收盘价的 MA20 | 通过(个股复权在 stocks_data 阶段已完成) |
| 指数数据无需复权 | 通过 |
| heat_z 基于指数成交额 | 通过 |
| 换手率分母为 T-1 份额 | 通过 |
| vol/amount 使用接口原始单位 | 通过 |
| 项目 | 数值 |
|---|---|
| 文件名 | strategy_data.csv |
| 字段数 | 14 列 |
| 数据行数 | 1729 行(截至构建当日 20260213) |
| 日期范围 | 20190102 ~ 20260213 |
| 空值 | 无 |
| 构建脚本 | build_strategy_data.py v5 |
回测验证(backtest.py):
看板验证(dashboard.py):Streamlit 决策看板已基于该数据表正常运行。