FerroMatch

Getting started

Run a deterministic order-book match cycle with FerroMatch.

FerroMatch exposes the matching engine as explicit orders, match results, and journal entries. Price-time priority and book state live in the core crate; persistence and transport are separate layers.

Add the workspace crates

[dependencies]
ferromatch-core = { version = "0.2" }
ferromatch-io = { version = "0.2" }
ferromatch-journal = { version = "0.2" }

Run a match cycle

Construct Order values, submit them to an OrderBook, and consume the returned MatchResult. Prices use the crate convention of fixed-point integers scaled by 1,000,000.

use ferromatch_core::{Order, OrderBook, OrderStatus, OrderType, Side, TimeInForce};
 
let mut book = OrderBook::new("AAPL");
 
book.submit(Order::new(
    1,
    185_000_000,
    100,
    Side::Sell,
    OrderType::Limit,
    TimeInForce::GoodTilCancel,
    0,
))?;
 
let result = book.submit(Order::new(
    2,
    185_000_000,
    100,
    Side::Buy,
    OrderType::Limit,
    TimeInForce::GoodTilCancel,
    0,
))?;
 
assert_eq!(result.status, OrderStatus::Filled);
assert_eq!(result.fills.len(), 1);
# Ok::<(), Box<dyn std::error::Error>>(())

Server path

For a runtime deployment, ferromatch_server owns the TCP server, engine thread, publisher, recovery flow, and stress harness. Keep the matching core free of transport concerns; wire external clients through the server layer.

ferromatch-server --port 9876 --symbol AAPL

Use the core API reference for matching semantics and the journal API for replayable persistence.