OpenPit is a workspace for embeddable pre-trade risk components. Before an order reaches a venue, it passes through a deterministic risk pipeline that can reject the request, reserve state, and later absorb post-trade outcomes back into the same control system.
The engine is in-memory and deterministic, designed to be embedded into a larger trading system rather than replace one. The pipeline itself is described on the wiki.
go get go.openpit.dev/openpit # Go
pip install openpit # Python
npm install @openpit/engine # JavaScript and TypeScript
cargo add openpit # RustC++ consumes the released CMake package and C integrates through the C ABI; see the C++ and C SDK READMEs.
use openpit::param::{AccountId, Asset, Price, Quantity, Side, TradeAmount, Volume};
use openpit::pretrade::policies::{
OrderSizeBrokerBarrier, OrderSizeLimit, OrderSizeLimitPolicy, OrderSizeLimitSettings,
};
use openpit::storage::NoLocking;
use openpit::{Engine, Instrument, OrderOperation};
// One fat-finger control, wired once at startup.
let engine = Engine::builder::<OrderOperation, (), ()>()
.no_sync()
.pre_trade(OrderSizeLimitPolicy::<NoLocking>::new(
OrderSizeLimitSettings::new(
Some(OrderSizeBrokerBarrier {
limit: OrderSizeLimit {
max_quantity: Quantity::from_str("500")?,
max_notional: Volume::from_str("100000")?,
},
}),
[],
[],
)?,
))
.build()?;
let order = OrderOperation {
instrument: Instrument::new(Asset::new("AAPL")?, Asset::new("USD")?),
account_id: AccountId::from_u64(99224416),
side: Side::Buy,
trade_amount: TradeAmount::Quantity(Quantity::from_str("1000")?),
price: Some(Price::from_str("185")?),
};
// The verdict: either a reservation to finalize once the venue answers,
// or the rejects that stopped the order.
match engine.execute_pre_trade(order) {
Ok(mut reservation) => reservation.commit(),
Err(rejects) => println!("order rejected: {rejects}"),
}Every SDK exposes the same pipeline in its own idiom; the per-language READMEs are listed under Where To Start.
- Spot Funds - per-account solvency gate over spendable funds.
- Order Validation - structural integrity checks on every order.
- Rate Limit - throttle order flow per broker, asset, or account.
- Order Size Limit - fat-finger caps on quantity and notional.
- P&L Kill Switch - halt an account when realized P&L breaches bounds.
- Custom policies - your own controls in Go, Python, JavaScript, C++, or Rust.
- Account Groups - branch a policy on a compact group identifier instead of an enumerated account list.
- Account Blocking - kill switch by account, by group, or engine-wide.
- Drop Copy - record already executed orders without pre-trade enforcement.
- Account Adjustments and Balance Reconciliation - keep engine state aligned with the venue.
- Market Data - quotes for policies that price an order.
- Dynamic Reconfiguration - retune a live policy without rebuilding the engine.
- Async Engine - per-account queues in Go and C++.
- Storage and Threading Contract - synchronization selected once at engine construction.
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.
- openpit.dev - project website with an overview and links to all documentation.
- docs.openpit.dev - generated API references: C, C++, and JavaScript.
- Go SDK README - integrate OpenPit from Go.
- Python SDK README - the
openpitPython package. - JavaScript SDK README - the
@openpit/enginepackage for JavaScript and TypeScript. - C++ SDK README - C++17 CMake package.
openpitcrate README - Rust interface with a runnable example.- C SDK README - C interface for environments that integrate through C.
- examples/ - end-to-end runnable scenarios.
- Wiki - conceptual pages and architecture notes.
- Ask questions and discuss integration ideas in GitHub Discussions.
- Report confirmed bugs and scoped feature requests in GitHub Issues.
- Read CONTRIBUTING.md before opening a pull request.
- Report vulnerabilities privately through SECURITY.md.
- Follow the project Code of Conduct in community spaces.
POSIX (Linux, macOS, etc)
- Rust toolchain
- cargo-nextest if you
run Rust tests through
just - Python
>=3.10for repository build/test recipes, generated API artifacts, and Python bindings - Go
1.22if you build or test Go bindings - golangci-lint if you lint Go
- Node.js
>=18if you build or test the JavaScript/WASM binding - CMake
>=3.21, a C++17 compiler, and clang-format and clang-tidy if you build, test, format, or lint C++ bindings and examples - doxygen and Graphviz if you generate the C++ reference docs
- Optional: Just if you use recipe shortcuts
python3 -m venv .venv
.venv/bin/python -m pip install -r ./requirements.txtThe repository build recipes use this local Python environment for helper
scripts, generated API artifacts, and Python tooling such as maturin and
pytest.
just install provisions the full build toolchain in one shot: the wasm32
Rust target, wasm-bindgen-cli (pinned to the version the crate resolved to),
the JS dev dependencies, and the Python dev install.
just installThis installs a lot. If you do not need the full build, do not run it blindly
- read the
installrecipe in thejustfileand install or build only the parts you actually use.
With Just:
just build-debugManual:
cargo build --workspaceWith Just:
just python-develop-debugManual:
.venv/bin/maturin develop --manifest-path bindings/python/Cargo.tomlThe recommended Python test flow is to run maturin develop before
pytest. This runs against the current checkout (including a dirty
worktree).
The JavaScript/TypeScript binding (@openpit/engine) is a WebAssembly build;
there is no native add-on to compile.
With Just:
just build-jsManual:
cd bindings/js
npm install
npm run buildThe Go SDK consumes the native runtime through CGo. Build the FFI library first:
cargo build -p openpit-ffi --lockedGo tests then expect the path to that library through
OPENPIT_RUNTIME_LIBRARY_PATH. The variable is needed only for local
development inside the pit repository - consumers installing the SDK with
go get do not need to set it.
The C++ binding is a header-only C++17 SDK. In-repo builds link it against the locally built native runtime:
With Just:
just build-cpp-debug
just build-examples-cpp-debugManual:
cargo build -p openpit-ffi --locked
cmake -S bindings/cpp -B bindings/cpp/build-debug \
-DCMAKE_BUILD_TYPE=Debug \
-DOPENPIT_RUNTIME_LIBRARY="$PWD/target/debug/libopenpit_ffi.dylib"
cmake --build bindings/cpp/build-debug --config DebugOn Linux, use libopenpit_ffi.so instead of libopenpit_ffi.dylib. On
Windows, use openpit_ffi.dll.
With Just:
# All tests:
just test-all-debug
# Rust:
just test-rust-debug
# Python:
just test-python-debug
just test-python-unit-debug
just test-python-integration-debug
# Go:
just test-go-debug
just test-go-race
# C++:
just test-cpp-debug
just test-examples-cpp-debug
# JavaScript:
just test-js-debugManual:
# All tests:
cargo test --workspace
.venv/bin/maturin develop --manifest-path bindings/python/Cargo.toml
.venv/bin/python -m pytest bindings/python/tests
# Rust:
cargo test --workspace
# Python
maturin develop --manifest-path bindings/python/Cargo.toml
.venv/bin/python -m pytest bindings/python/tests
.venv/bin/python -m pytest bindings/python/tests/unit
.venv/bin/python -m pytest bindings/python/tests/integration
# Go:
cargo build -p openpit-ffi --locked
cd bindings/go
# Linux:
export OPENPIT_RUNTIME_LIBRARY_PATH="$(pwd)/../../target/debug/libopenpit_ffi.so"
# macOS: use libopenpit_ffi.dylib instead.
go test ./...
go test -race ./...
# C++:
cd ../..
cargo build -p openpit-ffi --locked
cmake -S bindings/cpp -B bindings/cpp/build-debug \
-DCMAKE_BUILD_TYPE=Debug \
-DOPENPIT_RUNTIME_LIBRARY="$PWD/target/debug/libopenpit_ffi.dylib"
cmake --build bindings/cpp/build-debug --config Debug
ctest --test-dir bindings/cpp/build-debug --output-on-failure
# JavaScript:
cd bindings/js
npm install
npm run build
npm testWindows
- rustup - Rust toolchain and target
x86_64-pc-windows-msvc - cargo-nextest if you
run Rust tests through
just - Python
>=3.10aspythonfor repository build/test recipes, generated API artifacts, and Python bindings - Go
1.22if you build or test Go bindings - golangci-lint if you lint Go
- CMake
>=3.21if you build or test C++ bindings and examples - Visual Studio Build Tools with MSVC C++ tools if you build or test C++ bindings and examples
- LLVM if you build or test Go
through CGo, format/lint C++, or use
clang/lld - Doxygen and Graphviz if you generate the C++ reference docs
- Optional: Just if you use recipe shortcuts
Set up the Rust target:
rustup target add x86_64-pc-windows-msvcpython -m venv .venv
.\.venv\Scripts\python.exe -m pip install -r .\requirements.txtThe repository build recipes use this local Python environment for helper
scripts, generated API artifacts, and Python tooling such as maturin and
pytest.
With Just:
just build-debugManual:
cargo build --workspace --target x86_64-pc-windows-msvcWith Just:
just python-develop-debugManual:
.\.venv\Scripts\python.exe -m maturin develop `
--manifest-path bindings/python/Cargo.toml `
--target x86_64-pc-windows-msvcThe recommended Python test flow is to run maturin develop before
pytest. This runs against the current checkout (including a dirty
worktree).
The Go SDK consumes the native runtime through CGo. Build the FFI library first:
cargo build -p openpit-ffi --locked --target x86_64-pc-windows-msvcGo tests then expect the path to that library through
OPENPIT_RUNTIME_LIBRARY_PATH. The variable is needed only for local
development inside the pit repository - consumers installing the SDK with
go get do not need to set it.
The C++ binding is a header-only C++17 SDK. In-repo builds link it against the locally built native runtime:
With Just:
just build-cpp-debug
just build-examples-cpp-debugManual:
cargo build -p openpit-ffi --locked --target x86_64-pc-windows-msvc
cmake -S bindings/cpp -B bindings/cpp/build-debug `
-DCMAKE_BUILD_TYPE=Debug `
-DOPENPIT_RUNTIME_LIBRARY="$PWD\target\x86_64-pc-windows-msvc\debug\openpit_ffi.dll" `
-DOPENPIT_RUNTIME_IMPORT_LIBRARY="$PWD\target\x86_64-pc-windows-msvc\debug\openpit_ffi.dll.lib"
cmake --build bindings/cpp/build-debug --config DebugWith Just:
# All tests:
just test-all-debug
# Rust:
just test-rust-debug
# Python:
just test-python-debug
just test-python-unit-debug
just test-python-integration-debug
# Go:
just test-go-debug
just test-go-race
# C++:
just test-cpp-debug
just test-examples-cpp-debugManual:
# All tests:
cargo test --workspace --target x86_64-pc-windows-msvc
.\.venv\Scripts\python.exe -m maturin develop `
--manifest-path bindings/python/Cargo.toml `
--target x86_64-pc-windows-msvc
.\.venv\Scripts\python.exe -m pytest bindings/python/tests
# Rust:
cargo test --workspace --target x86_64-pc-windows-msvc
# Python
.\.venv\Scripts\python.exe -m maturin develop `
--manifest-path bindings/python/Cargo.toml `
--target x86_64-pc-windows-msvc
.\.venv\Scripts\python.exe -m pytest bindings/python/tests
.\.venv\Scripts\python.exe -m pytest bindings/python/tests/unit
.\.venv\Scripts\python.exe -m pytest bindings/python/tests/integration
# Go:
cargo build -p openpit-ffi --locked --target x86_64-pc-windows-msvc
$env:OPENPIT_RUNTIME_LIBRARY_PATH = `
(Resolve-Path target\x86_64-pc-windows-msvc\debug\openpit_ffi.dll)
$env:CGO_ENABLED = "1"
$env:CC = "clang -fuse-ld=lld"
$env:CXX = "clang++ -fuse-ld=lld"
Push-Location bindings\go
go test ./...
go test -race ./...
Pop-Location
# C++:
cargo build -p openpit-ffi --locked --target x86_64-pc-windows-msvc
cmake -S bindings/cpp -B bindings/cpp/build-debug `
-DCMAKE_BUILD_TYPE=Debug `
-DOPENPIT_RUNTIME_LIBRARY="$PWD\target\x86_64-pc-windows-msvc\debug\openpit_ffi.dll" `
-DOPENPIT_RUNTIME_IMPORT_LIBRARY="$PWD\target\x86_64-pc-windows-msvc\debug\openpit_ffi.dll.lib"
cmake --build bindings/cpp/build-debug --config Debug
ctest --test-dir bindings/cpp/build-debug --output-on-failure --build-config Debug