Strategies
High-Volatility-Quintile 6-Month Momentum with Jegadeesh-Titman Overlapping Cohorts, Long-Short, Point-in-Time Top-60 Binance USD-M Perp Universe (DAILY bars, monthly cohort formation, 6-month cohort hold)
Outcome: Abandoned
HighVolQuintileMomentumJTCohortsLSDaily
Outcome Summary
HighVolQuintileMomentumJTCohortsLSDaily adapted QuantConnect Strategy Library #155 to crypto perps. It bet that momentum is concentrated in the highest-volatility names, trading them long-short in overlapping 6-month monthly cohorts across a point-in-time top-60 Binance USD-M universe. Across 3 iterations the code never cleared Layer 3 verification: every sandbox smoke test ran past the 300s wall-clock limit on the ~20,000-bar daily window. The run was abandoned in a verification loop with no backtest, optimization or analyst verdict, so the hypothesis itself was never tested.
Hypothesis
Restated from first principles for crypto perps, not ported line by line, from QuantConnect Strategy Library #155 'Momentum and Reversal Combined with Volatility Effect in Stocks'. Kept from the source: momentum is concentrated in the highest-volatility names. Each month, rank a point-in-time top-60 universe of Binance USD-M perps by 30-day dollar volume. Keep the top vol quintile (12 names), using realized vol over days t-187..t-7 (the last week is skipped, as in the source). Rank those 12 by 180-day return. Go long the top 3 and short the bottom 3. Each monthly cohort gets 1/6 of gross, is held 6 months, and up to 6 cohorts overlap (Jegadeesh-Titman style). Book gross is 1.0x. Positions change only at month boundaries, and expected time-in-market is ~90% once all cohorts are live. The long-only half is pre-registered as a separately scored variant 2. The full text is in the outbox file.
Iteration 3 fixes the Layer-3 sandbox timeout. (1) Per-leg history moved from deques to plain lists with amortised chunk trimming. The old code sliced a deque (closes[a:b]), which raises TypeError at every rebalance attempt, and it ran bisect over deque indexing (O(n) in the middle). Lists make both O(1)/O(log n). (2) The instrument set is cut to 40 liquid, currently listed majors, all confirmed in the catalog with 1-DAY bars. That is ~96k sandbox bars instead of ~144k+ for a 60-leg book, and per-bar engine cost is the (c) per-span cost from L155. The top quintile of 40 is 8 names, so long 3 / short 3 is preserved. universe_size=60 can be restored when data and wall time allow. Signal logic, cohort math, the calendar-anchored scalar state, the L139 cutoff alignment rule (only bars with ts <= month-start cutoff, strictly older than the current primary bar) and 1.0x gross sizing are unchanged. Max gross = 1.0x equity, far under the 20x cap. Futures venue because the book shorts.
verification_loop: sandbox_timeout: Verification failed (Layer 3 — sandbox backtest): smoke test exceeded the 300s wall-clock limit on a ~20000-bar window (2400 days of BTCUSDT.BINANCE-1-DAY-LAST-EXTERNAL). This almost always means per-bar work that scales with history — e.g. rescanning the full funding/supplementary series, or rebuilding a list and calling min()/sorted() inside calculate_signal()/on_bar() on every bar. Precompute sorted timestamp arrays ONCE in __init__ and use bisect, or cache lookups keyed by timestamp, so per-bar cost is O(log n) not O(n).
Implementation
Each calendar month, rank a point-in-time universe of liquid Binance USD-M perps (candidate list of 40) by 30-day dollar volume. Keep the top vol quintile, using realized vol over days t-187..t-7. Rank that bucket by 180-day return: long the top 3, short the bottom 3. Each monthly cohort carries 1/6 of 1.0x gross and is held 6 months, with up to 6 cohorts overlapping (Jegadeesh-Titman). The book is netted per name and traded only at month boundaries. Daily bars.
Verification Results
sandbox_timeout: Verification failed (Layer 3 — sandbox backtest): smoke test exceeded the 300s wall-clock limit on a ~20000-bar window (2400 days of BTCUSDT.BINANCE-1-DAY-LAST-EXTERNAL). This almost always means per-bar work that scales with history — e.g. rescanning the full funding/supplementary series, or rebuilding a list and calling min()/sorted() inside calculate_signal()/on_bar() on every bar. Precompute sorted timestamp arrays ONCE in __init__ and use bisect, or cache lookups keyed by timestamp, so per-bar cost is O(log n) not O(n).
Iteration History
Verification failed (Layer 1 — static analysis): - Syntax error: invalid decimal literal (<unknown>, line 1) (line 1)
Outcome Summary
In multi-leg universe strategies with long lookbacks, precompute or cache cohort and ranking state and only recompute at month boundaries, so per-bar cost stays O(1) or O(log n) and the smoke test fits within the 300s sandbox limit.
After 3 iterations it was abandoned in a verification loop. The Layer 3 sandbox backtest went past the 300s wall-clock limit on a ~20,000-bar window (2,400 days of BTCUSDT.BINANCE 1-day bars), which points to per-bar work that grows with history length. Backtest review, analyst and risk stages never ran.
A long-short crypto adaptation of volatility-conditioned momentum: each month, take the highest-volatility quintile of a point-in-time top-60 Binance USD-M perp universe (ranked by 30-day dollar volume), rank those names by 180-day return, then go long the top 3 and short the bottom 3 in overlapping Jegadeesh-Titman monthly cohorts, each held 6 months at 1/6 of a 1.0x gross book.
There are no performance numbers: the strategy never finished verification, so no backtest report, optimization report, return, Sharpe or trade count exists.
Backtest and paper results are hypothetical. Trading involves risk of loss.