跳至正文
全部策略

策略

US 板块-ETF 横截面动量、美元中性多空策略,带绝对动量防御门控(USEQ,日线,6-1 排名,每月再平衡,做多前-3名 / 做空后-3名,共 SPDR 个板块,2 参数)

结局: 已放弃

UsSectorEtfCrossSectionalMomentumDollarNeutralLS

结局总结

仅有九只板块 ETF 的横截面动量价差过窄,无法形成优势;在无摩擦的交易场所中,PF≈1.03 表示异常不存在,而非对费用脆弱。

假设

ITERATION 2 — 报告的失败发生在 sandbox_timeout(第 3 层),因此第 1、1.5 和 2 层已通过;除标的范围大小和文档外,信号/结构代码保持逐字节不变。我在做任何更改前,分析了完全相同的沙箱运行(相同配置、相同的 2400 天 XLK.USEQ-1-DAY 窗口,并在运行中的进程上使用 py-spy);超时来自该策略每根 bar 的 NOT 工作量:calculate_signal 在固定大小的双端队列上按腿数执行 O(legs) 操作,不持有不断增长的列表,也不会重新扫描历史数据——每个采样都落在 fsspec 的目录遍历中,从未落在策略代码中。耗时来自目录发现:NautilusTrader 的 ParquetDataCatalog 会运行 `glob(data/bar/**/*.parquet)` ONCE PER BAR TYPE(完整遍历目录中约 102,000 个 bar 目录),随后对 crypto_option/binary_option 树执行一次 `instruments()` 遍历;这些都发生在引擎接收第一根 bar 之前。因此,十二种 bar……展开收起

ITERATION 2 — 报告的失败发生在 sandbox_timeout(第 3 层),因此第 1、1.5 和 2 层已通过;除标的范围大小和文档外,信号/结构代码保持逐字节不变。我在做任何更改前,分析了完全相同的沙箱运行(相同配置、相同的 2400 天 XLK.USEQ-1-DAY 窗口,并在运行中的进程上使用 py-spy);超时来自该策略每根 bar 的 NOT 工作量:calculate_signal 在固定大小的双端队列上按腿数执行 O(legs) 操作,不持有不断增长的列表,也不会重新扫描历史数据——每个采样都落在 fsspec 的目录遍历中,从未落在策略代码中。耗时来自目录发现:NautilusTrader 的 ParquetDataCatalog 会运行 `glob(data/bar/**/*.parquet)` ONCE PER BAR TYPE(完整遍历目录中约 102,000 个 bar 目录),随后对 crypto_option/binary_option 树执行一次 `instruments()` 遍历;这些都发生在引擎接收第一根 bar 之前。因此,十二种 bar 类型各自都承担了十二次此类遍历。 (这证实它是共享基础设施成本,而非此机制的问题:目前在这台主机上,同样的 sandbox_timeout 正以相同速率影响着单标的、无额外腿的策略。)策略唯一能影响这项成本的杠杆是 bar 类型的 NUMBER,所以我将标的范围从十一只行业 ETF 缩减到原有的九只 1998 Select Sector SPDR,剔除 XLRE(2015)和 XLC(2018)——将固定的运行前成本削减了 25%。这也是独立来看正确的研究决策:XLC 的 2018-06 起始时间是多腿对齐门槛的限制因素,因此移除它会将可用历史从约 2018 延长至 1998,并为滚动前向和留出窗口提供多得多的独立月份。假设完全保留:仍是横截面 6-1 动量,仍按月再平衡,仍按等美元做多排名前 -3 名 / 做空排名后 -3 名(九个标的意味着中间三个行业保持空仓),仍由绝对动量触发的防御性退出机制决定是否转为现金,仍只有两个边缘参数(formation_days、skip_days),且所有钳制范围都在 _param_bounds 中声明。杠杆 2.0 确实被使用:_rebalance 中的总敞口 = equity x gross_exposure x self.config.leverage。此前通过任何层的内容均未改动——导入项相同、类相同、以日历为锚定的月度安排相同(绝不按 bar 计数)、同步的单行价格缓冲区相同、按交易时段连续计算的 z-score 信号相同。

在决定性的 517-交易、28 年样本上的边际/盈亏平衡期望:profit_factor 1.0296(位于 [0.85,1.10] 拖累区间),avg_trade_return_pct 0.0844%(仅勉强高于 0.05% USEQ 下限),夏普 0.0736,CI [-0.2866, 0.4494] 跨越零。USEQ 佣金为 $0,冲击成本仅为毛额的 34.7%,因此这是一个 GROSS-边际信号,而非手续费脆弱性——仅 9 只行业 ETF(顶部-3/底部-3)的横截面动量价差过窄,不足以构成优势,正是 QA 所担忧的情况,已在完整历史中得到印证。空头腿是拖累(胜率 0.345 对多头 0.60),它在压力情景下亏损(-12.3%)并在 2026 中崩溃(-19.5%)。这是美元中性多空篮子家族(L45,0/N),以及 L75 USEQ 特征(近乎零摩擦场所上的 PF<1.2 = 异常缺失)。PF-1.03 信号无法通过调整 2 形成/跳过参数提升至盈亏平衡以上——不值得花费 2 小时进行优化。abandon_class=negative_expectancy。

实现

在九只最初的 Select Sector SPDR ETF(XLK、XLB、XLE、XLF、XLI、XLP、XLU、XLV、XLY)上,基于 USEQ 日线交易时段柱进行月度横截面 6-1 动量交易。每月按截至 `skip_days` 个交易时段之前的最近 `formation_days` 个交易时段累计收益率对板块排名;组合等美元做多前 3 名,做空后 3 名,因此两条腿名义金额相同,组合按构造即为美元中性。绝对动量防御门控会在任何横截面 MEAN 6-1 动量 <= 0 的月份将组合完全平仓(双重动量策略转为现金),以控制回撤。再平衡通过整股 delta 净额订单执行,最低金额为 $500,因此留在同一分组的标的不会被反复交易。总名义金额 = 权益 x gross_exposure x 杠杆(0.50 x 2.0 = 权益的 1.0x,即 0.5x 多头 + 0.5x 空头),采用声明的 Reg-T 2x 保证金。

验证结果

无需更改;内部缓冲区门控正确地执行了预热。仅作信息说明。

min_bars_required() 覆盖了基础框架方法,返回 30,而非完整的形成期+跳过期回看长度。这是有意为之(实际预热由策略自身的对齐行缓冲区完成,该缓冲区只有在首次调用 calculate_signal 后才会填充),且已有文档说明,但它会遮蔽基础预热门控。已确认无害:_momentum() 在 _rows 达到 _need_rows(148)之前会返回 None,因此缓冲区真正填满之前不会触发信号/交易。

作为研究/性能决策可以接受;分析师评估价差宽度时应注意横截面只有 9 个标的。

投资标的范围从假设所隐含的 11 SPDR 个板块缩减为 9 只最初的 1998 Select Sector SPDR(剔除了 XLRE/XLC)。这仍符合假设意图(横截面 SPDR 板块动量,做多前-3名/做空后-3名,3只标的持平),并显著延长了可用历史至 1998,但横截面略微收窄,降低了该优势所依赖的极端十分位价差。

沙盒冒烟测试结果决定性为负(total_return -18.6%,profit_factor 0.75,夏普 -0.41,avg_trade_return_pct -0.90%,空头腿胜率 25% 对多头 62%)。USEQ 近乎零摩擦(佣金 0,冲击成本仅 $560),因此这是 GROSS-负的回撤,而非手续费拖累——非对称的两腿胜率表明空头(输家)腿是拖累,与行业输家股上的动量崩盘/轧空动态一致。最近的"墓地"为 0/N(贝塔/美元中性多空篮子,UseqResidualMomentumLargeCap 已放弃,SolEth 美元中性已放弃;L45)。该策略是忠实、正确的实现,因此值得运行完整历史与优化器,但分析师应检查仅 9 只行业 ETF(顶部-3/底部-3,3 持平)的横截面价差是否足够宽以在样本外存活,以及空头腿是否承担了亏损。从 1998 起的完整历史跨越约 28 年的月度再平衡,完全可测。

回测评审

夏普
0.07
总收益率
12.20%
最大回撤
25.57%
总交易数
517
胜率
46.8%
盈利因子
1.03

忠实、正确的美元中性实现,具有真实的 28 年 / 517 笔交易的充分样本(metrics_reliable:是)

绝对动量门控确实将杠杆多空组合的回撤限制在适中的 25.6%

profit_factor 1.0296 位于 [0.85,1.10] 费用/冲击成本拖累区间;在近乎零摩擦的 USEQ 上(佣金 $0,冲击成本 34.7% 的毛额),这是一个毛额 MARGINAL/盈亏平衡信号,而非手续费拖累——仅 9 只行业 ETF(顶部-3/底部-3,3 持平)的横截面价差过窄,不足以构成优势

avg_trade_return_pct 0.0844% 仅勉强越过 0.05% USEQ 下限,远低于 0.10% 偏好门槛

夏普比率 0.0736,其 CI [-0.2866, 0.4494] 跨越零;索提诺比率 0.080;recovery_factor 0.38——不存在经风险调整后的优势

空头腿是拖累(空头胜率 0.345,而多头为 0.60)——在全历史数据中,QA 对动量崩盘/空头挤压的担忧得到证实;在压力时期亏损(-12.3%),并在 2026 中暴跌(-19.5%)

匹配 L45(美元/贝塔中性的多空篮子 0/N)和 L75(USEQ PF<1.2 表示异常本身不存在);同日的同类策略 UseqResidualMomentumLargeCap 和 SolEth 美元中性策略均已放弃

迭代历史

sandbox_timeout:验证失败(层级 3——沙盒回测):冒烟测试在约 20000 根柱的窗口(XLK.USEQ-1-DAY-LAST-EXTERNAL 的 2400 天)上超过了 300 秒的墙钟时间限制。这几乎总是意味着每根柱的工作量会随历史长度增长,例如反复扫描完整的资金费率/补充序列,或在每根柱上于 calculate_signal()/on_bar() 内重建列表并调用 min()/sorted()。在 __init__ 中预先计算已排序的时间戳数组 ONCE 并使用 bisect,或按时间戳缓存查找结果,使每根柱的成本为 O(log n) 而非 O(n)。

结局总结

分析师在优化前的回测审查关卡作出“放弃”结论——在无摩擦的 USEQ 上,该 PF-1.03 信号处于盈亏平衡,且无法通过 2 参数调优挽救;因此从未进入优化及后续阶段。

一个由九只最初的 Select Sector SPDR ETF 构成的美元中性多空组合,每月按 6-1 横截面动量对板块排名,做多前 3 名、做空后 3 名,并采用绝对动量门控:当板块整体尚未上涨时将组合平仓。

28 年、517 笔交易的回测:总收益率 12.203(CAGR 0.357),但夏普比率仅 0.0736(CI 跨越零),PF 1.0296,avg_trade_return_pct 0.0844%,最大回撤 25.57%;空头腿是拖累(胜率 0.345,而多头为 0.60)。

Stratmill 是研究与模拟交易工具,不提供财务建议,也不是经纪商。回测与模拟结果均为假设性结果。交易存在亏损风险。