策略
QuantRocket UpMinusDown:固定252/22日股票动量,月度多空等权
结局: 已放弃
QuantRocketUpMinusDownFixedStockMomentum
结局总结
该策略将 QuantRocket 固定跳月动量规则翻译为一个已声明的十只股票USEQ股票池,并采用月度多空等权配置。沙盒测试中,其平均交易收益为负,104个已平仓头寸的夏普比率为-0.16。经过三轮迭代,第QA层发现一个阻塞性的预热缺陷,该缺陷由标的历史数据起始日期不同导致;因此,在进行全历史回测或优化前,策略已被放弃。
假设
忠实翻译 QuantRocket LLC 的 Apache-2.0 UpMinusDown 信号与配置规则,并明确声明平台标的和成本。来源:https://github.com/quantrocket-codeload/moonshot-intro/blob/8717e87e279e3615bdd4c7787ce746b92d0713d7/intro_moonshot/umd.py. 保留 MOMENTUM_WINDOW=252、RANKING_PERIOD_GAP=22、TOP_N_PCT=50 和 REBALANCE_INTERVAL='M'。使用同步的USEQ日交易时段 K 线。UpMinusDown 基类未指定股票池;本实验声明了固定的十只股票平台股票池,并未声称复现演示中未明确指定成员的 usstock-free 股票池。UpMinusDownDemo 另外设置 CODE='umd-demo'、DB='usstock-free-1d'、UNIVERSES='usstock-free'、TOP_N_PCT=50 和 COMMISSION_CLASS=USStockCommission;该佣金类规定每股收取 $0.005。我们的实验使用 USEQ 的零佣金,并改用建模的价差和冲击成本。不允许优化、添加过滤条件、止损或按信号强度调整仓位。
用户要求忠实于源版本,这决定了采用的机制和股票市场;改成加密货币、期权或不同的排名方案都会违反该要求。这提供了多交易品种的多空敞口,弥补了投资组合 82.6% 仅做多所造成的集中度问题。未提供语料库中的交易品种集中度。失败的行业-ETF 实验采用风险调整动量和防御性配置;本实验则固定采用源版本的跳月原始收益率排名和等权配置。它们机制相近,仍是保持谨慎的理由,但不是存在优势的证据。固定的当前股票篮子带来幸存者偏差和选择偏差,必须将其报告为平台投资范围实验。
实现
Stratmill 将 QuantRocket UpMinusDown 策略翻译为固定的10只股票USEQ股票池。策略按每只股票跳过最近一个月后的12个月收益率排名(close[t-22]/close[t-252]-1),等权做多排名前50%名、做空后50%名,并采用每个日历月的最后一个信号。该信号在下一个交易时段生效(与 weights.shift() 一致),并持有至下一次月度再平衡。
本次迭代通过移除不允许的 zoneinfo 导入,修复了唯一的第 -1 层故障。USEQ 日线柱线的时间戳标记为 16:00 ET 交易时段收盘时刻(20:00 或 21:00 UTC;半日交易时段则为 17:00 或 18:00 UTC),因此 UTC 日历日期始终等于纽约交易时段日期,月界检测保持不变。信号、排名、再平衡和仓位规模逻辑与上一迭代相同。平台适配:(1)成交来自下一交易时段的市价单,而非 Moonshot 的开盘到开盘回报;(2)股数为整数并向零取整;(3)成本为 USEQ 的零佣金加建模点差和冲击成本,而非每股 $0.005。固定的当前股票投资范围带来幸存者偏差。
验证结果
让播种过程容错,而不是抛出异常。在 len(self._rows) >= window+1 之前返回 0.0 且不进行再平衡,并在每根处理过的柱线上追加一行对齐数据。或者,在后续柱线上持续重新播种,直到历史数据足够;缓冲区偏短时清除 _rebalance_due。还要让 min_bars_required() 检查对齐行,而不仅仅检查主柱线。保持假设规则不变(252/22、50%、月度)。
全历史回测必定会崩溃。策略工厂将回测/优化窗口设为PRIMARY腿目录中首根 K 线的时间(subprocess_entry.py:765/994)。对AAPL.USEQ而言,该时间是1980-12-12,但GOOGL.USEQ从2004-08-19开始,AMZN 1997-05-15和MSFT 1986-03-13。基础模板的对齐屏障会暂停主序列处理,直到每条同步腿在同一时间戳都有 K 线。因此,首根被处理的 K 线是GOOGL的首个交易时段。此时 len(self._bars)=275 >= min_bars_required,但额外腿的缓冲区各只有一根 K 线。_seed_rows 找到1条对齐行(需要253),并抛出 ValueError('Insufficient timestamp-aligned USEQ momentum history')。在回测中,_maybe_process_primary 会重新抛出异常,而不是跳过该 K 线,因此运行失败。所有起始时间早于2004加约253个交易时段的滚动窗口都会遇到同一故障。1379天的沙盒测试未发现此问题,因为该窗口内所有腿都已有完整历史数据。
目前可以接受。也可选择跟踪交易日期并显式向前跳过。
初始化后,仅在处理主序列 K 线时才会追加一行。如果某条腿缺少一个交易时段,屏障会跳过该时间戳,也不会添加该行。此后所有 t-22/t-252偏移都会对所有腿错开一个交易时段。影响很小,但与 Moonshot 的 pandas 索引不同,后者会保留 NaN 行。
无。
假设一致性警告(“22日 K 线”)是误报:22相当于RANKING_PERIOD_GAP个日交易时段,而1-DAY根 K 线对UMD是正确的。标的(10声明了USEQ个名称)、252/22跳月动量(close[t-22]/close[t-252]-1,通过 deque 索引-23/-253)、pandas 平均百分位排名及前后各50%名、resample('M').last() 在日历月末标记且使用 weights.shift()(当月末不是交易时段时,下一交易时段生效)、等权1/活跃权重且总敞口为1.0x,以及不设止损或过滤条件,均与源策略一致。再平衡按 K 线时间戳对应的日历月份锚定,而非按运行时长计数。额外腿通过显式的 ts 相等检查来防止前视偏差。整股数量向零截断。
迭代历史
验证失败(第1.5层——假设/配置一致性)[类别=hypothesis_mismatch]: - optimization_plan将杠杆固定为1.0 另请注意: - 假设写明22日 K 线,但 config.bar_type为AAPL.USEQ-1-DAY-LAST-EXTERNAL(1-DAY)——QA会拒绝与假设矛盾的时间框架;请调整bar_type或修改文本。
验证失败(第1层——静态分析): - 导入项不在沙盒允许列表中:from zoneinfo ——策略可导入 __future__、abc、bisect、calendar、collections、copy、dataclasses、datetime、decimal、enum、fractions、functools、heapq、itertools、json、math、nautilus_trader、numpy、operator、re、src、statistics、string、typing(第11行)
结局总结
预热就绪状态必须取决于所有篮子交易腿的同步历史数据,只有在存在足够的对齐行后才开始交易。
经过三轮迭代,第4层QA验证失败,因为标的历史数据不匹配会导致对齐的预热行不足,并使全历史回测崩溃。沙盒测试表现较弱已明确判定为非阻塞因素。
对十只USEQ股票应用固定的252/22交易时段动量排名,按月进行多空等权配置,不做优化或添加过滤条件。
QA 报告称,在为期 1,379 天的沙盒中,104 个已平仓交易腿的沙盒夏普比率为 -0.16,利润因子为 0.80,平均单笔交易回报为 -1.84%;做空腿有 27% 的时间获胜。尚未进行全历史回测和优化。
放弃原因
分析
UpMinusDown
Stratmill 是研究与模拟交易工具,不提供财务建议,也不是经纪商。回测与模拟结果均为假设性结果。交易存在亏损风险。