Skip to content

en Domain Types

Eugene Palchukovsky edited this page Mar 9, 2026 · 1 revision

Domain Types

Pit models financial quantities through typed values from openpit::param. The goal is twofold: keep domain meaning explicit for trading professionals and prevent accidental unit mix-ups for engineers integrating the SDK.

All numeric types use exact decimal arithmetic internally. f64 is not used for financial calculations inside the engine.

Why these types exist

In trading systems, 100, 100 USD, 100 shares, and 100 of realized P&L are not interchangeable. The SDK keeps those values separate at the type level so that API misuse is harder to express and easier to detect.

Type categories

Category Types Sign
Non-negative Quantity, Volume Cannot be negative
Signed Price, Pnl, CashFlow, PositionSize, Fee Can be negative
Identifiers Asset, Side Non-numeric

Type reference

Asset

String identifier for a currency or tradable symbol such as USD, AAPL, SPX, or BTC.

  • Backed by SmolStr, so short symbols stay inline.
  • Asset::new(...) rejects empty and whitespace-only identifiers.
  • Symbol semantics are still left to the caller because validity is venue- and product-specific.
use openpit::param::Asset;

let usd = Asset::new("USD").expect("asset code must be valid");
let aapl = Asset::new("AAPL").expect("asset code must be valid");

Side

Trade direction.

use openpit::param::Side;

let buy = Side::Buy;
let sell = Side::Sell;
let opposite = buy.opposite();
assert_eq!(opposite, Side::Sell);

Price

Limit price per one unit of the underlying asset.

Most spot and equity workflows use non-negative prices. Pit still models Price as signed because some derivatives and spread products can produce negative prices.

use openpit::param::Price;

let price = Price::from_str("185.50")?;
let negative = Price::from_str("-1.25")?;
# Ok::<(), openpit::param::Error>(())

Quantity

Order size in units of the underlying asset. Cannot be negative.

use openpit::param::Quantity;

let qty = Quantity::from_str("100")?;
# Ok::<(), openpit::param::Error>(())

Volume

Unsigned monetary amount. In the pre-trade pipeline it is commonly used for absolute notional, configured notional limits, and reserved amounts.

use openpit::param::{Price, Quantity};

let price = Price::from_str("185")?;
let qty = Quantity::from_str("100")?;
let notional = price.calculate_volume(qty)?;
assert_eq!(notional.to_decimal().to_string(), "18500");
# Ok::<(), openpit::param::Error>(())

Pnl

Realized profit and loss.

  • Positive means profit.
  • Negative means loss.
use openpit::param::Pnl;

let profit = Pnl::from_str("250.00")?;
let loss = Pnl::from_str("-600.00")?;
# Ok::<(), openpit::param::Error>(())

CashFlow

Directional monetary value.

  • Negative means an outflow, for example cash spent on a buy order.
  • Positive means an inflow, for example cash received from a sell order.

The engine exposes order notional to main-stage policies as Context::notional using CashFlow, not Volume, because trade side matters operationally.

Fee

Transaction fee or rebate.

  • Positive values represent fees paid.
  • Negative values represent rebates received.

Pass Fee::ZERO when fees are already included in ExecutionReport::pnl.

PositionSize

Signed position expressed in units of the underlying asset.

  • Positive means long.
  • Negative means short.

Preferred constructors

Use exact inputs by default:

  • T::from_str(s): preferred for literals, config, JSON text, and external text APIs
  • T::from_decimal_rounded(v, scale, strategy): preferred when upstream already provides exact decimals
  • T::from_str_rounded(s, scale, strategy): use when input precision is known but must be normalized
  • T::ZERO: use for neutral initialization

from_f64 and from_f64_rounded exist for interoperability with APIs that already expose floating-point values. They validate the float immediately, but they are an integration-boundary tool, not the preferred representation for domain data.

Arithmetic

All arithmetic is checked and returns Result<T, Error>:

use openpit::param::{Error, Pnl};

let a = Pnl::from_str("100")?;
let b = Pnl::from_str("-30")?;
let sum = a.checked_add(b)?;
assert_eq!(sum.to_decimal().to_string(), "70");
# Ok::<(), Error>(())

Available operation families:

  • checked_add and checked_sub;
  • checked_mul_*, checked_div_*, and checked_rem_*;
  • checked_neg for signed types.

Rounding

RoundingStrategy provides named strategies for common financial cases:

Constant Meaning
DEFAULT Round half to nearest even
BANKER Alias for DEFAULT
CONSERVATIVE_PROFIT Round down so profit is never overstated
CONSERVATIVE_LOSS Round towards more negative

CONSERVATIVE_LOSS is intended for cases where losses or risk must not be understated.

Error model

All validation and arithmetic failures use openpit::param::Error. Whenever possible, the error carries ParamKind so the caller can see which type rejected the value or arithmetic operation.

Variant Meaning
Negative { param } Value below zero for a non-negative type
Overflow { param } Arithmetic overflow
Underflow { param } Result became negative for a non-negative type
DivisionByZero { param } Divisor is zero
InvalidFloat NaN or infinity was passed from a float boundary
InvalidPrice Price has an invalid value (for example zero in division)
InvalidFormat { param, input } String input cannot be parsed

Related pages

Clone this wiki locally