5  Strategy Catalog

A comprehensive, self-contained reference covering every registered strategy in the platform — the downstream companion to the Factor Catalog. Where that chapter documents factors (measured, predictive characteristics of an instrument), this chapter documents strategies: the portfolio-construction mechanics that trade them, organized by the factor family they draw on.

Scope note — strategies, not factors. Per the platform’s canonical model (see Factor & Strategy Lifecycle), a strategy is a (factor_id, mechanic, params) triple: it always names exactly one underlying factor, plus a mechanic — the reusable selection/weighting algorithm that turns the factor’s value into positions (e.g. rank the cross-section and go long/short the extremes, or just follow each instrument’s own sign) — plus the sizing/universe/rebalance parameters around it. A strategy cannot exist without a factor beneath it; the dependency runs factor → strategy, never the reverse. Strategy promotion (incubating → paper → live, F-054) additionally requires the underlying factor’s ops.factor status to already be validated.

5.1 Provenance

  • Config fields (factor_id, mechanic, params, universe, benchmark, promotion gates, enabled_in_nightly / research_day_backtest) are pulled directly from config/strategies/*.yaml in SBFoundation as of 2026-08-05 — eight strategies, all kind: factor (every registered strategy today is factor-driven; no other strategy kind exists yet).
  • Empirical fields (backtest CAGR/Sharpe/drawdown, PBO, DSR, strategy-level MCPT) have no equivalent to the Factor Catalog’s single dated run synthesis — there is no one diagnostic run that scored all eight strategies at once. Each strategy’s numbers live in its own backtest sidecar (surfaced on the Strategies hub, #/run/<run_id>/pipeline/strategies) and, where a strategy has a dedicated findings write-up, that document is the authoritative source; both are cited per entry below. Everywhere else, empirical fields are marked PENDING rather than guessed — see Method.
  • None of the eight are currently live-submitting paper orders. config/execution.yaml’s experiment_portfolio_ids — the list that binds a strategy’s construction output to the paper order path — is empty. All eight are evaluated purely by nightly/research-day backtest + promotion-gate comparison against their sharpe_min/max_drawdown_max thresholds. This is a distinct, earlier-stage track from the ML signal book’s live paper execution (F-282, first live fills 2026-07-21) — that book trades a separate predictor ensemble, not one of these factor-strategy triples.

5.2 Method: where the backtest evidence lives

Each strategy entry below has empirical fields that are frequently PENDING. All are sourced the same way, stated once here rather than repeated eight times:

  • Backtest runsbbacktest drives a Zipline subprocess per strategy (nightly for enabled_in_nightly: true strategies; research-day-only for research_day_backtest: true strategies), producing a NAV series, tearsheet, and cost-drag sidecar (sbbacktest.sidecar_builder). CAGR/Sharpe/MaxDD/cost-drag come from there.
  • Overfitting controlssbpbo (Probability of Backtest Overfitting / CSCV) and strategy-level MCPT (compute_strategy_mcpt, research-day-only, pbo_splits / mcpt_permutations from the strategy’s own research: block) are the anti-overfitting layer referenced by research-platform/08-validation-and-anti-overfitting.md — the same epistemic caveat as the Factor Catalog’s t-stat columns applies here: a clean Sharpe is necessary evidence, not sufficient.
  • The actual promotion bar is the promotion_gates block (min_elapsed_days, min_green_nightlies, sharpe_min, max_drawdown_max), evaluated against ops.strategy by the F-054 lifecycle machinery — not any single backtest metric in isolation.
  • Where to look: the Strategies hub (#/run/<run_id>/pipeline/strategies, CLAUDE.md §18) surfaces the current run’s tearsheet, health timeline, and (for the six cross-asset/momentum strategies below) benchmark comparison for each strategy.

5.3 1. Cross-sectional equity momentum

The platform’s primary momentum family — four strategies sharing one factor (momentum_12_1_vol_scaled, Factor Catalog §4) and one universe (us_large_cap), each isolating a different construction choice: quantile long/short, long-only, beta-hedged dollar-neutral, or a fixed external yardstick. Jegadeesh–Titman 1993 [#49].

5.3.1 classic-momentum

  • Underlying factor: momentum_12_1_vol_scaled
  • Mechanic: long_short_quantiles — long the top decile, short the bottom decile of the cross-section, ranked monthly
  • Universe: us_large_cap — 500 names, NYSE/NASDAQ, ≥$1B market cap, ≥$5 price, ranked by 20-day dollar ADV
  • Params: 50 long / 50 short, monthly rebalance, 21-day hold, $500k capital, max_leverage: 2.2, vol-managed to a 10% portfolio-vol target (RP-1)
  • Benchmark: SPY (+ 17 more — QQQ/IWM/DIA/MTUM, VIXY/TLT/HYG, 10 sector SPDRs)
  • Lifecycle: enabled_in_nightly: true. Promotion gate: sharpe_min 1.1, max_drawdown_max -0.20, 30 elapsed days, 5 green nightlies.
  • Notes: factor_id was corrected (TASK-1811, 2026-06-26) from momentum_12m_1m to momentum_12_1_vol_scaled so the declared factor honestly names the column the backtest actually trades — the traded signal was unchanged, only the label. One consequence: the underlying factor’s ops.factor status is still experimental (not validated), so this strategy is knowingly trading a pre-validation factor for research purposes, and the Strategies SPA card renders that status honestly rather than a validated factor it doesn’t trade.

5.3.2 classic-momentum-long-only

  • Underlying factor: momentum_12_1_vol_scaled (same correction/caveat as above)
  • Mechanic: long_only_top_n — long the top decile, no short leg
  • Universe: us_large_cap (identical to classic-momentum)
  • Params: 50 long / 0 short, monthly rebalance, 21-day hold, $500k capital, max_leverage: 2.2, max_position_size_pct: 0.20, vol-managed to 10%
  • Benchmark: SPY, QQQ, IWM
  • Lifecycle: enabled_in_nightly: true; seed: true — F-245/LH-21 seeds this YAML as the auto-spawned incubating stub once momentum_12_1_vol_scaled validates (the production STRATEGY_CASCADE_ENFORCE switch itself stays OFF). Same promotion gate as classic-momentum.
  • Notes: the net-long baseline (F-207/TASK-1656, DRAFT-017) — deliberately the directional sibling of classic-momentum-dollar-neutral on the identical factor, so comparing the two isolates whether the edge is cross-sectional (survives beta-hedging) or merely directional (mostly market beta).

5.3.3 classic-momentum-dollar-neutral

  • Underlying factor: momentum_12_1_vol_scaled (same correction/caveat as above)
  • Mechanic: dollar_neutral_rank — long the top decile / short the bottom decile, rank-weighted to net ≈ 0 exposure
  • Universe: us_large_cap (identical to classic-momentum)
  • Params: 50 long / 50 short, monthly rebalance, 21-day hold, $500k capital, max_leverage: 2.2, vol-managed to 10%
  • Benchmark: SPY, QQQ, IWM
  • Lifecycle: enabled_in_nightly: true. Same promotion gate as classic-momentum.
  • Notes: the market-beta-hedged sibling in the DRAFT-017 three-way comparison — run to isolate cross-sectional alpha from directional market exposure, independent of classic-momentum-long-only’s net-long read on the same question.

5.3.4 clinic06-benchmark

  • Underlying factor: momentum_12_1_vol_scaled

  • Mechanic: long_only_top_n — long the top 20, equal-weight, no shorts

  • Universe: us_large_cap (500 names, same filters as classic-momentum)

  • Params: 20 long / 0 short, monthly rebalance, 21-day hold, $1M capital, max_leverage: 1.1, max_position_size_pct: 0.60

  • Benchmark: SPY, QQQ, IWM

  • Lifecycle: enabled_in_nightly: true, but not a promotion candidate — a fixed external yardstick, not traded.

  • Empirical (F-329/IR-14, TASK-2853, populated 2026-08-02) — dual-cost comparison over 2016-01-04→2025-12-30 (2,513 daily NAV rows), from the internal docs/research/clinic06_benchmark_findings.md findings note:

    Regime CAGR Sharpe MaxDD Cost drag (bps)
    TC-2 (platform-default, per-name Corwin–Schultz spread) 18.04% 0.70 −43.77% 503.57
    Fixed (Clinic-faithful flat 1% spread) 16.42% 0.65 −44.07% 613.98
  • Notes: a platform-native replica of the QSResearch Clinic-06 long-only top-20 vol-scaled-momentum book — not a new alpha source. Six deliberate structural divergences from the original harness (survivorship-free universe, dollar- vs share-volume ranking, dropped magnitude threshold, TC-2 vs flat-1% cost, etc.) are catalogued in the findings doc; each is the measurement of a platform effect, not noise. Its purpose is separating “platform effect” from “strategy edge” for every other strategy in this catalog, not generating a tradeable signal of its own.


5.4 2. Sector rotation

Same factor and mechanic as the us_large_cap family above, applied to a much thinner, single-asset-class cross-section — the 11 SPDR sector ETFs rather than 500 individual names.

5.4.1 etf-sector-momentum

  • Underlying factor: momentum_12_1_vol_scaled
  • Mechanic: long_only_top_n — long every ETF in the panel ranked into the top tier (long_q: 11 = the full 11-name panel), equal-weight
  • Universe: us_etf_sector_rotation — the 11 SPDR sector ETFs (XLK/XLF/XLV/XLE/XLI/ XLC/XLY/XLP/XLB/XLRE/XLU)
  • Params: 11 long / 0 short, monthly rebalance, 21-day hold, $1M capital, max_leverage: 1.1, max_position_size_pct: 0.30
  • Benchmark: SPY + the 11 sector ETFs
  • Lifecycle: enabled_in_nightly: false — backtest-only, paper-off. Requires ALLOW_ETFS=ON for the upstream allowlist to admit the sector panel. Promotion gate is looser than the equity family: sharpe_min 0.5, max_drawdown_max -0.30.
  • Notes: the F-247 ETF Universe Extension MVP demo — proves the same cross-sectional-momentum mechanic works on a thin, single-asset-class cross-section once ETFs are admitted at all, ahead of any nightly enablement decision.

5.5 3. Time-series momentum / Trend

The platform’s own-trend-sign complement to cross-sectional momentum: instead of ranking names against each other, each instrument is judged only against its own history — long if trending up, flat otherwise. Works on cross-asset panels too thin for a meaningful cross-sectional rank. Moskowitz–Ooi–Pedersen 2012 [#115], Hurst–Ooi–Pedersen 2017 [#95].

5.5.1 etf-trend

  • Underlying factor: tsmom_12_1_vol_scaled — funnel-exempt; this strategy’s own backtest is the factor’s only evidence (see Factor Catalog §12)
  • Mechanic: long_flat_trend — long every ETF whose own vol-scaled 12-1 trend is positive, flat otherwise (no shorts, no cross-sectional comparison)
  • Universe: us_multi_asset_etf_trend — a ~14-name cross-asset panel, one liquid long-history instrument per asset class (SPY/QQQ/IWM equity, EFA/EEM international, TLT/IEF/LQD/HYG rates & credit, GLD gold, DBC commodities, UUP dollar, VNQ REIT, TIP inflation-linked), pinned explicitly so a venue filter can’t drift the panel
  • Params: long_q 14 (the full panel cap), monthly rebalance, 21-day hold, $1M capital, max_leverage: 2.2, vol-managed to a 10% portfolio-vol target
  • Benchmark: SPY, AGG
  • Lifecycle: enabled_in_nightly: false, research_day_backtest: true (opts into the research-day-only backtest fan-out so its tearsheet surfaces on the Strategies hub without going nightly). Backtest-only, paper-off. Requires ALLOW_ETFS=ON. Promotion gate: sharpe_min 0.5, max_drawdown_max -0.25.
  • Notes: the platform’s first per-asset trend sleeve (F-283/R6-ETF slice) — the highest-value diversifier available to a US-equity book per Hurst–Ooi–Pedersen 2017. Per-asset inverse-vol weighting (rather than today’s equal-weight trend-positive names) is a deferred follow-on (PM-2).

5.6 4. Residual (market-neutral) momentum

The beta-hedged sibling of ordinary cross-sectional momentum: strips out market beta before ranking, via a rolling regression against an equal-weighted benchmark. Blitz–Huij–Martens 2011 [#50].

5.6.1 residual-momentum

  • Underlying factor: residual_momentum_252d_eod — the strongest IC-IR result in the diagnostic run synthesis (+0.724, Factor Catalog §4); note this is the atomic id, not the deprecated composite residual_momentum_252d (no FactorCompositionService exists to compute that recipe)
  • Mechanic: long_short_quantiles — long top decile / short bottom decile of the 252-day residual-return z-score
  • Universe: us_large_cap
  • Params: 50 long / 50 short, monthly rebalance, 21-day hold, $1M capital
  • Benchmark: SPY
  • Lifecycle: enabled_in_nightly: false, research_day_backtest: true. Promotion gate: sharpe_min 1.1, max_drawdown_max -0.20 (same bar as the equity momentum family).
  • Notes: despite trading the run’s single strongest factor result, the strategy itself is still research-day-only, not nightly-tracked — factor-level IC-IR and strategy-level backtest promotion are evaluated on separate cadences and neither implies the other has cleared its own gate.

5.7 5. Earnings momentum / PEAD

Trades the drift that follows a standardized earnings surprise — prices under-react to the news and continue drifting toward it for weeks. Bernard–Thomas 1989 [#75], Chan–Jegadeesh–Lakonishok 1996 [#79].

5.7.1 sue-earnings-momentum

  • Underlying factor: sue (Standardized Unexpected Earnings, Factor Catalog §11)
  • Mechanic: long_short_quantiles — long top decile / short bottom decile of SUE, the standard PEAD convention
  • Universe: us_large_cap
  • Params: 50 long / 50 short, monthly rebalance, 21-day hold, $1M capital
  • Benchmark: SPY
  • Lifecycle: enabled_in_nightly: false by explicit design (config comment: “start dormant; flip once validated in a Zipline backtest”), research_day_backtest: true. Same promotion gate as residual-momentum (sharpe_min 1.1, max_drawdown_max -0.20).
  • Notes: the backtest wiring for this strategy was broken (a Friday NIGHTLY_FULL exit-2 crash) and repaired 2026-08-01 (B-279.1) — the fix spanned four drift-prone layers, so a re-break here is a plausible failure mode to check first if this strategy’s research-day backtest goes red again.

5.8 Next steps

  1. Compile a per-strategy empirical table analogous to the Factor Catalog’s diagnostic-run synthesis — today only clinic06-benchmark has a dedicated, dated findings write-up; the other seven have PENDING CAGR/Sharpe/MaxDD/PBO/DSR fields above.
  2. Once residual_momentum_252d_eod and sue progress toward validated in ops.factor, revisit whether residual-momentum and sue-earnings-momentum should move from research_day_backtest to enabled_in_nightly.
  3. Reconcile each strategy’s ops.strategy lifecycle state (incubating/paper/live, F-054) against this chapter — the config-level enabled_in_nightly/research_day_backtest flags shown here are readiness signals, not the lifecycle state of record.
  4. Add strategy-level MCPT/PBO figures once compute_strategy_mcpt has run against the full eight-strategy set in one research-day pass, so results are directly comparable.