SolMacroEventBreakoutContinuationLS
Hypotheses
SOL Post-Macro-Announcement Breakout Continuation, Long-Short (SOLUSDT.BYBIT Perp, Scheduled US-Event-Gated: Trade the Trend-Aligned Range Break in the Hour After FOMC/CPI/NFP/PCE, Time+ATR Stop, 3-Parameter)
Hypotheses
A LONG-SHORT, single-instrument directional strategy on SOLUSDT.BYBIT (linear USD-M perpetual) whose entries are gated ENTIRELY to the timestamps of scheduled US macro releases. The event calendar (FOMC rate decisions ~8/yr @ 14:00 ET, CPI ~12/yr @ 08:30 ET, Nonfarm Payrolls ~12/yr @ 08:30 ET, PCE ~12/yr @ 08:30 ET) is KNOWN HISTORY — hardcoded UTC timestamps, no news/sentiment feed required, fully backtestable over SOL's multi-year Bybit history. ~44 events/yr x ~5-6 usable years ~= 220-260 event windows. This is NOT a continuous-momentum/regime-gate mechanism (L92), NOT a session/opening-range seasonality trade on the 24/7 clock (L79/L89 are about intraday VWAP/US-cash-open fades that fire thousands of times) — it fires only at a fixed, sparse, exogenous macro schedule and rides the information-driven repricing. Routed to BYBIT to fill the emptiest venue in the corpus (1 of 3011 experiments) and expressed LONG-SHORT to fill the under-target direction bucket; SOL chosen over BTC/ETH (44%/over-mined) because its higher macro-beta amplifies the post-event move, improving per-trade capture relative to fees. FEE ARITHMETIC: on FOMC/CPI/NFP release days SOL's realized intraday range is typically 3-7%; a trend-aligned breakout continuation captures ~1.0-1.5% of that swing. Bybit linear taker RT ~0.11%. Even at a realistic 45% win rate with avg_win ~1.6% / avg_loss ~0.9% (ATR stop), gross expectancy ~= 0.45*1.6 - 0.55*0.9 = +0.225%/trade, net ~+0.11% after the 0.11% RT fee — >2x the 0.10% low-fee bar is achieved through selectivity, not through a small edge fought against friction. Trend-alignment (only take breakouts in the direction of the 3-day trend) is a whipsaw filter on an already-rare exogenous trigger, not a regime gate manufacturing an edge from a sub-fee signal.
Hypotheses
Iteration 2 fixes the single reported failure (leverage_set_but_unused) with the smallest possible change: position_size() now reads self.config.leverage DIRECTLY (the previous getattr(self.config, 'leverage', ...) form did not register as a leverage reference) and consumes it as the gross-notional cap: max_notional = equity * max_notional_frac * self.config.leverage. The leverage genuinely binds — a risk_pct of 1.5% against a typical post-release ATR stop of ~1-1.5% asks for 1.0-1.5x equity of notional, which only exists on 2x margin, so the backtest is NOT identical to 1x. Nothing else changed: the macro-calendar schedule, frozen pre-release range, continuous ATR-distance signal, trend-alignment filter, bracket exits and time stop that already passed Layer 1 static analysis are untouched.
Hypotheses
Negative expectancy on a decisive 72-trade / 1788-day (~5-year) sample: profit_factor 0.657 (<1 — gross-NEGATIVE before costs, commission only 15.4% of gross, so this is a losing signal not fee-fragility), total_return -24.59%, expectancy -$342.8/trade, Sharpe -0.662 with CI [-1.474, 0.216] straddling zero. Optimization cannot lift an edge that is negative before costs. The code faithfully implements the post-macro trend-aligned breakout hypothesis (72 signaled = 72 submitted, balanced 42 long / 30 short, hardcoded macro calendar, venue-managed ATR bracket + time stop) so this is a fair test, and QA's concern is confirmed on full history: the post-FOMC/CPI/NFP/PCE breakout continuation does not capture the intended 1.0-1.5% swing on SOL (win rate 0.375, short leg 0.267). The failure is regime-WIDE — the book loses in the calm (-34.0%) and stressed (-17.8%) vol terciles (only_one_regime=true, profit confined to the normal tercile) and in 4 of 6 calendar years (2022 -4.3%, 2023 -1.2%, 2025 -13.0%, 2026 -9.6%) — the opposite of a robust event-driven edge. Tuning 3 parameters cannot rescue a PF-0.657 signal that is gross-negative in most regimes and years; not worth 2 hours of walk-forward. abandon_class=negative_expectancy (premise falsified on SOL).
Implementation
Long/short SOLUSDT Bybit linear-perp strategy that trades ONLY in the hour after a scheduled US macro release (FOMC 14:00 ET, CPI/NFP/PCE 08:30 ET), on a hardcoded, purely calendar-derived event schedule. On each release the pre-release 2h high/low range is frozen; a 15m close that breaks that range by more than entry_atr_mult ATR, in the same direction as the trailing 3-day return, takes one trade per event. Risk is managed by a venue-managed OUO bracket (ATR-scaled stop + R-multiple take-profit) so exits fire intra-bar on violent post-release candles, plus a bar-count time stop. Sizing risks risk_pct of equity at the ATR stop, capped at max_notional_frac x leverage x equity.
Verification Results
No change required if the base gates calculate_signal() on self.min_bars_required(); otherwise rename to avoid shadowing and set the warmup via the intended hook.
Verification Results
min_bars_required() overrides a base-template method (static analyzer flagged base_shadow). This appears deliberate — the strategy needs a long warmup (trend_bars + atr_period + 5 = 389 bars) to seed ATR/trend buffers — and Python polymorphism means the override IS used by the base loop. Not a defect, but confirm the base template actually calls the instance method (not a private cached value) so the intended 389-bar warmup is honored.
Verification Results
Verify the base template reads stop_loss_pct/take_profit_pct from self.parameters (not a snapshot taken at __init__) when use_bracket_orders is true, so the per-event overwrite reaches the submitted bracket.
Verification Results
should_enter() mutates self.parameters['stop_loss_pct'] / ['take_profit_pct'] each entry so the venue bracket legs are ATR-adaptive. This relies on the base template reading those keys from self.parameters at submission time, in the same call stack immediately after should_enter/position_size. The mechanism is sound and the config carries valid non-zero defaults (0.02 / 0.036) so bracket entries are never refused, but it is an implicit contract with the base template.
Verification Results
Sparse exogenous trigger: sandbox produced 9 trades in 208 days at a ~36% event-to-trade pass rate. Extrapolated over SOL's ~5-6y Bybit history (~44 events/yr) this implies only ~95-130 trades — borderline for statistical power (L16/L26). Sandbox smoke test is also net-negative (PF 0.23, avg_trade_return_pct -0.36%, negative in all three vol terciles) on one unoptimized draw; the trend-alignment filter + entry_atr_mult gate may be too selective to accumulate a decisive sample. Suggest the analyst confirm full-history trade count clears ~100 and that per-trade net edge survives the 0.11% Bybit RT before committing to optimization.
Backtest Review
Mechanism is faithfully implemented and deterministic: 72 signaled = 72 submitted, balanced 42 long / 30 short, macro calendar hardcoded with no look-ahead, venue-managed ATR bracket + time stop.
Backtest Review
Decisive sample for this cadence: 72 trades over 1788 days (~5 years) clears QA's ~100-trade worry is close but the result is not marginal — it is clearly negative.
Backtest Review
Gross-negative signal: profit_factor 0.657 (<1 BEFORE costs — commission is only 15.4% of gross), so no parameter tuning can lift an edge that is negative before fees.
Backtest Review
Negative expectancy across the board: total_return -24.6%, expectancy -$342.8/trade, Sharpe -0.662 with CI [-1.474, 0.216] straddling zero, Sortino -0.20, recovery_factor -0.865.
Backtest Review
Regime-wide failure, not a cliff: loses in the calm (-34.0%) and stressed (-17.8%) terciles (only_one_regime=true, profit only in the normal tercile +14.6%), and negative in 4 of 6 calendar years (2022 -4.3%, 2023 -1.2%, 2025 -13.0%, 2026 -9.6%).
Backtest Review
QA's edge concern is borne out and worse on full history: the post-macro trend-aligned breakout does not capture the intended swing — win rate 0.375 (short leg 0.267), the whipsaw filter did not manufacture an edge.
Outcome Summary
SolMacroEventBreakoutContinuationLS-3b464ab14f
Outcome Summary
SolMacroEventBreakoutContinuationLS attempted to exploit information-driven repricing by trading trend-aligned range breakouts on SOL perpetuals only in the hour after scheduled US macro releases, using a deterministic hardcoded event calendar routed to Bybit. The code faithfully implemented the hypothesis (72 signaled = 72 submitted, balanced 42 long / 30 short, venue-managed ATR bracket plus time stop), giving a fair test on a decisive ~5-year, 72-trade sample. But the result was clearly negative: total_return -24.59%, Sharpe -0.662, and a profit_factor of 0.657 that was below 1 even before fees, with losses spread across most years and both the calm and stressed regimes. The analyst abandoned it at the backtest-review gate as negative_expectancy with the premise falsified on SOL, since no amount of parameter tuning can lift an edge that is gross-negative before costs; optimization, analysis, and risk review were never reached.
Outcome Summary
A plausible fee-arithmetic thesis is not enough; the post-macro trend-aligned breakout on SOL failed to capture the intended swing and lost across 4 of 6 years and both the calm and stressed vol regimes, showing the premise was falsified rather than merely fee-fragile.
Outcome Summary
The analyst abandoned it at the pre-optimization backtest-review gate: the signal was gross-negative before costs (profit_factor 0.657, commission only 15.4% of gross), so parameter tuning could not rescue it and walk-forward optimization was not worth running.
Outcome Summary
A long-short SOLUSDT.BYBIT perpetual strategy that fired only in the hour after scheduled US macro releases (FOMC/CPI/NFP/PCE) via a hardcoded event calendar, riding trend-aligned breaks of the pre-release range with an ATR stop and bar-count time stop.
Outcome Summary
Over 72 trades across 1788 days (~5 years), it lost money with total_return -24.59%, Sharpe -0.662 (CI [-1.474, 0.216]), profit_factor 0.657, expectancy -$342.84/trade, win rate 0.375 (short leg 0.267), and max drawdown 28.82%.
Iteration History
Verification failed (leverage_set_but_unused): config sets leverage=2.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.
Backtest and paper results are hypothetical. Trading involves risk of loss.