Your first paper trading session
Goal: drive a paper-trading session from the bot you authored in first-bot. End-to-end: dispatch → fills → kill.
Why
Paper trading is the highest-fidelity dress rehearsal AlphaSwarm supports without putting real money at risk. Same broker abstraction, same risk overlays, same kill-switch wiring as live trading. The difference is that fills come from the simulated execution engine in alphaswarm/trading/paper_trading.py.
Step 1 — verify the bot is ready
curl http://localhost:8000/bots/<bot_id>
Confirm the response includes a recent backtest_runs reference and
non-zero sharpe. The
paper-metadata-gate
will refuse to start the session otherwise.
Step 2 — start the session
curl -X POST http://localhost:8000/bots/<bot_id>/paper \
-d '{"starting_cash":100000,"duration_minutes":60}'
The response includes paper_run_id. The session is now in
the canonical Celery loop; alphaswarm-worker polls the broker every
1 second.
Step 3 — watch the WebSocket
In a browser console:
const ws = new WebSocket("ws://localhost:8000/ws/paper/<paper_run_id>");
ws.onmessage = (e) => {
const frame = JSON.parse(e.data);
console.log(frame.stage, frame.message, frame.equity, frame.positions);
};
You should see:
bar.received— every minute bar.signal.emitted— when the strategy says "buy" / "sell" / "flat".order.placed— order goes to the simulated broker.order.filled— fill comes back; positions update.equity.update— equity-curve point at the end of each bar.
All frames follow the canonical {task_id, stage, message, timestamp, **extras} envelope per AGENTS rule 4.
Step 4 — risk + kill switch
The bot's risk block (Step 1 of first-bot) is enforced by
alphaswarm/risk/limits.py::RiskLimits.
Once any limit is hit, the session emits risk.halted and stops.
The topbar kill switch in the Vite UI fans out to:
POST /bots/halt-allPOST /paper/stop-allPOST /agents/haltPOST /rl/halt-allPOST /workflows/haltPOST /terraform/haltPOST /quant-agents/halt
The whole stack stops in under 250 ms.
Step 5 — inspect the ledger
SELECT id, bot_id, status, total_pnl, num_fills, started_at, ended_at
FROM paper_trading_runs ORDER BY started_at DESC LIMIT 1;
SELECT order_id, symbol, side, qty, price, filled_at
FROM paper_fills
WHERE paper_run_id = '<from_above>'
ORDER BY filled_at;
Verify
- WebSocket delivered at least one
order.filledframe. -
paper_trading_runsrow has non-NULLtotal_pnl. - Kill switch closed the session.
What next
- Concept: paper trading — the full session loop, broker abstraction, and risk model.
- Concept: paper metadata gate — why some sessions get blocked before they start.
- How-to: kill switch incident response — the runbook for when the kill switch fires in production.