Strategies
SOL weekend lull mean-reversion
Outcome: Abandoned
SolWeekendLullMeanReversionLS
Faithful, well-engineered implementation: timestamp-derived weekend schedule, restart-safe indicators, capital-relative sizing, hard Monday flat — no defect to fix
Hypothesis
SOL/USDT futures weekend mean-reversion. During the low-volatility weekend window (Saturday 00:00 through Sunday 23:59 UTC), fade intraday range extremes: when the 1H close stretches a configurable number of standard deviations (param: entry_sigma, default ~2.0) beyond a short rolling mean (param: ma_period on 1H bars, e.g. 20-EMA), enter a counter-trend position expecting reversion toward the mean. Long when stretched below the mean, short when stretched above. Exit on: (a) reversion back to the mean, (b) a stop beyond the extreme (param: stop_sigma), or (c) a hard time-stop flat at Monday 00:00 UTC. No positions held into the weekday session. Size relative to account equity via get_account_equity() for the ~0.8% hourly-vol weekend regime. Reversion target must clear round-trip fees (>0.15% of notional on Binance USD-M futures). Venue: BINANCE (USD-M futures), instrument SOLUSDT, primary bar_type 1H.
Implementation
Long/short weekend mean-reversion on SOLUSDT.BINANCE USD-M perpetual (1H bars). Each bar it returns -(close - EMA)/stdev(residual) over ma_period as the continuous signal, so the sign is the trade direction. Entry is gated to the Saturday 00:00 - Sunday 23:59 UTC window (derived arithmetically from bar.ts_event, so the schedule is restart- and replay-identical) and requires |z| >= entry_sigma with |z| < stop_sigma so the setup still has room. Exits, first to fire: an unconditional Monday-flat on the first non-weekend bar, a protective stop at stop_sigma beyond the mean tested intrabar, and the reversion target when the moving average is touched intrabar. Sizing risks 2% of equity at the stop and is independently capped at 50% of equity notional. BEHAVIOURALLY UNCHANGED from iteration 2 - the only edit is a recorded falsification block in the module docstring.
Verification Results
CLEAN RESTART 2026-09-04 — this run's verdict history and learning records were removed and it was restarted from verification. Its previous abandonment came from the pipeline, not from the market: the Layer-2 harness mis-bound @staticmethod helpers (fixed), QA issued terminal performance verdicts on an unoptimized smoke test (removed — QA now judges correctness only), and sandbox timeouts came from backtest-slot starvation (fixed). The hypothesis and the strategy code are unchanged. Verify the code on its merits; performance is decided later by the full backtest and the optimizer.
Decisively negative, well-sampled edge (244 trades, PF 0.65, avg_trade_return_pct -0.10%, -17.3%) whose failure is structural not parametric: the weekend regime adds no edge over a generic fade, and the mandated Monday-flat truncates the 12-24h drift horizon. Code faithfully implements the hypothesis (target=mean/stop=beyond-extreme geometry gives the inverted payoff by design), so a mechanism/premise finding for the analyst. Abandon at backtest-review per the developer's pre-registered condition; do not optimize; stop generating SOL-weekend variants.
Backtest Review
- Sharpe
- -0.26
- Total return
- -30.84%
- Max drawdown
- 36.63%
- Trades
- 612
- Win rate
- 60.9%
- Profit factor
- 0.77
Faithful, well-engineered implementation: timestamp-derived weekend schedule, restart-safe indicators, capital-relative sizing, hard Monday flat — no defect to fix
612 trades over 6 years is a large sample, so the negative verdict is statistically reliable, not an unmeasured artifact
Net loser: total_return -30.8%, negative in 5 of 7 years; profit_factor 0.77, expectancy -$49/trade
avg_trade_return_pct 0.031% — far below the 0.15% Binance USD-M fee floor (L22); commissions 16.5% of gross
Sharpe -0.256 (CI straddles zero), information_ratio -1.09, PSR 0.37 — no risk-adjusted edge; avg_loss 2x avg_win (L55 fade payoff asymmetry)
Structural kill: reversion horizon (12-24h, inverts by 48h) is a large fraction of the 48h weekend window, so the mandated Monday-00:00 flat truncates the very drift that carries the edge — unfixable by parameters
Regime premise adds nothing: weekday fade is as strong or stronger than weekend; best-cell t=1.73 < noise-expected 2.82
Iteration History
Verification failed (Layer 4 — QA review): - STRUCTURAL FEE-VIABILITY FAILURE (documented over the full history, not just the sandbox window). Sandbox avg_trade_return_pct = +0.021% net per trade over 98 trades — essentially zero and far below the 0.15% futures floor — with total_return -6.2%, PF 0.80, Sharpe -0.70. This is NOT a small-sample directional miss with large fee-clearing moves; the weekend low-vol regime produces small ~1% moves that net ~zero after the 0.10% round trip. The developer's OWN 6-year, 27-cell grid came out net-negative in EVERY cell (least-bad -0.091% at the shipped defaults), best case ~+0.12% (below the 0.15% floor, not significant, t=1.74). Root cause is structural: the reversion needs ~12h but any risk-bounding stop is hit first. The developer explicitly predicted this Layer-4 failure.
Verification failed (Layer 4 — QA review): - Per-trade edge is below the fee-viability floor and the strategy is net-negative. Layer-3 sandbox (real SOL USD-M fees): avg_trade_return_pct = 0.109% < the 0.15% futures floor; total_return −3.91%, Sharpe −0.77, PF 0.78, negative expectancy over 104 trades. Win rate 61.5% but avg_loss (~$451) ≈ 2× avg_win (~$221) — the weekend low-vol regime makes reversion likely but the moves too small to clear the ~0.10% round trip. Structural, not parameterisable. - Core edge (weekend mean-reversion) empirically falsified across 81 cells / 6 years: max |t|=1.73 vs expected max-|t|≈2.82 under pure noise (best cell weaker than chance — deflated-Sharpe signature), ragged non-monotone stop response, decayed recent years (2023 −0.090%, 2025 −0.193%). The code faithfully implements the hypothesis; the edge is not in the data.
Verification failed (Layer 3 — sandbox backtest): smoke test exceeded the 300s wall-clock limit. This almost always means per-bar work that scales with history — e.g. rescanning the full funding/supplementary series, or rebuilding a list and calling min()/sorted() inside calculate_signal()/on_bar() on every bar. Precompute sorted timestamp arrays ONCE in __init__ and use bisect, or cache lookups keyed by timestamp, so per-bar cost is O(log n) not O(n).
Backtest and paper results are hypothetical. Trading involves risk of loss.