Skip to content

View original

SolWeekendOvershootReversalLS

Hypotheses

SOL Weekend-Liquidity Overshoot Reversal, Long-Short (Single-Instrument SOLUSDT.BINANCE USD-M Perp, 1h Bars OHLCV-Only, Fade a SIGNIFICANT Friday→Monday Weekend Move at the Monday UTC Open When Institutional Liquidity Returns, Hold ~2 Days, One Trade/Week, 3-Parameter)

Hypotheses

A LONG-SHORT, single-instrument, CALENDAR/seasonality strategy on SOLUSDT.BINANCE (USD-M perp, OHLCV-only — no supplementary feed, the best-surviving tag family at 4%). The edge is a documented weekend microstructure effect that is nearly absent from this portfolio (weekly-cadence bucket is 0.5%): crypto weekend order flow is dominated by thin, retail liquidity because market-makers and institutional desks reduce inventory Fri→Sun. That thinness lets the weekend price OVERSHOOT its fair range; when deeper liquidity returns at the Monday UTC session, the dislocation partially reverts. Mechanism: at Monday 00:00 UTC, measure the volatility-normalized Friday→Monday weekend return; if it is a SIGNIFICANT dislocation (|z| > threshold), enter in the OPPOSITE direction and harvest the mean-reversion as liquidity normalizes, holding ~2 days. This is deliberately NOT any dead class: NOT a breakout, NOT a taker-flow/OI/liquidation feed strategy (those died on data or fees), NOT a funding carry (L33), NOT cross-sectional rotation (L32), and NOT an always-on VWAP fade — it fires at most once per week (~52 trades/yr, ~300 over the ~6-year SOL history), so fee drag is minimal and each trade targets a multi-percent weekend dislocation with large headroom over the ~0.15% futures floor. Only 3 parameters (weekend-move z-threshold, hold days, ATR-stop multiple); the threshold is volatility-normalized rather than a tuned fixed %, to resist the 248 overfit deaths. Fills under-represented long_short (13.8%) and the nearly-empty weekly-seasonality horizon.

Hypotheses

Iteration 3 targets the two blocking Layer-4 QA findings without touching the signal logic that already cleared Layers 1-3 (verified locally: static passes and all six synthetic scenarios pass). (1) Per-trade edge below fees (QA's primary economic complaint): the previous symmetric 2.5-ATR stop == 2.5-ATR TP round-tripped to the stop about as often as it profited (avg_win ~= avg_loss, 0.04% net). The exit is now asymmetric and mechanism-consistent: the take-profit is a REVERSION TARGET set at reversion_frac (0.6) of the weekend dislocation measured from the pre-weekend reference price, so the profit target scales with the multi-percent overshoot the hypothesis is built on (e.g. a ~4% weekend move yields a ~2.4% target, ~16x the 0.15% futures floor and far above the ~0.10% round-trip), while the ATR stop remains the protective leg -- the strategy now preferentially banks the reversion instead of coin-flipping symmetric barriers. (2) Structural non-measurability: entry_z is lowered from 1.0 to 0.6, so the weekly Monday-open gate fires on |z|>0.6 (~55% of weeks, ~28 trades/yr) instead of |z|>1.0 (~30% of weeks, ~15/yr). Over the ~6-year SOL history this lifts the realized count from ~90 to ~170, clearing the 100-trade floor to distinguish edge from noise, while keeping a genuine significance filter (0.6 sigma over a 51h window is still a multi-percent dislocation). (3) The QA-noted minor 51-bar-offset anchor drift is left as-is (QA flagged it non-blocking) to keep the change minimal. Only entry_z, atr_tp_mult (removed) -> reversion_frac (added), and the should_exit take-profit branch changed; imports, the once-per-week trigger, the continuous z signal, sizing, and leverage usage are unchanged.

Hypotheses

The weekend-overshoot-reversal premise is falsified. Fading the significant Friday->Monday move loses money in 6 of 7 years (only 2024 marginally positive +2.8%), ending at total_return -30.3% with Sharpe -0.48 (CI [-1.10, 0.20]), Sortino -0.25, profit_factor 0.80, and PSR 0.08. Across 123 trades avg_trade_return_pct is -0.325% (negative, below the fee floor) with expectancy -$238/trade. The payoff is upside-down: at a ~49% win rate avg_win $2,003 is smaller than avg_loss $2,372 — the reversion-target TP banks fractional wins while the 2.5-ATR stop absorbs larger losses. The weekend dislocation does not partially revert when Monday liquidity returns, so the contrarian entry is systematically on the wrong side; if anything the move continues. Tuning entry_z/hold_days/atr_stop_mult cannot flip a negative expectancy present in every year at a coin-flip hit rate. Not iterate (the code implements the premise correctly) and not revise_hypothesis (the tested mechanism itself is dead; flipping to weekend-momentum would be a different, speculative hypothesis, not a reframe). Abandon per the negative avg_trade_return_pct floor and PF < 1.0.

Implementation

Long-short weekend-overshoot reversal on SOLUSDT.BINANCE USD-M perp using 1h OHLCV only. Once per week, at the first Monday UTC session bar, it measures the volatility-normalized Friday(21:00)->Monday(00:00) weekend log return (weekend move divided by the realized-vol expectation over that ~51h window, giving a z-score). If |z| > entry_z it fades the dislocation: SHORT after a weekend up-move, LONG after a weekend down-move. Exit is now ASYMMETRIC to harvest the reversion: a reversion-target take-profit that captures reversion_frac (default 0.6) of the weekend dislocation (entry price minus the pre-weekend reference price), a protective ATR stop-loss (atr_stop_mult x ATR), and a hold_days time stop. Sizing risks risk_per_trade of equity at the ATR stop, capped at equity x leverage (2x).

Verification Results

Verification failed (Layer 4 — QA review): - Structural non-measurability. The strategy fires at most once per week (Monday-open gate) AND only when |z| > entry_z (1.0). A |z|>1 weekend move occurs ~30% of weeks, so realized cadence is ~15 trades/year — the sandbox confirms 11 trades over 363 days. The hypothesis's '~52/yr, ~300 over 6 years' ignores the z-gate, which cuts weekly cadence by ~70%. Even over the full ~6-year history this is well under 100 trades — below the floor to distinguish edge from noise. Sandbox Sharpe 0.13 with CI [-1.41, +1.78] straddling zero, PSR 0.56: statistically indistinguishable from random. Sending this to optimization repeats the L16/L26 burn. - Realized per-trade edge below fees. Sandbox avg_trade_return_pct 0.04% (net) is under the 0.15% futures floor and barely over the ~0.10% round-trip. Cause is structural: exit uses a symmetric 2.5-ATR stop and 2.5-ATR TP (atr_stop_mult == atr_tp_mult), so the fade round-trips to a stop about as often as it profits (avg_win $2458 vs avg_loss $2515, win_rate 0.55, PF 1.17) rather than preferentially harvesting the reversion the hypothesis claims. - The weekend reference is a fixed 51-bar offset. If the Monday 00:00 bar is missing, the gate fires at hour 1/2 and the 51h window shifts off the Fri 21:00 -> Mon 00:00 anchor by 1-2h. Minor for a multi-percent signal.

Verification Results

Analyst to evaluate over the full ~6-year SOL history (~130-170 trades at weekly cadence). Note: single-name reversal/fade class, which has died repeatedly this session.

Verification Results

Sandbox backtest is a net loser over a SMALL 22-trade / 363-day sample: total_return -11.8%, Sharpe -0.80 (CI [-2.32, 0.88] straddling zero), profit_factor 0.66, avg_trade_return_pct -0.645% (negative, below fee floor), win_rate 0.36. No code-defect signature (win_rate != 0.0, |Sharpe| < 5, profit_factor != 0.0), so this is a realized-edge failure not a bug, and 22 trades (kurtosis 18, skew -1.6) is too few to distinguish edge from noise. For the analyst at backtest_review, not a QA block.

Verification Results

Optional: lock the week only when an entry is submitted, or confirm the semantics. Acceptable as-is.

Verification Results

The weekly gate sets _last_trigger_week in calculate_signal whenever the first eligible Monday bar is seen, regardless of whether an entry fires. If a prior week's ~2-day position is still open on Monday, should_enter isn't called but the week is 'consumed', silently skipping that Monday. Consistent with 'at most once per week' intent; non-blocking.

Backtest Review

Clean single-instrument OHLCV-only design with sensible once-per-week cadence and low fee drag (turnover 16); trades match the hypothesis (weekly Monday-open fades, 55 long / 68 short, ~20h holds)

Backtest Review

max_drawdown 35.8% is below the hard-abandon line — this is an edge failure, not a blow-up

Backtest Review

Negative in 6 of 7 years; total_return -30.3%, no profitable regime

Backtest Review

Sharpe -0.48 (CI [-1.10, 0.20]), Sortino -0.25, profit_factor 0.80, PSR 0.08 — no statistical edge

Backtest Review

avg_trade_return_pct -0.325% (negative, below fee floor), expectancy -$238/trade

Backtest Review

Inverted reward:risk: avg_win $2,003 < avg_loss $2,372 at ~49% win rate — reversion-target TP banks small wins while ATR stop takes bigger losses; weekend move does not revert (premise falsified)

Outcome Summary

SolWeekendOvershootReversalLS tried to exploit a thin-weekend-liquidity effect, fading each significant Friday→Monday move at the Monday UTC open in the expectation that the dislocation would partially revert. The trades matched the design (once-weekly Monday fades, 55 long / 68 short, ~20h holds, low turnover), so the -30.3% result was a clean verdict on the premise: Sharpe -0.48, profit factor 0.80, and negative per-trade expectancy of -$238 with avg_win $2,003 below avg_loss $2,372 at a ~49% win rate. The analyst abandoned it at the backtest-review gate, concluding the weekend move does not revert and that tuning the three parameters could not flip an expectancy negative in six of seven years; it never reached optimization, risk review, or paper trading.

Outcome Summary

A documented microstructure effect does not guarantee a tradable reversion — the SOL weekend overshoot did not mean-revert when Monday liquidity returned (if anything it continued), so a reversion-target-TP/ATR-stop payoff banks small wins while absorbing larger losses.

Outcome Summary

It was abandoned at the pre-optimization backtest-review gate as a falsified-premise edge failure (not a blow-up): the weekend dislocation did not revert on Monday, so the contrarian entry was systematically on the wrong side, and negative expectancy present in every year at a coin-flip hit rate could not be tuned away.

Outcome Summary

A long-short, single-instrument calendar/seasonality strategy on SOLUSDT USD-M perps (1h bars, OHLCV-only) that once per week at the Monday UTC open faded a significant volatility-normalized Friday→Monday weekend move, betting the thin-liquidity weekend overshoot would partially revert as institutional liquidity returned, holding ~2 days with a reversion-target TP, ATR stop, and time stop.

Outcome Summary

Across a 123-trade sample it was negative in 6 of 7 years for a -30.3% total return, with Sharpe -0.48 (CI [-1.10, 0.20]), Sortino -0.25, profit factor 0.80, probabilistic Sharpe 0.08, and a 35.8% max drawdown. Per-trade expectancy was -$238 (avg_trade_return_pct -0.325%, below the fee floor), with inverted reward:risk as avg_win $2,003 fell short of avg_loss $2,372 at a ~49% win rate.

Iteration History

Verification failed (Layer 2 — synthetic scenarios): Parameters used: ['entry_z', 'hold_days', 'atr_period', 'atr_tp_mult', 'min_notional', 'vol_lookback', 'atr_stop_mult', 'weekend_hours', 'risk_per_trade', 'trigger_window_hours'] Check that __init__ sets all attributes from self.parameters.get(). - steady_uptrend: TypeError: FactoryStrategy._bar_ts() takes 1 positional argument but 2 were given (bar timestamp: 1735700100000) - steady_downtrend: TypeError: FactoryStrategy._bar_ts() takes 1 positional argument but 2 were given (bar timestamp: 1735700100000) - flat_ranging: TypeError: FactoryStrategy._bar_ts() takes 1 positional argument but 2 were given (bar timestamp: 1735700100000) - volatility_spike: TypeError: FactoryStrategy._bar_ts() takes 1 positional argument but 2 were given (bar timestamp: 1735700100000) - zero_volume: TypeError: FactoryStrategy._bar_ts() takes 1 positional argument but 2 were given (bar timestamp: 1735700100000) - price_gap: TypeError: FactoryStrategy._bar_ts() takes 1 positional argument but 2 were given (bar timestamp: 1735700100000)
Strategy report

Backtest and paper results are hypothetical. Trading involves risk of loss.