Insights
Testing a Market-Regime Filter on Momentum
Alphanume Team · July 21, 2026
Test a market-regime filter on momentum by holding the published monthly basket fixed and varying only the daily exposure rule, then compare drawdown, volatility, return, and filter-induced turnover.
Alphanume Quant Galore Momentum Index publishes 10 ranked stocks at each monthly rebalance. The Momentum Index guide documents the fixed basket clock. S&P 500 Risk Regime publishes a daily binary state, where 0 is risk-on and 1 is risk-off. The combined test asks whether a state-aware exposure rule changes the path of the fixed momentum basket.
The regime label is a volatility-state classification, not a directional forecast. A risk-off value can justify testing less gross exposure because market volatility is elevated. It does not say the basket or the S&P 500 must fall that day.
Align monthly holdings with a daily state
Input | Publication clock | Backtest rule |
|---|---|---|
Momentum basket | Monthly at 4:05 PM New York time | Enter on the next eligible session |
Risk regime | Daily at 10:10 AM New York time | Use prior state at the open or same-day state after publication |
Daily returns | Defined by the chosen price source | Apply to constituents already in the fixed basket |
Rebalance | Next published basket date | Replace names only on the scheduled monthly transition |
Expand each monthly 10-stock basket into daily holdings until the next rebalance, then join the regime known at the strategy's decision time. Do not rebuild momentum rankings daily. That would combine a regime filter with an unplanned change in the selection model.
The regime date join needs an observation-time rule. An open strategy uses the prior session's label because today's state arrives at 10:10 AM. A close strategy can use the same-day label after allowing a declared execution delay.
Build the fixed-basket panel
Pull both histories, verify exactly 10 unique ranks per momentum date, and create holding intervals from each rebalance through the day before the next. Then attach survivorship-complete daily prices and the correctly known regime.
import pandas as pd
baskets = pd.DataFrame(momentum_rows).sort_values(["date", "rank"])
regime = pd.DataFrame(regime_rows).sort_values("date")
assert baskets.groupby("date").size().eq(10).all()
assert baskets.groupby("date")["rank"].nunique().eq(10).all()
assert regime["date"].is_unique
# daily_holdings is expanded from each published basket without reranking.
panel = daily_holdings.merge(regime, how="left", on="date", validate="many_to_one")
panel["size_multiplier"] = panel["risk_regime"].map({0: 1.0, 1: 0.5})
panel["filtered_return"] = panel["basket_return"] * panel["size_multiplier"]The half-exposure rule is an example that must be predeclared. Test the unfiltered baseline first, then one filter. Searching many multipliers, delays, and state-transition rules will overfit a small number of stress periods.
Measure drawdown and turnover together
Metric | Baseline source | Filter effect |
|---|---|---|
Return | Equal-weight fixed basket | Exposure removed or retained by state |
Realized volatility | Daily basket returns | Primary state-aware risk result |
Maximum drawdown | Chronological portfolio path | Depth and duration change |
Basket turnover | Monthly constituent changes | Exists without the regime filter |
Overlay turnover | Daily multiplier changes | Additional trading caused by state transitions |
A filter can improve drawdown while lowering return, or lower volatility while adding frequent exposure changes. Report both turnover sources. Monthly constituent turnover trades names, while regime turnover changes gross exposure between rebalance dates. They have different spread, tax, and financing consequences.
Calculate drawdown from the full chronological equity curve. Computing state-specific drawdowns after splitting the dates destroys the path and can make the filter look safer than the implementable portfolio.
Specify what the uninvested half earns during risk-off periods. Cash at zero, a dated cash yield, and a hedge each produce different returns and risks. The simplest diagnostic uses zero return on unused notional, then reports financing or cash yield as a separate sensitivity.
Use the proof as a boundary
The Alphanume proof page reports that risk-off days have substantially higher realized and forward volatility while average market direction is similar across states. It also publishes the momentum basket's historical record separately. Neither result proves that the half-exposure overlay improves momentum. The interaction is a new strategy test.
- Timing leakage. Same-day risk state cannot be used at the open.
- Concentration. A 10-stock momentum basket has single-name and sector risk that a market-level flag does not describe.
- State simplicity. A binary label cannot distinguish a marginal risk-off day from a crisis.
- Execution costs. Regime flips add turnover beyond the monthly rebalance.
- Missing outcomes. Delisted constituents must remain in the fixed historical basket and return source.
Free access covers a trailing 20-session delayed window and may contain only one momentum basket. A drawdown test needs full histories and enough stress episodes to evaluate the state interaction.
Run one predeclared overlay
Build the unfiltered equal-weight basket with next-session rebalance entry, then apply one 1.0 versus 0.5 exposure rule using the prior regime at the open. Export holdings, state alignment, basket turnover, overlay turnover, equity curves, drawdowns, and missing-price rows. Validate on a later period before considering another multiplier.
Explore the state fields on the S&P 500 Risk Regime page and follow the Risk Regime guide for the daily clock and historical access contract.