Command lines¶
Programs are built into build/<preset>/bin/. Programs built with fastmm::cli::live, backtest and replay for your own strategies (tutorial-live, mm-live, ...) accept the same flags and print their own name in messages (Register a strategy). Durations take a unit: 1500ms, 60s, 5m, 2h.
fastmm-live¶
Trades a strategy on the venues of a configuration until SIGINT, SIGTERM or --duration.
Trades a strategy on the venues of a configuration.
usage: fastmm-live [OPTIONS]
OPTIONS:
-h, --help print this help and exit
--version print the version and exit
--config <file> engine / venue / strategy configuration (required)
--strategy <name> registered strategy (default: [strategy] name); a different
strategy ignores [strategy.params]
--param <key=value> strategy parameter override (repeatable)
--duration <t> stop after t (e.g. 60s, 5m, 1500ms; default: until SIGINT)
--dry-run public market data only, no API keys: quotes on paper, sends
no order
--record-raw <dir> append raw WebSocket frames to <dir>/<venue>-<channel>.jsonl
--journal <path> write the session journal (.fmj) here
--no-journal disable journaling even if [engine] journal = true
--status <path> live status file for fastmm-top (default
/dev/shm/fastmm-<engine>.status)
--no-status do not publish live status
--control <path> control socket for fastmm-ctl (default
<journal_dir>/<engine>.ctl, mode 0600)
--no-control do not open a control socket
--gateway <path> trade through the fastmm-gateway at this socket instead of
connecting to the venues (no API keys here)
--clear-kill clear a latched kill switch and the cumulative PnL before
starting; arms the whole [risk] max_loss budget again
--standby while another process holds the instance lock, wait for it
instead of exiting: connected to market data with orders
refused where the venues allow it, else before connecting;
trade once it is free
--takeover --standby, and ask the process holding the lock to hand over
(control socket `handoff`); exit 8 if it refuses or keeps the
lock past [engine] handoff_timeout_ms
--log <path> write the log to a file (warnings are mirrored to stderr)
--allow-inline-secrets accept literal API secrets in the config file
--list-strategies print the strategies this binary can run and exit
--format <text|json> output format of --list-strategies (default text)
API keys come from the environment through ${VAR} references in [venues.*],
e.g. FASTMM_BINANCE_API_KEY / FASTMM_BINANCE_API_SECRET.
SIGINT/SIGTERM trips the kill switch, cancels all open orders and exits. A second
SIGINT/SIGTERM 5 s or more after the first, or a shutdown still running 60 s after
the stop, exits at once with code 5 without waiting for cancel_all.
SIGHUP clears the kill switch and resumes quoting (on_kill = "stay").
fastmm-ctl talks to the control socket: pull, resume, param, limits, flatten,
kill, unkill, stop, handoff and status.
With [engine] instance_lock = true (implied by --standby and --takeover) one process
of an engine name trades at a time; `handoff` stops the holder for the successor.
A kill switch the engine trips itself ([risk] max_loss, a full ring, every venue
killed) does the same and exits with code 6, unless [engine] on_kill = "stay".
A max_loss trip is latched in [engine] kill_file: the next start refuses to trade
(exit code 6) until --clear-kill or the file is removed.
Exit codes:
0 stopped by --duration or SIGINT/SIGTERM, cancel_all ok
2 bad command line, or a venue has no API keys
3 bad config, strategy or parameters
4 venue reference data failed to load
5 runtime failure: cancel_all failed, journal, ring overflow, forced exit, uncaught error
6 kill switch tripped by the engine (on_kill = "exit"), or a latched max_loss trip
7 a Python strategy's slow tier failed (python -m fastmm run), cancel_all ok
8 another process holds the instance lock, or --takeover failed; nothing traded
Exit codes¶
| Exit code | Meaning |
|---|---|
| 0 | stopped by --duration, SIGINT/SIGTERM or fastmm-ctl stop with cancel_all ok, also after a kill with [engine] on_kill = "stay"; --help, --version and --list-strategies |
| 2 | bad command line, including a --log file that cannot be opened; a ${VAR} in [venues.*] that is not set, except api_key, api_secret and api_passphrase with --dry-run |
| 3 | the configuration does not load (including an invalid on_kill or a literal secret), no instruments or duplicate symbols, an unknown venue kind, a strategy that is unknown or cannot run live, an unknown parameter or invalid value, a strategy name registered twice by different code; an account setting the connector refuses (Bybit linear in hedge mode); instruments in several settlement currencies with a limit set and no [accounting] source for one of them (Configuration); threading = "single" with more than one venue or with --gateway; the epoch or kill file cannot be read; a [storage] backend that is not registered or cannot be opened (Storage) |
| 4 | a venue's reference data failed to load; with --gateway, the gateway cannot be reached or refused the attach |
| 5 | cancel_all FAILED, whatever stopped the session; the journal cannot be opened or written (a full filesystem trips the kill switch, Journal format); a venue's order-event ring overflowed; the gateway closed the attachment (--gateway); an uncaught error; a forced exit during shutdown: a second SIGINT/SIGTERM 5 s or more after the first, or a shutdown still running 60 s after the stop (include/fastmm/live/shutdown_guard.hpp), which does not wait for cancel_all |
| 6 | the engine tripped the kill switch itself ([risk] max_loss, a full outbound or journal ring, every venue killed, a failing hot hook of a Python strategy) with on_kill = "exit", and cancel_all ok; also a start refused because a max_loss trip is latched in [engine] kill_file (Kill switch and shutdown) |
| 7 | a Python strategy's slow tier failed, and cancel_all ok (python -m fastmm run and fastmm.run_live; fastmm-live does not return it) |
| 8 | another process holds the instance lock ([engine] instance_lock); --takeover whose handoff the holder refused or did not answer, or whose lock it kept past [engine] handoff_timeout_ms; a session answering on the control socket without the lock. Nothing was traded (Hand over a running session) |
- The journal records the configuration after
--strategyand--param. python -m fastmm runandfastmm.run_liverun the same session for a Python strategy with these exit codes (Live sessions).fastmm::cli::liveinstalls process-wide SIGINT and SIGTERM handlers. The first signal starts the shutdown (Kill switch and shutdown).
fastmm-gateway¶
Holds the venue connections of a configuration; several fastmm-live --gateway processes trade through them, under account-wide risk limits (Run a strategy behind a gateway).
Holds the venue connections that strategy processes attach to.
usage: fastmm-gateway [OPTIONS]
OPTIONS:
-h, --help print this help and exit
--version print the version and exit
--config <file> engine / venue configuration (required)
--socket <path> attach socket (default <journal_dir>/<engine>.gw, mode 0600)
--status <path> status file for fastmm-top (default
/dev/shm/fastmm-<engine>.gw.status)
--no-status do not publish live status
--control <path> control socket for fastmm-ctl (default <attach socket>.ctl,
mode 0600)
--no-control do not open a control socket
--duration <t> stop after t (e.g. 60s, 5m; default: until SIGINT)
--dry-run public market data only: no API keys, no orders
--log <path> write the log to a file (warnings are mirrored to stderr)
--allow-inline-secrets accept literal API secrets in the config file
--clear-kill clear a latched account kill switch and the account's
cumulative PnL before starting
Reads the same configuration as fastmm-live: [engine] (name, journal_dir, epoch_file,
kill_file, spin_mode, net_cpus, ring sizes), [venues.*], [[instruments]] (every
instrument of every strategy) and [gateway]. Strategies attach with fastmm-live
--gateway <socket>, several at once, each trading instruments no other attached
strategy trades. When one exits or dies, the gateway cancels its orders; the others
and the venue connections stay up. SIGINT/SIGTERM cancels all open orders and exits.
[gateway] max_loss is a loss budget for the account, every strategy together,
carried in <journal_dir>/<engine>.kill. When it trips, the gateway kills every
strategy's venues, cancels every open order and refuses attaches; the trip is
latched and every start exits 6 until --clear-kill or the file is removed.
fastmm-top --gateway <engine> shows the attachments, the account and the venues;
fastmm-ctl --gateway <engine> pulls and resumes the strategies' quotes, kills the
account and clears the kill without a restart (fastmm-ctl --gateway <engine> help).
Exit codes:
0 stopped by --duration or SIGINT/SIGTERM, cancel_all ok
2 bad command line, or a venue has no API keys
3 bad config, or the socket cannot be created
4 venue reference data failed to load
5 a cancel_all failed
6 the account kill switch is latched in the kill file
fastmm-backtest¶
Backtests a registered strategy on synthetic data, a journal, a CSV file or a public archive (Market-data sources).
Backtests a registered strategy.
usage: fastmm-backtest [OPTIONS]
OPTIONS:
-h, --help print this help and exit
--version print the version and exit
--config <file.toml> engine / strategy / backtest configuration (required)
--data <spec> market data: 'synthetic', a *.fmj / *.csv path, or
<source>:<args>; several separated by ';' merge by time
(default: [backtest] source/path). `fastmm-data list` prints
the sources
--strategy <name> registered strategy (default: [strategy] name)
--param <key=value> strategy parameter override (repeatable)
--out <dir> write equity.csv fills.csv orders.csv summary.json (default:
[backtest] output_dir; '-' = don't write)
--seed <n> synthetic market / latency model seed
--duration <seconds> synthetic horizon
--journal-out <file> record the session for fastmm-replay
--list-strategies print registered strategies and their parameters
--format <text|json> output format of --list-strategies (default text)
| Exit code | Meaning |
|---|---|
| 0 | the backtest ran |
| 2 | bad command line |
| 3 | bad configuration, unknown strategy or parameter, a strategy that cannot run in the simulator |
| 4 | the market data cannot be read |
| 5 | the run failed |
The flags override [backtest] (Configuration).
fastmm-data¶
Lists the market-data sources a backtest can read and packs any of them into a journal (Market-data sources). Downloading the files a source reads is python3 -m fastmm.data fetch. fill-check compares a live session's fills with the l2_queue fill model (Check the fill model against live fills); calibrate fits its conservatism and the simulated latencies to several sessions and prints the [backtest] keys (Calibrating against live sessions).
Lists the market-data sources a backtest can read and packs them into journals.
usage: fastmm-data [OPTIONS] [SUBCOMMAND]
OPTIONS:
-h, --help print this help and exit
--version print the version and exit
--data <spec> convert: source, e.g. binance:BTCUSDT,2024-03-27
--config <file.toml> convert: backtest config supplying the instruments; calibrate
--backtest: the configuration to run instead of the journals'
own, one for all or one per journal
--out <file.fmj> convert: output journal
--seed <n> convert: session id stamped in the journal (default 1)
--conservatism <c,...> fill-check, calibrate: queue_conservatism values to compare
(default 0,0.5,1; calibrate 0,0.25,0.5,0.75,1)
--csv <file.csv> fill-check: also write one row per order; calibrate: one row
per session, inputs and conservatism
SUBCOMMANDS:
list registered data sources, their options and what each one
carries
convert decode a source into an .fmj journal, the format a backtest
replays fastest
fill-check how many of a live session's resting orders the l2_queue fill
model would have filled
analyze what a live session's fills were worth: maker share, spread
captured and markouts per horizon, from its journal
calibrate fit queue_conservatism and the latencies to live sessions,
cross-validated, and print the [backtest] keys
Downloading what a source reads: python3 -m fastmm.data fetch --help
| Exit code | Meaning |
|---|---|
| 0 | the command ran |
| 2 | bad command line |
| 3 | bad configuration (convert, calibrate --backtest) |
| 4 | the source is unknown, its options are wrong, or its files are missing; a journal given to fill-check or calibrate cannot be read; a calibrate --backtest run failed |
| 5 | the journal, or the --csv file of fill-check or calibrate, could not be written |
fastmm-replay¶
Replays a journal through the same engine and strategy and, with --verify, compares the order messages it sends with the recorded ones.
Replays a journal through the same engine and strategy.
usage: fastmm-replay [OPTIONS]
OPTIONS:
-h, --help print this help and exit
--version print the version and exit
--journal <in.fmj> session or market-data journal to replay (required)
--config <file.toml> configuration to replay with (default: the one embedded in a
session journal; configs/backtest-example.toml for a
market-data journal)
--strategy <name> strategy to run (default: journal header / config)
--out <file.fmj> keep the re-simulated session journal (market-data input)
--expect <sha256> expected outbound hash (default: <journal>.sha256)
--verify fail (exit 1) unless every hash and message matches
--allow-incomplete replay a journal the writer never closed; its tail is missing,
so the outbound comparison proves nothing
--check check what the replay needs (journal, configuration, strategy,
parameters) without replaying; exit 3 when something is
missing
--json --check: one JSON object instead of lines
| Exit code | Meaning |
|---|---|
| 0 | the replay matched, or no verification was requested |
| 1 | mismatch: the first differing message is printed |
| 2 | bad command line, including a session journal without an embedded configuration and no --config |
| 3 | unreadable configuration or journal, unknown strategy; with --check, a check failed |
Journals, replay and PnL explains what-if replays and journals without outbound copies.
fastmm-pnl¶
Queries the store a session wrote: what it traded, PnL and funding by day and instrument, and what the last session left behind. It reads the store, not a journal.
What a deployment traded, read from the store.
usage: fastmm-pnl [OPTIONS] [SUBCOMMAND]
OPTIONS:
-h, --help print this help and exit
--version print the version and exit
--store <path> store file (default runs/<engine>.db)
--backend <name> storage backend (default sqlite)
--engine <name> [engine] name to filter on
--session <id> one session id
--instrument <sym> one symbol
--since <day> inclusive UTC day, YYYY-MM-DD, or today|yesterday
--until <day> inclusive UTC day, YYYY-MM-DD, or today|yesterday
--day <day> shorthand for --since <day> --until <day>
--limit <n> at most n rows
--csv comma-separated output instead of an aligned table
--exchange <file> audit: the venue's executions, a JSON array (Binance myTrades
/ userTrades) or CSV
--venue <name> audit: the [venues.<name>] the file is from
--from-ms <ms> audit: window start, Unix ms (default: the file's first)
--to-ms <ms> audit: window end, Unix ms (default: the file's last)
--at <time> params, config: a UTC time, YYYY-MM-DD[ HH:MM[:SS]] (default:
now)
--against <id> param-diff: the earlier session to compare with
--summary rejects: one row per account, instrument, side and source
--raw ledger: every stored row, with its copy number
--order <id> order: the client order id
SUBCOMMANDS:
sessions one row per session: when it ran, what it made, how it ended
fills one row per execution
orders one row per order, in its last known state
pnl realised (and the funding in it), fees and net by UTC day and
instrument
funding one row per perpetual funding payment
positions the last position snapshot of each session and instrument
duplicates executions and funding payments stored more than once (booked
twice)
recover what the newest session left behind
audit the stored fills against a file of the venue's executions
(--exchange)
params the strategy parameters in effect --at a time (default: now),
and their source
param-changes every parameter update: the starting set, then each one
applied
param-diff what a session started with against what --against (default:
the one before) ended with
config the effective configuration a session ran with (TOML, secrets
omitted)
rejects refused orders: who refused them (source), and the account's
budget then; --summary sums them
ledger one row per execution however many sessions stored it, with
its flags; --raw lists every stored copy
order everything stored about one order (--order <id>), in time
order
| Exit code | Meaning |
|---|---|
| 0 | the query ran |
| 2 | bad command line, unknown backend, or a store that cannot be opened or read |
| 3 | recover found no session |
| 4 | duplicates found executions stored more than once |
Query what you traded works through the questions.
fastmm-sim-exchange¶
A local exchange that speaks the Binance Spot API (Simulated exchange).
A Binance Spot-compatible simulated exchange.
usage: fastmm-sim-exchange [OPTIONS]
OPTIONS:
-h, --help print this help and exit
--version print the version and exit
--config <file> [[instruments]] + [sim] configuration (default: built-in
BTCUSDT)
--bind <ip> listen address (default 127.0.0.1; 0.0.0.0 for containers)
--port <n> plain HTTP/WebSocket port (default 9080, 0 = ephemeral)
--tls-port <n> TLS port (default 9443, 0 = ephemeral)
--no-tls do not open the TLS listener
--tls-cert <pem> certificate chain (default tests/fixtures/tls/cert.pem)
--tls-key <pem> private key (default tests/fixtures/tls/key.pem)
--seed <n> generator seed (overrides [sim] seed)
--duration <t> stop after t (e.g. 60s, 5m, 1500ms; default: until
SIGINT/SIGTERM)
--stats-interval <t> print statistics every t (default 5s, 0 = only at exit)
Endpoints: REST /api/v3/*, market data /stream?streams=... and /ws/<stream>,
WebSocket API /ws-api/v3. The API key/secret come from [sim.account] or
FASTMM_SIM_API_KEY / FASTMM_SIM_API_SECRET. See docs/reference/sim-exchange.md.
| Exit code | Meaning |
|---|---|
| 0 | stopped by --duration or a signal |
| 2 | bad command line |
| 3 | bad configuration |
| 4 | cannot listen on a port |
fastmm-sim-itch¶
A Nasdaq-style exchange: ITCH 5.0 over MoldUDP64 multicast, re-requests, GLIMPSE 5.0 and OUCH 5.0, with a wire-to-wire histogram (fastmm-sim-itch).
A Nasdaq-style simulated exchange: TotalView-ITCH 5.0, GLIMPSE and OUCH.
usage: fastmm-sim-itch [OPTIONS]
OPTIONS:
-h, --help print this help and exit
--version print the version and exit
--config <file> [[instruments]] + [sim] configuration (default: FMAA, FMBB)
--bind <ip> re-request, GLIMPSE and OUCH servers (default 127.0.0.1)
--rerequest-port <n> MoldUDP64 re-request server, UDP (default 31000, 0 =
ephemeral)
--glimpse-port <n> GLIMPSE 5.0 over SoupBinTCP (default 31010)
--ouch-port <n> OUCH 5.0 over SoupBinTCP (default 31020)
--line-a <addr:port> line A: multicast group or unicast address (default
239.192.0.1:31001)
--line-b <addr:port> line B (default 239.192.0.2:31002, off = none)
--interface <if> multicast interface, name or IPv4 address (default lo)
--source <ip> local address of the multicast socket
--ttl <n> multicast TTL (default 1)
--drop-a <p> probability of not sending a data datagram on line A
--drop-b <p> the same on line B
--drop-seed <n> seed of the drop draws
--rate <n> datagrams per second per line (default 0 = unpaced)
--burst <n> datagrams per sendmmsg call (default 32)
--speed <x> generator time per wall-clock time (default 1)
--seed <n> generator seed
--busy-poll never block waiting for I/O
--cpu <n> pin the simulator thread to a CPU
--duration <t> stop after t (e.g. 60s, 5m, 1500ms; default: until
SIGINT/SIGTERM)
--stats-interval <t> print statistics every t (default 5s, 0 = only at exit)
--summary-json <file> write the wire-to-wire summary at exit
Orders time wire-to-wire when their OUCH ClOrdID is 'T' + 13 digits of the triggering
ITCH sequence number. See docs/reference/sim-itch.md.
| Exit code | Meaning |
|---|---|
| 0 | stopped by --duration or a signal |
| 2 | bad command line |
| 3 | bad configuration, CPU pinning failed, or the summary file cannot be written |
| 4 | cannot open a socket |
fastmm-ctl¶
Sends one command to a running fastmm-live session over its control socket
(Operating a running session), or with
--gateway to a fastmm-gateway (Run behind a gateway).
Sends one command to a running fastmm-live session or fastmm-gateway and prints
the reply.
usage: fastmm-ctl [--name <engine> | --gateway <engine> | --path <socket> | --config <file.toml>] <command>
OPTIONS:
-h, --help print this help and exit
--version print the version and exit
--name <engine> talk to <dir>/<engine>.ctl ([engine] name in the config)
--gateway <engine> talk to the fastmm-gateway of that [engine] name, at
<dir>/<engine>.gw.ctl
--dir <directory> where --name and --gateway look, default runs ([engine]
journal_dir)
--path <socket> talk to this socket (fastmm-live --control <path>)
--config <file> take the engine name and journal_dir from a configuration file
--timeout <ms> how long to wait for the reply, default 2000
--wait <ms> after `param`, wait up to <ms> until the engine reports the
update applied (exit 4 if it does not)
commands (one per datagram; the reply starts with ok or error)
pull [--instrument SYM | --venue NAME] stop quoting: everywhere, or in that scope
resume [--instrument SYM | --venue NAME] quote again; without a scope it also clears
every scoped pull and stops a running flatten
param <name>=<value> ... [--instrument SYM] [--source WHO]
new strategy parameters, validated here; the
reply's seq is applied once `params` shows it
params [--instrument SYM] the parameters' values, and the sequence
numbers published and applied
limits <key>=<value> ... new risk limits (the [risk] keys, and
underlying.<BASE>.max_net)
flatten [--instrument SYM] [--max-slippage-bps N] work the position off, reduce-only
kill trip the kill switch (quotes pulled, all
orders cancelled; the position stays)
unkill clear it and quote again (SIGHUP)
stop shut the session down (SIGTERM)
handoff shut down for the process waiting on the
instance lock (fastmm-live --standby)
status one line per topic
help this text
gateway commands (one per datagram; the reply starts with ok or error)
pull [--instrument SYM | --venue NAME] the strategies in that scope stop quoting
(those trading SYM, every strategy on NAME,
or every strategy)
resume [--instrument SYM | --venue NAME] they quote again
kill trip the account kill switch, as max_loss
does (GatewayOperator)
clear-kill clear it and arm the loss budget again;
refused while a strategy is attached
attachments one line per attached strategy
status the fastmm-top frame
help this text
examples:
fastmm-ctl --name mm status
fastmm-ctl --name mm pull --instrument BTCUSDT
fastmm-ctl --name mm --wait 5000 param half_spread_bps=8 --source manual
fastmm-ctl --name mm params
fastmm-ctl --name mm limits max_position=0.5 orders_per_sec=10
fastmm-ctl --name mm flatten --max-slippage-bps 15
fastmm-ctl --gateway gw attachments
fastmm-ctl --gateway gw pull --venue binance
fastmm-ctl --gateway gw clear-kill
Exit codes: 0 the session answered ok, 1 it answered error, 2 bad command line,
3 no session answered (no socket, or it is not running), 4 with --wait: the update was
queued but the engine did not report it applied in time.
| Exit code | Meaning |
|---|---|
| 0 | the session answered ok, or printed its status or help |
| 1 | the session answered error (an unknown command, a bad argument, a parameter the schema refuses, a full control ring) |
| 2 | bad command line |
| 3 | no session answered: no socket at that path, nobody listening, or no reply within --timeout |
| 4 | with --wait: the param was queued but the engine did not report it applied within <ms>, or the session's strategy publishes its own updates and gives no sequence number to wait on |
fastmm-top¶
A terminal dashboard of a running fastmm-live session or fastmm-gateway (Status file).
Terminal dashboard for a running fastmm-live session or fastmm-gateway.
usage: fastmm-top [--name <engine name> | --gateway <engine name> | --path <status file>] [OPTIONS]
OPTIONS:
-h, --help print this help and exit
--version print the version and exit
--name <engine> read /dev/shm/fastmm-<engine>.status ([engine] name in the
config)
--gateway <engine> read the fastmm-gateway's /dev/shm/fastmm-<engine>.gw.status
([engine] name in its config)
--path <file> read this status file (fastmm-live or fastmm-gateway --status)
--interval <ms> refresh period, default 500
--once print one frame and exit (exit code 3 if no status is
available)
--json print the snapshot as one JSON object and exit (implies
--once)
--no-color plain output
--metrics <[host:]port> serve the snapshot at /metrics in Prometheus text format until
SIGINT, instead of drawing (default host 127.0.0.1; off unless
given). Scraping costs the engine nothing: this process reads
the status file, the engine never sees the request.
| Exit code | Meaning |
|---|---|
| 0 | quit, or --once printed a frame |
| 2 | bad command line |
| 3 | with --once: no status file, or one of another status version |