Comprehensive State Documentation for Polymarket Earnings Trading System
Version: 1.8 | Created: January 11, 2026 | Last Updated: May 31, 2026
v1.8 Changes (Apr 27, 2026 — Database Integrity Audit Phase 3 / Finding #258): - §8 "Watchdog v3" REPLACED by
polymarket-integrity-monitor.servicerunningsrc/data_tracker/integrity_monitor.py. The state machine below is retained as historical context — current operative health-check architecture is the ~51-rule declarative monitor. Seedocs/DATA_INTEGRITY.md§2 +docs/OPERATIONS.md§8.A. - Bothpolymarket-watchdog.service(v2) andpolymarket-watchdog-v3.servicewere decommissioned bydeploy/deploy_from_github.shApr 27, 2026.v1.7 / v1.4 / v1.3 / v1.2 / v1.1 Changes: see git history.
┌─────────────────────────────────────────────────────────────────────────┐
│ TRADING SYSTEM ARCHITECTURE │
└─────────────────────────────────────────────────────────────────────────┘
┌──────────────────┐ ┌──────────────────┐ ┌──────────────────┐
│ DATA LAYER │ │ DECISION LAYER │ │ EXECUTION LAYER │
└────────┬─────────┘ └────────┬─────────┘ └────────┬─────────┘
│ │ │
▼ ▼ ▼
┌──────────────────┐ ┌──────────────────┐ ┌──────────────────┐
│ Data Collectors │───▶│ Signal Generator │───▶│ Order Executor │
│ • Prices │ │ • Conviction │ │ • Entries │
│ • Orderbooks │ │ • Timing │ │ • Exits │
│ • Trades │ │ • Priority │ │ • Stop-Loss │
└──────────────────┘ └──────────────────┘ └──────────────────┘
│ │ │
│ ▼ │
│ ┌──────────────────┐ │
│ │Trading Orchestrator│◀──────────────┘
│ │ • Schedule │
│ │ • Coordination │
│ │ • Position Mgmt │
│ └──────────────────┘
│ │
│ ▼
│ ┌──────────────────┐
│ │ Risk Manager │
│ │ • Position Size │
│ │ • Circuit Breakers│
│ │ • Exposure Limits│
│ └──────────────────┘
│ │
▼ ▼
┌──────────────────┐ ┌──────────────────┐ ┌──────────────────┐
│ Integrity Monitor│ │ Dashboard │ │ IBKR Gateway │
│ • Service Health │ │ • Visualization │ │ • Connection │
│ • Data Quality │ │ • Monitoring │ │ • Orders │
│ • Alerts │ │ • History │ │ • Account │
└──────────────────┘ └──────────────────┘ └──────────────────┘
┌─────────────────────────────────┐
│ TradingOrchestrator │
│ (Main Controller - Entry Point) │
└───────────────┬─────────────────┘
│
┌────────────────────────┼────────────────────────┐
│ │ │
▼ ▼ ▼
┌───────────────┐ ┌─────────────────┐ ┌─────────────────┐
│SignalGenerator│ │ RiskManager │ │ OrderExecutor │
│ │ │ │ │ │
│ Dependencies: │ │ Dependencies: │ │ Dependencies: │
│ • Database │ │ • TradingMode │ │ • IBKRClient │
│ • Yahoo API │ │ • IBKRClient │ │ • RiskManager │
│ • Market Cal │ │ │ │ │
└───────────────┘ └─────────────────┘ └─────────────────┘
│ │ │
│ │ ▼
│ │ ┌─────────────────┐
│ │ │BatchOrderManager│
│ │ │ │
│ │ │ Dependencies: │
│ │ │ • OrderExecutor │
│ │ │ • RiskManager │
│ │ └─────────────────┘
│ │
▼ ▼
┌───────────────┐ ┌─────────────────┐
│EarningsDetector│ │ AuditLogger │
│ │ │ │
│ Dependencies: │ │ Dependencies: │
│ • Alpha Vantage│ │ • Database │
│ • Yahoo API │ │ │
└───────────────┘ └─────────────────┘
┌──────────────────────────────────────────────────────────────────────────┐
│ TRADING ORCHESTRATOR STATE MACHINE │
└──────────────────────────────────────────────────────────────────────────┘
┌──────────────────┐
│ INITIALIZING │
│ │
│ • Load config │
│ • Init components│
│ • Load positions │
└────────┬─────────┘
│
│ Components ready
▼
┌──────────────────┐
│ STARTING │
│ │
│ • Setup schedule │
│ • Start monitoring│
│ • Startup check │
└────────┬─────────┘
│
┌────────────────┴────────────────┐
│ │
│ Market Open │ Market Closed
▼ ▼
┌──────────────────┐ ┌──────────────────┐
│ RUNNING │ │ IDLE │
│ │ │ │
│ • Execute cycles │◀────────────▶│ • Wait for market│
│ • Monitor exits │ Market │ • Background sync│
│ • Check earnings │ Open/Close │ │
└────────┬─────────┘ └──────────────────┘
│
┌────────────┼────────────────────────┐
│ │ │
│ Error │ Circuit Breaker │ Shutdown Signal
▼ ▼ ▼
┌──────────┐ ┌──────────────┐ ┌──────────────────┐
│ ERROR │ │ PAUSED │ │ SHUTTING_DOWN │
│ │ │ │ │ │
│ • Log │ │ • No new │ │ • Close positions│
│ • Alert │ │ trades │ │ • Save state │
│ • Recover│ │ • Monitor │ │ • Send alerts │
└──────────┘ │ existing │ └──────────────────┘
└──────────────┘
┌──────────────────────────────────────────────────────────────────────────┐
│ TRADING MODE STATE MACHINE │
└──────────────────────────────────────────────────────────────────────────┘
┌──────────────────┐
│ PAPER │
│ │
│ Simulated trades │
│ No real money │
│ Full position │
└────────┬─────────┘
│
│ Enable TESTING_PROD
▼
┌──────────────────┐
│ TESTING_PROD │◀─────────────────┐
│ │ │
│ • Real money │ │
│ • 50% sizing │ │ Trade < 100
│ • Track 100 trades│ │
└────────┬─────────┘ │
│ │
┌──────────────┴──────────────┐ │
│ │ │
│ 100 trades │ Any trade │
│ completed │ result │
│ successfully │ │
▼ └────────────┘
┌──────────────────┐
│ LIVE │
│ │
│ • Full position │
│ • All features │
└────────┬─────────┘
│
│ Manual pause / Circuit breaker
▼
┌──────────────────┐
│ PAUSED │
│ │
│ • No new trades │
│ • Monitor only │
│ • Manual review │
└──────────────────┘
┌──────────────────────────────────────────────────────────────────────────┐
│ MARKET STATUS STATE MACHINE │
└──────────────────────────────────────────────────────────────────────────┘
4:00 AM ET 8:00 PM ET
│ │
▼ ▼
┌──────────────────┐ 9:30 AM ET ┌──────────────────┐
│ PRE_MARKET │─────────────▶│ OPEN │
│ │ │ │
│ 4:00 AM - 9:30 AM│ │ 9:30 AM - 4:00 PM│
│ │ │ │
│ • Extended hours │ │ • Regular trading│
│ • NASDAQ active │ │ • Full liquidity │
│ • NYSE limited │ │ • All order types│
└──────────────────┘ └────────┬─────────┘
▲ │
│ │ 4:00 PM ET
│ ▼
┌──────────────────┐ ┌──────────────────┐
│ CLOSED │◀─────────────│ AFTER_HOURS │
│ │ 8:00 PM ET │ │
│ 8:00 PM - 4:00 AM│ │ 4:00 PM - 8:00 PM│
│ │ │ │
│ • No trading │ │ • Extended hours │
│ • Prep for next │ │ • NASDAQ active │
│ • System maint. │ │ • NYSE limited │
└──────────────────┘ └──────────────────┘
┌──────────────────────────────────────────────────────────────────────────┐
│ DAILY TRADING CYCLE │
└──────────────────────────────────────────────────────────────────────────┘
TIME (ET) EVENT STATE TRANSITIONS
───────── ───── ─────────────────
4:00 AM Market Pre-Open CLOSED → PRE_MARKET
│
9:30 AM Market Opens PRE_MARKET → OPEN
│
10:30 AM AMC Signal Check
│ ┌─────────────────────────────────────────────────┐
10:30 AM ────▶│ run_amc_cycle() │
│ │ • Check AMC signals for today's earnings │
│ │ • If signals found → schedule entry at 10:34 AM │
│ └─────────────────────────────────────────────────┘
│
10:32 AM BMO Exit Time (1h after open)
│ ┌─────────────────────────────────────────────────┐
10:32 AM ────▶│ execute_scheduled_exits(BMO) │
│ │ • Close all BMO positions from previous day │
│ │ • LIMIT → MARKET fallback │
│ └─────────────────────────────────────────────────┘
│
10:34 AM AMC Entry Time (1h 4min after open)
│ ┌─────────────────────────────────────────────────┐
10:34 AM ────▶│ execute_batch_entries(AMC) │
│ │ • Execute all AMC entries in batch │
│ │ • Attach stop-loss to each │
│ └─────────────────────────────────────────────────┘
│
3:50 PM BMO Signal Check
│ ┌─────────────────────────────────────────────────┐
3:50 PM ────▶│ run_bmo_cycle() │
│ │ • Check BMO signals for tomorrow's earnings │
│ │ • Calculate batch sizes │
│ │ • If signals found → schedule entry at 3:58 PM │
│ └─────────────────────────────────────────────────┘
│
3:57 PM AMC Exit Time
│ ┌─────────────────────────────────────────────────┐
3:57 PM ────▶│ execute_scheduled_exits(AMC) │
│ │ • Close all AMC positions │
│ │ • 1-min buffer before BMO entries │
│ └─────────────────────────────────────────────────┘
│
3:58 PM BMO Entry Time
│ ┌─────────────────────────────────────────────────┐
3:58 PM ────▶│ execute_batch_entries(BMO) │
│ │ • Execute all BMO entries in batch │
│ │ • 2 minutes before market close │
│ └─────────────────────────────────────────────────┘
│
4:00 PM Market Closes OPEN → AFTER_HOURS
│
8:00 PM After-Hours End AFTER_HOURS → CLOSED
┌──────────────────────────────────────────────────────────────────────────┐
│ ORDER STATUS STATE MACHINE │
└──────────────────────────────────────────────────────────────────────────┘
┌──────────────────┐
│ PENDING │
│ │
│ Order created, │
│ not yet submitted│
└────────┬─────────┘
│
│ Submit to IBKR
▼
┌──────────────────┐
│ SUBMITTED │
│ │
│ Waiting for fill │
└────────┬─────────┘
│
┌─────────────────────────┼─────────────────────────┐
│ │ │
│ Full fill │ Partial fill │ Rejected/Error
▼ ▼ ▼
┌──────────────────┐ ┌──────────────────┐ ┌──────────────────┐
│ FILLED │ │PARTIALLY_FILLED │ │ FAILED │
│ │ │ │ │ │
│ Order complete │ │ Some shares │ │ Order rejected │
│ Position updated │ │ filled │ │ Error logged │
└──────────────────┘ └────────┬─────────┘ └──────────────────┘
│
┌────────────┴────────────┐
│ │
│ Remaining fills │ Cancelled
▼ ▼
┌──────────────────┐ ┌──────────────────┐
│ FILLED │ │ CANCELLED │
│ │ │ │
│ All shares │ │ Remaining shares │
│ executed │ │ not filled │
└──────────────────┘ └──────────────────┘
┌──────────────────────────────────────────────────────────────────────────┐
│ GUARANTEED FILL STATE MACHINE │
└──────────────────────────────────────────────────────────────────────────┘
┌──────────────────┐
│ START │
│ │
│ Calculate limit │
│ price with buffer│
└────────┬─────────┘
│
│ Submit LIMIT order
▼
┌──────────────────┐
│ LIMIT_PENDING │
│ │
│ Timeout: 12 sec │
│ (batch mode) │
└────────┬─────────┘
│
┌────────────────┴────────────────┐
│ │
│ Filled within timeout │ Timeout reached
▼ ▼
┌──────────────────┐ ┌──────────────────┐
│ LIMIT_FILLED │ │ CANCEL_LIMIT │
│ │ │ │
│ Record slippage │ │ Cancel LIMIT │
│ Log fill details │ │ Submit MARKET │
└────────┬─────────┘ └────────┬─────────┘
│ │
│ ▼
│ ┌──────────────────┐
│ │ MARKET_PENDING │
│ │ │
│ │ Wait for fill │
│ │ (usually instant)│
│ └────────┬─────────┘
│ │
│ │ Filled
│ ▼
│ ┌──────────────────┐
│ │ MARKET_FILLED │
│ │ │
│ │ Record as │
│ │ LIMIT_FALLBACK │
│ └────────┬─────────┘
│ │
└─────────────────┬───────────────┘
│
▼
┌──────────────────┐
│ COMPLETE │
│ │
│ • ExecutionResult│
│ • Slippage logged│
│ • Commission │
└──────────────────┘
┌──────────────────────────────────────────────────────────────────────────┐
│ ORDER TYPE DECISION STATE MACHINE │
└──────────────────────────────────────────────────────────────────────────┘
┌──────────────────┐
│ DETERMINE_TYPE │
│ │
│ Input: Exchange, │
│ Session, Action │
└────────┬─────────┘
│
┌────────────────────┴────────────────────┐
│ │
│ Exchange == NASDAQ │ Exchange == NYSE
▼ ▼
┌──────────────────┐ ┌──────────────────┐
│ NASDAQ │ │ NYSE │
│ │ │ │
│ All sessions: │ │ Check session: │
│ • Entry: LIMIT │ │ │
│ • Exit: MARKET │ └────────┬─────────┘
│ • Stop: STOP │ │
└──────────────────┘ ┌────────────────┴────────────────┐
│ │
│ Regular Hours │ Extended Hours
│ (9:30 AM - 4:00 PM) │ (Pre/Post)
▼ ▼
┌──────────────────┐ ┌──────────────────┐
│ NYSE_REGULAR │ │ NYSE_EXTENDED │
│ │ │ │
│ Same as NASDAQ: │ │ LIMIT only: │
│ • Entry: LIMIT │ │ • Entry: LIMIT │
│ • Exit: MARKET │ │ • Exit: LIMIT │
│ • Stop: STOP │ │ • Stop: STOP-LMT │
└──────────────────┘ └──────────────────┘
The system uses WHOLE SHARES ONLY for all orders.
CRITICAL BUG FIX (Jan 20, 2026 - Finding #51): IBKR's
cashQtyfeature does NOT work reliably: - Error 10244: "Cash Quantity cannot be used for this order" - Fails with extended hours trading (outsideRth=True) - Has stock-specific restrictions that are unpredictableSolution: Always use whole shares. If position size < stock price, skip the trade.
┌──────────────────────────────────────────────────────────────────────────┐
│ POSITION SIZING STATE MACHINE (v3 - Whole Shares Only) │
└──────────────────────────────────────────────────────────────────────────┘
┌──────────────────┐
│ START │
│ │
│ Target: $100.00 │
│ Price: $90.00 │
└────────┬─────────┘
│
│ Calculate whole shares
│ shares = int(target / price)
▼
┌──────────────────┐
│ CALC_WHOLE_SHARES│
│ │
│ $100 / $90 = 1.11│
│ int(1.11) = 1 │
└────────┬─────────┘
│
┌────────────────┴────────────────┐
│ │
│ shares >= 1 │ shares == 0
▼ ▼
┌──────────────────┐ ┌──────────────────┐
│ PLACE_ORDER │ │ SKIP_POSITION │
│ │ │ │
│ totalQuantity=1 │ │ Target < Price │
│ (whole shares) │ │ Cannot buy 1 sh │
│ │ │ │
│ Order placed! │ │ Log warning │
└────────┬─────────┘ └────────┬─────────┘
│ │
│ │
▼ ▼
┌──────────────────┐ ┌──────────────────┐
│ ORDER_DOLLAR │ │ ORDER_WHOLE │
│ │ │ │
│ totalQuantity=0 │ │ Use int type │
│ cashQty=$121.13 │ │ is_fractional=F │
│ is_fractional=T │ │ │
│ │ │ │
│ IBKR handles │ │ Actual: $0 │
│ fractional calc │ │ (skipped - <1 sh)│
└────────┬─────────┘ └────────┬─────────┘
│ │
└─────────────────┬───────────────┘
│
▼
┌──────────────────┐
│ SUBMIT_TO_IBKR │
│ │
│ Uses existing │
│ LIMIT→MARKET │
│ fallback flow │
└──────────────────┘
API Order Syntax:
# WRONG (Error 10243)
order = LimitOrder('BUY', Decimal('0.7219'), 168.13)
# CORRECT (Dollar-based order)
order = LimitOrder('BUY', 0, 168.13) # totalQuantity=0
order.cashQty = 121.13 # Dollar amount
Eligible Exchanges: - NYSE, NASDAQ, AMEX, ARCA, BATS, IEX - Canadian and European exchanges (limited)
Not Eligible: - OTC/Pink Sheet stocks - Low-liquidity stocks - Some non-USD denominated stocks
Minimum Order: - Dollar-based: $1.00 minimum cashQty - Whole shares: 1 share minimum
Database Tracking (Migration 012):
-- trading_positions
is_fractional BOOLEAN -- True if cashQty was used
shares_fractional NUMERIC(12,4) -- Display/tracking only
-- trade_audit_log
is_fractional BOOLEAN
shares_fractional NUMERIC(12,4)
fractional_reason VARCHAR(50)
fractional_capital_saved NUMERIC(10,2)
┌──────────────────────────────────────────────────────────────────────────┐
│ EXIT VERIFICATION STATE MACHINE │
└──────────────────────────────────────────────────────────────────────────┘
┌──────────────────┐
│ EXIT_ORDERED │
│ │
│ Exit order sent │
│ to IBKR │
└────────┬─────────┘
│
│ Wait for fill
▼
┌──────────────────┐
│ WAIT_FOR_FILL │
│ │
│ • LIMIT: 5s │
│ • NYSE: 30s │
│ • Fallback: MKT │
└────────┬─────────┘
│
┌────────────────┴────────────────┐
│ │
│ Filled │ Not Filled
▼ ▼
┌──────────────────┐ ┌──────────────────┐
│ VERIFY_IBKR_POS │ │ MARKET_FALLBACK │
│ │ │ │
│ Query IBKR │ │ Cancel LIMIT │
│ positions() │ │ Place MARKET │
└────────┬─────────┘ └────────┬─────────┘
│ │
│ Check shares │
▼ ▼
┌──────────────────┐ ┌──────────────────┐
│ Position = 0? │ │ VERIFY_IBKR_POS │
└────────┬─────────┘ └────────┬─────────┘
│ │
┌────────────┴────────────┐ │
│ │ │
│ Yes │ No │
▼ ▼ ▼
┌──────────────┐ ┌──────────────────┐ ┌──────────────┐
│ VERIFIED │ │ VERIFICATION_ │ │ VERIFIED │
│ │ │ FAILED │ │ (if 0) │
│ exit_verified│ │ │ └──────────────┘
│ = True │ │ • Log error │
│ │ │ • Send CRITICAL │
│ Mark DB │ │ alert │
│ closed │ │ • Keep DB open │
└──────────────┘ │ • Manual review │
│ required │
└──────────────────┘
| Outcome | Action | Database | Alert |
|---|---|---|---|
| Verified (shares=0) | Position closed | status='closed', exit_verified=TRUE | None |
| Failed (shares>0) | Investigation required | status='open', exit_verified=FALSE | 🚨 CRITICAL |
| Error (query failed) | Retry on next cycle | No change | ⚠️ WARNING |
┌──────────────────────────────────────────────────────────────────────────┐
│ POSITION RECONCILIATION STATE MACHINE │
└──────────────────────────────────────────────────────────────────────────┘
┌──────────────────┐
│ LOAD_DB_POSITIONS│
│ │
│ Query open │
│ positions from │
│ trading_positions│
└────────┬─────────┘
│
▼
┌──────────────────┐
│ LOAD_IBKR_POS │
│ │
│ Query ib. │
│ positions() │
└────────┬─────────┘
│
▼
┌──────────────────┐
│ COMPARE │
│ │
│ For each DB pos: │
│ • Find in IBKR │
│ • Check shares │
│ For each IBKR: │
│ • Find in DB │
└────────┬─────────┘
│
┌────────────────────────┼────────────────────────┐
│ │ │
▼ ▼ ▼
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ ORPHANED │ │ MISMATCH │ │ EXTERNAL │
│ │ │ │ │ │
│ In DB but │ │ Shares │ │ In IBKR but │
│ not IBKR │ │ differ │ │ not in DB │
│ │ │ │ │ │
│ → Alert │ │ → Alert │ │ → Alert │
│ → Mark │ │ → Log │ │ → Log to │
│ orphaned │ │ → Manual fix │ │ external_ │
│ │ │ │ │ trades │
└──────────────┘ └──────────────┘ └──────────────┘
-- trading_positions
exit_verified BOOLEAN
exit_verified_at TIMESTAMPTZ
ibkr_position_at_exit NUMERIC(12,4)
last_reconciled_at TIMESTAMPTZ
reconciliation_status VARCHAR(20) -- 'synced', 'mismatch', 'orphaned', 'external'
-- trade_audit_log
ibkr_client_id INTEGER -- Bot uses clientId=1
-- New Tables
external_trades -- Log detected external trades
position_reconciliation_log -- Audit reconciliation runs
┌──────────────────────────────────────────────────────────────────────────┐
│ SIGNAL GENERATION STATE MACHINE │
└──────────────────────────────────────────────────────────────────────────┘
┌──────────────────┐
│ GET_EARNINGS │
│ │
│ Query earnings_ │
│ markets table │
└────────┬─────────┘
│
│ List of upcoming earnings
▼
┌──────────────────┐
│ FETCH_ORDERBOOKS │
│ │
│ Get Polymarket │
│ orderbook data │
└────────┬─────────┘
│
│ For each market
▼
┌──────────────────┐
│CALC_CONVICTION │
│ │
│ Conviction = │
│ (YES bid + ask)/2│
└────────┬─────────┘
│
┌────────────────┴────────────────┐
│ │
│ 70% ≤ Conviction │ Conviction ≤ 30%
│ (LONG signal) │ (SHORT signal)
▼ ▼
┌──────────────────┐ ┌──────────────────┐
│ VALIDATE_LONG │ │ VALIDATE_SHORT │
│ │ │ │
│ • Check spread │ │ • Check spread │
│ • Check volume │ │ • Check volume │
│ • Check timing │ │ • Calc confidence│
│ │ │ (1 - conviction) │
└────────┬─────────┘ └────────┬─────────┘
│ │
│ Valid │ Valid
▼ ▼
┌──────────────────┐ ┌──────────────────┐
│ CLASSIFY_MCAP │ │ CLASSIFY_MCAP │
│ │ │ │
│ • >$100B = LARGE │ │ • >$100B = LARGE │
│ • $10-100B = MID │ │ • $10-100B = MID │
│ • <$10B = SMALL │ │ • <$10B = SMALL │
└────────┬─────────┘ └────────┬─────────┘
│ │
└─────────────┬───────────────────┘
│
▼
┌──────────────────┐
│ CALC_PRIORITY │
│ │
│ Market Cap + │
│ Conviction + │
│ Volume → Score │
│ (0-8, #313) │
└────────┬─────────┘
│
┌────────────────┴────────────────┐
│ │
│ Score > 0 │ Score == 0
▼ ▼
┌──────────────────┐ ┌──────────────────┐
│ CREATE_SIGNAL │ │ SKIP │
│ │ │ │
│ TradingSignal │ │ Log reason: │
│ dataclass │ │ • Small cap │
│ populated │ │ • NYSE small │
└────────┬─────────┘ │ • Low conviction │
│ └──────────────────┘
│
▼
┌──────────────────┐
│ PRIORITIZE │
│ │
│ Sort by priority │
│ Filter SKIP │
│ Return list │
└──────────────────┘
┌──────────────────────────────────────────────────────────────────────────┐
│ SIGNAL DIRECTION STATE MACHINE │
└──────────────────────────────────────────────────────────────────────────┘
┌──────────────────┐
│ CHECK_CONVICTION │
│ │
│ Input: conviction│
│ (0.0 - 1.0) │
└────────┬─────────┘
│
┌─────────────────────────┼─────────────────────────┐
│ │ │
│ conviction ≥ 0.70 │ 0.30 < conv < 0.70 │ conviction ≤ 0.30
│ (Beat expected) │ (No edge) │ (Miss expected)
▼ ▼ ▼
┌──────────────────┐ ┌──────────────────┐ ┌──────────────────┐
│ LONG │ │ NO_SIGNAL │ │ SHORT │
│ │ │ │ │ │
│ • BUY stock │ │ Skip this market │ │ • SELL stock │
│ • Stop: 3/4/5% │ │ No trading edge │ │ • Stop: 3/4/5% │
│ • Exit: +move │ │ │ │ • Exit: +move │
└──────────────────┘ └──────────────────┘ └──────────────────┘
Stop levels: 3% / 4% / 5% by mcap tier, placed as STP-LMT orders (Findings #202 / #179).
┌──────────────────────────────────────────────────────────────────────────┐
│ EARNINGS TIMING STATE MACHINE │
└──────────────────────────────────────────────────────────────────────────┘
┌──────────────────┐
│ DETERMINE_TIMING │
│ │
│ Input: endDate │
│ from Polymarket │
└────────┬─────────┘
│
Priority 1: Check earnings_timing.py (centralized)
│
┌───────────────────┴───────────────────┐
│ │
│ Found in lookup │ Not in lookup
▼ ▼
┌──────────────────┐ ┌──────────────────┐
│ USE_KNOWN_TIMING │ │ INFER_FROM_TIME │
│ │ │ │
│ e.g., JPM → BMO │ │ Parse endDate │
│ e.g., NFLX → AMC │ │ UTC hour │
└──────────────────┘ └────────┬─────────┘
│
┌────────────────────────┼────────────────────────┐
│ │ │
│ hour < 15 UTC │ hour ≥ 21 UTC │ else
│ (before 11 AM ET) │ (after 5 PM ET) │
▼ ▼ ▼
┌──────────────────┐ ┌──────────────────┐ ┌──────────────────┐
│ BMO │ │ AMC │ │ TBD │
│ │ │ │ │ │
│ Before Market │ │ After Market │ │ Ambiguous │
│ Open │ │ Close │ │ Fallback to Yahoo│
│ │ │ │ │ │
│ Entry: 3:58 PM │ │ Entry: 10:34 AM │ │ Entry: TBD │
│ Exit: 10:32 AM │ │ Exit: 3:57 PM │ │ │
└──────────────────┘ └──────────────────┘ └──────────────────┘
┌──────────────────────────────────────────────────────────────────────────┐
│ RISK LEVEL STATE MACHINE │
└──────────────────────────────────────────────────────────────────────────┘
┌──────────────────┐
│ NORMAL │
│ │
│ • Full trading │
│ • 100% sizing │
│ • VIX < 20 │
└────────┬─────────┘
│
│ VIX > 20 OR Losses > 1%
▼
┌──────────────────┐
│ ELEVATED │
│ │
│ • 75% sizing │
│ • VIX 20-25 │
│ • Daily loss 1-2%│
└────────┬─────────┘
│
│ VIX > 25 OR Losses > 2%
▼
┌──────────────────┐
│ HIGH │
│ │
│ • 50% sizing │
│ • VIX 25-30 │
│ • Daily loss 2-3%│
│ • Minimal new │
└────────┬─────────┘
│
│ VIX > 30 OR Losses > 3%
▼
┌──────────────────┐
│ CRITICAL │
│ │
│ • No new trades │
│ • VIX > 30 │
│ • Daily loss >3% │
│ • Circuit breaker│
└──────────────────┘
Recovery Path (when conditions improve):
CRITICAL → HIGH → ELEVATED → NORMAL
(Gradual de-escalation with cooldown periods)
┌──────────────────────────────────────────────────────────────────────────┐
│ CIRCUIT BREAKER STATE MACHINE │
└──────────────────────────────────────────────────────────────────────────┘
┌──────────────────┐
│ INACTIVE │
│ │
│ No breakers │
│ Normal trading │
└────────┬─────────┘
│
┌────────────────────────────┼────────────────────────────┐
│ │ │
│ Daily Loss > 3% │ Drawdown > 10% │ VIX > 30
▼ ▼ ▼
┌───────────────┐ ┌───────────────┐ ┌───────────────┐
│ DAILY_LOSS │ │ DRAWDOWN │ │ VIX │
│ │ │ │ │ │
│ Resume: EOD │ │ Resume: Manual│ │ Resume: <25 │
└───────────────┘ └───────────────┘ └───────────────┘
│ │ │
│ Consec. Loss > 3 │ Slippage > 1% │ Manual
▼ ▼ ▼
┌───────────────┐ ┌───────────────┐ ┌───────────────┐
│CONSEC_LOSS │ │ EXEC_QUALITY │ │ MANUAL_PAUSE │
│ │ │ │ │ │
│ Resume: 24h │ │ Resume: 1h │ │ Resume: Manual│
└───────────────┘ └───────────────┘ └───────────────┘
│
▼
┌──────────────────┐
│ BREAKER_ACTIVE │
│ │
│ • No new trades │
│ • Monitor only │
│ • Log all events │
│ • Send alerts │
└────────┬─────────┘
│
│ resume_at reached OR manual clear
▼
┌──────────────────┐
│ RESUMING │
│ │
│ • Clear breaker │
│ • Log recovery │
│ • Resume trading │
└────────┬─────────┘
│
▼
┌──────────────────┐
│ INACTIVE │
└──────────────────┘
┌──────────────────────────────────────────────────────────────────────────┐
│ POSITION SIZING STATE MACHINE │
└──────────────────────────────────────────────────────────────────────────┘
┌──────────────────┐
│ CHECK_CAPITAL │
│ │
│ Get available │
│ capital from IBKR│
└────────┬─────────┘
│
▼
┌──────────────────┐
│ CHECK_EXPOSURE │
│ │
│ Current exposure │
│ vs 1.40x cap │
└────────┬─────────┘
│
┌────────────────┴────────────────┐
│ │
│ Exp < 1.40x cap │ Exp ≥ 1.40x cap
▼ ▼
┌──────────────────┐ ┌──────────────────┐
│ CHECK_MARKET_CAP │ │ REJECT │
│ │ │ │
│ Size by tier: │ │ Max exposure │
│ • LARGE: 30% │ │ reached │
│ • MID: 22% │ │ │
│ • SMALL: 15% │ └──────────────────┘
└────────┬─────────┘
│
▼
┌──────────────────┐
│ APPLY_MODIFIERS │
│ │
│ • Risk level │
│ • Trading mode │
│ • BMO reservation│
└────────┬─────────┘
│
▼
┌──────────────────┐
│ FINAL_SIZE │
│ │
│ Calculate shares │
│ Round to whole │
│ Min 1 share │
└──────────────────┘
Exposure cap: uniform 1.40 across regimes (Finding #317). The legacy
MAX_TOTAL_EXPOSURE_PCT(the old 70% limit) is vestigial (Finding #315). Sizing tiers: Large 30% / Mid 22% / Small 15% (Finding #211).
┌──────────────────────────────────────────────────────────────────────────┐
│ BATCH ORDER MANAGER STATE MACHINE │
└──────────────────────────────────────────────────────────────────────────┘
┌──────────────────┐
│ INITIALIZE │
│ │
│ Generate batch_id│
│ Record start time│
└────────┬─────────┘
│
▼
┌──────────────────┐
│ CALC_SIZES │
│ │
│ Fair allocation │
│ by priority & │
│ market cap │
└────────┬─────────┘
│
▼
┌──────────────────┐
│ SUBMIT_ORDERS │
│ │
│ Sequential submit│
│ 50ms between │
│ orders │
└────────┬─────────┘
│
│ All orders submitted
▼
┌──────────────────┐
│ MONITOR_FILLS │
│ │
│ Parallel monitor │
│ 12 sec timeout │
│ per order │
└────────┬─────────┘
│
┌────────────────────┼────────────────────┐
│ │ │
│ All filled │ Some timeout │ All timeout
▼ ▼ ▼
┌──────────────────┐ ┌──────────────────┐ ┌──────────────────┐
│ COMPLETE │ │ MARKET_FALLBACK │ │ ALL_FALLBACK │
│ │ │ │ │ │
│ All LIMIT fills │ │ Cancel unfilled │ │ All went to │
│ Record results │ │ Submit MARKET │ │ MARKET │
└──────────────────┘ │ for timeout │ └────────┬─────────┘
└────────┬─────────┘ │
│ │
▼ │
┌──────────────────┐ │
│ MARKET_MONITOR │ │
│ │ │
│ Wait for MARKET │ │
│ fills (instant) │ │
└────────┬─────────┘ │
│ │
└────────────────────┤
│
▼
┌──────────────────┐
│ FINALIZE │
│ │
│ • Place stop-loss│
│ • Update DB │
│ • Send alerts │
│ • Return results │
└──────────────────┘
┌──────────────────────────────────────────────────────────────────────────┐
│ BATCH TYPE STATE MACHINE │
└──────────────────────────────────────────────────────────────────────────┘
┌──────────────────┐
│ DETERMINE_TYPE │
│ │
│ Input: action │
│ from orchestrator│
└────────┬─────────┘
│
┌─────────────────────────┼─────────────────────────┐
│ │ │
│ New positions │ Scheduled exits │ Earnings detected
▼ ▼ ▼
┌──────────────────┐ ┌──────────────────┐ ┌──────────────────┐
│ BATCH_ENTRY │ │ BATCH_EXIT │ │ BATCH_INSTANT_ │
│ │ │ │ │ EXIT │
│ • BUY orders │ │ • SELL orders │ │ │
│ • Attach stops │ │ • Cancel stops │ │ • MARKET orders │
│ • Pre-calc sizes │ │ • Multiple exits │ │ • No stops │
│ • 12s timeout │ │ • 12s timeout │ │ • Immediate │
└──────────────────┘ └──────────────────┘ └──────────────────┘
┌──────────────────────────────────────────────────────────────────────────┐
│ GATEWAY CONNECTION STATE MACHINE │
└──────────────────────────────────────────────────────────────────────────┘
┌──────────────────┐
│ UNKNOWN │
│ │
│ Initial state │
│ before first │
│ check │
└────────┬─────────┘
│
│ First health check
▼
┌────────────────┴────────────────┐
│ │
│ Connection successful │ Connection failed
▼ ▼
┌──────────────────┐ ┌──────────────────┐
│ CONNECTING │ │ ERROR │
│ │ │ │
│ Handshake in │ │ • Log error │
│ progress │ │ • Send alert │
└────────┬─────────┘ │ • Retry later │
│ └────────┬─────────┘
│ Authenticated │
▼ │
┌──────────────────┐ │
│ CONNECTED │ │
│ │ │
│ • API ready │ │
│ • Account data │ │
│ • Trading allowed│ │
└────────┬─────────┘ │
│ │
│ Connection lost │
▼ │
┌──────────────────┐ │
│ DISCONNECTED │◀──────────────────────┘
│ │
│ • Alert sent │
│ • Positions safe │
│ • Stops active │
└────────┬─────────┘
│
│ Retry connection
▼
┌──────────────────┐
│ CONNECTING │ (Loop back)
└──────────────────┘
┌──────────────────────────────────────────────────────────────────────────┐
│ GATEWAY SESSION STATE MACHINE │
│ Updated: January 26, 2026 (v3.0) │
└──────────────────────────────────────────────────────────────────────────┘
WEEKLY CYCLE (Sunday 6:00 UTC = 10:00 AM Abu Dhabi)
────────────────────────────────────────────────────
** 2FA REQUIRED - User must approve on IBKR app **
┌──────────────────┐
│ SESSION_ACTIVE │◀────────────────────────────────┐
│ │ │
│ • Trading allowed│ │
│ • API connected │ │
│ • Session token │ │
│ valid (7 days) │ │
└────────┬─────────┘ │
│ │
│ Sunday 6:00 UTC: IBKR resets all tokens │
▼ │
┌──────────────────┐ │
│ SESSION_EXPIRED │ │
│ │ │
│ • Weekly token │ │
│ expiry (IBKR) │ │
│ • 2FA required │ │
└────────┬─────────┘ │
│ │
│ IBC enters credentials automatically │
▼ │
┌──────────────────┐ │
│ AWAITING_2FA │ │
│ │ │
│ • 2FA notification│ │
│ sent to phone │ │
│ • 180 sec timeout│ │
└────────┬─────────┘ │
│ │
┌────────────┴────────────┐ │
│ │ │
│ 2FA approved │ 2FA timeout │
▼ ▼ │
┌──────────────────┐ ┌──────────────────┐ │
│ LOGIN_SUCCESS │ │ LOGIN_FAILED │ │
│ │ │ │ │
│ • New session │ │ • Retry in 120s │ │
│ • Token valid │ │ • Send alert │ │
│ • Resume trading │ │ • Manual VNC │ │
└────────┬─────────┘ └────────┬─────────┘ │
│ │ │
│ │ ReloginAfter...Timeout=yes │
│ └───────────────────────────────│
│ │
└─────────────────────────────────────────────────────┘
DAILY CYCLE (Mon-Sat 6:00 UTC = 10:00 AM Abu Dhabi) - SESSION PRESERVATION
──────────────────────────────────────────────────────────────────────────
** NO 2FA - IBC's AutoRestart is in-process and keeps the session (#437) **
┌──────────────────┐
│ SESSION_ACTIVE │
│ │
│ • Session token │
│ valid │
└────────┬─────────┘
│
│ 6:00 UTC: IBC "Re-starting session" (same JVM)
│ :4001 closed ~20-40 s
▼
┌──────────────────┐
│ RESTARTING │
│ │
│ • No 2FA │
│ • ibkr-monitor │
│ SLA 180 s │
└────────┬─────────┘
│
│ "Login has completed" + :4001 back
│ trader reattaches / attach-bounces once (#441)
▼
┌──────────────────┐
│ SESSION_ACTIVE │
│ │
│ • Original token │
│ PRESERVED │
│ • NO 2FA needed │
│ • Trading resumes│
└──────────────────┘
No Telegram on a healthy restart. :4001 still down after 180 s → one
ibkr-monitor page (lever: systemctl restart ibgateway-ibc), page-only (#448).
History (retired #476): gateway_restart_manager.sh waited at 05:58 for a
"dual process" and killed the newer one; the restart is in-process, so
that state never occurred.
OVERNIGHT RECOVERY (Smart Restart - Added Jan 26, 2026)
────────────────────────────────────────────────────────
** Handles IBKR's internal shutdown at ~23:45 UTC (3:45 AM Abu Dhabi) **
┌──────────────────┐
│ SESSION_ACTIVE │
│ │
│ • Trading complete│
│ • Night time │
└────────┬─────────┘
│
│ 23:45 UTC (3:45 AM): IBKR internal shutdown
│ Gateway exits with status 0
▼
┌──────────────────┐
│ GATEWAY_STOPPED │
│ │
│ • IBC exits │
│ • systemd triggers│
│ Restart=always │
└────────┬─────────┘
│
│ ibc_smart_restart.sh checks current hour
▼
┌──────────────────┐
│ SMART_WAIT │ (Hour 22-05 UTC only)
│ │
│ • Outside active │
│ hours detected │
│ • Telegram alert │
│ • Sleep until │
│ 05:00 UTC │
└────────┬─────────┘
│
│ 05:00 UTC (09:00 AM Abu Dhabi): Wake up
▼
┌──────────────────┐
│ STARTING_IBC │
│ │
│ • Start Gateway │
│ • IBC enters │
│ credentials │
└────────┬─────────┘
│
│ IBKR sends 2FA (if Sunday or session expired)
▼
┌──────────────────┐
│ AWAITING_2FA │
│ │
│ • Approve on │
│ IBKR app │
│ • 3 min window │
└────────┬─────────┘
│
▼
┌──────────────────┐
│ SESSION_ACTIVE │
│ │
│ • Ready before │
│ market open │
└──────────────────┘
Telegram: "⚠️ Gateway restarting at 09:00 AM. Please approve 2FA."
§8 redirect: the operative health-check architecture is now
src/data_tracker/integrity_monitor.pyrunning underpolymarket-integrity-monitor.service. State below is retained as historical reference for the v2/v3 lifecycle that preceded it. The current monitor uses a declarative-rule model rather than the per-service state-machine model below — ~51 rules across 6 categories (was ~47 pre-#383, 37, and 34 pre-#269/#291) (freshness,null_rate,systemd,artifact,storage,meta), each withok/warn/fail/unknownstatus persisted to theintegrity_statustable. Seedocs/DATA_INTEGRITY.md§2 for architecture,docs/OPERATIONS.md§8.A for runbook.
┌──────────────────────────────────────────────────────────────────────────┐
│ WATCHDOG SERVICE HEALTH STATE MACHINE │
└──────────────────────────────────────────────────────────────────────────┘
┌──────────────────┐
│ HEALTHY │
│ │
│ • Service running│
│ • Data fresh │
│ • No errors │
└────────┬─────────┘
│
│ Check fails
▼
┌──────────────────┐
│ DEGRADED │
│ │
│ • 1-2 failures │
│ • Log warning │
│ • No alert yet │
└────────┬─────────┘
│
│ 3+ consecutive failures
▼
┌──────────────────┐
│ UNHEALTHY │
│ │
│ • Send alert │
│ • Attempt restart│
│ • Log critical │
└────────┬─────────┘
│
┌────────────────┴────────────────┐
│ │
│ Restart successful │ Restart failed
▼ ▼
┌──────────────────┐ ┌──────────────────┐
│ RECOVERING │ │ CRITICAL │
│ │ │ │
│ • Watching for │ │ • 3+ restart │
│ stability │ │ attempts │
│ • No new restarts│ │ • Escalate alert │
│ for 5 min │ │ • Manual review │
└────────┬─────────┘ └──────────────────┘
│
│ Stable for 5 min
▼
┌──────────────────┐
│ HEALTHY │
│ │
│ Recovery complete│
│ Send recovery │
│ notification │
└──────────────────┘
┌──────────────────────────────────────────────────────────────────────────┐
│ ALERT ESCALATION STATE MACHINE │
└──────────────────────────────────────────────────────────────────────────┘
┌──────────────────┐
│ NONE │
│ │
│ All systems OK │
└────────┬─────────┘
│
│ Minor issue detected
▼
┌──────────────────┐
│ INFO │
│ │
│ • Log only │
│ • No notification│
│ • e.g., brief │
│ spike │
└────────┬─────────┘
│
│ Issue persists > 5 min
▼
┌──────────────────┐
│ WARNING │
│ │
│ • Telegram alert │
│ • ⚠️ icon │
│ • Auto-restart │
│ attempted │
└────────┬─────────┘
│
│ Restart fails OR critical service
▼
┌──────────────────┐
│ CRITICAL │
│ │
│ • Urgent alert │
│ • 🚨 icon │
│ • Repeat every │
│ 15 min │
│ • Manual review │
└────────┬─────────┘
│
│ Issue resolved
▼
┌──────────────────┐
│ RECOVERY │
│ │
│ • ✅ notification│
│ • Log recovery │
│ • Clear counters │
└────────┬─────────┘
│
▼
┌──────────────────┐
│ NONE │
└──────────────────┘
Implementation Note (Phase 4B+4D - Feb 7, 2026): The position lifecycle is formalized in src/earnings/position_state.py as a PositionState enum with validated transitions: PENDING -> OPEN -> CLOSING -> CLOSED (or FAILED). IBKR is the source of truth for live state via IBKRPositionCache. Stop fills are detected in real-time via IBKR orderStatusEvent callbacks through the EventBus (Phase 4D), with periodic reconciliation as backup.
┌──────────────────────────────────────────────────────────────────────────┐
│ POSITION LIFECYCLE STATE MACHINE │
└──────────────────────────────────────────────────────────────────────────┘
┌──────────────────┐
│ SIGNAL_GEN │
│ │
│ Signal generated │
│ for earnings │
└────────┬─────────┘
│
│ Risk check passed
▼
┌──────────────────┐
│ SCHEDULED │
│ │
│ Entry scheduled │
│ for specific time│
└────────┬─────────┘
│
│ Entry time reached
▼
┌──────────────────┐
│ ENTERING │
│ │
│ Order submitted │
│ Waiting for fill │
└────────┬─────────┘
│
┌────────────────┴────────────────┐
│ │
│ Fill successful │ Fill failed
▼ ▼
┌──────────────────┐ ┌──────────────────┐
│ ACTIVE │ │ FAILED │
│ │ │ │
│ • Stop-loss set │ │ Log error │
│ • Exit scheduled │ │ Alert sent │
│ • Monitoring │ └──────────────────┘
└────────┬─────────┘
│
┌────────────┼────────────────────────┐
│ │ │
│ Stop-loss │ Earnings │ Scheduled
│ triggered │ detected wrong │ exit time
▼ ▼ ▼
┌───────────┐ ┌──────────────┐ ┌──────────────────┐
│ STOPPED │ │INSTANT_EXIT │ │ SCHED_EXIT │
│ │ │ │ │ │
│ Stop hit │ │ Wrong predict│ │ Normal exit │
│ Loss taken│ │ Fast exit │ │ Take profit/loss │
└─────┬─────┘ └──────┬───────┘ └────────┬─────────┘
│ │ │
└──────────────┴─────────────────────┘
│
▼
┌──────────────────┐
│ CLOSED │
│ │
│ • P&L calculated │
│ • DB updated │
│ • Audit logged │
│ • Capital freed │
└──────────────────┘
┌──────────────────────────────────────────────────────────────────────────┐
│ EXIT TYPE DECISION STATE MACHINE │
└──────────────────────────────────────────────────────────────────────────┘
┌──────────────────┐
│ ACTIVE_POS │
│ │
│ Position open │
│ Monitoring... │
└────────┬─────────┘
│
┌───────────────────────────────┼───────────────────────────────┐
│ │ │
│ Price hits stop │ Earnings released │ Exit time
│ │ │ reached
▼ ▼ ▼
┌───────────────┐ ┌───────────────┐ ┌───────────────┐
│ STOP_LOSS │ │ CHECK_RESULT │ │ SCHED_EXIT │
│ │ │ │ │ │
│ IBKR native │ │ Compare actual│ │ At scheduled │
│ stop triggers │ │ vs consensus │ │ exit time │
│ automatically │ │ EPS │ │ │
└───────┬───────┘ └───────┬───────┘ └───────┬───────┘
│ │ │
│ ┌────────┴────────┐ │
│ │ │ │
│ │ Prediction │ Prediction │
│ │ correct │ WRONG │
│ ▼ ▼ │
│ ┌───────────────┐ ┌───────────────┐ │
│ │ HOLD_TO_EXIT │ │ INSTANT_EXIT │ │
│ │ │ │ │ │
│ │ Keep to │ │ MARKET order │ │
│ │ scheduled exit│ │ immediately │ │
│ └───────┬───────┘ └───────┬───────┘ │
│ │ │ │
│ │ │ │
└───────────────┴─────────────────┴─────────────────┘
│
▼
┌───────────────┐
│ CLOSED │
│ │
│ Exit complete │
│ Record result │
└───────────────┘
┌──────────────────────────────────────────────────────────────────────────┐
│ DATA COLLECTOR STATE MACHINE │
└──────────────────────────────────────────────────────────────────────────┘
┌──────────────────┐
│ INITIALIZING │
│ │
│ • Load config │
│ • Connect to DB │
│ • Verify schema │
└────────┬─────────┘
│
▼
┌──────────────────┐
│ SYNC_MARKETS │
│ │
│ • Fetch markets │
│ from Gamma API │
│ • Update markets │
│ table │
└────────┬─────────┘
│
▼
┌──────────────────┐◀─────────────────┐
│ COLLECTING │ │
│ │ │
│ For each market: │ │
│ • Orderbooks │ │
│ • Prices │ │
│ • Trades │ │
└────────┬─────────┘ │
│ │
│ Cycle complete │
▼ │
┌──────────────────┐ │
│ SLEEPING │──────────────────┘
│ │ Sleep interval
│ Wait for next │ (15 min for
│ collection cycle │ market sync)
└──────────────────┘
┌──────────────────────────────────────────────────────────────────────────┐
│ EARNINGS MARKET SYNC STATE MACHINE │
└──────────────────────────────────────────────────────────────────────────┘
┌──────────────────┐
│ FETCH_EVENTS │
│ │
│ GET /events/ │
│ pagination? │
│ tag_id=1013 │
└────────┬─────────┘
│
│ Paginate through all
▼
┌──────────────────┐
│ EXTRACT_DATA │
│ │
│ • Parse ticker │
│ • Parse date │
│ • Parse timing │
│ • Get condition │
│ IDs │
└────────┬─────────┘
│
▼
┌──────────────────┐
│ SYNC_TO_DB │
│ │
│ UPSERT into │
│ earnings_markets │
│ table │
└────────┬─────────┘
│
│ Every 1 hour
▼
┌──────────────────┐
│ COMPLETE │
│ │
│ Log stats │
│ Schedule next run│
└──────────────────┘
| Component | States | Transitions | Key Events |
|---|---|---|---|
| TradingOrchestrator | 6 | 12 | Market open/close, signals, errors |
| TradingMode | 4 | 5 | Trade count, manual toggle |
| MarketStatus | 4 | 4 | Time-based (4/9:30/16/20) |
| OrderStatus | 5 | 6 | Submit, fill, cancel, fail |
| RiskLevel | 4 | 6 | VIX, P&L, circuit breakers |
| CircuitBreaker | 2 | 7 | Loss, drawdown, VIX, manual |
| ConnectionState | 5 | 8 | Connect, disconnect, error |
| ServiceHealth | 4 | 6 | Check, fail, restart, recover |
| Position | 6 | 8 | Entry, exit, stop, close |
| BatchOrder | 4 | 5 | Submit, fill, timeout, fallback |
Signal Generated → Risk Check → Entry Scheduled → Entry Filled →
Stop-Loss Set → Earnings Released (correct) → Scheduled Exit → Closed
Position Active → Earnings Released (wrong) → Instant Exit Triggered →
MARKET Order → Filled → Closed
Position Active → Price Drops → Stop Triggered (IBKR) →
Filled at Stop → Closed
Trade Executed → Loss Recorded → Daily Loss > 3% →
Circuit Breaker DAILY_LOSS → No New Trades → EOD Reset → Resume
Document generated: January 11, 2026 System Version: Polymarket Earnings Trading System v4.1