Skip to content

View translation

SolDailyAdxDonchianBreakoutLong

Hypotheses

SOL 1D ADX-Filtered Donchian Breakout Long with EMA Regime Gate

Hypotheses

A long-only single-instrument trend-following strategy on SOLUSDT perpetual futures using daily (1D) bars and ONLY OHLCV data. The strategy combines a 20-day Donchian breakout entry with two strict regime filters: ADX(14) > 25 (genuine trending market, not chop) and close > 50-day EMA (longer-term uptrend alignment). SOL is intentionally chosen to address a portfolio diversification gap — currently no SOL solo strategy exists (only SolAvaxPairsSpreadMeanReversion, which is a market-neutral pair). SOL has 4+ years of clean Binance USD-M data, high beta with strong multi-month directional persistence, and ample liquidity. Designed to be deliberately minimal (4 parameters, 1 instrument, no supplementary data) to avoid the coding-stuck failures (LINK 1D, BTC COIN-M, BNB Weekend, OP-ARB pairs) and verification-bug failures (ETH OI Divergence) that plagued recent multi-data hypotheses. The ADX filter directly addresses the failure mode of the LTC Inside-Bar Breakout (no edge because pattern fired in chop) — by requiring ADX > 25, we mathematically exclude the regime where breakouts have zero predictive value. Daily timeframe ensures fee drag (~0.10% RT) is small relative to typical trend-trade returns (5-30%).

Hypotheses

Iteration 4 fixes the Layer 2 frozen-signal failure. The prior signal was a scale-invariant ratio (close-donchian_upper)/donchian_upper that collapses to a constant under the synthetic generator's geometric down/flat regimes (both close and the channel shrink proportionally). The new calculate_signal builds a continuous, bar-varying value from three terms that respond to every bar's actual movement: the close's position within the Donchian channel, breakout extension above the channel top, and the latest bar return (weighted so any price move produces variation) — guaranteeing non-frozen output in steady_downtrend and flat_ranging while still leaning positive when bullish. The actual entry decision remains driven entirely by _armed (breakout AND ADX>25 AND close>EMA50), so real-data trading behavior and all downstream exit/sizing logic are unchanged. Imports and class structure are untouched, preserving the already-passing Layer 1 static checks.

Hypotheses

verifying_stuck_3_timeouts

Implementation

Long-only daily trend follower on SOLUSDT perpetual futures using pure OHLCV. Enters long when close breaks above the prior 20-day Donchian high AND ADX(14) > 25 AND close > EMA(50). Exits on a trailing 10-day Donchian-low break, a close back below EMA(50), or a 10% protective stop. Leverage 2.0 (notional ~1.2x equity).

Verification Results

Verification failed (Layer 4 — QA review) [class=not_measurable]: - [edge_concern] The 7482% headline / avg_trade_return_pct 54% is an outlier-concentration artifact, not an edge read: 2x-leveraged single-name trend-following riding SOL's 2021 parabola (return_kurtosis 49.3, one +$12.2M largest_win vs -$3.3M largest_loss, max_drawdown 65.7% CI to 96.2%, benchmark_correlation 0.57 to buy-hold). Exactly the '2021-concentrated single-name breakout' failure the hypothesis claims to avoid, and the Donchian-breakout OHLCV family that has repeatedly shown zero survivors. - Too sparse to be measurable: the sandbox ran ~full SOL history (data_days 2179 ~= 6 years) yet produced only 15 trades (avg holding ~29 days; the ADX>25 + close>EMA50 filters make entries even more selective). The holdout HARD gate needs >=10 trades in the last 20% (this run would put ~3 there -> auto-fail), the 3-window walk-forward can't populate, and 15 trades can't separate edge from noise. Promotion is structurally impossible regardless of the headline — a Layer-4 reject to avoid a wasted full backtest + optimization. - position_size rounds to 3 decimals, matching SOL size precision — sizing is capital-relative and physical (avg_position_pct 120.8% == 0.60*2.0). No change needed.

Iteration History

Verification failed (Layer 2 — synthetic scenarios): Parameters used: ['adx_period', 'ema_period', 'min_notional', 'position_pct', 'adx_threshold', 'exit_lookback', 'stop_loss_pct', 'donchian_period'] Check that __init__ sets all attributes from self.parameters.get(). - steady_downtrend: Frozen signal: all 441 signals are identical (value=0.0). calculate_signal() likely has a bug — the signal never varies. - flat_ranging: Frozen signal: all 441 signals are identical (value=0.0). calculate_signal() likely has a bug — the signal never varies.

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.