Skip to content

View original

BtcPerpPremiumConfirmedMomentumLS

Hypotheses

BTC Perp-Premium-Confirmed Momentum, Long-Short (Single-Instrument BTCUSDT.BINANCE Perp, 4H Bars — Trade Price Momentum ONLY When the Perp Mark-vs-Index PREMIUM Confirms Leveraged Conviction in the Same Direction, Flat on Divergence, ATR-Trailing, 3-Parameter)

Hypotheses

A LONG-SHORT, single-instrument strategy on BTCUSDT.BINANCE USD-M perpetual that trades 4H price momentum ONLY when the perpetual's mark-vs-index PREMIUM (basis) confirms leveraged conviction in the same direction, and stands flat when price and premium diverge. This targets a distinct EDGE SOURCE — leverage/basis sentiment — on the ONE instrument this session has conclusively shown to be directionally tradable (BTC; every alt directional variant across price, volume, structure, ADX has now died 'no edge', and only BTC momentum survives). It completes the orthogonal-signal sweep the factory is effectively running on BTC: my pending ideas confirm momentum with aggressor FLOW (taker ratio) and positioning STOCK (open interest); this uses the PREMIUM (the price of leverage) — a genuinely different feed. The thesis: a price move where the perp simultaneously trades at a premium in that direction reflects leveraged demand committing (persistent), whereas a price move against the basis (e.g., price up while the perp sits at a discount = spot-led, no leverage support) is unsupported and tends not to continue. It applies the survivor's proven SELECTIVITY principle (trade direction only when an independent confirm agrees, flat otherwise) with an orthogonal confirm. It is engineered against every confirmed failure mode: kept DEAD SIMPLE for the developer — ONE supplementary scalar (premium_index), the SAME instrument it trades, standard incremental smoothing — to prevent the whole-strategy-swap that killed prior supplementary ideas; 4H cadence for a MEASURABLE ~150-250 trade sample (not a low-frequency gate); BTC 4H legs (~2-4%) that clear the ~0.10% fee. It fills the under-target LONG-SHORT bucket (13.3% vs an 86.7%-long-only book). Only 3 parameters.

Hypotheses

The previous iteration attributed the zero-trade failure to dual-key parsing of funding_rates. That diagnosis was wrong, and its fix could not have worked, because funding_rates was never reached. I traced the actual chain. premium_index is not in PipelineProcessor.SUPP_KEYS, so the Layer-3 sandbox never loads the real series and substitutes synthetic_scenarios._gen_synthetic_premium_index, which emits bars[::60] — one print per 60 bars, i.e. one per 10 DAYS on a 4H clock. Those synthetic rows parse perfectly (valid timestamp, a close premium field) and clear _finalize with ~240 rows against a 20-sample minimum, so _prem_source locked onto premium_index and the candidate loop returned before ever trying funding_rates. But _prem_z requires at least prem_min_z_samples (20) samples inside the 30-day z-window, and at 10-day spacing that window holds about 3, so it returned None on every bar, confirm_dir stayed 0, and no entry could fire — precisely the reported 0-entries-over-14,360-bars. The 24h staleness cap also failed on roughly 90% of bars against 10-day spacing. Meanwhile funding_rates IS in SUPP_KEYS and is real and dense: I confirmed 85,697 BTCUSDT rows spanning 2020-01-01 to 2026-09-04 at an 8h cadence, which gives 90 samples per 30-day window and sits well inside the 24h staleness cap. The usable series was sitting behind the unusable one. The fix is a single new check, _density_ok: a candidate is accepted only if its median inter-sample spacing fits inside prem_max_lag_ns and a prem_z_days window is expected to contain at least prem_min_z_samples; otherwise it is rejected with a logged median gap and the loop falls through to the next same-quantity source. This is a data-adequacy test, not a loosening of the edge — no threshold moved, the confirmation gate is untouched, and the strategy still refuses to trade without a genuine premium reading. It is also correct in both environments: in the sandbox the sparse synthetic premium_index is rejected and the real 8h funding_rates is used, while in the full backtest the real premium_index (1-minute premiumIndexKlines) passes density and is preferred, exactly as the hypothesis intends. Imports, the signal maths, entry/exit logic, O(log n) prefix-sum lookups and sizing are otherwise unchanged, and I added _param_bounds mirroring the clamps.

Hypotheses

Reliable 271-trade/6.7-year sample with avg_trade_return_pct 0.123% (below the 0.15% Binance USD-M fee floor) and profit_factor 1.0067 — the classic fee_edge signature where the gross edge sits entirely inside the ~0.10% round-trip cost. information_ratio -0.82 vs buy-hold, Sharpe 0.164 (CI low -0.60 straddles zero), and impact_cost_pct 73.97% (capacity only ~$183k) confirm no net edge. Optimization cannot lift a per-trade edge below trading costs, so the QA edge concern is borne out on the full backtest. The premium-confirmation axis adds no directional persistence (near-flat regime spread). Not worth 2 hours of optimization.

Implementation

Long-short 4-hour momentum on BTCUSDT.BINANCE USD-M perpetual, taken only when the perp's mark-vs-index premium confirms the same direction. Momentum is the close-to-close change over mom_lookback bars divided by ATR; the premium is read from the supplementary series, smoothed over 24 hours and standardized as a z-score against its trailing 30-day mean and standard deviation. The traded signal is momentum weighted by premium conviction, min(1, |z|/prem_thresh), with the divergence branch clipped below the entry threshold so momentum without premium agreement can never trigger a trade. Entry requires a fresh cross of the signal through entry_thresh_atr while the premium confirms directionally; the previous bar's eligibility is recomputed from history rather than carried in state, so behaviour is identical across restarts and replay. Exits are momentum loss with hysteresis, a full-threshold premium flip against the position, and an ATR trailing stop from the best close since entry. Sizing risks 2% of equity across the trailing-stop distance, capped at 1x equity notional and floored at BTC's 0.001 step and the $100 minimum. If no usable premium reading exists the strategy holds no position — there is no price-only fallback.

Verification Results

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

Verification Results

Confirm in the full backtest logs that _prem_source resolves to premium_index (not funding_rates); if it silently keeps falling back to funding, the strategy is testing a related-but-different feed than the hypothesis intends.

Verification Results

In the Layer-3 sandbox the confirm signal is funding_rates (8h cadence), not the premium_index (mark-vs-index) the hypothesis centers on, because premium_index is not in the sandbox SUPP_KEYS and the synthetic stand-in is too sparse to pass the density gate. The developer documents this and treats funding as the same-quantity 8h time-average of the premium (the hypothesis lists it as the same-quantity alternate), so this is acceptable — but the sandbox edge is measured on the proxy, not the intended feed. Verify the real premium_index loads and is preferred in the full backtest.

Verification Results

No action required unless the framework relies on its own min_bars_required semantics; the override value is reasonable.

Verification Results

min_bars_required(self) overrides the framework method (base_shadow static-analysis warning). It returns max(atr_period+2, mom_lookback+2) which is a sensible warm-up and honors a parameter override, so behavior is correct; noted only because it shadows the base implementation.

Verification Results

Sandbox (unoptimized single draw) shows avg_trade_return_pct 0.024% (< the 0.15% futures fee floor), profit_factor 0.96, negative expectancy (-$26/trade), win_rate 33%, and information_ratio -0.78 vs buy-hold over 374 trades. This is a smoke test on default params, so it does not block, but the mechanism's per-trade edge is thin and the confirm axis in the sandbox is funding_rates (8h) rather than the 1-min premium_index the hypothesis names — the analyst should verify on the full backtest that (a) the real premium_index actually loads and passes the density gate (so the intended feed, not the funding proxy, drives entries) and (b) the ~2-4% BTC 4H legs the hypothesis claims materialize net of the ~0.10% round trip and 7.8% commission drag seen here. Regime spread is small (calm/normal/stressed all near-zero Sharpe), suggesting weak directional persistence in the confirmed signal.

Backtest Review

Faithful, dense implementation: the real premium/funding feed loads and the strategy trades a measurable 271-trade sample over 6.7 years (metrics_reliable=true), so the edge is genuinely measured rather than unmeasured.

Backtest Review

Reasonable drawdown control (max_drawdown 22.9%) and near-zero market beta (0.017) — the mechanism does what it claims, it just has no edge.

Backtest Review

avg_trade_return_pct 0.123% is BELOW the 0.15% Binance USD-M fee floor — the per-trade edge is smaller than the ~0.10% round-trip cost (L22).

Backtest Review

profit_factor 1.0067 with 271 trades — the fee_edge signature: gross edge sits entirely inside commissions and cannot be tuned above cost (L18).

Backtest Review

information_ratio -0.82 vs a meaningful buy-hold benchmark; alpha ~0.028 is negligible and Sharpe 0.164 with sharpe_ci_low -0.60 straddles zero.

Backtest Review

impact_cost_pct 73.97% and capacity_usd ~$183k — market impact consumes ~3/4 of gross PnL; the edge is real only at toy scale.

Backtest Review

Regime spread near-zero across calm/normal/stressed and 4 of 7 years negative — no directional persistence in the confirmed signal.

Iteration History

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

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