{"record":{"id":"9d5b52d1aff0d636","repo":"nautechsystems/nautilus_trader","slug":"historical-field-value-is-not-exactly-represen","errorCode":null,"errorMessage":"historical {field} {value} is not exactly representable as a price","messagePattern":"historical (.+?) (.+?) is not exactly representable as a price","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/adapters/polymarket/src/execution/reconciliation.rs","lineNumber":319,"sourceCode":"        price.as_decimal() == value,\n        \"{field} {value} is not exactly representable with price precision {precision}\",\n    );\n    Ok(())\n}\n\nfn validate_historical_price_evidence(value: Decimal, field: &str) -> anyhow::Result<Price> {\n    anyhow::ensure!(\n        value > Decimal::ZERO && value < Decimal::ONE,\n        \"{field} {value} must be greater than zero and less than one\",\n    );\n    let evidence = value.normalize();\n    anyhow::ensure!(\n        evidence.scale() <= u32::from(FIXED_PRECISION),\n        \"historical {field} {value} exceeds the maximum representable price precision of {FIXED_PRECISION} decimals\",\n    );\n    let price = Price::from_decimal(evidence)\n        .with_context(|| format!(\"failed to represent historical {field} {value}\"))?;\n    anyhow::ensure!(\n        price.as_decimal() == value,\n        \"historical {field} {value} is not exactly representable as a price\",\n    );\n    Ok(price)\n}\n\n#[derive(Clone, Copy, Debug)]\nstruct ValidatedOrderRow {\n    venue_order_id: VenueOrderId,\n    ts_accepted: UnixNanos,\n    expire_time: Option<UnixNanos>,\n}\n\nfn parse_provider_order_expiration(\n    order: &PolymarketOpenOrder,\n) -> anyhow::Result<Option<UnixNanos>> {\n    match order.expiration.as_deref() {\n        None => Ok(None),","sourceCodeStart":301,"sourceCodeEnd":337,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/polymarket/src/execution/reconciliation.rs#L301-L337","documentation":"This is the final exactness check: after building a domain Price via Price::from_decimal, the adapter asserts price.as_decimal() equals the original value. If the Price conversion lost precision or rounded, the historical evidence is not exactly representable and the anyhow error fires. It catches cases the earlier scale check cannot (e.g. internal tick-size rounding inside Price).","triggerScenarios":"Price::from_decimal succeeds but internally rounds to the venue tick size, so price.as_decimal() != value, in validate_trade_values -> validate_historical_price_evidence — e.g. a price not on the market's tick grid despite fitting FIXED_PRECISION decimals.","commonSituations":"Prices computed from fee-adjusted math or weighted averages landing between valid ticks; market tick size finer than FIXED_PRECISION or vice versa; importing evidence generated under a different tick regime.","solutions":["Snap the value to the instrument's tick size (quantize) before validation and persist the snapped value as the evidence.","Recompute historical evidence using the venue tick grid so it is exactly representable.","Check the instrument's tick_size/price_increment configuration matches the era the historical data came from."],"exampleFix":"// before\nlet p = Decimal::new(123456, 6); // 0.123456, not on tick grid\nlet price = validate_historical_price_evidence(p, \"price\")?;\n// after\nlet p = p.round_dp_with_strategy(instrument.tick_size().as_decimal().scale(), RoundingStrategy::ToNearest);\nlet price = validate_historical_price_evidence(p, \"price\")?;","handlingStrategy":"validation","validationCode":"fn is_tick_aligned(price: rust_decimal::Decimal, tick: rust_decimal::Decimal) -> bool {\n    (price % tick).is_zero()\n}\n// snap before validating: price = (price / tick).round() * tick;","typeGuard":null,"tryCatchPattern":"let price = match validate_historical_price_evidence(value, field) {\n    Err(e) if e.to_string().contains(\"not exactly representable as a price\") => {\n        snap_to_tick(value, instrument.tick_size())? // retry with snapped value\n    }\n    other => other?,\n};","preventionTips":["Snap all prices to the instrument tick size before any reconciliation","Keep tick-size config in sync with the era of historical data being reconciled","Test derived-price math (fees, averages) for tick-grid alignment in unit tests"],"tags":["polymarket","reconciliation","precision","tick-size"],"backgroundTag":"internal-invariant-violation","analyzedSha":"18893faf8b356be3320add8de2f861b0b647cf06","analyzedAt":"2026-09-08T20:49:34.690Z","contentChangedAt":"2026-09-08T20:49:34.690Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}