Skip to content

openpitkit/pit

Repository files navigation

OpenPit: Pre-trade Integrity Toolkit

Pit

Verify Release License Go version Module Python versions PyPI C++17 Rust crates.io C API

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.

How The Flow Works

  1. The engine is configured once during platform initialization.
  2. Each order first goes through lightweight start-stage checks. This stage makes fast decisions and runs controls that must observe every request, including rejected ones.
  3. If the order passes the start stage, the caller receives a deferred request object. The heavier pre-trade stage has not run yet.
  4. When the deferred request is executed, the engine runs the main-stage risk policies and collects all registered mutations. If any policy rejects, the collected state is rolled back. If the stage succeeds, the caller receives a reservation. The shortcut engine.execute_pre_trade(order) composes the two stages into one call when manual request handling is not needed.
  5. The reservation must be finalized explicitly: commit keeps the reserved state, rollback cancels it. Dropping the reservation without finalization rolls it back automatically.
  6. Post-trade reports are fed back into the engine so policies that depend on realized outcomes can update their state.

Current Scope

The current implementation focuses on the pre-trade pipeline, a small set of built-in controls, and an API for building project-specific strategy and risk policies. Built-ins:

Custom policies that maintain state across calls can use the built-in Storage abstraction. Synchronization is selected once at engine construction and applied transparently, with no overhead in single-threaded embeddings.

Controls can act both by account and by group of accounts: register accounts under a compact identifier with Account Groups and let a policy branch on the group instead of an enumerated account list.

The engine is intentionally in-memory and deterministic, designed to be embedded into a larger trading system rather than replace one. For custom policy APIs:

Versioning Policy (Pre‑1.0)

Before the 1.0 release OpenPit follows a relaxed Semantic Versioning:

  • PATCH releases carry bug fixes and small internal corrections.
  • MINOR releases 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.

Where To Start

Local Build And Test

POSIX (Linux, macOS, etc)

Prerequisites

python3 -m venv .venv
.venv/bin/python -m pip install -r ./requirements.txt

The repository build recipes use this local Python environment for helper scripts, generated API artifacts, and Python tooling such as maturin and pytest.

Build

SDK

With Just:

just build-debug

Manual:

cargo build --workspace

Python

With Just:

just python-develop-debug

Manual:

.venv/bin/maturin develop --manifest-path bindings/python/Cargo.toml

The recommended Python test flow is to run maturin develop before pytest. This runs against the current checkout (including a dirty worktree).

Go

The Go SDK consumes the native runtime through CGo. Build the FFI library first:

cargo build -p openpit-ffi --locked

Go 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.

C++

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-debug

Manual:

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

On Linux, use libopenpit_ffi.so instead of libopenpit_ffi.dylib. On Windows, use openpit_ffi.dll.

Tests

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

Manual:

# 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
Windows

Prerequisites

  • rustup - Rust toolchain and target x86_64-pc-windows-msvc
  • cargo-nextest if you run Rust tests through just
  • Python >=3.10 as python for repository build/test recipes, generated API artifacts, and Python bindings
  • Go 1.22 if you build or test Go bindings
  • golangci-lint if you lint Go
  • CMake >=3.21 if 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 if you generate C++ reference docs
  • Graphviz if you generate docs with diagrams
  • Optional: Just if you use recipe shortcuts

Set up the Rust target:

rustup target add x86_64-pc-windows-msvc
python -m venv .venv
.\.venv\Scripts\python.exe -m pip install -r .\requirements.txt

The repository build recipes use this local Python environment for helper scripts, generated API artifacts, and Python tooling such as maturin and pytest.

Build

SDK

With Just:

just build-debug

Manual:

cargo build --workspace --target x86_64-pc-windows-msvc

Python

With Just:

just python-develop-debug

Manual:

.\.venv\Scripts\python.exe -m maturin develop `
  --manifest-path bindings/python/Cargo.toml `
  --target x86_64-pc-windows-msvc

The recommended Python test flow is to run maturin develop before pytest. This runs against the current checkout (including a dirty worktree).

Go

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-msvc

Go 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.

C++

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-debug

Manual:

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

Tests

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

Manual:

# 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

About

OpenPit - an embeddable pre-trade risk SDK that checks every order against position & P&L limits and kill switches before it reaches the venue. Go, Python, C++, Rust and C API.

Topics

Resources

License

Stars

4 stars

Watchers

1 watching

Forks

Contributors