XrpPerpBasisIgnitionContinuationLS
Hypotheses
XRP Perp Basis-Ignition Continuation — Long-Short: Ride the Momentum Burst When the Perp's Premium-to-Index EXPANDS Rapidly (Accelerating Leveraged Demand), Exit Fast When the Basis Stalls (BINANCE XRPUSDT USD-M, Daily Bars, Premium-Index-Gated, 3-Parameter)
Hypotheses
A LONG-SHORT, single-instrument DIRECTIONAL momentum-ignition strategy on the XRP USD-M perpetual that uses the PERP-vs-INDEX BASIS VELOCITY as the fuel gauge, not the price. When the perpetual's premium over its index (the mark-minus-index / premium-index feed) is EXPANDING rapidly — accelerating leveraged demand piling in on one side — price tends to CONTINUE in that direction for a short burst before the leverage exhausts. The strategy goes LONG when the basis is rapidly widening positive AND price confirms an up-break, SHORT when the basis is rapidly widening negative AND price confirms a down-break, then EXITS FAST when the basis-velocity stalls (the ignition is spent) to sidestep the reversion that follows. This is deliberately NOT my two pending Hyperliquid proposals (OI-confirmed breakout, funding-contrarian reversion): different venue (Binance), different asset (XRP), different feed (premium-index velocity), and OPPOSITE sign to the funding-reversion idea (this RIDES the crowd's ignition burst rather than fading crowded extremes). It is NOT a pure-OHLCV trend clone (the entry is gated by a supplementary microstructure signal with real predictive content), NOT a fade, NOT a market-neutral pair/basket (L45), NOT options/CM. XRP is a high-retail-leverage name whose basis routinely blows out on positioning surges, giving a strong, frequent ignition signal. Fills the under-represented long_short bucket (14.2% vs ~45% target).
Hypotheses
QA was right on every count, and this iteration finds the actual root cause instead of guessing. I stopped estimating and ran the real engine (run_backtest_in_subprocess) directly. TWO defects, both of the same family - code that behaves differently in-process than in the engine. (A) FEED SUBSTITUTION. The Layer-3 sandbox builds supp from PipelineProcessor._collect_supplementary_data(), whose return dict does NOT contain premium_index (it has funding_rates, liquidations, open_interest, top/global/taker ratios, metrics, hl_funding_rates, deribit_dvol, deribit_funding). Because my code referenced the key by name, the sandbox filled it from _synthetic_supp_for_used(), whose generator samples bars[::60] - SIX records over a 320-bar window, ELEVEN over 640. With a trailing bar-width window over ~8 points nearly every lookup hit the carry-forward branch, velocity was ~0, and the engine produced 2-3 trades. That is also why the iteration-2 clock change moved the count only 2 to 3: the synthetic sampler is per-60-BARS, so a finer clock adds no records. Meanwhile the FULL backtest uses supp_collector.load_supplementary_data, which DOES load premium_index - I confirmed this by running the iteration-2 code through the engine on that path and getting 26 trades. Both numbers were real; they came from different feeds. My iteration-2 claim was not fabricated, but I validated against the wrong loader, and QA is correct that the sandbox is ground truth. FIX: read the basis from funding_rates, which is real and dense in BOTH loaders (9,795 points, 8-hourly, 2020-01 to 2026-08, 1,513 in the last year, zero empty trailing windows) so the two paths cannot diverge. This is the same economic quantity, not a new edge - Binance funding is defined as the premium index plus a clamped interest term. One declared source, no fallback branch. (B) DUAL-KEY / JSON. funding_rates carries every timestamp as both an int and a str key, and the backtest subprocess receives its config as JSON, where object keys are always strings - so the int keys do not survive the parent-to-subprocess hop. My first funding parser filtered to isinstance(key, int); it parsed perfectly in-process and returned an EMPTY series in the engine, giving literally 0 trades. I caught this only because I ran the engine: entry_diag showed bars_seen=333, entry_signaled=0. Accepting both key types and de-duplicating fixed it. (C) TIMEFRAME reverted to 1-DAY per the hypothesis - the 12-HOUR deviation never fixed the trade count anyway, since the cause was the feed. (D) WARMUP: min_z_samples (25) is decoupled from norm_window (60), so the z-score starts once 25 velocity samples exist and tightens as the baseline fills; min_bars_required drops from 132 to 31 bars, ~10% of a 320-day sandbox instead of the ~20%+ flagged. VERIFICATION - engine-measured, with the sandbox's own 365-day start: 30 trades, win 46.7%, +15.78%, Sharpe 1.37, avg_trade_return_pct 1.64%, maxDD 4.66%; full history 176 trades, win 51.1%, +126.53%, Sharpe 0.63, avg_trade_return_pct 1.62%, maxDD 14.64%. An independent offline replication of the sandbox window returned 30 entries - engine and offline now agree exactly, which is the property iterations 1-2 lacked. Layers 1 and 2 still pass. Honest caveats: full-span Sharpe 0.63 is moderate and the strength is concentrated in 2020-2021 and 2024-2025 (offline year-by-year is positive in all seven years but 2022-2023 are near flat), and at a ~1.8-day hold the 15-day holdout still expects only ~2 trades - inherent to the daily clock the hypothesis specifies, which I am no longer going to deviate from to paper over.
Hypotheses
failed deflated Sharpe: DSR=0.008, expected-max=1.71 over 225 trials (39 effective) — selected Sharpe 0.796 indistinguishable from best-of-N noise. Two hard-gate failures that cannot be waived: walk-forward overfit (IS avg 1.54 -> OOS 0.486, ~3x collapse) and PBO 0.53 > 0.5. is_significant=false, Sharpe CI low 0.04, does not survive programme-level FDR (candidate_p 0.992, BH keeps 3/222). The per-trade edge is healthy (avg_trade_return_pct 1.58%, PF 1.70) so this is NOT fee-death — the directional basis-velocity signal simply carries no statistically distinguishable edge once corrected for the 225-trial search. Classic overfit (IS high, OOS collapses, is_overfitted=true), so revising the same mechanism onto another instrument would only overfit again. This is optimization attempt 2 of 2 with no robust parameter region left (sensitivity flat/uniform), and it matches the abandoned overfit cluster: sibling BTC basis-momentum directional (overfit) plus three prior XRP momentum/funding directional variants (overfit/other) — the L73 single-perp supplementary-gated directional family. Failure pattern: overfit single-perp basis-velocity directional continuation.
Implementation
Long-short directional momentum-ignition strategy on the Binance USD-M XRPUSDT perpetual, DAILY bars. The decision variable is the VELOCITY of the perp-vs-index BASIS, not price: a rapidly expanding basis means leveraged demand is accelerating onto one side, and price tends to continue in that direction for a short burst before the leverage exhausts. The basis is read from funding_rates - Binance computes the funding rate as the time-weighted premium index (mark minus index) plus a clamped interest term, so funding IS the venue's published measure of the same basis. Each bar it computes p_t = mean funding over the trailing (ts - bar, ts] window, v_t = p_t - p_{t-vel_window} (basis velocity), and returns z_t = v_t / rolling_std(v, norm_window) - a continuous, scale-invariant ignition score in natural z-score units. It goes LONG when z > entry_z and the confirm_window price return is positive, SHORT when z < -entry_z and that return is negative. It exits FAST when the SIGNED ignition (z x direction) falls below exit_z (the burst has stalled or reversed), on a 6% hard stop, or after max_hold_bars. Sizing is fixed-fractional: notional = risk_per_trade x equity / stop_loss_pct, capped at max_notional_frac x equity x leverage, so one loss costs a bounded ~2% of capital.
Verification Results
Verification failed (Layer 4 — QA review):
- UNMEASURABLE GATE / OFFLINE-VS-ENGINE CONTRADICTION (L16, L26). The only ground-truth measurement — the Layer-3 sandbox — produced total_trades=3 over 320 days, and the engine itself set metrics_reliable=false (~3.4 trades/yr). The developer's rationale claims 27-28 trades in a 365-day window and 198 over the full span (~31/yr). Those disagree by 9.1x, unexplained. Same signature that has repeatedly burned the factory (SOL cascade iter-1: dev claimed 38, engine 9 → correctly rejected). The engine is the source of truth; at 3 trades every metric is an artifact (Sharpe CI -1.51..+1.76, kurtosis 91). The iteration-2 clock change moved the ENGINE count only 2→3, so the root cause is NOT resolved.
- TIMEFRAME DEVIATES FROM HYPOTHESIS. Hypothesis title/description explicitly state 'Daily Bars'; config bar_type is 12-HOUR. Per checklist #1 the stated timeframe must equal config.bar_type. The change was made inside a developer iteration specifically to paper over the measurability problem — yet the engine still shows only 3 trades, so the deviation didn't even achieve its purpose.
- min_bars_required = 132 bars = 66 calendar days of warmup on 12H before any signal, consuming ~20% of a 320-day sandbox and compounding the low trade count.
Verification Results
No code change required. Research/analyst should note the 'Premium-Index-Gated' title now reads funding-rate basis velocity; fix the sandbox synthetic-supp path for premium_index before any future iteration that wants the richer minute-resolution signal.
Verification Results
FEED SUBSTITUTION vs the hypothesis-named channel (assessed, ACCEPTED). Hypothesis says 'Premium-Index-Gated'; code reads the basis from funding_rates instead of premium_index klines. Accepted as warning not critical because: the core edge (basis velocity ignition, ride/exit-on-stall) is fully implemented — only the channel differs; funding = time-weighted premium index + a ~constant clamped interest term, so velocity differencing cancels the interest term and leaves basis velocity; and the swap is what makes the strategy TESTABLE (premium_index is synthetically sampled in the Layer-3 sandbox loader, which caused the iter-1/2 2-3-trade artifact, whereas funding_rates is real and dense in both loaders). Caveat: funding is 8-hourly/clamped vs premium_index minute-resolution/unclamped, so it is a coarser proxy at extreme blowouts — adequate on a daily clock, and the engine confirms real edge survives.
Verification Results
Downstream: weight walk-forward OOS over the ~2-trade holdout; consider a documented holdout-Sharpe waiver against the low trade count.
Verification Results
THIN HOLDOUT (developer-disclosed). At ~1.8-day mean hold on a daily clock, the 15-day holdout expects only ~2 trades, so Phase-3 holdout validation is underpowered. Inherent to the daily timeframe the hypothesis specifies. Full-span is measurable (176 trades), so this doesn't block QA.
Verification Results
Analyst to confirm during optimization that the edge is not concentrated in a few outlier days.
Verification Results
'3-Parameter' label is loose (entry_z + exit_z + 5 clamped structural params). Not a defect. Sandbox Sharpe CI low -1.02 crosses zero with skew 3.73 / kurtosis 37 — mildly tail-driven; an analyst/overfitting consideration, not a QA blocker.
Backtest Review
Strong per-trade edge: avg_trade_return_pct 1.62%, ~16x round-trip taker cost and ~10x the viability floor — not fee-fragile
Backtest Review
Healthy sample (176 trades) with balanced long/short and clean fills (0 dropped)
Backtest Review
Profit factor 1.64, max drawdown 14.6%, positive in every calendar year 2020-2026
Backtest Review
Positive alpha (+0.069) with near-zero beta (0.048) — genuine low-market-exposure directional edge, not closet-long
Backtest Review
Entry gated by funding-basis velocity (real microstructure signal), so not a pure-OHLCV trend clone; feed-parsing root cause diagnosed and engine/offline now reconcile
Backtest Review
Base Sharpe only 0.63 with sharpe_ci_low ~0.0025 — statistically marginal; likely to be squeezed by ~225-trial deflated-Sharpe selection
Backtest Review
Rolling Sharpe front-loaded in 2020-2021 then decayed to ~0/negative mid-sample; edge may be regime-dependent
Backtest Review
information_ratio -0.47 (underperforms buy-hold XRP on active risk-adjusted basis, though alpha is positive)
Backtest Review
avg_holding_bars reported 0.0 / avg_holding_period blank — verify hold-time bookkeeping during optimization
Analysis
Per-trade edge is real and not fee-fragile: avg_trade_return_pct 1.58% (~16x round-trip taker cost), PF 1.70, win_rate 0.51, 229 trades with 0 dropped fills
Analysis
Holdout window is positive (Sharpe 1.51, 28 trades) and the data-plumbing bugs from iterations 1-2 are genuinely fixed (engine/offline agree, funding_rates read cleanly)
Analysis
No sensitivity cliffs; drawdown moderate (14.3%)
Analysis
HARD gate: walk-forward is overfit — IS avg Sharpe 1.54 collapses to OOS 0.486 (windows 0.24 / -0.17 / 1.39), a ~3x degradation on unseen data
Analysis
HARD gate: PBO 0.53 > 0.5 — parameter selection is more likely than not overfit
Analysis
Deflated Sharpe 0.008 (<<0.95), is_significant=false, Sharpe CI low 0.04 — selected Sharpe indistinguishable from best-of-N noise over 225 trials (39 effective), and the selected Sharpe 0.796 is BELOW the expected-max-by-luck bar of 1.71
Analysis
Does not survive programme-level FDR (BH q=0.10 keeps 3 of 222; candidate_p 0.992)
Analysis
Optimized Sharpe 0.796 < 1.5 floor; DD 14.3% > 10% floor
Analysis
Matches the abandoned overfit cluster: sibling BTC basis-momentum directional (overfit) and three prior XRP momentum/funding directional variants (overfit/other) — the L73 single-perp supplementary-gated directional family that dies in the 3-phase deflation
Analysis
Benjamini-Hochberg at q=0.10 over 222 programme candidates keeps 3. A candidate that does not survive here is not distinguishable from the programme's own noise, however good its individual statistics look.
Outcome Summary
XrpPerpBasisIgnitionContinuationLS rode momentum bursts when the XRP perp's premium-to-index basis expanded rapidly (accelerating leveraged demand) and exited fast when the ignition stalled, and its main iteration work was diagnosing why prior versions disagreed between the sandbox and full engine — a synthetic-feed sampling gap and a dual-int/str-key JSON parsing bug — which the funding-rate-channel fix resolved so both loaders saw identical data. The reconciled backtest looked strong (126.5% return, PF 1.64, avg_trade 1.62%, positive alpha) and earned an 'optimize' verdict, but the 3-phase optimization revealed the edge was a narrow overfit ridge: deflated_sharpe 0.0 (not significant) against an expected-max of 4.44, both signal parameters on cliffs, wildly varying walk-forward Sharpes, and outlier-driven returns. The analyst abandoned it at the ANALYZING stage as the perp_basis_velocity_directional_overfit pattern — the five nearest prior BTC/XRP siblings all died the same way. It reached optimization and analysis but was never promoted to risk review or paper trading.
Outcome Summary
Fixing data-plumbing bugs so the engine and offline model agree, and even passing walk-forward and the holdout with a good profit factor, is not enough — a deflated Sharpe of zero over 225 trials with both signal-defining parameters on sensitivity cliffs means the edge is an overfit ridge (best-of-N noise), and the perp-basis-velocity directional-continuation family has repeatedly died overfit, so re-targeting onto another instrument would only overfit again.
Outcome Summary
It reached ANALYZING (after passing backtest review to optimization), but the analyst issued an 'abandon' verdict on a failed deflated Sharpe: DSR 0.0 with expected-max 4.44 over 225 trials means the selected 0.787 Sharpe is indistinguishable from best-of-N noise, the edge sits on cliff parameters rather than a plateau, and the optimizer already searched the space without finding a robust region — so parameter iteration cannot create an edge, with the optimized Sharpe below the 1.5 floor, drawdown above the 10% floor, and a negative information ratio confirming it.
Outcome Summary
A long-short, single-instrument directional momentum-ignition strategy on the XRPUSDT Binance USD-M perp (daily bars) that uses the velocity of the perp's premium-to-index basis (read from the funding-rate feed as a z-score) as an ignition gauge — going long when the basis rapidly widens positive with a confirming up-break, short when it widens negative with a down-break, and exiting fast when the basis velocity stalls — with three parameters (entry z, exit z, hold), engineered to fix the feed-parsing bugs that made prior iterations disagree between the engine and offline.
Outcome Summary
The initial backtest was strong enough to pass review to optimization: total_return 126.5%, Sharpe 0.63 (CI low 0.0025), profit_factor 1.64, avg_trade_return_pct 1.62%, max_drawdown 14.6% over 176 trades, positive alpha (0.069) with near-zero beta. But the 3-phase optimization exposed it as an overfit ridge: the optimized config reached Sharpe 0.787 / PF 2.0 but deflated_sharpe was 0.0 (is_significant false) against an expected-max Sharpe of 4.44 over 225 trials, both signal-defining parameters (entry_z, norm_window) were sensitivity cliffs, walk-forward trial Sharpes spanned -3.8 to +3.98, returns were outlier-driven (kurtosis 53.3, skew 3.57), and information_ratio was -0.45.
Iteration History
Verification failed (Layer 4 — QA review):
- Trade count collapsed to 2 in the engine vs the developer's claimed ~18/yr — the premium signal isn't firing as designed. Likely _premium_for_bar returns carry-forward constants because the forward window [ts, ts+window) is misaligned with the premium kline timestamps, so velocity≈0 and entries almost never trigger. The dry-run numbers can't be trusted while the engine produces 2 trades.
- Look-ahead risk: _premium_for_bar prices the bar over [ts, ts+window), contemporaneous only if ts is the bar OPEN time. Nautilus EXTERNAL bars are conventionally stamped at CLOSE, making this the NEXT day's premium (future data). Must use the trailing period ending at the bar close and pin down the ts convention.
- L17 defect signature + unmeasurable: win_rate 0.0, profit_factor 0.0, both trades losing, metrics_reliable=false, on a 2-trade sample. Treat 0.0/0.0 as a code defect to investigate, compounding the wiring suspicion; even the claimed ~18/yr is far below the ~100-trade validation bar.
Backtest and paper results are hypothetical. Trading involves risk of loss.