← back to Zero Code Trading Bot

references/safety-model.md

53 lines

# Safety model — why this bot ships safe

A trading bot touches money, and money actions are Steve-gated. The design rule:
**the scaffold is never one typo away from spending real funds.** Everything below
is defense-in-depth so that "paper" stays paper until Steve deliberately, in
multiple explicit steps, decides otherwise.

## Layers (all must be defeated, in order, to trade real money)

1. **Paper by default.** `strategy.json.mode` scaffolds to `"paper"`. `new_bot.py`
   force-sets `mode="paper"` even if a compiled strategy said otherwise.
2. **`SAFE_MODE=1` default.** `LiveExecutor` refuses unless `SAFE_MODE=0`. safe_mode
   is a *hard precondition*, not advisory — this is the exact failure the Ken/Kalshi
   autoTrader once had (it traded while safe_mode was on). Here it cannot.
3. **`LIVE=1` required.** Absent it, `LiveExecutor` refuses.
4. **`data/LIVE_CONFIRMED` token required.** A human must create this file — an env
   flag alone is not enough.
5. **A real broker key required** (`POLYMARKET_API_KEY` / `KALSHI_API_KEY`).
6. **The broker order call is not wired in the template.** Even with 1–5 cleared,
   `LiveExecutor.open_position` raises `NotImplementedError`. Wiring it is a
   deliberate code change, not a config toggle.
7. **Go-live approval memo.** Before any of the above is cleared, draft a memo to
   `~/.claude/yolo-queue/pending-approval/` describing the strategy, the caps, the
   venue, and the expected spend. Steve approves. This is the same gate every
   customer-facing / money / irreversible action uses.

## Runtime guardrails (active even in paper)

- **Kill switch** — `touch data/KILL` halts all new entries on the next cycle;
  existing exits still run so positions can wind down.
- **Daily-loss circuit breaker** — `risk.max_daily_loss_usd`; once tripped, no new
  entries for the rest of the day.
- **Exposure cap** — `risk.max_total_exposure_usd`; a candidate is skipped if it
  would push summed open size over the cap.
- **Position caps** — `sizing.max_open_positions`, `sizing.max_position_usd`.
- **Sandboxed rules** — strategy expressions run through `safe_eval.py` (AST
  whitelist), never Python `eval`. A malicious/typo'd rule cannot execute code.
- **Append-only ledger** — every fill is one immutable JSONL line; state is
  replayed, never mutated, so a trade is never silently lost.

## Cost visibility

- Paper mode = **$0** — Polymarket's public Gamma API is free and keyless. The bot
  prints a `cost:` line every cycle.
- Live mode = **real money** — the cycle line switches to `cost: REAL MONEY (live)`.
- Any future paid data/execution API must be logged to the `cost-tracker` ledger.

## What this skill will NOT do autonomously

Place a live order · create the `LIVE_CONFIRMED` token · set `SAFE_MODE=0` · add
broker keys · deploy a bot to a server · run a live loop. All of those are surfaced
to Steve. The skill builds, validates, and paper-tests — it stops at the money line.