这一步的目标是为中证500的每一只成分股准备一份独立的 CSV 文件,存放在 stocks_data/ 文件夹中。这些个股数据是计算”市场广度”(breadth)的原材料——策略需要知道每天有多少只成分股站在20日均线上方。
stocks_data/ 文件夹包含 1074 个 CSV 文件,每只股票一个文件(如 000006.SZ.csv),涵盖这只股票从 2018 年 11 月 1 日至今的全部交易日数据。
每个文件有 6 个字段:
| 字段 | 含义 | 用途 |
|---|---|---|
| ts_code | 股票代码 | 标识(如 000006.SZ) |
| trade_date | 交易日期 | 时间轴 |
| close | 收盘价(后复权) | 计算 MA20,判断是否站上均线 |
| pre_close | 前收盘价(后复权) | 辅助校验 |
| vol | 成交量 | 过滤停牌/低流动性 |
| amount | 成交额 | 过滤停牌/低流动性 |
文件按日期降序排列(最新的日期在最上面)。
策略总表 strategy_data.csv 的数据从 2019 年 1 月 1 日开始,但计算 MA20 需要往前看 20 个交易日的收盘价。为了让 2019 年 1 月的 MA20 不缺失,个股数据需要提前约 2 个月,从 2018 年 11 月 1 日开始拉取。
根据 csi500_components_schedule.csv,从 2019 年 1 月 1 日的前一个成分股发布日开始往后统计,一共涉及 1075 只股票。
实际获取 1074 只,少了一只:
600270.SH(外运发展):在 2018 年 12 月 28 日的成分股发布日当天退市。发布日当天它还在名单里,但到 2019 年 1 月 1 日已经没有交易数据了,因此剔除。
退市股票的处理规则:
asof_date >= delist_date → 这只股票不能出现在该期的成分股里asof_date < delist_date → 即使快要退市,只要还没退,照常保留个股价格使用后复权,目的是消除分红、送股等导致的价格跳空,让历史价格和最新价格处于同一尺度上。
计算公式:
后复权收盘价 = 原始收盘价 × 当日复权因子 ÷ 最新复权因子
latest_factor)取该股票最近一天的 adj_factorpre_close 不是简单复权前一天的原始价格,而是取”前一个交易日的后复权收盘价”(即 close.shift(1)),这样才能保证前后一致如果某只股票某天停牌(该交易日没有数据):
这样做的目的是保持 MA20 计算的连续性。如果停牌日留空,均线就会断裂,广度统计结果就不可比了。
数据拉取由脚本自动完成,流程如下:
第 1 步:确定股票清单
stocks_data/ 里已有的 1074 个 CSV 文件名,作为股票列表第 2 步:构建完整交易日序列
trade_cal 接口获取 2018-11-01 至今的上交所交易日历is_open=1 的日期,作为”标准交易日”索引第 3 步:逐只拉取原始数据
pro.daily(日线)和 pro.adj_factor(复权因子)limit + offset)避免单次请求被截断第 4 步:合并 & 后复权
ts_code + trade_date 合并第 5 步:停牌补齐
第 6 步:生成 pre_close
pre_close = close.shift(1)第 7 步:输出
第 8 步:校验
pre_close == 前一交易日的 close,一致性 100%| 项目 | 数值 |
|---|---|
| 股票数量 | 1074 只 |
| 交易天数 | 1729 天(截至数据准备当日) |
| 数据起始日 | 2018-11-01 |
| 策略起始日 | 2019-01-01 |
| 每只股票字段数 | 6 个 |
| 复权方式 | 后复权 |