Skip to content

14 — Operating Modes

1. Why modes are a state machine, not a setting

Six modes span the distance between "read historical data" and "spend my money without asking." That is not a dropdown. Treating it as one invites the failure this whole system is built to avoid: a mode changing by accident, by bug, or by a click made without understanding what it authorises.

So modes are modelled as a state machine with explicit, auditable transitions, three properties of which are load-bearing:

  1. Escalation requires a ceremony; de-escalation is instant. Moving toward automation takes deliberate steps and satisfied preconditions. Moving away takes one tap and never fails.
  2. Capability is granted by the mode, not checked against it. A mode does not "allow" live orders past a check — in lower modes the live execution adapter is not constructed at all, so there is nothing to bypass.
  3. Every transition is a ledger event, hash-chained alongside trades, with the actor, timestamp, and preconditions recorded.

2. The six modes

# Mode Money Broker Who decides Who executes
1 Backtest None None Strategy, historically Simulated fills
2 Paper Virtual None You, or a strategy Simulated fills
3 Recommend None Read-only AI proposes Nobody — output only
4 Manual live Real IBKR AI proposes, you approve each order Broker, after your approval
5 Semi-automated Real IBKR AI, within hard limits Broker, automatically inside limits
6 Automated Real IBKR AI, within hard limits Broker, automatically

Modes 1–3 are the complete product for a user who never enables real money. Modes 4–6 are the optional continuation.

Mode 1 — Backtest

Replays the point-in-time store through the same strategy, compliance, risk, and fill code the live path uses (08). No broker adapter is constructed. Its purpose is falsification: to find out that an idea would not have worked.

Mode 2 — Paper (built — see the running app)

A simulated brokerage account with the realism described in 06: next-session fills, spread, square-root market impact, participation caps, dividends, corporate actions, and 0% on cash. This is where a track record is earned.

Mode 3 — Recommend

The full agent pipeline runs and produces recommendations with complete reasoning (04), but no order object is created. The broker connection, if configured, is read-only: positions and balances flow in for portfolio context; nothing flows out. This is the first mode where a real IBKR account may be connected, and it is deliberately the one where the outbound path does not exist.

Mode 4 — Manual live

The AI prepares an order; you approve it individually. Approval requires a fresh authentication assertion and shows the full order ticket, the compliance verdict, the risk plan, and the post-trade portfolio state. An unapproved order expires rather than resting — a stale approval prompt answered an hour later is answering a question about a market that has moved.

Mode 5 — Semi-automated

The AI executes without per-order approval, but only inside limits you set: maximum order value, maximum daily notional, maximum position and sector weight, permitted markets and sectors, and daily/weekly/monthly loss limits. Anything outside the envelope falls back to Mode 4 behaviour for that order — it asks. The envelope is enforced at the adapter layer, below and independent of the risk engine, so a risk-engine bug cannot widen it.

Mode 6 — Automated

As Mode 5 with a wider envelope and no fallback-to-ask. Requires periodic re-confirmation — it cannot be enabled once and forgotten, because an automation you have stopped thinking about is the one that hurts you.

3. Transitions

stateDiagram-v2
    [*] --> Backtest
    Backtest --> Paper: no gate
    Paper --> Recommend: no gate
    Recommend --> ManualLive: ENABLEMENT CEREMONY
    ManualLive --> SemiAuto: track record + limits set
    SemiAuto --> Automated: explicit opt-in + re-confirmation schedule

    Automated --> SemiAuto: instant
    SemiAuto --> ManualLive: instant
    ManualLive --> Recommend: instant, revokes credentials
    Recommend --> Paper: instant
    Paper --> Backtest: instant

    Automated --> Recommend: EMERGENCY STOP
    SemiAuto --> Recommend: EMERGENCY STOP
    ManualLive --> Recommend: EMERGENCY STOP

Note the asymmetry. Every upward edge carries a precondition; every downward edge is unconditional and immediate. The emergency stop collapses straight to Recommend from any live mode, cancels working orders, and revokes stored broker credentials — not merely "stops sending."

The enablement ceremony (Recommend → Manual live)

Crossing into real money once, deliberately:

  1. Track record — at least 12 months of paper trading under the current model and rule-pack versions, with the reliability diagram shown honestly whatever it says (11).
  2. Benchmark — paper performance clears the naive compliant equal-weight benchmark after costs. Beating cash is not the bar; beating the simple alternative is.
  3. Correctness — zero unresolved defects in ledger, compliance, or risk.
  4. Acknowledgement — a written statement, typed not clicked, of what can be lost.
  5. Fresh authentication and entry of IBKR credentials directly into encrypted storage.
  6. Cooling-off period — a mandatory delay between enabling and the first live order. The point is to separate the decision from the impulse.

Failing any precondition blocks the transition and says which one failed.

4. What each mode may construct

The mechanism that makes modes real rather than advisory:

def build_execution_path(mode: Mode) -> ExecutionPath:
    """The only place a live adapter can come into existence."""
    if mode in (Mode.BACKTEST, Mode.PAPER):
        return SimulatedExecution()
    if mode is Mode.RECOMMEND:
        return NoExecution(broker=IBKRReadOnly() if configured else None)
    # Live modes only; requires credentials that lower modes cannot decrypt.
    return LiveExecution(
        adapter=IBKRAdapter(credentials=vault.unlock(mode)),
        caps=HardCaps.for_mode(mode),
        approval=PerOrderApproval() if mode is Mode.MANUAL_LIVE else None,
    )

In Modes 1–3 no object capable of sending an order exists in the process. This is the same argument as ADR-0004 on compliance and ADR-0007 on broker isolation: a capability that is absent cannot be reached by a bug, a prompt injection, or a mistaken click.

Credentials reinforce it. The vault key derivation includes the mode, so a process running in Recommend cannot decrypt live credentials even if it somehow tried.

5. Mode is visible, always

Every screen carries an unmistakable mode indicator, and the four live-capable modes use visually distinct treatments rather than a subtle label. The moment a user forgets which mode they are in, every safety property above becomes theoretical.

Mode Indicator
Backtest Grey chip, "BACKTEST — historical replay"
Paper Amber chip, "PAPER — virtual money"
Recommend Teal chip, "RECOMMEND — no orders sent"
Manual live Red chip, "LIVE — you approve every order"
Semi-automated Red chip, "LIVE — auto within limits", with remaining daily notional
Automated Red chip, "LIVE — automated", with the next re-confirmation date

The emergency stop is present in all modes, in the same place.

6. Where the current build sits

The running application implements Mode 2 end to end, and Portfolio.mode has exactly one legal value. Modes 1 and 3 are designed and unbuilt; Modes 4–6 are designed, unbuilt, and gated behind the ceremony above.

The roadmap sequence is unchanged: 12 builds Backtest and Recommend before any live mode is written, because the track record that gates live trading can only be produced by the modes below it.