hypercall_engine/lib.rs
1//! Pure deterministic engine state machine for the Hypercall options exchange.
2//!
3//! `hypercall-engine` is the financial core of the Hypercall matching engine,
4//! extracted into a standalone crate with zero runtime dependencies. It contains
5//! position tracking, MMP (Market Maker Protection) state, and the command/event
6//! types that define the engine's public interface.
7//!
8//! # Design Constraints
9//!
10//! This crate is deliberately minimal. It has:
11//!
12//! - **No async runtime.** Every method is synchronous. No tokio, no futures.
13//! - **No database.** Persistence is the runtime's job, routed through [`traits::JournalWriter`].
14//! - **No networking.** Event distribution goes through [`traits::EventSink`].
15//! - **No filesystem access.** The engine never touches `std::fs`.
16//! - **No `unsafe` code.**
17//!
18//! These constraints exist so that the engine is fully deterministic: given the same
19//! sequence of commands, it always produces the same state and events. This property
20//! enables crash recovery via journal replay, state replication to standby instances,
21//! and independent validator verification.
22//!
23//! # Architecture
24//!
25//! All state transitions follow a pure function pattern:
26//!
27//! ```text
28//! Commands IN --> apply(state, cmd) --> (new_state, events)
29//! ```
30//!
31//! External data (spot prices, IV surfaces, deposits, orders) enters as
32//! [`EngineCommand`] variants. The engine processes each command synchronously
33//! and produces an [`ApplyOutput`] containing the resulting events and a state
34//! hash for replication.
35//!
36//! The outer `hypercall` crate provides the runtime (tokio, channels, WAL persistence)
37//! and implements the traits defined in [`traits`].
38//!
39//! # Modules
40//!
41//! - [`command`] -- Input commands ([`EngineCommand`]) and output ([`ApplyOutput`]).
42//! - [`position`] -- Position tracking with fill application, weighted-average entry
43//! price, and realized PnL calculation ([`EnginePosition`]).
44//! - [`mmp`] -- Market Maker Protection state machine with configurable rolling windows,
45//! greek limits (quantity, delta, vega), and timed freeze ([`EngineMmpState`]).
46//! - [`traits`] -- Trait boundary between engine and runtime: [`traits::EventSink`],
47//! [`traits::JournalWriter`], [`traits::CommandPublisher`].
48//! - `proofs` (cfg-gated, `#[cfg(kani)]`) -- Kani bounded model checking harnesses
49//! that verify conservation of value, PnL sign consistency, MMP correctness, and
50//! zero-sum matching. Run with `cargo kani -p hypercall-engine`.
51//!
52//! # Trait Boundary
53//!
54//! The runtime implements three traits to wire the engine into production:
55//!
56//! - [`traits::EventSink`] -- Routes engine events to WebSocket clients, persistence,
57//! and downstream caches.
58//! - [`traits::JournalWriter`] -- Writes commands to a WAL for crash recovery.
59//! - [`traits::CommandPublisher`] -- Replicates commands to standby instances.
60//!
61//! In tests, these traits can be stubbed with in-memory implementations.
62//!
63//! # Standalone / Validator Usage
64//!
65//! Because the engine is a pure state machine, external validators can import
66//! this crate, replay the command stream, and compare state hashes:
67//!
68//! ```rust,ignore
69//! use hypercall_engine::{EngineCommand, ApplyOutput};
70//!
71//! // For each command from the sequencer's stream:
72//! let output: ApplyOutput = engine.apply(command);
73//! assert_eq!(output.hash, sequencer_published_hash);
74//! ```
75//!
76//! Hash divergence constitutes proof of sequencer misbehavior.
77
78pub mod accounting;
79pub mod admission;
80pub mod command;
81pub mod fee;
82pub mod greeks;
83pub mod instrument;
84pub mod margin_admission;
85pub mod matching;
86pub mod mmp;
87pub mod nonce;
88pub mod order_index;
89pub mod orderbook;
90pub mod position;
91#[cfg(kani)]
92mod proofs;
93pub mod traits;
94
95pub use accounting::{
96 apply_fill_accounting, apply_fill_position_accounting, calculate_fill_accounting,
97 fill_premium_delta, FillAccounting, FillAccountingContext, FillAccountingPosition,
98 FillCashSettlement,
99};
100pub use admission::{OrderAdmissionDecision, OrderAdmissionInput, OrderAdmissionState};
101pub use command::{ApplyOutput, EngineCommand};
102pub use fee::{FeeCalculation, FeeConfig, FeeService};
103pub use instrument::{contract_key, is_option_symbol, perp_underlying, ParsedInstrument};
104pub use margin_admission::{
105 decide_portfolio_margin, decide_standard_margin, margin_decision_result,
106 MarginAdmissionDecision, PortfolioMarginAdmissionInput, StandardMarginAdmissionInput,
107};
108pub use matching::{MmpTriggerIntent, OptionMatchOutcome};
109pub use mmp::{EngineMmpState, MmpFillRecord};
110pub use nonce::{nonce_within_time_bounds, BoundedNonceSet};
111pub use order_index::{EngineOrderIndex, OpenSellPositionInfo, OrderSummary};
112pub use orderbook::{L2UpdateSet, MatchResult, Order, OrderBook, OrderBookEvent, OrderRecord};
113pub use position::{EnginePosition, PositionFillTransition};