Skip to content

View original

RetailCrowdingContrarianReversalLS

Hypotheses

Retail-Crowding Contrarian Reversal, Long-Short (3-Asset Retail-Heavy USD-M Basket DOGE/XRP/SOL, 4h Bars + GLOBAL Long/Short ACCOUNT-Ratio Feed, Fade the Crowd ONLY at Statistical Positioning Extremes — Short When Retail Is Maximally Net-Long / Buy When Retail Is Maximally Net-Short, Revert-to-Mean Exit, 3-Parameter)

Hypotheses

A LONG-SHORT, multi-instrument contrarian on three high-retail-participation Binance USD-M perps (DOGEUSDT, XRPUSDT, SOLUSDT) on 4h bars, driven by the GLOBAL long/short ACCOUNT ratio (the count-based retail-positioning proxy in the Binance Vision metrics CSV — count_long_short_ratio — which has MULTI-YEAR history, unlike the API-only top-trader feed that left the prior 'Informed-Positioning' basket dormant after 2021). The edge is behavioral and structural, not a price prediction: the retail account crowd is systematically wrong at extremes — when the overwhelming majority of retail accounts are net-long a name, the marginal buyer is exhausted and forward returns are weak; when retail is maximally net-short, downside fuel is spent and bounces follow. Critically this is the CONTRARIAN reading of retail (fade the crowd), NOT the trend-following read of informed/large accounts that already failed. Deliberately 3-parameter (z_lookback, entry_z, atr_stop_mult) to resist the overfit deaths, and a 3-name basket dilutes single-symbol curve-fitting and lifts trade count for statistical reliability.

Hypotheses

Iteration 4 fixes the Layer-4 QA failure (instrument-set mismatch + single-name measurability) by turning the strategy into the genuine 3-asset basket the hypothesis mandates: extra_instruments now carries XRPUSDT.BINANCE and SOLUSDT.BINANCE, on_extra_bar is overridden, and both extra legs are actually traded with full position/exit/sizing handling. This restores the diversification and ~3x trade count (roughly 300 trades vs the prior 100) that the hypothesis names as its core anti-overfit / sample-size mechanism, addressing the QA note that the Sharpe CI straddled zero on a single name. Data constraint handled honestly: I verified against src/backtesting/supp_collector.py and by running load_for_subprocess that the backtest pipeline loads the L/S account ratio ONLY for the primary leg (extras receive funding only), so a strict per-leg-ratio basket would leave XRP/SOL dataless and untraded (a fake basket). Instead the basket shares the primary DOGE global account ratio — DOGE being the most retail-dominated of the three, a broad retail-sentiment thermometer — which stays within the SAME L/S-account-ratio contrarian mechanism (NOT a switch to a price-only proxy), while each leg's execution (entry timing per shared z, but independent ATR stop / revert exit / per-leg price and sizing) is fully separate. The z-score, entry, exit, and sizing math is byte-for-byte the logic that already passed Layer 3 for DOGE (100 trades, refactored into shared helpers _zscore_for_bars/_atr_of/_size_for), so DOGE behavior is preserved and the extra legs behave identically. Layer-2 safety: extra-leg orders route through the base _submit_entry_instrument, which early-returns when the mock cache yields no instrument, so the added on_extra_bar path cannot crash the synthetic proxy — verified locally that Layer 1 (static) and all six Layer 2 scenarios pass. Imports unchanged (no banned additions); the ratio parser remains a local closure to avoid the proxy static-binding trap. Leverage is referenced in _size_for (max_size = equity*leverage/price) so it is not set-but-unused.

Hypotheses

Non-significant risk-adjusted edge plus crash-day-dependent fat tails. Sharpe is only 0.285 with a 95% CI of [-0.326, 0.916] that straddles zero, so the edge cannot be distinguished from noise and optimization of three params cannot lift it toward a promotable ~1.5. The +1814% total return is a fat-tailed artifact (kurtosis 15.5, skew 1.18) carried by ~6 extreme single days — +80.8% on the 2022-11-01 FTX collapse, +40.3%, +37.5%, +32.9%, +30.2%, +30.0% — i.e. a few lucky contrarian crash shorts, not a smooth retail-fade edge. Critically, the code note admits the backtest supp pipeline delivers the L/S account ratio only for the primary leg, so XRP and SOL trade on DOGE's crowd z-score rather than their own; the hypothesis's central diversification premise (three independent retail-positioning signals) is therefore not realized — it's one signal on three correlated majors, which is why variance is huge and Sharpe collapses. That defect is an engine data-delivery constraint the developer cannot fix, so iterating won't help. Compounded by max_drawdown 40.4% (CI to 98.4%), turnover 784x, impact 14.6% of gross, and capacity only $4.67M. avg_trade_return_pct 0.716% clears the fee floor, so this is a risk-quality/edge-significance abandon, not a fee-edge death.

Implementation

Long-short contrarian reversal on a 3-asset retail-heavy Binance USD-M basket (DOGEUSDT primary + XRPUSDT, SOLUSDT extras, all 4h bars). The signal is a rolling z-score of the log GLOBAL long/short ACCOUNT ratio (count-based retail-positioning proxy from the Binance Vision metrics/global_account_ratio feed). Contrarian mapping fades the crowd at extremes: z >= +entry_z (retail maximally net-long) -> short; z <= -entry_z (retail maximally net-short) -> long. Each of the three legs is entered/exited independently — its own ATR stop, revert-to-mean exit (z crosses back through 0 for the held side), and risk-based sizing (risk_frac of equity over the ATR stop distance, capped at leveraged equity notional). DOGE trades through the base primary flow; XRP and SOL are managed in on_extra_bar via _submit_entry_instrument / _submit_exit_position.

Verification Results

Verification failed (Layer 4 — QA review): - Instrument-set mismatch: the hypothesis is explicitly a 3-asset basket (DOGEUSDT, XRPUSDT, SOLUSDT) and states the basket IS the core anti-overfit / trade-count mechanism ('a 3-name basket dilutes single-symbol curve-fitting and lifts trade count for statistical reliability'). The delivered code is single-name DOGE only: config.instrument_id=DOGEUSDT.BINANCE, extra_instruments=[], the class docstring says 'single-name', and there is no multi-instrument handling (on_extra_bar not overridden). Two of the three named instruments (XRP, SOL) are absent, so the code does not implement the hypothesis it is filed under, and the diversification/sample-size the hypothesis relies on is gone. - Sandbox Sharpe 1.05 CI is [-0.57, 2.66] (straddles zero) on 100 trades, and the result leans on the short leg (short_win_rate 0.596 vs long_win_rate 0.417) over a single 363-day window. Dropping the basket to one name leaves the edge at the low end of measurability.

Verification Results

Decide whether single-name DOGE satisfies intent; if a true basket is required it needs per-leg L/S supp. If single-name accepted, weight OOS/holdout heavily.

Verification Results

UNIVERSE REDUCED FROM 3-ASSET BASKET TO SINGLE-NAME DOGE (analyst/PM to rule). The hypothesis is explicitly a 3-asset basket (DOGE/XRP/SOL) relying on the basket to dilute single-symbol curve-fitting and lift trade count; config is single-instrument DOGEUSDT. Developer discloses the framework constraint (L/S supp feed injected for the primary only) and correctly declined a cross-name retail proxy as signal-inappropriate. DOGE is a named asset and the mechanism is identical, so not a critical wrong-asset mismatch — but it removes the overfitting-resistance and trade-count reliability the hypothesis was buying.

Verification Results

Send to optimization/holdout; check stability with largest winners excluded and confirm out-of-sample.

Verification Results

Positive sandbox is thin/fat-tail-driven: +36% / Sharpe 1.02 but CI [-0.58, 2.64] spans zero, largest_win $11,287 vs avg_win $2,096 (~5x), skew +0.53, only 100 trades. Encouragingly NOT the dead inverted-RR pattern (avg_win $2,096 > avg_loss $1,447, win 0.51) and a genuine non-price retail feed, so the edge is plausible but needs OOS confirmation.

Verification Results

Verify the loaded long_short_ratio maps to count_long_short_ratio (global accounts), not top-trader/taker; select the column explicitly if ambiguous.

Verification Results

Confirm the ratio field is the intended RETAIL proxy. Code reads long_short_ratio/longShortRatio, but the metrics CSV has count_long_short_ratio (global accounts=retail), top-trader ratios, and taker-volume ratio. The contrarian edge is specifically the count-based GLOBAL ACCOUNT ratio; fading top-trader/taker would be a different, possibly opposite signal.

Backtest Review

avg_trade_return_pct 0.716% is above the futures fee floor; 1695 trades is a decisive sample

Backtest Review

Positive in 5 of 5 full years (2022 +82%, 2023 +22%, 2024 +74%, 2025 +209%, 2026 +76% YTD) — not strictly single-regime

Backtest Review

benchmark_meaningful=false and beta ~0 — genuinely market-neutral construction (do not penalize vs buy-hold)

Backtest Review

Sharpe 0.285 with 95% CI [-0.326, 0.916] straddling zero — risk-adjusted edge not distinguishable from zero; cannot be tuned to a promotable ~1.5

Backtest Review

The +1814% return is a fat-tailed artifact (kurtosis 15.5) driven by ~6 crash-period single days including +80.8% on the FTX collapse — lumpy, not a consistent edge

Backtest Review

Structural gap: supp pipeline delivers the L/S ratio only for the primary leg, so all 3 legs trade DOGE's crowd z-score — the hypothesis's 3-independent-signal diversification is not realized (and is an engine constraint the developer can't fix)

Backtest Review

max_drawdown 40.4% (CI high 98.4%), Sortino 0.345, turnover 784x, impact 14.6% of gross, capacity only $4.67M — fee/impact-fragile, small-scale, high tail risk

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: The hypothesis (title + body) defines a LONG-SHORT 3-asset basket over DOGEUSDT/XRPUSDT/SOLUSDT whose stated purpose is to dilute single-symbol curve-fitting and lift trade count, but config.extra_instruments and extra_bar_types are both empty (only DOGEUSDT.BINANCE) and the code implements a single-name strategy (single _ts_arr/_ratio_arr, single self.instrument_id lookups, no on_extra_bar/basket logic, docstring says 'single-name'). The strategy's own rationale field concedes the DOGE/XRP/SOL basket was abandoned as 'infeasible' due to a supplementary-feed framework limitation, so the shipped strategy is a single-name reversal rather than the 3-asset long-short basket the hypothesis claims.

Outcome Summary

RetailCrowdingContrarianReversalLS tried to fade the retail crowd across a DOGE/XRP/SOL basket, going contrarian at extremes of the global long/short account ratio in a deliberately 3-parameter, market-neutral design. It posted an eye-catching +1814% over 1,695 trades and was positive every full year, but its Sharpe was only 0.285 with a confidence interval spanning zero, and the profit was a fat-tailed artifact driven by roughly six extreme crash days (notably +80.8% during the FTX collapse) rather than a consistent edge. Compounding the problem, the backtest's supplementary pipeline delivered the account ratio only for the primary leg, so XRP and SOL actually traded on DOGE's z-score and the central diversification premise was never realized — an engine constraint the developer couldn't fix. The analyst abandoned it at the backtest-review gate as a risk-quality/edge-significance failure, and it never reached optimization, risk review, or paper trading.

Outcome Summary

A huge headline return can be a fat-tailed illusion — check whether the edge is statistically significant (Sharpe CI clear of zero) and not carried by a few crash days, and verify that a multi-asset diversification premise is actually realized rather than defeated by a data-delivery constraint that routes every leg off one shared signal.

Outcome Summary

It was abandoned at the pre-optimization backtest-review gate because the risk-adjusted edge was not distinguishable from zero (Sharpe CI crossing zero) and the returns depended on a handful of lucky crash-day shorts rather than a smooth retail-fade edge; optimization was skipped as the three parameters could not lift a non-significant Sharpe toward a promotable ~1.5.

Outcome Summary

A market-neutral, long-short contrarian on a retail-heavy 3-asset Binance USD-M basket (DOGE/XRP/SOL, 4h bars) that faded the crowd at statistical extremes of the global long/short account ratio — shorting when retail was maximally net-long and buying when maximally net-short, exiting on mean-reversion or an ATR stop, with just three tuned parameters.

Outcome Summary

Over a decisive 1,695-trade sample it returned +1814.7% and was positive in all five full years, but risk-adjusted quality was poor: Sharpe 0.285 with a 95% CI of [-0.326, 0.916] straddling zero, Sortino 0.345, profit factor 1.35, 46.2% win rate, and 40.4% max drawdown. The return was a fat-tailed artifact (kurtosis 15.5) carried by ~6 extreme single days including +80.8% on the 2022 FTX collapse, alongside 784x turnover, 14.6% impact cost, and only ~$4.67M capacity.

Iteration History

Verification failed (Layer 2 — synthetic scenarios): Parameters used: ['entry_z', 'risk_frac', 'atr_period', 'z_lookback', 'min_notional', 'atr_stop_mult', 'min_ratio_pts'] Check that __init__ sets all attributes from self.parameters.get(). - steady_uptrend: TypeError: RetailCrowdingContrarianReversalLS._extract() takes 1 positional argument but 2 were given (bar timestamp: 1735692540000) - steady_downtrend: TypeError: RetailCrowdingContrarianReversalLS._extract() takes 1 positional argument but 2 were given (bar timestamp: 1735692540000) - flat_ranging: TypeError: RetailCrowdingContrarianReversalLS._extract() takes 1 positional argument but 2 were given (bar timestamp: 1735692540000) - volatility_spike: TypeError: RetailCrowdingContrarianReversalLS._extract() takes 1 positional argument but 2 were given (bar timestamp: 1735692540000) - zero_volume: TypeError: RetailCrowdingContrarianReversalLS._extract() takes 1 positional argument but 2 were given (bar timestamp: 1735692540000) - price_gap: TypeError: RetailCrowdingContrarianReversalLS._extract() takes 1 positional argument but 2 were given (bar timestamp: 1735692540000)
Strategy report

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