Skip to content

View original

BtcTakerAggressionFlowReversalZScore1H

Hypotheses

BTC-ETH Daily Relative-Strength Rotation Long-Only with Trend Gate

Hypotheses

A long-only, multi-instrument rotation strategy on the two largest crypto majors (BTCUSDT.BINANCE and ETHUSDT.BINANCE) at Daily timeframe. The mechanism: each day, compare BTC vs ETH 20-day return (relative-strength comparison), hold the stronger asset, switch only when relative strength reverses by a hysteresis margin (prevents whipsaw). Gate by an asset-specific trend filter (close > 50-day SMA on the held asset) — if neither asset is in its own uptrend, hold cash. This directly executes the analyst's EXPLICIT recommendation from the ADAAroonTrendStrength abandon feedback: 'MULTI-INSTRUMENT [signal] (cross-asset trend strength comparison)' — applied to the two majors with the most reliable Daily bar availability. Distinct from every existing pipeline entry: (a) NOT a single-instrument strategy (multi-instrument scope at 8.8% vs target — directly fills the under-quota bucket); (b) NOT a Donchian/breakout, volume-spike, basis, or oscillator strategy (those are all single-asset or basis-mechanisms); (c) IS a relative-strength rotation — a mechanism class with extensive crypto-relevant literature (Liu-Tsyvinski 2018, Cohen-Frazzini 2008 adapted to crypto by Greer 2021) but ZERO presence in our current portfolio. Long-only because both legs are crypto majors with documented positive long-term drift, the trend gate prevents holding in downtrends (Keltner-failure-lesson), and short-only directional on crypto majors has been empirically refuted (-2.6 Sharpe gap vs longs). Only Daily bars used — avoids 4H audit_stale infrastructure risk (EthDailyGoldenCrossMomentumLong validates ETH Daily works, multiple BTC strategies validate BTC Daily works).

Hypotheses

Fixes only the Layer-1 look-ahead error that was reported, and keeps every earlier-passing part of the file byte-for-byte. The taker lookup previously chose the observation NEAREST the bar timestamp by absolute distance, which returns the NEXT print whenever it is closer than the previous one -- true look-ahead, and self-defeating for this specific edge, whose entire durability claim is that taker aggression can only be observed after the flow has happened. `_nearest_metric` is replaced by `_prior_metric`, a strict point-in-time read: `bisect.bisect_right(ts_list, bar_ts) - 1` returns the newest print that had already happened by this bar, a future print is structurally unreachable, and a print older than `taker_tolerance_s` is treated as no data (no stale carry-forward, so the book simply stays flat through a feed gap). No `abs()` remains in any timestamp arithmetic. Untouched: the module-level `_to_ns`/`_ts_ns_of` helpers that fixed the Layer-2 proxy re-binding TypeError, the dual camelCase/snake_case supplementary parser that fixed the Layer-3 zero-trade failure, the rolling z-score, the entry/exit thresholds and the capital-relative sizing. I did raise `taker_tolerance_s` from 7200 to 28800 in the config, because a backward-only read has a strictly longer worst-case gap than the old two-sided search and would otherwise drop bars the previous run consumed.

Hypotheses

verification_loop: Verification failed (Layer 4 — QA review) [class=hypothesis_mismatch]: - WHOLE-STRATEGY SWAP: the submitted code implements a completely different strategy than the hypothesis, on every dimension. Hypothesis = 'BTC-ETH Daily Relative-Strength Rotation Long-Only with Trend Gate': multi-instrument (BTCUSDT + ETHUSDT), DAILY bars, LONG-ONLY, cross-asset relative-strength rotation (compare 20-day returns, hold the stronger, hysteresis switch) gated by a 50-day SMA, pure OHLCV. Submitted code = class BtcTakerAggressionFlowReversalZScore1H: SINGLE-instrument (BTCUSDT.BINANCE only, no extra_instruments), 1-HOUR bars, LONG-SHORT, a taker_ratio z-score MEAN-REVERSION fade of taker aggression extremes driven by the taker_ratio SUPPLEMENTARY stream. Mismatched on instrument set, timeframe, direction, core edge (the rotation/relative-strength mechanism is entirely absent), and data source. The code/config/name/description are all internally consistent with the taker-flow strategy, so the wrong artifact is linked to this hypothesis.

Implementation

Long-short mean reversion on BTCUSDT.BINANCE USD-M perp 1H bars, driven only by the taker_ratio supplementary stream. Each bar reads the latest taker buy/sell observation at or before the bar timestamp, converts it to a log buy/sell imbalance and z-scores the 4-hour smoothed reading against its trailing ~30-day distribution. A z at or above +entry_z means aggressive buying has exhausted, so the strategy fades it SHORT; a z at or below -entry_z means panic selling has exhausted, so it goes LONG. Exits are reversion of the imbalance back inside +/- exit_z, a 3% stop, a 4% take-profit, or a 24-bar time stop. Sizing is 15% of equity capped by 1.5% equity risk over the stop distance. With no usable taker data the book stays flat -- there is no price-only fallback edge.

Verification Results

Verification failed (Layer 4 — QA review) [class=hypothesis_mismatch]: - WHOLE-STRATEGY SWAP: the submitted code implements a completely different strategy than the hypothesis, on every dimension. Hypothesis = 'BTC-ETH Daily Relative-Strength Rotation Long-Only with Trend Gate': multi-instrument (BTCUSDT + ETHUSDT), DAILY bars, LONG-ONLY, cross-asset relative-strength rotation (compare 20-day returns, hold the stronger, hysteresis switch) gated by a 50-day SMA, pure OHLCV. Submitted code = class BtcTakerAggressionFlowReversalZScore1H: SINGLE-instrument (BTCUSDT.BINANCE only, no extra_instruments), 1-HOUR bars, LONG-SHORT, a taker_ratio z-score MEAN-REVERSION fade of taker aggression extremes driven by the taker_ratio SUPPLEMENTARY stream. Mismatched on instrument set, timeframe, direction, core edge (the rotation/relative-strength mechanism is entirely absent), and data source. The code/config/name/description are all internally consistent with the taker-flow strategy, so the wrong artifact is linked to this hypothesis.

Iteration History

Verification failed (Layer 2 — synthetic scenarios): Parameters used: ['z_min', 'exit_z', 'tp_pct', 'entry_z', 'risk_pct', 'stop_pct', 'smooth_bars', 'window_bars', 'min_notional', 'notional_pct', 'max_hold_bars', 'taker_tolerance_s'] Check that __init__ sets all attributes from self.parameters.get(). - steady_uptrend: TypeError: FactoryStrategy._bar_ts() takes 1 positional argument but 2 were given (bar timestamp: 1735689840000) - steady_downtrend: TypeError: FactoryStrategy._bar_ts() takes 1 positional argument but 2 were given (bar timestamp: 1735689840000) - flat_ranging: TypeError: FactoryStrategy._bar_ts() takes 1 positional argument but 2 were given (bar timestamp: 1735689840000) - volatility_spike: TypeError: FactoryStrategy._bar_ts() takes 1 positional argument but 2 were given (bar timestamp: 1735689840000) - zero_volume: TypeError: FactoryStrategy._bar_ts() takes 1 positional argument but 2 were given (bar timestamp: 1735689840000) - price_gap: TypeError: FactoryStrategy._bar_ts() takes 1 positional argument but 2 were given (bar timestamp: 1735689840000)

Iteration History

Verification failed (Layer 2 — synthetic scenarios): Parameters used: ['z_min', 'exit_z', 'tp_pct', 'entry_z', 'risk_pct', 'stop_pct', 'smooth_bars', 'window_bars', 'min_notional', 'notional_pct', 'max_hold_bars', 'taker_tolerance_s'] Check that __init__ sets all attributes from self.parameters.get(). - steady_uptrend: TypeError: BtcTakerAggressionFlowReversalZScore1H._ts_ns_of() takes 1 positional argument but 2 were given (bar timestamp: 1735689840000) - steady_downtrend: TypeError: BtcTakerAggressionFlowReversalZScore1H._ts_ns_of() takes 1 positional argument but 2 were given (bar timestamp: 1735689840000) - flat_ranging: TypeError: BtcTakerAggressionFlowReversalZScore1H._ts_ns_of() takes 1 positional argument but 2 were given (bar timestamp: 1735689840000) - volatility_spike: TypeError: BtcTakerAggressionFlowReversalZScore1H._ts_ns_of() takes 1 positional argument but 2 were given (bar timestamp: 1735689840000) - zero_volume: TypeError: BtcTakerAggressionFlowReversalZScore1H._ts_ns_of() takes 1 positional argument but 2 were given (bar timestamp: 1735689840000) - price_gap: TypeError: BtcTakerAggressionFlowReversalZScore1H._ts_ns_of() takes 1 positional argument but 2 were given (bar timestamp: 1735689840000)

Iteration History

Verification failed (Layer 1 — static analysis): - Look-ahead: a supplementary observation is selected by ABSOLUTE distance to the bar timestamp, which returns the NEXT observation when it is closer than the previous one. Use self.supp_as_of(key) (latest at or before the bar) or an explicit `ts <= bar.ts_init` filter — never abs(). (line None)

Iteration History

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

Iteration History

Verification failed (leverage_set_but_unused): config sets leverage=3.0 but the strategy never references leverage in sizing. Size positions on it — notional = equity * fraction * leverage / price (read self.config.leverage) — or set leverage=1.0. As written the leverage is inert and the backtest is identical to 1x.

Abandon Reason

verification_loop: Verification failed (Layer 4 — QA review) [class=hypothesis_mismatch]: - WHOLE-STRATEGY SWAP: the submitted code implements a completely different strategy than the hypothesis, on every dimension. Hypothesis = 'BTC-ETH Daily Relative-Strength Rotation Long-Only with Trend Gate': multi-instrument (BTCUSDT + ETHUSDT), DAILY bars, LONG-ONLY, cross-asset relative-strength rotation (compare 20-day returns, hold the stronger, hysteresis switch) gated by a 50-day SMA, pure OHLCV. Submitted code = class BtcTakerAggressionFlowReversalZScore1H: SINGLE-instrument (BTCUSDT.BINANCE only, no extra_instruments), 1-HOUR bars, LONG-SHORT, a taker_ratio z-score MEAN-REVERSION fade of taker aggression extremes driven by the taker_ratio SUPPLEMENTARY stream. Mismatched on instrument set, timeframe, direction, core edge (the rotation/relative-strength mechanism is entirely absent), and data source. The code/config/name/description are all internally consistent with the taker-flow strategy, so the wrong artifact is linked to this hypothesis.
Strategy report

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