Skip to content

Automation with CommandClient & MM Bot Tuning

Objective

Use EduMatcher's programmatic command client for repeatable admin workflows and practice advanced pm-mm-bot runtime tuning for startup and reconciliation.

Prerequisites

  • Chapters 01-20 completed.
  • Engine running with GW_ADMIN and at least one MM gateway configured.
  • Python environment able to import edumatcher.commands.

Background

The interactive tools are excellent for manual operation, but production-like operations often require deterministic automation:

  • One-shot operator runbooks (halt/resume, symbol cleanup, gateway checks).
  • Repeatable incident actions with explicit timeouts.
  • MM bot tuning for startup reliability in sparse-book conditions.

This chapter combines two advanced surfaces:

  1. ExchangeCommandClient (programmatic admin command API).
  2. Advanced pm-mm-bot runtime flags such as bootstrap timeout and QLEGS reconciliation interval.

Exercise 1: Run a Minimal CommandClient Session

Execute a short Python script:

python - <<'PY'
from edumatcher.commands import ExchangeCommandClient

with ExchangeCommandClient("GW_ADMIN") as client:
    auth = client.connect()
    print("auth:", auth)
    symbols = client.symbol_list()
    print("symbols:", symbols)
    state = client.session_status()
    print("session:", state)
PY

Checkpoint: you can connect, read symbols, and read session status programmatically.

Exercise 2: Script a Safe Symbol-Protection Runbook

Run a scripted sequence:

python - <<'PY'
from edumatcher.commands import ExchangeCommandClient

with ExchangeCommandClient("GW_ADMIN") as c:
    c.connect()
    c.symbol_halt("AAPL")
    c.cancel_symbol("AAPL")
    book = c.book_depth("AAPL")
    print("AAPL bids:", len(book.get("bids", [])), "asks:", len(book.get("asks", [])))
    c.symbol_resume("AAPL")
    print("AAPL resumed")
PY

This is easier to run consistently than a manual multi-step console sequence.

Checkpoint: you can automate halt/cancel/verify/resume for one symbol.

Exercise 3: Automate Gateway Exposure Cleanup

Use API methods to clear one participant and verify no resting orders remain:

python - <<'PY'
from edumatcher.commands import ExchangeCommandClient

target = "TRADER02"

with ExchangeCommandClient("GW_ADMIN") as c:
    c.connect()
    c.kill_switch(target)
    orders = c.order_list(target)
    print("remaining orders for", target, ":", len(orders))
PY

Optional extension:

  • Add gateway_kick(target, reason=...) after kill_switch when operational policy requires immediate disconnect.

Checkpoint: you can explain when to use kill-switch only vs. kill-switch + kick.

Exercise 4: Tune pm-mm-bot Startup Reliability

Run one bot with explicit startup controls:

pm-mm-bot \
  --symbol AAPL \
  --gap 0.10 \
  --qty 500 \
  --startup-session-timeout-sec 5.0 \
  --bootstrap-timeout-sec 1.0 \
  --qlegs-reconcile-interval-sec 15.0 \
  -v

Observe startup logs for:

  • Bootstrap reference resolution (existing quote adopted, or a random-range price).
  • Session readiness before the first quote.
  • QLEGS reconciliation, which is silent while everything agrees and only logs when it finds a mismatch.

Every bot log line is prefixed with the bot's gateway ID ([<gateway_id>]), and per-symbol lines add a [<symbol>] tag. Representative startup lines (after the usual timestamp/level/logger prefix):

[MM_AAPL_01] starting: gateway=MM_AAPL_01 symbols=AAPL
[MM_AAPL_01] [AAPL] strategy=symmetric gap=0.1 qty=500 tif=DAY drift_ticks=3
[MM_AAPL_01] [AAPL] bootstrap from random range: 100.37
[MM_AAPL_01] running symbols=['AAPL'] session=CONTINUOUS

The bootstrap from random range line only appears when the price came from --initial_min/--initial_max (Exercise 5); with a live book the reference comes from the book and -v shows it as [<symbol>] reference from book/trade: <price>. There is no per-quote INFO line — use QLEGS|SYM=AAPL on the MM gateway to confirm the quote is live.

Checkpoint: you can identify and tune the timeout knobs that control startup behavior.

Most of these knobs can differ per symbol

--bootstrap-timeout-sec and --qlegs-reconcile-interval-sec are per-symbol settings: on a multi-symbol bot each symbol may be given its own, either by scoping the flag after that symbol's --symbol or from its block in a config file (see 02 — Setting Up Market-Maker Liquidity, Exercise 8). --startup-session-timeout-sec is the exception and stays process-wide, because the session phase it waits for is exchange-wide and there is nothing per-symbol to express.

The QBOOT/QLEGS requests themselves, and the startup/gap checks they inform, run once per symbol regardless. A pm-mm-bot --symbols AAPL,MSFT,TSLA -v run shows three independent [AAPL]/[MSFT]/[TSLA]-tagged QBOOT and QLEGS exchanges in the startup log, not one — so a --bootstrap-timeout-sec tuned down aggressively for a fast classroom demo is a budget applied to each symbol's round trip in turn, not split across them.

Exercise 5: Empty-Book Bootstrap Drill

Simulate sparse startup conditions and run bot with explicit bootstrap range:

pm-mm-bot --symbol AAPL --initial_min 95.00 --initial_max 105.00 -v

Then compare behavior with and without range configured.

Expected understanding:

  • With range: bot can start quoting on fresh books.
  • Without any bootstrap source: bot fails fast with clear reason.

Fails fast per symbol, not necessarily for the whole process

On a --symbols bot, "without any bootstrap source" excludes that symbol from quoting rather than stopping the process outright, as long as at least one other symbol resolves a reference price — see Per-symbol failure isolation. The single-symbol case in this exercise is the special case where there is no "other symbol" left, so the process-level failure you'll observe here is the same behavior applied to a symbol set of one. --initial_min/ --initial_max are per-symbol settings too: give them once before any --symbol and every symbol draws from that one range (expect a different random price per symbol), or scope them to a single symbol to give a volatile name a range of its own.

Checkpoint: you can choose a bootstrap strategy appropriate for your environment.

Exercise 6: Build a Combined Automation Flow

Design a short automation script that:

  1. Checks session status.
  2. Halts one symbol if needed.
  3. Clears that symbol's resting orders.
  4. Resumes symbol.
  5. Verifies top-of-book depth.

Use ExchangeCommandClient methods only (no manual prompt commands).

Acceptance criteria — your script passes if all of the following hold:

  • Correct halt response: the halt call returns a success/ack response for the target symbol (not a generic exception or timeout).
  • Book actually empties: after the clear step, a book query for that symbol shows zero resting orders on both sides before you resume it.
  • Correct resume response: the resume call returns success and a subsequent SYMBOL_STATUS-style query (or equivalent client method) shows the symbol back in a tradeable state.
  • Idempotent rerun: running the entire script a second time immediately afterward produces the same end state (symbol active, book empty of the orders your script itself cleared) without raising an error — halting an already-halted symbol or clearing an already-empty book must not crash the script.
  • No orphaned state: after the script finishes, no test order placed by the script remains resting outside of what step 5 intentionally verifies.

Checkpoint: your script is deterministic, idempotent, and easy to rerun during drills, and satisfies all five acceptance criteria above.

Summary

You now have advanced operational coverage for:

  • Programmatic admin orchestration with ExchangeCommandClient.
  • Repeatable incident-response style command sequencing.
  • Practical pm-mm-bot tuning for startup/bootstrap/reconciliation behavior.

Reflection

Why does this chapter insist your automation scripts be idempotent (safe to rerun) rather than accepting "runs correctly once" as good enough? Think about an incident-response scenario at 3am — what goes wrong if an on-call engineer reruns a non-idempotent halt/clear/resume script by mistake?

Further Reading

You have completed the operator track. The remaining chapters (22–27) cover the external protocols — RALF, CALF, the REST/WebSocket API, the market index, and the ALF/BALF TCP gateways.