Skip to content

View translation

SolFourHourVolumeConfirmedBreakoutLong

Hypotheses

SOL 4H Volume-Confirmed Breakout Long with Daily Regime Filter

Hypotheses

A long-only single-instrument breakout strategy on SOLUSDT perpetual futures using 4-hour bars and OHLCV-only data, with a daily-bar regime filter. Architecturally MIRRORS the proven BNB 4H Volume-Confirmed Breakout (Sharpe 2.03, paper_stage), applied to SOL with mechanism-and-timeframe orthogonality versus the existing SOL strategy in the pipeline (SolDailyEmaTrendContinuationLong is daily / EMA-crossover-based). Crucially, this proposal acknowledges the recently-documented failure pattern of 'auto-replicating BTC/ETH architecture to other crypto majors without sensitivity validation' (BNB Golden Cross, ETH Spot Drawdown both failed for this reason), and explicitly addresses it by: (a) requiring sensitivity_passed in the optimization phase as a hard gate before promotion (cliff_count must be 0 across all parameters), (b) selecting a SOL-appropriate construction rather than a SOL-inappropriate one — 4H volume-confirmed breakouts match SOL's empirically high-volume retail DeFi trading character (SOL is a top-3 perp by 4H volume, comparable to BNB), versus mean-reversion or shallow-pullback constructions which have failed on SOL repeatedly (Keltner breakout, funding contrarian variants). The construction is fundamentally a TRENDING strategy on a high-momentum asset, NOT a mean-reversion strategy on a smoother asset (which is the failure axis that doomed ETH Spot Drawdown). Single-dominant-filter design (200-day SMA regime + 20-bar 4H high + volume confirmation), explicitly NOT a multi-condition AND-gate. Calibrated for ~30-60 entries/year on 4H bars (matching BNB's empirical signal frequency) — well above the sparsity-failure threshold.

Hypotheses

Fixes the iteration-3 Layer-3 failure (No trades / 0 evaluated bars). Root cause: the base class caps the primary bar buffer at self._max_bars = 500, but min_bars_required() = regime_bars(1200) + 20 + 5 = 1225. Since len(self._bars) can never exceed 500, the `len(self._bars) < min_bars_required()` guard in _maybe_process_primary was permanently true, so _process_primary and therefore should_enter were never invoked. The minimal fix enlarges the bar buffer to regime_bars + 60 (1260) in __init__ so the full 200-day regime history accumulates and min_bars_required is reachable, allowing bars to be evaluated and the breakout entry to trigger. All signal logic, regime/breakout/volume conditions, exits, leverage-consuming sizing, and clean imports (which already passed Layers 1 and 2) are unchanged. This preserves the hypothesis's faithful 200-day (1200 4H-bar) regime filter mirroring the proven BNB architecture, rather than shortening the regime window.

Hypotheses

No robust edge to optimize. Base Sharpe 0.171 with bootstrap CI [-0.593, 0.983] straddling zero, profit_factor 1.079 (<1.2), and information_ratio -1.02 mean the strategy has no significant risk-adjusted edge and underperforms holding SOL. The +17.9% over 6.6 years (~2.9%/yr) is outlier-driven (kurtosis 21.6) and leverage-amplified (avg_position_pct 128%). Market impact already consumes 39.3% of gross with capacity of only $648K, so even the marginal edge is a toy-scale artifact. This is the single-name OHLCV directional breakout zero-survivor class (L9/L41/L63); the paper-stage BNB 4H sibling framing does not transfer — on SOL the same mechanism yields Sharpe 0.17 / PF 1.08, and L82's survivable variant is dual-timeframe momentum-confluence, not a single-name breakout+regime filter. A sub-1.0 base Sharpe on this class is the ceiling; deflation/holdout only lower it and no parameter tuning lifts it to a promotable, robust level. Not fee-limited (avg_trade 0.266%) but not worth 2 hours of optimization. Failure pattern: no_edge single-name directional breakout.

Implementation

Long-only 4H volume-confirmed Donchian breakout on SOLUSDT perpetual futures (Binance USD-M, 2x leverage), gated by a 200-day-equivalent (1200 4H-bar) SMA regime filter computed directly from the primary 4H series. Enters long when price is above the long SMA (bull regime), breaks above the prior 20-bar Donchian high, and volume exceeds 1.5x its 20-bar average. Exits on a 10-bar Donchian-low break, 6% stop-loss, 18% take-profit, or a 30-bar time stop. Pure OHLCV, single instrument.

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.

Verification Results

None required.

Verification Results

200-day regime filter derived from 1200 4H bars rather than actual daily bars — a faithful equivalent, correct. Requires the buffer to hold >1200 bars; the iteration-4 fix (raising _max_bars to 1260) addresses this and the sandbox confirms bars are evaluated.

Verification Results

No action needed.

Verification Results

_bars_held may increment to 1 on the entry bar depending on dispatch order, making the effective time stop ~29-30 bars. Negligible off-by-one.

Backtest Review

Mechanism is correctly implemented (169 trades over 6.6 years, no coverage wall, iteration-4 buffer fix works)

Backtest Review

avg_trade_return_pct 0.266% clears the 0.15% Binance USD-M fee floor

Backtest Review

max_drawdown 23.9% is contained (though CI extends to 76.9%)

Backtest Review

Base Sharpe 0.171 with bootstrap CI [-0.593, 0.983] straddling zero — no significant risk-adjusted edge

Backtest Review

profit_factor 1.079, below the 1.2 meaningful-edge line

Backtest Review

information_ratio -1.02 — underperforms simply holding SOL on a risk-adjusted basis

Backtest Review

impact_cost_pct 39.3% with capacity only $648K — impact eats ~39% of gross, edge is toy-scale

Backtest Review

Single-name OHLCV directional breakout — zero-survivor class (L9/L41/L63); base Sharpe <1.0 is the ceiling

Backtest Review

Headline +17.9% is ~2.9%/yr, outlier-driven (kurtosis 21.6), amplified by 128% avg position

Iteration History

Verification failed (Layer 2 — synthetic scenarios): Parameters used: ['vol_mult', 'vol_period', 'min_notional', 'position_pct', 'exit_lookback', 'max_hold_bars', 'regime_period', 'stop_loss_pct', 'take_profit_pct', 'breakout_lookback'] Check that __init__ sets all attributes from self.parameters.get(). - steady_downtrend: Frozen signal: all 476 signals are identical (value=0.0). calculate_signal() likely has a bug — the signal never varies. - volatility_spike: Frozen signal: all 476 signals are identical (value=0.0). calculate_signal() likely has a bug — the signal never varies. - zero_volume: Frozen signal: all 476 signals are identical (value=0.0). calculate_signal() likely has a bug — the signal never varies. - price_gap: Frozen signal: all 476 signals are identical (value=0.0). calculate_signal() likely has a bug — the signal never varies.

Iteration History

Verification failed (Layer 3 — sandbox backtest): No trades produced Bar type used: SOLUSDT.BINANCE-4-HOUR-LAST-EXTERNAL, Bars processed: 12467 Diagnostics: should_enter() returned a side 0 times over 12443 evaluated bars -> your ENTRY CONDITION never triggered. Loosen the entry logic / thresholds. Ensure your strategy produces trades with the given data and parameters.

Iteration History

Verification failed (Layer 3 — sandbox backtest): No trades produced Bar type used: SOLUSDT.BINANCE-4-HOUR-LAST-EXTERNAL, Bars processed: 12665 Diagnostics: should_enter() returned a side 0 times over 0 evaluated bars -> your ENTRY CONDITION never triggered. Loosen the entry logic / thresholds. Ensure your strategy produces trades with the given data and parameters.

Iteration History

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).
Strategy report

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