OpenPit: Pre-trade Integrity Toolkit
openpit is an embeddable pre-trade risk SDK for integrating policy-driven
risk checks into trading systems.
For an overview and links to all resources, see the project website openpit.dev. For full project documentation, see the repository README. For conceptual and architectural pages, see the project wiki.
Versioning Policy (Pre‑1.0)
Before the 1.0 release OpenPit follows a relaxed Semantic Versioning:
PATCHreleases carry bug fixes and small internal corrections.MINORreleases may introduce new features and may also change the public interface.
Breaking API changes can appear in minor releases before 1.0. Pick
version constraints that tolerate API evolution during the pre-stable
phase.
Getting Started
Visit the crate page on crates.io and the API documentation on docs.rs.
Install
Run the following Cargo command in your project directory:
Engine
Overview
The engine evaluates an order through a deterministic pre-trade pipeline:
start_pre_trade(order)runs lightweight start-stage policiesPreTradeRequest::execute()runs main-stage policiesPreTradeReservation::commit()applies reserved state- dropping
PreTradeReservationrolls state back automatically apply_execution_report(report)updates post-trade policy state
Start-stage policies aggregate rejects from all registered policies. Main-stage policies aggregate rejects and roll back registered mutations in reverse order when any reject is produced.
Built-in policies:
SpotFundsPolicy- per-account solvency gate over spendable fundsOrderValidationPolicy- structural integrity checks on every orderRateLimitPolicy- throttle order flow per broker, asset, or accountOrderSizeLimitPolicy- fat-finger caps on quantity and notionalPnlBoundsKillSwitchPolicy- halt an account when realized P&L breaches bounds
The primary integration model is to write project-specific policies against the public Rust policy API: Custom Rust policies.
Two types of rejections are supported: a full kill switch for the account and a rejection of only the current request. Kill switches are intended for algorithmic trading where automatic order submission must be halted until the situation is analyzed.
Threading
Canonical contract: Threading Contract.
Custom policies that need internal state across calls use the built-in Storage abstraction. The synchronization policy - no-sync, full-sync, or caller-sharded for per-key parallelism - is selected once at engine construction and applied transparently. Policy code never names a lock primitive; misuse is prevented at compile time.
- The SDK never spawns OS threads. Every public method runs on the OS thread that invoked it.
- Preventing concurrent invocation of any public method on the same SDK handle is the caller's responsibility. Entering one handle concurrently from multiple threads is undefined behavior.
- Sequential calls to public methods on the same handle from different OS threads are supported. Handles, contexts, and callbacks are not pinned to a specific thread.
Reject.user_data/Order.user_data/ExecutionReport.user_data/AccountAdjustment.user_dataare opaque caller tokens. The SDK never inspects, dereferences, or frees them. Lifetime, thread-safety, and meaning are entirely caller-managed.
Usage
use Duration;
use ;
use ;
use ;
use ;
#
Errors
Rejects from start_pre_trade(order) and PreTradeRequest::execute() are
returned as
Err(Reject) and Result<PreTradeReservation, Vec<Reject>>.
Each Reject contains:
policy: policy namecode: stable machine-readable code (for exampleRejectCode::OrderQtyExceedsLimit)reason: short human-readable reject type (for example"order quantity exceeded")details: concrete case details (for example"requested 11, max allowed: 10")scope:RejectScope::OrderorRejectScope::Accountuser_data: opaque caller-defined pointer payload (nullby default)
RejectCode values are standardized and stable across Rust, Python, and C FFI.