FerroMatch
Matching cycle
Command, match, event, journal: the FerroMatch execution loop.
The core loop is intentionally small: orders enter the book, the book returns deterministic match results, and the journal records durable status and trade entries without changing matching semantics.
use std::path::Path;
use ferromatch_core::{Order, OrderBook, OrderStatus, OrderType, Side, TimeInForce};
use ferromatch_journal::{EventJournal, JournalEntry};
let mut book = OrderBook::new("AAPL");
let mut journal = EventJournal::create(Path::new("session.fmj"), 1_024)?;
let orders = [
Order::new(1, 185_000_000, 100, Side::Sell, OrderType::Limit, TimeInForce::GoodTilCancel, 0),
Order::new(2, 185_000_000, 100, Side::Buy, OrderType::Limit, TimeInForce::GoodTilCancel, 0),
];
for order in orders {
let submitted_id = order.id;
let result = book.submit(order)?;
let status_entry = JournalEntry::order_status(
0,
0,
submitted_id,
result.status as u8,
result.remaining_quantity,
0,
);
journal.append(&status_entry);
for fill in &result.fills {
let trade_entry = JournalEntry::trade(
0,
fill.timestamp,
fill.taker_order_id,
fill.maker_order_id,
fill.price,
fill.quantity,
0,
);
journal.append(&trade_entry);
}
}
assert_eq!(book.order_count(), 0);
# Ok::<(), Box<dyn std::error::Error>>(())The journal is the contract between live matching, recovery, and replay. Consumers should depend on status and trade entries rather than inspecting book internals.