nautilus_infrastructure/sql/models/
orders.rs

1// -------------------------------------------------------------------------------------------------
2//  Copyright (C) 2015-2025 Nautech Systems Pty Ltd. All rights reserved.
3//  https://nautechsystems.io
4//
5//  Licensed under the GNU Lesser General Public License Version 3.0 (the "License");
6//  You may not use this file except in compliance with the License.
7//  You may obtain a copy of the License at https://www.gnu.org/licenses/lgpl-3.0.en.html
8//
9//  Unless required by applicable law or agreed to in writing, software
10//  distributed under the License is distributed on an "AS IS" BASIS,
11//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12//  See the License for the specific language governing permissions and
13//  limitations under the License.
14// -------------------------------------------------------------------------------------------------
15
16use std::str::FromStr;
17
18use indexmap::IndexMap;
19use nautilus_core::{UUID4, UnixNanos};
20use nautilus_model::{
21    enums::{
22        ContingencyType, LiquiditySide, OrderSide, OrderStatus, OrderType, TimeInForce, TriggerType,
23    },
24    events::{
25        OrderAccepted, OrderCancelRejected, OrderCanceled, OrderDenied, OrderEmulated,
26        OrderEventAny, OrderExpired, OrderFilled, OrderInitialized, OrderModifyRejected,
27        OrderPendingCancel, OrderPendingUpdate, OrderRejected, OrderReleased, OrderSnapshot,
28        OrderSubmitted, OrderTriggered, OrderUpdated,
29    },
30    identifiers::{
31        AccountId, ClientOrderId, ExecAlgorithmId, InstrumentId, OrderListId, PositionId,
32        StrategyId, TradeId, TraderId, VenueOrderId,
33    },
34    types::{Currency, Money, Price, Quantity},
35};
36use rust_decimal::Decimal;
37use sqlx::{FromRow, Row, postgres::PgRow};
38use ustr::Ustr;
39
40use crate::sql::models::enums::TrailingOffsetTypeModel;
41
42pub struct OrderEventAnyModel(pub OrderEventAny);
43pub struct OrderAcceptedModel(pub OrderAccepted);
44pub struct OrderCancelRejectedModel(pub OrderCancelRejected);
45pub struct OrderCanceledModel(pub OrderCanceled);
46pub struct OrderDeniedModel(pub OrderDenied);
47pub struct OrderEmulatedModel(pub OrderEmulated);
48pub struct OrderExpiredModel(pub OrderExpired);
49pub struct OrderFilledModel(pub OrderFilled);
50pub struct OrderInitializedModel(pub OrderInitialized);
51pub struct OrderModifyRejectedModel(pub OrderModifyRejected);
52pub struct OrderPendingCancelModel(pub OrderPendingCancel);
53pub struct OrderPendingUpdateModel(pub OrderPendingUpdate);
54pub struct OrderRejectedModel(pub OrderRejected);
55pub struct OrderReleasedModel(pub OrderReleased);
56pub struct OrderSubmittedModel(pub OrderSubmitted);
57pub struct OrderTriggeredModel(pub OrderTriggered);
58pub struct OrderUpdatedModel(pub OrderUpdated);
59pub struct OrderSnapshotModel(pub OrderSnapshot);
60
61impl<'r> FromRow<'r, PgRow> for OrderEventAnyModel {
62    fn from_row(row: &'r PgRow) -> Result<Self, sqlx::Error> {
63        let kind = row.get::<String, _>("kind");
64        if kind == "OrderAccepted" {
65            let model = OrderAcceptedModel::from_row(row)?;
66            Ok(OrderEventAnyModel(OrderEventAny::Accepted(model.0)))
67        } else if kind == "OrderCancelRejected" {
68            let model = OrderCancelRejectedModel::from_row(row)?;
69            Ok(OrderEventAnyModel(OrderEventAny::CancelRejected(model.0)))
70        } else if kind == "OrderCanceled" {
71            let model = OrderCanceledModel::from_row(row)?;
72            Ok(OrderEventAnyModel(OrderEventAny::Canceled(model.0)))
73        } else if kind == "OrderDenied" {
74            let model = OrderDeniedModel::from_row(row)?;
75            Ok(OrderEventAnyModel(OrderEventAny::Denied(model.0)))
76        } else if kind == "OrderEmulated" {
77            let model = OrderEmulatedModel::from_row(row)?;
78            Ok(OrderEventAnyModel(OrderEventAny::Emulated(model.0)))
79        } else if kind == "OrderExpired" {
80            let model = OrderExpiredModel::from_row(row)?;
81            Ok(OrderEventAnyModel(OrderEventAny::Expired(model.0)))
82        } else if kind == "OrderFilled" {
83            let model = OrderFilledModel::from_row(row)?;
84            Ok(OrderEventAnyModel(OrderEventAny::Filled(model.0)))
85        } else if kind == "OrderInitialized" {
86            let model = OrderInitializedModel::from_row(row)?;
87            Ok(OrderEventAnyModel(OrderEventAny::Initialized(model.0)))
88        } else if kind == "OrderModifyRejected" {
89            let model = OrderModifyRejectedModel::from_row(row)?;
90            Ok(OrderEventAnyModel(OrderEventAny::ModifyRejected(model.0)))
91        } else if kind == "OrderPendingCancel" {
92            let model = OrderPendingCancelModel::from_row(row)?;
93            Ok(OrderEventAnyModel(OrderEventAny::PendingCancel(model.0)))
94        } else if kind == "OrderPendingUpdate" {
95            let model = OrderPendingUpdateModel::from_row(row)?;
96            Ok(OrderEventAnyModel(OrderEventAny::PendingUpdate(model.0)))
97        } else if kind == "OrderRejected" {
98            let model = OrderRejectedModel::from_row(row)?;
99            Ok(OrderEventAnyModel(OrderEventAny::Rejected(model.0)))
100        } else if kind == "OrderReleased" {
101            let model = OrderReleasedModel::from_row(row)?;
102            Ok(OrderEventAnyModel(OrderEventAny::Released(model.0)))
103        } else if kind == "OrderSubmitted" {
104            let model = OrderSubmittedModel::from_row(row)?;
105            Ok(OrderEventAnyModel(OrderEventAny::Submitted(model.0)))
106        } else if kind == "OrderTriggered" {
107            let model = OrderTriggeredModel::from_row(row)?;
108            Ok(OrderEventAnyModel(OrderEventAny::Triggered(model.0)))
109        } else if kind == "OrderUpdated" {
110            let model = OrderUpdatedModel::from_row(row)?;
111            Ok(OrderEventAnyModel(OrderEventAny::Updated(model.0)))
112        } else {
113            panic!("Unknown order event kind: {kind} in Postgres transformation",)
114        }
115    }
116}
117
118impl<'r> FromRow<'r, PgRow> for OrderInitializedModel {
119    fn from_row(row: &'r PgRow) -> Result<Self, sqlx::Error> {
120        let event_id = row.try_get::<&str, _>("id").map(UUID4::from)?;
121        let client_order_id = row
122            .try_get::<&str, _>("client_order_id")
123            .map(ClientOrderId::from)?;
124        let trader_id = row.try_get::<&str, _>("trader_id").map(TraderId::from)?;
125        let strategy_id = row
126            .try_get::<&str, _>("strategy_id")
127            .map(StrategyId::from)?;
128        let instrument_id = row
129            .try_get::<&str, _>("instrument_id")
130            .map(InstrumentId::from)?;
131        let order_type = row
132            .try_get::<&str, _>("order_type")
133            .map(|x| OrderType::from_str(x).unwrap())?;
134        let order_side = row
135            .try_get::<&str, _>("order_side")
136            .map(|x| OrderSide::from_str(x).unwrap())?;
137        let quantity = row.try_get::<&str, _>("quantity").map(Quantity::from)?;
138        let time_in_force = row
139            .try_get::<&str, _>("time_in_force")
140            .map(|x| TimeInForce::from_str(x).unwrap())?;
141        let post_only = row.try_get::<bool, _>("post_only")?;
142        let reduce_only = row.try_get::<bool, _>("reduce_only")?;
143        let quote_quantity = row.try_get::<bool, _>("quote_quantity")?;
144        let reconciliation = row.try_get::<bool, _>("reconciliation")?;
145        let ts_event = row.try_get::<String, _>("ts_event").map(UnixNanos::from)?;
146        let ts_init = row.try_get::<String, _>("ts_init").map(UnixNanos::from)?;
147        let price = row
148            .try_get::<Option<&str>, _>("price")
149            .ok()
150            .and_then(|x| x.map(Price::from));
151        let trigger_price = row
152            .try_get::<Option<&str>, _>("trigger_price")
153            .ok()
154            .and_then(|x| x.map(Price::from));
155        let trigger_type = row
156            .try_get::<Option<&str>, _>("trigger_type")
157            .ok()
158            .and_then(|x| x.map(|x| TriggerType::from_str(x).unwrap()));
159        let limit_offset = row
160            .try_get::<Option<&str>, _>("limit_offset")
161            .ok()
162            .and_then(|x| x.and_then(|s| Decimal::from_str(s).ok()));
163        let trailing_offset = row
164            .try_get::<Option<&str>, _>("trailing_offset")
165            .ok()
166            .and_then(|x| x.and_then(|s| Decimal::from_str(s).ok()));
167        let trailing_offset_type = row
168            .try_get::<Option<TrailingOffsetTypeModel>, _>("trailing_offset_type")
169            .ok()
170            .and_then(|x| x.map(|x| x.0));
171        let expire_time = row
172            .try_get::<Option<&str>, _>("expire_time")
173            .ok()
174            .and_then(|x| x.map(UnixNanos::from));
175        let display_qty = row
176            .try_get::<Option<&str>, _>("display_qty")
177            .ok()
178            .and_then(|x| x.map(Quantity::from));
179        let emulation_trigger = row
180            .try_get::<Option<&str>, _>("emulation_trigger")
181            .ok()
182            .and_then(|x| x.map(|x| TriggerType::from_str(x).unwrap()));
183        let trigger_instrument_id = row
184            .try_get::<Option<&str>, _>("trigger_instrument_id")
185            .ok()
186            .and_then(|x| x.map(InstrumentId::from));
187        let contingency_type = row
188            .try_get::<Option<&str>, _>("contingency_type")
189            .ok()
190            .and_then(|x| x.map(|x| ContingencyType::from_str(x).unwrap()));
191        let order_list_id = row
192            .try_get::<Option<&str>, _>("order_list_id")
193            .ok()
194            .and_then(|x| x.map(OrderListId::from));
195        let linked_order_ids = row
196            .try_get::<Vec<String>, _>("linked_order_ids")
197            .ok()
198            .map(|x| x.iter().map(|x| ClientOrderId::from(x.as_str())).collect());
199        let parent_order_id = row
200            .try_get::<Option<&str>, _>("parent_order_id")
201            .ok()
202            .and_then(|x| x.map(ClientOrderId::from));
203        let exec_algorithm_id = row
204            .try_get::<Option<&str>, _>("exec_algorithm_id")
205            .ok()
206            .and_then(|x| x.map(ExecAlgorithmId::from));
207        let exec_algorithm_params: Option<IndexMap<Ustr, Ustr>> = row
208            .try_get::<Option<serde_json::Value>, _>("exec_algorithm_params")
209            .ok()
210            .and_then(|x| x.map(|x| serde_json::from_value::<IndexMap<String, String>>(x).unwrap()))
211            .map(|x| {
212                x.into_iter()
213                    .map(|(k, v)| (Ustr::from(k.as_str()), Ustr::from(v.as_str())))
214                    .collect()
215            });
216        let exec_spawn_id = row
217            .try_get::<Option<&str>, _>("exec_spawn_id")
218            .ok()
219            .and_then(|x| x.map(ClientOrderId::from));
220        let tags: Option<Vec<Ustr>> = row
221            .try_get::<Option<serde_json::Value>, _>("tags")
222            .ok()
223            .and_then(|x| x.map(|x| serde_json::from_value::<Vec<String>>(x).unwrap()))
224            .map(|x| x.into_iter().map(|x| Ustr::from(x.as_str())).collect());
225        let order_event = OrderInitialized::new(
226            trader_id,
227            strategy_id,
228            instrument_id,
229            client_order_id,
230            order_side,
231            order_type,
232            quantity,
233            time_in_force,
234            post_only,
235            reduce_only,
236            quote_quantity,
237            reconciliation,
238            event_id,
239            ts_event,
240            ts_init,
241            price,
242            trigger_price,
243            trigger_type,
244            limit_offset,
245            trailing_offset,
246            trailing_offset_type,
247            expire_time,
248            display_qty,
249            emulation_trigger,
250            trigger_instrument_id,
251            contingency_type,
252            order_list_id,
253            linked_order_ids,
254            parent_order_id,
255            exec_algorithm_id,
256            exec_algorithm_params,
257            exec_spawn_id,
258            tags,
259        );
260        Ok(OrderInitializedModel(order_event))
261    }
262}
263
264impl<'r> FromRow<'r, PgRow> for OrderAcceptedModel {
265    fn from_row(row: &'r PgRow) -> Result<Self, sqlx::Error> {
266        let event_id = row.try_get::<&str, _>("id").map(UUID4::from)?;
267        let trader_id = row.try_get::<&str, _>("trader_id").map(TraderId::from)?;
268        let strategy_id = row
269            .try_get::<&str, _>("strategy_id")
270            .map(StrategyId::from)?;
271        let instrument_id = row
272            .try_get::<&str, _>("instrument_id")
273            .map(InstrumentId::from)?;
274        let client_order_id = row
275            .try_get::<&str, _>("client_order_id")
276            .map(ClientOrderId::from)?;
277        let venue_order_id = row
278            .try_get::<&str, _>("venue_order_id")
279            .map(VenueOrderId::from)?;
280        let account_id = row.try_get::<&str, _>("account_id").map(AccountId::from)?;
281        let ts_event = row.try_get::<&str, _>("ts_event").map(UnixNanos::from)?;
282        let ts_init = row.try_get::<&str, _>("ts_init").map(UnixNanos::from)?;
283        let order_event = OrderAccepted::new(
284            trader_id,
285            strategy_id,
286            instrument_id,
287            client_order_id,
288            venue_order_id,
289            account_id,
290            event_id,
291            ts_event,
292            ts_init,
293            false,
294        );
295        Ok(OrderAcceptedModel(order_event))
296    }
297}
298
299impl<'r> FromRow<'r, PgRow> for OrderCancelRejectedModel {
300    fn from_row(_row: &'r PgRow) -> Result<Self, sqlx::Error> {
301        todo!()
302    }
303}
304
305impl<'r> FromRow<'r, PgRow> for OrderCanceledModel {
306    fn from_row(_row: &'r PgRow) -> Result<Self, sqlx::Error> {
307        todo!()
308    }
309}
310
311impl<'r> FromRow<'r, PgRow> for OrderDeniedModel {
312    fn from_row(_row: &'r PgRow) -> Result<Self, sqlx::Error> {
313        todo!()
314    }
315}
316
317impl<'r> FromRow<'r, PgRow> for OrderEmulatedModel {
318    fn from_row(_row: &'r PgRow) -> Result<Self, sqlx::Error> {
319        todo!()
320    }
321}
322
323impl<'r> FromRow<'r, PgRow> for OrderExpiredModel {
324    fn from_row(_row: &'r PgRow) -> Result<Self, sqlx::Error> {
325        todo!()
326    }
327}
328
329impl<'r> FromRow<'r, PgRow> for OrderFilledModel {
330    fn from_row(row: &'r PgRow) -> Result<Self, sqlx::Error> {
331        let event_id = row.try_get::<&str, _>("id").map(UUID4::from)?;
332        let trader_id = row.try_get::<&str, _>("trader_id").map(TraderId::from)?;
333        let strategy_id = row
334            .try_get::<&str, _>("strategy_id")
335            .map(StrategyId::from)?;
336        let instrument_id = row
337            .try_get::<&str, _>("instrument_id")
338            .map(InstrumentId::from)?;
339        let client_order_id = row
340            .try_get::<&str, _>("client_order_id")
341            .map(ClientOrderId::from)?;
342        let venue_order_id = row
343            .try_get::<&str, _>("venue_order_id")
344            .map(VenueOrderId::from)?;
345        let account_id = row.try_get::<&str, _>("account_id").map(AccountId::from)?;
346        let trade_id = row.try_get::<&str, _>("trade_id").map(TradeId::from)?;
347        let order_side = row
348            .try_get::<&str, _>("order_side")
349            .map(|x| OrderSide::from_str(x).unwrap())?;
350        let order_type = row
351            .try_get::<&str, _>("order_type")
352            .map(|x| OrderType::from_str(x).unwrap())?;
353        let last_px = row.try_get::<&str, _>("last_px").map(Price::from)?;
354        let last_qty = row.try_get::<&str, _>("last_qty").map(Quantity::from)?;
355        let currency = row.try_get::<&str, _>("currency").map(Currency::from)?;
356        let liquidity_side = row
357            .try_get::<&str, _>("liquidity_side")
358            .map(|x| LiquiditySide::from_str(x).unwrap())?;
359        let ts_event = row.try_get::<&str, _>("ts_event").map(UnixNanos::from)?;
360        let ts_init = row.try_get::<&str, _>("ts_init").map(UnixNanos::from)?;
361        let position_id = row
362            .try_get::<Option<&str>, _>("position_id")
363            .map(|x| x.map(PositionId::from))?;
364        let commission = row
365            .try_get::<Option<&str>, _>("commission")
366            .map(|x| x.map(|x| Money::from_str(x).unwrap()))?;
367        let order_event = OrderFilled::new(
368            trader_id,
369            strategy_id,
370            instrument_id,
371            client_order_id,
372            venue_order_id,
373            account_id,
374            trade_id,
375            order_side,
376            order_type,
377            last_qty,
378            last_px,
379            currency,
380            liquidity_side,
381            event_id,
382            ts_event,
383            ts_init,
384            false,
385            position_id,
386            commission,
387        );
388        Ok(OrderFilledModel(order_event))
389    }
390}
391
392impl<'r> FromRow<'r, PgRow> for OrderModifyRejectedModel {
393    fn from_row(_row: &'r PgRow) -> Result<Self, sqlx::Error> {
394        todo!()
395    }
396}
397
398impl<'r> FromRow<'r, PgRow> for OrderPendingCancelModel {
399    fn from_row(_row: &'r PgRow) -> Result<Self, sqlx::Error> {
400        todo!()
401    }
402}
403
404impl<'r> FromRow<'r, PgRow> for OrderPendingUpdateModel {
405    fn from_row(_row: &'r PgRow) -> Result<Self, sqlx::Error> {
406        todo!()
407    }
408}
409
410impl<'r> FromRow<'r, PgRow> for OrderRejectedModel {
411    fn from_row(_row: &'r PgRow) -> Result<Self, sqlx::Error> {
412        todo!()
413    }
414}
415
416impl<'r> FromRow<'r, PgRow> for OrderReleasedModel {
417    fn from_row(_row: &'r PgRow) -> Result<Self, sqlx::Error> {
418        todo!()
419    }
420}
421
422impl<'r> FromRow<'r, PgRow> for OrderSubmittedModel {
423    fn from_row(row: &'r PgRow) -> Result<Self, sqlx::Error> {
424        let trader_id = row.try_get::<&str, _>("trader_id").map(TraderId::from)?;
425        let strategy_id = row
426            .try_get::<&str, _>("strategy_id")
427            .map(StrategyId::from)?;
428        let instrument_id = row
429            .try_get::<&str, _>("instrument_id")
430            .map(InstrumentId::from)?;
431        let client_order_id = row
432            .try_get::<&str, _>("client_order_id")
433            .map(ClientOrderId::from)?;
434        let account_id = row.try_get::<&str, _>("account_id").map(AccountId::from)?;
435        let event_id = row.try_get::<&str, _>("id").map(UUID4::from)?;
436        let ts_event = row
437            .try_get::<String, _>("ts_event")
438            .map(|res| UnixNanos::from(res.as_str()))?;
439        let ts_init = row
440            .try_get::<String, _>("ts_init")
441            .map(|res| UnixNanos::from(res.as_str()))?;
442        let order_event = OrderSubmitted::new(
443            trader_id,
444            strategy_id,
445            instrument_id,
446            client_order_id,
447            account_id,
448            event_id,
449            ts_event,
450            ts_init,
451        );
452        Ok(OrderSubmittedModel(order_event))
453    }
454}
455
456impl<'r> FromRow<'r, PgRow> for OrderTriggeredModel {
457    fn from_row(_row: &'r PgRow) -> Result<Self, sqlx::Error> {
458        todo!()
459    }
460}
461
462impl<'r> FromRow<'r, PgRow> for OrderUpdatedModel {
463    fn from_row(_row: &'r PgRow) -> Result<Self, sqlx::Error> {
464        todo!()
465    }
466}
467
468impl<'r> FromRow<'r, PgRow> for OrderSnapshotModel {
469    fn from_row(row: &'r PgRow) -> Result<Self, sqlx::Error> {
470        let trader_id = row.try_get::<&str, _>("trader_id").map(TraderId::from)?;
471        let strategy_id = row
472            .try_get::<&str, _>("strategy_id")
473            .map(StrategyId::from)?;
474        let instrument_id = row
475            .try_get::<&str, _>("instrument_id")
476            .map(InstrumentId::from)?;
477        let client_order_id = row
478            .try_get::<&str, _>("client_order_id")
479            .map(ClientOrderId::from)?;
480        let venue_order_id = row
481            .try_get::<Option<&str>, _>("venue_order_id")
482            .ok()
483            .and_then(|x| x.map(VenueOrderId::from));
484        let position_id = row
485            .try_get::<Option<&str>, _>("position_id")
486            .ok()
487            .and_then(|x| x.map(PositionId::from));
488        let account_id = row
489            .try_get::<Option<&str>, _>("account_id")
490            .ok()
491            .and_then(|x| x.map(AccountId::from));
492        let last_trade_id = row
493            .try_get::<Option<&str>, _>("last_trade_id")
494            .ok()
495            .and_then(|x| x.map(TradeId::from));
496        let order_type = row
497            .try_get::<&str, _>("order_type")
498            .map(|x| OrderType::from_str(x).expect("Invalid `OrderType`"))?;
499        let order_side = row
500            .try_get::<&str, _>("order_side")
501            .map(|x| OrderSide::from_str(x).expect("Invalid `OrderSide`"))?;
502        let quantity = row.try_get::<&str, _>("quantity").map(Quantity::from)?;
503        let price = row
504            .try_get::<Option<&str>, _>("price")
505            .ok()
506            .and_then(|x| x.map(Price::from));
507        let trigger_price = row
508            .try_get::<Option<&str>, _>("trigger_price")
509            .ok()
510            .and_then(|x| x.map(Price::from));
511        let trigger_type = row
512            .try_get::<Option<&str>, _>("trigger_type")
513            .ok()
514            .and_then(|x| x.map(|x| TriggerType::from_str(x).expect("Invalid `TriggerType`")));
515        let limit_offset = row
516            .try_get::<Option<&str>, _>("limit_offset")
517            .ok()
518            .and_then(|x| x.and_then(|s| Decimal::from_str(s).ok()));
519        let trailing_offset = row
520            .try_get::<Option<&str>, _>("trailing_offset")
521            .ok()
522            .and_then(|x| x.and_then(|s| Decimal::from_str(s).ok()));
523        let trailing_offset_type = row
524            .try_get::<Option<TrailingOffsetTypeModel>, _>("trailing_offset_type")
525            .ok()
526            .and_then(|x| x.map(|x| x.0));
527        let time_in_force = row
528            .try_get::<&str, _>("time_in_force")
529            .map(|x| TimeInForce::from_str(x).expect("Invalid `TimeInForce`"))?;
530        let expire_time = row
531            .try_get::<Option<&str>, _>("expire_time")
532            .ok()
533            .and_then(|x| x.map(UnixNanos::from));
534        let filled_qty = row.try_get::<&str, _>("filled_qty").map(Quantity::from)?;
535        let liquidity_side = row
536            .try_get::<Option<&str>, _>("liquidity_side")
537            .ok()
538            .and_then(|x| x.map(|x| LiquiditySide::from_str(x).expect("Invalid `LiquiditySide`")));
539        let avg_px = row.try_get::<Option<f64>, _>("avg_px").ok().flatten();
540        let slippage = row.try_get::<Option<f64>, _>("slippage").ok().flatten();
541        let commissions = row
542            .try_get::<Option<Vec<String>>, _>("commissions")?
543            .map_or_else(Vec::new, |c| {
544                c.into_iter().map(|s| Money::from(&s)).collect()
545            });
546        let status = row
547            .try_get::<&str, _>("status")
548            .map(|x| OrderStatus::from_str(x).expect("Invalid `OrderStatus`"))?;
549        let is_post_only = row.try_get::<bool, _>("is_post_only")?;
550        let is_reduce_only = row.try_get::<bool, _>("is_reduce_only")?;
551        let is_quote_quantity = row.try_get::<bool, _>("is_quote_quantity")?;
552        let display_qty = row
553            .try_get::<Option<&str>, _>("display_qty")
554            .ok()
555            .and_then(|x| x.map(Quantity::from));
556        let emulation_trigger = row
557            .try_get::<Option<&str>, _>("emulation_trigger")
558            .ok()
559            .and_then(|x| x.map(|x| TriggerType::from_str(x).expect("Invalid `TriggerType`")));
560        let trigger_instrument_id = row
561            .try_get::<Option<&str>, _>("trigger_instrument_id")
562            .ok()
563            .and_then(|x| x.map(InstrumentId::from));
564        let contingency_type = row
565            .try_get::<Option<&str>, _>("contingency_type")
566            .ok()
567            .and_then(|x| {
568                x.map(|x| ContingencyType::from_str(x).expect("Invalid `ContingencyType`"))
569            });
570        let order_list_id = row
571            .try_get::<Option<&str>, _>("order_list_id")
572            .ok()
573            .and_then(|x| x.map(OrderListId::from));
574        let linked_order_ids = row
575            .try_get::<Option<Vec<String>>, _>("linked_order_ids")
576            .ok()
577            .and_then(|ids| ids.map(|ids| ids.into_iter().map(ClientOrderId::from).collect()));
578        let parent_order_id = row
579            .try_get::<Option<&str>, _>("parent_order_id")
580            .ok()
581            .and_then(|x| x.map(ClientOrderId::from));
582        let exec_algorithm_id = row
583            .try_get::<Option<&str>, _>("exec_algorithm_id")
584            .ok()
585            .and_then(|x| x.map(ExecAlgorithmId::from));
586        let exec_algorithm_params: Option<IndexMap<Ustr, Ustr>> = row
587            .try_get::<Option<serde_json::Value>, _>("exec_algorithm_params")
588            .ok()
589            .and_then(|x| {
590                x.map(|x| {
591                    serde_json::from_value::<IndexMap<String, String>>(x)
592                        .expect("Invalid exec algorithm params")
593                })
594            })
595            .map(|x| {
596                x.into_iter()
597                    .map(|(k, v)| (Ustr::from(k.as_str()), Ustr::from(v.as_str())))
598                    .collect()
599            });
600        let exec_spawn_id = row
601            .try_get::<Option<&str>, _>("exec_spawn_id")
602            .ok()
603            .and_then(|x| x.map(ClientOrderId::from));
604        let tags = row
605            .try_get::<Option<serde_json::Value>, _>("tags")
606            .ok()
607            .flatten()
608            .and_then(|tags_value| {
609                serde_json::from_value::<Vec<String>>(tags_value)
610                    .ok()
611                    .map(|vec| {
612                        vec.into_iter()
613                            .map(|tag| Ustr::from(tag.as_str()))
614                            .collect::<Vec<Ustr>>()
615                    })
616            });
617        let init_id = row.try_get::<&str, _>("init_id").map(UUID4::from)?;
618        let ts_init = row.try_get::<String, _>("ts_init").map(UnixNanos::from)?;
619        let ts_last = row.try_get::<String, _>("ts_last").map(UnixNanos::from)?;
620
621        let snapshot = OrderSnapshot {
622            trader_id,
623            strategy_id,
624            instrument_id,
625            client_order_id,
626            venue_order_id,
627            position_id,
628            account_id,
629            last_trade_id,
630            order_type,
631            order_side,
632            quantity,
633            price,
634            trigger_price,
635            trigger_type,
636            limit_offset,
637            trailing_offset,
638            trailing_offset_type,
639            time_in_force,
640            expire_time,
641            filled_qty,
642            liquidity_side,
643            avg_px,
644            slippage,
645            commissions,
646            status,
647            is_post_only,
648            is_reduce_only,
649            is_quote_quantity,
650            display_qty,
651            emulation_trigger,
652            trigger_instrument_id,
653            contingency_type,
654            order_list_id,
655            linked_order_ids,
656            parent_order_id,
657            exec_algorithm_id,
658            exec_algorithm_params,
659            exec_spawn_id,
660            tags,
661            init_id,
662            ts_init,
663            ts_last,
664        };
665
666        Ok(OrderSnapshotModel(snapshot))
667    }
668}