-
Notifications
You must be signed in to change notification settings - Fork 1
Getting Started
Eugene Palchukovsky edited this page Mar 12, 2026
·
1 revision
Pit has two full public SDKs today:
- Rust crate
openpit - Python package
openpit
This page uses the conceptual step names start stage, execute request,
finalize reservation, and apply execution report in prose. Exact API names
stay inside the code blocks.
Both SDKs follow the same operational flow:
- Build an engine once during application startup.
- Run the
start stagefor each order. -
Execute requestif the start stage passes. -
Finalize reservationexplicitly. -
Apply execution reportafter realized outcomes are known.
cargo add openpitpip install openpitRust
use std::time::Duration;
use openpit::param::{Asset, Pnl, Quantity, Volume};
use openpit::pretrade::policies::{
OrderSizeLimit,
OrderSizeLimitPolicy,
OrderValidationPolicy,
PnlKillSwitchPolicy,
RateLimitPolicy,
};
use openpit::{
FinancialImpact, ExecutionReportOperation, OrderOperation,
WithFinancialImpact, WithExecutionReportOperation,
};
use openpit::Engine;
# fn main() -> Result<(), Box<dyn std::error::Error>> {
type ExecutionReport = WithExecutionReportOperation<WithFinancialImpact<()>>;
let usd = Asset::new("USD")?;
let pnl_policy = PnlKillSwitchPolicy::new(
(
usd.clone(),
Pnl::from_str("1000")?,
),
[],
)?;
let rate_limit_policy = RateLimitPolicy::new(100, Duration::from_secs(1));
let size_policy = OrderSizeLimitPolicy::new(
OrderSizeLimit {
settlement_asset: usd.clone(),
max_quantity: Quantity::from_str("500")?,
max_notional: Volume::from_str("100000")?,
},
[],
);
let engine = Engine::<OrderOperation, ExecutionReport>::builder()
.check_pre_trade_start_policy(OrderValidationPolicy::new())
.check_pre_trade_start_policy(pnl_policy)
.check_pre_trade_start_policy(rate_limit_policy)
.check_pre_trade_start_policy(size_policy)
.build()?;
# Ok(())
# }The Rust SDK verifies policy-to-order compatibility at compile time through
capability traits. A policy that declares O: HasTradeAmount + HasOrderPrice
will not compile unless the order type satisfies both bounds. Custom order
types gain capabilities either by implementing the traits directly or by using
Deref to delegate to an OrderOperation base.
Python
import openpit
pnl_policy = openpit.pretrade.policies.PnlKillSwitchPolicy(
settlement_asset=openpit.param.Asset("USD"),
barrier=openpit.param.Pnl("1000"),
)
rate_limit_policy = openpit.pretrade.policies.RateLimitPolicy(
max_orders=100,
window_seconds=1,
)
order_size_policy = openpit.pretrade.policies.OrderSizeLimitPolicy(
limit=openpit.pretrade.policies.OrderSizeLimit(
settlement_asset=openpit.param.Asset("USD"),
max_quantity=openpit.param.Quantity("500"),
max_notional=openpit.param.Volume("100000"),
)
)
engine = (
openpit.Engine.builder()
.check_pre_trade_start_policy(
policy=openpit.pretrade.policies.OrderValidationPolicy(),
)
.check_pre_trade_start_policy(policy=pnl_policy)
.check_pre_trade_start_policy(policy=rate_limit_policy)
.check_pre_trade_start_policy(policy=order_size_policy)
.build()
)Rust
use openpit::param::{Asset, Price, Quantity, Side, TradeAmount};
use openpit::{Instrument, OrderOperation};
# fn main() -> Result<(), Box<dyn std::error::Error>> {
let order = OrderOperation {
instrument: Instrument::new(
Asset::new("AAPL")?,
Asset::new("USD")?,
),
side: Side::Buy,
trade_amount: TradeAmount::Quantity(
Quantity::from_str("100")?,
),
price: Some(Price::from_str("185")?),
};
let request = match engine.start_pre_trade(order) {
Ok(request) => request,
Err(reject) => {
eprintln!(
"rejected by {} [{}]: {} ({})",
reject.policy,
reject.code,
reject.reason,
reject.details
);
return;
}
};
let reservation = match request.execute() {
Ok(reservation) => reservation,
Err(rejects) => {
for reject in &rejects {
eprintln!(
"rejected by {} [{}]: {} ({})",
reject.policy,
reject.code,
reject.reason,
reject.details
);
}
return;
}
};
reservation.commit();
# Ok(())
# }Python
order = openpit.Order(
operation=openpit.OrderOperation(
instrument=openpit.Instrument(
openpit.param.Asset("AAPL"),
openpit.param.Asset("USD"),
),
side=openpit.param.Side.BUY,
trade_amount=openpit.param.Quantity("100"),
price=openpit.param.Price("185"),
),
)
start_result = engine.start_pre_trade(order=order)
if not start_result:
reject = start_result.reject
raise RuntimeError(
f"{reject.policy} [{reject.code}]: {reject.reason}: {reject.details}"
)
execute_result = start_result.request.execute()
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
reservation.commit()Rust
use openpit::{
FinancialImpact, ExecutionReportOperation, WithFinancialImpact,
WithExecutionReportOperation,
};
use openpit::param::{Asset, Fee, Pnl, Side};
use openpit::Instrument;
# fn main() -> Result<(), Box<dyn std::error::Error>> {
let report = WithExecutionReportOperation {
inner: WithFinancialImpact {
inner: (),
financial_impact: FinancialImpact {
pnl: Pnl::from_str("-50")?,
fee: Fee::from_str("3")?,
},
},
operation: ExecutionReportOperation {
instrument: Instrument::new(
Asset::new("AAPL")?,
Asset::new("USD")?,
),
side: Side::Buy,
},
};
let result = engine.apply_execution_report(&report);
if result.kill_switch_triggered {
eprintln!("halt new orders until the blocked state is cleared");
}
# Ok(())
# }Python
report = openpit.ExecutionReport(
operation=openpit.ExecutionReportOperation(
instrument=openpit.Instrument(
openpit.param.Asset("AAPL"),
openpit.param.Asset("USD"),
),
side=openpit.param.Side.BUY,
),
financial_impact=openpit.FinancialImpact(
pnl=openpit.param.Pnl("-50"),
fee=openpit.param.Fee("3"),
),
)
result = engine.apply_execution_report(report=report)
if result.kill_switch_triggered:
print("halt new orders until the blocked state is cleared")- Pit is in-memory. Persistence belongs to the host system.
- Pit does not route orders or talk to venues.
- Pit does not calculate realized P&L from raw fills for you. The caller sends realized outcomes through execution reports.
- One shared engine instance does not coordinate concurrent access for you.
- Pre-trade Pipeline: Request, reject, and reservation semantics
- Policies: Built-in controls and custom policy hooks
- Reject Codes: Standard business reject codes
- Architecture: Public integration model