1. 课程导入与实战目标
很多投资者都听过一句话:强者恒强。在 ETF 投资里,这句话可以落成一个非常具体的规则——定期比较一批候选 ETF 近一段时间的涨幅,买入排名最靠前的几只,过一段时间再重新排名、换仓。这就是“相对强弱排名选 ETF”策略的基本思想。它不预测大盘涨跌,也不依赖主观判断某只 ETF 好不好,而是用相对表现说话:谁在过去 N 天里涨得更多,谁就更有资格留在组合里。
但“听起来有道理”和“实际能不能赚钱”是两回事。同一套排名规则,换一个回看窗口、换一个调仓频率、换一个持仓数量,结果可能天差地别。如果只凭感觉选参数,很容易陷入“事后看着都对、实盘一用就亏”的陷阱。因此本课程的核心不是教你写一个排名公式,而是带你完成一次完整的策略回测:从数据获取、信号计算、调仓模拟,到绩效评估与参数敏感性分析,最终得到一份能说清楚“这个策略在什么条件下有效、风险在哪里”的结论。
本节要建立的整体流程认知
在动手写代码之前,先把整条链路看清楚。一次可信的 ETF 相对强弱回测,至少包含五个环节,它们之间存在明确的先后依赖关系,任何一个环节处理不当,后面的绩效数字都会失真。
这张图里有两个地方值得特别强调。第一是信号与成交的时间错位:排名必须用 T 日收盘后才能拿到的数据计算,成交只能发生在 T+1 日。很多初学者图省事,直接用当日收盘价买入当日排名第一的 ETF,回测曲线会漂亮得离谱,但这是典型的未来函数,实盘根本无法复现。第二是反馈回路:稳健性检验不是流程的终点,而是迭代的起点。如果参数稍微一动绩效就崩,说明策略本身不牢靠,需要回到规则设计层面重新思考。
候选池与数据:先把“原材料”准备好
相对强弱策略的效果高度依赖候选池的构成。候选池太窄,比如只放三五只宽基 ETF,排名区分度低,策略退化成简单的择时;候选池太宽,又会混入流动性差、跟踪误差大的品种。一个合理的教学示例是选取覆盖不同资产类别和行业板块的 8~12 只场内 ETF,例如沪深300、中证500、创业板、黄金、国债、半导体、医药、消费等,既保证有足够的强弱分化,又便于逐只核查数据质量。
数据方面,必须使用前复权或后复权收盘价。ETF 分红、拆分会导致价格跳空,若用未复权价计算收益率,会把分红误判为下跌,排名信号随之失真。数据字段至少包含交易日期、开盘价、收盘价、成交额;成交额用于过滤流动性不足的交易日,避免在无法成交的价格上“假装”完成交易。数据区间建议覆盖一轮完整的牛熊,例如 2018 年初至 2024 年底,这样绩效评估才有说服力。
本地回测环境:轻量、可控、可复现
本课程不依赖任何商业回测平台,全部在本地用 Python 完成,好处是每一步计算都透明可见,出了问题能定位到具体代码行。环境搭建的核心是三个库:pandas 负责时间序列与表格运算,numpy 负责数值计算,matplotlib 负责净值曲线与回撤图。建议用虚拟环境隔离依赖,并把版本固定下来,保证半年后重跑结果一致。
python -m venv etf_bt
source etf_bt/bin/activate # Windows 用 etf_bt\Scripts\activate
pip install pandas==2.2.2 numpy==1.26.4 matplotlib==3.8.4
目录结构也建议一开始就定好,避免后期文件散乱:data/ 存放原始与清洗后的行情文件,src/ 存放信号计算与回测引擎代码,output/ 存放净值曲线图与绩效表,config.py 集中管理候选池代码、回看窗口、调仓频率、持仓数量、费率等参数。把所有可调参数集中到一处,是后续做参数敏感性分析的前提——否则改一个数字要翻遍整个项目。
实战目标:用可检验的标准代替“感觉不错”
完成本课程后,你应该能独立回答四个问题:这套排名规则在历史区间内的年化收益、最大回撤、夏普比率分别是多少;它与“等权买入持有候选池”这一基准相比是否真的有超额;当回看窗口从 20 日改到 60 日、持仓数从 2 只改到 4 只时,绩效是平滑变化还是剧烈跳变;以及收益主要来自哪些年份、最大回撤发生在什么市场环境下。这四个问题构成了策略评估的最小闭环,也是区分“回测玩具”和“可讨论的策略”的分水岭。