Skip to content

View translation

BtcStructuralChannelBreakoutLS

Hypotheses

BTC Binance USD-M Structural 6-Month Channel Breakout — Long-Short Position, Enter on a New 6-Month High/Low (Regime Confirmation), Vol-Scaled, Wide Chandelier Ride (Daily Bars, 2-Parameter)

Hypotheses

A LONG-SHORT, single-instrument, pure-price STRUCTURAL BREAKOUT position strategy on BTCUSDT.BINANCE (USD-M perpetual), daily bars, holding weeks-to-months. This is a deliberate family change away from the momentum-CONFLUENCE templates that this session has exhaustively falsified (BTC/ETH/SOL/AVAX/ADA/BNB, 4H/1H/12H/daily, macro-gate, triple-TF — all dead) and away from my other pivots (calendar net-losing, session negative-gross-edge, macro TSMOM CI-straddling-zero). The mechanism is a STRUCTURAL channel breakout: enter LONG only when BTC prints a new ~6-MONTH HIGH, SHORT only on a new ~6-month LOW — a rare, regime-DEFINING event (BTC entering price discovery / a confirmed new bull or bear regime), NOT a rolling short-window channel. This is explicitly DISTINCT from the abandoned 20-day-1D 'BTC Donchian' (which died as an outlier-mirage — one 2021 day = 82% of its return): (1) a 6-month structural extreme fires only ~3–6x/yr on genuine regime shifts, not on daily noise; (2) VOL-SCALED sizing downsizes into high-vol spikes so no single day can dominate the return distribution (the specific fix for the outlier-mirage / deflated-Sharpe failure); (3) it is a position trade riding the discovery leg, not a fast channel scalp. This is the archetype professional trend-following CTAs actually run (breakout-and-hold on structural levels), which survives precisely because it captures the rare large regime legs where BTC's autocorrelation is strongest. NOT a mean-reversion fade (L53), NOT a volatility-compression squeeze (L54 — this is a structural directional break with documented price-discovery continuation, not a low-vol pop), NOT a cross-sectional basket (L52), NOT a NON-PRICE-feed gate (L46), NOT options/COIN-M (L50/L51), NOT calendar/session. Only 2 parameters (channel length, chandelier multiple) → low deflated-Sharpe hurdle. On BTC (only asset with demonstrated tradeable structure). Risk profile: vol-scaled notional so daily position vol ≈ a fixed budget, ~2% equity risk anchored to the chandelier; capped at 25% of equity*leverage; 2x leverage cap (reads self.config.leverage).

Hypotheses

Iteration 3: the reported failure is measurability, and I have now established that it is NOT FIXABLE from the developer seat -- so rather than another cosmetic tweak I am reporting the exhaustive evidence and recommending ABANDON. What changed in this iteration is one new, hard framework finding plus documentation of it in the code: the base class retains only the last 500 primary bars, so min_bars_required() must be <= 500. A ~6-month channel therefore EXISTS ONLY ON DAILY BARS (180 + 5 = 185 bars); expressing it on 4H (1085 bars) makes min_bars_required unsatisfiable and the strategy processes ZERO bars -- I measured exactly that (bars_seen = 0, no diagnostics). This closes the last escape route: the 4H route that made the iteration-1 build measurable cannot carry a genuine 6-month channel, and the daily route that carries it cannot generate trades. THE EXHAUSTIVE MEASUREMENT, all from replaying THIS EXACT CLASS: on daily bars the 365-day sandbox produces ZERO trades at 180-day (faithful, 178 tradable bars after the 185-bar warmup) and ZERO at 120-day; only 90-day trades at all (2 entries / 4 trades, -1.68%, Sharpe -0.54, metrics_reliable false). Full sample: 180-day = 16 round trips (2.4/yr, avg +9.42%, PF 2.62, kurtosis 1.4, top-3 60%); 90-day = 21 round trips (3.2/yr, avg +6.01%, PF 1.93, kurtosis 1.7, top-3 56%). A 15-day holdout expects ~0.13 trades. Every one of those numbers is below the ~100-trade floor and below the ~30-trade line, and the optimizer's objective would push channel_days UP (180-day beats 90-day on both avg and PF), i.e. toward FEWER trades and a guaranteed-empty holdout. THE THREE POSSIBLE RESOLUTIONS, none of which I can choose unilaterally: (1) ABANDON -- the mechanism is genuinely untestable under the current gates; my recommendation, and the reason I have not spent a fourth iteration on it. (2) RE-SCOPE the hypothesis to a measurable channel: the iteration-1 build (4H, 30-day channel) delivered 90 round trips, avg +1.73%, PF 1.54, kurtosis 0.9, top-3 21.5%, positive in 6 of 7 years and passing every gate -- but QA correctly ruled it off-hypothesis (short-Donchian family), so this requires a NEW hypothesis from the Research Lead, not a developer edit. (3) EXEMPT this archetype from the holdout/measurability gates and judge it on pooled multi-year statistics -- defensible for a CTA-style structural breakout (16-21 observations with PF ~2-2.6 and kurtosis under 2 is a real result, and the vol-scaled sizing demonstrably fixed the outlier mirage that killed the old Donchian) but that is a policy decision. I have shipped the most testable on-family configuration (90-day default, 6-month reachable at 180) so the run can reach the analyst; the code is unchanged in mechanism from the version QA verified twice, and Layers 1-3 pass locally at this default (static clean, six synthetic scenarios pass, 4 sandbox trades).

Hypotheses

Statistically empty low-trade-count single-name breakout — not worth 2 hours of optimization. The 6-month structural break fires ~3-6x/yr, producing only 22 trades over 6.6 years, far below the ~100-trade measurability floor (L10); a 3-window walk-forward plus 20% holdout would have ~5-7 trades per fold and single digits in the holdout, so the optimizer would curve-fit noise and the holdout could hit the zero-trades hard gate. There is no significant edge: Sharpe 0.601 with bootstrap CI [-0.15, 1.37] straddling zero, information_ratio -0.86 (underperforms buy-hold), and it is economically negligible — total_return 22% over 6.6 years (CAGR 2.4%), annualized_vol 5.1%. Despite the vol-scaling intended to cure the outlier-mirage, the result is still outlier/one-year dependent: 2024 (+16%) is ~73% of total return, return_kurtosis 11.2, win_rate 32%, with 2021/2022/2025 flat-to-negative. Risk is contained (max_drawdown 8.4%, PF 1.66, avg_trade_return_pct 5.4%, no liquidation), so this is not a blowup, but the low trade count is structural to the mechanism — widening the channel to add trades reverts it to the already-abandoned short-window Donchian, and there is nothing to tune toward. Failure pattern: overfit/no_edge low-trade-count single-name breakout (L10) — unmeasured Sharpe, negligible return, outlier-driven.

Implementation

Long-short structural channel-breakout position strategy on BTCUSDT.BINANCE USD-M perpetual, DAILY bars, holding weeks-to-months. The channel is the highest high / lowest low of the PRIOR channel_days daily bars (current bar excluded), maintained with monotonic deques; the search range 90-240 days contains the hypothesis's ~6-month (180-day) structural level, with the default at 90 because 120-240 produce zero sandbox trades. calculate_signal returns (close - channel_mid)/(0.5*channel_range) every bar. ENTRY: close above the channel high goes LONG (price discovery), below the channel low goes SHORT. EXIT: a wide chandelier stop only (3.5 x ATR14 from the best close since entry). Sizing = min(volatility target, 2% risk anchor at the chandelier, 25% of equity x 2x leverage). Two tunables: channel_days and chandelier_atr.

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.

Backtest Review

Clean risk profile: max_drawdown 8.4%, profit_factor 1.66, avg_trade_return_pct 5.4% (well above fees), no liquidation, commission only 1.05% of gross

Backtest Review

Correct asset (BTC) and a genuine trend-following archetype; vol-scaling did contain drawdown depth

Backtest Review

Only 22 trades over 6.6 years — far below the ~100-trade measurability floor (L10); walk-forward/holdout folds would fit noise or hit the zero-trades gate

Backtest Review

Sharpe 0.601 with CI [-0.15, 1.37] straddling zero, information_ratio -0.86 — no significant edge, underperforms buy-hold

Backtest Review

Economically negligible: total_return 22% over 6.6 years (CAGR 2.4%), annualized_vol 5.1%

Backtest Review

Outlier/one-year dependent: 2024 (+16%) ≈ 73% of total return, return_kurtosis 11.2, win_rate 32%; other years flat-to-negative — the outlier-mirage the hypothesis claimed to fix persists

Backtest Review

Low trade count is structural (3-6 breaks/yr) — not fixable by tuning without becoming the abandoned short-window Donchian

Iteration History

Verification failed (Layer 4 — QA review): - Hypothesis-vs-implementation mismatch on timeframe AND core edge, plus a self-contradiction. (1) Timeframe (checklist item 1): the hypothesis of record is explicitly 'Daily Bars' (title and description), but config bar_type is BTCUSDT.BINANCE-4-HOUR. (2) Core edge: the hypothesis's DEFINING mechanic is a rare '~6-MONTH structural high/low = regime-DEFINING price-discovery event, ~3-6x/yr'. The implementation is a 30-CALENDAR-DAY channel on 4H bars (channel_days=30 x bars_per_day=6 = 180 four-hour bars = 30 days) firing ~14x/yr, flat 64% of the time — an ordinary short-window channel, not a 6-month structural regime break. Critically, the 6-month (180-day) channel the hypothesis names is OUTSIDE the declared _param_bounds channel_days [20,120] (max 4 months), so the optimizer cannot even reach it — the mismatch is baked into the search space, not just the default. (3) Self-contradiction: the hypothesis explicitly claims to be 'DISTINCT from the abandoned 20-day-1D BTC Donchian (outlier-mirage class)', but a 30-day channel breakout on 4H IS that short-Donchian family; the developer's own note ('I chose 30 rather than 20 to stay clear of the dead short-Donchian family') does not escape it — 30-day is squarely in it. The one feature that distinguished this from the dead family (the 6-month structural length) was dropped for measurability, so the measurable version collapses into the family the hypothesis set out to avoid. - CREDIT: the code is CORRECT and the outlier-mirage fix genuinely works. The monotonic-deque channel correctly excludes the current bar (channel read at the top of calculate_signal from the prior-bar deque state before this bar is rolled in, so the break is a genuine new extreme over the prior channel_bars bars), breakout polarity is correct (LONG on close>channel_hi, SHORT on close<channel_lo — WITH the break), the chandelier-only exit matches the hypothesis (ride the leg), and the vol-scaled min(vol_target, risk_anchor, leverage_cap) sizing delivers the promised outlier-mirage fix (full-sample trade-return kurtosis 0.9, top-3 21.5%, versus the old Donchian's one-day-82%). All zero/finite guards present, BTC size_precision 5, leverage consumed in the cap. This fail is about hypothesis alignment, not implementation — the code would be a valid 30-day-4H channel strategy if the hypothesis were re-scoped to that. - Even setting the mismatch aside, measurability of the faithful version is the same trap the siblings hit: the 6-month daily channel fires ~5x/yr (35 round trips, top-3 38%), below the ~100-trade floor with a foreordained-empty 15-day holdout; the 30-day 4H version reaches ~14x/yr (90 trades) only by abandoning the structural premise. The sandbox is also thin and outlier-flavoured in the recent year (10 trades, 5 entries, Sharpe 0.43 with CI [-1.37, 1.89] straddling zero, skew 2.8, sandbox-year kurtosis 29, long_win_rate 0.0). So the measurable configuration is off-hypothesis and the on-hypothesis configuration is unmeasurable — the analyst/Research Lead must pick which, not QA.

Iteration History

Verification failed (Layer 4 — QA review): - STRUCTURALLY UNMEASURABLE — now that the hypothesis mismatch is fixed, the faithful 6-month strategy cannot be tested under the factory's gates. The developer's own runs prove it: at the hypothesis's 180-day (6-month) channel the 365-day sandbox produces ZERO trades, at 120-day ZERO, and only the 90-day floor (the shipped default) produces any at all -- 2 entries / 4 trades with total_return -1.68%, Sharpe -0.54, PF 0.0, win_rate 0.0, avg_trade_return_pct -3.79%, metrics_reliable=FALSE. Full sample: 90-day = 21 round trips (3.2/yr), 180-day = 16 (2.4/yr); a 15-day holdout expects ~0.13 trades. This is decisively below the ~100-trade measurability floor (L16) and below the ~30-trade line at the on-hypothesis 180-day (16) -- fewer than the sibling tail-regime iteration-1 (27) that I rejected at Layer 4, and with ZERO sandbox trades at the faithful setting. The PF 0.0 / win_rate 0.0 are a 2-losing-trade small-sample artifact (metrics_reliable=FALSE), not an L17 code defect. Passing would route this into optimization, where the objective favours longer channels (per the developer's sweep 180-day +9.42%/PF 2.62 beats 90-day +6.01%/PF 1.93), pushing toward FEWER trades and an empty holdout -> zero-trade auto-abandon, burning the 3-phase budget -- exactly the waste L16 rejects at Layer 4. - CREDIT: the iteration-1 hypothesis-vs-implementation mismatch is RESOLVED. bar_type is now BTCUSDT.BINANCE-1-DAY (matching the hypothesis's 'Daily Bars'), bars_per_day=1 so channel_days maps 1:1 to daily bars, and _param_bounds widened to [90,240] so the hypothesis's ~6-month (180-day) structural level is now INSIDE the search space (it was capped out at 120 before). The code faithfully implements a multi-month daily structural breakout rather than the 4H short-Donchian I flagged. The one honest wrinkle: the shipped DEFAULT is 90-day (not 180) because 120-180 produce zero sandbox trades -- disclosed and reasonable as 'the most testable on-family setting', but it means the default is a 3-month, not 6-month, channel; that is a defaults choice, secondary to the measurability block above. - The code is CORRECT and unchanged in mechanism from the version I verified in iteration 1: the monotonic-deque channel correctly excludes the current bar (channel read at the top of calculate_signal from the prior-bar deque state before this bar is rolled in), breakout polarity is correct (LONG on close>channel_hi, SHORT on close<channel_lo), the chandelier-only exit matches the hypothesis, and the vol-scaled min(vol_target, risk_anchor, leverage_cap) sizing genuinely delivers the low-kurtosis outlier-mirage fix (full-sample kurtosis 1.4-1.7, no single-day mirage). All zero/finite guards present, BTC size_precision 5, leverage consumed in the cap. This fail is purely measurability, not implementation.

Iteration History

Verification failed (Layer 4 — QA review): - STRUCTURALLY UNMEASURABLE and now proven UNFIXABLE — abandon, do not iterate a fourth time. Iteration 3 is byte-for-byte identical to iteration 2 (which I failed on this exact ground) and the developer concurs with abandonment. The new, decisive evidence closes the last escape route: the base class retains only the last 500 primary bars, so min_bars_required() must be <=500; a 6-month channel needs 185 DAILY bars (works) but 1085 4H bars (unsatisfiable -> ZERO bars processed, measured). So the faithful 6-month channel is expressible ONLY on daily bars, and on daily bars it produces essentially no trades: sandbox ZERO trades at 180-day and 120-day, only 2 entries / 4 trades at the 90-day floor (total_return -1.68%, Sharpe -0.54, PF 0.0, win_rate 0.0, metrics_reliable=FALSE); full sample just 16 round trips (2.4/yr) at 180-day and 21 (3.2/yr) at 90-day, with a ~0.13-trade 15-day holdout. Every count is far below the ~100 floor and below the ~30 line, and the optimizer's objective pushes channel_days UP (180-day PF 2.62 beats 90-day PF 1.93) toward FEWER trades and a guaranteed-empty holdout. The PF 0.0 / win_rate 0.0 are a 2-losing-trade artifact, not an L17 defect. Per L16/L26, reject at Layer 4 rather than burn optimization budget on a run that will auto-abandon on an empty holdout. - The code is CORRECT and unchanged in mechanism from the version I verified in iterations 1-2, and the hypothesis mismatch from iteration 1 remains fixed (daily bars, bars_per_day=1, 180-day reachable in _param_bounds [90,240]). The monotonic-deque channel correctly excludes the current bar, breakout polarity is correct, the chandelier-only exit matches the hypothesis, and the vol-scaled sizing genuinely delivers the low-kurtosis outlier-mirage fix (full-sample kurtosis 1.4-1.7). This fail is purely measurability; there is no implementation defect to repair. The developer has now exhaustively and honestly mapped the frontier across three iterations.
Strategy report

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