Getting Started with EduMatcher¶
Learning objectives
After reading this page you will understand:
- What EduMatcher is and what you can do with it
- The minimum steps to start an exchange and execute your first trade
- What each process does and when to start it
- How to quickly bootstrap a new
engine_config.yamlwithpm-config-gen - Which sections to read next based on your role
What is EduMatcher?¶
EduMatcher is a fully functional financial exchange matching engine built for education, research, and demo purposes. It implements the same core mechanics that underpin real stock exchanges:
- A continuous order book that matches buyers and sellers
- Auction phases (opening and closing) with equilibrium price calculation
- Market-maker quoting with obligations and protection
- Risk controls: price collars, circuit breakers, kill switches
- Combo and OCO orders: multi-leg strategies with cascade cancellation
- Statistics recording (OHLCV, VWAP, mid prices) in SQLite
- Drop-copy feed for compliance monitoring
- Autonomous AI traders to simulate real order flow
Participants connect via a terminal (the gateway) and type commands to place orders. The engine matches them and publishes fill events over a ZeroMQ message bus that all other processes subscribe to.
flowchart LR
GW1["pm-alf-console\nParticipant A"]
GW2["pm-alf-console\nParticipant B"]
AI["pm-ai-trader\nAutonomous bot"]
ENG["pm-engine\nMatching engine\nPULL :5555 / PUB :5556"]
ADM["pm-admin\nOperator console"]
CLR["pm-clearing\nP&L tracker"]
STAT["pm-stats\nStatistics recorder"]
DC["Drop-copy feed\n(built into pm-engine)\n:5557"]
SCH["pm-scheduler\nSession phases"]
GW1 -- "NEW|SYM=AAPL|..." --> ENG
GW2 -- "NEW|SYM=AAPL|..." --> ENG
AI -- "orders" --> ENG
ADM -- "HALT / RESUME / STATUS" --> ENG
ENG -- "fills / book / session" --> GW1
ENG -- "fills / book / session" --> GW2
ENG -- "trade.executed" --> CLR
ENG -- "trade.executed / book." --> STAT
ENG -- "per-fill drop-copy" --> DC
SCH -- "session state" --> ENG
How to get started¶
Running the exchange is complex enough that you really need to read the documentation and follow the instructions in the User Guide to get a full exchange up and running. The installation below is just the very first step to get started. The rest of the User Guide will explain how to configure the exchange, start and stop processes, and run the system in a realistic way.
This might seem overwhelming at first and the best way to get started is to skim through the entirety of the user-guide. After the installation a good way to get started is through the self-paced training sections
Installation¶
EduMatcher supports two installation modes. Choose the one that matches your role.
VM bootstrap mode — curl + Multipass (no repo clone)¶
Use this mode when you want a ready-to-run EduMatcher VM without installing Python or cloning this repository on your host.
What is Multipass?
Multipass is a lightweight VM manager from Canonical. It launches Ubuntu VMs with simple CLI commands so you can run isolated Linux environments locally on macOS, Linux, or Windows.
Requirements
| Requirement | Notes |
|---|---|
| Multipass | Install from multipass.run |
| curl | Used to download the VM bootstrap script |
| Internet access | Required for downloading scripts and PyPI packages |
| Host resources | Recommended minimum: 2 vCPU, 3 GB RAM, 10 GB disk |
Bootstrap with one command
curl -fsSL https://raw.githubusercontent.com/johan162/EduMatcher/main/vm/curl_setup_vm.sh | bash -s -- --version 0.15.1 --snapshot
This command downloads the VM setup scripts, launches a Multipass VM,
installs EduMatcher in the VM, links all pm-* commands into
/usr/local/bin, prepares /home/ubuntu/session, and optionally takes
an initial snapshot.
Start using the VM
Open additional host terminals and run multipass shell edumatcher-vm in each
terminal to start pm-alf-console, pm-viewer, pm-clearing, and pm-audit.
Useful bootstrap options
# Different VM name and version
curl -fsSL https://raw.githubusercontent.com/johan162/EduMatcher/main/vm/curl_setup_vm.sh | \
bash -s -- --name edumatcher-vm --version 0.15.1 --snapshot
# Tune resources
curl -fsSL https://raw.githubusercontent.com/johan162/EduMatcher/main/vm/curl_setup_vm.sh | \
bash -s -- --cpus 2 --memory 3G --disk 8G
Optional: inspect script before execution
curl -fsSL https://raw.githubusercontent.com/johan162/EduMatcher/main/vm/curl_setup_vm.sh -o curl_setup_vm.sh
less curl_setup_vm.sh
bash curl_setup_vm.sh --version 0.15.1 --snapshot
End-user / student mode — pipx install (recommended)¶
This is the quickest path if you just want to run an exchange session — no source code, no Poetry, no virtual environment management.
Requirements
| Requirement | Notes |
|---|---|
| Python 3.13 or later | Check with python --version |
| Three or more terminal windows | Or a terminal multiplexer such as tmux |
Install
If using brew then install pipx
# Install pipx using homebrew
brew install pipx
pipx ensurepath # adds ~/.local/bin to PATH; reopen your shell after this
or on Linux
# Install pipx (once, if not already present)
pip install pipx
pipx ensurepath # adds ~/.local/bin to PATH; reopen your shell after this
Install EduMatcher — all pm-* commands land on your PATH¶
pm-setup prints a shell snippet to add to your .zshrc / .bashrc:
export EDUMATCHER_DATA_DIR="$HOME/.local/share/edumatcher"
export EDUMATCHER_CONFIG="$HOME/my-exchange-session/engine_config.yaml"
Or use the provided one-shot script (handles pipx installation automatically):
After reloading your shell, every pm-* command picks up the right data
directory automatically — no flags needed.
Edit the config, then start trading
If you prefer generating a starter config instead of manually writing YAML:
pm-config-gen \
--symbols AAPL MSFT \
--gateways TRADER01 TRADER02 OPS01:ADMIN \
--sessions-enabled \
--output engine_config.yaml
Then edit any remaining details and start the engine.
For full generator details (all flags, --symbol-opts, MM quote stubs,
validation hints, and recipes), see
Configuration.
# Edit the sample config that pm-setup copied into your directory
nano engine_config.yaml
# Start the engine
pm-engine --verbose
Developer mode — Poetry + source checkout¶
Use this mode if you want to modify the engine, run tests, or contribute.
Requirements
| Requirement | Notes |
|---|---|
| Python 3.13 or later | Check with python --version |
| Poetry | pip install poetry or pipx install poetry |
| Three terminal windows | Or tmux / screen |
Install
Data is stored in src/data/ inside the repo and engine_config.yaml is
read from the repo root — no environment variables needed.
All commands are prefixed with poetry run:
Switching from developer to end-user mode
You can install the locally built wheel with pipx at any time:
Environment variables¶
These two variables work in both modes. Set them in your shell profile to override the defaults permanently.
| Variable | Default (installed) | Default (source) | Purpose |
|---|---|---|---|
EDUMATCHER_DATA_DIR |
~/.local/share/edumatcher |
<repo>/src/data/ |
Where all persistent data files are stored |
EDUMATCHER_CONFIG |
./engine_config.yaml (CWD) |
<repo>/engine_config.yaml |
Path to the engine configuration YAML |
The --config flag on pm-engine and pm-scheduler always takes precedence
over both the environment variable and the default.
PM command family overview¶
Use these tables as a quick index for every pm- entry point currently
documented. All commands are shown in pipx form; in developer mode prepend
poetry run. All pm- processes/utilities are described in Processes.
Runtime processes (runnable)¶
| Command | Interactivity | Purpose | More information |
|---|---|---|---|
pm-engine |
Background | Matching engine; central order-book writer | Processes, Running the Engine, Configuration |
pm-alf-console |
Interactive terminal | ALF participant terminal and order entry | Processes, Gateway, ALF Protocol |
pm-scheduler |
Background | Session phase transitions by schedule | Processes, Auctions and Scheduling |
pm-viewer |
Terminal display | Single-symbol live order book view | Processes, Order Types |
pm-orders |
Terminal display | Live cross-gateway order status monitor | Processes, Messages |
pm-board |
Terminal display | Multi-symbol market board display | Processes |
pm-ticker |
Terminal display | Scrolling ticker with live plus OHLCV context | Processes, Statistics and Reporting |
pm-stats |
Background | Persist market statistics to SQLite | Processes, Statistics and Reporting |
pm-clearing |
Terminal display | Trade recording and running P&L | Processes, P&L and Clearing |
pm-audit |
Background | Full event log capture from the bus | Processes, Persistence |
pm-ralf-gwy |
Background | External post-trade dissemination gateway (RALF) | Processes, Post-Trade Dissemination, RALF Protocol |
pm-admin |
Interactive terminal | Interactive operational console | Processes, Risk Controls |
pm-ai-trader |
Background | Single autonomous trading bot gateway | Processes, AI Bot Traders |
pm-ai-swarm |
Background | Multi-agent autonomous trading swarm | Processes, AI Bot Traders |
pm-mm-bot |
Background | Autonomous market-maker quoting bot | Processes, Market-Maker Bot |
pm-md-gwy |
Background | Market-data distribution gateway (CALF) | Processes, Market Data Feed, CALF Protocol |
pm-api-gwy |
Background | REST/WebSocket order-entry and market-data API gateway | Processes, API Gateway |
pm-index |
Background | Real-time cap-weighted index calculation and dissemination | Processes, Market Index |
CLI utilities (runnable)¶
| Command | Purpose | More information |
|---|---|---|
pm-admin-cli |
Non-interactive admin commands for scripts | Processes, Risk Controls |
pm-cverifier |
Validate engine_config.yaml before runtime (YAML, schema, semantic, completeness checks) |
Processes, Configuration, Config Verifier |
pm-stats-cli |
Query stats.db without writing SQL |
Processes, Statistics and Reporting |
pm-index-cli |
Read-only query interface for index history files | Processes, Commands, Market Index |
pm-setup |
Bootstrap local session directory and defaults | Processes, Installation |
pm-config-gen |
Generate engine_config.yaml from CLI options |
Processes, Configuration generator |
Planned runtime processes (design proposals)¶
| Command | Interactivity | Purpose | More information |
|---|---|---|---|
pm-balf-gateway |
Background | Binary order-entry gateway (BALF) | Processes planned section, BALF Protocol |
For startup order and a practical first-run sequence, see Processes.
Market-Maker Quick Reference¶
If your gateway role is MARKET_MAKER, this is the fastest practical command
set for quote operation and fill recognition:
| Goal | Command |
|---|---|
| Submit/replace quote | QUOTE\|SYM=AAPL\|BID=209.80\|ASK=210.20\|BID_QTY=500\|ASK_QTY=500\|QUOTE_ID=Q123 |
| Cancel active quote | QUOTE_CANCEL\|SYM=AAPL |
| Show active quote legs | QLEGS |
| Show one-symbol quote legs | QLEGS\|SYM=AAPL |
| Show recent completed legs | QLEGS\|SHOW=RECENT |
| Show active + recent legs | QLEGS\|SYM=AAPL\|SHOW=ALL |
Recommended manual loop:
- Send
QUOTEwith an explicitQUOTE_ID. - After any
FILL, runQLEGS|SYM=<symbol>|SHOW=ALL. - Read
Filled?,Rem, andLeg statusto decide whether to re-quote.
See Gateway for
full QLEGS behavior and Market Making for operator
workflows and policy-specific behavior.
Five-minute minimum session¶
This walkthrough starts a matching engine, connects two participant terminals,
and executes one trade. No configuration file is required — the engine starts in
unrestricted mode when engine_config.yaml is absent.
Step 1 — Start the engine¶
Open a terminal and run:
"Installed (pipx)" mode
"Developer (Poetry)" mode
Expected output:
[ENGINE] EduMatcher matching engine starting
[ENGINE] Listening for orders on tcp://127.0.0.1:5555
[ENGINE] Publishing events on tcp://127.0.0.1:5556
[ENGINE] Drop-copy feed on tcp://127.0.0.1:5557
[ENGINE] Session state: PRE_OPEN
[ENGINE] Ready
The engine is now running. Leave this terminal open.
Step 2 — Connect Participant A (the buyer)¶
Open a second terminal:
"Installed (pipx)" mode
"Developer (Poetry)" mode
You should see a prompt after the connection banner:
Step 3 — Connect Participant B (the seller)¶
Open a third terminal:
"Installed (pipx)" mode
"Developer (Poetry)" mode
Step 4 — Check the session state¶
On either gateway, ask what state the exchange is in:
The engine replies with the current session state. In unrestricted mode it starts
in PRE_OPEN. To enable matching, advance to CONTINUOUS:
Skipping auctions in testing
Without pm-scheduler, the session state stays where you set it. Advance
to CONTINUOUS with pm-admin or the operator console. The quickest way
if you just have the engine running is to start with a config that sets
sessions_enabled: false (which defaults to CONTINUOUS).
For this walkthrough, start the engine with:
echo "sessions_enabled: false" > /tmp/demo.yaml
pm-engine --config /tmp/demo.yaml # installed
# or: poetry run pm-engine --config /tmp/demo.yaml
Step 5 — Place orders and trade¶
Book liquidity depends on your configuration
This walkthrough starts the engine with sessions_enabled: false and no
engine_config.yaml, so the book is completely empty at startup.
If you are running against an engine_config.yaml that configures AAPL
with a market_maker_quotes seed block, the book already has a two-sided
MM quote resting in it when trading opens. In that case, an aggressive order
from one participant will immediately match against the seed quote — before
the second participant even types anything. For example, a market buy from
GW01 would fill against the MM's resting ask rather than waiting for GW02's
sell.
If this happens and you are surprised by an unexpected fill, check whether your config seeds the book:
To follow this walkthrough exactly with a known-empty book, either start the engine with no config file, or use a config with nomarket_maker_quotes
entries.
On Participant B's terminal, post a sell order at 150.00:
Expected response:
On Participant A's terminal, buy at the same price:
Both gateways see fill events:
A trade.executed event is published to all subscribers. Congratulations — you
just ran a trade on your own exchange.
What happened under the hood¶
sequenceDiagram
participant A as GW01 (buyer)
participant E as pm-engine
participant B as GW02 (seller)
B->>E: NEW SELL AAPL 100@150.00
E-->>B: order.ack → RESTING
A->>E: NEW BUY AAPL 100@150.00
E-->>A: order.ack → RESTING
note over E: bid price ≥ ask price → match
E-->>A: order.fill.GW01 AAPL BUY 100@150.00
E-->>B: order.fill.GW02 AAPL SELL 100@150.00
E-->>E: trade.executed published to all subscribers
Starting more processes¶
The engine is the only mandatory process. Add the others as you need them:
| When you want to… | Start this process | More information |
|---|---|---|
| Watch P&L update in real time | pm-clearing |
P&L and Clearing |
| Record OHLCV statistics | pm-stats |
Statistics and Reporting |
| Query recorded statistics without SQL | pm-stats-cli daily --date 2026-06-14 |
Statistics and Reporting |
Use pm-admin operator commands |
pm-admin (interactive REPL) |
Risk Controls |
| Schedule opening/closing auctions | pm-scheduler |
Auctions and Scheduling |
| Add autonomous AI order flow | pm-ai-swarm --count 5 --duration 60 |
AI Traders |
| Add automated market-maker liquidity | pm-mm-bot --symbol AAPL |
Market-Maker Bot |
| Feed external clearing/drop-copy consumers over TCP | pm-ralf-gwy |
Post-Trade Dissemination |
| Feed compliance/risk systems | Subscribe to :5557 (drop-copy socket) |
Drop Copy |
For a full classroom session, use the provided launch script:
The script detects whether pm-engine is on PATH (installed mode) or falls
back to poetry run automatically when running from a source checkout.
Typical architecture for a classroom demo¶
flowchart TD
subgraph Instructor
direction TB
ADM["pm-admin\n(operator console)"]
end
subgraph Server
direction TB
ENG["pm-engine"]
CLR["pm-clearing"]
STAT["pm-stats"]
SCH["pm-scheduler"]
AI["pm-ai-swarm\n(simulated order flow)"]
end
subgraph Student terminals
direction TB
GW1["pm-alf-console --id ST01"]
GW2["pm-alf-console --id ST02"]
GWN["pm-alf-console --id STnn"]
end
ADM -- "halt / resume / session" --> ENG
ENG -- "gateway traffic" --> GW1
GW1 --> GW2
GW2 --> GWN
AI -. "orders" .-> ENG
SCH -. "phase changes" .-> ENG
ENG -- "trade events" --> CLR
ENG -- "market data" --> STAT
Typical setup:
- Instructor creates
engine_config.yamlwith student gateway IDs and symbols. - Instructor starts engine, scheduler, clearing, stats, and a small AI swarm.
- Students each
sshto the server and run their gateway. - Instructor uses
pm-adminto manage session phases and monitor the market.
Reading path¶
Use the table below to decide what to read based on your goal.
| Goal | Read these sections in order |
|---|---|
| Understand the full system | 01 → 03 → 08 → 04 → 06 → 11 → 12 → 02 → 07 → 09 → 10 |
| Set up a classroom session | 01 → 03 → 08 → 06 → 14 (MM) → 15 (AI) |
| Participate as a trader | 08 → 04 → 05 |
| Run as a market maker | 01 → 08 → 14 (MM) |
| Monitor the market | 09 → 10 → 13 → 07 |
| Write a custom client | 09 → 20 → 02 |
| Understand risk controls | 12 → 06 → 04 |
Glossary of terms used throughout this guide¶
| Term | Meaning |
|---|---|
| Engine | The pm-engine matching engine process — the authoritative order book |
| Gateway | A pm-alf-console participant terminal; one per trader |
| Symbol | A tradeable instrument, e.g. AAPL, MSFT |
| Order book | Sorted list of resting bids and asks for one symbol |
| Fill | An execution — the result of two orders matching |
| TIF | Time-in-Force: how long an order lives (DAY, GTC, ATO, ATC) |
| Tick | Minimum price increment (e.g. 0.01 for most equities) |
| Gateway ID | Unique identifier for a participant connection, e.g. GW01 |
| Session state | Phase of the trading day: PRE_OPEN, OPENING_AUCTION, CONTINUOUS, CLOSING_AUCTION, CLOSED |
| Market maker | A participant with role MARKET_MAKER who quotes two-sided prices |
| Circuit breaker | Automatic halt triggered when price moves beyond a configured threshold |
| Drop copy | A copy of all fill events published to a dedicated socket for compliance systems |
See also¶
- Configuration — full
engine_config.yamlreference - Configuration generator — build
engine_config.yamlfrom CLI flags - Running the Engine — detailed startup, monitoring, and troubleshooting
- Gateway Commands — complete command reference for participants
- Order Types — LIMIT, MARKET, STOP, ICEBERG, TRAILING_STOP, OCO, COMBO
- Market Making — QUOTE command, obligations, and MMP
- AI Traders — autonomous order flow with
pm-ai-traderandpm-ai-swarm - Market-Maker Bot — automated quoting with
pm-mm-bot - Post-Trade Dissemination — external post-trade gateway with
pm-ralf-gwy - External Protocols Overview — where ALF, BALF, CALF, and RALF fit and how to choose between them
- RALF Protocol — protocol-level wire specification