跳至正文
全部策略

策略

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 实验采用风险调整动量和防御性配置;本实验则固定采用源版本的跳月原始收益率排名和等权配置。它们机制相近,仍是保持谨慎的理由,但不是存在优势的证据。固定的当前股票篮子带来幸存者偏差和选择偏差,必须将其报告为平台投资范围实验。

verification_loop:验证失败(第 4 层 — QA 审查)[类别=code_defect]: - [edge_concern] 在 1379 天沙盒中,avg_trade_return_pct 在 104 个已平仓交易腿上为 -1.84%,PF 0.80,夏普比率为 -0.16。空头交易腿仅有 27% 的胜率。对当前的 10 只超大市值股进行 12-1 动量策略,一半做多、一半做空,形成的横截面非常稀薄,往往会受行业贝塔主导(XOM、KO、PEP、PG、JNJ 与科技股相比)。该策略还存在幸存者偏差,并包含模型估算的借券成本(整个沙盒期间约为 1.2%)。应由全历史回测进行衡量;这不是阻塞性问题。 - [严重] 全历史回测必然会崩溃。工厂将回测/优化窗口设为 PRIMARY 个交易腿中最早的目录 K 线起点(subprocess_entry.py:765/994)。对 AAPL.USEQ 来说,该时间为 1980-12-12,但 GOOGL.USEQ 从 2004-08-19 开始,AMZN 1997-05-15,而 MSFT……展开收起

verification_loop:验证失败(第 4 层 — QA 审查)[类别=code_defect]: - [edge_concern] 在 1379 天沙盒中,avg_trade_return_pct 在 104 个已平仓交易腿上为 -1.84%,PF 0.80,夏普比率为 -0.16。空头交易腿仅有 27% 的胜率。对当前的 10 只超大市值股进行 12-1 动量策略,一半做多、一半做空,形成的横截面非常稀薄,往往会受行业贝塔主导(XOM、KO、PEP、PG、JNJ 与科技股相比)。该策略还存在幸存者偏差,并包含模型估算的借券成本(整个沙盒期间约为 1.2%)。应由全历史回测进行衡量;这不是阻塞性问题。 - [严重] 全历史回测必然会崩溃。工厂将回测/优化窗口设为 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('时间戳对齐的 USEQ 动量历史不足')。在回测中,_maybe_process_primary 会重新抛出异常,而不是跳过该 K 线,因此运行会失败。所有起始时间早于 2004 加约 253 个交易时段的滚动前向窗口都会遇到同样的故障。1379 天沙盒没有发现此问题,因为该窗口中所有交易腿都已有完整历史。(第 62 行)— 修复:让初始化过程能够容忍历史不足,而不是抛出异常。当 len(self._rows) < window+1 时,返回 0.0,且不进行再平衡;每处理一根 K 线就追加一条对齐记录。或者,在后续 K 线上持续重新初始化,直到历史数据足够,并在缓冲区较短时清除 _rebalance_due。此外,让 min_bars_required() 检查对齐记录,而不仅仅检查主 K 线。保持假设规则不变(252/22、50%、月度)。 - [警告] 初始化后,只有在处理主 K 线时才会追加记录。如果某个交易腿缺少一个交易时段,屏障就会跳过该时间戳,且不会添加该记录。之后所有交易腿的每个 t-22/t-252 偏移都会错后一档。影响很小,但这与 Moonshot 的 pandas 索引不同;后者会保留 NaN 记录。(第 91 行)— 修复:维持现状可以接受。也可选择跟踪交易时段日期并显式向前跳过。 - [警告] 假设一致性警告(“22 天 K 线”)是误报:22 在每日交易时段中为 RANKING_PERIOD_GAP,且 1-DAY 根 K 线对于 UMD 是正确的。交易品种(10 声明了 USEQ 个名称)、252/22 跳月动量(通过双端队列索引 -23/-253 计算 close[t-22]/close[t-252]-1)、采用 pandas 平均百分比排名且取前后各 50% 名、用 resample('M').last() 标记在日历月末并配合 weights.shift()(若月末并非交易日,则延后一档交易时段生效)、等权的 1/活跃权重且总敞口为 1.0x,以及未设置任何止损或过滤条件,均与源文件一致。再平衡以 K 线时间戳对应的日历月份为准,而非运行计数器。通过明确的 ts 相等检查,防止额外交易腿发生前视。整股数量向零截断。— 修复:无。

实现

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。固定的当前股票投资范围带来幸存者偏差。

验证结果

验证失败(第4层——QA审查)[类别=code_defect]: - [edge_concern] 在1379天的沙盒测试中,avg_trade_return_pct在104个已平仓头寸中为-1.84%,PF 0.80,夏普比率为-0.16。空头头寸仅有27%的时间获利。对10只当前的大盘股做12-1动量、多空各半,横截面非常狭窄,容易受到行业贝塔主导(与科技板块相比,XOM、KO、PEP、PG、JNJ)。此外还存在幸存者偏差,以及建模的借券成本(沙盒测试期间约为1.2%)。全历史回测应当对此进行衡量;这不是阻塞问题。 - [critical] 全历史回测必定会崩溃。策略工厂将回测/优化窗口设为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的首个交易时段。此时……展开收起

验证失败(第4层——QA审查)[类别=code_defect]: - [edge_concern] 在1379天的沙盒测试中,avg_trade_return_pct在104个已平仓头寸中为-1.84%,PF 0.80,夏普比率为-0.16。空头头寸仅有27%的时间获利。对10只当前的大盘股做12-1动量、多空各半,横截面非常狭窄,容易受到行业贝塔主导(与科技板块相比,XOM、KO、PEP、PG、JNJ)。此外还存在幸存者偏差,以及建模的借券成本(沙盒测试期间约为1.2%)。全历史回测应当对此进行衡量;这不是阻塞问题。 - [critical] 全历史回测必定会崩溃。策略工厂将回测/优化窗口设为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天的沙盒测试未发现此问题,因为该窗口内所有腿都已有完整历史数据。(第62行)——修复:让初始化过程能够容忍历史数据不足,而不是抛出异常。在 len(self._rows) >= window+1之前返回0.0且不进行再平衡,并在每根已处理 K 线上追加一行对齐数据。或者,在后续 K 线上继续重新初始化,直到历史数据充足,并在缓冲区数据不足时清除_rebalance_due。另外,让min_bars_required()检查对齐行,而不只是主序列 K 线。保持假设规则不变(252/22、50%、月度)。 - [warning] 初始化后,仅在处理主序列 K 线时才会追加一行。如果某条腿缺少一个交易时段,屏障会跳过该时间戳,也不会添加该行。此后所有 t-22/t-252偏移都会对所有腿错开一个交易时段。影响很小,但与 Moonshot 的 pandas 索引不同,后者会保留 NaN 行。(第91行)——修复:目前可以接受。也可选择跟踪交易日期并显式向前跳过。 - [warning] 假设一致性警告(“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 相等检查来防止前视偏差。整股数量向零截断。——修复:无。

让播种过程容错,而不是抛出异常。在 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% 的时间获胜。尚未进行全历史回测和优化。

放弃原因

verification_loop:验证失败(第4层——QA审查)[类别=code_defect]: - [edge_concern] 在1379天的沙盒测试中,avg_trade_return_pct在104个已平仓头寸中为-1.84%,PF 0.80,夏普比率为-0.16。空头头寸仅有27%的时间获利。对10只当前的大盘股做12-1动量、多空各半,横截面非常狭窄,容易受到行业贝塔主导(与科技板块相比,XOM、KO、PEP、PG、JNJ)。此外还存在幸存者偏差,以及建模的借券成本(沙盒测试期间约为1.2%)。全历史回测应当对此进行衡量;这不是阻塞问题。 - [critical] 全历史回测必定会崩溃。策略工厂将回测/优化窗口设为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……展开收起

verification_loop:验证失败(第4层——QA审查)[类别=code_defect]: - [edge_concern] 在1379天的沙盒测试中,avg_trade_return_pct在104个已平仓头寸中为-1.84%,PF 0.80,夏普比率为-0.16。空头头寸仅有27%的时间获利。对10只当前的大盘股做12-1动量、多空各半,横截面非常狭窄,容易受到行业贝塔主导(与科技板块相比,XOM、KO、PEP、PG、JNJ)。此外还存在幸存者偏差,以及建模的借券成本(沙盒测试期间约为1.2%)。全历史回测应当对此进行衡量;这不是阻塞问题。 - [critical] 全历史回测必定会崩溃。策略工厂将回测/优化窗口设为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天的沙盒测试未发现此问题,因为该窗口内所有腿都已有完整历史数据。(第62行)——修复:让初始化过程能够容忍历史数据不足,而不是抛出异常。在 len(self._rows) >= window+1之前返回0.0且不进行再平衡,并在每根已处理 K 线上追加一行对齐数据。或者,在后续 K 线上继续重新初始化,直到历史数据充足,并在缓冲区数据不足时清除_rebalance_due。另外,让min_bars_required()检查对齐行,而不只是主序列 K 线。保持假设规则不变(252/22、50%、月度)。 - [warning] 初始化后,仅在处理主序列 K 线时才会追加一行。如果某条腿缺少一个交易时段,屏障会跳过该时间戳,也不会添加该行。此后所有 t-22/t-252偏移都会对所有腿错开一个交易时段。影响很小,但与 Moonshot 的 pandas 索引不同,后者会保留 NaN 行。(第91行)——修复:目前可以接受。也可选择跟踪交易日期并显式向前跳过。 - [warning] 假设一致性警告(“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 相等检查来防止前视偏差。整股数量向零截断。——修复:无。

分析

UpMinusDown

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