Skip to content

View original

UsSessionAttributedDriftSolBybitLS

Hypotheses

US-Session-Attributed Drift: Build the Directional Signal ONLY From the 13:00-21:00 UTC Slice of the 24/7 Crypto Tape and Discard the Other 16 Hours (SOLUSDT.BYBIT perp, 1H bars, always-in long-short, no gate, no supplementary feed)

Hypotheses

A SINGLE-INSTRUMENT, SINGLE-LEG, always-in LONG-SHORT directional strategy on SOLUSDT.BYBIT linear perpetual, 1-HOUR bars (catalog verified: 2021-10-15 -> 2026-09-18, ~1,800 days). The mechanism is a DECOMPOSITION of the price series by hour-of-day, not a filter on it and not a trailing-return momentum signal. Crypto trades 24/7, but the flow inside it is not homogeneous: the 13:00-21:00 UTC window contains the entire US cash equity session under both DST regimes, and that is when US macro-sensitive, mandate-driven capital (ETF creation/redemption baskets, CTA and multi-strat risk books, treasury/corporate allocators, US retail brokerages) actually transacts. Those participants execute in SLICES OVER DAYS because their orders are large relative to perp depth; the Asian and European hours are dominated by leveraged perp flow that mean-reverts within the day. CLAIM: the cumulative return realised inside the US window carries the persistent, information-bearing component of the crypto tape, while the return realised outside it is mostly inventory noise. So the signal is s_t = sum of the K most recent daily US-window log returns (close of the 21:00 UTC bar minus close of the 13:00 UTC bar, same calendar day), and the book is ALWAYS long or short in sign(s_t) — never flat, no regime gate, no volatility deadband, no funding/OI/taker overlay, no second instrument, no hedge leg. Decisions are taken once per day at the 21:00 UTC bar close. This is NOT the factory's dual-timeframe/TSMOM survivor with a new ticker (lesson 112): a full trailing 5-day return and a 5-session US-window sum have low correlation precisely because the non-US 16 hours are ~2/3 of the variance and are being deliberately thrown away — the hypothesis lives or dies on whether discarding them RAISES information, which is a new economic claim, not a new wrapper. It is also NOT a scheduled-event overlay (lesson 104): the window fires 365 times a year, not 8, so the sample is not capped. PRE-REGISTERED FALSIFICATION TEST: the mirror strategy built from the complementary 21:00->13:00 UTC non-US window over the same K must produce materially LOWER Sharpe. If the non-US window is equally or more predictive, the hour-attribution premise is false and the result is a generic momentum artifact that should be abandoned regardless of its own Sharpe. VENUE/INSTRUMENT SELECTION, stated explicitly per lesson 122: BYBIT is chosen because it is 0.3% of a 3,166-experiment corpus against a 5% quota target AND has validated plumbing (two prior runs completed full backtests on Bybit linear perps, satisfying lesson 103); SOL is chosen because the mechanism REQUIRES an asset whose marginal buyer is a US institution — SOL has US spot ETFs and the heaviest US-hours flow concentration outside BTC/ETH — and because BTC and ETH are near the 25% instrument-breadth ceiling. SOL is a top-3 Bybit perp by depth, so this is NOT a never-traded thin-name novelty claim (lesson 136). PARAMETERS: K (number of US sessions accumulated, ~3-10), an annualised volatility target for sizing, and one catastrophic stop. No gates.

Hypotheses

Iteration 2 addresses the reported incoherence (Sharpe +0.33 against total_return -21.1%) at its only possible source for an always-in book: volatility drag. Geometric return ~= mu - sigma^2/2, so a book running a 35% vol target (and a materially higher marked vol) loses more to drag than the drift pays — which is exactly a positive mean daily return sitting under a negative compounded equity curve. Since mu scales linearly with exposure while the drag scales with its square, halving exposure (target_ann_vol 0.35 -> 0.18, notional cap 1.5x -> 0.75x, vol floor 0.22 -> 0.25) makes the compounded curve agree in sign with the mean at the same Sharpe, and shrinks the daily marked amplitude that made the two series hard to reconcile. K goes 5 -> 7, which lengthens the hold and cuts round-trip fee drag by flipping sign less often — trade count falls through a slower signal, NOT through a new entry gate (no conditions added; the book is still always in the market, per lesson 131). Everything that already passed the earlier layers — the hour-decomposition signal, the continuous decision variable, the calendar-anchored 21:00 UTC commit, the O(1) incremental EWMA vol, scalar-only state and the clean import set — is untouched. Leverage stays 1.0 and the code reads self.config.leverage as the hard ceiling on deployed notional.

Hypotheses

abandon_class=artifact, with an independent economic ground so the abandon holds on either branch. The daily MTM series contradicts the equity curve it describes (+4.03% compounded vs +17.42% realized), autocorrelates at -0.26 and cancels within a week, and its ±5-12% day-pairs are incoherent with the positions actually held — yet sharpe_ratio (the Phase 2 objective), vol, sortino, var/cvar, calmar and kurtosis all derive from it. Honest qualifier: the artifact DEPRESSES rather than flatters, so it is not the whole reason to stop — cleaning it still leaves Sharpe ~0.17 / PF 1.06, a per-trade edge at t=0.92 (t=0.23 over the last 150 trades), top-5 concentration of 321% of book PnL, 3 of 6 positive years, impact at 32.6% of gross and capacity under $1M. Not negative_expectancy (dollar-weighted per-trade +0.176% clears the 0.15% Bybit floor) and not broken_mechanism (the trades implement the premise precisely). For the Research Lead: the pre-registered mirror control must be produced inside the same backtest if hour-attribution is retried — without it a positive result is indistinguishable from ordinary trailing-return momentum. For Engineering: sixth consecutive run with daily-MTM marking symptoms, second on a single-leg book; the new evidence is that the daily series does not compound to its own equity curve.

Implementation

Always-in long/short SOLUSDT.BYBIT linear perp on 1-HOUR bars. The tape is decomposed by hour-of-day: the signal is the sum of the K=7 most recent US-window log returns (close of the 21:00 UTC bar minus close of the 13:00 UTC bar of the same session); the other 16 hours are discarded entirely. The book is long or short in the sign of that sum, committed once per day at the 21:00 UTC bar close (calendar-anchored, restart-identical). Sizing is an 18% annualised-vol target capped at 0.75x equity notional, with one catastrophic 15% stop checked hourly that locks re-entry until the next daily commit. Setting window_start_hour=21 / window_end_hour=13 builds the pre-registered mirror (non-US window) falsification run.

Verification Results

Use an explicit sentinel: `self._have_prev: bool = False` set to True after the first bar, and guard on that (or on `self._prev_lp != 0.0`) instead of on the sign of the log price.

Verification Results

`if self._prev_lp > 0.0:` is doing double duty as a 'have a previous bar' sentinel and as a validity guard, but `_prev_lp` is a LOG price, so the condition is really 'previous price > $1.00'. On SOLUSDT (never below ~$8 in the catalog window) this is harmless, but if the same class is ever pointed at a sub-$1 instrument (or the mirror/falsification run is ported to a cheap alt), the EWMA variance would never update, `_ret_count` would stay 0, and position_size() would return Decimal('0') on every bar forever — a silent no-trade strategy rather than a loud failure.

Verification Results

Either drop max_notional_mult from _param_bounds (documenting min_ann_vol as the exposure ceiling), or restate the bounds so the cap can actually bind (e.g. max_notional_mult upper bound <= 0.72), so the optimizer searches a live dimension.

Verification Results

The notional cap is inert. `mult = target_ann_vol / max(ann_vol, min_ann_vol)` is bounded above by 0.18/0.25 = 0.72, which is strictly below `max_notional_mult` = 0.75 (and below the 0.80 hard clamp). So `min(mult, self.max_notional_mult)` never binds at the shipped parameters, and `max_notional_mult` is a flat dimension over most of its pre-registered range [0.15, 0.80] — the Phase-1 sensitivity sweep will report zero sensitivity for it over [0.72, 0.80] and the Optuna search will waste trials on a parameter that only matters below 0.72. The same interaction makes `min_ann_vol` (0.25) the real exposure cap rather than the documented 0.75x.

Verification Results

Declare `PERSIST_STATE = ('_sessions_list',)` with a list mirror of the deque (and rehydrate it in restore), or assert a minimum warmup of k_sessions+1 sessions of hourly bars in the strategy docstring/config so the paper controller replays enough history.

Verification Results

`self._sessions` is a deque and is therefore NOT covered by `persistable_state()` (which keeps only bool/int/float/str scalars unless PERSIST_STATE is declared). On a paper restart the scalars `_target_side`, `_decision_count` and `_stop_block_decision` are restored but the session deque comes back empty, so no NEW daily commit can occur until K=7 fresh US windows accumulate (~7 calendar days / ~190 hourly bars). The book would hold the restored stale side through that period. Backtests are unaffected, and live warmup replay does run calculate_signal (base template) so a sufficiently long replay rebuilds the deque — but this is an unstated dependency on warmup length.

Verification Results

Clear the anchor once `ts - _anchor_ts_ns` exceeds the nominal window length, and only commit/increment `_decision_count` when a session return was actually appended on that bar.

Verification Results

The running-partial term added to the RETURNED signal is only cleared at a window_end_hour bar. If the 21:00 UTC bar is missing from the tape, `_anchor_ts_ns` stays set and the partial keeps being added for up to `_max_gap_ns` (26h), past the end of the attribution window, until the next 13:00 bar overwrites the anchor. This affects only the diagnostic/published signal — the trading decision uses `_committed_signal`/`_target_side`, which is untouched — but the published paper signal history would misrepresent the decision variable on those days. Relatedly, if the gap check fails on a completion bar, no session return is appended yet `_decision_count` still increments and a commit still fires off the stale deque.

Verification Results

Two things the analyst should look at with full-history numbers, neither of which blocks the code. (1) The sandbox's per-trade % and per-trade dollars disagree in SIGN: avg_trade_return_pct +0.2427% (gross price return, commission-free) against avg_trade_pnl_usd -$49.83 and total_return -7.65%. This is NOT an accounting defect here — it is the vol target inverting the dollar weighting: mult = 0.18/max(ann_vol, 0.25) sizes LARGEST exactly in the calm tercile, and the calm tercile is where the book loses (calm -19.45% / Sharpe -1.66, normal -8.71%, stressed +28.06%). So the mechanism's dollars are concentrated in the regime where it works worst. Worth attributing per-regime on the full run before spending an optimize. (2) Fee margin is thin: gross ~0.24%/trade against a Bybit round trip of 0.11% plus modeled impact ($2,420 impact + $4,331 commission over 154 trades on ~$26k average notional = ~0.17%/trade of cost), leaving ~0.07% of gross edge. At ~330 trades over full history the cost stack consumes most of the stated edge. (3) The iteration-2 rationale does not reconcile arithmetically: at a 35% vol target the drag term sigma^2/2 is ~6%/yr, which cannot turn a Sharpe +0.33 (mu ~ +11.6%/yr) into a -21.1% compounded result — ~64% realized vol would be required. The current run IS internally coherent (Sharpe -0.215 at 18.5% ann vol over 2.28y ~ -12.6% geometric vs -7.65% reported), so the exposure cut did restore coherence, but the original diagnosis may have been the wrong cause and the analyst should not treat the halved exposure as a tested fix for the previous run's incoherence.

Backtest Review

Trades implement the hypothesis exactly: 342 always-in decisions (170 long / 172 short), 21:00 UTC commits, ~5d holds, vol-scaled size (mean leverage 0.24x). No mechanism mismatch.

Backtest Review

Realized ledger is coherent: trade PnL sums to $17,387 and ties exactly to the equity curve 100,000 -> 117,420.83; funding credited (-$4,967), commission $10,852 and impact $8,422 folded in.

Backtest Review

Adequate sample/span (342 trades, 1,758 days) and positive stress windows (LUNA +9.0%, FTX +11.5%, SVB +3.8%, tariff-2025 +4.2%).

Backtest Review

Daily MTM series compounds to +4.03% while the ledger and equity curve both end at +17.42%; lag-1 autocorrelation -0.26; annualized vol collapses 28.78% (daily) -> 19.86% (7d) -> 19.66% (30d).

Backtest Review

The ±5-12% day-pairs contradict the positions held (e.g. 2026-03-22/23 -10.86%/+12.82% on a single 427.7-SOL LONG at 0.30x whose whole 10-day life netted +$1,156).

Backtest Review

Cleaning the artifact does not rescue it: 3.41% CAGR at ~19.7% clean vol = Sharpe ~0.17, PF 1.059.

Backtest Review

Per-trade edge not measurable: +0.536% of notional at t=0.92 over 342 trades, median -0.647%; +0.155% at t=0.23 over the last 150 trades.

Backtest Review

Top 5 trades +$55,802 vs a book total of +$17,387 (other 337 net -$38,415); 3 of 6 years positive; sharpe_ci [-0.77, +1.02].

Backtest Review

QA concern #1 confirmed: dollar-weighted per-trade edge +0.176% vs equal-weighted +0.536% — the vol target sizes largest in the calm tercile, which loses -27.35% (Sharpe -0.46).

Backtest Review

Impact is 32.6% of gross PnL, capacity_usd $939k; short leg contributes only $2,941 of $17,387.

Backtest Review

The hypothesis's pre-registered mirror (non-US window) falsification test was never run — the core claim is untested.

Analysis

Backtest gate: - metrics unreliable: Incoherent: Sharpe 0.33 disagrees in sign with total_return -21.10% — the Sharpe is computed from the mtm_equity_curve series while the return comes from the equity curve. Judge on the equity curve.

Outcome Summary

UsSessionAttributedDriftSolBybitLS-4025b14a08

Outcome Summary

UsSessionAttributedDriftSolBybitLS tested whether discarding the non-US 16 hours of the SOL perp tape raises information, holding an always-in long/short book in the sign of a 7-session US-window return sum, sized to an annualised vol target. Iteration 2 halved exposure (vol target 0.35 -> 0.18, notional cap 1.5x -> 0.75x) and lengthened K from 5 to 7 to fix a prior run where a positive mean daily return sat beside a negative compounded curve; the resulting backtest realized +17.42% over 1,758 days on 342 trades, but at Sharpe 0.17 and profit factor 1.06. The analyst abandoned it at backtest review on two independent grounds: the daily MTM series does not compound to its own equity curve (+4.03% vs +17.42%, lag-1 autocorrelation -0.26), corrupting the Sharpe-family metrics, and even after cleaning that artifact the per-trade edge is statistically indistinguishable from zero with PnL concentrated in five trades and impact at a third of gross. Optimization, the analyst promotion decision and risk review were never reached, and the hypothesis's own mirror-window falsification test was never run.

Outcome Summary

A pre-registered falsification control — here the mirror non-US-window variant — must be produced inside the same backtest, otherwise an hour-attribution result is indistinguishable from ordinary trailing-return momentum and cannot be adjudicated.

Outcome Summary

The analyst abandoned it at backtest review (abandon_class=artifact) before optimization: the daily MTM series compounds to +4.03% versus the ledger's +17.42%, autocorrelates at -0.26 and produces day-pairs incoherent with the positions held, contaminating every Sharpe-derived metric. The abandon was also grounded economically — cleaning the artifact still leaves Sharpe ~0.17, PF 1.06, a per-trade edge at t=0.92 (t=0.23 over the last 150 trades), top-5 trades at 321% of book PnL and only 3 of 6 positive years.

Outcome Summary

It decomposed the 24/7 SOLUSDT.BYBIT perp tape by hour-of-day and took an always-in long/short position in the sign of the summed last 7 US-session (13:00-21:00 UTC) log returns, on the claim that the US-hours slice carries the information-bearing drift while the other 16 hours are inventory noise.

Outcome Summary

Over 1,758 days and 42,168 hourly bars it made 342 trades (170 long / 172 short, ~5d average hold) for +17.42% total return, 3.41% CAGR, Sharpe 0.17 (CI -0.77 to +1.02), profit factor 1.06, win rate 47.1%, max drawdown 24.3% and avg trade return 0.80% of notional. Calm-vol regime lost -27.35% (Sharpe -0.46) while stress windows were positive, impact cost was 32.6% of gross PnL, and capacity was under $1M.
Strategy report

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