股票池工程:Universe的定义决定一切
我的掌握程度:
先掌握这个答案
时点正确股票池=每天重新计算:当日实际存在且可交易的股票=全A当日列表 − ST/*ST(当日状态)− 上市<120日 − 停牌 −(可选)成交额后20%。数据要点:用「历史快照」接口或带上市/退市/状态日期的表自行重建——绝不用"当前列表"。选股域两档:①基准域(如中证500内选股):对标指增产品、对冲匹配好;②扩展域(基准±20%市值带):信息更多但暴露管理更难。进化管理:池规则版本化(v1.2剔除了次新)——历史回测的可复现依赖池的冻结。
先读结论,再核对下方使用边界;数字例题为教学情景,涉及实际行情与规则时请核对原始来源。
从理解到使用
本阶段实战方法 · 回测先过时序、成交与成本三道关
把信号变成策略收益时,每笔收益必须能追溯到当时能下出的订单。
- 画出时间线:数据可得→算信号→下单→成交→持仓收益;收盘信号不能倒用当天完整收益。
- 明确交易价格、T+1可卖数量、停牌涨跌停、仓位上限和实际成交量约束。
- 同时报告毛/净收益、换手、最大回撤、基准和样本外结果;对滑点与费率做压力测试。
使用边界
- 简单shift(1)只解决部分时序问题;次日开盘成交还要区分隔夜和日内收益。
- 成本应按成交金额与买卖方向计提;0.15%是教学情景,不是统一市场费率。
背景 · 从一个困惑说起
回测代码第一行不是信号而是股票池——它像实验的"样本框":框错了,后面所有统计都在错误总体上展开。而大多数人随手用"今天的成分股列表",浑然不知已把幸存者偏差焊进了地基。
由此产生的问题
一个"时点正确"的股票池怎么构造(三过滤+历史快照)?选股域(基准域vs扩展域)怎么选?股票池的"进化管理"?
核心概念
时点正确股票池=每天重新计算:当日实际存在且可交易的股票=全A当日列表 − ST/*ST(当日状态)− 上市<120日 − 停牌 −(可选)成交额后20%。数据要点:用「历史快照」接口或带上市/退市/状态日期的表自行重建——绝不用"当前列表"。选股域两档:①基准域(如中证500内选股):对标指增产品、对冲匹配好;②扩展域(基准±20%市值带):信息更多但暴露管理更难。进化管理:池规则版本化(v1.2剔除了次新)——历史回测的可复现依赖池的冻结。
为什么需要它
①总体正确性:统计推断的每一句结论都隐含"在XX总体上"——总体错了结论全错(q-067幸存者数据+20%虚高的来源);②策略可比性:两个策略比较的前提是同池——池不同的比较是关公战秦琼;③容量与风格的入口:池的市值结构决定了策略的容量与风格暴露——调池=调策略性格。
实际应用场景
工程实现:每日股票池存成一张时点表(date×code×in_pool原因字段),所有回测从这张表取池——一处修正全局生效;池统计(每天多少只、市值分布)作为数据体检的一部分。
与之前知识的联系
q-067(幸存者)的工程解药;q-341-343(阶段1过滤三件套)的系统化;q-036(选股域)与本题的"基准域"呼应。
⚠ 常见误解
- 股票池是细节、信号才重要:池是总体、信号是统计量——总体错统计量必错;两者的优先级恰恰相反
- 剔除ST/停牌会美化回测:剔除的是"不可交易"的现实约束——不剔除才是美化(假装能买到停牌股);但要用"当日状态"剔除而非"事后知道它退市"剔除
- 池定了一次管十年:规则会进化(注册制、涨跌停变化)——版本化记录每次改池,保证历史可复现
🛠 本题实践任务
为你的数据建时点股票池表(先做存在性+ST两过滤即可),抽三个历史日期统计池大小;对照"当前列表"的数量差——那就是幸存者偏差的具体规模。
💡 提示(先自己想5分钟再看)
上市/退市日期在tushare的stock_basic(含退市股);ST状态可用namechange历史表重建(粗略版)。
✅ 验收标准
三个日期的池大小对比+与当前列表的差值。你的回测地基从流沙换成了混凝土。
在你的浏览器内运行。首次需联网下载 Python;支持标准库和 Pyodide 提供的 NumPy、pandas 等包。行情抓取、系统文件访问和部分第三方库请在本地环境运行。输出自检仅比对结果关键词,不代替逻辑审查。
Python · 独立工作线程 · 执行限时10秒
🤖 AI导师
导师会先检查你的前置知识(幸存者偏差、选股池三件套),再用案例、公式和代码帮助理解。此功能需要先启用服务。