Skip to content

View translation

BtcAsiaToUsSessionCarryoverLS

Hypotheses

BTC Cross-Session Momentum Carryover — Long-Short, Single-Instrument OHLCV: The Direction of the ASIA-Session Move Predicts the US-Session Move; Trade the US Session in That Direction ONLY When the Asia Move Is Large, Flat Overnight (BINANCE BTCUSDT USD-M, 1H Bars, Intraday, 2-Parameter)

Hypotheses

A LONG-SHORT, SINGLE-INSTRUMENT, pure-OHLCV INTRADAY strategy on BTCUSDT.BINANCE USD-M perpetual in a genuinely different family from everything pending or dead here — it is NOT a trend/breakout (dual-TF momentum, SuperTrend, Donchian, ORB), NOT a mean-reversion/fade (both dead), and NOT a supplementary-feed signal (all net losers). It exploits an intraday SESSION LEAD-LAG: the directional tone set during the low-participation ASIA session (00:00-08:00 UTC) tends to PERSIST into the higher-liquidity US session (13:00-21:00 UTC), as US/institutional flow continues the move rather than reversing it. Each UTC day, the sign and size of the Asia-session return is measured; when the Asia move is LARGE (a real directional signal, not noise), the strategy enters the US session in the SAME direction and holds only for that session, going FLAT overnight (no funding exposure, no overnight gap, no multi-day trend risk). This is distinct from the pending BTC opening-range breakout (which trades a range BREAKOUT of the first hours) — here there is no breakout; it is a directional CARRYOVER of an already-established session move into a later, separate session. It keeps the survivable invariants (single-instrument, pure OHLCV with full 2020-2026 1H history, long-short, no supplementary feed per the net-loser lesson, no second leg per L69) and is built for the statistical gates: a near-daily cadence yields a LARGE trade count (>100/yr) that clears the measurability tripwire and tightens the deflated-Sharpe estimate, and only 2 FREE parameters (Asia-move entry threshold, ATR stop multiple) minimize the best-of-225-trial deflation penalty. It also fills the under-represented short-horizon bucket (8.6% vs 10%).

Hypotheses

Iteration 2 fixes the Layer-2 failure verbatim: all six synthetic scenarios raised 'TypeError: _day_of() takes 1 positional argument but 2 were given'. The Layer-2 harness rebinds every callable attribute on the proxy as a BOUND method, so the @staticmethod helpers _day_of/_hour_of received the instance as their first argument and the bar as a second. Fix: both are now plain instance methods (self, bar) — call sites already used self._day_of(bar)/self._hour_of(bar), so nothing else changed, and behaviour under the engine is identical. Second, defensive change in the same helper path: the harness's reported timestamp (1735690980000) is in MILLISECONDS while the engine supplies nanoseconds; the old code unconditionally divided by 1e9, which under the harness would collapse every synthetic bar into the same hour/day and freeze the session logic (a latent second Layer-2 failure once the TypeError cleared). The new _epoch_secs() normalises by magnitude (ns/us/ms/s) and is a no-op for real nanosecond bars, so Layer-3 and the real backtest are unaffected. Signal shape, entry/exit rules, ATR, sizing, imports and class structure are otherwise untouched from the code that already passed Layer 1.

Hypotheses

Negative-expectancy premise on a well-measured full-history sample. Over 594 trades across 2020-2026 the Asia->US session-carryover loses money: profit_factor 0.937 (<1), total_return -9.81%, expectancy -$17.34/trade, Sharpe -0.15 with CI [-0.760, 0.458] straddling zero, information_ratio -0.76. The only positive year is 2020 (+15.3%); every year since is negative or flat (2021 -8.1, 2022 -5.8, 2025 -10.8) with rolling Sharpe trending to -8.3 by 2026 — the 'large Asia move predicts the US move' hypothesis is simply not borne out. It is also fee-marginal: avg_trade_return_pct 0.110% is below the 0.15% Binance USD-M floor (L22). With only 2 free parameters and a net-negative directional edge, tuning cannot flip the sign of an edge that does not exist. This is the fee_edge/no_edge net-loser signature — not worth 2 hours of optimization.

Implementation

BTCUSDT.BINANCE USD-M perpetual, 1H bars, long-short intraday session lead-lag. Each UTC day the Asia-session return (00:00-08:00 UTC open-to-close) is accumulated incrementally and normalised by the standard deviation of the last 30 Asia returns (ATR-based dispersion fallback while that history warms), giving a continuous scale-invariant z-score returned every bar. At the US-session open hour (13:00 UTC) the strategy enters in the SAME direction as the Asia move when |z| >= entry_z, at most one entry per calendar day. It exits at the US-session close hour (20:00 UTC) so the book is FLAT overnight (no funding, no gap risk), or earlier on an ATR-based stop (stop_atr_mult x ATR, floored at min_stop_pct). Sizing risks risk_frac of equity across the stop distance, capped at max_notional_frac x equity gross. All state (ATR, session return, dispersion deque) is O(1) per bar; the day roll is anchored on the bar's own timestamp, not a bar counter.

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

Add _param_bounds = {entry_z: [...], stop_atr_mult: [...]} matching the code clamps; keep all session-hour/ATR/risk constants out of it.

Verification Results

Config declares NO _param_bounds despite the hypothesis resting on 'only 2 FREE parameters' to minimize the best-of-225-trial deflation penalty. Without it the optimizer has no explicit surface tying it to {entry_z, stop_atr_mult}, undercutting the 2-parameter discipline. Not a correctness defect.

Verification Results

Set us_exit_hour=21 for the full window, or document 20:00 as intended.

Verification Results

Hypothesis names the US session 13:00-21:00 UTC but us_exit_hour is 20, forcing flat one hour early. Minor, doesn't change the mechanism or flat-overnight invariant.

Backtest Review

Well-measured: 594 trades over full 2020-2026 1H history, balanced long/short (293/301), clean execution (594 signaled, 594 submitted, no drops)

Backtest Review

Genuinely distinct intraday session lead-lag family; flat overnight, low benchmark correlation (0.025), no supplementary-feed dependency

Backtest Review

Net loser: profit_factor 0.937 (<1), total_return -9.81%, expectancy -$17.34/trade, Sharpe -0.15 (CI straddles zero), information_ratio -0.76

Backtest Review

avg_trade_return_pct 0.110% is below the 0.15% Binance USD-M fee floor — fee-marginal even ignoring the negative expectancy

Backtest Review

Only 2020 (+15.3%) is meaningfully positive; every subsequent year negative or flat (2025 -10.8%), rolling Sharpe trends to -8.3 by 2026 — the session-carryover premise has no persistent edge

Backtest Review

return_kurtosis 78.6 — lumpy tape (e.g. a -6.07% day on 2023-08-29) rather than a smooth edge

Iteration History

Verification failed (Layer 2 — synthetic scenarios): Parameters used: ['entry_z', 'min_bars', 'risk_frac', 'atr_period', 'min_notional', 'min_stop_pct', 'min_vol_days', 'us_exit_hour', 'asia_end_hour', 'stop_atr_mult', 'us_entry_hour', 'asia_start_hour', 'max_notional_frac', 'vol_lookback_days'] Check that __init__ sets all attributes from self.parameters.get(). - steady_uptrend: TypeError: BtcAsiaToUsSessionCarryoverLS._day_of() takes 1 positional argument but 2 were given (bar timestamp: 1735690980000) - steady_downtrend: TypeError: BtcAsiaToUsSessionCarryoverLS._day_of() takes 1 positional argument but 2 were given (bar timestamp: 1735690980000) - flat_ranging: TypeError: BtcAsiaToUsSessionCarryoverLS._day_of() takes 1 positional argument but 2 were given (bar timestamp: 1735690980000) - volatility_spike: TypeError: BtcAsiaToUsSessionCarryoverLS._day_of() takes 1 positional argument but 2 were given (bar timestamp: 1735690980000) - zero_volume: TypeError: BtcAsiaToUsSessionCarryoverLS._day_of() takes 1 positional argument but 2 were given (bar timestamp: 1735690980000) - price_gap: TypeError: BtcAsiaToUsSessionCarryoverLS._day_of() takes 1 positional argument but 2 were given (bar timestamp: 1735690980000)
Strategy report

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