Hedge Trading Platform β Complete System Documentation (March 2026)
P3 - LowHedge Trading Platform β Complete System Documentation
Overview
Hedge is a personal trading platform built for Henry Kim that automates portfolio management across multiple brokerage accounts using regime-based strategies. It detects market regimes (bullish/neutral/bearish) using machine learning models and automatically rebalances portfolios to match target allocations.
Stack: Python FastAPI backend + SvelteKit frontend (Vercel)
Repo: github.com/widerwings-inc/hedge (local: ~/clawd/projects/hedge)
Frontend: hedge.widerwings.com (Vercel)
Backend: Ubuntu server + Cloudflare Tunnel β api.widerwings.com
Backend Port: localhost:8000 (systemd service: hedge-api)
Architecture
Backend Services
- FastAPI on port 8000 (39 API routers)
- PostgreSQL via Supabase (bmwbwyptqiiqolgvbhsw.supabase.co)
- Systemd services:
hedge-api(FastAPI),cloudflared(tunnel) - Cron jobs: regime_cache, nightly_signals, auto_execute
Data Providers (Priority Order)
- Schwab (primary, when authenticated via OAuth)
- Alpaca (secondary)
- yfinance (last resort fallback)
Unified provider:backend/app/services/data_provider.py
Frontend
- SvelteKit + Tailwind CSS
- Deployed on Vercel at hedge.widerwings.com
- Key routes: /accounts/[id], /strategy/regime-lab, /strategy/opening-power, /strategy/hmm-combo
Trading Accounts
| Account ID | Broker | Type | Strategy | Auto-Execute | Mode |
|---|---|---|---|---|---|
| alpaca_paper | Alpaca | Trading | Malik TQQQ/SQQQ | β ON | Auto-trade (MOC orders) |
| alpaca_trading | Alpaca | Trading | HMM+Combo | β OFF | Pending Phase 2 |
| schwab_common | Schwab | Trading | Malik TQQQ/SQQQ | β OFF | Pending Phase 2 |
| schwab_hsa | Schwab | IRA | (none assigned) | β OFF | Pending Phase 2 |
| schwab_ira | Schwab | IRA | (none assigned) | β OFF | Pending Phase 3 |
| vanguard_401k | Vanguard | 401K | Vanguard 401K | β ON | Guidance-only (Telegram alert) |
Rollout Plan (Henry-approved)
- Phase 1 (NOW): Alpaca Paper on autopilot. Monitor for days to weeks.
- Phase 2: If Phase 1 looks good β enable Alpaca Live, Schwab Common, Schwab HSA
- Phase 3: If Phase 2 looks good β enable Schwab Roth IRA
- Vanguard: Always guidance-only (no API trading). Telegram alerts to Henry for manual rebalancing.
Enabling New Accounts for Auto-Execute
For Alpaca accounts:
# In account settings (Supabase trading_accounts table):
settings.auto_execute = True
settings.live_execute_enabled = True # Required for non-paper accounts
For Schwab accounts: NOT YET WIRED. Need to:
- Connect
schwab_client.place_order()into auto_execute.py - Schwab uses whole shares (not notional) β need conversion logic
- Verify if Schwab API supports MOC order type
Auto-Execute System
How It Works
- Cron fires at 12:00 PM PT (3:00 PM ET) weekdays
- Refreshes daily bars for regime tickers (SPY, QQQ, VIX, TLT, GLD, TQQQ, SQQQ)
- Computes regime signal for each account's assigned strategy
- Compares target allocation vs current positions
- If drift > 3%: computes rebalance trades
- Trading accounts: submits MOC orders (
time_in_force="cls") β executes in closing auction - Guidance-only accounts: sends Telegram alert to Henry with exact trades to make
- Logs everything to
/tmp/auto_execute.logand Supabaseauto_execute_logtable
Key Files
backend/app/jobs/auto_execute.pyβ Core logic (signal determination, rebalance computation, order execution)backend/scripts/auto_execute_cron.pyβ Cron entry point (bar refresh β execute β alerts)backend/scripts/nightly_signals.pyβ Full signal refresh (runs 8 PM PT)- State tracking:
backend/data/auto_execute_state.json(prevents duplicate Vanguard alerts)
Cron Schedule
# Regime cache refresh (12:30 AM PT)
30 0 * * 2-6 venv/bin/python -m app.jobs.regime_cache
# Pre-close auto-execute + MOC orders (12:00 PM PT / 3:00 PM ET)
0 12 * * 1-5 venv/bin/python scripts/auto_execute_cron.py
# Nightly full signal refresh (8:00 PM PT)
0 20 * * 1-5 venv/bin/python scripts/nightly_signals.py
MOC Orders (Market-on-Close)
- Orders use
time_in_force="cls"via Alpaca API - Execute in the NYSE closing auction at official close price
- Must be submitted before 3:50 PM ET (we submit at 3:00 PM ET β 50 min buffer)
- Eliminates overnight gap risk: signal and execution happen same day
- If submitted after 3:50 PM but before 7:00 PM β REJECTED
- If submitted after 7:00 PM β queues for next day's close
Vanguard Guidance-Only Mode
- Account has
guidance_only: truein settings - Auto-execute computes signals but does NOT place orders
- Cron script tracks last-alerted regime in state file
- Only sends Telegram alert when regime CHANGES (no daily spam)
- Alert includes: regime change, target allocation, deadline (1:00 PM PT for Vanguard)
- Vanguard mutual fund cutoff: 4:00 PM ET (1:00 PM PT) for same-day NAV pricing
Safety Guards
- Sells execute before buys (won't buy without freed cash)
- Total allocation weight must sum to β€ 105% (5% rounding tolerance)
- Buy notional can't exceed available cash + sell proceeds (no margin)
- Portfolio value must be > $100
- Non-paper accounts require explicit
live_execute_enabled: true
Strategy System
Strategy Lab (Primary System)
All regime-based strategies live in Strategy Lab. Two database tables:
model_sets β Reusable groups of regime detection models:
| Name | Models | ID (prefix) |
|---|---|---|
| Original 4 | hmm, vix, sma_trend, realized_vol | af6ed297 |
| ML + Rules | gmm, bocpd, vix, sma_trend | 491d4c12 |
| Best Risk-Adj | hmm, bocpd, msgarch, correlation, sma_trend | df941bc5 |
| All 9 | all 9 models | bd985aa5 |
| Adaptive 3 | msgarch, sma_trend, volume_flow | d4f860e3 |
| HMM+Combo | hmm, msgarch, volume_flow, bocpd | 93513055 |
| Malik Trend+MR | sma_trend, realized_vol, volume_flow, bocpd | 205f4b95 |
lab_strategies β Strategy definitions with allocations per regime:
| Strategy | Model Set | Bullish | Neutral | Bearish |
|---|---|---|---|---|
| Malik TQQQ/SQQQ | Malik Trend+MR | 100% TQQQ | 75% CASH, 25% TQQQ | 75% CASH, 25% SQQQ |
| Vanguard 401K | ML + Rules | 60% VIGAX, 30% VITAX, 10% VTIAX | 40% VBIAX, 30% VBTLX, 20% VFIAX, 10% VMFXX | 100% VMFXX |
| Schwab IRA (Aggressive) | ML + Rules | 100% TQQQ | 60% SPY | 100% CASH |
| Trading Aggressive | ML + Rules | 100% TQQQ | 50% SPY | 50% SQQQ |
| Adaptive Regime (3-Model) | Adaptive 3 | Multi-fund aggressive | Multi-fund balanced | Multi-fund defensive |
| HMM+Combo | HMM+Combo | Multi-fund growth | Multi-fund balanced | Multi-fund value |
API: /api/strategy-lab/* (model-sets, strategies, backtest)
Custom Strategies (Code-Based)
These have dedicated Python engines beyond simple regimeβallocation mapping:
- HMM+Combo (
hmm_combo.py) β HMM gatekeeper + 3 independent signals (MS-GARCH, Volume Flow, BOCPD). Frontend:/strategy/hmm-combo - Opening Power (
opening_power.py) β Oliver Velez method. Intraday: elephant bar entry, 3-push exit. Frontend:/strategy/opening-power - Malik TQQQ/SQQQ (
tqqq_trend.py) β 250-day MA on QQQ. Hasget_current_signal()for auto-execute.
All Strategy Engines (24 total)
Located in backend/app/services/strategies/:
adaptive_allocation, bollinger, credit_spreads_0dte, dual_ma, gap_fill, gap_scanner, hmm, hmm_combo, hmm_pro, insider_buying, iv_hv_screener, macd_rsi, micro_pullback, momentum_rotation, opening_power, orb, rsi2, sma200, tqqq_trend, turtle, vix_overlay, wheel
Each registered in STRATEGY_REGISTRY in __init__.py with slug, class, metadata, parameters, and backtesting support.
Regime Detection
Core: backend/app/services/regime_composite.py
9 regime models available:
- HMM β Hidden Markov Model (3-state)
- VIX β Volatility index levels
- SMA Trend β 200-day SMA position
- Realized Vol β Historical volatility analysis
- BOCPD β Bayesian Online Changepoint Detection
- MS-GARCH β Markov-Switching GARCH
- Correlation β Cross-asset correlation regimes
- GMM β Gaussian Mixture Model
- Volume Flow β Volume-weighted flow analysis
RegimeComposite takes a list of models + weights + veto rules β produces a composite score β maps to regime name (bearish/neutral/bullish) with confidence level.
Broker Integrations
Alpaca
- Dual account support: Paper + Live (separate API keys in .env)
- Services: AlpacaClientManager, TradingService, MarketDataService
- Order types: Market, Limit, MOC (time_in_force: day, gtc, cls, opg, ioc, fok)
- Notional orders: Supports dollar-amount orders (fractional shares)
- Env vars: ALPACA_API_KEY_PAPER, ALPACA_SECRET_KEY_PAPER, ALPACA_API_KEY_LIVE, ALPACA_SECRET_KEY_LIVE
Schwab
- OAuth authentication (tokens expire, need periodic re-auth)
- Service:
schwab_client.pyusing schwab-py library - Endpoints: /api/schwab/* (status, auth, callback, accounts, positions, orders, quotes, history)
- Order execution:
place_order()supports market/limit, whole shares only (no fractional/notional) - Token refresh: Auto-refresh on 401, manual re-auth when refresh token expires (~7 days)
- Auth URL:
https://api.schwabapi.com/v1/oauth/authorize?client_id=...&redirect_uri=https://api.widerwings.com/api/schwab/callback - CRITICAL: Never display live Alpaca API keys (Henry's explicit request)
Vanguard (via Plaid)
- Read-only: Holdings and balances synced via Plaid
- No trading API β all trades done manually by Henry
- Plaid endpoints: /api/plaid/* (link, sync, holdings)
- Guidance-only mode for auto-execute alerts
Historical Bar Cache
Daily Bars
- Service:
backend/app/services/daily_bar_cache.py - Used by regime models and strategy backtests
- Refreshed by nightly_signals.py and pre-close auto_execute_cron.py
2-Minute Bars (for Opening Power strategy)
- Table:
market_bars_2m(symbol, timestamp, OHLCV, source) - Service:
backend/app/services/bar_cache.py - Smart fetch: DB first β Alpaca backfill β store
- 24 tickers cached: ~1.97M 2m bars, 270 trading days
- 5 momentum tickers: 30 months cached (NVDA, TSLA, AVGO, GOOG, AMZN)
- API: GET /api/strategies/bar-cache/stats, POST /api/strategies/bar-cache/fetch
Opening Power Strategy (Oliver Velez Method)
Source: YouTube video transcribed and documented
Strategy doc: docs/OPENING_POWER_STRATEGY.md
Backend: backend/app/services/strategies/opening_power.py (~750 lines)
Rules
- Pre-market scan: Find stocks with narrow SMA20/SMA200 on 2m bars
- Bar 1 must open clearly above/below BOTH MAs
- Bar 1 must be a confirming elephant bar (green=long, red=short)
- LONG entry: 1 penny above bar 1's HIGH
- Stop: 1 penny below bar 1's LOW
- Exit: 3 pushes (new highs for longs)
Backtest Results (1-Year, 24 Tickers)
- 570 trades, 54% win rate, $14,122 net P&L on $50K/ticker
- 19/24 tickers profitable
- Top: AVGO (+$2,887, 72% WR), NVDA, TSLA, GOOG, AMZN
Exit Strategy Comparison (30 Months, 5 Momentum Tickers)
- Best: Extended 60 min β $26,339, 61% WR, 2.12x PF
- Baseline 20 min β $19,568, 61% WR, 2.42x PF
- WORST: 1% trailing stop β -$38,334 (trailing % stops fail on 2m bars)
Liz AI Assistant
Built-in AI assistant at /api/liz/*. Has access to:
- Strategy Lab operations (create/list/backtest strategies)
- Market data and regime signals
- Account information
- Chat interface in the frontend
Chart Configuration
- Default timeframe: 2-minute bars (fetches 3 days 1m from Schwab, aggregates client-side)
- Default indicators: SMA20 + SMA200
- Timestamps display in Pacific Time
Key Environment Variables (.env)
# Supabase
SUPABASE_URL=https://bmwbwyptqiiqolgvbhsw.supabase.co
SUPABASE_KEY=...
SUPABASE_SERVICE_KEY=...
# Alpaca
ALPACA_API_KEY_PAPER=...
ALPACA_SECRET_KEY_PAPER=...
ALPACA_API_KEY_LIVE=...
ALPACA_SECRET_KEY_LIVE=...
# Schwab
SCHWAB_APP_KEY=...
SCHWAB_APP_SECRET=...
SCHWAB_CALLBACK_URL=https://api.widerwings.com/api/schwab/callback
# Plaid (Vanguard)
PLAID_CLIENT_ID=...
PLAID_SECRET=...
# OpenAI (for Liz)
OPENAI_API_KEY=...
Monitoring & Logs
- Auto-execute log:
/tmp/auto_execute.log - Nightly signals log:
/tmp/hedge_nightly.log - Regime cache log:
/tmp/regime_cache.log - Supabase table:
auto_execute_log(every execution logged with regime, trades, timestamps) - State file:
backend/data/auto_execute_state.json(guidance-only alert tracking)
Recent Changes (March 3, 2026)
- Auto-Execute V2 β Added strategy_lab support, TQQQ signal integration, configurable live trading
- Regime Lab β Strategy Lab consolidation β Migrated all 6 profiles, deleted old profiles.py (626 lines removed)
- MOC orders β Changed from market orders (day) to Market-on-Close (cls) for better execution
- Pre-close cron β Moved execution to 12:00 PM PT (3:00 PM ET), 50 min before MOC cutoff
- Vanguard guidance-only β Telegram alerts on regime change with target allocation and deadline
- Same-day detection β Cron refreshes daily bars before computing signals
TODO / Future Work
- Wire Schwab
place_order()into auto-execute for Phase 2 - Verify Schwab MOC support (or use limit orders near close)
- Consider separate strategy assignment per Schwab account (Common vs HSA vs IRA)
- Clean up duplicate regime entries in migrated lab_strategies (two "bearish" and two "bullish" from old score-based system)
- Opening Power: Re-run exit tests on 3-month window for rapid iteration
- Strategy works best on momentum stocks β consider filtering slow movers
Created: Tue, Mar 3, 2026, 9:28 PM by bob
Updated: Tue, Mar 3, 2026, 9:28 PM
Last accessed: Mon, Mar 9, 2026, 2:19 AM
ID: d573d2f2-04b5-46bb-aac0-923797a45b5e