Case study · Backtest
🗓 Backtest period: 2020-01-01..2024-07-01
Spec ID: spec-msm-forecast-volatility-targeting-liquid-us-equities-etfs-1787691749 · Generated: 2026-08-26 01:15 UTC
Cluster: Volatility Targeting · Sub Cluster: Msm Forecast Inverse-Volatility Overlay
The strategy holds SPY long with exposure scaled from a one-day-ahead binomial Markov-switching multifractal volatility forecast. It targets 12% annualized portfolio volatility and exits when forecast SPY volatility exceeds 35%.
Equity volatility clusters and evolves across multiple persistence horizons. A binomial MSM represents this behavior through latent volatility multipliers with heterogeneous switching rates, potentially producing a more responsive conditional-variance forecast than a static volatility estimate.
The trading overlay seeks to stabilize risk rather than predict return direction: exposure falls when forecast volatility rises and increases when forecast volatility falls, subject to gross-exposure and position caps. Because the universe contains only SPY, the forecast controls market exposure rather than allocating risk across assets.
[code omitted from public view] The occupation-sector filter is analysis-only and never generates portfolio weights.
| Param | Value | Notes |
|---|---|---|
| Universe | SPY ETF | Fixed symbol SPY&US&ETF; GSPC is not traded |
| Direction | Long-only | Exposure ranges from cash to the applicable cap |
| Data and return | Daily adjusted close; log(close_t/close_{t-1}) |
Close is assumed split- and dividend-adjusted |
| Signal / rebalance | Daily at close | Information through date t forecasts t+1; market-on-close convention |
| Backtest window | 2020-01-01 to 2024-07-01 | Daily bars |
| MSM states | Binomial, conventional full-state filter | Sector filter is analysis-only |
| Candidate orders | k ∈ {2,3,4,5,6} |
Re-estimated and selected by minimum BIC |
| BIC | -2*ell_k + 3*ln(T_est) |
Three fitted parameters: m_0, sigma, and b |
| Slowest switch probability | gamma_k = 1/756 |
Remaining gamma_l values follow Eq. (10) |
| Return drift | mu_t = 0 |
Strategy-layer implementation choice |
| Forecast horizon | 1 trading day | Full-state posterior is propagated to t+1 |
| Annualization | 252 | Volatility is multiplied by sqrt(252) |
| Volatility target | 12% annualized | Scaler is min(1.5, 0.12/v_port) |
| High-volatility gate | 35% annualized | Desired exposure becomes zero above the threshold |
| Portfolio covariance | Diagonal approximation | v_port = sqrt(sum_i((u_i*v_i)^2)); immaterial cross-covariance for one asset |
| Position / gross cap | 1.5 / 1.5 | A single SPY position may use the full gross cap |
| Maximum leverage guard | 4.0 | Gross and position caps bind first under stated rules |
| Calibration history | Expanding window | The implementation indicates expansion because no rolling window is specified; warm-up details are not supplied |
| Explicit trading charge | 5 bps per side | Applied to traded notional on buys and sells |
| Platform costs | $0.004/share; $1 minimum; 1% maximum commission; 0 bps slippage | Cost configuration accompanying the backtest |
| # | Concern | Status |
|---|---|---|
| 1 | Close-derived signal execution | Pass — the signal uses data through date t and trades at that date's close under the platform's market-on-close convention |
| 2 | Future returns entering MSM calibration | Pass if implemented as specified — each calibration must contain observations dated no later than t |
| 3 | BIC model selection leakage | Pass if implemented as specified — candidate models are compared only on the contemporaneous calibration sample |
| 4 | Corporate-action information | Assumption — the supplied close is treated as split- and dividend-adjusted; no synthetic or forward-filled execution prices are permitted |
| 5 | Fundamental release timing | Not applicable — the strategy uses no earnings, filings, transcripts, or other fundamental data |
| 6 | Missing execution prices | Pass — orders are skipped when the required close is missing or non-finite |
1 < m_0 < 2. It can therefore admit m_0 >= 2, making the second multiplier 2-m_0 <= 0 and invalidating the square root and Gaussian variance in Eqs. (9), (16), and (17); the paper's likelihood and filtering results then do not describe the forecast being traded.T_est and the solution of the non-concave MLE remain implementation-dependent, preventing a direct reproduction of the paper's calibration results.k by BIC. The paper's sector-filter O(k^2) runtime advantage and its fixed-k likelihood, marginal-error, MAP-agreement, orbit-TV, and recovery results in Tables 4 and 5 do not characterize production trading.gamma_k=1/756, and sets mu_t=0. These deviations invalidate direct use of the paper's GSPC timing benchmark, Eq. (14) calibration-dependent likelihood and QLIKE results, and any results requiring nonzero or time-varying drift.From 2020-01-01 through 2024-07-01, the SPY overlay returned 54.55% with a 0.90 Sharpe ratio, 1.21 Sortino ratio, and 13.52% annualized volatility. Realized volatility exceeded the 12% target, while maximum drawdown reached 20.21%. The run recorded a 3.08 profit factor, an 80.55% win rate, and 1,069 trades; these outcomes describe this single-asset implementation and do not validate the MSM forecast against the listed filter comparators.
Recomputed here from the run's stored daily returns, because every annualized figure in the table above is derived from the LENGTH of that array (years = n / 252). Only total return and max drawdown do not depend on the row count, so when the recomputed and stored values differ by a common factor, those two are the numbers to trust.
| Check | From the run's own returns | Note |
|---|---|---|
| Daily-return rows | 1,131 | 1.00x the 1,134 trading days in 2020-01-01..2024-07-01 |
| Distinct dates | 1,131 | one row per date |
| Date span | 2020-01-02 .. 2024-07-01 | |
| Sum of daily returns | 54.55% | matches the reported total return |
| Sharpe from these rows | 0.90 | stored 0.90 |
| Volatility from these rows | 13.52% | stored 13.52% |
| Max drawdown from these rows | -20.21% | stored -20.21% |
| CAGR from these rows | 10.19% | stored 10.19% |
| Metric | Value |
|---|---|
| Total Return | 54.55% |
| Sharpe | 0.90 |
| Sortino | 1.21 |
| Calmar | 0.50 |
| Max Drawdown | -20.21% |
| Volatility | 13.52% |
| Beta vs SPY | 0.46 |
| Win Rate | 80.55% |
| Profit Factor | 3.08 |
| Total Trades | 1069 |
| Symbols | 1 (SPY) |