Skip to content

做什么(One-liner)

单标的均值回归 backtest:价格偏离 SMA(fast_period) 超 ±2% 阈值时触发买/卖。Backtrader event-driven + yfinance 真实历史 + 10bps 手续费。返回 total_return / Sharpe / max_drawdown / win_rate / 归一权益曲线。

怎么用

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

典型用法:

upstream price_factor → mean_reversion_strategy_v1 (fast_period=20) → portfolio / risk

核心公式

# Strategy (Backtrader event-driven):
deviation = (close - SMA(fast_period)) / SMA(fast_period)

if deviation < -0.02 and flat:  .buy()      # HARDCODED threshold
if deviation > +0.02 and long:  .sell()

# Post-run metrics (same pipeline as momentum):
total_return       = (final - 100k) / 100k                [round 4]
annualized_return  = (1 + tr) ** (252/bars) - 1           [round 4]
sharpe_ratio       = mean(daily)/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), downsample step=len//200 if >200

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

假设与适用场景

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

适用:range-bound 行情的单标的 mean-reversion backtest、Canvas 策略图 overlay、institution 决策后策略方向调整、教学 demo。

不适用:趋势行情(结构性亏损)、intraday / short-sell / 多标的 pair / 需要 custom threshold 的实盘 / crisis periods。

输入 / 输出契约

{symbol?, start_date?, end_date?, fast_period?=20, 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 (buy/sell/neutral)、fast_maslow_ma

已知局限

  1. Threshold 0.02 hardcoded:API 不暴露,无法从 Canvas 调整
  2. 默认 .buy() size = 1 股:total_return 对 alpha 几乎不敏感(current-state lock;同 momentum gotcha)
  3. slow_period 参数被静默忽略(UI 保留)
  4. Long-only:偏离 > +2% 仅平仓,不开空
  5. SMA warmup 期间(前 fast_period-1 bars)无 entry
  6. Sharpe 无 risk-free rate 扣除
  7. Max drawdown 仅 peak-trough
  8. Equity curve downsample edge case:bars ∈ (200, 400] → step = 1 → 不降采样
  9. yfinance auto_adjust=True 固定
  10. akshare 仅对 symbol='GOLD' 生效

参考文献

Poterba-Summers (1988) mean reversion in prices + De Bondt-Thaler (1985) overreaction + Avellaneda-Lee (2010) stat-arb 现代实现。详见 frontmatter。

Golden Test

tests/golden/fixtures/tier2/mean_reversion_strategy/monkey-patched fetch_price_data + 300-day oscillating OHLC (seed=7, 3% sine amplitude / 25-day 周期)。1e-10 tolerance。8 tests:

  • matches_snapshot — 全输出 byte-equal(11 trades, win_rate 1.0 的 synthetic 场景)
  • determinism — 5 reruns 字节一致
  • result_structure — 13 固定 top-level keys
  • rounding_contract — metrics round 4, equity_curve round 6
  • trades_executed — oscillating data 应触发 ≥1 round-trip
  • win_rate_bounds — ∈ [0, 1]
  • flat_market_no_trades — 平坦 (< 2% 波动) → 0 trades, return 0
  • fetch_error_handled — 数据拉取失败 → error 字段设置

:golden fixture 的 100% win_rate 是 synthetic oscillation 特性,代表真实市场 mean-reversion 效果(实际约 0.4-0.6)。

Changelog

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

Verifiable intelligence for the decisions that demand scrutiny.