Skip to content

View original

XrpDailyRangeExpansionBreakout

Hypotheses

XRP Daily Range Expansion Breakout

Hypotheses

A simple long-and-short daily breakout strategy on XRPUSDT perpetual futures. XRP exhibits a distinctive market structure: long periods of tight range consolidation (often 30-90 days) punctuated by violent range expansion moves driven by regulatory catalysts (SEC rulings, ETF news, partnership announcements) and accumulation by long-term holders. Unlike BTC/ETH which trend more continuously, XRP behaves like a coiled spring — range contraction precedes expansion. The strategy enters in the direction of a true-range expansion event (current bar's true range exceeds 2.5x its 20-day average) when the close is in the upper or lower 25% of the bar, indicating directional commitment. Holds for up to 7 days or exits on a chandelier-style trailing stop. Uses daily bars to keep frequency low (~1-2 trades per month), making the 0.10% round-trip fee negligible relative to expected per-trade returns of 5-15%.

Hypotheses

NOTE ON THE BRIEF: the `previous_code` supplied with this task is a different strategy entirely — AvaxTakerAggressorDominanceMomentumLong4H, a 4H AVAX taker-ratio order-flow strategy with no range-expansion logic, no XRP instrument and no short side. It cannot be edited into the XRP daily range-expansion breakout this hypothesis describes, so this submission implements the hypothesis directly and cleanly rather than mutating unrelated code. The restart notice confirms there is no outstanding code defect to preserve a fix for. Implementation maps 1:1 to the hypothesis: the 2.5x-of-20-day-average true-range expansion test, the upper/lower-25% close-location directional filter, the up-to-7-day hold, and the chandelier-style trailing stop are all present with the stated defaults; frequency is deliberately low (daily bars, ~1-2 signals a month at the default threshold) so the ~0.10% round-trip futures taker cost is immaterial against the 5-15% per-trade moves the thesis targets. Design choices worth flagging: (1) BINANCE USD-M rather than spot, because the strategy trades both directions and a CASH account cannot short — leverage stays 1.0 with a 1x-equity notional cap, so no margin amplification is claimed or used; (2) the ATR baseline excludes the current bar, otherwise the expansion day inflates its own denominator and the ratio is structurally compressed; (3) the chandelier extremes are seeded from the entry bar so a failed breakout is stopped out at roughly 3xATR instead of running unprotected; (4) every tunable is clamped to a declared range mirrored verbatim in `_param_bounds`, and the ranges let the optimizer loosen expansion_mult toward 1.6 or widen close_loc_frac toward 0.40 if the default gate proves too selective to populate walk-forward OOS windows; (5) true ranges are kept in a fixed-length deque with a running sum, so per-bar cost is O(1) and the sandbox cannot time out on history growth.

Hypotheses

Negative-edge, unmeasurable, near-zero-return single-instrument breakout — no edge to optimize. Over 46 trades in 6.7 years: avg_trade_return_pct is -1.24% (negative), total_return only +3.0% (CAGR 0.38%, flat), and the tiny positive is carried by a couple of outlier days (return_kurtosis 112) while most years are negative. It is not statistically distinguishable from zero (Sharpe 0.131 with bootstrap CI [-0.746, 0.786] straddling zero, PSR 0.59) and the 46-trade sample is far below the ~100 measurability floor, so the walk-forward folds and 20% holdout would be near-empty. exposure_pct is 2.12% — the 2.5x expansion gate almost never fires, so the strategy barely deploys capital and cannot compound (PF 1.14). This is the L30/L63 single-instrument breakout graveyard with a negative stressed regime (-3.6%). No parameter tuning conjures a positive edge from a negative-per-trade, ~0%-CAGR strategy on an unmeasurable sample. Failure pattern: no_edge single-instrument breakout, negative per-trade, unmeasurable (L30/L63/L10).

Implementation

Long-and-short daily range-expansion breakout on XRPUSDT.BINANCE USD-M perpetual, 1-DAY bars, pure OHLCV, leverage 1.0. Each day the strategy measures today's true range against the mean of the prior 20 true ranges (the quiet-regime baseline, current bar excluded). When today's range is at least 2.5x that average AND the bar closes in its upper 25% it goes LONG; when it closes in the lower 25% it goes SHORT — the close-location filter separates a directional-commitment expansion from a wide but indecisive bar. calculate_signal returns expansion x close-location every bar, a continuous score whose sign is direction and whose magnitude is the violence of the expansion. Positions exit on a chandelier trailing stop (highest high since entry minus 3xATR for longs, lowest low plus 3xATR for shorts, seeded from the entry bar so it doubles as the initial stop) or a 7-day time stop, whichever fires first. Size is risk-based: equity x 2% divided by the 3xATR stop distance, capped at 1x equity notional and floored to the instrument's size precision. All per-bar work is O(1) via a bounded true-range deque with a running sum.

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.

Backtest Review

Clean, low-parameter pure-OHLCV construction; low drawdown (5.4%) and low fee drag (commission 3% of gross); no blow-up

Backtest Review

Sensible expansion+close-location breakout logic

Backtest Review

Negative edge: avg_trade_return_pct -1.24%; total_return +3.0% over 6.7 years (CAGR 0.38%), carried by a couple of outlier days (kurtosis 112)

Backtest Review

Not significant and below measurability: 46 trades over 6.7 years, Sharpe 0.13 with CI [-0.746, 0.786] straddling zero, PSR 0.59 — the 20% holdout would be near-empty

Backtest Review

Capital idle: exposure_pct 2.12% — the expansion gate rarely fires, so it cannot compound; PF 1.14 thin

Backtest Review

Single-instrument breakout (L30/L63 graveyard); most years negative; stressed regime -3.6% (Sharpe -0.33)

Analysis

Code↔hypothesis misalignment found by the semantic auditor — the code does NOT implement the hypothesis. Re-code the strategy to implement the hypothesis EXACTLY (instrument, timeframe, direction, the named edge/mechanic, sizing). Concrete issues: Wrong instrument: hypothesis specifies XRPUSDT perpetual futures, config uses AVAXUSDT.BINANCE | Wrong timeframe: hypothesis specifies daily bars (~1-2 trades/month), config uses AVAXUSDT.BINANCE-4-HOUR-LAST-EXTERNAL | Wrong direction: hypothesis is explicitly long-and-short (entry on close in upper OR lower 25% of the bar), but should_enter only ever returns OrderSide.BUY or None | Wrong edge/mechanic: hypothesis's core signal is true-range expansion (current TR > 2.5x 20-day average TR); the code contains no true-range/ATR computation and never reads bar.high or bar.low — it signals entirely off the taker buy/sell volume ratio supplementary stream (ratio_threshold=1.005, confirm_period=1) | Wrong exit logic: hypothesis specifies up to a 7-day hold with a chandelier-style trailing stop; the code implements a 12-bar (48h) time stop, a taker-ratio flow-reversal exit (ratio < 1.0), and a flat 6% hard stop — no trailing/chandelier stop exists

Iteration History

AvaxTakerAggressorDominanceMomentumLong4H

Iteration History

Verification failed (Layer 2 — synthetic scenarios): Parameters used: ['risk_pct', 'exit_bars', 'min_notional', 'min_stop_pct', 'hard_stop_pct', 'per_trade_pct', 'confirm_period', 'ratio_threshold', '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 3 — sandbox backtest): No trades produced Bar type used: AVAXUSDT.BINANCE-4-HOUR-LAST-EXTERNAL, Bars processed: 12413 Diagnostics: should_enter() returned a side 0 times over 12409 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 (Layer 3 — sandbox backtest): smoke test exceeded the 300s wall-clock limit. This almost always means per-bar work that scales with history — e.g. rescanning the full funding/supplementary series, or rebuilding a list and calling min()/sorted() inside calculate_signal()/on_bar() on every bar. Precompute sorted timestamp arrays ONCE in __init__ and use bisect, or cache lookups keyed by timestamp, so per-bar cost is O(log n) not O(n).
Strategy report

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