Trading Modes
Every strategy in the bot moves through three distinct modes before capital is at risk. The transition is strictly one-way: DRY_RUN → SHADOW → LIVE. Skipping a step is not allowed — you must earn each promotion.
🔵 DRY_RUN
Default starting state for every strategy
- Signals computed normally
- No real orders placed
- Simulated fills at scanner prices
- Trade records stored with
DR_prefix - P&L tracked but not real money
- Full exit logic runs (profit/stop/IV)
Purpose: Validate strategy edge over real market conditions with zero financial exposure.
🟡 SHADOW
Real orders + parallel dry-run record
- Real orders placed via broker
- Simultaneously writes a shadow dry-run record (
SHADOW_DR_) - Actual fills confirmed from broker
- Risk controls (kill-switch, margin, Greeks) all apply
- Shadow records excluded from the confidence gate
- Dashboard shows both real + shadow P&L
Purpose: Prove execution quality (fills, slippage, latency) at full scale before committing to live-only record-keeping.
🟢 LIVE
Full production mode
- Real orders placed via broker
- Single trade record — no parallel dry-run
- All risk controls and P&L reporting are real-money
- Kill-switch, drawdown caps, and Greeks gate all block live entries
- Operator must manually
/promote
Purpose: Normal operating mode once the strategy has demonstrated edge (DRY_RUN) and clean execution (SHADOW).
Mode Comparison
| Feature | 🔵 DRY_RUN | 🟡 SHADOW | 🟢 LIVE |
|---|---|---|---|
| Real broker orders placed | No | Yes | Yes |
| Fills simulated from scanner prices | Yes | No — actual fills | No — actual fills |
| Trade record tag prefix | DR_ | DR_ + shadow flag | no prefix |
| Kill-switch and drawdown caps apply | Kill-switch only | Yes | Yes |
| Portfolio Greeks gate blocks entry | No (surfaced only) | Yes | Yes |
| Margin check before entry | No | Yes (+10% buffer) | Yes (+10% buffer) |
| Counted in confidence gate | Yes | No (shadow excluded) | N/A |
| Telegram alerts on trades | Yes | Yes | Yes |
| Broker health downgrade applies | Allowed | Downgraded to dry-run | Downgraded to dry-run |
Promotion Path
To revert to DRY_RUN at any time: /revert <strategy>
Confidence Gate (DRY_RUN → SHADOW)
Before a strategy can enter SHADOW mode, it must pass an automated confidence check calculated over the most recent 15 trading days of dry-run records. The check rejects strategies that haven't traded enough or haven't been profitable enough to justify real capital.
Gate Thresholds
| Check | Requirement |
|---|---|
| Minimum closed trades | ≥ 3 trades over the 15-day window |
| Win rate | ≥ 60% of closed trades profitable |
| Data source | Dry-run records only — shadow records are excluded |
How to Check Gate Status
| Command | What it shows |
|---|---|
/confidence_report <strategy> | Day-by-day win rate breakdown for the last 15 trading days |
/golive_status | Current DRY_RUN / SHADOW / LIVE state plus one-line confidence summary for every strategy |
/shadow AI_MARKET and /promote AI_MARKET
both require the AI promotion report to pass — checking AI usefulness signals, DDC comparison,
error log, and API cost. Use /ai_promotion_report to inspect the full report.
Operator Commands
| Command | Transition | Notes |
|---|---|---|
/shadow <strategy> |
DRY_RUN → SHADOW | Blocked until confidence gate passes. Shows win-rate summary on success. |
/promote <strategy> |
SHADOW → LIVE | Manual operator decision only. Strategy must currently be in SHADOW. |
/revert <strategy> |
Any → DRY_RUN | Immediate. Resets shadow_since and promoted_at timestamps. |
/golive_status |
Read-only | Shows all strategies with icon, state, and confidence summary. |
/confidence_report <strategy> |
Read-only | Per-day breakdown for the 15-day window used by the gate. |
Walk-Through Examples
Example 1 — Promoting DC to Shadow
# After 15 trading days with ≥3 dry-run trades and ≥60% win rate:
/shadow DC
# Bot replies (if gate passes):
✅ DC → SHADOW
Win rate: 67% (10/15 trades, 15 days sampled)
Real orders will be placed next cycle; shadow dry-run records will be written.
# Check the state:
/golive_status
🔵 IC: DRY_RUN — 45% win rate (5/11 trades, 12d)
🟡 DC: SHADOW — 67% win rate (10/15 trades, 15d)
🟢 MDC: LIVE
Example 2 — Gate Blocked
/shadow DCS
# Bot replies (if gate fails):
❌ Confidence gate not met for DCS:
52% win rate over 15 sampled day(s) (<60% required)
# See the breakdown:
/confidence_report DCS
2026-06-01: 2 trades, 1 profitable
2026-06-02: 1 trade, 0 profitable
...
Total: 11 trades, 52% win rate — gate requires ≥60%
Example 3 — Shadow to Live
# After validating fill quality during SHADOW:
/promote DC
# Bot replies:
✅ DC → LIVE. Real orders from next cycle.
# Reverting if something looks wrong:
/revert DC
✅ DC → DRY_RUN. Reverted to simulation.
Example 4 — What changes at runtime
# DRY_RUN: scanner finds a signal at 09:47
[DC] DRY_RUN fill simulated — CE 24000 @ 89.50 / PE 24000 @ 91.20
Trade tag: DR_20260608_0947_DC_1 — no order sent to broker
# SHADOW: same signal next day
[DC] SHADOW — placing real IOC orders
CE 24000 filled @ 89.00 / PE 24000 filled @ 91.50 (actual fills)
Shadow dry-run record written (tag: SHADOW_DR_20260609_0947_DC_1)
Live record written (tracks real P&L)
# LIVE: same signal in production
[DC] LIVE — placing real IOC orders
CE 24000 filled @ 89.00 / PE 24000 filled @ 91.50
Single live record written
State Persistence
Go-live state is stored in arb_bot_records.sqlite3 under the go_live_state table.
On startup, the bot loads each strategy's state from SQLite. If no record exists, it seeds from the
*_DRY_RUN flags in Config. The state survives restarts and deploys — promoting
a strategy to LIVE persists across make deploy.
| Field | Meaning |
|---|---|
state | Current mode: DRY_RUN | SHADOW | LIVE |
shadow_since | ISO timestamp when strategy entered SHADOW (null otherwise) |
promoted_at | ISO timestamp when strategy was promoted to LIVE (null otherwise) |
*_DRY_RUN = True flags in config.py only set the initial state
when no SQLite record exists. Once a strategy has been promoted, its state is read from SQLite and the
config flag is ignored. To hard-reset a strategy back to DRY_RUN (e.g., after wiping the database),
ensure the flag is True before restarting.
Why Three Modes?
A single on/off switch for live trading creates a blind spot: you can never validate execution quality (fill rates, slippage, API latency) on paper alone. The three-mode design solves this:
- DRY_RUN validates signal quality — is the edge real?
- SHADOW validates execution quality — do orders fill as expected?
- LIVE is only reached after both validations pass.
The confidence gate prevents premature promotion based on luck (a handful of winning trades).
The manual /promote step ensures a human reviews execution before real P&L is at stake.