{"record":{"id":"372a81408abaf1eb","repo":"nautechsystems/nautilus_trader","slug":"polymarket-collateral-sized-limit-buy-amount-pu","errorCode":null,"errorMessage":"Polymarket collateral-sized limit BUY amount {} pUSD truncates to zero at {LOT_SIZE_SCALE} decimal places","messagePattern":"Polymarket collateral-sized limit BUY amount (.+?) pUSD truncates to zero at (.+?) decimal places","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/adapters/polymarket/src/execution/order_builder.rs","lineNumber":163,"sourceCode":"    /// venue-required cent quantization, and the taker amount is the share quantity derived from\n    /// that exact signed amount.\n    pub(crate) fn build_limit_order_from_collateral(\n        &self,\n        token_id: &str,\n        price: Decimal,\n        amount: Decimal,\n        expiration: &str,\n        neg_risk: bool,\n        tick_decimals: u32,\n    ) -> anyhow::Result<PolymarketOrder> {\n        anyhow::ensure!(\n            price > Decimal::ZERO,\n            \"Polymarket collateral-sized limit BUY price must be positive\"\n        );\n\n        let (maker_amount, taker_amount) =\n            compute_quote_buy_maker_taker_amounts(price, amount, tick_decimals);\n        anyhow::ensure!(\n            maker_amount > Decimal::ZERO,\n            \"Polymarket collateral-sized limit BUY amount {} pUSD truncates to zero at {LOT_SIZE_SCALE} decimal places\",\n            amount.normalize(),\n        );\n        anyhow::ensure!(\n            taker_amount > Decimal::ZERO,\n            \"Polymarket collateral-sized limit BUY derives a zero share quantity\"\n        );\n        anyhow::ensure!(\n            taker_amount * price == maker_amount,\n            \"Polymarket collateral-sized limit BUY amount {} pUSD cannot preserve limit price {} after venue quantization\",\n            amount.normalize(),\n            price.normalize(),\n        );\n\n        self.build_and_sign(\n            token_id,\n            PolymarketOrderSide::Buy,","sourceCodeStart":145,"sourceCodeEnd":181,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/polymarket/src/execution/order_builder.rs#L145-L181","documentation":"Polymarket order amounts are expressed in pUSD collateral and quantized to LOT_SIZE_SCALE decimal places. When a collateral-sized limit BUY is converted into maker/taker amounts via compute_quote_buy_maker_taker_amounts, a very small collateral amount truncates to a maker_amount of zero. The builder rejects it up front because a zero-size order is meaningless on the venue.","triggerScenarios":"Calling build_limit_order_from_collateral with a BUY amount so small that, scaled by the limit price and truncated to LOT_SIZE_SCALE decimals, maker_amount <= 0 (e.g. amounts in the sub-cent range at typical LOT_SIZE_SCALE).","commonSituations":"Position-sizing or risk code computing a collateral budget that rounds down to a tiny value; converting a notional from another unit (e.g. USD cents) without accounting for pUSD precision; test fixtures using amount values like 0.0001 pUSD.","solutions":["Increase the BUY collateral amount so it survives truncation at LOT_SIZE_SCALE decimal places (>= 1 unit at that scale after applying the price).","Check where the amount is produced (sizer/risk module) and raise its minimum notional floor to at least the venue lot size.","If truly tiny orders are needed, accumulate capital and submit fewer, larger orders instead of per-signal micro orders."],"exampleFix":"// before\nbuilder.build_limit_order_from_collateral(&order, price, Decimal::new(1, 4) /* 0.0001 pUSD */, ...)\n// after\nlet amount = Decimal::new(1, 0); // >= smallest pUSD amount that survives LOT_SIZE_SCALE truncation\nbuilder.build_limit_order_from_collateral(&order, price, amount, ...)","handlingStrategy":"validation","validationCode":"let min_amount = Decimal::ONE / LOT_SIZE_SCALE.powu(TICK_SCALE) /* one quantized unit in pUSD */;\nif amount < min_amount { return Err(format!(\"amount {amount} below min {min_amount} pUSD\")); }","typeGuard":"fn is_tradeable_collateral(amount: Decimal, lot_size_scale: u32) -> bool {\n    amount > Decimal::ZERO && amount.round_dp(lot_size_scale as u32) > Decimal::ZERO\n}","tryCatchPattern":null,"preventionTips":["Enforce a minimum notional floor in the position sizer well above the venue lot size.","Keep amounts as Decimal end-to-end; never round through f64 before order building.","Unit-test the builder with boundary amounts at exactly one quantized unit."],"tags":["polymarket","decimal-precision","order-building","validation"],"backgroundTag":"value-out-of-range","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"}