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:
- [
EXECUTION_TEXT_CAP]
Identifier types:
- [
FixedAscii<N>] - [
ClientOrderId] - [
VenueOrderId] - [
ExecutionId] - [
AccountId] - [
RouteId] - [
StrategyId] - [
VenueId] - [
InstrumentId] - [
ExecutionText]
Errors and domain types:
- [
ExecutionCoreError] - [
ExecutionSymbol] - [
OrderQty] - [
OrderPrice] - [
OrderSide] - [
OrderType] - [
TimeInForce] - [
OrderStatus] - [
ExecutionType]
Request and report types:
- [
OrderRequest] - [
CancelRequest] - [
AmendRequest] - [
ExecutionEvent]
State-machine types:
- [
OrderState] - [
OrderStateMachine]
Risk types:
- [
RiskRejectReason] - [
RiskDecision] - [
RiskLimits] - [
RiskContext] - [
RiskCheck] - [
BasicRiskGate]
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 ;
let id = new?;
assert_eq!;
assert_eq!;
assert!;
let too_long = "X".repeat;
assert!;
# Ok::
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 ;
let symbol = new?;
let qty = new?;
let price = new?;
assert_eq!;
assert_eq!;
assert_eq!;
# Ok::
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 ;
let req = OrderRequest ;
let mut state = new;
let ack = accepted;
state.apply?;
assert_eq!;
# Ok::
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 ;
let gate = new;
// 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