Skip to content

View original

AaveMacroReleaseHourDriftLS

Hypotheses

US Macro-Release-Hour Repricing Continuation on AAVEUSDT.BINANCE Perp — Long-Short 15m Intraday Drift from the 08:30 ET Data Slot to the US Close (DST-aware time gate, self-selecting volatility trigger, 3-parameter)

Hypotheses

A LONG-SHORT, SINGLE-INSTRUMENT, PURE-OHLCV, INTRADAY strategy on AAVEUSDT.BINANCE USD-M perpetual, 15-MINUTE bars (catalog verified: 2020-10-16 -> 2026-09-09, ~207,000 bars, ~1,780 US business days). The mechanism is NOT price-pattern momentum and NOT a mean-reversion fade: it is a CLOCK-ANCHORED INFORMATION-ARRIVAL effect. Essentially every high-impact scheduled US macro release (CPI, PPI, NFP, PCE, retail sales, jobless claims, GDP) prints at 08:30 America/New_York. Crypto perps are the only deeply liquid venue open at that instant and they reprice immediately; slower capital (US desks opening at 09:30, spot-ETF creation flow, CTA/vol-target rebalancing, options dealer hedging) arrives over the following hours, producing a post-announcement DRIFT in the direction of the initial repricing. The strategy needs NO event calendar and NO news data: it looks only at the single 15m bar spanning 08:30-08:45 ET on US business days (DST-aware via zoneinfo America/New_York -> 12:30-12:45 UTC in EDT, 13:30-13:45 UTC in EST), and lets a VOLATILITY-RELATIVE MAGNITUDE FILTER self-select the days on which something actually printed. On a day with no release the 08:30 bar looks like any other bar and the trigger simply does not fire. Deliberately fills three portfolio gaps at once: direction long_short (14.9% vs >=45% target), horizon short_1m_15m (9.5%), and an instrument (AAVE) with ZERO prior use in the 74-of-767 corpus. It does NOT clone any surviving mechanism — no trend/MA/RSI/breakout indicator appears anywhere in the logic; the only 'signal' is a timestamp plus a vol-normalised move size.

Hypotheses

Iteration 3 fixes the [critical] QA defect and nothing else. The stale hold anchor is gone: should_exit() now reads the live position from cache.positions_open() and derives both the entry ET ordinal (from position.ts_opened) and bars-held (elapsed seconds / _bar_interval_secs) from it, holding NO mutable cross-bar state. Previously _entry_ordinal/_bars_held were cleared only when should_exit() returned True, so an intra-bar bracket stop/TP fill (the base template never calls should_exit() on a bar where the book is already flat) left a stale ordinal that flattened the next release-day entry after a single 15m bar -- exactly the 4h43m vs ~7h15m holding-period gap QA identified. The position-derived anchor also resolves the [warning] about state surviving flattening/on_stop/warm restart by construction. For the thin-sample [warning] the entry_z clamp ceiling was lowered from 4.0 to 2.5 (bounds declared identically in _param_bounds) so the optimizer cannot thin the ~179-trade full-sample trigger below measurability. Clock gate, z-score signal, imports and sizing are untouched, so Layers 1-3 stay green. Honest caveat on the advisory [edge_concern]: my full-sample dry run measured the post-08:30-ET drift at every |z| threshold AND every holding horizon (including hold-to-16:00-ET, which is what this fix restores) and it is statistically indistinguishable from zero everywhere (|t| <= 1.4), negative at this config -- so the fix makes the backtest test the hypothesis faithfully but I do not expect it to produce a positive edge.

Hypotheses

premise_falsified on an adequate, reliable sample. The strategy implements the hypothesis correctly — 179 entries, all on the 08:30-08:45 ET bar on US business days, DST handled, held to the 16:00 ET close — and the measured post-release drift is negative, not positive: avg_trade_return_pct -0.237% against a +0.15% USD-M fee floor, PF 0.650, Sharpe -0.713, expectancy -$96.26/trade, -17.19% total. Not a fee problem (commissions 10.18% of gross), not a leg-asymmetry bug (longs 32.3% win / shorts 44.6% win, both sub-breakeven), not regime-specific (negative in calm, normal and stressed terciles, and in 5 of 7 calendar years). The stressed tercile — where macro-release days live — is negative, so the information-arrival premise fails precisely where it should be strongest; the 38% win rate with a ~1.06 payoff says the 08:30 repricing mean-reverts into the US session rather than drifting. Optimization cannot help: the only tunables are entry_z and vol_lookback, and the developer's own full-sample dry run already swept |z| 0.75-4.0 and every horizon out to 16:00 ET, finding no drift anywhere (|t| <= 1.4, -0.210%/trade). QA's pre-registered edge concern is confirmed rather than refuted. Not revise_hypothesis: the mechanism was tested directly and the sign is wrong on a 6-year sample, and the naive inversion is not a free win either — a fade would need to clear the same 0.15% round trip plus ~$5.7k modeled impact at 20%-of-equity clips on a mid-cap alt perp, so any reframe needs a materially stronger conditioning variable than a vol z-score, and a more liquid instrument.

Implementation

Long/short intraday continuation on AAVEUSDT.BINANCE USD-M perp, 15m bars. Each US business day the strategy looks only at the 15m bar closing at 08:45 ET (the 08:30 ET macro-release slot; DST-aware via a precomputed US transition table resolved with bisect, so 12:45 UTC in EDT / 13:45 UTC in EST). The signal is that bar's log return divided by trailing realized vol (192-bar sigma, excluding the current bar) and is computed continuously every bar; the clock gate plus |z| >= entry_z (2.0) self-selects days on which a release actually repriced the perp. Entry is in the direction of the repricing, sized by the tighter of a 25%-of-equity notional cap and a 0.5%-of-equity per-trade risk budget over the 2.5% stop. Exits: venue-managed bracket (2.5% stop / 5% take-profit) plus a time exit at the 16:00 ET US cash close, never carrying overnight.

Verification Results

Lower risk_per_trade to ~0.002-0.003 so clips are ~5-10% of equity; re-check impact_cost_pct on the full backtest.

Verification Results

position_size() commits 20% of equity in notional per 15m clip (risk 0.5%/stop 2.5% binds); modeled impact ~$44/clip (~0.22% of notional) vs $20 commission, capacity_usd $95,986 — sizing sits at modeled capacity with no headroom.

Verification Results

Optionally exclude XNYS holidays via src/data/market_calendar.py.

Verification Results

Business-day gate is weekday-only; US market holidays are not excluded, so a high-|z| 08:30-ET bar on a holiday is a pure crypto-vol event, not the stated mechanism. The vol filter mitigates but does not eliminate it.

Verification Results

Treat sub-sample splits as descriptive if the backtest lands under ~150 trades.

Verification Results

~179 entries over the full history (~10% of US business days) is near the lower bound for distinguishing edge from noise; the optimizer can thin it further toward the entry_z 2.5 ceiling.

Verification Results

No change required.

Verification Results

Static analysis 'base_shadow' on min_bars_required() is a FALSE POSITIVE — the base method is documented 'Override as needed'.

Verification Results

Sandbox is negative (total_return -1.33%, Sharpe -0.89, PF 0.99 on 15 positions) and loses in all three vol terciles, worst in the stressed third (-1.16%, Sharpe -2.19) — the opposite of what an information-arrival drift should do, since release days ARE the high-vol days. Commissions are only 14.5% of gross, so costs are not binding; the gross drift is. The developer's full-sample dry run corroborates: no forward drift at any |z| in 0.75-4.0 or any horizon out to the 16:00 ET close (|t| <= 1.4), -0.210%/trade at n=179. Only ~179 trades over ~6 years. First checks at backtest review: long/short leg symmetry, drift on the highest-|z| subset only, and modeled impact (impact_cost_pct 102%, capacity_usd ~$96k at 20%-of-equity clips).

Backtest Review

Implementation is clean and does what the hypothesis says: 179 entries all fire on the 08:30-08:45 ET close bar on US business days, DST-aware, long 96 / short 83 (near-symmetric), avg holding 4h42m to the US close, exposure 1.64% — the clock gate, the self-selecting vol trigger and the hold-to-close all work as designed.

Backtest Review

Sample is adequate for a verdict: 179 trades over 2155 days with metrics_reliable=true, so this is a measurement of the premise, not a small-sample accident.

Backtest Review

Not a cost artifact: commissions are only 10.18% of gross.

Backtest Review

Hypothesized drift is absent with the WRONG sign: avg_trade_return_pct -0.237% (vs +0.15% floor), PF 0.650, Sharpe -0.713, expectancy -$96.26/trade, -17.19% total.

Backtest Review

Both legs fail independently — long win rate 32.3%, short win rate 44.6% — so not a leg-asymmetry bug.

Backtest Review

Negative in 5 of 7 calendar years and in all three vol terciles, including stressed (-2.3%), which is where release days live.

Backtest Review

38.0% win rate with ~1.06 payoff: the 08:30 move mean-reverts into the session rather than drifting.

Backtest Review

Developer's own dry run already swept |z| 0.75-4.0 and every horizon to 16:00 ET: no drift anywhere (|t| <= 1.4).

Backtest Review

Capacity: $5,709 modeled impact at avg_position_pct 20.7% on a mid-cap alt perp; 2129 days underwater, tail_ratio 0.0.

Analysis

Backtest gate: - metrics unreliable: Incoherent: Sharpe 0.22 disagrees in sign with total_return -65.02% — 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

AaveMacroReleaseHourDriftLS-f8ad9e628e

Outcome Summary

AaveMacroReleaseHourDriftLS tested a clock-anchored information-arrival thesis on AAVEUSDT.BINANCE 15m bars: trade the direction of the 08:30-08:45 ET macro-release bar when its move was volatility-large, and hold to the 16:00 ET US close. After three iterations the code did exactly what the hypothesis specified - 179 DST-aware entries on US business days, 96 long and 83 short, 4h42m average hold, 1.64% exposure - and the six-year measurement came back with the opposite sign to the prediction: -17.19% total, Sharpe -0.713, profit factor 0.650, and -0.237% average per-trade return versus a +0.15% fee floor. The weakness was not cost, leg asymmetry or a single regime; losses appeared in calm, normal and stressed volatility alike and in 5 of 7 years, with a 38% win rate at a ~1.06 payoff indicating the release-hour move fades into the session. The analyst abandoned it at backtest review rather than spending the 3-phase optimization, noting that the only tunables had already been swept with no drift found at any threshold or horizon.

Outcome Summary

A clock gate plus a volatility z-score is not a strong enough conditioning variable to isolate macro-release information arrival: the 08:30 ET repricing in this perp mean-reverts into the US session rather than drifting, so any reframe needs a genuine event/surprise signal and a more liquid instrument.

Outcome Summary

The backtest-review gate returned `abandon` before optimization, citing premise_falsified: the implementation matched the hypothesis exactly (179 entries all on the 08:30-08:45 ET bar, DST-aware, held to the close) but the measured drift had the wrong sign on an adequate, reliable sample. It was ruled out as a fee artifact (commissions 10.18% of gross) and as a leg-asymmetry bug (long win 32.3%, short win 44.6%, both sub-breakeven), and the developer's own sweep of |z| 0.75-4.0 across every horizon to 16:00 ET found no drift anywhere (|t| <= 1.4), so optimization could not have rescued it.

Outcome Summary

It bet that the immediate AAVEUSDT perp repricing in the 08:30-08:45 ET US macro-release slot would continue to drift in the same direction through to the 16:00 ET US cash close, long or short, with a volatility-relative magnitude z-score self-selecting the release days without any event calendar.

Outcome Summary

Over 2,155 days and 206,852 15-minute bars it took 179 trades (96 long / 83 short, avg hold 4h42m) for a total return of -17.19%, Sharpe -0.713, profit factor 0.650, win rate 38.0% and expectancy -$96.26 per trade. Average per-trade return was -0.237% of notional against the +0.15% USD-M viability floor, and it was negative in 5 of 7 calendar years and in all three volatility terciles, including the stressed tercile (-2.33%).

Iteration History

Verification failed (Layer 4 — QA review) [class=code_defect]: - [edge_concern] Developer's full-sample dry run shows the post-08:30-ET continuation drift is statistically zero at every |z| threshold and horizon (|t| <= 1.4), and negative at the stated config (-0.210%/trade, t=-0.67, n=179); the prior backtest matched (avg_trade_return_pct -0.237%, PF 0.58, commission only ~11% of gross, i.e. gross drift is the problem). This sandbox loses in all three vol terciles. Advisory only — not the reason for the verdict. - [critical] Stale hold-state across positions. `_entry_ordinal`/`_bars_held` reset ONLY when should_exit() returns True, but `use_bracket_orders: true` (2.5% stop / 5% TP) means positions are frequently closed intra-bar by a venue-managed leg — on that bar the base template sees `position is None` and never calls should_exit(). The next release-day entry then hits should_exit() on its FIRST bar with `_et_ordinal != _entry_ordinal` already true (the gate fires at most once per business day), flattening after a single 15m bar instead of holding to 16:00 ET. Sandbox avg_holding_period 4h43m vs the intended ~7h15m is consistent with this firing. (line 197) — fix: Derive the anchor from the live position (`position.ts_opened` → ET ordinal, bars held = (bar ts − ts_opened)/interval) and hold no cross-bar mutable state, or clear the state whenever on_bar observes a flat book. - [warning] Same state is never cleared by on_stop/flattening or a warm restart. (line 197) — fix: Position-derived anchor removes the class. - [warning] Trigger rate is thin (15 trades / 207 sandbox days; 179 over 2,155 days) — a higher optimized entry_z easily pushes the sample below measurable. (line 57) — fix: Floor entry_z so expected trades stay above ~100.
Strategy report

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