SolIntradayVwapReversionLS
Hypotheses
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)
Hypotheses
[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.
Hypotheses
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.
Hypotheses
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.
Verification Results
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.
Verification Results
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.
Verification Results
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.
Verification Results
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
Well-formed, frequently-firing strategy with a large, statistically decisive sample (3313 trades over ~6 years)
Backtest Review
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
Backtest Review
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%
Backtest Review
Sharpe -0.40 (CI [-1.30, +0.45]), Sortino -0.45, information_ratio -1.33 vs buy-hold
Backtest Review
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
Backtest Review
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
Backtest Review
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
Verification failed (Layer 4 — QA review):
- FEE-VIABILITY FAILURE (checklist #7): the VWAP-fade mechanism does not clear round-trip trading costs. Over a decisive 1660-trade / 363-day sandbox sample the realized avg_trade_return_pct is -0.016% — net-negative and an order of magnitude below the ~0.10% BINANCE USD-M round-trip taker cost and the 0.15% futures floor. Turnover 297x, avg_holding 2h22m. The exit_z=0.3 reversion band banks tiny sub-fee reversions while the 1.5% stop lets losers run, producing an INVERTED reward:risk despite a 58% win rate: avg_win $75.81 vs avg_loss $156.52 (~2x). Result: total_return -36.1%, PF 0.67, Sharpe -2.19 (CI [-4.07, -0.64] entirely below zero). The rationale's claim that '~0.4-0.6% reversions clear the round-trip' is contradicted by the data — the exit_z quick-bank fires long before. Saturated single-name VWAP-fade class (zero survivors; cf. the 9158-trade SOL VWAP fade at -88%).
- Signal polarity and logic are CORRECT and faithfully implement the hypothesis (z>entry_z -> SELL; z<-entry_z -> BUY; trend-off gate; stop/TP/exit_z/time-stop exits; capital-relative sizing). Noted so the developer does not chase a phantom code bug — the failure is economic, not a coding defect.
Iteration History
Verification failed (Layer 4 — QA review):
- FEE/EDGE FAILURE PERSISTS (checklist #7, L6) — the iteration-2 fee-viability fixes did NOT create edge. Over a DECISIVE 755-trade / 363-day sample the realized avg_trade_return_pct is -0.064% (still net-negative and below the 0.15% futures floor), total_return -21.9%, profit_factor 0.61, Sharpe -2.45 with CI [-4.14, -0.85] ENTIRELY below zero (probabilistic_sharpe 0.001). The min_dev_pct=0.6% floor cut turnover (297x -> 143x) and halved trades (1660 -> 755), but the single-name VWAP-fade has no directional edge net of costs — the saturated zero-survivor class the developer's own caveat concedes 'may simply not exist'.
- INVERTED REWARD:RISK IS BUILT INTO THE PARAMETERS. The reversion target captures ~(entry_z-exit_z)/entry_z = (2.2-0.5)/2.2 = 0.77x the entry deviation (~0.46% at the 0.6% floor). The stop = min(stop_mult*dev, stop_loss_pct) = 1.2*0.6% = 0.72%, LARGER than the 0.46% target -> reward:risk ~0.64 and break-even win rate ~61% vs the realized 53%. The rationale's 'risking ~1.2x what the reversion is worth' is a math error: the reversion is worth only 0.77x the deviation, so stop_mult=1.2 risks ~1.56x the reward — which is why avg_loss $159.66 is still ~1.86x avg_win $85.70. A favorable payoff requires stop_mult BELOW the capture fraction (~0.77), not above it.
- Signal polarity and mechanics are CORRECT and faithfully implement the hypothesis and the iteration-2 changes (z>entry_z -> SELL, z<-entry_z -> BUY; min_dev_pct percent gate; deviation-latched stop; trend-off gate; exit ladder; capital-relative sizing). NO L17 code-defect signature (win_rate 0.53, |Sharpe| 2.45 < 5, PF 0.61). Noted so the developer does not chase a phantom coding bug — the failure is economic, not a code error.
Iteration History
Verification failed (Layer 4 — QA review):
- MECHANISM HAS NO EDGE — now demonstrated DECISIVELY with the payoff geometry corrected. Iteration 3 correctly implemented the required fix (computed _capture_frac, target = capture_frac x entry_deviation, stop_rr=0.7 clamped <1, min_dev_pct raised 0.6->1.2%), and realized reward:risk improved (avg_win $121 vs avg_loss $167, ratio 1.38, up from iter-2's 0.54). Yet over a DECISIVE 499-trade sample it is still a clear loser: avg_trade_return_pct -0.089% (below the 0.15% floor), total_return -16.2%, PF 0.63, win_rate 0.467, Sharpe -2.69 with CI [-4.54, -1.01] ENTIRELY below zero (probabilistic_sharpe 0.0011). The 1.2% deviation floor selects more extreme stretches that trend rather than revert, dropping the win rate to 46.7% — below the ~58% break-even implied by the realized geometry. Fixing the geometry did not create edge because the reversion signal has none net of costs.
- The developer's OWN pre-registered abandonment condition is met. The rationale states verbatim: 'if the next backtest still shows a negative per-trade expectancy with a favourable reward:risk and a ~150-300 trade sample, that is evidence about the mechanism itself and the strategy should be abandoned rather than re-tuned.' The backtest shows exactly that: favourable designed reward:risk, a 499-trade sample, and negative expectancy (-0.089%).
- The code is CORRECT and faithfully implements the iteration-3 fixes (capture_frac from entry_z/exit_z; target_pct = capture_frac * latched deviation; stop_pct = min(stop_rr*target_pct, stop_loss_pct), stop_rr clamped <=0.9; take-profit at target; polarity/trend gate/latching/sizing intact). NO L17 code-defect signature (win 0.467, |Sharpe| 2.69 < 5, PF 0.63). Noted so the developer does not chase a phantom coding bug — the geometry fix worked; the mechanism has no edge.
Backtest and paper results are hypothetical. Trading involves risk of loss.