Expand description
Low-latency execution-domain primitives for Orderflow.
§of_execution_core
of_execution_core is the canonical execution-domain model for Orderflow.
It contains the low-level types used by the order-management and execution
layers: fixed-size identifiers, typed order requests, execution reports,
order-state transitions, and pre-trade risk contracts.
This crate is intentionally small. It has no broker SDKs, no sockets, no worker threads, no JSON payloads, and no dependency on the market-data analytics runtime. Higher-level crates build on it:
of_executionadds routes, adapters, journals, simulated execution, concurrency, and OMS helpers.of_execution_adaptersadds optional provider adapter scaffolds.of_ffi_c, Python, and Java expose execution APIs through additive handles and classes.
§First Release: 0.1.0
of_execution_core starts at 0.1.0 even though the broader Orderflow release
line is 0.4.0. This crate is a new public execution-domain surface. It is
kept independent from the mature analytics crates so its identifiers, state
machine, and risk contracts can stabilize honestly without implying the same
API age as of_core.
Compatibility expectations:
- all public APIs are intended to be additive where possible;
- provider adapters should pin compatible
0.1.xversions while the execution trait family matures; - analytics crates do not depend on this crate;
- bindings expose these concepts through additive execution handles/classes, not by changing existing analytics types.
§Design Goals
- Keep hot-path order data as typed structs, not dynamic maps.
- Use fixed-size ASCII identifiers instead of heap-owned strings.
- Use integer-normalized prices and quantities.
- Preserve deterministic, auditable state transitions.
- Keep provider-specific behavior outside the core schema.
- Make pre-trade risk decisions structured and testable.
- Keep the model suitable for Rust, C ABI, Python, and Java integration.
§Public API Inventory
Constants:
Identifier types:
FixedAscii<N>ClientOrderIdVenueOrderIdExecutionIdAccountIdRouteIdStrategyIdVenueIdInstrumentIdExecutionText
Errors and domain types:
ExecutionCoreErrorExecutionSymbolOrderQtyOrderPriceOrderSideOrderTypeTimeInForceOrderStatusExecutionType
Request and report types:
State-machine types:
Risk types:
§Identifier Model
Execution identifiers use FixedAscii<N>. A fixed ASCII value stores a length
and an inline byte array. This avoids heap allocation in ordinary command and
report structs, keeps FFI boundaries predictable, and prevents accidental
Unicode normalization differences between host languages.
| Alias | Capacity | Purpose |
|---|---|---|
ClientOrderId | 40 | Strategy/client-assigned order id |
VenueOrderId | 48 | Venue-assigned order id |
ExecutionId | 48 | Venue fill/report id |
AccountId | 32 | Trading account |
RouteId | 32 | Execution route |
StrategyId | 32 | Strategy attribution |
VenueId | 16 | Venue/exchange id |
InstrumentId | 32 | Venue-native instrument id |
ExecutionText | 128 | Bounded diagnostic text |
Identifier rules:
- Empty identifiers are allowed where a venue value is not known yet.
- Non-ASCII input returns
ExecutionCoreError::NonAsciiIdentifier. - Over-capacity input returns
ExecutionCoreError::IdentifierTooLong. - Equality, hashing,
Debug, andDisplayuse the validated string content.
Example:
use of_execution_core::{ClientOrderId, ExecutionCoreError};
let id = ClientOrderId::new("STRAT-0001")?;
assert_eq!(id.as_str(), "STRAT-0001");
assert_eq!(id.capacity(), 40);
assert!(!id.is_empty());
let too_long = "X".repeat(41);
assert!(matches!(
ClientOrderId::new(&too_long),
Err(ExecutionCoreError::IdentifierTooLong { .. })
));§Symbols, Quantity, And Price
ExecutionSymbol is the venue-native execution symbol:
venue: venue or exchange identifierinstrument: venue-native instrument id
OrderQty and OrderPrice are integer-normalized wrappers. Use symbol
metadata outside this crate to convert user-facing decimals into the integer
representation expected by a provider.
OrderQty::new rejects zero and negative values. OrderPrice::new rejects
zero and negative values. Some request fields still use OrderPrice(0) as a
sentinel when a price is not applicable, for example a market order limit
price.
use of_execution_core::{ExecutionSymbol, OrderPrice, OrderQty};
let symbol = ExecutionSymbol::new("CME", "ESM6")?;
let qty = OrderQty::new(10)?;
let price = OrderPrice::new(505_000)?;
assert_eq!(symbol.instrument.as_str(), "ESM6");
assert_eq!(qty.0, 10);
assert_eq!(price.0, 505_000);§Order Classification
OrderSide variants:
BuySell
OrderType variants:
MarketLimitStopStopLimit
TimeInForce variants:
DayGtcIocFokGtd
These are canonical values. Provider adapters can translate them to native protocol values or reject unsupported combinations through capabilities/risk.
§Request Types
§OrderRequest
OrderRequest is the canonical new-order command.
Fields:
client_order_id: client-assigned id for the new orderaccount_id: trading accountroute_id: execution routestrategy_id: strategy attributionsymbol: target venue/instrumentside: buy/sellorder_type: canonical typetime_in_force: canonical TIFquantity: requested quantitylimit_price: limit price, or zero when not applicablestop_price: stop trigger price, or zero when not applicablets_exchange_ns: exchange/session timestamp when knownts_recv_ns: local creation/receive timestamp
OrderRequest::validate checks:
- quantity must be positive
- limit orders require positive
limit_price - stop orders require positive
stop_price - stop-limit orders require both positive
limit_priceandstop_price
§CancelRequest
CancelRequest carries:
client_order_id: client id for the cancel request itselforig_client_order_id: client id of the order being cancelledaccount_idroute_idsymbolts_exchange_nsts_recv_ns
This mirrors FIX-style cancel semantics where the cancel command may need a new client id separate from the original order id.
§AmendRequest
AmendRequest is the canonical cancel/replace command. It carries a new
client id, the original client id, replacement quantity, replacement limit
price, and timestamps. The higher-level engine checks that the original order
is locally known before routing the request.
§Execution Reports
ExecutionType explains why an execution event exists:
AckRejectTradeCancelPendingCancelAckCancelRejectReplacePendingReplaceAckReplaceRejectExpiredStatusRestatedDegraded
OrderStatus explains the state after the event is applied. Terminal states
are detected with OrderStatus::is_terminal().
ExecutionEvent is the canonical report shape. It includes:
- current and original client order ids
- venue order id
- execution id
- account, route, and symbol
- execution type and resulting order status
- last fill quantity/price
- cumulative quantity
- leaves quantity
- average price
- exchange and receive timestamps
- structured rejection reason
- bounded diagnostic text
Constructors:
ExecutionEvent::accepted(&OrderRequest, VenueOrderId)ExecutionEvent::rejected(&OrderRequest, RiskRejectReason, ExecutionText)
Provider adapters can construct events directly, but these helpers keep common local ack/reject reports consistent.
§Order State Machine
OrderStateMachine owns one OrderState and applies ExecutionEvent
values. Illegal transitions return ExecutionCoreError::InvalidTransition.
Typical lifecycle:
OrderStateMachine::new(&request)starts atPendingNew.ExecutionType::Ackmoves toNew.ExecutionType::Trademoves toPartiallyFilledorFilled.ExecutionType::CancelAckmoves toCancelled.ExecutionType::ReplaceAckmoves toReplacedand updates the active client order id.ExecutionType::Restatedupdates local state from recovery reports.
The state machine is deliberately strict. It accepts status-style reports after terminal states, but rejects ordinary lifecycle transitions that would mutate a terminal order.
use of_execution_core::{
AccountId, ClientOrderId, ExecutionEvent, ExecutionSymbol, OrderPrice,
OrderQty, OrderRequest, OrderSide, OrderStateMachine, OrderType, RouteId,
StrategyId, TimeInForce, VenueOrderId,
};
let req = OrderRequest {
client_order_id: ClientOrderId::new("C1")?,
account_id: AccountId::new("ACC")?,
route_id: RouteId::new("SIM")?,
strategy_id: StrategyId::new("STRAT")?,
symbol: ExecutionSymbol::new("SIM", "ES")?,
side: OrderSide::Buy,
order_type: OrderType::Limit,
time_in_force: TimeInForce::Day,
quantity: OrderQty::new(1)?,
limit_price: OrderPrice::new(5000)?,
stop_price: OrderPrice(0),
ts_exchange_ns: 0,
ts_recv_ns: 1,
};
let mut state = OrderStateMachine::new(&req);
let ack = ExecutionEvent::accepted(&req, VenueOrderId::new("V1")?);
state.apply(&ack)?;
assert_eq!(state.state().client_order_id, req.client_order_id);§Risk Model
RiskLimits is the basic per-route/account/symbol risk configuration:
kill_switchmax_order_qtymax_order_notionalmax_open_ordersmax_open_notionalprice_band_ticks
Zero disables numeric checks. RiskLimits::default() enables the kill switch,
so callers must explicitly disable it for test or live routes that should
accept orders.
RiskContext is supplied by higher-level engines. It includes runtime facts:
- open order count
- open notional
- reference price
- duplicate client order id flag
- whether the account, route, and symbol are enabled
- whether the order type and TIF are supported
RiskCheck is the extension trait:
check_newcheck_amendcheck_cancel
BasicRiskGate implements deterministic checks for the basic limit set.
use of_execution_core::{BasicRiskGate, RiskCheck, RiskLimits};
let gate = BasicRiskGate::new(RiskLimits {
kill_switch: false,
max_order_qty: 100,
max_order_notional: 1_000_000,
max_open_orders: 5,
max_open_notional: 5_000_000,
price_band_ticks: 0,
});
// Higher-level engines build RiskContext and call the gate before routing.
let _ = gate;§Low-Latency Notes
- Requests and reports are fixed-layout structs.
- Identifiers are inline fixed-size ASCII fields.
- Numeric fields are integers.
- Validation is explicit and local.
- The crate does not allocate for ordinary order/request/event structs.
- Provider strings and protocol-specific payloads should be translated at the adapter boundary before entering this model.
§What This Crate Does Not Do
This crate does not:
- connect to brokers or exchanges
- own order routes
- run worker threads
- expose a C ABI directly
- persist journals
- reconcile venue open orders
- enforce provider rate limits
- parse FIX/REST/WebSocket messages
Use of_execution for routing, adapter calls, simulated execution,
journaling, recovery, and OMS helpers.
§Documentation
Additional project documentation:
docs/handbook/05g-of-execution-core-reference.mddocs/handbook/09-oms-architecture.mddocs/handbook/11-low-latency-design.md
Structs§
- Amend
Request - Amend/cancel-replace request.
- Basic
Risk Gate - Deterministic pre-trade risk gate.
- Cancel
Request - Cancel request.
- Execution
Event - Canonical execution event.
- Execution
Symbol - Execution symbol in venue-native format.
- Fixed
Ascii - Fixed-size ASCII field used for low-allocation identifiers.
- Order
Price - Integer-normalized order price.
- Order
Qty - Integer-normalized order quantity.
- Order
Request - New order request.
- Order
State - Current order state.
- Order
State Machine - Deterministic order state machine.
- Risk
Context - Runtime risk context supplied by the execution engine.
- Risk
Decision - Risk decision.
- Risk
Limits - Static risk limits for one route/account scope.
Enums§
- Execution
Core Error - Execution-core error.
- Execution
Type - Canonical execution report purpose.
- Order
Side - Buy/sell order side.
- Order
Status - FIX-style canonical order status.
- Order
Type - Supported canonical order types.
- Risk
Reject Reason - Structured risk rejection reason.
- Time
InForce - Time-in-force policy.
Constants§
- EXECUTION_
TEXT_ CAP - Maximum bytes stored in an execution diagnostic text field.
Traits§
- Risk
Check - Pre-trade risk-check contract.
Type Aliases§
- Account
Id - Trading account identifier.
- Client
Order Id - Client-assigned order identifier.
- Execution
Id - Venue execution/fill identifier.
- Execution
Text - Bounded diagnostic text.
- Instrument
Id - Instrument identifier in venue/native format.
- RouteId
- Execution route identifier.
- Strategy
Id - Strategy identifier used for attribution.
- VenueId
- Venue identifier used by execution routing.
- Venue
Order Id - Venue-assigned order identifier.