🧠 All Projects
πŸ“

Hedge Trading Platform β€” Complete System Documentation (March 2026)

P3 - Low
Spec Hedge

Hedge 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)

  1. Schwab (primary, when authenticated via OAuth)
  2. Alpaca (secondary)
  3. 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:

  1. Connect schwab_client.place_order() into auto_execute.py
  2. Schwab uses whole shares (not notional) β€” need conversion logic
  3. Verify if Schwab API supports MOC order type

Auto-Execute System

How It Works

  1. Cron fires at 12:00 PM PT (3:00 PM ET) weekdays
  2. Refreshes daily bars for regime tickers (SPY, QQQ, VIX, TLT, GLD, TQQQ, SQQQ)
  3. Computes regime signal for each account's assigned strategy
  4. Compares target allocation vs current positions
  5. If drift > 3%: computes rebalance trades
  6. Trading accounts: submits MOC orders (time_in_force="cls") β€” executes in closing auction
  7. Guidance-only accounts: sends Telegram alert to Henry with exact trades to make
  8. Logs everything to /tmp/auto_execute.log and Supabase auto_execute_log table

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: true in 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:

  1. HMM+Combo (hmm_combo.py) β€” HMM gatekeeper + 3 independent signals (MS-GARCH, Volume Flow, BOCPD). Frontend: /strategy/hmm-combo
  2. Opening Power (opening_power.py) β€” Oliver Velez method. Intraday: elephant bar entry, 3-push exit. Frontend: /strategy/opening-power
  3. Malik TQQQ/SQQQ (tqqq_trend.py) β€” 250-day MA on QQQ. Has get_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:

  1. HMM β€” Hidden Markov Model (3-state)
  2. VIX β€” Volatility index levels
  3. SMA Trend β€” 200-day SMA position
  4. Realized Vol β€” Historical volatility analysis
  5. BOCPD β€” Bayesian Online Changepoint Detection
  6. MS-GARCH β€” Markov-Switching GARCH
  7. Correlation β€” Cross-asset correlation regimes
  8. GMM β€” Gaussian Mixture Model
  9. 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.py using 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

  1. Pre-market scan: Find stocks with narrow SMA20/SMA200 on 2m bars
  2. Bar 1 must open clearly above/below BOTH MAs
  3. Bar 1 must be a confirming elephant bar (green=long, red=short)
  4. LONG entry: 1 penny above bar 1's HIGH
  5. Stop: 1 penny below bar 1's LOW
  6. 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)

  1. Auto-Execute V2 β€” Added strategy_lab support, TQQQ signal integration, configurable live trading
  2. Regime Lab β†’ Strategy Lab consolidation β€” Migrated all 6 profiles, deleted old profiles.py (626 lines removed)
  3. MOC orders β€” Changed from market orders (day) to Market-on-Close (cls) for better execution
  4. Pre-close cron β€” Moved execution to 12:00 PM PT (3:00 PM ET), 50 min before MOC cutoff
  5. Vanguard guidance-only β€” Telegram alerts on regime change with target allocation and deadline
  6. 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: Wed, Mar 4, 2026, 5:28 AM by bob

Updated: Wed, Mar 4, 2026, 5:28 AM

Last accessed: Wed, Apr 1, 2026, 11:51 PM

ID: d573d2f2-04b5-46bb-aac0-923797a45b5e