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.4.0.tar.gz (401.1 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.4.0-cp310-abi3-win_amd64.whl (649.8 kB view details)

Uploaded CPython 3.10+Windows x86-64

openpit-0.4.0-cp310-abi3-musllinux_1_2_x86_64.whl (774.5 kB view details)

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

openpit-0.4.0-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (775.3 kB view details)

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

openpit-0.4.0-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (738.9 kB view details)

Uploaded CPython 3.10+manylinux: glibc 2.17+ ARM64

openpit-0.4.0-cp310-abi3-macosx_11_0_arm64.whl (671.0 kB view details)

Uploaded CPython 3.10+macOS 11.0+ ARM64

openpit-0.4.0-cp310-abi3-macosx_10_12_x86_64.whl (726.5 kB view details)

Uploaded CPython 3.10+macOS 10.12+ x86-64

File details

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

File metadata

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

File hashes

Hashes for openpit-0.4.0.tar.gz
Algorithm Hash digest
SHA256 bf5afb5ef8fc98ba2559be71e61aa74ec56b2a992a3dceb6d6f3e4f4c7d63b29
MD5 f741dfc2b40d6e1a6d97e4b7b23c6c19
BLAKE2b-256 c061d4d4dffc2313b42285bc75bfcc9ec7c720691b6eff8c1779d60a6cb3535d

See more details on using hashes here.

File details

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

File metadata

  • Download URL: openpit-0.4.0-cp310-abi3-win_amd64.whl
  • Upload date:
  • Size: 649.8 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.4.0-cp310-abi3-win_amd64.whl
Algorithm Hash digest
SHA256 6e069943b11f33442834bfa0cc413bb9e6ca361ba9b3106dac259b9a0adf9614
MD5 efce2735ccace320df645da79ea4a3fb
BLAKE2b-256 03e4728b2184c6901412c82e812fd89ff74f07b2e6ccb67bab5bb69498440eb7

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for openpit-0.4.0-cp310-abi3-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 e944c9df324e3fee75758cdd9d448028448096bea6ada303231dcbdad034996e
MD5 5172d8ed4bae0a9e7fe45f4d56bed84c
BLAKE2b-256 b38c7dafec926c798d19ba2a93a224eb5910b97f12baec743a7f9b19ccd4e240

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for openpit-0.4.0-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 439d74f5cf7bb4de161f2bd433c9fac27da4a799210f3b4f52a7bbdfa0074381
MD5 4fc28e30c8e427287acff02c6374bc6d
BLAKE2b-256 3ef6537227d12d170601f719f581378ebdc6333427e04245274d042560351b04

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for openpit-0.4.0-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 a2d9fc1d748b6ef32da6dd0de465456c3bc40cbd414e6ebe81bab6fd507326b3
MD5 07c614271dafc532b3af6e7dcf5c0bcc
BLAKE2b-256 5f51ed1394a021d93c927cc5b3ba120bbd115e17cd60fc01aeaa1a972dd92bcb

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for openpit-0.4.0-cp310-abi3-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 0829647bd307a87ea2aa0c99d34b2a170626dc4768cd08cfec76107b3ba4be9c
MD5 3dc62b67ae5deab2898d7b84d9501e87
BLAKE2b-256 94be0445f19538cd8fe812e94f0076a6705bac4ccf16d65bdf3a5c675251a476

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for openpit-0.4.0-cp310-abi3-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 0d673997253e532a51e5181c9dd74cbbcdd44b124fa4d7abd145b9c87e7d5023
MD5 99f144562e581c5fe5861ca77ff842f0
BLAKE2b-256 df52220860d3e182783be762c6846b3046c456b8746c902ea00fc5208453636d

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