Skip to main content

Embeddable pre-trade risk SDK

Project description

OpenPit (Pre-trade Integrity Toolkit) for Python

Verify Release Python versions PyPI License

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

For an overview and links to all resources, see the project website openpit.dev. For the Python API guide and generated reference, see openpit.readthedocs.io. 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

Visit the PyPI package.

Examples

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

Install

For normal end-user installation, use the published PyPI package:

pip install openpit

If you need local development/debugging, clone this repository and build from source with Maturin:

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

Local release build:

maturin develop --release --manifest-path bindings/python/Cargo.toml

Engine

Overview

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

  • engine.start_pre_trade(order=...) runs lightweight start-stage checks
  • request.execute() runs main-stage check policies
  • reservation.commit() applies reserved state
  • reservation.rollback() reverts reserved state
  • engine.apply_execution_report(report=...) updates post-trade policy state

Start-stage checks aggregate rejects from all registered policies. Main-stage checks aggregate rejects and run rollback 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 Python policy API: Custom Python policies.

Threading

Canonical contract: Threading Contract.

Public methods acquire the GIL when needed; the SDK does not release the GIL across callback boundaries, so Python policies execute on the calling thread.

Custom policies that need internal state across calls can use the built-in Storage abstraction. In typical Python usage (synchronous code or an asyncio loop pinned to one thread) the no-sync policy is sufficient and the storage compiles down to direct dictionary access. A synchronizing policy is needed only when the engine is genuinely shared across OS threads.

Usage

import datetime
import openpit
import openpit.pretrade.policies

# 1. Configure policies.
pnl_policy = (
    openpit.pretrade.policies.build_pnl_bounds_killswitch()
    .broker_barriers(
        openpit.pretrade.policies.PnlBoundsBrokerBarrier(
            settlement_asset="USD",
            lower_bound=openpit.param.Pnl("-1000"),
        ),
    )
)

rate_limit_policy = (
    openpit.pretrade.policies.build_rate_limit()
    .broker_barrier(
        openpit.pretrade.policies.RateLimitBrokerBarrier(
            limit=openpit.pretrade.policies.RateLimit(
                max_orders=100,
                window=datetime.timedelta(seconds=1),
            ),
        ),
    )
)

max_qty = openpit.param.Quantity("500")
max_notional = openpit.param.Volume("100000")
order_size_policy = (
    openpit.pretrade.policies.build_order_size_limit()
    .broker_barrier(
        openpit.pretrade.policies.OrderSizeBrokerBarrier(
            limit=openpit.pretrade.policies.OrderSizeLimit(
                max_quantity=max_qty,
                max_notional=max_notional,
            ),
        )
    )
    .asset_barriers(
        openpit.pretrade.policies.OrderSizeAssetBarrier(
            limit=openpit.pretrade.policies.OrderSizeLimit(
                max_quantity=max_qty,
                max_notional=max_notional,
            ),
            settlement_asset="USD",
        ),
    )
)

# 2. Build the engine (one time at the platform initialization).
engine = (
    openpit.Engine.builder()
    .no_sync()
    .builtin(openpit.pretrade.policies.build_order_validation())
    .builtin(pnl_policy)
    .builtin(rate_limit_policy)
    .builtin(order_size_policy)
    .build()
)

# 3. Check an order.
order = openpit.Order(
    operation=openpit.OrderOperation(
        instrument=openpit.Instrument("AAPL", "USD"),
        account_id=openpit.param.AccountId.from_int(99224416),
        side=openpit.param.Side.BUY,
        trade_amount=openpit.param.TradeAmount.quantity(100.0),
        price=openpit.param.Price(185.0),
    ),
)

start_result = engine.start_pre_trade(order=order)

if not start_result:
    messages = ", ".join(
        f"{r.policy} [{r.code}]: {r.reason}: {r.details}"
        for r in start_result.rejects
    )
    raise RuntimeError(messages)

request = start_result.request

# 4. Quick, lightweight checks, such as fat-finger scope or enabled kill
# switch, were performed during pre-trade request creation. The system state
# has not yet changed, except in cases where each request, even rejected ones,
# must be considered. Before the heavy-duty checks, other work on the request
# can be performed simply by holding the request object.

# 5. Real pre-trade and risk control.
execute_result = request.execute()

# Optional shortcut for the same two-stage flow:
# execute_result = engine.execute_pre_trade(order=order)

if not execute_result:
    messages = ", ".join(
        f"{reject.policy} [{reject.code}]: {reject.reason}: {reject.details}"
        for reject in execute_result.rejects
    )
    raise RuntimeError(messages)

reservation = execute_result.reservation

# 6. If the request is successfully sent to the venue, it must be committed.
# The rollback must be called otherwise to revert all performed reservations.
try:
    send_order_to_venue(order)
except Exception:
    reservation.rollback()
    raise

reservation.commit()

# 7. The order goes to the venue and returns with an execution report.
report = openpit.ExecutionReport(
    operation=openpit.ExecutionReportOperation(
        instrument=openpit.Instrument("AAPL", "USD"),
        account_id=openpit.param.AccountId.from_int(99224416),
        side=openpit.param.Side.BUY,
    ),
    financial_impact=openpit.FinancialImpact(
        pnl=openpit.param.Pnl("-50"),
        fee=openpit.param.Fee("3.4"),
    ),
)

result = engine.apply_execution_report(report=report)

# 8. After each execution report is applied, the system may report that it has
# been determined in advance that all subsequent requests will be rejected if
# the account status does not change.
assert not result.account_blocks

Errors

Policy rejects from engine.start_pre_trade() and request.execute() are returned as StartResult and ExecuteResult.

Input validation errors and API misuse still raise exceptions:

  • ValueError for invalid assets/sides/malformed numeric inputs
  • RuntimeError for lifecycle misuse, for example executing the same request twice or finalizing the same reservation twice
  • Business rejects use stable reject codes such as openpit.pretrade.RejectCode.ORDER_VALUE_CALCULATION_FAILED when a policy cannot evaluate order value without price

Local Testing

Recommended local flow:

maturin develop --manifest-path bindings/python/Cargo.toml
python -m pytest bindings/python/tests

Run only unit tests:

maturin develop --manifest-path bindings/python/Cargo.toml
python -m pytest bindings/python/tests/unit

Run only integration test:

maturin develop --manifest-path bindings/python/Cargo.toml
python -m pytest bindings/python/tests/integration

For full build/test command matrix (manual and just), see the repository README.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

openpit-0.5.0.tar.gz (491.2 kB view details)

Uploaded Source

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

openpit-0.5.0-cp310-abi3-win_amd64.whl (758.4 kB view details)

Uploaded CPython 3.10+Windows x86-64

openpit-0.5.0-cp310-abi3-musllinux_1_2_x86_64.whl (878.0 kB view details)

Uploaded CPython 3.10+musllinux: musl 1.2+ x86-64

openpit-0.5.0-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (879.2 kB view details)

Uploaded CPython 3.10+manylinux: glibc 2.17+ x86-64

openpit-0.5.0-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (851.8 kB view details)

Uploaded CPython 3.10+manylinux: glibc 2.17+ ARM64

openpit-0.5.0-cp310-abi3-macosx_11_0_arm64.whl (784.7 kB view details)

Uploaded CPython 3.10+macOS 11.0+ ARM64

openpit-0.5.0-cp310-abi3-macosx_10_12_x86_64.whl (839.9 kB view details)

Uploaded CPython 3.10+macOS 10.12+ x86-64

File details

Details for the file openpit-0.5.0.tar.gz.

File metadata

  • Download URL: openpit-0.5.0.tar.gz
  • Upload date:
  • Size: 491.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.10.20

File hashes

Hashes for openpit-0.5.0.tar.gz
Algorithm Hash digest
SHA256 ec8004516a258431d34088da3f2a08662f5869b3c58a80a14a145fb76563b690
MD5 b081698d3c0828760d2ad43c865c2d74
BLAKE2b-256 a22a51bf2d6036160d02e804753a4d49ed44419f1a35480321b65b6d9dfd4bcf

See more details on using hashes here.

File details

Details for the file openpit-0.5.0-cp310-abi3-win_amd64.whl.

File metadata

  • Download URL: openpit-0.5.0-cp310-abi3-win_amd64.whl
  • Upload date:
  • Size: 758.4 kB
  • Tags: CPython 3.10+, Windows x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.10.11

File hashes

Hashes for openpit-0.5.0-cp310-abi3-win_amd64.whl
Algorithm Hash digest
SHA256 dbfc5e5b9b6f3948b75f69baabe866069f649de6f73d29f031dc7e646523e5c9
MD5 afa13ce5d688ed485e1ab50cbea321d8
BLAKE2b-256 10f0fe6a3426d025704a2e9174af5473dfc7eb5c9a7ba67b92cee4c870d94eb8

See more details on using hashes here.

File details

Details for the file openpit-0.5.0-cp310-abi3-musllinux_1_2_x86_64.whl.

File metadata

File hashes

Hashes for openpit-0.5.0-cp310-abi3-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 e0359c44559e01332c1d6f74ed5434496a97c55d91c8d6a8c5c6ba3de98e58d2
MD5 11c5f003e88a0da235d52b0c789df625
BLAKE2b-256 b28919ee03a180a9249787f7ce120ac9adda91afb5d9cd8b0c9adde3efba3829

See more details on using hashes here.

File details

Details for the file openpit-0.5.0-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for openpit-0.5.0-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 978b28d35f25cc65829ec9ce450ffd0ea671f87e2948d69e036c39751d4dad2c
MD5 1723904ea6b0069ecee0b85affff6682
BLAKE2b-256 5eafd84e414d0b82a88eea4194ce7a2ff51bda786650da024e0952c417752eeb

See more details on using hashes here.

File details

Details for the file openpit-0.5.0-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for openpit-0.5.0-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 733673ebe6ec15956465450bc711d2bf9bb31b63896a6d86389185f68158a0a1
MD5 978c1f60be19225088e5e6ee9f97c697
BLAKE2b-256 ffbad34a444ce17dabed01b12d845ec7a905f923b253bba1459cd1edccf11c38

See more details on using hashes here.

File details

Details for the file openpit-0.5.0-cp310-abi3-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for openpit-0.5.0-cp310-abi3-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 ad382bbf39467e25954209cda4da97263352452d96aac51753c3e3ab537066bc
MD5 1d9a4d45211f0a4f9f1e04d72d0ef5c7
BLAKE2b-256 05970131fc660dcfa42efcffadf34c246d25c49f8d4628f2522e92e103899c1c

See more details on using hashes here.

File details

Details for the file openpit-0.5.0-cp310-abi3-macosx_10_12_x86_64.whl.

File metadata

File hashes

Hashes for openpit-0.5.0-cp310-abi3-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 1a4a912fe3f9b9bace28530a7af43fccd9a2f5af1bad7c93b922d27b54240dca
MD5 a67cf72a937b3816069a9a4a67ea8dfa
BLAKE2b-256 c7654dd9d89bc4e514043a1f2ece86fc763fbfe1ea60a285dc9b34ec0f1da7c5

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page