Skip to content

Getting Started

Learning objectives

After reading this page you will understand:

  • What EduMatcher is, and why it is split into many pm-* processes
  • The smallest useful path from installation to a first trade, whether you installed the containers or the Python package
  • The handful of concepts that make the rest of the guide easier to read
  • How configuration, data files, market data, logs and reports fit together
  • Which chapters to read next for your role

What EduMatcher is

EduMatcher is a working educational exchange. It has a real matching engine, real order books, session phases, auctions, market-maker quoting, risk controls, statistics, clearing-style P&L, audit logs, external gateways, market-data feeds, post-trade feeds, monitoring tools and autonomous bot traders.

That makes it useful for three different kinds of learning:

  • Market microstructure — what happens inside an order book, why auctions exist, how spreads, time priority, market makers and risk controls change the market
  • Exchange operations — how to configure a venue, start the processes, run a session, monitor it, stop it and inspect what happened afterwards
  • Protocol and system design — how order entry, market data, post-trade dissemination, drop copy, logging and recovery semantics are separated in a multi-process system

The project is intentionally bigger than a toy. The User Guide is long because the system covers the whole exchange surface, not because you must learn every chapter before typing your first order. This page is the map.

If you would rather be told exactly what to do next

This page is the map: what the system is and how the pieces relate. If you want a route instead — a staged path with exact commands and a checkpoint at every step — go to A Path Through the Guide. It gets you to a running exchange in about fifteen minutes and a matched trade in about an hour.

If you are new to exchanges

Read How an Exchange Works before the rest of the User Guide. It explains the domain without assuming you already know what a book, fill, auction, market maker or drop-copy feed is.

The system in one picture

EduMatcher is a set of independent processes connected by message streams. The engine is the only process that owns the order books. Everything else either sends commands to the engine, listens to events from it, or exposes those events to another audience.

flowchart LR
    subgraph order_entry["Order entry and control"]
        ALF["pm-alf-console\ninteractive traders"]
        ALFGWY["pm-alf-gwy\nexternal ALF clients"]
        BALF["pm-balf-gwy\nbinary clients"]
        ADM["pm-admin / pm-admin-cli\noperator commands"]
        BOTS["pm-ai-trader / pm-ai-swarm / pm-mm-bot\nautomation"]
    end

    ENG["pm-engine\nmatching engine\norder books"]

    subgraph observers["Internal observers"]
        CLR["pm-clearing\nP&L"]
        STATS["pm-stats\nOHLCV / VWAP / mid"]
        AUDIT["pm-audit\naudit log"]
        IDX["pm-index\nmarket index"]
    end

    subgraph external["External and visual interfaces"]
        CALF["pm-md-gwy\nCALF market data"]
        API["pm-api-gwy\nREST / WebSocket"]
        RALF["pm-ralf-gwy\npost-trade feed"]
        DC["pm-dc-gwy\ndrop-copy TCP"]
        TERM["TapeDeck / pm-terminal\ntrader information terminal"]
        LOG["pm-log-srv / pm-log-ui\ncentral logs"]
        TRD["trader-gui\nbrowser trading terminal"]
        BOOK["pm-book\nbrowser order book viewer"]
    end

    ALF --> ENG
    ALFGWY --> ENG
    BALF --> ENG
    ADM --> ENG
    BOTS --> ENG
    ENG --> CLR
    ENG --> STATS
    ENG --> AUDIT
    ENG --> IDX
    ENG --> CALF
    ENG --> API
    ENG --> RALF
    ENG --> DC
    CALF --> TERM
    API --> TERM
    API --> TRD
    API --> BOOK
    LOG -. receives logs from .- ENG
    LOG -. receives logs from .- external

The important first idea is this: the exchange is not one command. It is a small operating environment. For a five-minute demo you only need pm-engine and two pm-alf-console terminals. For a classroom or realistic session you add configuration, the scheduler, clearing, statistics, market data, logging and visual displays.

The five concepts to learn first

You do not need every detail yet. These concepts are enough to make the rest of the guide readable.

Concept What it means Read more
Engine pm-engine, the authoritative process that owns all order books and matches orders Running the Exchange, Processes
Symbol A tradeable instrument such as AAPL, with tick size, reference prices, optional market-maker seeds and risk settings Configuration, Risk Controls
Gateway ID The identity a trader, bot or operator uses when connecting; roles such as TRADER, MARKET_MAKER and ADMIN are attached to gateway IDs Configuration, Gateway Concepts
Session phase Where the trading day is: PRE_OPEN, OPENING_AUCTION, CONTINUOUS, CLOSING_AUCTION, CLOSED, or a halt-related phase Auctions & Scheduling
Deployed configuration The running system reads one compiled artifact at <EDUMATCHER_DATA_DIR>/ref_data/engine_config.json; you edit YAML, then deploy it Configuration

Two more ideas become important once you start observing or integrating:

  • Events and records are not the same thing. The engine publishes live events. pm-stats, pm-clearing, pm-audit, pm-index and the log server turn those events into durable records. See Persistence.
  • Internal tools and external protocols are separate. Local processes use ZeroMQ around the engine. External clients use ALF, BALF, CALF, RALF, DC1 or the API gateway. See External Protocols Overview.

How to approach the documentation

The User Guide is arranged roughly in layers:

Layer Chapters Use them when...
Start and configure Getting Started, Configuration, Config Verifier, Config GUI, Running the Exchange You need to install, create a session config, deploy it and start processes
Trade Gateway Reference, Order Types, Combo Orders, Auctions & Scheduling, Market Making You want to understand what traders and market makers can do
Operate Risk Controls, P&L & Clearing, Statistics, Market Index, Exchange Commands, Processes You are running a classroom, demo or test venue and need control and observability
Persist and audit Persistence, Audit Trail, Drop Copy, Centralized Log Server You need to know what gets written, where, and how to inspect or replay it
Integrate External Protocols Overview, ALF, BALF, CALF, RALF, API Gateway, protocol appendices You are writing a client, feed handler, dashboard or post-trade consumer
Observe visually TapeDeck, Log Operator Console, ticker/board/viewer process sections You want browser or terminal displays for a running market
Practice Examples, Example Engine Configs, Training You want guided exercises rather than reference material

The Training Guide is the most beginner-friendly hands-on route. The User Guide is the reference; the training chapters are the guided lab.

Installation

Installation has its own chapter: Installation. It covers all five modes — the one-command container install, building the containers from a checkout, the Multipass VM, pipx and a Poetry checkout — together with the container networking, every build flag, and every directory the system uses.

Two of them matter for this page, because they lead to different first steps.

Containers — the whole system, four browser applications included:

curl -fsSL https://raw.githubusercontent.com/johan162/EduMatcher/main/deployment/curl/install.sh | bash
cd ~/.edumatcher

The exchange is now running on a bundled configuration.
The pm-* commands, the control plane of the exchange, lives inside the container.
Use regular Docker/Podman command to open a shell in the conainer or use the shortcut:

./edumatcher.sh shell        # then pm-help, pm-admin, pm-alf-console, pm-stats-cli, ...

Once inside the container, start with reviewing available commands

pm-help

Then, on your host, open a browser and go to the following URLs for the more user-friendly ways to trade and watch the market:

# The trading platform to buy/sell equities. Requires log-in using
# one of the API keys defined in the `engine_config.yaml`
Trader GUI       :  http://localhost:8093.

# The terminal to watch the movements of the market
Trading terminal :  http://localhost:8090

# One symbol's full order book, session statistics and trade tape
# (the browser companion to pm-viewer)
Order book       :  http://localhost:8094

# The central log server to observe what is happening internally
# in the exchange platform
Log viewer       :  http://localhost:8091      

# The Swagger REST-API documentation. The exchange can be
# completely run using REST commands
REST API docs    :  http://localhost:8080/docs

Configuring the exchange can be done by either 1) Manually edit the config YAML file (and then verify/lint it with pm-cverifier) or, 2) generate it in scripts using the pm-config-gen tool or, 3) using the Web application reachable at :

Config builder   :  http://localhost:8092

Python package — the processes on your own machine:

pipx install edumatcher
mkdir edumatcher-session && cd edumatcher-session
pm-setup

The pm-setup command will create a new data-directory and install a default example engine-config file with ten symbols.

Here you start each process yourself. That is slower, but it is the better way to learn the system: you see what each process does, and what breaks when one is missing. Starting the system should be done in a particular order for a smooth experience. For example, the engine is not actually the first process you should start; that would be the log-server (pm-log-srv). The reason being that all other processes will automatically send their logs to the log-server if they can find it on startup. Having all logs centralized in the log-server is much better for trouble-shooting (and learning!) than having to manually reaad through a lot of different log files.

As an administer the system offers a process management tool called pm-opctl-cli that allows you to easily start, stop and check the health of a running system. The tool can start the full system in the optimal order with one command as the example below shows. In this example we have installed the system in a virtual machine (using Multipass and deployment/vm/mknode.sh utility script)

ubuntu@ems:~$ pm-opctl-cli start
Starting pm-opctl configuration 'default' from /home/ubuntu/.local/share/edumatcher/emo-config.yaml
Data directory: /home/ubuntu/.local/share/edumatcher
  started log (pid 21210): pm-log-srv
  started audit (pid 21212): pm-audit --verbose
  started stats (pid 21214): pm-stats --verbose
  started clearing (pid 21216): pm-clearing --verbose
  started engine (pid 21218): pm-engine --verbose
  started scheduler (pid 21220): pm-scheduler --daily --verbose
  started market-data-gwy (md-gwy) (pid 21222): pm-md-gwy --verbose
  started post-trade-gwy (ralf-gwy) (pid 21224): pm-ralf-gwy --verbose
  started drop-copy-gwy (dc-gwy) (pid 21226): pm-dc-gwy --verbose
  started api-desk-gwy (api-gwy) (pid 21228): pm-api-gwy --verbose --instance desk
  started api-dashboards-gwy (api-gwy) (pid 21231): pm-api-gwy --verbose --instance dashboards
  started alf-gwy (pid 21233): pm-alf-gwy --verbose
  started balf-gwy (pid 21235): pm-balf-gwy --verbose
  started index-srv (pid 21239): pm-index --verbose

Later we can check the if all processes are running as expected using the list subcommand as in:

ubuntu@ems:~$ pm-opctl-cli list
pm-opctl profile: default
data directory: /home/ubuntu/.local/share/edumatcher
  Process                  PID   Uptime  RSS(MB)  Status          Details
----------------------------------------------------------------------------------------------
✅ log                   106208    00:51     40.0  running         tcp connect to 127.0.0.1:5600 ok
✅ audit                 106210    00:51     38.2  running         no healthcheck or tcp check configured
✅ stats                 106212    00:51     40.8  running         healthcheck passed
✅ clearing              106214    00:51     42.5  running         no healthcheck or tcp check configured
✅ engine                106216    00:51     51.3  running         tcp connect to 127.0.0.1:5555 ok
✅ scheduler             106218    00:51     49.9  running         no healthcheck or tcp check configured
✅ market-data-gwy (md-gwy)  106220    00:51     37.9  running         tcp connect to 127.0.0.1:5570 ok
✅ post-trade-gwy (ralf-gwy)  106222    00:51     37.7  running         tcp connect to 127.0.0.1:5580 ok
✅ drop-copy-gwy (dc-gwy)  106224    00:51     37.7  running         tcp connect to 127.0.0.1:5590 ok
✅ api-desk-gwy (api-gwy)  106264    00:51     71.9  running         tcp connect to 127.0.0.1:8080 ok
✅ api-dashboards-gwy (api-gwy)  106268    00:51     71.9  running         tcp connect to 127.0.0.1:8081 ok
✅ alf-gwy               106270    00:51     37.9  running         tcp connect to 127.0.0.1:5565 ok
✅ balf-gwy              106272    00:51     38.1  running         tcp connect to 127.0.0.1:5560 ok
✅ index-srv             106276    00:51     38.3  running         no healthcheck or tcp check configured

Forgot what a command does?

With this many pm-* commands, run pm-help any time for a one-screen table of every one of them with a one-sentence explanation, grouped by category. Run pm-help pm-opctl-cli (or any other command name) for a full man page: its options, ports, related commands, and a worked example. pm-man is the same tool under a second, more familiar name.

Containers pipx / Poetry
Time to a running exchange one command a few, plus pm-setup, pm-opctl-cli
Web applications five, already wired to the exchange started separately
Where pm-* commands run inside the container, after ./edumatcher.sh shell your own shell
Data on disk ~/.edumatcher/data ~/.local/share/edumatcher
Best for seeing the whole system; classrooms and demos learning the pieces; developing against them

Commands in this chapter are shown in installed form. In a Poetry checkout, prefix every pm-* command with poetry run. In a container, run them after ./edumatcher.sh shell, where they are already on PATH and the data directory is already set.

Environment variables

EduMatcher has one variable that decides where everything lives:

Variable Default in installed mode Default in source checkout Purpose
EDUMATCHER_DATA_DIR ~/.local/share/edumatcher <repo>/src/data/ Root directory for deployed reference data and runtime data files

Every process reads the deployed config from <EDUMATCHER_DATA_DIR>/ref_data/engine_config.json. Set this variable once in your shell profile or launcher so every process in a session sees the same configuration and writes to the same data area.

How the default is selected

The data directory is selected when the EduMatcher Python package is imported; it is not selected from the process's current working directory:

  1. If EDUMATCHER_DATA_DIR is set, its expanded and absolute path wins in both development and installed deployments.
  2. Otherwise, EduMatcher checks where edumatcher/config.py is installed. If its package parent is named src, EduMatcher treats the process as running from a source checkout and uses <repo>/src/data/.
  3. Otherwise, EduMatcher treats the package as installed and uses ~/.local/share/edumatcher (for example, /Users/<user>/.local/share/edumatcher on macOS).

This means running an installed command from inside a repository does not make it a source checkout, and running a Poetry command from another directory does not change the source-checkout data location. All processes in one exchange must use the same EDUMATCHER_DATA_DIR value when an explicit shared location is needed.

The authored YAML may live elsewhere, but deployment always installs the compiled artifact and its copied source under the selected data directory:

<DATA_DIR>/ref_data/engine_config.json
<DATA_DIR>/ref_data/engine_config.yaml

Configured relative runtime paths such as data/stats.db are also resolved under <DATA_DIR>, so they refer to the same files regardless of the command's working directory. Absolute paths remain explicit overrides.

A container sets this for you: EDUMATCHER_DATA_DIR is /data inside, bind- mounted from ~/.edumatcher/data (or deployment/docker/data from a checkout), so the databases and logs are ordinary files on your disk.

Other environment variables exist — which network interface each process binds, where the log failover directory goes — but none of them are needed for a first session. They are all in Installation.

Configuration: edit YAML, deploy artifact

EduMatcher separates the file you edit from the file the exchange runs.

File Purpose
engine_config.yaml Authored configuration. Keep this in your session directory or version control. Edit this.
<EDUMATCHER_DATA_DIR>/ref_data/engine_config.json Compiled deployed artifact. Every running process reads this. Do not edit it by hand.

Why this matters: a multi-process exchange is dangerous if each process can be pointed at a different file. EduMatcher avoids that. You deploy once, then every process reads the same artifact.

Typical loop:

# Start from the sample copied by pm-setup, or generate a new authored file
pm-config-gen \
    --symbols AAPL MSFT TSLA \
    --participants TRADER01:TRADER TRADER02:TRADER OPS01:ADMIN MM01:MARKET_MAKER \
    --output engine_config.yaml

# Validate only
pm-config-deploy --check engine_config.yaml

# Validate, compile and install as the deployed artifact
pm-config-deploy engine_config.yaml

# Confirm where the deployed config lives
pm-config-deploy --show

# Show an overview of the engine config
pm-config-show

For the full field reference, see Configuration. For a visual editor, see Configuration GUI. For a catalog of ready-made examples, see Example Engine Configs.

Your first session: one trade in five minutes

This path uses the sample configuration installed by pm-setup. It has TRADER01, TRADER02, OPS01, MM01 and symbols such as AAPL, MSFT and TSLA. Session scheduling is disabled in the sample, so matching is available immediately.

Open three terminals in the same session environment.

Using the container install?

The exchange is already running — skip Terminal 1. Open two shells inside the container instead of two on your host:

cd ~/.edumatcher
./edumatcher.sh shell        # in each of two terminals

Then run the pm-alf-console commands below in those. The container's default configuration is s10-basic, which includes the same symbols (AAPL, MSFT, TSLA, and seven more) and the same gateways (TRADER01, TRADER02, OPS01, MM01) as the pm-setup sample, so every command below works unchanged. pm-config-show prints what is actually deployed if you want to confirm. You can also watch the trade land in the browser terminal on http://localhost:8090.

Terminal 1 - start the engine

pm-engine --verbose

Wait until the engine has bound its sockets and printed the deployed configuration it is using. Leave this process running.

Terminal 2 - connect the seller

pm-alf-console --id TRADER02

At the TRADER02> prompt, post a resting sell order:

NEW|SYM=AAPL|SIDE=SELL|TYPE=LIMIT|QTY=100|PRICE=150.00|TIF=DAY

Terminal 3 - connect the buyer

pm-alf-console --id TRADER01

At the TRADER01> prompt, buy at the same price:

NEW|SYM=AAPL|SIDE=BUY|TYPE=LIMIT|QTY=100|PRICE=150.00|TIF=DAY

Both gateways should report a fill. The engine matched the buy and sell because the bid price was high enough to trade with the resting ask.

sequenceDiagram
    participant S as TRADER02
    participant E as pm-engine
    participant B as TRADER01

    S->>E: NEW SELL AAPL 100@150.00
    E-->>S: ACK -> RESTING
    B->>E: NEW BUY AAPL 100@150.00
    E-->>B: FILL BUY 100@150.00
    E-->>S: FILL SELL 100@150.00
    E-->>E: publish trade.executed

That is the core of the system. Everything else in EduMatcher either changes what orders can do, changes when matching is allowed, observes what happened, or exposes the same activity to other clients.

What if the order fills before the other trader acts?

Your configuration may contain market-maker seed quotes. In that case an aggressive order can trade against the seeded quote instead of waiting for the other participant. That is not a bug; it means the book already had liquidity. Read Market Making when you are ready for that layer.

Add one process at a time

After the first trade, add observers. This is the safest way to learn the system: start with the engine and gateways, then add one new responsibility at a time.

New to trading?

If exchanges and trading are new to you, don't stop at the five-minute quickstart above — read these two concept chapters next, in order:

  1. The Order Book — the fundamental structure every exchange is built on. It is absolutely crucial to fully understand and internalise what this structure is and how it works before going further. Follow up with The Order Book: Deep Dive once the basics are solid.
  2. Your First Trade — a guided, hands-on walkthrough that re-runs the quickstart above one step at a time, explaining every field, every response, and the maker/taker and P&L concepts behind them.

To explore the processes the following table will be helpful

When you want to... Start this Then read
See one live order book pm-viewer --symbol AAPL The Order Book, Order Types, Processes
See a multi-symbol board or ticker pm-board, pm-ticker Statistics and Reporting
Record OHLCV, VWAP and mid prices pm-stats Statistics and Reporting
Track positions and P&L pm-clearing P&L & Clearing
Capture a full audit log pm-audit Audit Trail, Persistence
Drive opening and closing phases by time pm-scheduler Auctions & Scheduling
Run operator commands pm-admin or pm-admin-cli Risk Controls, Exchange Commands
Publish external market data pm-md-gwy Market Data Feed (CALF)
Open the browser trader info terminal web-apps/terminal-gui/ Trader Information Terminal
Open the browser trader platform web-apps/trader-gui/ Trader Information Terminal
See one live order book in the browser web-apps/book-gui/ Order Book Viewer
Collect logs from all processes pm-log-srv, then pm-log-cli or pm-log-ui Centralized Log Server, Log Operator Console

| Open the browser trading terminal, order book viewer, log console or config builder | the container stack, or make dev in web-apps/<app> | Installation, Trader Information Terminal, Order Book Viewer, Log Operator Console |

Note: Starting the Web-application backends (to be able to use the GUIs) it is easiest to use one of the pre-build containers. See the README.md file in respective application catalogue for details. To use the trading terminal you will also need to authenticate with an API key that was specified in the engine_config.yaml file for the API Gateways.

The full process catalog is in Processes. Use that chapter when you want exact command-line flags and startup dependencies.

Once you know which processes you want, you do not have to start them one at a time forever. pm-opctl-cli start brings up a whole named profile — micro, mini, default or mm-demo — writes each process's log to a file, and reports the lot with pm-opctl-cli list. It is what the container runs internally, and it works the same on the host. See Running the Exchange.

What the major feature areas are for

Trading and order behavior

Start here if you are a trader, market maker or instructor building exercises.

Operations and controls

Start here if you are running the venue.

Observation, reports and records

Start here if you need to explain or audit what happened.

External connectivity

Start here if you are writing a client or integration.

Roadmaps by role

You can read the whole guide front to back, but most readers should not start that way. Pick the path that matches what you are trying to do.

Role or goal Suggested path
Beginner learning the market How an Exchange Works -> this page -> Training chapters 00-08 -> ALF Console
Student trader Installation -> first session -> ALF Console -> Order Types -> Auctions & Scheduling
Instructor running a class Installation -> Configuration -> Running the Exchange -> Processes -> Training
Market maker Market Making -> Market-Maker Bot -> ALF Console
Operator / supervisor Running the Exchange -> Risk Controls -> Exchange Commands -> Centralized Log Server
Analyst / auditor P&L & Clearing -> Statistics and Reporting -> Audit Trail -> Persistence
Dashboard or feed developer External Protocols Overview -> CALF or API Gateway -> protocol appendices
Core developer Developer install -> Architecture -> Developer Practice -> The Development Loop -> tests for the subsystem you are changing
Web application developer Installation -> The Development Loop -> the app's own README.md -> API Gateway or CALF

Three details worth knowing early

Prices are exact integer ticks internally

Displayed prices look like money: 150.25. Internally, the engine matches on integer ticks. With tick_decimals: 2, 150.25 is stored as 15025 ticks. This avoids floating-point drift in matching, turnover and reports.

Most commands, CLIs and APIs convert for you. Raw SQLite rows may show the tick form. Read Prices are stored as integer ticks before doing direct SQL analysis.

Instants and trading dates are different

Event timestamps are UTC instants. Daily OHLCV, clearing summaries and index rows are grouped by the exchange's local trading date. If a session crosses midnight UTC, one trading day can span two UTC dates.

If you run pm-stats and pm-clearing with a non-default timezone, give both the same value:

pm-stats --timezone Europe/Stockholm
pm-clearing --timezone Europe/Stockholm

Read The trading date before comparing daily reports.

Empty books are normal until someone provides liquidity

An exchange does not create bids and asks by itself. The book has liquidity only when orders rest in it. For demos, you can provide liquidity manually, by seeded market-maker quotes in configuration, or with pm-mm-bot / AI traders.

If a beginner sees no fill, the most common reason is simple: nobody is resting on the other side at a price that crosses.

Tip: Use the pm-viewer --symbol <SYMBOL> command to view a selected symbol's order book. This tool sits on the bus so this command will only work if you are running t he command on the "inside" of the container/VM with one exception. If the container was started with ZMQ=1 . This makes the bus ports available outside the container, for example as make up ZMQ=1 (in deployment/docker/) Then you can run the pm-viewer directly from the host.

Quick glossary

Term Meaning
Order book The sorted resting buy and sell orders for one symbol
Bid / ask Best available buy price / best available sell price
Spread Difference between best ask and best bid
Fill An execution: two orders matched and traded
TIF Time-in-force: how long an order may remain active (DAY, GTC, ATO, ATC, etc.)
Auction A call phase where orders collect first and execute together at an equilibrium price
Market maker A participant expected to quote both bid and ask liquidity
Circuit breaker A risk control that halts a symbol after a configured price move
Drop copy A copy of fills sent to compliance, audit or risk systems
CALF EduMatcher's external market-data protocol (Channel-ALF)
RALF EduMatcher's external post-trade dissemination protocol (Reconcilliation-ALF)
LALF EduMatcher's centralized log protocol (Logging-ALF)

For the full vocabulary, see the Glossary.

Where to go next

If you want to... Go to
Be told what to do next, step by step A Path Through the Guide
Follow a guided, hands-on lab with exercises Training
Get the whole system running, GUIs included Installation
Build your own session configuration Configuration
Operate a session — start, monitor, troubleshoot, shut down Running the Exchange
See the complete runtime map Processes
Write a client against a protocol External Protocols Overview
Work on EduMatcher itself Developer Practice

The rest of the guide is large, but it is not a wall. It is a map of a whole exchange. Start with one process, one symbol and one trade; then add the next layer when the previous one makes sense.

If you are new to the trading world it is probably worth reading the included "How an Exchange Work" book available both as PDF and HTML in the documentation site.