Skip to content

做什么(One-liner)

单标的动量 backtest:ROC(period=fast_period) > 0 → 买入,< 0 → 卖出。Backtrader event-driven + yfinance 真实历史 + 10bps 手续费。返回 total_return / Sharpe / max_drawdown / win_rate / 归一权益曲线。

怎么用

Canvas 拖 momentum_strategy_v1,上游接 price_factor_v1 节点(或填 symbol)+ 可选 fast_period=10(ROC 窗口)。date range 默认过去 365 天。

典型用法:

upstream price_factor → momentum_strategy_v1 (fast_period=10) → portfolio_optimization

                                                  risk_management_v1

核心公式

# Strategy (Backtrader event-driven):
if ROC(fast_period) > 0 and flat: .buy()     # default size = 1 share
if ROC(fast_period) < 0 and long: .sell()

# Post-run metrics:
total_return       = (final_equity - 100k) / 100k       [round 4]
annualized_return  = (1 + total_return) ** (252/bars)-1 [round 4]
sharpe_ratio       = mean(daily_rtn)/std * √252         [round 4]
max_drawdown       = max((peak - eq)/peak)              [round 4]
win_rate           = won/total on exits                 [round 4]
equity_curve       = [round(v/100k, 6) for v in vals]   [normalized]
                   step = len//200 if len>200 else 1 (gotcha: ≤400 → 1)

Rounding 契约:metrics → 4;equity_curve → 6.

假设与适用场景

假设:daily frequency + ≥30 bars + long-only + $100k 本金 + 10bps commission + 默认 .buy() size=1 股 + no slippage + yfinance auto_adjust=True。

适用:单标的动量 backtest、Canvas 策略图 overlay、institution 决策后策略方向调整、教学 demo。

不适用:intraday / short-sell / 多标的 portfolio / 精细 sizing 实盘 / pre-2000 数据。

输入 / 输出契约

{symbol?, start_date?, end_date?, fast_period?=10, slow_period?=30 (unused), data_source?='yfinance'}{symbol, strategy, start_date, end_date, total_return, annualized_return, sharpe_ratio, max_drawdown, win_rate, num_trades, equity_curve, bars, data_source, error?}

Canvas 在上述基础上附加 signal (long_bias/neutral/short_bias)、fast_maroc_lookback

已知局限

  1. 默认 .buy() size = 1 股:$100k 本金 × 每次 $100 position → total_return 对 alpha 几乎不敏感(current-state lock;修复需加 sizer)
  2. slow_period 参数被 MomentumStrategy 静默忽略(UI 保留,但不影响结果)
  3. Long-only:ROC 翻负仅平仓,不开空
  4. Sharpe 无 risk-free rate 扣除
  5. Max drawdown 仅 peak-trough;无 underwater duration
  6. Equity curve downsample bug:bars ∈ (200, 400] → step = 1 → 实际没降采样(仅在 > 400 才生效)
  7. yfinance auto_adjust=True 固定:分红 / 拆分后 adjusted price(可能改变 ROC 触发时机)
  8. akshare 仅对 symbol='GOLD' 生效,其他 fallback yfinance

参考文献

Jegadeesh-Titman (1993) Cross-sectional momentum + Moskowitz-Ooi-Pedersen (2012) Time series momentum + AQR Trend-following 综述。详见 frontmatter。

Golden Test

tests/golden/fixtures/tier2/momentum_strategy/monkey-patched fetch_price_data + 300-day synthetic OHLC (seed=42)。1e-10 tolerance。8 tests:

  • matches_snapshot — 全输出 byte-equal
  • determinism — 5 reruns 字节一致
  • result_structure — 13 固定 top-level keys
  • rounding_contract — metrics round 4, equity_curve round 6
  • equity_curve_downsampling_contract — 锁定 downsample bug 当前行为(len=290 保持 290)
  • win_rate_bounds — ∈ [0, 1]
  • fetch_error_handled — 数据拉取失败 → error 字段设置,不抛
  • insufficient_data — < 30 bars → error "数据不足"

Changelog

  • 1.0.0 (2026-04-20) — 首次 Active(Tier 2 batch 7)

Verifiable intelligence for the decisions that demand scrutiny.