Skip to content

Live trading

Live trading places real orders on a real Interactive Brokers account (a U… id). The same strategy code that you backtested and paper-traded runs unchanged. Because this is real money, it sits behind multiple deliberate gates and a tighter risk profile.

Live trading is for a personal build you operate yourself. The sold/research edition ships with ATS_ENABLE_LIVE_TRADING=false — research and paper only.

  1. Edition flagATS_ENABLE_LIVE_TRADING must be true, or the Live tab doesn’t even appear.
  2. A separate live gateway — the live IB Gateway runs on its own port (ATS_IB_LIVE_PORT, default 4001) with the live account id (ATS_IB_LIVE_ACCOUNT_ID, a U… id — the guard rejects a DU-prefixed paper id here).
  3. An audited approve-to-live step — a strategy cannot trade live until you explicitly approve it, and that approval is recorded (GoLiveApproval) in the append-only audit log. The research ladder makes this an explicit step, not a default.

A Studio-generated strategy is no exception — it must clear the gauntlet and the approval like any other.

Nautilus’s RiskEngine runs inside the trading node and denies any order that breaches:

  • max notional per orderATS_LIVE_RISK_MAX_NOTIONAL_PER_ORDER (default 5000, deliberately tighter than paper’s 25000).
  • max order-submit rateATS_LIVE_RISK_MAX_ORDER_SUBMIT_RATE (default 2/00:00:01).

Denied orders never reach the broker. Raise these in backend/.env only once proven.

  • Kill switch — an operator control that cancels open orders, closes all positions, and stops the node once the account is actually flat (closing fills are asynchronous). If it isn’t flat within a 30-second grace window the node stops anyway — a kill never hangs — and startup reconciliation picks up any remainder on the next session.
  • Reconciliation — on connect, the node reconciles its orders/positions against the broker’s truth, so a restart can’t double-trade or lose track. If it comes up already holding open orders/positions, the session feed shows a “Recovered N open orders, M positions from the broker” notice — so recovery is visible, not silent.
  • Gateway resilience — a monitor watches gateway health and alerts on a healthy→broken transition; IBC handles the gateway’s nightly/weekly restarts.
  • Audit log — every order intent and security-relevant action is recorded, append-only.

The pre-trade risk engine is a per-order guard; the circuit breaker is a per-session one. It’s opt-in and off by default — arm it on the Paper/Live start form:

  • Triggers — halt when session drawdown exceeds X% below the run’s peak equity, and/or when the session loss exceeds $Y below its starting equity (measured from session start; there’s no calendar-day reset).
  • ActionFlatten (cancel orders + close positions, then stay halted) or Pause (deny new orders, hold positions). It fires once and stays tripped until you manually Resume or Stop — no auto-resume.
  • How it works — the alert relay already tracks each session’s peak/loss; on a breach it enqueues the flatten/pause onto the same control queue the manual kill switch uses, publishes a CircuitBreakerTripped event (the feed shows why), and pages Telegram. The running-session card shows the armed thresholds, or a red TRIPPED chip. Defaults for the form are ATS_CIRCUIT_BREAKER_* (see configuration).
  • Caveat — the peak/loss baseline re-derives from the first heartbeat after a worker restart, so a mid-session relay restart re-baselines the breaker.

The same strategy code, gated. Run one gateway at a time — paper and live share your IB username, and IB allows a single session.

  1. Validate on paper until you trust the behavior; confirm the Research ladder’s paper rung passes.

  2. Record your sign-off (audited; the live runner refuses to start without it):

    Terminal window
    cd backend
    uv run python -m ats.cli approve-live --strategy ibs_reversion \
    --instrument QQQ.NASDAQ --note "2w paper, 14 trades, matched backtest"

    (revoke-live removes it. See the admin CLI.)

  3. Configure — set ATS_IB_LIVE_ACCOUNT_ID (your U… id); review the ATS_LIVE_RISK_* caps; make sure 2FA is on.

  4. Swap gateways and start (start small, during market hours, watching the Live tab and the IB portal). Two equivalent paths, both behind the same gates:

    From the Live tab — the start panel shows the pre-flight checklist (edition flag, account config, per-sleeve approvals, gateway health), refuses while the IB paper session is running, and requires you to type the live account id into a confirmation dialog. The API validates the confirmation server-side, spawns the supervised runner, and audits who clicked; the runner then independently re-checks every gate before connecting (defense in depth — the browser is never trusted with the decision).

    From a terminal (automation/cron):

    Terminal window
    docker compose -f infra/docker-compose.yml --profile ib stop ib-gateway-paper
    docker compose -f infra/docker-compose.yml --profile ib-live up -d --wait
    cd backend && uv run python -m ats.live --strategy ibs_reversion \
    --instrument QQQ.NASDAQ --bar-spec 1-DAY-LAST --params '{"buy_threshold": 0.15}'

    The runner prints the session summary (account, params, risk caps, who approved) and requires you to type the live account id before anything connects (--i-understand <account-id> for supervised scripts). The Live tab mirrors the Paper tab — same kill switch (typed KILL confirmation in the UI), a separate Redis namespace, and a REAL MONEY badge.

Guards: the paper runner refuses ids that aren’t DU; the live runner refuses anything that isn’t a U… account and requires the typed confirmation. A live book (--sleeves-json) is allowed, but every sleeve must have its own approve-live sign-off (the gate loops over all of them).

Live runs as its own process (ats.live), or from the Live tab’s start panel (same shape as paper, pointed at the live gateway). Sessions, telemetry, controls, and history work identically to paper, and the page has the same anatomy — the status-card hero with the always-visible money strip, the equity chart and positions beside the live event stream, and the Performance tab with its CSV export (see the page, top to bottom). Live-only differences: the unmistakable REAL MONEY chip and red styling, the typed-KILL confirm, and no Fidelity tab (the scorecard is a paper-trading tool). The live leg also rolls into Home’s All accounts card whenever a live session heartbeats.

  • ARM64/Apple Silicon gateway image support is experimental; if the container misbehaves, enable Rosetta in Docker Desktop or run IB Gateway natively.
  • See the headless gateway GUI: with VNC_SERVER_PASSWORD set in backend/.env, uvx --from vncdotool vncdo -s 127.0.0.1::5900 -p "$VNC_PASS" capture shot.png (VNC is localhost-only).