Strategies
SOL USD-M Intraday VWAP-Reversion, Long-Short (Single-Instrument BINANCE Perp, 15m Bars, Fade MODERATE Deviations from Rolling VWAP, Trend-Regime Gated OFF, Frequently-Firing, Low-Parameter)
Outcome: Abandoned
SolIntradayVwapReversionLS
Backtest gate: - metrics unreliable: Incoherent: Sharpe 0.37 disagrees in sign with total_return -88.82% — the Sharpe is computed from the mtm_equity_curve series while the return comes from the equity curve. Judge on…
Hypothesis
[RESTORED 2026-07-10] Original hypothesis text lost to a cascade delete during test-vehicle cleanup (the HL fill-test vehicle shared this hypothesis). Fade moderate z-score deviations from rolling VWAP on SOL USD-M 15m; see experiment config rationale for the full strategy reasoning.
Implements the hypothesis directly: fade MODERATE deviations from a rolling intraday VWAP on SOL USD-M 15m, long+short, trend-regime gated OFF, few parameters. Iteration 4 is a clean restart with correctness-only edits and no change to the signal or entry logic that already passed the earlier layers: (1) the time-stop's bar interval is now measured from consecutive bar timestamps (seeded by bar_seconds) instead of a hardcoded 15-minute nanosecond constant, so max_hold_bars really means bars for whatever bar type is configured; (2) the broad try/except around the time-stop is removed -- bar.ts_event and position.ts_opened are guaranteed ints, so the handler could only mask a real defect; (3) parameters now declare _param_bounds for the stop_rr clamp the constructor enforces (min(stop_rr, 0.9)) plus the other active knobs, so the optimizer never reports a best value the code silently rewrites. Venue stays BINANCE USD-M because the strategy takes short positions; leverage stays 1.0 and sizing does not reference leverage beyond the identity multiplier, so no leverage_set_but_unused risk.
Negative expectancy on a reliable, decisive 3313-trade / 6-year sample: avg_trade_return_pct -0.0798% (below ZERO), profit_factor 0.68, total_return -87.1%, Sharpe -0.40, expectancy -$26.35/trade. The VWAP-reversion fade loses in EVERY calendar year and EVERY vol regime (calm -100%, normal -40.6%, stressed -42.9%), so the mean-reversion premise is measurably absent — this is a statement about the entry/direction, which IS the hypothesis, not a parameter cliff. The stated reward:risk ~1.43 does not manifest (avg_loss 179.97 > avg_win 103.57), the classic bar-close-stop overshoot signature QA flagged, now confirmed on full history. Commission is only 15.5% of gross, so this is not fee-fragility — the signal is gross-negative, and the 5 optimizable knobs cannot invert a PF-0.68 fade. Matches L55 (single-name fade, PF < 1.15, negative return → abandon). QA's edge concern is borne out. Not worth 2 hours of optimization.
Implementation
Intraday VWAP mean-reversion on SOL USD-M perpetual, 15-minute bars, long and short. Every bar it computes a continuous z-score of the close's deviation from a 32-bar (~8h) volume-weighted average price, scaled by RMS dispersion of closes around that anchor. It fades stretched deviations (|z| > 2.2) back toward VWAP -- short above, long below -- but only when the absolute deviation also exceeds a 1.2% fee floor and a loose 24h trend gate (|24h move| < 6%) says the market is oscillating rather than trending. Exits are derived from the same deviation: profit target = capture_frac * entry deviation (capture_frac = (entry_z - exit_z)/entry_z ~ 0.86), stop = 0.7x that target (capped at 1.5%), plus a z-back-inside-0.3 reversion exit and a 24-bar (~6h) time stop. Sizing is 15% of account equity in notional at leverage 1.
Verification Results
Verify FactoryStrategy uses the subclass's min_bars_required() for the warmup gate; if not, guard the -(trend_window+1) access explicitly.
min_bars_required() overrides a framework method (base_shadow warning from static analysis). Here it is deliberate — it raises the warmup to max(vwap_window, trend_window)+2 = 98 bars so the trend_window lookback index -(trend_window+1) is always in range — but confirm the base template honors the override for its warmup gate rather than using its own value, otherwise entries could fire before 98 bars accumulate.
If the hypothesis's reward:risk depends on the stop holding intrabar, implement the stop as a bracket/stop_market order at entry rather than bar-close logic; otherwise document that the effective stop is bar-close only.
The hard stop (pnl_pct <= -stop_pct, ~0.73% of notional) is only evaluated at bar close in should_exit(). On 15m bars a single bar can traverse well past the stop level intrabar, which explains largest_loss -527 vs largest_win 284 and avg_loss > avg_win despite the designed 1.43 reward:risk. This is realistic backtest behavior, not a defect, but the stated risk geometry is not actually enforced intrabar.
Sandbox is deeply negative on a reliable 227-trade / 205-day sample: total_return -8.34%, Sharpe -5.07 (CI [-7.56,-2.81]), profit_factor 0.61, avg_trade_return_pct -0.104% (below zero, roughly the round-trip fee), commission 25.4% of gross, and every vol tercile negative (calm/normal/stressed all lose). Crucially the claimed payoff geometry (reward:risk ~1.43) does NOT manifest: avg_loss 179.9 > avg_win 118.2, i.e. losers are larger than winners. This is consistent with (a) the stop being checked only at bar close, so 15m bars overshoot the derived ~0.73% stop before it can fire, and (b) the z-inside-exit and 24-bar time-stop closing most trades before the ~1.04% target is reached — so the VWAP-reversion edge is not clearing costs on SOL 15m. Not a correctness verdict (this is an unoptimized single draw), but the analyst should verify on full history whether captured deviation actually clears the ~0.10% round-trip and whether an intrabar/bracket stop is needed to make the stated reward:risk real, before spending optimization time.
Backtest Review
- Sharpe
- -0.40
- Total return
- -87.10%
- Max drawdown
- 87.17%
- Trades
- 3313
- Win rate
- 54.2%
- Profit factor
- 0.68
Well-formed, frequently-firing strategy with a large, statistically decisive sample (3313 trades over ~6 years)
Trades correctly implement the hypothesis (fades deviations from rolling VWAP, balanced 1638 long / 1675 short), so this is a fair test of the VWAP-reversion premise
Negative expectancy: avg_trade_return_pct -0.0798% (BELOW ZERO, roughly the ~0.10% round-trip cost), profit_factor 0.68, expectancy -$26.35/trade, total_return -87.1%
Sharpe -0.40 (CI [-1.30, +0.45]), Sortino -0.45, information_ratio -1.33 vs buy-hold
Premise falsified across the board: losing in every calendar year (2020 through 2026) and every vol regime (calm/normal/stressed all negative), so it is not a regime-selection or cliff problem
Inverted payoff geometry: the claimed reward:risk ~1.43 does not manifest (avg_loss 179.97 > avg_win 103.57) — losers are larger than winners, consistent with bar-close stops overshooting on 15m bars
Commission is only 15.48% of gross, so this is NOT fee-fragility — the raw fade signal is gross-negative; there is no positive edge for a fee/threshold tweak to rescue
Analysis
Backtest gate: - metrics unreliable: Incoherent: Sharpe 0.37 disagrees in sign with total_return -88.82% — the Sharpe is computed from the mtm_equity_curve series while the return comes from the equity curve. Judge on the equity curve.
Iteration History
Backtest and paper results are hypothetical. Trading involves risk of loss.