Skip to content

Latest commit

 

History

History
304 lines (228 loc) · 11.4 KB

File metadata and controls

304 lines (228 loc) · 11.4 KB

OpenPit (Pre-trade Integrity Toolkit) for C++

Verify Release C++17 CMake License

openpit is an embeddable pre-trade risk SDK for integrating policy-driven risk checks into trading systems from C++.

The C++ SDK is a header-only C++17 wrapper over the native OpenPit runtime. It is packaged as a CMake config package and exposes the OpenPit::openpit target.

For an overview and links to all resources, see the project website openpit.dev. For the C++ API reference, see the C++ API docs. 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:

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

Getting Started

CMake find_package

Use the package generated by cmake --install from another CMake project:

find_package(OpenPit CONFIG REQUIRED)
target_link_libraries(your_target PRIVATE OpenPit::openpit)

On Windows, OpenPit resolves both the runtime DLL and the MSVC import library. If your application needs the DLL copied next to the executable, call:

openpit_copy_runtime_dll(your_target)

Include <openpit/openpit.hpp> for the complete SDK surface, or include <openpit/fwd.hpp> in precompiled headers when only forward declarations are needed.

Declare the dependency in the project manifest, vcpkg.json:

{
  "name": "your-project",
  "version-string": "0",
  "builtin-baseline": "<microsoft-vcpkg-commit>",
  "dependencies": ["openpit"]
}

builtin-baseline is a commit of the microsoft/vcpkg checkout the project builds against; vcpkg x-update-baseline --add-initial-baseline fills it in. It fixes the package versions of the whole build and is required for both installation paths below.

Consume the port like any other CMake package:

find_package(OpenPit CONFIG REQUIRED)
target_link_libraries(your_target PRIVATE OpenPit::openpit)

Configure your project with the vcpkg toolchain file. The normal OpenPit runtime resolver then downloads and verifies the matching released runtime asset.

Public microsoft/vcpkg registry

The preferred path: the manifest above is the whole setup, because vcpkg resolves openpit from the registry it already ships with. Ports land there through upstream review, so a fresh OpenPit release becomes installable this way with a delay.

Managed OpenPit registry

openpitkit/vcpkg-registry receives every OpenPit release first. Use it when the release you need has not reached the public registry yet, or when pinning an exact OpenPit version. The cost is one extra file next to the manifest, vcpkg-configuration.json:

{
  "registries": [
    {
      "kind": "git",
      "repository": "https://github.com/openpitkit/vcpkg-registry.git",
      "baseline": "<openpit-registry-commit>",
      "packages": ["openpit"]
    }
  ]
}

This baseline is a commit of the managed registry, not of microsoft/vcpkg; every OpenPit release note publishes the commit to use.

Examples

Runnable end-to-end examples live in examples/cpp/:

  • spot_funds - simplest SpotFunds policy integration (limit-only).
  • spot_table - table-driven test runner for the SpotFunds policy.
  • rate_pnl_killswitch - rate-limit + P&L kill-switch supervisor.
  • spot_loadtest - synthetic load test for pre-trade request throughput and latency.

Install

POSIX (Linux, macOS, etc)

Dependencies: Rust, CMake, and a C++17 compiler.

Build and install the C++ package from a local checkout:

cargo build -p openpit-ffi --release --locked
cmake -S bindings/cpp -B bindings/cpp/build \
  -DOPENPIT_RUNTIME_LIBRARY="$PWD/target/release/libopenpit_ffi.dylib"
cmake --build bindings/cpp/build
cmake --install bindings/cpp/build --prefix "$PWD/.openpit"

The command above uses the macOS .dylib; on Linux, point OPENPIT_RUNTIME_LIBRARY at target/release/libopenpit_ffi.so.

Windows

Install rustup, target x86_64-pc-windows-msvc, Visual Studio Build Tools, and CMake. Optional: Just.

With Just:

rustup target add x86_64-pc-windows-msvc
just build-cpp-release
just test-cpp-release

Manual:

rustup target add x86_64-pc-windows-msvc
cargo build -p openpit-ffi --release --locked --target x86_64-pc-windows-msvc
cmake -S bindings/cpp -B bindings/cpp/build `
  -DOPENPIT_RUNTIME_LIBRARY="$PWD\target\x86_64-pc-windows-msvc\release\openpit_ffi.dll" `
  -DOPENPIT_RUNTIME_IMPORT_LIBRARY="$PWD\target\x86_64-pc-windows-msvc\release\openpit_ffi.dll.lib"
cmake --build bindings/cpp/build
cmake --install bindings/cpp/build --prefix "$PWD\.openpit"

When a released package is consumed through find_package(OpenPit CONFIG REQUIRED), the runtime resolver uses this order:

  • OPENPIT_RUNTIME_LIBRARY - absolute path to a prebuilt runtime library.
  • OPENPIT_RUNTIME_DIR - directory containing the platform runtime library.
  • Download the matching release asset from GitHub and verify its SHA-256 sidecar.

Engine

Overview

The engine evaluates an order through a deterministic pre-trade pipeline:

  • engine.StartPreTrade(order) runs start-stage policies.
  • request.Execute() runs main-stage policies.
  • reservation.Commit() applies reserved state.
  • reservation.Rollback() reverts reserved state.
  • engine.ExecutePreTrade(order) is a shortcut that composes both stages.
  • engine.ApplyExecutionReport(report) updates post-trade policy state.

ApplyExecutionReport returns account blocks, account-PnL outcomes, and account-adjustment outcomes. Post-trade policies commit independently, so always consume both outcome vectors even when the account-block vector is non-empty.

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:

The primary integration model is to write project-specific policies against the public C++ policy API: Custom C++ policies.

Usage

#include <openpit/openpit.hpp>

#include <stdexcept>
#include <string>

int main() {
  namespace model = openpit::model;
  namespace policies = openpit::pretrade::policies;

  openpit::EngineBuilder builder(openpit::SyncPolicy::None);
  builder.Add(policies::OrderValidationPolicy{});
  openpit::Engine engine = builder.Build();

  model::Order order = model::Order::Limit(
      model::Instrument(openpit::param::Asset("AAPL"),
                        openpit::param::Asset("USD")),
      openpit::param::AccountId::FromUint64(99224416), model::Side::Buy,
      model::TradeAmount::OfQuantity(
          openpit::param::Quantity::FromString("100")),
      openpit::param::Price::FromString("185"));

  openpit::pretrade::StartResult start = engine.StartPreTrade(order);
  if (!start.Passed()) {
    const std::string reason = start.rejects.empty()
                                   ? "pre-trade start rejected"
                                   : start.rejects.front().reason;
    throw std::runtime_error(reason);
  }

  openpit::pretrade::ExecuteResult execute = start.request->Execute();
  if (!execute.Passed()) {
    const std::string reason = execute.rejects.empty()
                                   ? "pre-trade execute rejected"
                                   : execute.rejects.front().reason;
    throw std::runtime_error(reason);
  }

  execute.reservation->Commit();
  return 0;
}

For per-account asynchronous submission, use openpit::asyncengine::MakeTypedAsyncEngine(engine, workers). The returned wrapper owns the default C++ engine adapter and exposes the typed async methods (StartPreTrade, ExecutePreTrade, ApplyExecutionReport, ApplyAccountAdjustment) without manual driver lifetime plumbing.

Threading

Canonical contract: Threading Contract.

Choose the storage synchronization policy when building the engine:

  • openpit::SyncPolicy::None - single-threaded engine ownership.
  • openpit::SyncPolicy::Full - concurrent calls on one engine handle.
  • openpit::SyncPolicy::Account - account-sharded synchronization.

Custom policies that need internal state across calls use the built-in Storage abstraction: synchronization-aware key-value storage that keeps locking details out of policy code.

Errors

Expected business outcomes are returned as values:

  • Pre-trade rejects from StartPreTrade, ExecutePreTrade, and Request::Execute.
  • Account operation outcomes from account-control and adjustment APIs.

Programmer mistakes, invalid input, lifecycle misuse, and runtime boundary failures throw openpit::Error or a more specific derived error such as openpit::EngineBuildError or openpit::ConfigureError.