nautechsystems/nautilus_trader · error
ProbabilityPriceFeeModel requires a fill price in [0, 1]
Error message
ProbabilityPriceFeeModel requires a fill price in [0, 1]
What it means
ProbabilityPriceFeeModel treats the fill price as a probability, so it must lie within [0, 1]. get_commission validates the fill_px decimal against the inclusive range ZERO..=ONE and bails if it is outside, because fee math (fill_price * (1 - fill_price)) is only valid for probabilities.
Source
Thrown at crates/execution/src/models/fee.rs:458
)
)]
pub struct ProbabilityPriceFeeModel;
impl FeeModel for ProbabilityPriceFeeModel {
fn get_commission(
&self,
order: &OrderAny,
fill_quantity: Quantity,
fill_px: Price,
instrument: &InstrumentAny,
) -> anyhow::Result<Money> {
if !matches!(instrument, InstrumentAny::BinaryOption(_)) {
anyhow::bail!("ProbabilityPriceFeeModel requires a binary option instrument");
}
let fill_price = fill_px.as_decimal();
if !(Decimal::ZERO..=Decimal::ONE).contains(&fill_price) {
anyhow::bail!("ProbabilityPriceFeeModel requires a fill price in [0, 1]");
}
let fee_rate = match order.liquidity_side() {
Some(LiquiditySide::Maker) => instrument.maker_fee(),
Some(LiquiditySide::Taker) => instrument.taker_fee(),
Some(LiquiditySide::NoLiquiditySide) | None => anyhow::bail!("Liquidity side not set"),
};
let one_minus_p = Decimal::ONE - fill_price;
let commission = mul_checked(fill_quantity.as_decimal(), fee_rate)
.and_then(|v| mul_checked(v, fill_price))
.and_then(|v| mul_checked(v, one_minus_p))
.map(|v| v.round_dp(5))?;
Money::from_decimal(commission, instrument.quote_currency()).map_err(Into::into)
}
}
View on GitHub (pinned to 18893faf8b)
Solutions
- Pass binary-option fill prices normalized to the [0, 1] probability range
- Check the instrument's price_precision/price_increment so prices are parsed at the correct scale
- Verify the fill Price was constructed from the venue's probability quote, not a converted cash price
Example fix
// before let px = Price::new(55.50, 2); // invalid probability let fee = model.get_commission(&order, qty, px, &instrument)?; // after let px = Price::new(0.555, 3); // probability in [0, 1] assert!((Decimal::ZERO..=Decimal::ONE).contains(&px.as_decimal())); let fee = model.get_commission(&order, qty, px, &instrument)?;
Defensive patterns
Strategy: validation
Validate before calling
let d = fill_px.as_decimal();
if !(Decimal::ZERO..=Decimal::ONE).contains(&d) {
return Err(anyhow::anyhow!("fill price {} not in [0,1]", d));
} Type guard
fn is_probability_price(px: &Price) -> bool {
(Decimal::ZERO..=Decimal::ONE).contains(&px.as_decimal())
} Try / catch
let fee = model.get_commission(&order, qty, px, &instrument)
.with_context(|| format!("prob-fee calc failed for px={px}"))?; Prevention
- Confirm binary-option price_precision/increment keep quotes in [0,1]
- Sanity-check fill prices against the instrument's price range before fee calc
- Don't route non-binary asset prices through the probability fee model
When it happens
Trigger: Calling get_commission with a fill_px whose decimal value is < 0 or > 1, e.g. a Price expressed in whole currency units (like 55.50) rather than 0..1 probability units, or a mis-scaled price.
Common situations: Feeding a regular asset price into the binary-option fee model; price precision/increment config that scales binary option prices outside [0,1]; unit mismatch between venue pricing and internal Price representation.
Understand the failure class
Background: "value must be between 0 and 1" / "out of range" / "must not be negative" errors: fixing range-validation failures across open-source libraries — this error's family across 42 libraries.
Related errors
- ProbabilityPriceFeeModel requires a binary option instrument
- DateTime timestamp out of range for UnixNanos: {nanos}
- Commission must be greater than or equal to zero
- Liquidity side not set
- `{name}` must be greater than or equal to zero
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/81bf9a6f72ceafec.
Report an issue: GitHub.