EthGlobalRetailCrowdContrarianReversalLS
Hypotheses
Retail Crowd-Positioning Contrarian Reversal, Long-Short (Single-Instrument ETHUSDT.BINANCE USD-M — Fade the GLOBAL Retail Account Long/Short Ratio at Crowding Extremes: Short When the Retail Crowd Is Overwhelmingly Long, Long When It Is Overwhelmingly Short, Hold Until Positioning Normalizes, 2-Parameter)
Hypotheses
A LONG-SHORT, SINGLE-INSTRUMENT, SINGLE-VENUE swing-reversal strategy on ETHUSDT.BINANCE USD-M whose ONLY signal is the GLOBAL account Long/Short RATIO — the 'L/S ratios' supplementary feed (Binance globalLongShortAccountRatio), which counts how many retail accounts are net-long vs net-short. This is a genuinely NEW data source relative to everything currently pending or burned: the pending SOL hypothesis uses the FUNDING RATE, the pending ETH hypothesis uses OPEN INTEREST, and my prior basis hypothesis used MARK/INDEX premium — none of them use the account-positioning ratio, and it is orthogonal to price (it measures the composition of the crowd, not the tape). The mechanism is the classic 'dumb-money' contrarian effect: when the global retail crowd is overwhelmingly positioned one way, that side is over-owned and primed to be flushed, so forward returns skew against the crowd. It deliberately AVOIDS every recent death trap: not OHLCV-only-directional (L42 — the signal is exogenous positioning data); not the liquidations feed (forward-only from 2026-04-21, unmeasurable); not options/IV (L43); not cross-venue or multi-leg (L44 — one instrument, one venue, one feed); and NOT a momentum-gating overlay (the AVAX funding-gated-momentum that just died overfit) — it is pure contrarian mean-reversion on positioning, not a trend re-derivation. It is also mechanistically distinct from the earlier 'informed-positioning basket' that died no_trades: that one FOLLOWED top-trader smart-money in a low-turnover LONG-ONLY SPOT basket; this one FADES the retail global crowd as a LONG-SHORT single perp. Being long-short fills the under-represented direction bucket (13.4% vs the ≤55% long-only target).
Hypotheses
Iteration 3 makes the smallest changes that address the three Layer-4 findings, leaving the signal path, imports, and class structure (which passed Layers 1-3 and the QA logic review) untouched. (1) TOO FEW TRADES — I measured the actual feed instead of guessing: data/supplementary/global_account_ratio/ETHUSDT holds 13,626 rows spanning 2026-03-23 to 2026-08-01 (~131 days; 5-minute to 2026-05-06, hourly after). That is the true measurement window, and QA is right that it is forward-capture-only and cannot be backfilled. The 14-trade result follows directly from the previous 4-HOUR clock: signal existed on only ~1/3 of the 363-day sandbox, and a fixed 120-bar baseline consumed 20 of those days as warmup, leaving ~660 signal-bearing bars. Switching to 1-HOUR bars (the feed's native cadence after 2026-05-06, and 12x oversampled before it) cuts warmup to 5 days and yields ~3,000 signal-bearing bars in the SAME measurable window — roughly an order of magnitude more entry opportunities without touching the mechanism. entry_z 1.5 -> 1.25 and max_hold_hours 240 -> 72 add turnover on top, so each walk-forward OOS window and the 15-day holdout can actually be populated. (2) AVG TRADE BELOW THE FEE FLOOR — faster bars alone would risk churning out sub-fee scalps, so I added a frozen 12-hour minimum hold that arms only the signal-based exits (normalization / crowd flip); the hard stop stays unconditional, so tail risk is unchanged while every non-stopped trade gets at least half a day for the positioning unwind to exceed the ~0.10% round trip. (3) UNROUNDED QUANTITY — position_size now floors the quantity to the venue lot step (10^-size_precision, default 3 dp = ETHUSDT USD-M step 0.001), formats it at exactly that precision, and re-verifies the $20 ETHUSDT minimum notional after rounding, so no order can be silently re-rounded or rejected. I have also stated the measured feed depth explicitly in the class docstring, since QA noted none was provided. One honest caveat, flagged rather than hidden: the ~131-day feed ceiling is a data-availability fact I cannot code around — this strategy can only ever be validated on the forward capture, and it will grow at one day per day.
Hypotheses
Negative-edge single-perp positioning fade — not worth 2 hours of optimization. profit_factor 0.797 (<1.0), avg_trade_return_pct -0.062% (negative, below the 0.15% USD-M fee floor), Sharpe -0.26 with CI [-1.20, 0.43] straddling zero, total_return -7.73%, expectancy -$111/trade over 71 trades. The globalLongShortAccountRatio feed is forward-capture-limited to ~131 days (un-backfillable; dev docstring concedes Binance serves ~30 days), so every trade sits in a single 2026 regime and there is no additional data for the optimizer to tune toward or for walk-forward/holdout to validate — the contrarian premise is falsified on the only window it can be measured on. This is the L73 single-perp supplementary-gated directional family (0 survivors), here outright loss-making rather than merely marginal. No parameter change conjures a positive edge from a negatively-predictive signal on a single-regime sample. Failure pattern: no_edge/fee_edge single-perp positioning-gated contrarian, negative per-trade edge on un-extendable single-regime feed (L73).
Implementation
Long-short contrarian fade of the Binance GLOBAL retail account long/short ratio on ETHUSDT.BINANCE USD-M, now clocked at 1-HOUR bars to match the feed's own cadence. The signal is unchanged: the rolling z-score of log(long/short account ratio) over the strategy's own 120-observation history, returned every bar in natural units. SHORT when the retail crowd is unusually long (z >= entry_z), LONG when unusually short (z <= -entry_z); exit when positioning normalizes (|z| <= exit_z) or the crowd flips to the opposite extreme, with a 4% hard stop (always live) and a 72-hour calendar time stop. A new 12-hour minimum hold gates only the signal-based exits so each trade has room to clear the ~0.10% round-trip taker cost; the stop is exempt. Position size is 50% of equity in notional, now floored to the ETHUSDT USD-M lot step (0.001) and re-checked against the $20 minimum notional before submission. If the positioning feed is missing or stale beyond 48h the z collapses to 0.0 and the strategy stays flat — never a price-only proxy.
Verification Results
Verification failed (Layer 4 — QA review) [class=not_measurable]:
- [edge_concern] The sandbox is negative (-7.73%, Sharpe -0.45 CI [-1.97, 0.67], PF 0.80, win_rate 0.28, avg_trade_return_pct -0.062% over 71 trades) but confined to a SINGLE ~4-month 2026 regime and cannot be generalized: the 2024/2025 stress windows show 0.0 because the signal feed doesn't exist then. So the loss isn't a decisive falsification, and a positive result on this window wouldn't be trustworthy either — the feed can't support a valid conclusion yet. A data-coverage verdict, not an edge one; the code is correct and should be revisited unchanged once the feed deepens.
- DATA TOO YOUNG / FORWARD-CAPTURE-ONLY. The sole signal is Binance globalLongShortAccountRatio (global_account_ratio), which the developer measured to span only 2026-03-23 to 2026-08-01 (~131 days) for ETHUSDT — Binance serves ~30 days of this endpoint, a forward live capture that CANNOT be backfilled. Of the 831-day sandbox the strategy is flat ~700 days and its 71 trades all fall in one ~4-month 2026 regime. A ~131-day single-regime window can't support a robust 3-window walk-forward + 15-day holdout or the deflated-Sharpe/PBO gates. No code change deepens the feed. Park until the capture accrues multiple years/regimes, then re-run the unchanged code; do not optimize on the 131-day window.
Backtest Review
Genuinely novel, orthogonal signal (global retail account L/S ratio) that avoids the OHLCV-only, liquidations, options, and cross-venue death traps
Backtest Review
Clean single-instrument/single-venue/single-feed construction; signal-only use of the feed (never PnL); bounded stop and time-stop for tail protection
Backtest Review
profit_factor 0.797 (<1.0) and avg_trade_return_pct -0.062% — the strategy has NEGATIVE per-trade edge, well below the 0.15% USD-M fee floor; fees are 10.5% of gross on a losing book
Backtest Review
All 71 trades fall in a single ~131-day 2026 window because the globalLongShortAccountRatio feed is forward-capture-limited and un-backfillable (dev docstring: Binance serves ~30 days) — no multi-regime data exists to optimize or validate against
Backtest Review
Negative headline metrics across the board: total_return -7.73%, Sharpe -0.26 (CI straddles 0), Sortino -0.13, information_ratio -0.97, win_rate 28%, expectancy -$111/trade
Backtest Review
L73 single-perp supplementary-gated directional family (0 survivors); this instance is not even marginal — it is loss-making on its only measurable window
Iteration History
Verification failed (Layer 2 — synthetic scenarios):
Parameters used: ['exit_z', 'entry_z', 'min_notional', 'min_ratio_obs', 'stop_loss_pct', 'target_weight', 'max_hold_hours', 'ratio_lookback', 'max_ratio_lag_s']
Check that __init__ sets all attributes from self.parameters.get().
- steady_uptrend: TypeError: EthGlobalRetailCrowdContrarianReversalLS._event_ts() takes 1 positional argument but 2 were given (bar timestamp: 1735690980000)
- steady_downtrend: TypeError: EthGlobalRetailCrowdContrarianReversalLS._event_ts() takes 1 positional argument but 2 were given (bar timestamp: 1735690980000)
- flat_ranging: TypeError: EthGlobalRetailCrowdContrarianReversalLS._event_ts() takes 1 positional argument but 2 were given (bar timestamp: 1735690980000)
- volatility_spike: TypeError: EthGlobalRetailCrowdContrarianReversalLS._event_ts() takes 1 positional argument but 2 were given (bar timestamp: 1735690980000)
- zero_volume: TypeError: EthGlobalRetailCrowdContrarianReversalLS._event_ts() takes 1 positional argument but 2 were given (bar timestamp: 1735690980000)
- price_gap: TypeError: EthGlobalRetailCrowdContrarianReversalLS._event_ts() takes 1 positional argument but 2 were given (bar timestamp: 1735690980000)
Iteration History
Verification failed (Layer 4 — QA review):
- TOO FEW TRADES TO VALIDATE, AND THE SIGNAL FEED LIKELY HAS A SHALLOW FORWARD-ONLY HISTORY. The sandbox produced only 14 trades over 363 days (~14/yr, 8 long / 6 short), multi-day holds (avg 2d 1h). At that turnover the pipeline cannot be populated: each of the 3 walk-forward OOS windows sees ~4-5 trades and the 15-day holdout expects <1 trade. Compounding it, the ONLY signal is Binance globalLongShortAccountRatio, which per Binance docs serves only the latest ~30 days and cannot be backfilled — so usable history is limited to the factory's forward capture (~1 year per data_days=363) and cannot grow into the past. Same forward-only ceiling that killed the liquidation line. No event study or stated feed depth was provided.
- SANDBOX EDGE NEGATIVE BUT INCONCLUSIVE ALONE: -3.72% total, Sharpe -0.568 (CI [-2.21,+1.00]), PF 0.574, win_rate 0.357, avg_trade_return_pct -0.395% (below fee floor) over 14 trades; long leg weak (0.125 on 8), short leg small-sample positive (0.67 on 6). With n=14 not a decisive falsification, but no positive evidence either, and combined with the measurability ceiling it does not justify a full backtest + optimization.
- position_size returns Decimal(str(notional/price)) without rounding to ETH size precision (4 dp); other strategies round. The sandbox executed fills so it was tolerated, but an unrounded quantity risks order-rejection/silent re-rounding depending on venue precision handling.
Iteration History
Verification failed (Layer 4 — QA review):
- STRUCTURALLY UNMEASURABLE — TRADE COUNT DID NOT MOVE, AND THE CAUSE IS A HARD DATA CEILING THE DEVELOPER ADMITS CANNOT BE CODED AROUND. Iteration 3's entire thesis was that re-clocking from 4H to 1H bars (plus entry_z 1.5->1.25 and max_hold 240h->72h) would raise turnover 'roughly an order of magnitude' — the docstring predicts ~3,000 signal-bearing bars and 'roughly an order of magnitude more entry opportunities.' The real-data sandbox delivered 19 trades, essentially unchanged from the previous 14. The prediction failed because trade count is not gated by the bar clock: it is gated by (a) the globalLongShortAccountRatio feed being forward-capture-only, ~131 days (2026-03-23 -> 2026-08-01), which the developer correctly states cannot be backfilled, and (b) crowding extremes at z>=1.25 being rare and then serialized by a 12h min-hold on top of a ~1.5-day average hold (avg_holding_period 1d 14h). 19 trades is far below the ~100-trade measurability floor and cannot populate the downstream pipeline — 3 walk-forward OOS windows + a 15-day holdout would each see a handful of trades, so any Sharpe/OOS number produced there is noise, not edge. The feed ceiling grows one day per day and cannot be accelerated, so no code change can reach a measurable sample.
- Performance over the tiny sample is deeply negative but statistically meaningless and must NOT be read as edge or anti-edge: total_return -7.30%, avg_trade_return_pct -0.65%, win_rate 0.26 over just 19 trades, with return_kurtosis 21.2, Sharpe -1.01 whose 95% CI straddles zero [-2.65, +0.63] and PSR 0.11. The long/short win-rate split (0.09 n=11 vs 0.50 n=8) is pure small-sample noise. No conclusion about the contrarian mechanism can be drawn from 19 trades.
Backtest and paper results are hypothetical. Trading involves risk of loss.