CrossSectionalMomentumLSBasketDaily
Hypotheses
Cross-Sectional Momentum, Dollar-Neutral Long-Short Basket on Binance USD-M Perps (Rank Alts by Intermediate-Horizon Relative Strength, Long Top / Short Bottom, Weekly Rebalance, Market-Neutral, Low-Parameter)
Hypotheses
A MARKET-NEUTRAL (dollar-neutral) LONG-SHORT cross-sectional momentum book on a basket of liquid Binance USD-M perpetuals. Each weekly rebalance it ranks the basket by intermediate-horizon relative strength and goes LONG the top-K strongest names and SHORT the bottom-K weakest names in equal notional, so the book carries ~zero net market beta. This is deliberately built to survive the failure mode that has killed the most strategies this session — recent-regime NON-GENERALIZATION (the HL impulse/breakout strategies were positive in-sample but collapsed on the held-out recent tail because they were net-long-beta directional bets). By construction a dollar-neutral cross-sectional book strips out BTC-beta and trades only the DISPERSION between winners and losers, which persists across bull, bear, and chop, so the held-out tail is not a single directional regime bet. It uses the factory's one repeatedly-validated edge family (momentum) in its most regime-robust form, on deep multi-year Binance USD-M history. It is NOT any landmine: NOT a funding/carry/cross-venue trade (those were just shown to be fee-and-basis-dominated and, for COIN-M, categorically unbacktestable), NOT a Deribit option (broken harness), NOT an HL short-window pure-OHLCV bet (data wall / non-generalization), NOT a small-TP/large-stop fade (inverted payoff). Crucially it captures LARGE cross-sectional dispersion (alts routinely diverge tens of percent over weeks via narrative rotation), which dwarfs the ~0.10% USD-M round-trip fee — the opposite of the ~0.02-0.10% funding spreads that lost to fees. It fills the under-weight long/short (14.8%) and multi-instrument (14.4%) buckets and is distinct from the existing AbsoluteMomentum (time-series sign) and CrossSectional7DayReversal (short-horizon reversal) siblings — this is intermediate-horizon relative-strength CONTINUATION. Tiny parameter count (lookback, K, rebalance period).
Hypotheses
Iteration 7 fix for the Layer-2 failure. I reproduced the reported error exactly (same bar timestamp 1735691640000) against the real StrategyVerifier harness and traced it to `self._bar_ts(bar)` resolving to the base class's @staticmethod: the Layer-2 proxy (strategy_verifier.py:119-126) walks dir(instance) and rebinds every callable with types.MethodType(); a staticmethod read off an instance is a plain function with no __func__, so the proxy binds it and injects `self`, producing 'FactoryStrategy._bar_ts() takes 1 positional argument but 2 were given'. previous_code's module-level free function only dodged the rebinder — it left self._bar_ts still pointing at the broken bound staticmethod, so any base-class path (_maybe_process_primary, which calls self._bar_ts at base_template.py:289/292) or stale call site re-triggers it. The fix is a minimal, surgical instance-method override `def _bar_ts(self, bar)` that delegates to the renamed module-level `_ts_ns()`: it carries __func__, so the proxy unwraps and rebinds it with correct arity, AND the real engine's internal self._bar_ts(bar) calls still work. I verified against the actual harness: Layer 1 static analysis passes with zero errors (imports untouched — no banned imports reintroduced), all 6 Layer-2 scenarios pass with no frozen-signal warning (the z-score signal remains continuous), and both the previously-crashing `proxy._instance._bar_ts(bar)` and `_maybe_process_primary()` now execute cleanly. Every other line — ranking, dollar-neutral sizing, skip-gap momentum, churn-suppressing resize, inert base hooks — is byte-identical to previous_code, so no earlier-passing layer regresses. Venue is Binance USD-M futures because the book goes short; leverage=2.0 is consumed in sizing (budget = equity * self._leverage, per_leg = budget/(2k)), giving 1x long + 1x short, so the leverage_set_but_unused gate is satisfied. Weekly rebalance on daily bars matches the intermediate-horizon hypothesis, and cross-sectional alt dispersion over week-long holds is tens of percent — far above the ~0.10% USD-M round-trip taker cost.
Hypotheses
max_iterations_after_review
Implementation
Dollar-neutral cross-sectional momentum book on 12 liquid Binance USD-M perpetuals, rebalanced weekly on daily bars. Ranks the basket by a skip-gapped intermediate-horizon return (30-bar lookback, skipping the most recent 3 bars to strip short-term-reversal contamination), then goes LONG the top-3 strongest and SHORT the bottom-3 weakest names in equal notional. With leverage=2.0 the gross book is 2x equity, split into a 1x long half and a 1x short half, so net market beta is ~zero and only winners-minus-losers dispersion is harvested. Legs are rebalanced directly from calculate_signal via per-instrument orders; a side flip closes then reopens, while a same-side leg is only resized on a material (>=25% of target notional) delta to suppress fee churn. Three tunables: lookback, top_k, rebalance_days.
Verification Results
Verification failed (Layer 2 — synthetic scenarios):
Parameters used: ['gap', 'top_k', 'assets', 'lookback', 'resize_frac', 'min_notional', 'rebalance_days']
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: 1735691640000)
- steady_downtrend: TypeError: FactoryStrategy._bar_ts() takes 1 positional argument but 2 were given (bar timestamp: 1735691640000)
- flat_ranging: TypeError: FactoryStrategy._bar_ts() takes 1 positional argument but 2 were given (bar timestamp: 1735691640000)
- volatility_spike: TypeError: FactoryStrategy._bar_ts() takes 1 positional argument but 2 were given (bar timestamp: 1735691640000)
- zero_volume: TypeError: FactoryStrategy._bar_ts() takes 1 positional argument but 2 were given (bar timestamp: 1735691640000)
- price_gap: TypeError: FactoryStrategy._bar_ts() takes 1 positional argument but 2 were given (bar timestamp: 1735691640000)
Backtest Review
The market-neutrality claim IS satisfied: beta 0.0266, benchmark_correlation 0.036, and benchmark_meaningful correctly set to false. The buy-hold comparison is properly ignored.
Backtest Review
The trade population is genuinely cross-sectional and well-distributed: 692 trades (328 LONG / 364 SHORT) spread across all 12 basket names (BTC 47 to LINK 65) and all 7 calendar years (2020: 30, 2021: 129, 2022: 121, 2023: 108, 2024: 117, 2025: 118, 2026: 69). No data-coverage truncation, no dead instrument.
Backtest Review
The skip-gap (drop the most recent 3 bars) is a correct and thoughtful de-contamination of short-term reversal from an intermediate-horizon continuation signal.
Backtest Review
The account never liquidated: equity runs 100,000 -> 421,396 and never falls below 84,164.64.
Backtest Review
Commission drag is modest in relative terms (commission_pct_of_gross 1.54%) — fees alone are not what kills this.
Backtest Review
BLOCKING — the book is neither dollar-neutral nor exposure-capped. With top_k=3 and leverage=1.0, `per_leg = equity/(2k) = equity/6` implies every leg should report engine leverage (notional/equity_at_entry) of ~0.167 and gross exposure of 1.0x. Observed across 692 trades: min 0.33, MEDIAN 0.79, MAX 58.67. The median leg is ~4.7x target; the worst is ~350x. avg_position_pct is 195.86%. A single leg at 58.67x equity is not a dollar-neutral basket. I have NOT traced the cause and will not guess.
Backtest Review
BLOCKING — every risk statistic in this report is uninterpretable. compute_daily_returns() (metrics.py:179) groups realized PnL by trade CLOSE date, and legs are held for weeks (DOGE 2024-10-23 -> 2024-12-11, 49d; SOL 2022-10-26 -> 2022-12-21, 56d). So daily_returns['2024-12-18'] = +3096.15%, ['2024-09-25'] = -297.14%, ['2024-04-03'] = -197.04%. A daily loss worse than -100% is not a return. Everything derived from that series is meaningless: annualized_volatility 1095.67%, return_skew 42.76, return_kurtosis 1912.80, sharpe_ratio 0.43 (sharpe_ci_low -0.0416, straddling zero), sortino 2.98, probabilistic_sharpe 0.9977.
Backtest Review
The long stretches of exactly 0.0 (2023-07-26 -> 2023-12-06; 2024-04-10 -> 2024-09-18) and rolling_sharpe frozen at 0.9530 for 14 consecutive readings are the same artifact, NOT a dead strategy — 108 trades fired in 2023 and 117 in 2024. They are weeks in which no leg closed.
Backtest Review
Degenerate outputs: cagr -100.0, calmar_ratio -1.0, recovery_factor -1.0, max_drawdown_ci_high 509.6% — while the equity curve ends at 4.2x its start and never approaches zero. Symptom reported; metrics path not diagnosed beyond compute_daily_returns.
Backtest Review
ESSENTIALLY NO EDGE, even with the oversized book: profit_factor 1.023 across 692 trades, avg_win $15,728 vs avg_loss $13,773, expectancy $167/trade against $79,284 of commissions.
Backtest Review
impact_cost_pct 23.05% (total_impact_usd $34,697) — modeled market impact consumes about a quarter of gross PnL — and capacity_usd is only $1,882,946. The edge exists only at toy scale, and that capacity figure is itself inflated by the oversized legs.
Backtest Review
end_unrealized_pct 205.53 against a +321.4% total_return: roughly 206 points of the headline is an open position marked to market on the final bar and never closed. Realized is ~116%.
Backtest Review
THE HYPOTHESIS'S CENTRAL CLAIM IS FALSIFIED. It argues dispersion 'persists across bull, bear, and chop.' Annual returns: 2021 +338.3%, 2022 -50.4%, 2023 -61.4%, 2024 -46.8%, 2025 +369.3%, 2026 +14.1%. Three consecutive losing years bracketed by two explosive dispersion waves (2021 alt season, 2025 rotation), with max_drawdown_duration_days 1645 (~4.5 years). That is regime-dependence, not regime-robustness.
Backtest Review
entry_diag reports entry_signaled 0 / entries_submitted 0 against 692 real trades, because rebalancing bypasses the base hooks. A legal pattern, but the harness's entry diagnostics are blind to this strategy.
Analysis
Do NOT optimize — the current run measures a 6x-levered accident, not the cross-sectional momentum edge. The ranking logic and the 12-asset dollar-neutral construction are correct and worth keeping; the sizing is broken. (1) FIX THE SIZING. Intended per-leg is equity*leverage/(2*top_k) = 0.167x; observed median is 0.79x with a max of 53.38x and ALL 599 measurable legs above target. Add a hard in-strategy invariant asserted at every rebalance: sum(|leg_notional|) <= equity*leverage*1.05, and each leg <= equity*leverage/(2*top_k)*1.05 — log and skip on violation. Do not rely on the optimizer to discover this; the base template's guardrails are bypassed (entry_diag shows entry_signaled=0), so nothing is checking you. (2) MAKE THE REBALANCE STATE-CORRECT. _rebalance_asset reads cache.positions_open() and then submits both exits and entries on the same bar, but market orders do not fill until the next bar — so cur_qty reflects a book state that never existed and exposure ratchets every week. Either (a) flatten everything, then open fresh targets on the NEXT bar (one-bar lag, simple, honest), or (b) net against pending orders as well as filled positions. Also verify that _submit_entry_instrument nets into an existing same-side position rather than opening a second one — if it opens a second, the delta re-adds forever, which matches the monotone growth to 53x. (3) DELETE the blanket `except Exception: continue` in _rebalance — it silently swallows per-asset failures and leaves stale legs. Fix float(pos.quantity) -> pos.quantity.as_double(). (4) RE-RUN AND VERIFY BEFORE RESUBMITTING: exposure_pct ~100% (not 602%); avg_position_pct ~100% (not 171%); max per-leg leverage <= 0.20x; cagr/calmar_ratio/recovery_factor finite and consistent with total_return (they currently read -100.0/-1.0/-1.0 while total_return is +308% and equity never drops below $84,164); max_drawdown_ci_high < 100%; total funding small relative to gross PnL (it is currently -$209,468, a neutrality failure in its own right); impact_cost_pct < 10% and capacity_usd > $10M. Only after the book actually runs at its stated 1.0x gross is a 225-trial optimization worth the compute. Full detail: workspace/discussions/6f05ec86-758d-4ae7-906b-299ea198b811/iteration_7_feedback.md
Outcome Summary
CrossSectionalMomentumLSBasketDaily was explicitly designed to dodge the session's dominant failure mode — recent-regime non-generalization from net-long directional bets — by stripping out BTC beta and trading only winners-minus-losers dispersion. The neutrality worked (beta 0.0266, benchmark_correlation 0.036), and the trade population was genuinely broad and well-distributed, but the book itself was broken: legs ran up to 58.67x equity against a 0.167x target, and every derived risk statistic was corrupted by a metrics artifact that recorded daily returns of +3096% and -297%. Worse, the hypothesis's central claim was falsified by its own annual returns — +338.3% in 2021, then three consecutive losing years (-50.4%, -61.4%, -46.8%), then +369.3% in 2025 — which is regime dependence, not the promised bull/bear/chop robustness, and profit_factor of 1.023 showed essentially no edge even with the oversized book. Seven iterations failed to resolve the blocking sizing and metrics issues, and it was abandoned at the pre-optimization gate.
Outcome Summary
A dollar-neutral construction is only as good as its leg sizing, and a metrics pipeline that buckets multi-week realized PnL into single days makes Sharpe, volatility, skew, and CAGR meaningless — verify both before reading any risk number as evidence.
Outcome Summary
The backtest-review gate returned `iterate` on two blocking findings — leg sizing was neither dollar-neutral nor exposure-capped (median leg leverage 0.79 vs a 0.167 target, max 58.67, avg_position_pct 195.86%), and every risk statistic was uninterpretable because compute_daily_returns() groups realized PnL by trade close date while legs are held for weeks. After 7 iterations it was abandoned with reason `max_iterations_after_review`, never reaching optimization or the post-optimization analyst.
Outcome Summary
Rank a basket of 12 liquid Binance USD-M perps by skip-gapped intermediate-horizon relative strength each week, going long the top-3 and short the bottom-3 in equal notional to harvest cross-sectional dispersion with ~zero net market beta.
Outcome Summary
It produced 692 trades (328 long / 364 short) across all 12 names and all 7 calendar years, with total_return +321.4% and beta 0.0266 — but profit_factor was only 1.023, expectancy $167/trade against $79,284 of commissions, impact_cost_pct 23.05%, capacity_usd just $1.88M, and roughly 206 of the 321 return points were an unclosed open position marked to market on the final bar.
Iteration History
Verification failed (Layer 2 — synthetic scenarios):
Parameters used: ['gap', 'top_k', 'assets', 'lookback', 'resize_frac', 'min_notional', 'rebalance_days']
Check that __init__ sets all attributes from self.parameters.get().
- steady_uptrend: TypeError: CrossSectionalMomentumLSBasketDaily._bar_ts() takes 1 positional argument but 2 were given (bar timestamp: 1735691640000)
- steady_downtrend: TypeError: CrossSectionalMomentumLSBasketDaily._bar_ts() takes 1 positional argument but 2 were given (bar timestamp: 1735691640000)
- flat_ranging: TypeError: CrossSectionalMomentumLSBasketDaily._bar_ts() takes 1 positional argument but 2 were given (bar timestamp: 1735691640000)
- volatility_spike: TypeError: CrossSectionalMomentumLSBasketDaily._bar_ts() takes 1 positional argument but 2 were given (bar timestamp: 1735691640000)
- zero_volume: TypeError: CrossSectionalMomentumLSBasketDaily._bar_ts() takes 1 positional argument but 2 were given (bar timestamp: 1735691640000)
- price_gap: TypeError: CrossSectionalMomentumLSBasketDaily._bar_ts() takes 1 positional argument but 2 were given (bar timestamp: 1735691640000)
Backtest and paper results are hypothetical. Trading involves risk of loss.