Case study · Backtest
🗓 Backtest period: 2020-01-01..2026-11-01
Spec ID: spec-macro-gated-time-series-momentum-us-stocks-1783195630_v22 · Generated: 2026-11-05 09:47 UTC
Cluster: Momentum · Sub Cluster: Low-Rate Gated Absolute Equity Momentum
Buys up to 20 liquid stocks with positive absolute momentum and confirmed uptrends when FEDFUNDS is at or below 1%. Eligible stocks are ranked by volatility-adjusted multi-horizon returns and held in equal weights subject to position limits.
Price trends may persist because investors incorporate information gradually and institutional flows adjust slowly. The low-rate gate hypothesizes that accommodative monetary conditions support sustained equity trends; the trend filters seek to avoid deteriorating names, while volatility-adjusted ranking reduces preference for stocks whose returns simply reflect higher volatility. These are economic hypotheses, not causal conclusions established by this backtest.
Specification-level logic; the truncated source does not verify the complete trading implementation. [code omitted from public view] The specification also requires low-rate, non-low-rate, and ungated momentum comparisons, including regime-level return, risk, trade, and exposure statistics; these outputs are not supplied.
| Param | Value | Notes |
|---|---|---|
| Universe | STOCK; top_n = 100; sort_by = capitalization | Supplied 100-symbol list; historical membership methodology is unverified. |
| Price inputs | close, volume_in_dollars | Daily bars. |
| Return lookbacks | 63, 126, 252 trading days | minimum_history_days = 252. |
| Ranking score | 0.4 * return_63d + 0.4 * return_126d + 0.2 * return_252d | Divided by realized_volatility_20d; adjustment enabled; volatility lookback = 20 days. |
| Trend averages | SMA50, SMA200 | Entry requires close > SMA200 and SMA50 > SMA200. |
| Entry momentum | return_63d > 0; return_126d > 0 | time_series_absolute_momentum; primary gate = low_interest_rate. |
| Macro source | FEDFUNDS; macro_indicators | pit_filter: observation_date <= signal_date. |
| Rate regimes | Low: <= 1.0; non-low: > 1.0 | Absolute thresholds, in percentage points. |
| Missing macro policy | skip_new_entries_until_latest_pit_observation_available | Existing-position handling during missing observations is not specified. |
| Exit rules | Negative 63-day return; close below SMA200; rate regime not low | All enabled; rebalance_existing_positions_by_rank = true. |
| Position sizing | equal_weight_among_selected_positions | max_active_positions = 20; max_position_size_pct = 0.1. |
| Maximum leverage | 4.0 | Ceiling, not a stated target exposure. |
| Liquidity filter | Enabled; min_20d_avg_volume_in_dollars = 25000000 | Rule-level filter applies; backtest-plan liquidity_filter is null. |
| Execution | daily bars, MOC (market-on-close) | rebalance_time = close; skip_trade_if_real_daily_close_price_missing. |
| Planned backtest | 2020-01-01..2026-11-01 | bar = 1d; wfa = null; position_limits = null. |
| Declared data period | 2018-01-01..2023-01-01 | Conflicts with planned backtest endpoint; actual coverage requires reconciliation. |
| Annualization origin | 2020-04-02 | Supplied measurement start, not confirmation of the realized endpoint. |
| Regime comparison | Required: low_interest_rate and non_low_interest_rate | Variants: low_interest_rate_gated_momentum, non_low_interest_rate_gated_momentum, ungated_momentum. |
| Comparison metrics | total_return, annualized_return, sharpe_ratio, max_drawdown, win_rate, average_trade_return, exposure_days | Comparison results are not supplied. |
| Commissions | $0.0040 per share, minimum $1.00 per order, capped at 1.00% of trade value | Charged per fill by the results module; all metrics are net of them |
| Slippage | 0 bps — not applied | Not an omission — MOC (market-on-close) fills at the auction print the backtest uses |
| Costs not modelled | short borrow fees / rebate, margin financing on leverage, market impact, exchange/regulatory/clearing pass-through fees, taxes | Excluded deliberately, not unknown |
| Minimum order notional | 0.0 USD | min_notional_order_limit_usd = 0.0. |
| # | Concern | Status |
|---|---|---|
| 1 | Macro observation dates versus publication availability | ⚠ observation_date <= signal_date is enforced in the visible configuration, but publication timestamps and historical vintages are unverified; observation dating alone does not establish availability. |
| 2 | Historical universe membership | ⚠ The supplied capitalization-selected symbol list does not establish point-in-time constituents, delisting coverage, or identifier correctness. |
| 3 | Trailing signals and price history | ⚠ The specification requires trailing windows and 252 days of history; full rolling calculations, corporate-action treatment, and missing-price handling are not visible in the truncated source. |
| 4 | Execution timing | ✓ Specified execution is at the close using MOC, consistent with the platform convention; no same-day-open execution is specified. |
| 5 | Backtest coverage and validation | ⚠ Planned endpoint exceeds the declared data endpoint; realized coverage is unverified and no walk-forward analysis is supplied. |
| 6 | Charged transaction costs | ✓ commissions $0.0040/share (min $1.00/order); slippage 0 bps — not applied |
The reported backtest earns 57.14% total return net of charged commissions, with Sharpe 0.78 and maximum drawdown of 15.13%. Profit factor is 1.76, but average losing trades are substantially larger than average winners despite the high win rate. These results indicate positive historical performance with meaningful downside asymmetry; unresolved date coverage and missing regime comparisons prevent attributing that performance specifically to the low-rate gate.
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 from its first active row (years = n / 252, counted from the first trade). 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,717 | 1.00x the 1,722 trading days in 2020-01-01..2026-11-01 |
| Annualized from | 2020-04-02 | 63 leading flat row(s) before the first trade are excluded from Sharpe, volatility and CAGR (1,654 rows count) |
| Distinct dates | 1,717 | one row per date |
| Date span | 2020-01-02 .. 2026-10-30 | |
| Sum of daily returns | 57.14% | matches the reported total return |
| Sharpe from these rows | 0.78 | stored 0.78 |
| Volatility from these rows | 11.11% | stored 11.11% |
| Max drawdown from these rows | -15.13% | stored -15.13% |
| Lowest the book stood | -0.49% | low-water mark, in units of starting capital |
| CAGR from these rows | 7.13% | stored 7.13% |
| Metric | Value |
|---|---|
| Total Return | 57.14% |
| Sharpe | 0.78 |
| Sortino | 0.64 |
| Calmar | 0.47 |
| Max Drawdown | -15.13% |
| Volatility | 11.11% |
| Beta vs SPY | 0.32 |
| Annualized from | 2020-04-02 |
| Win Rate | 78.71% |
| Profit Factor | 1.76 |
| Total Trades | 10738 |
| Symbols | 100 (AAPL, ABBV, ABT, ACN, ACON, ADBE, ADP, AMD, AMGN, AMT, +90 more) |