System Documentation
Complete guide to the Regime Trader platform — strategies, risk management, and configuration.
Platform Overview
Regime Trader is a multi-strategy automated trading systemthat trades equities via an Alpaca brokerage account. Three independent strategy “sleeves” share the same account with configurable capital splits (default 60% HMM / 40% Brando / 10% Short Hedge):
HMM Volatility Rotational
A Gaussian Hidden Markov Model classifies market volatility regimes. An allocation layer maps each regime to a target exposure level and rotates capital into top-momentum assets. Runs daily at 19:00 ET after market close.
Brando Level Trader
A swing-trading strategy that detects confirmed support/resistance levels, enters on rejection candles, and manages positions with staged profit-taking (50% at TP1, remainder at TP2) and hard stops. Scans every 15 minutes during market hours.
Short Hedge Sleeve
A defensive sleeve (disabled by default, dry-run only) that buys the inverse ETF SH when the HMM enters a high-vol defensive regime. Caps at 30% of its 10% capital allocation. Provides tail-risk hedging during market stress.
An independent risk managerenforces hard limits across all sleeves: circuit breakers, drawdown caps, and volatility caps. A symbol cannot exist in both the HMM and Brando pools simultaneously — the system enforces disjoint universes.
App Pages
| Page | What it does |
|---|---|
| Analytics Explorer | Research hub for exploring any symbol. Shows the current HMM regime, confidence, regime probability history, allocation overlay chart, scorecard table, and model metadata. Symbol selection triggers auto-seeding of 3 years of data + HMM training. |
| Bot Engine | Live command center for managing the trading system. Configure capital splits and max positions per sleeve, manage trading pools (add/remove symbols), view Brando active positions and trade history, and trigger manual screener scans. |
| Portfolio | Live account overview from Alpaca: total equity, cash, buying power, daily change. Shows all current broker positions with unrealized P&L, historical equity curve, overall performance metrics (total return, max drawdown), and per-strategy summaries. |
| Backtests | Walk-forward backtest runner. Tests the HMM strategy against baselines (buy-and-hold, 60/40, vol-targeting, “dumb HMM”) using rolling in-sample/out-of-sample windows with regime-aware slippage and fill delay. |
| Logs | Structured event log with real-time push (SSE) and polling fallback. Shows every trading event: cycle starts, orders placed, regime changes, risk blocks, Brando entries/exits, screener scans. Filterable by level (INFO/WARNING/ERROR) and searchable. |
| Help & Docs | This page. System reference documentation. |
Trading Schedule
All times are Eastern (ET). The scheduler runs independent jobs on weekdays only, plus quarterly maintenance tasks.
Scans Alpaca + Finnhub news for trending symbols, scores by mention frequency / volume / recency, and persists suggestions. Auto-add to Brando watchlist if enabled.
Evaluates all open Brando trades for exits (stop, TP1, TP2, time-limit). Checks for new entry signals on symbols in the Brando universe. Handles scale-in tranche 2 fills.
After market close: evaluates each symbol in the Brando universe for new entry signals using the freshly completed daily bar. New entries are submitted as GTC limit orders for the next session.
After market close (delayed to ensure OPG fallback window is open): captures equity snapshot, trains/updates HMM, evaluates regime for each symbol in the HMM universe, computes target allocation, rebalances portfolio using whole-share DAY limit orders with GTC stop-loss.
First trading day of each quarter. Recomputes the optimal HMM/Brando capital split using Kelly sizing on the last 60 closed Brando trades. Requires ≥20 trades; falls back to the static 60/40 split otherwise.
First Friday of each quarter. Runs a walk-forward optimization on historical Brando trades to update key parameters (stop multiplier, reward multiple, etc.). Results are logged and applied to the BRANDO sleeve config.
HMM Volatility Strategy
The HMM engine uses a Gaussian Hidden Markov Modelwith full-covariance matrices to classify market volatility environments. It operates strictly as a volatility classifier — it does not predict price direction. The regime state informs an allocation layer that adjusts position sizes, risk limits, and leverage.
Model Selection
- Candidates tested:
n_components ∈ [3, 4, 5, 6, 7] - Each candidate trained with 10 random restarts (keeps highest log-likelihood)
- Winner selected by lowest BIC (Bayesian Information Criterion)
- States ranked by expected volatility and assigned human-readable labels
Regime Labels & Allocation Floors
- BULL / EUPHORIALowest volatility states. Prices trend positively or drift safely. Full allocation (95%) with up to 1.25x leverage.
- NEUTRAL / BEARIntermediate volatility. Market is ranging or in a moderate downtrend. Cautious exposure (max 30%), leverage disabled (1.0x).
- DEEP BEAR / CRASHHigh volatility with rapid moves and gap-downs. Allocation forced to 0% (full cash). These regimes override all other signals.
Filtered Inference (No Look-Ahead)
The system uses the forward algorithm exclusively for live inference. Probabilities at time t depend only on observations up to and including t— no Viterbi, no smoothing. This prevents any look-ahead bias and is enforced by automated tests.
Uncertainty & Flicker Detection
- Uncertainty mode: if max regime probability < 55% or flickering is detected, allocation is halved and leverage forced to 1.0x
- Flicker rate: counts regime changes per 20-bar window. If changes > 4, the model is “flickering” and risk is reduced
- Confirmation: a regime must persist for 3+ consecutive bars before it's considered confirmed
Order Execution
HMM orders use whole shares only (fractional quantities are floored). Entry is submitted as a DAY limit at a slightly aggressive price; if unfilled within 30 seconds, the remaining quantity is submitted as an OPG market order(fills at next morning's opening auction). After fill, a GTC stop-loss is attached as a standalone order so it persists overnight until cancelled by the next rebalance cycle.
Regime Allocation Strategies
Each regime is assigned a strategy based on its volatility rank. The strategy controls allocation sizing, leverage limits, and stop/target distances.
Bottom 33% of volatile regimes. Enables 95% allocation with up to 1.25x leverage. Stop: 3.0x ATR, Target: 5.0x ATR.
Intermediate volatility. Allocation scales with short-term trend strength (EMA filter). Max 30%. Leverage disabled (1.0x). Stop: 2.0x ATR, Target: 4.0x ATR.
Top 33% of volatile regimes. Allocation capped at 60%, leverage disabled. Stop: 1.5x ATR, Target: 3.0x ATR. Triggers the Short Hedge sleeve if enabled.
Allocation forced to 0% regardless of other signals. System holds cash only. Overrides all regime strategy logic.
All three active strategies share a 1.67x reward-to-risk ratio (5/3 = 4/2 = 3/1.5). Stop distances scale with ATR(14) normalized by close price, so they automatically widen in volatile markets and tighten in calm ones.
Brando Level Trader
A swing-trading strategy that trades off confirmed support and resistance levels. The core philosophy: identify where institutional interest clusters (levels with multiple touches on high volume), wait for a rejection signal, enter with predefined risk, and manage the trade through staged exits.
Level Detection
- Scans the last 120 daily bars (~6 months) for swing pivots
- Nearby pivots within 0.5x ATR are clustered into a single level
- A level is confirmed when it has ≥2 touches on above-60th-percentile volume
- Levels are scored 0–1 based on touch count (30%), duration (25%), recency (25%), and volume (20%)
Entry Criteria (all must hold)
- Price is within 0.75x ATR above a confirmed support level
- All enabled macro gates pass (see Advanced Features below)
- Last completed daily bar is a rejection candle:
- Low tested the level (within 0.2x ATR)
- Close recovered above the level
- Body ratio ≥ 0.3% (not a doji)
- Volume ≥ median of lookback window
- Risk sizing produces a valid quantity ≥ 1 share
Position Sizing (Size-to-Zero)
stop_price = level_price − 0.5 × ATR
risk_per_unit = entry_price − stop_price
qty = (sleeve_equity × 0.25%) / risk_per_unit
With conviction sizing: qty ×= (0.5 + 0.5 × level_strength)
With Kelly sizing: sleeve_equity is scaled by the Kelly fraction computed from recent trade history
Exit Rules (Priority Order)
| Priority | Condition | Action |
|---|---|---|
| 1. Stop | Price ≤ stop_price (or trailing Chandelier stop) | Full close. Trade marked STOPPED. |
| 2. TP2 | Price ≥ tp2_price (after TP1 hit) | Close remaining 50%. Trade marked CLOSED. |
| 3. TP1 | Price ≥ tp1_price (while OPEN) | Close 50%, move stop to entry + 50% of (TP1 − entry). Status → TP1_HIT. |
| 4. Time limit | Held ≥ 20 bars | Full close. Trade marked TIME_LIMIT. |
Target Calculation
- TP2: nearest confirmed resistance above entry, or entry + 3.5 × (entry − stop) as fallback
- TP1: entry + 50% × (TP2 − entry) — the halfway point
Brando Advanced Features
All of the following are independently toggleable via sleeve params. They default to conservative (off or permissive) and can be enabled incrementally.
Macro Gate (B2)
Three market-regime filters that block new Brando entries when macro conditions are unfavorable. All gates default to permissive when data is unavailable to prevent infrastructure outages from halting trading.
gate_spy_trend=1)Blocks entries when SPY close is below its 50-day SMA. Only trade the long side in a rising market.
gate_vix_term_structure=0)Blocks entries when VIX > VIX3M (inverted term structure = stress). Requires FINNHUB_API_KEY.
gate_vol_regime=0)Blocks entries when SPY 20-day realized vol exceeds the 95th historical percentile.
Multi-Timeframe Confirmation (MTF)
Disabled by default (mtf_confirmation_enabled=0). When enabled, a daily support signal is only valid if there is also a confirmed weekly support levelwithin 1.5× the weekly ATR. Expected effect: ~40% fewer signals, ~10 percentage-point win-rate improvement.
Chandelier Trailing Stop
Disabled by default (chandelier_enabled=0, multiplier chandelier_atr_multiplier=2.0). After TP1 is hit, instead of a static breakeven stop, the stop trails as:
This lets winners run in trending markets while still locking in gains from TP1.
Correlation Guard
Disabled by default (corr_guard_enabled=0, window corr_guard_window=60). When enabled, skips a new entry if the candidate symbol has a 60-day return correlation ≥ 0.70 with any already-open Brando position. Prevents over-concentration in correlated names.
Brando Configuration
All parameters are stored in sleeve_config.params for the BRANDO sleeve and can be changed via the Bot Engine page or API.
| Parameter | Default | Description |
|---|---|---|
| risk_per_trade_pct | 0.0025 | Fraction of sleeve equity risked per trade (0.25%) |
| pivot_lookback | 120 | Daily bars scanned for swing pivots (~6 months) |
| min_level_touches | 2 | Minimum confirmed touches for a valid level |
| volume_percentile_threshold | 60 | Minimum volume percentile to count a touch as confirmed |
| entry_proximity_atr | 0.75 | Price must be within this × ATR of the level to qualify for entry |
| stop_atr_multiplier | 0.5 | Stop = level − this × ATR |
| tp1_fraction | 0.5 | TP1 = entry + this fraction × (TP2 − entry) |
| reward_multiple | 3.5 | Fallback TP2 = entry + this × risk distance (when no resistance found) |
| post_tp1_stop_fraction | 0.5 | After TP1: stop moves to entry + this fraction × (TP1 − entry). 0 = breakeven only. |
| max_holding_bars | 20 | Maximum days before time-limit exit |
| conviction_sizing | 1 | Scale position size by level strength score (0=off, 1=on) |
| scale_in_enabled | 0 | Two-tranche entry (0=single fill, 1=split into T1 + T2) |
| scale_in_pct | 0.5 | Tranche 1 = this fraction of total qty when scale-in enabled |
| gate_spy_trend | 1 | Block entries when SPY is below its 50-day SMA (0=off) |
| gate_vix_term_structure | 0 | Block entries when VIX > VIX3M (inverted term structure) |
| gate_vol_regime | 0 | Block entries during extreme realized vol (>95th pct) |
| mtf_confirmation_enabled | 0 | Require weekly support confirmation for daily signals |
| chandelier_enabled | 0 | Use chandelier trailing stop after TP1 (0=static stop) |
| chandelier_atr_multiplier | 2.0 | Chandelier trailing distance = highest_high − this × ATR14 |
| corr_guard_enabled | 0 | Skip entries if symbol correlation ≥0.70 with open positions |
| corr_guard_window | 60 | Lookback window in days for correlation calculation |
News Screener
The screener runs daily before market open (08:30 ET) and can be triggered manually from the Bot Engine page. It identifies symbols “in play” by analyzing recent financial news. News tells you where to look. Levels tell you when to trade.The screener feeds the Brando watchlist — it does not generate trading signals.
News Sources
- Alpaca News API — included with your trading credentials, returns articles with tagged ticker symbols
- Finnhub — free API (requires
FINNHUB_API_KEYin .env), extracts tickers from headlines
Screening Pipeline
- Pull articles from all configured news sources (last 24h, up to 200 per source)
- Count symbol mentions across all articles, excluding symbols already in any pool
- Take top 30 candidates by raw mention count
- Filter: must be tradable on Alpaca, avg daily volume > 500K, price $10–$500
- Score remaining candidates (composite 0–1)
- Return top 10 as pending suggestions
Scoring Formula
| Weight | Factor | Formula |
|---|---|---|
| 40% | Mention frequency | log(1 + count) / log(1 + max_count) |
| 30% | Volume | avg_volume / max_volume |
| 30% | Recency | 1 − avg_hours_ago / lookback_hours |
Screener Parameters
| Parameter | Default | Description |
|---|---|---|
| screener_enabled | 0 | Enable/disable scheduled daily scans (0=off, 1=on) |
| screener_auto_add | 0 | Auto-add top suggestions to Brando universe (0=manual, 1=auto) |
| screener_max_suggestions | 10 | Maximum suggestions per scan |
| screener_min_volume | 500,000 | Minimum 20-day average daily volume |
| screener_min_price | $10 | Minimum stock price |
| screener_max_price | $500 | Maximum stock price |
| screener_lookback_hours | 24 | How far back to search news |
| screener_max_watchlist_size | 20 | Maximum symbols in Brando universe |
Risk Management
The risk manager operates independently of both strategies. It enforces hard limits that cannot be overridden by signals. On any HMM or data error, the system defaults to risk-off (hold current positions, no new trades).
Circuit Breakers
| Trigger | Threshold | Action |
|---|---|---|
| Daily drawdown (soft) | > −2% | Position sizes cut by 50% |
| Weekly drawdown (soft) | > −5% | Position sizes cut by 75% |
| Peak drawdown (hard) | > −10% | Full trading halt. Manual reset required. |
Position Limits
- Max portfolio exposure: 100% of sleeve equity
- Max single position: 95% of sleeve equity
- Max leverage: 1.25x (only in low-vol bull regimes)
- Max risk per trade: 1% of portfolio
Global Volatility Cap
If 20-day realized volatility exceeds the 95th historical percentile, max allocation is capped and leverage is disabled regardless of HMM output.
Portfolio Vol Targeting
Disabled by default (vol_target_enabled=0). When enabled, all position sizes are uniformly scaled by target_ann_vol / forecast_vol (never above 1.0). Default target: target_ann_vol=0.12 (12% annualized). This keeps realized portfolio volatility consistent across different market environments.
Buying Power Guard
Before every order, the system checks live buying power from Alpaca with a 5% safety margin. If the order would exceed available buying power, it's automatically downsized (never blocked entirely).
Kelly Capital Sizing
The system can dynamically rebalance the HMM/Brando capital split each quarter using Kelly sizing based on actual closed-trade performance. Disabled by default (kelly_rebalance_enabled=0).
Kelly Formula
kelly = (win_rate × avg_win_R − (1 − win_rate) × avg_loss_R) / avg_win_R
— then apply a 50% haircut (half-Kelly) for conservatism
— clamp to [min_allocation=0.0, max_allocation=0.6]
- Lookback: last 60 closed Brando trades
- Minimum trades required: 20 (falls back to static 60/40 split otherwise)
- Wins/losses measured by R-multiple:
realized_pnl / risk_notional - Negative Kelly expectancy → Brando allocation set to 0% (strategy disabled)
- Rebalance fires quarterly (first trading day, 17:00 ET)
Pool Management & Symbol Changes
The two active strategies handle pool changes differently. HMM is a rebalancer (reconciles positions to a target every cycle), while Brando is a position manager (exits follow pre-set rules, independent of the universe).
HMM — Immediate forced liquidation
Remove a symbol → liquidated at market on the next daily cycle. Add a symbol → eligible for selection based on regime + momentum.
Brando — Natural exit
Remove a symbol → existing position runs its full exit sequence (TP1/TP2/stop/time-limit). Add a symbol → eligible for new entry on next 15-minute scan.
Max Positions
Each sleeve has an independent max positions limit, configurable from the Capital Allocation card on the Bot Engine page. For HMM this caps how many assets can be held simultaneously from the rotational pool. For Brando it caps the number of concurrent swing trades. Both accept a value between 1 and 50.
A symbol cannot exist in both poolssimultaneously. The UI hides the “Add” button for any symbol already present in the other pool, and the API enforces the same disjoint constraint as a hard server-side check.
HMM Feature Engineering
The HMM classifies environments by observing Z-score standardized technical indicators (252-bar rolling lookback). Features are split into Core and Extended sets.
Core Features (v1)
- log_return_XLog returns over 1, 5, and 20 bar windows. Short-term trajectory.
- realized_vol_20d20-period rolling std of daily log returns. Primary volatility signal.
- atr_norm_14ATR(14) / close price. Dimensionless volatility fraction.
- sma_ratio_50_20050-SMA / 200-SMA ratio. Macro trend proxy (golden/death cross).
Extended Features
- volume_zscoreZ-score of volume vs 50-bar avg. Detects capitulation/euphoria.
- adx_14Average Directional Index (14). Trend strength, direction-agnostic.
- rsi_zscore_14RSI(14) Z-scored over optimal lookback. Momentum extremes.
- dist_from_sma200% distance from 200-SMA. Mean reversion / trend extension signal.
Walk-Forward Backtest
The backtest uses a rolling window approach to simulate realistic out-of-sample performance. No future data is used at any point — the HMM is retrained on each in-sample window.
Window Design
- In-sample: 252 bars (1 year) — HMM is trained on this window
- Out-of-sample: 126 bars (6 months) — strategy is evaluated here
- Step: 126 bars — windows slide forward by half a year
- Fill delay: 1 bar (orders execute on the next bar's open)
- Rebalance threshold: 10% (only rebalances if allocation changes by >10%)
Regime-Aware Slippage
| Regime | Slippage |
|---|---|
| Low Vol Bull | 0.05% |
| Mid Vol Cautious | 0.10% |
| High Vol Defensive | 0.15% |
Baselines
- Buy-and-hold: 100% SPY, no rebalancing
- 60/40: 60% equity / 40% bonds (simulated 4% annual return)
- Vol-targeting: Inverse 20-day realized vol, targeting 10% annualized
- Dumb HMM: 3 fixed regimes, 1-day returns only, static allocation map
Metrics Computed
Total return, CAGR, annualized volatility, Sharpe ratio, Sortino ratio, maximum drawdown, and Calmar ratio — for both the strategy and all baselines across each OOS window.
Chart & Visualization Reference
Regime Probability Chart
Historical state probabilities from filtered HMM inference. Forward-only (“filtered”) ensures zero look-ahead bias. Shows how confident the model is in each state over time.
Allocation Overlay
Target allocation percentage overlaid on asset price. Illustrates how the system reduces exposure during crashes and increases it during stable bull regimes.
Equity Curve (Portfolio page)
Historical portfolio equity from daily snapshots. Populates after the first trading cycle runs and records a snapshot.
Flicker Rate
Regime changes per 20-bar window. A high flicker rate (>4 changes) means the HMM states are conflicting. The system enters an uncertainty fallback and halves risk.