docs: add live trading checklist
Operator-facing pre-flight gate before real orders: MTDATA_TRADE_* guardrail inventory with defaults, idempotency, dry-run rehearsal (verified CLI tokens only), first-size orders and incident response. Indexed in the README trading table. Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,159 @@
|
||||
# Live Trading Checklist
|
||||
|
||||
**Audience:** Operator
|
||||
|
||||
You are about to let mtdata place **real orders** on a **real account**. This
|
||||
page is the pre-flight gate: confirm each section before switching off
|
||||
dry-run. It complements the safer-by-default guidance in
|
||||
[TRADING_SAFETY.md](TRADING_SAFETY.md) (User page) and the execution-shell
|
||||
tiers in `trading/README.md` (`preview` → `dry_run` → `demo` → `live`).
|
||||
|
||||
Related: [TRADING_SAFETY.md](TRADING_SAFETY.md) · [TRADING_RISK.md](TRADING_RISK.md) · [ENV_VARS.md](ENV_VARS.md)
|
||||
|
||||
---
|
||||
|
||||
## 0. The rule that never bends
|
||||
|
||||
1. `MTDATA_TRADING_ENABLED=0` is the **hard kill-switch**. Every trade path
|
||||
honors it. Default is `1` (trading allowed) — set it to `0` and keep a way
|
||||
to set it quickly before any live session.
|
||||
2. Every trade command defaults to **preview mode** (`dry_run=true`). A real
|
||||
order is sent only when you explicitly pass `--dry-run false`.
|
||||
3. Trade on a **demo account** first. Do not point the same terminal at a live
|
||||
account until the rehearsal in section 4 is green.
|
||||
|
||||
---
|
||||
|
||||
## 1. Guardrails — know what is actually active
|
||||
|
||||
Guardrails are **off by default** (`MTDATA_TRADE_GUARDRAILS_ENABLED=0`). They
|
||||
activate automatically when **any** of the limits below is configured, or when
|
||||
`MTDATA_TRADE_GUARDRAILS_ENABLED=1` is set. Confirmed via
|
||||
`src/mtdata/bootstrap/settings.py` (`_TradeGuardrailPolicy.is_enabled`).
|
||||
|
||||
A live trade submitted while guardrails are disabled still goes through, but is
|
||||
flagged with a `warnings` entry telling you to set
|
||||
`MTDATA_TRADE_GUARDRAILS_ENABLED=1`.
|
||||
|
||||
### Full environment-variable inventory
|
||||
|
||||
| Variable | Default | Effect |
|
||||
|----------|---------|--------|
|
||||
| `MTDATA_TRADING_ENABLED` | `1` | Master switch. `0` blocks all trading. |
|
||||
| `MTDATA_TRADE_GUARDRAILS_ENABLED` | `0` | Opt-in guardrails toggle. |
|
||||
| `MTDATA_TRADE_GUARDRAILS_IGNORE_ON_DEMO` | `0` | When `1`, guardrail checks are skipped on demo accounts only. |
|
||||
| `MTDATA_TRADE_ALLOWED_SYMBOLS` | — | Comma-separated allow-list (uppercased). |
|
||||
| `MTDATA_TRADE_BLOCKED_SYMBOLS` | — | Comma-separated block-list (uppercased). |
|
||||
| `MTDATA_TRADE_MAX_VOLUME` | — | Global max order volume (lots). |
|
||||
| `MTDATA_TRADE_MAX_VOLUME_BY_SYMBOL` | — | Per-symbol max volume, e.g. `EURUSD=0.1,GBPUSD=0.05`. |
|
||||
| `MTDATA_TRADE_SAFETY_MAX_VOLUME` | — | Safety max volume (lots). |
|
||||
| `MTDATA_TRADE_SAFETY_REQUIRE_STOP_LOSS` | `0` | When `1`, orders without a stop-loss are blocked. |
|
||||
| `MTDATA_TRADE_SAFETY_MAX_DEVIATION` | — | Max allowed slippage deviation (points). |
|
||||
| `MTDATA_TRADE_SAFETY_REDUCE_ONLY` | `0` | When `1`, new increasing exposure is blocked (reduce-only). |
|
||||
| `MTDATA_TRADE_MIN_MARGIN_LEVEL_PCT` | — | Minimum margin level (%) before orders are blocked. |
|
||||
| `MTDATA_TRADE_MAX_FLOATING_LOSS` | — | Max floating loss (account currency) before block. |
|
||||
| `MTDATA_TRADE_MAX_TOTAL_EXPOSURE_LOTS` | — | Max total open exposure (lots) before block. |
|
||||
| `MTDATA_TRADE_MAX_RISK_PCT_OF_EQUITY` | — | Max risk as % of equity. |
|
||||
| `MTDATA_TRADE_MAX_RISK_PCT_OF_BALANCE` | — | Max risk as % of balance. |
|
||||
| `MTDATA_TRADE_MAX_RISK_PCT_OF_FREE_MARGIN` | — | Max risk as % of free margin. |
|
||||
| `MTDATA_TRADE_IDEMPOTENCY_DB` | default path | SQLite file for order idempotency keys. |
|
||||
| `MTDATA_TRADE_IDEMPOTENCY_TTL_SECONDS` | default | How long a duplicate submission key is retained. |
|
||||
|
||||
---
|
||||
|
||||
## 2. Must confirm before live trading
|
||||
|
||||
### A. Account and demo-first
|
||||
|
||||
- [ ] You are on a **demo account** for your first session. Confirm the
|
||||
connected terminal is the intended one:
|
||||
```bash
|
||||
mtdata-cli trade_account_info --json
|
||||
```
|
||||
- [ ] You know the account currency, leverage, and whether it is hedged or
|
||||
netting. Note the server/company shown above.
|
||||
- [ ] No real-money terminal is logged in on the same MT5 port.
|
||||
|
||||
### B. Guardrails and kill switch
|
||||
|
||||
- [ ] `MTDATA_TRADING_ENABLED=0` is set and honored while you rehearse.
|
||||
- [ ] `MTDATA_TRADE_GUARDRAILS_ENABLED=1` is set for live, with at least one
|
||||
concrete limit configured (symbol allow-list, max volume, or risk %).
|
||||
- [ ] You have decided whether `MTDATA_TRADE_GUARDRAILS_IGNORE_ON_DEMO` should
|
||||
be `0` (guardrails apply everywhere) or `1` (relaxed on demo only).
|
||||
- [ ] Stop-loss is required before live
|
||||
(`MTDATA_TRADE_SAFETY_REQUIRE_STOP_LOSS=1`) or every order you place
|
||||
carries an explicit `--stop-loss`.
|
||||
|
||||
### C. Idempotency and journal
|
||||
|
||||
- [ ] The idempotency DB exists and is writable. Keep a unique
|
||||
`--idempotency-key` per logical order so a retry never double-sends.
|
||||
- [ ] You can read your deal history to verify fills:
|
||||
```bash
|
||||
mtdata-cli trade_history --kind deals --minutes-back 1440 --limit 50 --json
|
||||
```
|
||||
- [ ] Your execution shell (`trading/`) is writing its `journal.jsonl`, or you
|
||||
have an equivalent audit trail.
|
||||
|
||||
### D. Dry-run rehearsal (no real orders)
|
||||
|
||||
Run the full plan as previews and confirm the responses say
|
||||
`dry_run=true` / `would_send_order=false`:
|
||||
|
||||
```bash
|
||||
# account + session context + current book
|
||||
mtdata-cli trade_session_context EURUSD --json
|
||||
mtdata-cli trade_get_open --symbol EURUSD --json
|
||||
mtdata-cli trade_get_pending --symbol EURUSD --json
|
||||
|
||||
# market context the strategy will see
|
||||
mtdata-cli data_fetch_candles EURUSD --timeframe H1 --limit 300 --indicators rsi,ema --json
|
||||
|
||||
# walk-forward validation of a candidate before trusting it
|
||||
mtdata-cli strategy_validate EURUSD --timeframe H1 --lookback 1000 --strategy ema_cross --n-splits 5 --json
|
||||
|
||||
# preview the exact order you intend to send
|
||||
mtdata-cli trade_idea_compose EURUSD --timeframe H1 --horizon 12 --direction long --template standard --risk-pct 0.5 --json
|
||||
|
||||
# explicit place/modify/close previews
|
||||
mtdata-cli trade_place EURUSD --volume 0.01 --side buy --stop-loss 1.09800 --take-profit 1.10400 --magic 314159 --comment mtdata-check --dry-run true --json
|
||||
mtdata-cli trade_modify --ticket 12345 --stop-loss 1.09600 --dry-run true --json
|
||||
mtdata-cli trade_close --symbol EURUSD --magic 314159 --dry-run true --json
|
||||
```
|
||||
|
||||
### E. First live orders (small)
|
||||
|
||||
- [ ] First live size is the **minimum viable lot** for your account.
|
||||
- [ ] First live order uses a short horizon you can watch.
|
||||
- [ ] You verify the `retcode`/`order_sent` fields in the response and the
|
||||
matching deal in `trade_history` before placing anything else.
|
||||
- [ ] Guardrail responses (`guardrail_blocked`, `guardrails_preview`) are
|
||||
treated as **stop signals**, not something to override.
|
||||
|
||||
### F. Operations and incident response
|
||||
|
||||
- [ ] You know how to set `MTDATA_TRADING_ENABLED=0` in under a minute and
|
||||
that the running process will pick it up.
|
||||
- [ ] Your execution shell's circuit breaker is armed (after N consecutive
|
||||
failures it stops sending), and you know its cooldown.
|
||||
- [ ] Someone or something (journal, alert) will notice an unexpected open
|
||||
position within the first hour.
|
||||
- [ ] You can flatten quickly:
|
||||
```bash
|
||||
mtdata-cli trade_get_open --symbol EURUSD --json # get tickets
|
||||
mtdata-cli trade_close --symbol EURUSD --magic 314159 --dry-run false --json
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3. Deeper detail
|
||||
|
||||
- Preview responses carry `dry_run`, `would_send_order`, and — when a guardrail
|
||||
blocked the attempt — `guardrail_blocked` plus a `guardrail_rule`. Read all
|
||||
three on every rehearsal.
|
||||
- The guardrail policy is reloaded atomically from the environment
|
||||
(`TradeGuardrailsRuntimeConfig`), so setting the env vars takes effect without
|
||||
restarting the process.
|
||||
- Do **not** put real credentials, API tokens, or account numbers in this
|
||||
repository. Copy placeholders from `.env.example` only.
|
||||
@@ -106,6 +106,7 @@ How we write these pages: [STYLE.md](STYLE.md) (Contributor).
|
||||
| [TRADE_IDEAS.md](TRADE_IDEAS.md) | User | Preview-only compose: forecast, barriers, size, dry-run |
|
||||
| [TRADING_SAFETY.md](TRADING_SAFETY.md) | User | Dry-run, guardrails, account/journal (read-only first) |
|
||||
| [TRADING_RISK.md](TRADING_RISK.md) | User | Sizing, VaR/CVaR, stress tests (read-only) |
|
||||
| [LIVE_TRADING_CHECKLIST.md](LIVE_TRADING_CHECKLIST.md) | Operator | Pre-flight gate before real orders: guardrails, idempotency, rehearsal |
|
||||
| [BARRIER_FUNCTIONS.md](BARRIER_FUNCTIONS.md) | User | Take-profit / stop-loss probabilities |
|
||||
|
||||
## Contributor / inventory
|
||||
|
||||
Reference in New Issue
Block a user