diff --git a/nautilus_core/model/src/orders/market.rs b/nautilus_core/model/src/orders/market.rs index 455f4bfec34f..80b08dbe7e55 100644 --- a/nautilus_core/model/src/orders/market.rs +++ b/nautilus_core/model/src/orders/market.rs @@ -77,7 +77,7 @@ impl MarketOrder { ) -> anyhow::Result { check_quantity_positive(quantity)?; if time_in_force == TimeInForce::Gtd { - anyhow::bail!("{}", "GTD not supported for Market orders"); + anyhow::bail!("GTD not supported for Market orders"); } let init_order = OrderInitialized::new( trader_id, diff --git a/nautilus_core/model/src/python/orders/limit.rs b/nautilus_core/model/src/python/orders/limit.rs index c0f4f4a5bb9c..702b15cd50b0 100644 --- a/nautilus_core/model/src/python/orders/limit.rs +++ b/nautilus_core/model/src/python/orders/limit.rs @@ -555,7 +555,10 @@ impl LimitOrder { dict.set_item("price", self.price.to_string())?; dict.set_item("status", self.status.to_string())?; dict.set_item("time_in_force", self.time_in_force.to_string())?; - dict.set_item("expire_time_ns", self.expire_time.map(|e| e.as_u64()))?; + dict.set_item( + "expire_time_ns", + self.expire_time.filter(|&t| t != 0).map(|t| t.as_u64()), + )?; dict.set_item("is_post_only", self.is_post_only)?; dict.set_item("is_reduce_only", self.is_reduce_only)?; dict.set_item("is_quote_quantity", self.is_quote_quantity)?; diff --git a/nautilus_core/model/src/python/orders/stop_limit.rs b/nautilus_core/model/src/python/orders/stop_limit.rs index 7722174fe7de..b5301f037ecf 100644 --- a/nautilus_core/model/src/python/orders/stop_limit.rs +++ b/nautilus_core/model/src/python/orders/stop_limit.rs @@ -359,7 +359,10 @@ impl StopLimitOrder { dict.set_item("is_reduce_only", self.is_reduce_only)?; dict.set_item("is_quote_quantity", self.is_quote_quantity)?; dict.set_item("init_id", self.init_id.to_string())?; - dict.set_item("expire_time_ns", self.expire_time.map(|e| e.as_u64()))?; + dict.set_item( + "expire_time_ns", + self.expire_time.filter(|&t| t != 0).map(|t| t.as_u64()), + )?; dict.set_item("ts_init", self.ts_init.as_u64())?; dict.set_item("ts_last", self.ts_last.as_u64())?; let commissions_dict = PyDict::new(py); diff --git a/nautilus_trader/model/orders/limit.pyx b/nautilus_trader/model/orders/limit.pyx index 86ba7aa4b189..92a2d6c3cb0f 100644 --- a/nautilus_trader/model/orders/limit.pyx +++ b/nautilus_trader/model/orders/limit.pyx @@ -165,7 +165,7 @@ cdef class LimitOrder(Order): Condition.true(expire_time_ns == 0, "`expire_time_ns` was set when `time_in_force` not GTD.") Condition.true( display_qty is None or 0 <= display_qty <= quantity, - fail_msg="display_qty was negative or greater than order quantity", + fail_msg="`display_qty` was negative or greater than `quantity`", ) # Set options @@ -319,7 +319,7 @@ cdef class LimitOrder(Order): "quantity": str(self.quantity), "price": str(self.price), "time_in_force": time_in_force_to_str(self.time_in_force), - "expire_time_ns": self.expire_time_ns, + "expire_time_ns": self.expire_time_ns if self.expire_time_ns > 0 else None, "filled_qty": str(self.filled_qty), "liquidity_side": liquidity_side_to_str(self.liquidity_side), "avg_px": str(self.avg_px) if self.filled_qty.as_f64_c() > 0.0 else None, diff --git a/nautilus_trader/model/orders/limit_if_touched.pyx b/nautilus_trader/model/orders/limit_if_touched.pyx index 9dad03ca712d..b342b8dcd3de 100644 --- a/nautilus_trader/model/orders/limit_if_touched.pyx +++ b/nautilus_trader/model/orders/limit_if_touched.pyx @@ -179,7 +179,7 @@ cdef class LimitIfTouchedOrder(Order): Condition.true(expire_time_ns == 0, "`expire_time_ns` was set when `time_in_force` not GTD.") Condition.true( display_qty is None or 0 <= display_qty <= quantity, - fail_msg="display_qty was negative or greater than order quantity", + fail_msg="`display_qty` was negative or greater than `quantity`", ) # Set options @@ -312,7 +312,7 @@ cdef class LimitIfTouchedOrder(Order): "price": str(self.price), "trigger_price": str(self.trigger_price), "trigger_type": trigger_type_to_str(self.trigger_type), - "expire_time_ns": self.expire_time_ns, + "expire_time_ns": self.expire_time_ns if self.expire_time_ns > 0 else None, "time_in_force": time_in_force_to_str(self.time_in_force), "filled_qty": str(self.filled_qty), "liquidity_side": liquidity_side_to_str(self.liquidity_side), diff --git a/nautilus_trader/model/orders/market_if_touched.pyx b/nautilus_trader/model/orders/market_if_touched.pyx index 778ac60a96d0..8a790438b244 100644 --- a/nautilus_trader/model/orders/market_if_touched.pyx +++ b/nautilus_trader/model/orders/market_if_touched.pyx @@ -280,7 +280,7 @@ cdef class MarketIfTouchedOrder(Order): "quantity": str(self.quantity), "trigger_price": str(self.trigger_price), "trigger_type": trigger_type_to_str(self.trigger_type), - "expire_time_ns": self.expire_time_ns, + "expire_time_ns": self.expire_time_ns if self.expire_time_ns > 0 else None, "time_in_force": time_in_force_to_str(self.time_in_force), "filled_qty": str(self.filled_qty), "liquidity_side": liquidity_side_to_str(self.liquidity_side), diff --git a/nautilus_trader/model/orders/market_to_limit.pyx b/nautilus_trader/model/orders/market_to_limit.pyx index 0f0a13ce6ea9..4d370f4ef874 100644 --- a/nautilus_trader/model/orders/market_to_limit.pyx +++ b/nautilus_trader/model/orders/market_to_limit.pyx @@ -259,7 +259,7 @@ cdef class MarketToLimitOrder(Order): "quantity": str(self.quantity), "price": str(self.price), "time_in_force": time_in_force_to_str(self.time_in_force), - "expire_time_ns": self.expire_time_ns, + "expire_time_ns": self.expire_time_ns if self.expire_time_ns > 0 else None, "is_reduce_only": self.is_reduce_only, "is_quote_quantity": self.is_quote_quantity, "display_qty": str(self.display_qty) if self.display_qty is not None else None, diff --git a/nautilus_trader/model/orders/stop_limit.pyx b/nautilus_trader/model/orders/stop_limit.pyx index b09ac810069f..24d596d3e9a8 100644 --- a/nautilus_trader/model/orders/stop_limit.pyx +++ b/nautilus_trader/model/orders/stop_limit.pyx @@ -184,7 +184,7 @@ cdef class StopLimitOrder(Order): Condition.true(expire_time_ns == 0, "`expire_time_ns` was set when `time_in_force` not GTD.") Condition.true( display_qty is None or 0 <= display_qty <= quantity, - fail_msg="display_qty was negative or greater than order quantity", + fail_msg="`display_qty` was negative or greater than `quantity`", ) # Set options diff --git a/nautilus_trader/model/orders/stop_market.pyx b/nautilus_trader/model/orders/stop_market.pyx index 0078feedcaff..1dc1c5771a3c 100644 --- a/nautilus_trader/model/orders/stop_market.pyx +++ b/nautilus_trader/model/orders/stop_market.pyx @@ -285,7 +285,7 @@ cdef class StopMarketOrder(Order): "quantity": str(self.quantity), "trigger_price": str(self.trigger_price), "trigger_type": trigger_type_to_str(self.trigger_type), - "expire_time_ns": self.expire_time_ns, + "expire_time_ns": self.expire_time_ns if self.expire_time_ns > 0 else None, "time_in_force": time_in_force_to_str(self.time_in_force), "filled_qty": str(self.filled_qty), "liquidity_side": liquidity_side_to_str(self.liquidity_side), diff --git a/nautilus_trader/model/orders/trailing_stop_limit.pyx b/nautilus_trader/model/orders/trailing_stop_limit.pyx index f4d05ac9ec1c..dcd027e2bc5e 100644 --- a/nautilus_trader/model/orders/trailing_stop_limit.pyx +++ b/nautilus_trader/model/orders/trailing_stop_limit.pyx @@ -184,7 +184,7 @@ cdef class TrailingStopLimitOrder(Order): Condition.true(expire_time_ns == 0, "`expire_time_ns` was set when `time_in_force` not GTD.") Condition.true( display_qty is None or 0 <= display_qty <= quantity, - fail_msg="`display_qty` was negative or greater than order quantity", + fail_msg="`display_qty` was negative or greater than `quantity`", ) # Set options @@ -329,7 +329,7 @@ cdef class TrailingStopLimitOrder(Order): "limit_offset": str(self.limit_offset), "trailing_offset": str(self.trailing_offset), "trailing_offset_type": trailing_offset_type_to_str(self.trailing_offset_type), - "expire_time_ns": self.expire_time_ns, + "expire_time_ns": self.expire_time_ns if self.expire_time_ns > 0 else None, "time_in_force": time_in_force_to_str(self.time_in_force), "filled_qty": str(self.filled_qty), "liquidity_side": liquidity_side_to_str(self.liquidity_side), diff --git a/nautilus_trader/model/orders/trailing_stop_market.pyx b/nautilus_trader/model/orders/trailing_stop_market.pyx index 3563d2597d0f..af4c5821022e 100644 --- a/nautilus_trader/model/orders/trailing_stop_market.pyx +++ b/nautilus_trader/model/orders/trailing_stop_market.pyx @@ -294,7 +294,7 @@ cdef class TrailingStopMarketOrder(Order): "trigger_type": trigger_type_to_str(self.trigger_type), "trailing_offset": str(self.trailing_offset), "trailing_offset_type": trailing_offset_type_to_str(self.trailing_offset_type), - "expire_time_ns": self.expire_time_ns, + "expire_time_ns": self.expire_time_ns if self.expire_time_ns > 0 else None, "time_in_force": time_in_force_to_str(self.time_in_force), "filled_qty": str(self.filled_qty), "liquidity_side": liquidity_side_to_str(self.liquidity_side), diff --git a/tests/unit_tests/model/test_orders.py b/tests/unit_tests/model/test_orders.py index 31c282d02158..6598a1df945b 100644 --- a/tests/unit_tests/model/test_orders.py +++ b/tests/unit_tests/model/test_orders.py @@ -488,7 +488,7 @@ def test_limit_order_to_dict(self): "side": "BUY", "quantity": "100000", "price": "1.00000", - "expire_time_ns": 0, + "expire_time_ns": None, "time_in_force": "GTC", "filled_qty": "0", "liquidity_side": "NO_LIQUIDITY_SIDE", @@ -603,7 +603,7 @@ def test_stop_market_order_to_dict(self): "quantity": "100000", "trigger_price": "1.00000", "trigger_type": "DEFAULT", - "expire_time_ns": 0, + "expire_time_ns": None, "time_in_force": "GTC", "filled_qty": "0", "liquidity_side": "NO_LIQUIDITY_SIDE", @@ -860,7 +860,7 @@ def test_market_if_touched_order_to_dict(self): "quantity": "100000", "trigger_price": "1.00000", "trigger_type": "DEFAULT", - "expire_time_ns": 0, + "expire_time_ns": None, "time_in_force": "GTC", "filled_qty": "0", "liquidity_side": "NO_LIQUIDITY_SIDE", @@ -951,7 +951,7 @@ def test_limit_if_touched_order_to_dict(self): "price": "1.00000", "trigger_price": "1.10010", "trigger_type": "MARK_PRICE", - "expire_time_ns": 0, + "expire_time_ns": None, "time_in_force": "GTC", "filled_qty": "0", "liquidity_side": "NO_LIQUIDITY_SIDE", @@ -1070,7 +1070,7 @@ def test_trailing_stop_market_order_to_dict(self): "trigger_type": "DEFAULT", "trailing_offset": "0.00050", "trailing_offset_type": "PRICE", - "expire_time_ns": 0, + "expire_time_ns": None, "time_in_force": "GTC", "filled_qty": "0", "liquidity_side": "NO_LIQUIDITY_SIDE", @@ -1123,7 +1123,7 @@ def test_trailing_stop_market_order_with_no_initial_trigger_to_dict(self): "trigger_type": "DEFAULT", "trailing_offset": "0.00050", "trailing_offset_type": "PRICE", - "expire_time_ns": 0, + "expire_time_ns": None, "time_in_force": "GTC", "filled_qty": "0", "liquidity_side": "NO_LIQUIDITY_SIDE", @@ -1242,7 +1242,7 @@ def test_trailing_stop_limit_order_to_dict(self): "limit_offset": "5", "trailing_offset": "10", "trailing_offset_type": "BASIS_POINTS", - "expire_time_ns": 0, + "expire_time_ns": None, "time_in_force": "GTC", "filled_qty": "0", "liquidity_side": "NO_LIQUIDITY_SIDE", @@ -1299,7 +1299,7 @@ def test_trailing_stop_limit_order_with_no_initial_prices_to_dict(self): "limit_offset": "5", "trailing_offset": "10", "trailing_offset_type": "BASIS_POINTS", - "expire_time_ns": 0, + "expire_time_ns": None, "time_in_force": "GTC", "filled_qty": "0", "liquidity_side": "NO_LIQUIDITY_SIDE",