做什么(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 >200Rounding 契约: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_ma、slow_ma。
已知局限
- Threshold 0.02 hardcoded:API 不暴露,无法从 Canvas 调整
- 默认 .buy() size = 1 股:total_return 对 alpha 几乎不敏感(current-state lock;同 momentum gotcha)
slow_period参数被静默忽略(UI 保留)- Long-only:偏离 > +2% 仅平仓,不开空
- SMA warmup 期间(前 fast_period-1 bars)无 entry
- Sharpe 无 risk-free rate 扣除
- Max drawdown 仅 peak-trough
- Equity curve downsample edge case:bars ∈ (200, 400] → step = 1 → 不降采样
- yfinance auto_adjust=True 固定
- 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 keysrounding_contract— metrics round 4, equity_curve round 6trades_executed— oscillating data 应触发 ≥1 round-tripwin_rate_bounds— ∈ [0, 1]flat_market_no_trades— 平坦 (< 2% 波动) → 0 trades, return 0fetch_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)

