Skip to content

View translation

SmartMoneySpotRegimeAccumulationLong

Hypotheses

Multi-Major SPOT Regime Accumulation Gated by TOP-TRADER (Smart-Money) Positioning, Long-Only & Unlevered (BINANCE_SPOT, 4 Deep Majors, Daily Bars — Hold a Name Only While Its Perp's TOP-TRADER Long/Short Account Ratio Is Elevated, Rotate to CASH When Informed Traders De-Risk; Non-Price Positioning Feed, 2-Parameter)

Hypotheses

A LONG-ONLY, UNLEVERED (cash-account, no liquidation) regime-accumulation strategy across a diversified basket of 4 deep spot majors — BTCUSDT, ETHUSDT, SOLUSDT, BNBUSDT on BINANCE_SPOT — timed by a genuine NON-PRICE feed: the TOP-TRADER long/short ACCOUNT ratio from the Binance VISION 'metrics' files (count_toptrader_long_short_ratio column, MULTI-YEAR back to ~2020, NOT the 30-day API). The insight: Binance's top-account cohort is the informed/sophisticated side of the book, and their aggregate net-long conviction leads — accumulate a name on spot only while its perp top-trader ratio is elevated, rotate that sleeve to CASH when the smart-money cohort de-risks. This deliberately answers the two failure modes that dominate this session: (1) catastrophic drawdown — the strategy is UNLEVERED spot and rotates to cash on the smart-money exit signal, so it cannot be liquidated and DD is bounded far below the 50% floor (unlike the dollar-neutral spreads that hit 90%+ and my SOL taker trade that hit -100%); (2) L30 pure-OHLCV death — the gate is a committed-positioning series not derivable from price. It is distinct from every pending/failed item: EthRetail FADES the GLOBAL/retail ratio on a single ETH perp LONG-SHORT — this FOLLOWS the TOP-TRADER ratio on a 4-name SPOT basket LONG-ONLY (different column, opposite direction, different venue/structure); BtcSmartMoneyCrowd was a sparse two-part divergence (16 trades) — this is a responsive regime filter across 4 names for adequate sample. NOT funding (L13/L28), NOT options (L29), NOT a momentum sort (the signal is positioning, not price rank). Fills the under-represented BINANCE_SPOT venue (11.5% vs ≥15%) and multi-instrument scope. 2 parameters to resist the overfit that killed the spot momentum port.

Hypotheses

Iteration-5 scope fix for the QA critical (single-instrument config vs a 4-name hypothesis). QA's remedy (a) turned out to be available: src/backtesting/subprocess_entry._add_per_leg_top_trader_ratio + supp_collector.load_top_trader_ratio_series expose 'top_trader_ratio_by_instrument' -> {instrument_id: {ts_ns_str: ratio}} for every leg (spot legs mapped to their USDT perp, metrics mirrors present for all four symbols), so the per-NAME smart-money gate across the full basket IS deliverable to strategy code. The strategy now trades the exact instruments and venue the hypothesis declares, gating each leg by its own cohort, which also restores the diversification the hypothesis cites as its drawdown defense. The prior single-name re-scope, the price-trend overlay and any price fallback are all removed. Honest note: this premise has now been measured twice with opposite structures and lost both times, so I would not expect an edge -- but this is the first build that actually tests the hypothesis as written, so it deserves the measurement rather than another substitute.

Hypotheses

premise_falsified: on an adequate 162-trade / 6.5-year sample the top-trader (smart-money) positioning gate produces no separation vs simply holding the four majors — measured against the fair equal_weight_basket benchmark (benchmark_meaningful=true) it posts information_ratio -1.01 and negative alpha (-0.0219), i.e. it risk-adjusted-UNDERPERFORMS buy-and-hold. The gate's timing (rotating to cash when the cohort de-risks) actively subtracts value. Per-trade edge is negative and below the spot fee floor (avg_trade_return_pct -0.032% vs ~0.25% round-trip), so there is no positive gross edge for optimization to tune toward — the +34% headline is crypto beta carried with a 41% drawdown. QA's edge concern is borne out on full history. Not worth 2 hours of optimization.

Implementation

Long-only, unlevered BINANCE_SPOT basket of the four deep majors (BTCUSDT, ETHUSDT, SOLUSDT, BNBUSDT) on 1-DAY bars. Each name is held only while ITS OWN perp TOP-TRADER long/short account ratio (Binance smart-money cohort, multi-year VISION metrics mirror) sits in an elevated percentile of that name's trailing history; the sleeve rotates to cash when that cohort de-risks. Equal-weight targets (alloc_frac/4 of equity per active name), hysteresis on the percentile gate, and a churn band on rebalancing. No price/momentum input anywhere -- the sole driver is the non-price positioning feed; with no positioning data the book stands in cash.

Verification Results

Let the optimizer explore higher entry_level within the declared [0.30,0.90] bound; consider whether a stricter default better reflects 'elevated'.

Verification Results

entry_level default 0.55 (55th percentile of the name's own trailing top-trader ratio) is only marginally above median, whereas the hypothesis frames the gate as 'elevated' / smart-money conviction. Structurally correct (percentile gate + hysteresis) but the threshold barely restricts exposure at default params.

Verification Results

Confirm the base template honors the override; otherwise rename. No behavioral impact observed.

Verification Results

min_bars_required(self) overrides a framework method (static-analysis base_shadow warning). Returns 40, which is compatible with min_obs/ratio_window warm-up, so functionally fine.

Verification Results

Slow regime-accumulation book: sandbox avg_trade_return_pct is -0.032% against a ~0.20% spot round-trip, and the developer notes this positioning premise has been measured twice (opposite structures) and lost both times. The gate is barely-above-median (entry_level 0.55 percentile) rather than genuinely 'elevated', so risk-on much of the time and the top-trader signal may add little over just holding the basket (beta 0.157, information_ratio -1.04 vs equal-weight basket). Sample is adequate (162 trades over 6.5y) so it is measurable — but I'd first check on full history whether the top-trader percentile gate produces any separation vs buy-and-hold before committing optimization time.

Backtest Review

Genuine non-price feed (top-trader long/short account ratio), 2 parameters, low overfit surface

Backtest Review

Adequate, measurable sample (162 trades / 6.5y), unlevered spot so DD is bounded (41% < 50%) and no liquidation

Backtest Review

Point-in-time as-of lookups and per-leg gating are correctly wired to the 4-name basket

Backtest Review

The smart-money gate adds NO edge over simply holding the basket: benchmark is equal_weight_basket (benchmark_meaningful=true) yet information_ratio = -1.01 and alpha = -0.0219 (negative) — it risk-adjusted-underperforms buy-and-hold, confirming QA's edge concern on full history

Backtest Review

avg_trade_return_pct = -0.032% (negative, and below the ~0.25% BINANCE_SPOT round-trip floor) — no positive per-notional edge for optimization to lift

Backtest Review

Headline +34% return / 5.35% CAGR is pure crypto beta carried with a 41% drawdown, not an active edge

Backtest Review

This positioning premise has now lost across three independent structures (retail-fade, sparse divergence, this follow-the-top-trader basket)

Analysis

Backtest gate: - metrics unreliable: 4 trades / 3304 data days is too little evidence (need >=5 trades over >=10 days) — increase signal frequency or widen the window

Iteration History

Verification failed (Layer 4 — QA review): - Core-edge mismatch. The hypothesis is a PER-NAME top-trader gate ('Hold a Name Only While ITS Perp's TOP-TRADER Long/Short Account Ratio Is Elevated') — a cross-sectional strategy where each of 4 majors is held on its OWN top-trader ratio. The code reads only the PRIMARY (BTC) ratio and applies one shared percentile as a market-wide switch that holds/dumps ALL four names at once (single self._regime_on over self._all_iids). Developer discloses this as a supp-loader workaround, but the stated per-name mechanism is not implemented — it is a single-signal BTC market-timing overlay, a materially different strategy. - Code-defect signature: win_rate 0.0 and profit_factor 0.0 across ALL 12 trades, avg_trade_return_pct -19.5%, Sharpe -1.64, total_return -47.9%, max_drawdown 56.0%. Every entry in every regime cycle lost. For an unlevered long-only SPOT basket to lose ~48%, the 'follow smart money' gate is systematically buying tops and rotating to cash at bottoms — polarity/exit defect, not a fee-edge miss. - Only 12 trades over 362 days (~3 regime cycles x 4 names) — below the ~100-trade measurability floor. The developer's '~80-200 trades' estimate is contradicted by the run; metrics cannot distinguish edge from noise.

Iteration History

Verification failed (Layer 4 — QA review): - No fee-clearing edge on a measurable sample; the premise has failed twice. Sandbox: avg_trade_return_pct -0.96% (below the 0.25% spot floor), profit_factor 0.42, win_rate 0.22, total_return -11.2%, Sharpe -1.00 over 36 trades. Not the v1 0.0/PF-0.0 defect signature — a real but negative edge. The follow-top-trader premise showed anti-edge in v1 (-48%, 0% win) and still loses net in v2. Meets the developer's own abandon criterion. - The return-driving component has drifted to an OHLCV trend filter. The hypothesis edge is a per-name top-trader positioning gate; that signal alone was anti-edge in v1. v2's per-name selection is a price-SMA trend filter (OHLCV, L7 zero-survivor class), which now shapes returns while the top-trader ratio is only a BTC-only market switch — not the per-name positioning gate the hypothesis specifies. - Marginal measurability: 36 trades over 362 days — modest for a decisive edge read, though the negative expectancy is consistent enough to conclude against it.

Iteration History

Verification failed (Layer 4 — QA review): - No fee-clearing edge; the follow-top-trader premise is exhausted after two decisive, oppositely-constructed samples. Sandbox (unchanged from v2): avg_trade_return_pct -0.96% (below the 0.25% spot floor), PF 0.42, win_rate 0.22, total_return -11.2%, Sharpe -1.00 over 36 trades — a real but negative edge. v1 (pure positioning regime) lost ~48% at 0% win (following elevated positioning was anti-edge); v2 (regime + trend) still loses. Meets the abandon criterion the developer pre-registered in iteration 2 and now invokes. - The return-shaping component is a price-SMA (OHLCV, L7 zero-survivor) trend filter, not the hypothesis's stated per-name top-trader positioning gate, which remains a single BTC-only market switch. The stated edge is unimplementable here and was anti-edge where tested market-wide, so the passing v2 behavior does not test the hypothesis and does not clear fees.

Iteration History

Verification failed (Layer 4 — QA review) [class=hypothesis_mismatch]: - [edge_concern] Sandbox is a long-only spot-majors basket carried by beta: only 4 trades (metrics_reliable=false), information_ratio -0.9928 vs the equal-weight-basket benchmark (benchmark_meaningful=true), benchmark_correlation 0.028, end_unrealized_pct -3.17. Even setting the mechanism mismatch aside, this is the long-only unlevered majors-basket profile that has shown negative alpha vs its own benchmark repeatedly this session. Advisory only; it does not drive the fail. - [critical] The hypothesis's single defining, repeatedly-stated edge is a PER-NAME top-trader positioning gate: 'hold a name only while ITS perp's TOP-TRADER long/short account ratio is elevated', and it explicitly disavows price-based selection ('NOT a momentum sort ... the signal is positioning, not price rank'). The code does NOT implement this. Because the supp loader loads 'metrics' only for the primary symbol (developer-disclosed), the per-name top-trader ratio for ETH/SOL/BNB is never read. Instead the code substitutes (a) BTC's single top-trader ratio as one market-wide regime on/off switch (_ratio_asof -> percentile -> self._regime_on), and (b) a per-name PRICE-SMA trend filter (_name_uptrend: close > trailing SMA) to decide which of the 4 names to hold within a risk-on regime. The signal that actually discriminates one name from another is therefore price trend, i.e. exactly the price-momentum selection the hypothesis says it is NOT. The distinguishing per-name positioning edge is absent from the code. (line 336) — fix: Either extend the supplementary loader to provide the top_trader_account_long_short_ratio for every basket instrument (not just the primary) and gate each name on its OWN positioning percentile, or re-scope the hypothesis to a single-instrument BTC top-trader regime study. As coded, the per-name discrimination is a price/SMA trend overlay, which is a different mechanism from the one under test.

Iteration History

Verification failed (Layer 4 — QA review) [class=hypothesis_mismatch]: - [edge_concern] The developer reports the follow-top-trader-positioning premise has been measured twice with opposite structures and lost both times (pure regime ~-48% at 0% win rate; regime+trend ~-11%, PF 0.42, avg -0.96%/trade). The Layer-3 sandbox here is not informative on edge (1 equity-moving trade over a 2397-day span, metrics_reliable=false, Sharpe CI [0.0, 0.68], information_ratio -0.84 vs buy-hold). This is advisory for the analyst on any corrected/re-scoped build; it does not drive this verdict, which is about scope, not performance. - [critical] Instrument/scope mismatch with the hypothesis. The hypothesis is explicitly and repeatedly a MULTI-MAJOR basket: 'Multi-Major', '4 Deep Majors', 'across a diversified basket of 4 deep spot majors -- BTCUSDT, ETHUSDT, SOLUSDT, BNBUSDT on BINANCE_SPOT', holding/rotating each NAME by ITS OWN perp top-trader ratio. The diversified 4-name structure is not incidental -- the hypothesis cites it as a core defense against the catastrophic drawdown that killed prior single-name/spread attempts, and as filling the under-represented multi-instrument scope. The submitted config trades a SINGLE instrument: config.instrument_id='BTCUSDT.BINANCE_SPOT', extra_instruments=[], extra_bar_types=[]. Per the QA checklist (instrument(s) named MUST equal config.instrument_id/extra_instruments; multi-instrument scope must match), the code implements a materially narrower, different-risk-profile strategy than the hypothesis under test. The core positioning mechanism (top-trader account-ratio percentile gate) IS faithfully implemented for BTC, but on 1 of the 4 named legs, so the hypothesis as written is not being tested. (line 1) — fix: Either (a) implement the true 4-name basket with a PER-NAME top-trader gate -- which requires wiring the 'metrics'/top-trader series per leg in the backtest supplementary loader (mirroring funding_rates_by_instrument), since src/backtesting/supp_collector.py::_load_supp_with_per_leg_funding currently loads per-leg data for FUNDING ONLY and every other supp key, including metrics, comes from the primary instrument; or (b) recognize that until per-leg metrics loading exists, the hypothesis's core per-name gate across 4 names cannot be delivered to strategy code -- i.e. the FULL hypothesis is not - [warning] The code docstring and config.rationale acknowledge the mechanism has already failed twice and recommend abandonment, and the re-scope was chosen precisely because the correctly-scoped 4-name per-leg gate is infeasible in this framework. This is honest but underscores that the artifact in front of QA is a knowingly-substituted narrower strategy, not the hypothesis's design. (line 12) — fix: Route to the analyst/factory with the framework limitation (per-leg metrics not wired) as the actionable blocker; if per-leg metrics wiring is not planned, disposition the multi-major top-trader hypothesis as not_measurable rather than iterating single-name variants.
Strategy report

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