Skip to main content

nautilus_serialization/capnp/
conversions.rs

1// -------------------------------------------------------------------------------------------------
2//  Copyright (C) 2015-2026 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
16//! Conversion implementations between Nautilus types and Cap'n Proto.
17
18use std::error::Error;
19
20use indexmap::IndexMap;
21use nautilus_model::{
22    data::{
23        FundingRateUpdate, IndexPriceUpdate, InstrumentClose, InstrumentStatus, MarkPriceUpdate,
24        QuoteTick, TradeTick,
25        bar::{Bar, BarSpecification, BarType},
26        delta::OrderBookDelta,
27        deltas::OrderBookDeltas,
28        depth::OrderBookDepth10,
29        order::BookOrder,
30    },
31    enums::{
32        AccountType, AggregationSource, AggressorSide, AssetClass, BarAggregation, BookAction,
33        BookType, ContingencyType, CurrencyType, InstrumentClass, InstrumentCloseType,
34        LiquiditySide, MarketStatusAction, OmsType, OptionKind, OrderSide, OrderStatus, OrderType,
35        PositionAdjustmentType, PositionSide, PriceType, RecordFlag, TimeInForce,
36        TrailingOffsetType, TriggerType,
37    },
38    events::{
39        OrderAccepted, OrderCancelRejected, OrderCanceled, OrderDenied, OrderEmulated,
40        OrderExpired, OrderFilled, OrderInitialized, OrderModifyRejected, OrderPendingCancel,
41        OrderPendingUpdate, OrderRejected, OrderReleased, OrderSubmitted, OrderTriggered,
42        OrderUpdated, PositionAdjusted, PositionChanged, PositionClosed, PositionOpened,
43    },
44    identifiers::{
45        AccountId, ActorId, ClientId, ClientOrderId, ComponentId, ExecAlgorithmId, InstrumentId,
46        OrderListId, PositionId, StrategyId, Symbol, TradeId, TraderId, Venue, VenueOrderId,
47    },
48    types::{AccountBalance, Currency, MarginBalance, Money, Price, Quantity},
49};
50use rust_decimal::Decimal;
51use ustr::Ustr;
52use uuid::Uuid;
53
54use super::{FromCapnp, ToCapnp};
55use crate::{
56    base_capnp, enums_capnp, identifiers_capnp, market_capnp, order_capnp, position_capnp,
57    types_capnp,
58};
59
60trait CapnpWriteExt<'a, T>
61where
62    T: ToCapnp<'a>,
63{
64    fn write_capnp<F>(&self, init: F)
65    where
66        F: FnOnce() -> T::Builder;
67}
68
69impl<'a, T> CapnpWriteExt<'a, T> for T
70where
71    T: ToCapnp<'a>,
72{
73    fn write_capnp<F>(&self, init: F)
74    where
75        F: FnOnce() -> T::Builder,
76    {
77        self.to_capnp(init());
78    }
79}
80
81impl<'a, T> CapnpWriteExt<'a, T> for Option<T>
82where
83    T: ToCapnp<'a>,
84{
85    fn write_capnp<F>(&self, init: F)
86    where
87        F: FnOnce() -> T::Builder,
88    {
89        if let Some(value) = self {
90            value.to_capnp(init());
91        }
92    }
93}
94
95fn read_optional_from_capnp<'a, T, FHas, FGet>(
96    has: FHas,
97    get: FGet,
98) -> Result<Option<T>, Box<dyn Error>>
99where
100    T: FromCapnp<'a>,
101    FHas: FnOnce() -> bool,
102    FGet: FnOnce() -> capnp::Result<<T as FromCapnp<'a>>::Reader>,
103{
104    if has() {
105        let reader = get()?;
106        Ok(Some(T::from_capnp(reader)?))
107    } else {
108        Ok(None)
109    }
110}
111
112impl<'a> ToCapnp<'a> for nautilus_core::UUID4 {
113    type Builder = base_capnp::u_u_i_d4::Builder<'a>;
114
115    fn to_capnp(&self, mut builder: Self::Builder) {
116        builder.set_value(&self.as_bytes());
117    }
118}
119
120impl<'a> FromCapnp<'a> for nautilus_core::UUID4 {
121    type Reader = base_capnp::u_u_i_d4::Reader<'a>;
122
123    fn from_capnp(reader: Self::Reader) -> Result<Self, Box<dyn Error>> {
124        let bytes = reader.get_value()?;
125        let bytes_array: [u8; 16] = bytes.try_into().map_err(|_| {
126            std::io::Error::new(
127                std::io::ErrorKind::InvalidData,
128                "Invalid UUID4 bytes length",
129            )
130        })?;
131        let uuid = Uuid::from_bytes(bytes_array);
132        Ok(Self::from(uuid))
133    }
134}
135
136// Decimal
137// rust_decimal serialization format (16 bytes):
138// - Bytes 0-3: flags (u32) - scale and sign
139// - Bytes 4-7: lo (u32) - low 32 bits of coefficient
140// - Bytes 8-11: mid (u32) - middle 32 bits of coefficient
141// - Bytes 12-15: hi (u32) - high 32 bits of coefficient
142fn decimal_to_parts(value: &Decimal) -> (u64, u64, u64, u32) {
143    let bytes = value.serialize();
144    let flags = u32::from_le_bytes(bytes[0..4].try_into().expect("flags slice"));
145    let lo = u32::from_le_bytes(bytes[4..8].try_into().expect("lo slice"));
146    let mid = u32::from_le_bytes(bytes[8..12].try_into().expect("mid slice"));
147    let hi = u32::from_le_bytes(bytes[12..16].try_into().expect("hi slice"));
148    (lo as u64, mid as u64, hi as u64, flags)
149}
150
151fn decimal_from_parts(lo: u64, mid: u64, hi: u64, flags: u32) -> Decimal {
152    let mut bytes = [0u8; 16];
153    bytes[0..4].copy_from_slice(&flags.to_le_bytes());
154    bytes[4..8].copy_from_slice(&(lo as u32).to_le_bytes());
155    bytes[8..12].copy_from_slice(&(mid as u32).to_le_bytes());
156    bytes[12..16].copy_from_slice(&(hi as u32).to_le_bytes());
157    Decimal::deserialize(bytes)
158}
159
160impl<'a> ToCapnp<'a> for Decimal {
161    type Builder = types_capnp::decimal::Builder<'a>;
162
163    fn to_capnp(&self, mut builder: Self::Builder) {
164        let (lo, mid, hi, flags) = decimal_to_parts(self);
165        builder.set_flags(flags);
166        builder.set_lo(lo);
167        builder.set_mid(mid);
168        builder.set_hi(hi);
169    }
170}
171
172impl<'a> FromCapnp<'a> for Decimal {
173    type Reader = types_capnp::decimal::Reader<'a>;
174
175    fn from_capnp(reader: Self::Reader) -> Result<Self, Box<dyn Error>> {
176        let flags = reader.get_flags();
177        let lo = reader.get_lo();
178        let mid = reader.get_mid();
179        let hi = reader.get_hi();
180        Ok(decimal_from_parts(lo, mid, hi, flags))
181    }
182}
183
184impl<'a> ToCapnp<'a> for TraderId {
185    type Builder = identifiers_capnp::trader_id::Builder<'a>;
186
187    fn to_capnp(&self, mut builder: Self::Builder) {
188        builder.set_value(self.as_str());
189    }
190}
191
192impl<'a> FromCapnp<'a> for TraderId {
193    type Reader = identifiers_capnp::trader_id::Reader<'a>;
194
195    fn from_capnp(reader: Self::Reader) -> Result<Self, Box<dyn Error>> {
196        let value = reader.get_value()?.to_str()?;
197        Ok(value.into())
198    }
199}
200
201impl<'a> ToCapnp<'a> for StrategyId {
202    type Builder = identifiers_capnp::strategy_id::Builder<'a>;
203
204    fn to_capnp(&self, mut builder: Self::Builder) {
205        builder.set_value(self.as_str());
206    }
207}
208
209impl<'a> FromCapnp<'a> for StrategyId {
210    type Reader = identifiers_capnp::strategy_id::Reader<'a>;
211
212    fn from_capnp(reader: Self::Reader) -> Result<Self, Box<dyn Error>> {
213        let value = reader.get_value()?.to_str()?;
214        Ok(value.into())
215    }
216}
217
218impl<'a> ToCapnp<'a> for ActorId {
219    type Builder = identifiers_capnp::actor_id::Builder<'a>;
220
221    fn to_capnp(&self, mut builder: Self::Builder) {
222        builder.set_value(self.as_str());
223    }
224}
225
226impl<'a> FromCapnp<'a> for ActorId {
227    type Reader = identifiers_capnp::actor_id::Reader<'a>;
228
229    fn from_capnp(reader: Self::Reader) -> Result<Self, Box<dyn Error>> {
230        let value = reader.get_value()?.to_str()?;
231        Ok(value.into())
232    }
233}
234
235impl<'a> ToCapnp<'a> for AccountId {
236    type Builder = identifiers_capnp::account_id::Builder<'a>;
237
238    fn to_capnp(&self, mut builder: Self::Builder) {
239        builder.set_value(self.as_str());
240    }
241}
242
243impl<'a> FromCapnp<'a> for AccountId {
244    type Reader = identifiers_capnp::account_id::Reader<'a>;
245
246    fn from_capnp(reader: Self::Reader) -> Result<Self, Box<dyn Error>> {
247        let value = reader.get_value()?.to_str()?;
248        Ok(value.into())
249    }
250}
251
252impl<'a> ToCapnp<'a> for ClientId {
253    type Builder = identifiers_capnp::client_id::Builder<'a>;
254
255    fn to_capnp(&self, mut builder: Self::Builder) {
256        builder.set_value(self.as_str());
257    }
258}
259
260impl<'a> FromCapnp<'a> for ClientId {
261    type Reader = identifiers_capnp::client_id::Reader<'a>;
262
263    fn from_capnp(reader: Self::Reader) -> Result<Self, Box<dyn Error>> {
264        let value = reader.get_value()?.to_str()?;
265        Ok(value.into())
266    }
267}
268
269impl<'a> ToCapnp<'a> for ClientOrderId {
270    type Builder = identifiers_capnp::client_order_id::Builder<'a>;
271
272    fn to_capnp(&self, mut builder: Self::Builder) {
273        builder.set_value(self.as_str());
274    }
275}
276
277impl<'a> FromCapnp<'a> for ClientOrderId {
278    type Reader = identifiers_capnp::client_order_id::Reader<'a>;
279
280    fn from_capnp(reader: Self::Reader) -> Result<Self, Box<dyn Error>> {
281        let value = reader.get_value()?.to_str()?;
282        Ok(value.into())
283    }
284}
285
286impl<'a> ToCapnp<'a> for VenueOrderId {
287    type Builder = identifiers_capnp::venue_order_id::Builder<'a>;
288
289    fn to_capnp(&self, mut builder: Self::Builder) {
290        builder.set_value(self.as_str());
291    }
292}
293
294impl<'a> FromCapnp<'a> for VenueOrderId {
295    type Reader = identifiers_capnp::venue_order_id::Reader<'a>;
296
297    fn from_capnp(reader: Self::Reader) -> Result<Self, Box<dyn Error>> {
298        let value = reader.get_value()?.to_str()?;
299        Ok(value.into())
300    }
301}
302
303impl<'a> ToCapnp<'a> for TradeId {
304    type Builder = identifiers_capnp::trade_id::Builder<'a>;
305
306    fn to_capnp(&self, mut builder: Self::Builder) {
307        builder.set_value(self.as_cstr().to_str().expect("Valid UTF-8"));
308    }
309}
310
311impl<'a> FromCapnp<'a> for TradeId {
312    type Reader = identifiers_capnp::trade_id::Reader<'a>;
313
314    fn from_capnp(reader: Self::Reader) -> Result<Self, Box<dyn Error>> {
315        let value = reader.get_value()?.to_str()?;
316        Ok(value.into())
317    }
318}
319
320impl<'a> ToCapnp<'a> for PositionId {
321    type Builder = identifiers_capnp::position_id::Builder<'a>;
322
323    fn to_capnp(&self, mut builder: Self::Builder) {
324        builder.set_value(self.as_str());
325    }
326}
327
328impl<'a> FromCapnp<'a> for PositionId {
329    type Reader = identifiers_capnp::position_id::Reader<'a>;
330
331    fn from_capnp(reader: Self::Reader) -> Result<Self, Box<dyn Error>> {
332        let value = reader.get_value()?.to_str()?;
333        Ok(value.into())
334    }
335}
336
337impl<'a> ToCapnp<'a> for ExecAlgorithmId {
338    type Builder = identifiers_capnp::exec_algorithm_id::Builder<'a>;
339
340    fn to_capnp(&self, mut builder: Self::Builder) {
341        builder.set_value(self.as_str());
342    }
343}
344
345impl<'a> FromCapnp<'a> for ExecAlgorithmId {
346    type Reader = identifiers_capnp::exec_algorithm_id::Reader<'a>;
347
348    fn from_capnp(reader: Self::Reader) -> Result<Self, Box<dyn Error>> {
349        let value = reader.get_value()?.to_str()?;
350        Ok(value.into())
351    }
352}
353
354impl<'a> ToCapnp<'a> for ComponentId {
355    type Builder = identifiers_capnp::component_id::Builder<'a>;
356
357    fn to_capnp(&self, mut builder: Self::Builder) {
358        builder.set_value(self.as_str());
359    }
360}
361
362impl<'a> FromCapnp<'a> for ComponentId {
363    type Reader = identifiers_capnp::component_id::Reader<'a>;
364
365    fn from_capnp(reader: Self::Reader) -> Result<Self, Box<dyn Error>> {
366        let value = reader.get_value()?.to_str()?;
367        Ok(value.into())
368    }
369}
370
371impl<'a> ToCapnp<'a> for OrderListId {
372    type Builder = identifiers_capnp::order_list_id::Builder<'a>;
373
374    fn to_capnp(&self, mut builder: Self::Builder) {
375        builder.set_value(self.as_str());
376    }
377}
378
379impl<'a> FromCapnp<'a> for OrderListId {
380    type Reader = identifiers_capnp::order_list_id::Reader<'a>;
381
382    fn from_capnp(reader: Self::Reader) -> Result<Self, Box<dyn Error>> {
383        let value = reader.get_value()?.to_str()?;
384        Ok(value.into())
385    }
386}
387
388impl<'a> ToCapnp<'a> for Symbol {
389    type Builder = identifiers_capnp::symbol::Builder<'a>;
390
391    fn to_capnp(&self, mut builder: Self::Builder) {
392        builder.set_value(self.as_str());
393    }
394}
395
396impl<'a> FromCapnp<'a> for Symbol {
397    type Reader = identifiers_capnp::symbol::Reader<'a>;
398
399    fn from_capnp(reader: Self::Reader) -> Result<Self, Box<dyn Error>> {
400        let value = reader.get_value()?.to_str()?;
401        Ok(value.into())
402    }
403}
404
405impl<'a> ToCapnp<'a> for Venue {
406    type Builder = identifiers_capnp::venue::Builder<'a>;
407
408    fn to_capnp(&self, mut builder: Self::Builder) {
409        builder.set_value(self.as_str());
410    }
411}
412
413impl<'a> FromCapnp<'a> for Venue {
414    type Reader = identifiers_capnp::venue::Reader<'a>;
415
416    fn from_capnp(reader: Self::Reader) -> Result<Self, Box<dyn Error>> {
417        let value = reader.get_value()?.to_str()?;
418        Ok(value.into())
419    }
420}
421
422impl<'a> ToCapnp<'a> for InstrumentId {
423    type Builder = identifiers_capnp::instrument_id::Builder<'a>;
424
425    fn to_capnp(&self, mut builder: Self::Builder) {
426        self.symbol.to_capnp(builder.reborrow().init_symbol());
427        self.venue.to_capnp(builder.init_venue());
428    }
429}
430
431impl<'a> FromCapnp<'a> for InstrumentId {
432    type Reader = identifiers_capnp::instrument_id::Reader<'a>;
433
434    fn from_capnp(reader: Self::Reader) -> Result<Self, Box<dyn Error>> {
435        let symbol = Symbol::from_capnp(reader.get_symbol()?)?;
436        let venue = Venue::from_capnp(reader.get_venue()?)?;
437        Ok(Self::new(symbol, venue))
438    }
439}
440
441impl<'a> ToCapnp<'a> for Price {
442    type Builder = types_capnp::price::Builder<'a>;
443
444    #[expect(clippy::useless_conversion)] // Needed for non-high-precision builds
445    fn to_capnp(&self, mut builder: Self::Builder) {
446        let raw_i128: i128 = self.raw.into();
447        let lo = raw_i128 as u64;
448        let hi = (raw_i128 >> 64) as u64;
449
450        let mut raw_builder = builder.reborrow().init_raw();
451        raw_builder.set_lo(lo);
452        raw_builder.set_hi(hi);
453
454        builder.set_precision(self.precision);
455    }
456}
457
458impl<'a> FromCapnp<'a> for Price {
459    type Reader = types_capnp::price::Reader<'a>;
460
461    fn from_capnp(reader: Self::Reader) -> Result<Self, Box<dyn Error>> {
462        let raw_reader = reader.get_raw()?;
463        let lo = raw_reader.get_lo();
464        let hi = raw_reader.get_hi();
465        let precision = reader.get_precision();
466
467        // Reconstruct i128 from two u64 halves with proper sign extension.
468        // Casting hi through i64 first ensures the sign bit (MSB of hi) propagates
469        // to all upper bits when widened to i128, preserving two's complement.
470        let raw_i128 = ((hi as i64 as i128) << 64) | (lo as i128);
471
472        #[cfg(not(feature = "high-precision"))]
473        let raw = i64::try_from(raw_i128).map_err(|_| -> Box<dyn Error> {
474            "Price value overflows i64 in standard precision mode".into()
475        })?;
476
477        #[cfg(feature = "high-precision")]
478        let raw = raw_i128;
479
480        #[expect(clippy::useless_conversion)] // Needed for non-high-precision builds
481        Ok(Self::from_raw(raw.into(), precision))
482    }
483}
484
485impl<'a> ToCapnp<'a> for Quantity {
486    type Builder = types_capnp::quantity::Builder<'a>;
487
488    #[expect(clippy::useless_conversion)] // Needed for non-high-precision builds
489    fn to_capnp(&self, mut builder: Self::Builder) {
490        let raw_u128: u128 = self.raw.into();
491        let lo = raw_u128 as u64;
492        let hi = (raw_u128 >> 64) as u64;
493
494        let mut raw_builder = builder.reborrow().init_raw();
495        raw_builder.set_lo(lo);
496        raw_builder.set_hi(hi);
497
498        builder.set_precision(self.precision);
499    }
500}
501
502impl<'a> FromCapnp<'a> for Quantity {
503    type Reader = types_capnp::quantity::Reader<'a>;
504
505    fn from_capnp(reader: Self::Reader) -> Result<Self, Box<dyn Error>> {
506        let raw_reader = reader.get_raw()?;
507        let lo = raw_reader.get_lo();
508        let hi = raw_reader.get_hi();
509        let precision = reader.get_precision();
510
511        // Reconstruct u128 from two u64 halves (unsigned, no sign extension needed)
512        let raw_u128 = ((hi as u128) << 64) | (lo as u128);
513
514        #[cfg(not(feature = "high-precision"))]
515        let raw = u64::try_from(raw_u128).map_err(|_| -> Box<dyn Error> {
516            "Quantity value overflows u64 in standard precision mode".into()
517        })?;
518
519        #[cfg(feature = "high-precision")]
520        let raw = raw_u128;
521
522        #[expect(clippy::useless_conversion)] // Needed for non-high-precision builds
523        Ok(Self::from_raw(raw.into(), precision))
524    }
525}
526
527#[must_use]
528pub fn currency_type_to_capnp(value: CurrencyType) -> enums_capnp::CurrencyType {
529    match value {
530        CurrencyType::Crypto => enums_capnp::CurrencyType::Crypto,
531        CurrencyType::Fiat => enums_capnp::CurrencyType::Fiat,
532        CurrencyType::CommodityBacked => enums_capnp::CurrencyType::CommodityBacked,
533    }
534}
535
536#[must_use]
537pub fn currency_type_from_capnp(value: enums_capnp::CurrencyType) -> CurrencyType {
538    match value {
539        enums_capnp::CurrencyType::Crypto => CurrencyType::Crypto,
540        enums_capnp::CurrencyType::Fiat => CurrencyType::Fiat,
541        enums_capnp::CurrencyType::CommodityBacked => CurrencyType::CommodityBacked,
542    }
543}
544
545#[must_use]
546pub fn account_type_to_capnp(value: AccountType) -> enums_capnp::AccountType {
547    match value {
548        AccountType::Cash => enums_capnp::AccountType::Cash,
549        AccountType::Margin => enums_capnp::AccountType::Margin,
550        AccountType::Betting => enums_capnp::AccountType::Betting,
551        AccountType::Wallet => enums_capnp::AccountType::Wallet,
552    }
553}
554
555#[must_use]
556pub fn account_type_from_capnp(value: enums_capnp::AccountType) -> AccountType {
557    match value {
558        enums_capnp::AccountType::Cash => AccountType::Cash,
559        enums_capnp::AccountType::Margin => AccountType::Margin,
560        enums_capnp::AccountType::Betting => AccountType::Betting,
561        enums_capnp::AccountType::Wallet => AccountType::Wallet,
562    }
563}
564
565#[must_use]
566pub fn aggressor_side_to_capnp(value: AggressorSide) -> enums_capnp::AggressorSide {
567    match value {
568        AggressorSide::NoAggressor => enums_capnp::AggressorSide::NoAggressor,
569        AggressorSide::Buyer => enums_capnp::AggressorSide::Buyer,
570        AggressorSide::Seller => enums_capnp::AggressorSide::Seller,
571    }
572}
573
574#[must_use]
575pub fn aggressor_side_from_capnp(value: enums_capnp::AggressorSide) -> AggressorSide {
576    match value {
577        enums_capnp::AggressorSide::NoAggressor => AggressorSide::NoAggressor,
578        enums_capnp::AggressorSide::Buyer => AggressorSide::Buyer,
579        enums_capnp::AggressorSide::Seller => AggressorSide::Seller,
580    }
581}
582
583#[must_use]
584pub fn asset_class_to_capnp(value: AssetClass) -> enums_capnp::AssetClass {
585    match value {
586        AssetClass::FX => enums_capnp::AssetClass::Fx,
587        AssetClass::Equity => enums_capnp::AssetClass::Equity,
588        AssetClass::Commodity => enums_capnp::AssetClass::Commodity,
589        AssetClass::Debt => enums_capnp::AssetClass::Debt,
590        AssetClass::Index => enums_capnp::AssetClass::Index,
591        AssetClass::Cryptocurrency => enums_capnp::AssetClass::Cryptocurrency,
592        AssetClass::Alternative => enums_capnp::AssetClass::Alternative,
593    }
594}
595
596#[must_use]
597pub fn asset_class_from_capnp(value: enums_capnp::AssetClass) -> AssetClass {
598    match value {
599        enums_capnp::AssetClass::Fx => AssetClass::FX,
600        enums_capnp::AssetClass::Equity => AssetClass::Equity,
601        enums_capnp::AssetClass::Commodity => AssetClass::Commodity,
602        enums_capnp::AssetClass::Debt => AssetClass::Debt,
603        enums_capnp::AssetClass::Index => AssetClass::Index,
604        enums_capnp::AssetClass::Cryptocurrency => AssetClass::Cryptocurrency,
605        enums_capnp::AssetClass::Alternative => AssetClass::Alternative,
606    }
607}
608
609#[must_use]
610pub fn instrument_class_to_capnp(value: InstrumentClass) -> enums_capnp::InstrumentClass {
611    match value {
612        InstrumentClass::Spot => enums_capnp::InstrumentClass::Spot,
613        InstrumentClass::Swap => enums_capnp::InstrumentClass::Swap,
614        InstrumentClass::Future => enums_capnp::InstrumentClass::Future,
615        InstrumentClass::FuturesSpread => enums_capnp::InstrumentClass::FuturesSpread,
616        InstrumentClass::Forward => enums_capnp::InstrumentClass::Forward,
617        InstrumentClass::Cfd => enums_capnp::InstrumentClass::Cfd,
618        InstrumentClass::Bond => enums_capnp::InstrumentClass::Bond,
619        InstrumentClass::Option => enums_capnp::InstrumentClass::Option,
620        InstrumentClass::OptionSpread => enums_capnp::InstrumentClass::OptionSpread,
621        InstrumentClass::Warrant => enums_capnp::InstrumentClass::Warrant,
622        InstrumentClass::SportsBetting => enums_capnp::InstrumentClass::SportsBetting,
623        InstrumentClass::BinaryOption => enums_capnp::InstrumentClass::BinaryOption,
624    }
625}
626
627#[must_use]
628pub fn instrument_class_from_capnp(value: enums_capnp::InstrumentClass) -> InstrumentClass {
629    match value {
630        enums_capnp::InstrumentClass::Spot => InstrumentClass::Spot,
631        enums_capnp::InstrumentClass::Swap => InstrumentClass::Swap,
632        enums_capnp::InstrumentClass::Future => InstrumentClass::Future,
633        enums_capnp::InstrumentClass::FuturesSpread => InstrumentClass::FuturesSpread,
634        enums_capnp::InstrumentClass::Forward => InstrumentClass::Forward,
635        enums_capnp::InstrumentClass::Cfd => InstrumentClass::Cfd,
636        enums_capnp::InstrumentClass::Bond => InstrumentClass::Bond,
637        enums_capnp::InstrumentClass::Option => InstrumentClass::Option,
638        enums_capnp::InstrumentClass::OptionSpread => InstrumentClass::OptionSpread,
639        enums_capnp::InstrumentClass::Warrant => InstrumentClass::Warrant,
640        enums_capnp::InstrumentClass::SportsBetting => InstrumentClass::SportsBetting,
641        enums_capnp::InstrumentClass::BinaryOption => InstrumentClass::BinaryOption,
642    }
643}
644
645#[must_use]
646pub fn option_kind_to_capnp(value: OptionKind) -> enums_capnp::OptionKind {
647    match value {
648        OptionKind::Call => enums_capnp::OptionKind::Call,
649        OptionKind::Put => enums_capnp::OptionKind::Put,
650    }
651}
652
653#[must_use]
654pub fn option_kind_from_capnp(value: enums_capnp::OptionKind) -> OptionKind {
655    match value {
656        enums_capnp::OptionKind::Call => OptionKind::Call,
657        enums_capnp::OptionKind::Put => OptionKind::Put,
658    }
659}
660
661#[must_use]
662pub fn order_side_to_capnp(value: OrderSide) -> enums_capnp::OrderSide {
663    match value {
664        OrderSide::NoOrderSide => enums_capnp::OrderSide::NoOrderSide,
665        OrderSide::Buy => enums_capnp::OrderSide::Buy,
666        OrderSide::Sell => enums_capnp::OrderSide::Sell,
667    }
668}
669
670#[must_use]
671pub fn order_side_from_capnp(value: enums_capnp::OrderSide) -> OrderSide {
672    match value {
673        enums_capnp::OrderSide::NoOrderSide => OrderSide::NoOrderSide,
674        enums_capnp::OrderSide::Buy => OrderSide::Buy,
675        enums_capnp::OrderSide::Sell => OrderSide::Sell,
676    }
677}
678
679#[must_use]
680pub fn order_type_to_capnp(value: OrderType) -> enums_capnp::OrderType {
681    match value {
682        OrderType::Market => enums_capnp::OrderType::Market,
683        OrderType::Limit => enums_capnp::OrderType::Limit,
684        OrderType::StopMarket => enums_capnp::OrderType::StopMarket,
685        OrderType::StopLimit => enums_capnp::OrderType::StopLimit,
686        OrderType::MarketToLimit => enums_capnp::OrderType::MarketToLimit,
687        OrderType::MarketIfTouched => enums_capnp::OrderType::MarketIfTouched,
688        OrderType::LimitIfTouched => enums_capnp::OrderType::LimitIfTouched,
689        OrderType::TrailingStopMarket => enums_capnp::OrderType::TrailingStopMarket,
690        OrderType::TrailingStopLimit => enums_capnp::OrderType::TrailingStopLimit,
691    }
692}
693
694#[must_use]
695pub fn order_type_from_capnp(value: enums_capnp::OrderType) -> OrderType {
696    match value {
697        enums_capnp::OrderType::Market => OrderType::Market,
698        enums_capnp::OrderType::Limit => OrderType::Limit,
699        enums_capnp::OrderType::StopMarket => OrderType::StopMarket,
700        enums_capnp::OrderType::StopLimit => OrderType::StopLimit,
701        enums_capnp::OrderType::MarketToLimit => OrderType::MarketToLimit,
702        enums_capnp::OrderType::MarketIfTouched => OrderType::MarketIfTouched,
703        enums_capnp::OrderType::LimitIfTouched => OrderType::LimitIfTouched,
704        enums_capnp::OrderType::TrailingStopMarket => OrderType::TrailingStopMarket,
705        enums_capnp::OrderType::TrailingStopLimit => OrderType::TrailingStopLimit,
706    }
707}
708
709#[must_use]
710pub fn order_status_to_capnp(value: OrderStatus) -> enums_capnp::OrderStatus {
711    match value {
712        OrderStatus::Initialized => enums_capnp::OrderStatus::Initialized,
713        OrderStatus::Denied => enums_capnp::OrderStatus::Denied,
714        OrderStatus::Emulated => enums_capnp::OrderStatus::Emulated,
715        OrderStatus::Released => enums_capnp::OrderStatus::Released,
716        OrderStatus::Submitted => enums_capnp::OrderStatus::Submitted,
717        OrderStatus::Accepted => enums_capnp::OrderStatus::Accepted,
718        OrderStatus::Rejected => enums_capnp::OrderStatus::Rejected,
719        OrderStatus::Canceled => enums_capnp::OrderStatus::Canceled,
720        OrderStatus::Expired => enums_capnp::OrderStatus::Expired,
721        OrderStatus::Triggered => enums_capnp::OrderStatus::Triggered,
722        OrderStatus::PendingUpdate => enums_capnp::OrderStatus::PendingUpdate,
723        OrderStatus::PendingCancel => enums_capnp::OrderStatus::PendingCancel,
724        OrderStatus::PartiallyFilled => enums_capnp::OrderStatus::PartiallyFilled,
725        OrderStatus::Filled => enums_capnp::OrderStatus::Filled,
726    }
727}
728
729#[must_use]
730pub fn order_status_from_capnp(value: enums_capnp::OrderStatus) -> OrderStatus {
731    match value {
732        enums_capnp::OrderStatus::Initialized => OrderStatus::Initialized,
733        enums_capnp::OrderStatus::Denied => OrderStatus::Denied,
734        enums_capnp::OrderStatus::Emulated => OrderStatus::Emulated,
735        enums_capnp::OrderStatus::Released => OrderStatus::Released,
736        enums_capnp::OrderStatus::Submitted => OrderStatus::Submitted,
737        enums_capnp::OrderStatus::Accepted => OrderStatus::Accepted,
738        enums_capnp::OrderStatus::Rejected => OrderStatus::Rejected,
739        enums_capnp::OrderStatus::Canceled => OrderStatus::Canceled,
740        enums_capnp::OrderStatus::Expired => OrderStatus::Expired,
741        enums_capnp::OrderStatus::Triggered => OrderStatus::Triggered,
742        enums_capnp::OrderStatus::PendingUpdate => OrderStatus::PendingUpdate,
743        enums_capnp::OrderStatus::PendingCancel => OrderStatus::PendingCancel,
744        enums_capnp::OrderStatus::PartiallyFilled => OrderStatus::PartiallyFilled,
745        enums_capnp::OrderStatus::Filled => OrderStatus::Filled,
746    }
747}
748
749#[must_use]
750pub fn time_in_force_to_capnp(value: TimeInForce) -> enums_capnp::TimeInForce {
751    match value {
752        TimeInForce::Gtc => enums_capnp::TimeInForce::Gtc,
753        TimeInForce::Ioc => enums_capnp::TimeInForce::Ioc,
754        TimeInForce::Fok => enums_capnp::TimeInForce::Fok,
755        TimeInForce::Gtd => enums_capnp::TimeInForce::Gtd,
756        TimeInForce::Day => enums_capnp::TimeInForce::Day,
757        TimeInForce::AtTheOpen => enums_capnp::TimeInForce::AtTheOpen,
758        TimeInForce::AtTheClose => enums_capnp::TimeInForce::AtTheClose,
759    }
760}
761
762#[must_use]
763pub fn time_in_force_from_capnp(value: enums_capnp::TimeInForce) -> TimeInForce {
764    match value {
765        enums_capnp::TimeInForce::Gtc => TimeInForce::Gtc,
766        enums_capnp::TimeInForce::Ioc => TimeInForce::Ioc,
767        enums_capnp::TimeInForce::Fok => TimeInForce::Fok,
768        enums_capnp::TimeInForce::Gtd => TimeInForce::Gtd,
769        enums_capnp::TimeInForce::Day => TimeInForce::Day,
770        enums_capnp::TimeInForce::AtTheOpen => TimeInForce::AtTheOpen,
771        enums_capnp::TimeInForce::AtTheClose => TimeInForce::AtTheClose,
772    }
773}
774
775#[must_use]
776pub fn trigger_type_to_capnp(value: TriggerType) -> enums_capnp::TriggerType {
777    match value {
778        TriggerType::NoTrigger => enums_capnp::TriggerType::NoTrigger,
779        TriggerType::Default => enums_capnp::TriggerType::Default,
780        TriggerType::LastPrice => enums_capnp::TriggerType::LastPrice,
781        TriggerType::MarkPrice => enums_capnp::TriggerType::MarkPrice,
782        TriggerType::IndexPrice => enums_capnp::TriggerType::IndexPrice,
783        TriggerType::BidAsk => enums_capnp::TriggerType::BidAsk,
784        TriggerType::DoubleLast => enums_capnp::TriggerType::DoubleLast,
785        TriggerType::DoubleBidAsk => enums_capnp::TriggerType::DoubleBidAsk,
786        TriggerType::LastOrBidAsk => enums_capnp::TriggerType::LastOrBidAsk,
787        TriggerType::MidPoint => enums_capnp::TriggerType::MidPoint,
788    }
789}
790
791#[must_use]
792pub fn trigger_type_from_capnp(value: enums_capnp::TriggerType) -> TriggerType {
793    match value {
794        enums_capnp::TriggerType::NoTrigger => TriggerType::NoTrigger,
795        enums_capnp::TriggerType::Default => TriggerType::Default,
796        enums_capnp::TriggerType::LastPrice => TriggerType::LastPrice,
797        enums_capnp::TriggerType::MarkPrice => TriggerType::MarkPrice,
798        enums_capnp::TriggerType::IndexPrice => TriggerType::IndexPrice,
799        enums_capnp::TriggerType::BidAsk => TriggerType::BidAsk,
800        enums_capnp::TriggerType::DoubleLast => TriggerType::DoubleLast,
801        enums_capnp::TriggerType::DoubleBidAsk => TriggerType::DoubleBidAsk,
802        enums_capnp::TriggerType::LastOrBidAsk => TriggerType::LastOrBidAsk,
803        enums_capnp::TriggerType::MidPoint => TriggerType::MidPoint,
804    }
805}
806
807#[must_use]
808pub fn contingency_type_to_capnp(value: ContingencyType) -> enums_capnp::ContingencyType {
809    match value {
810        ContingencyType::NoContingency => enums_capnp::ContingencyType::NoContingency,
811        ContingencyType::Oco => enums_capnp::ContingencyType::Oco,
812        ContingencyType::Oto => enums_capnp::ContingencyType::Oto,
813        ContingencyType::Ouo => enums_capnp::ContingencyType::Ouo,
814    }
815}
816
817#[must_use]
818pub fn contingency_type_from_capnp(value: enums_capnp::ContingencyType) -> ContingencyType {
819    match value {
820        enums_capnp::ContingencyType::NoContingency => ContingencyType::NoContingency,
821        enums_capnp::ContingencyType::Oco => ContingencyType::Oco,
822        enums_capnp::ContingencyType::Oto => ContingencyType::Oto,
823        enums_capnp::ContingencyType::Ouo => ContingencyType::Ouo,
824    }
825}
826
827#[must_use]
828pub fn position_side_to_capnp(value: PositionSide) -> enums_capnp::PositionSide {
829    match value {
830        PositionSide::NoPositionSide => enums_capnp::PositionSide::NoPositionSide,
831        PositionSide::Flat => enums_capnp::PositionSide::Flat,
832        PositionSide::Long => enums_capnp::PositionSide::Long,
833        PositionSide::Short => enums_capnp::PositionSide::Short,
834    }
835}
836
837#[must_use]
838pub fn position_side_from_capnp(value: enums_capnp::PositionSide) -> PositionSide {
839    match value {
840        enums_capnp::PositionSide::NoPositionSide => PositionSide::NoPositionSide,
841        enums_capnp::PositionSide::Flat => PositionSide::Flat,
842        enums_capnp::PositionSide::Long => PositionSide::Long,
843        enums_capnp::PositionSide::Short => PositionSide::Short,
844    }
845}
846
847#[must_use]
848pub fn position_adjustment_type_to_capnp(
849    value: PositionAdjustmentType,
850) -> enums_capnp::PositionAdjustmentType {
851    match value {
852        PositionAdjustmentType::Commission => enums_capnp::PositionAdjustmentType::Commission,
853        PositionAdjustmentType::Funding => enums_capnp::PositionAdjustmentType::Funding,
854    }
855}
856
857#[must_use]
858pub fn position_adjustment_type_from_capnp(
859    value: enums_capnp::PositionAdjustmentType,
860) -> PositionAdjustmentType {
861    match value {
862        enums_capnp::PositionAdjustmentType::Commission => PositionAdjustmentType::Commission,
863        enums_capnp::PositionAdjustmentType::Funding => PositionAdjustmentType::Funding,
864    }
865}
866
867#[must_use]
868pub fn liquidity_side_to_capnp(value: LiquiditySide) -> enums_capnp::LiquiditySide {
869    match value {
870        LiquiditySide::NoLiquiditySide => enums_capnp::LiquiditySide::NoLiquiditySide,
871        LiquiditySide::Maker => enums_capnp::LiquiditySide::Maker,
872        LiquiditySide::Taker => enums_capnp::LiquiditySide::Taker,
873    }
874}
875
876#[must_use]
877pub fn liquidity_side_from_capnp(value: enums_capnp::LiquiditySide) -> LiquiditySide {
878    match value {
879        enums_capnp::LiquiditySide::NoLiquiditySide => LiquiditySide::NoLiquiditySide,
880        enums_capnp::LiquiditySide::Maker => LiquiditySide::Maker,
881        enums_capnp::LiquiditySide::Taker => LiquiditySide::Taker,
882    }
883}
884
885#[must_use]
886pub fn book_action_to_capnp(value: BookAction) -> enums_capnp::BookAction {
887    match value {
888        BookAction::Add => enums_capnp::BookAction::Add,
889        BookAction::Update => enums_capnp::BookAction::Update,
890        BookAction::Delete => enums_capnp::BookAction::Delete,
891        BookAction::Clear => enums_capnp::BookAction::Clear,
892    }
893}
894
895#[must_use]
896pub fn book_action_from_capnp(value: enums_capnp::BookAction) -> BookAction {
897    match value {
898        enums_capnp::BookAction::Add => BookAction::Add,
899        enums_capnp::BookAction::Update => BookAction::Update,
900        enums_capnp::BookAction::Delete => BookAction::Delete,
901        enums_capnp::BookAction::Clear => BookAction::Clear,
902    }
903}
904
905#[must_use]
906pub fn book_type_to_capnp(value: BookType) -> enums_capnp::BookType {
907    match value {
908        BookType::L1_MBP => enums_capnp::BookType::TopOfBookBidOffer,
909        BookType::L2_MBP => enums_capnp::BookType::MarketByPrice,
910        BookType::L3_MBO => enums_capnp::BookType::MarketByOrder,
911    }
912}
913
914#[must_use]
915pub fn book_type_from_capnp(value: enums_capnp::BookType) -> BookType {
916    match value {
917        enums_capnp::BookType::TopOfBookBidOffer => BookType::L1_MBP,
918        enums_capnp::BookType::MarketByPrice => BookType::L2_MBP,
919        enums_capnp::BookType::MarketByOrder => BookType::L3_MBO,
920    }
921}
922
923#[must_use]
924pub fn record_flag_to_capnp(value: RecordFlag) -> enums_capnp::RecordFlag {
925    match value {
926        RecordFlag::F_LAST => enums_capnp::RecordFlag::FLast,
927        RecordFlag::F_TOB => enums_capnp::RecordFlag::FTob,
928        RecordFlag::F_SNAPSHOT => enums_capnp::RecordFlag::FSnapshot,
929        RecordFlag::F_MBP => enums_capnp::RecordFlag::FMbp,
930        RecordFlag::RESERVED_2 => enums_capnp::RecordFlag::Reserved2,
931        RecordFlag::RESERVED_1 => enums_capnp::RecordFlag::Reserved1,
932    }
933}
934
935#[must_use]
936pub fn record_flag_from_capnp(value: enums_capnp::RecordFlag) -> RecordFlag {
937    match value {
938        enums_capnp::RecordFlag::FLast => RecordFlag::F_LAST,
939        enums_capnp::RecordFlag::FTob => RecordFlag::F_TOB,
940        enums_capnp::RecordFlag::FSnapshot => RecordFlag::F_SNAPSHOT,
941        enums_capnp::RecordFlag::FMbp => RecordFlag::F_MBP,
942        enums_capnp::RecordFlag::Reserved2 => RecordFlag::RESERVED_2,
943        enums_capnp::RecordFlag::Reserved1 => RecordFlag::RESERVED_1,
944    }
945}
946
947#[must_use]
948pub fn aggregation_source_to_capnp(value: AggregationSource) -> enums_capnp::AggregationSource {
949    match value {
950        AggregationSource::External => enums_capnp::AggregationSource::External,
951        AggregationSource::Internal => enums_capnp::AggregationSource::Internal,
952    }
953}
954
955#[must_use]
956pub fn aggregation_source_from_capnp(value: enums_capnp::AggregationSource) -> AggregationSource {
957    match value {
958        enums_capnp::AggregationSource::External => AggregationSource::External,
959        enums_capnp::AggregationSource::Internal => AggregationSource::Internal,
960    }
961}
962
963#[must_use]
964pub fn price_type_to_capnp(value: PriceType) -> enums_capnp::PriceType {
965    match value {
966        PriceType::Bid => enums_capnp::PriceType::Bid,
967        PriceType::Ask => enums_capnp::PriceType::Ask,
968        PriceType::Mid => enums_capnp::PriceType::Mid,
969        PriceType::Last => enums_capnp::PriceType::Last,
970        PriceType::Mark => enums_capnp::PriceType::Mark,
971    }
972}
973
974#[must_use]
975pub fn price_type_from_capnp(value: enums_capnp::PriceType) -> PriceType {
976    match value {
977        enums_capnp::PriceType::Bid => PriceType::Bid,
978        enums_capnp::PriceType::Ask => PriceType::Ask,
979        enums_capnp::PriceType::Mid => PriceType::Mid,
980        enums_capnp::PriceType::Last => PriceType::Last,
981        enums_capnp::PriceType::Mark => PriceType::Mark,
982    }
983}
984
985#[must_use]
986pub fn bar_aggregation_to_capnp(value: BarAggregation) -> enums_capnp::BarAggregation {
987    match value {
988        BarAggregation::Tick => enums_capnp::BarAggregation::Tick,
989        BarAggregation::TickImbalance => enums_capnp::BarAggregation::TickImbalance,
990        BarAggregation::TickRuns => enums_capnp::BarAggregation::TickRuns,
991        BarAggregation::Volume => enums_capnp::BarAggregation::Volume,
992        BarAggregation::VolumeImbalance => enums_capnp::BarAggregation::VolumeImbalance,
993        BarAggregation::VolumeRuns => enums_capnp::BarAggregation::VolumeRuns,
994        BarAggregation::Value => enums_capnp::BarAggregation::Value,
995        BarAggregation::ValueImbalance => enums_capnp::BarAggregation::ValueImbalance,
996        BarAggregation::ValueRuns => enums_capnp::BarAggregation::ValueRuns,
997        BarAggregation::Millisecond => enums_capnp::BarAggregation::Millisecond,
998        BarAggregation::Second => enums_capnp::BarAggregation::Second,
999        BarAggregation::Minute => enums_capnp::BarAggregation::Minute,
1000        BarAggregation::Hour => enums_capnp::BarAggregation::Hour,
1001        BarAggregation::Day => enums_capnp::BarAggregation::Day,
1002        BarAggregation::Week => enums_capnp::BarAggregation::Week,
1003        BarAggregation::Month => enums_capnp::BarAggregation::Month,
1004        BarAggregation::Year => enums_capnp::BarAggregation::Year,
1005        BarAggregation::Renko => enums_capnp::BarAggregation::Renko,
1006    }
1007}
1008
1009#[must_use]
1010pub fn bar_aggregation_from_capnp(value: enums_capnp::BarAggregation) -> BarAggregation {
1011    match value {
1012        enums_capnp::BarAggregation::Tick => BarAggregation::Tick,
1013        enums_capnp::BarAggregation::TickImbalance => BarAggregation::TickImbalance,
1014        enums_capnp::BarAggregation::TickRuns => BarAggregation::TickRuns,
1015        enums_capnp::BarAggregation::Volume => BarAggregation::Volume,
1016        enums_capnp::BarAggregation::VolumeImbalance => BarAggregation::VolumeImbalance,
1017        enums_capnp::BarAggregation::VolumeRuns => BarAggregation::VolumeRuns,
1018        enums_capnp::BarAggregation::Value => BarAggregation::Value,
1019        enums_capnp::BarAggregation::ValueImbalance => BarAggregation::ValueImbalance,
1020        enums_capnp::BarAggregation::ValueRuns => BarAggregation::ValueRuns,
1021        enums_capnp::BarAggregation::Millisecond => BarAggregation::Millisecond,
1022        enums_capnp::BarAggregation::Second => BarAggregation::Second,
1023        enums_capnp::BarAggregation::Minute => BarAggregation::Minute,
1024        enums_capnp::BarAggregation::Hour => BarAggregation::Hour,
1025        enums_capnp::BarAggregation::Day => BarAggregation::Day,
1026        enums_capnp::BarAggregation::Week => BarAggregation::Week,
1027        enums_capnp::BarAggregation::Month => BarAggregation::Month,
1028        enums_capnp::BarAggregation::Year => BarAggregation::Year,
1029        enums_capnp::BarAggregation::Renko => BarAggregation::Renko,
1030    }
1031}
1032
1033#[must_use]
1034pub fn trailing_offset_type_to_capnp(value: TrailingOffsetType) -> enums_capnp::TrailingOffsetType {
1035    match value {
1036        TrailingOffsetType::NoTrailingOffset => enums_capnp::TrailingOffsetType::NoTrailingOffset,
1037        TrailingOffsetType::Price => enums_capnp::TrailingOffsetType::Price,
1038        TrailingOffsetType::BasisPoints => enums_capnp::TrailingOffsetType::BasisPoints,
1039        TrailingOffsetType::Ticks => enums_capnp::TrailingOffsetType::Ticks,
1040        TrailingOffsetType::PriceTier => enums_capnp::TrailingOffsetType::PriceTier,
1041    }
1042}
1043
1044#[must_use]
1045pub fn trailing_offset_type_from_capnp(
1046    value: enums_capnp::TrailingOffsetType,
1047) -> TrailingOffsetType {
1048    match value {
1049        enums_capnp::TrailingOffsetType::NoTrailingOffset => TrailingOffsetType::NoTrailingOffset,
1050        enums_capnp::TrailingOffsetType::Price => TrailingOffsetType::Price,
1051        enums_capnp::TrailingOffsetType::BasisPoints => TrailingOffsetType::BasisPoints,
1052        enums_capnp::TrailingOffsetType::Ticks => TrailingOffsetType::Ticks,
1053        enums_capnp::TrailingOffsetType::PriceTier => TrailingOffsetType::PriceTier,
1054    }
1055}
1056
1057#[must_use]
1058pub fn oms_type_to_capnp(value: OmsType) -> enums_capnp::OmsType {
1059    match value {
1060        OmsType::Unspecified => enums_capnp::OmsType::Unspecified,
1061        OmsType::Netting => enums_capnp::OmsType::Netting,
1062        OmsType::Hedging => enums_capnp::OmsType::Hedging,
1063    }
1064}
1065
1066#[must_use]
1067pub fn oms_type_from_capnp(value: enums_capnp::OmsType) -> OmsType {
1068    match value {
1069        enums_capnp::OmsType::Unspecified => OmsType::Unspecified,
1070        enums_capnp::OmsType::Netting => OmsType::Netting,
1071        enums_capnp::OmsType::Hedging => OmsType::Hedging,
1072    }
1073}
1074
1075#[must_use]
1076pub fn instrument_close_type_to_capnp(
1077    value: InstrumentCloseType,
1078) -> enums_capnp::InstrumentCloseType {
1079    match value {
1080        InstrumentCloseType::EndOfSession => enums_capnp::InstrumentCloseType::EndOfSession,
1081        InstrumentCloseType::ContractExpired => enums_capnp::InstrumentCloseType::ContractExpired,
1082    }
1083}
1084
1085#[must_use]
1086pub fn instrument_close_type_from_capnp(
1087    value: enums_capnp::InstrumentCloseType,
1088) -> InstrumentCloseType {
1089    match value {
1090        enums_capnp::InstrumentCloseType::EndOfSession => InstrumentCloseType::EndOfSession,
1091        enums_capnp::InstrumentCloseType::ContractExpired => InstrumentCloseType::ContractExpired,
1092    }
1093}
1094
1095#[must_use]
1096pub fn market_status_action_to_capnp(value: MarketStatusAction) -> enums_capnp::MarketStatusAction {
1097    match value {
1098        MarketStatusAction::None => enums_capnp::MarketStatusAction::None,
1099        MarketStatusAction::PreOpen => enums_capnp::MarketStatusAction::PreOpen,
1100        MarketStatusAction::PreCross => enums_capnp::MarketStatusAction::PreCross,
1101        MarketStatusAction::Quoting => enums_capnp::MarketStatusAction::Quoting,
1102        MarketStatusAction::Cross => enums_capnp::MarketStatusAction::Cross,
1103        MarketStatusAction::Rotation => enums_capnp::MarketStatusAction::Rotation,
1104        MarketStatusAction::NewPriceIndication => {
1105            enums_capnp::MarketStatusAction::NewPriceIndication
1106        }
1107        MarketStatusAction::Trading => enums_capnp::MarketStatusAction::Trading,
1108        MarketStatusAction::Halt => enums_capnp::MarketStatusAction::Halt,
1109        MarketStatusAction::Pause => enums_capnp::MarketStatusAction::Pause,
1110        MarketStatusAction::Suspend => enums_capnp::MarketStatusAction::Suspend,
1111        MarketStatusAction::PreClose => enums_capnp::MarketStatusAction::PreClose,
1112        MarketStatusAction::Close => enums_capnp::MarketStatusAction::Close,
1113        MarketStatusAction::PostClose => enums_capnp::MarketStatusAction::PostClose,
1114        MarketStatusAction::ShortSellRestrictionChange => {
1115            enums_capnp::MarketStatusAction::ShortSellRestrictionChange
1116        }
1117        MarketStatusAction::NotAvailableForTrading => {
1118            enums_capnp::MarketStatusAction::NotAvailableForTrading
1119        }
1120    }
1121}
1122
1123#[must_use]
1124pub fn market_status_action_from_capnp(
1125    value: enums_capnp::MarketStatusAction,
1126) -> MarketStatusAction {
1127    match value {
1128        enums_capnp::MarketStatusAction::None => MarketStatusAction::None,
1129        enums_capnp::MarketStatusAction::PreOpen => MarketStatusAction::PreOpen,
1130        enums_capnp::MarketStatusAction::PreCross => MarketStatusAction::PreCross,
1131        enums_capnp::MarketStatusAction::Quoting => MarketStatusAction::Quoting,
1132        enums_capnp::MarketStatusAction::Cross => MarketStatusAction::Cross,
1133        enums_capnp::MarketStatusAction::Rotation => MarketStatusAction::Rotation,
1134        enums_capnp::MarketStatusAction::NewPriceIndication => {
1135            MarketStatusAction::NewPriceIndication
1136        }
1137        enums_capnp::MarketStatusAction::Trading => MarketStatusAction::Trading,
1138        enums_capnp::MarketStatusAction::Halt => MarketStatusAction::Halt,
1139        enums_capnp::MarketStatusAction::Pause => MarketStatusAction::Pause,
1140        enums_capnp::MarketStatusAction::Suspend => MarketStatusAction::Suspend,
1141        enums_capnp::MarketStatusAction::PreClose => MarketStatusAction::PreClose,
1142        enums_capnp::MarketStatusAction::Close => MarketStatusAction::Close,
1143        enums_capnp::MarketStatusAction::PostClose => MarketStatusAction::PostClose,
1144        enums_capnp::MarketStatusAction::ShortSellRestrictionChange => {
1145            MarketStatusAction::ShortSellRestrictionChange
1146        }
1147        enums_capnp::MarketStatusAction::NotAvailableForTrading => {
1148            MarketStatusAction::NotAvailableForTrading
1149        }
1150    }
1151}
1152
1153#[must_use]
1154pub fn optional_bool_to_capnp(value: Option<bool>) -> enums_capnp::OptionalBool {
1155    match value {
1156        None => enums_capnp::OptionalBool::Unknown,
1157        Some(true) => enums_capnp::OptionalBool::True,
1158        Some(false) => enums_capnp::OptionalBool::False,
1159    }
1160}
1161
1162#[must_use]
1163pub fn optional_bool_from_capnp(value: enums_capnp::OptionalBool) -> Option<bool> {
1164    match value {
1165        enums_capnp::OptionalBool::Unknown => None,
1166        enums_capnp::OptionalBool::True => Some(true),
1167        enums_capnp::OptionalBool::False => Some(false),
1168    }
1169}
1170
1171impl<'a> ToCapnp<'a> for Currency {
1172    type Builder = types_capnp::currency::Builder<'a>;
1173
1174    fn to_capnp(&self, mut builder: Self::Builder) {
1175        builder.set_code(self.code);
1176        builder.set_precision(self.precision);
1177        builder.set_iso4217(self.iso4217);
1178        builder.set_name(self.name);
1179        builder.set_currency_type(currency_type_to_capnp(self.currency_type));
1180    }
1181}
1182
1183impl<'a> FromCapnp<'a> for Currency {
1184    type Reader = types_capnp::currency::Reader<'a>;
1185
1186    fn from_capnp(reader: Self::Reader) -> Result<Self, Box<dyn Error>> {
1187        let code = reader.get_code()?.to_str()?;
1188        let precision = reader.get_precision();
1189        let iso4217 = reader.get_iso4217();
1190        let name = reader.get_name()?.to_str()?;
1191        let currency_type = currency_type_from_capnp(reader.get_currency_type()?);
1192
1193        Ok(Self::new(code, precision, iso4217, name, currency_type))
1194    }
1195}
1196
1197impl<'a> ToCapnp<'a> for Money {
1198    type Builder = types_capnp::money::Builder<'a>;
1199
1200    #[expect(clippy::useless_conversion)] // Needed for non-high-precision builds
1201    fn to_capnp(&self, mut builder: Self::Builder) {
1202        let mut raw_builder = builder.reborrow().init_raw();
1203
1204        let raw_i128: i128 = self.raw.into();
1205        raw_builder.set_lo(raw_i128 as u64);
1206        raw_builder.set_hi((raw_i128 >> 64) as u64);
1207
1208        let currency_builder = builder.init_currency();
1209        self.currency.to_capnp(currency_builder);
1210    }
1211}
1212
1213impl<'a> FromCapnp<'a> for Money {
1214    type Reader = types_capnp::money::Reader<'a>;
1215
1216    fn from_capnp(reader: Self::Reader) -> Result<Self, Box<dyn Error>> {
1217        let raw_reader = reader.get_raw()?;
1218        let lo = raw_reader.get_lo();
1219        let hi = raw_reader.get_hi();
1220
1221        // Cast through i64 to sign-extend and preserve two's complement for negative values
1222        let raw_i128 = ((hi as i64 as i128) << 64) | (lo as i128);
1223
1224        let currency_reader = reader.get_currency()?;
1225        let currency = Currency::from_capnp(currency_reader)?;
1226
1227        #[cfg(not(feature = "high-precision"))]
1228        {
1229            let raw = i64::try_from(raw_i128).map_err(|_| -> Box<dyn Error> {
1230                "Money value overflows i64 in standard precision mode".into()
1231            })?;
1232            Ok(Self::from_raw(raw.into(), currency))
1233        }
1234
1235        #[cfg(feature = "high-precision")]
1236        {
1237            Ok(Self::from_raw(raw_i128, currency))
1238        }
1239    }
1240}
1241
1242impl<'a> ToCapnp<'a> for AccountBalance {
1243    type Builder = types_capnp::account_balance::Builder<'a>;
1244
1245    fn to_capnp(&self, mut builder: Self::Builder) {
1246        let total_builder = builder.reborrow().init_total();
1247        self.total.to_capnp(total_builder);
1248
1249        let locked_builder = builder.reborrow().init_locked();
1250        self.locked.to_capnp(locked_builder);
1251
1252        let free_builder = builder.init_free();
1253        self.free.to_capnp(free_builder);
1254    }
1255}
1256
1257impl<'a> FromCapnp<'a> for AccountBalance {
1258    type Reader = types_capnp::account_balance::Reader<'a>;
1259
1260    fn from_capnp(reader: Self::Reader) -> Result<Self, Box<dyn Error>> {
1261        let total_reader = reader.get_total()?;
1262        let total = Money::from_capnp(total_reader)?;
1263
1264        let locked_reader = reader.get_locked()?;
1265        let locked = Money::from_capnp(locked_reader)?;
1266
1267        let free_reader = reader.get_free()?;
1268        let free = Money::from_capnp(free_reader)?;
1269
1270        Ok(Self::new(total, locked, free))
1271    }
1272}
1273
1274impl<'a> ToCapnp<'a> for MarginBalance {
1275    type Builder = types_capnp::margin_balance::Builder<'a>;
1276
1277    fn to_capnp(&self, mut builder: Self::Builder) {
1278        let initial_builder = builder.reborrow().init_initial();
1279        self.initial.to_capnp(initial_builder);
1280
1281        let maintenance_builder = builder.reborrow().init_maintenance();
1282        self.maintenance.to_capnp(maintenance_builder);
1283
1284        // Only set the instrument pointer for per-instrument entries; leave
1285        // unset to signal account-wide (cross margin) balances.
1286        if let Some(instrument_id) = self.instrument_id {
1287            let instrument_builder = builder.init_instrument();
1288            instrument_id.to_capnp(instrument_builder);
1289        }
1290    }
1291}
1292
1293impl<'a> FromCapnp<'a> for MarginBalance {
1294    type Reader = types_capnp::margin_balance::Reader<'a>;
1295
1296    fn from_capnp(reader: Self::Reader) -> Result<Self, Box<dyn Error>> {
1297        let initial_reader = reader.get_initial()?;
1298        let initial = Money::from_capnp(initial_reader)?;
1299
1300        let maintenance_reader = reader.get_maintenance()?;
1301        let maintenance = Money::from_capnp(maintenance_reader)?;
1302
1303        let instrument_id = if reader.has_instrument() {
1304            let instrument_reader = reader.get_instrument()?;
1305            Some(InstrumentId::from_capnp(instrument_reader)?)
1306        } else {
1307            None
1308        };
1309
1310        Ok(Self::new(initial, maintenance, instrument_id))
1311    }
1312}
1313
1314/// Serializes an [`InstrumentId`] to Cap'n Proto bytes.
1315///
1316/// # Errors
1317///
1318/// Returns an error if Cap'n Proto serialization fails.
1319pub fn serialize_instrument_id(id: &InstrumentId) -> Result<Vec<u8>, Box<dyn Error>> {
1320    let mut message = capnp::message::Builder::new_default();
1321    let builder = message.init_root::<identifiers_capnp::instrument_id::Builder>();
1322    id.to_capnp(builder);
1323
1324    let mut bytes = Vec::new();
1325    capnp::serialize::write_message(&mut bytes, &message)?;
1326    Ok(bytes)
1327}
1328
1329/// Deserializes an [`InstrumentId`] from Cap'n Proto bytes.
1330///
1331/// # Errors
1332///
1333/// Returns an error if Cap'n Proto deserialization fails.
1334pub fn deserialize_instrument_id(bytes: &[u8]) -> Result<InstrumentId, Box<dyn Error>> {
1335    let reader =
1336        capnp::serialize::read_message(&mut &bytes[..], capnp::message::ReaderOptions::new())?;
1337    let root = reader.get_root::<identifiers_capnp::instrument_id::Reader>()?;
1338    InstrumentId::from_capnp(root)
1339}
1340
1341/// Serializes a [`Price`] to Cap'n Proto bytes.
1342///
1343/// # Errors
1344///
1345/// Returns an error if Cap'n Proto serialization fails.
1346pub fn serialize_price(price: &Price) -> Result<Vec<u8>, Box<dyn Error>> {
1347    let mut message = capnp::message::Builder::new_default();
1348    let builder = message.init_root::<types_capnp::price::Builder>();
1349    price.to_capnp(builder);
1350
1351    let mut bytes = Vec::new();
1352    capnp::serialize::write_message(&mut bytes, &message)?;
1353    Ok(bytes)
1354}
1355
1356/// Deserializes a [`Price`] from Cap'n Proto bytes.
1357///
1358/// # Errors
1359///
1360/// Returns an error if Cap'n Proto deserialization fails.
1361pub fn deserialize_price(bytes: &[u8]) -> Result<Price, Box<dyn Error>> {
1362    let reader =
1363        capnp::serialize::read_message(&mut &bytes[..], capnp::message::ReaderOptions::new())?;
1364    let root = reader.get_root::<types_capnp::price::Reader>()?;
1365    Price::from_capnp(root)
1366}
1367
1368/// Serializes a [`Quantity`] to Cap'n Proto bytes.
1369///
1370/// # Errors
1371///
1372/// Returns an error if Cap'n Proto serialization fails.
1373pub fn serialize_quantity(qty: &Quantity) -> Result<Vec<u8>, Box<dyn Error>> {
1374    let mut message = capnp::message::Builder::new_default();
1375    let builder = message.init_root::<types_capnp::quantity::Builder>();
1376    qty.to_capnp(builder);
1377
1378    let mut bytes = Vec::new();
1379    capnp::serialize::write_message(&mut bytes, &message)?;
1380    Ok(bytes)
1381}
1382
1383/// Deserializes a [`Quantity`] from Cap'n Proto bytes.
1384///
1385/// # Errors
1386///
1387/// Returns an error if Cap'n Proto deserialization fails.
1388pub fn deserialize_quantity(bytes: &[u8]) -> Result<Quantity, Box<dyn Error>> {
1389    let reader =
1390        capnp::serialize::read_message(&mut &bytes[..], capnp::message::ReaderOptions::new())?;
1391    let root = reader.get_root::<types_capnp::quantity::Reader>()?;
1392    Quantity::from_capnp(root)
1393}
1394
1395/// Serializes a [`Currency`] to Cap'n Proto bytes.
1396///
1397/// # Errors
1398///
1399/// Returns an error if Cap'n Proto serialization fails.
1400pub fn serialize_currency(currency: &Currency) -> Result<Vec<u8>, Box<dyn Error>> {
1401    let mut message = capnp::message::Builder::new_default();
1402    let builder = message.init_root::<types_capnp::currency::Builder>();
1403    currency.to_capnp(builder);
1404
1405    let mut bytes = Vec::new();
1406    capnp::serialize::write_message(&mut bytes, &message)?;
1407    Ok(bytes)
1408}
1409
1410/// Deserializes a [`Currency`] from Cap'n Proto bytes.
1411///
1412/// # Errors
1413///
1414/// Returns an error if Cap'n Proto deserialization fails.
1415pub fn deserialize_currency(bytes: &[u8]) -> Result<Currency, Box<dyn Error>> {
1416    let reader =
1417        capnp::serialize::read_message(&mut &bytes[..], capnp::message::ReaderOptions::new())?;
1418    let root = reader.get_root::<types_capnp::currency::Reader>()?;
1419    Currency::from_capnp(root)
1420}
1421
1422/// Serializes a [`Money`] to Cap'n Proto bytes.
1423///
1424/// # Errors
1425///
1426/// Returns an error if Cap'n Proto serialization fails.
1427pub fn serialize_money(money: &Money) -> Result<Vec<u8>, Box<dyn Error>> {
1428    let mut message = capnp::message::Builder::new_default();
1429    let builder = message.init_root::<types_capnp::money::Builder>();
1430    money.to_capnp(builder);
1431
1432    let mut bytes = Vec::new();
1433    capnp::serialize::write_message(&mut bytes, &message)?;
1434    Ok(bytes)
1435}
1436
1437/// Deserializes a [`Money`] from Cap'n Proto bytes.
1438///
1439/// # Errors
1440///
1441/// Returns an error if Cap'n Proto deserialization fails.
1442pub fn deserialize_money(bytes: &[u8]) -> Result<Money, Box<dyn Error>> {
1443    let reader =
1444        capnp::serialize::read_message(&mut &bytes[..], capnp::message::ReaderOptions::new())?;
1445    let root = reader.get_root::<types_capnp::money::Reader>()?;
1446    Money::from_capnp(root)
1447}
1448
1449/// Serializes an [`AccountBalance`] to Cap'n Proto bytes.
1450///
1451/// # Errors
1452///
1453/// Returns an error if Cap'n Proto serialization fails.
1454pub fn serialize_account_balance(balance: &AccountBalance) -> Result<Vec<u8>, Box<dyn Error>> {
1455    let mut message = capnp::message::Builder::new_default();
1456    let builder = message.init_root::<types_capnp::account_balance::Builder>();
1457    balance.to_capnp(builder);
1458
1459    let mut bytes = Vec::new();
1460    capnp::serialize::write_message(&mut bytes, &message)?;
1461    Ok(bytes)
1462}
1463
1464/// Deserializes an [`AccountBalance`] from Cap'n Proto bytes.
1465///
1466/// # Errors
1467///
1468/// Returns an error if Cap'n Proto deserialization fails.
1469pub fn deserialize_account_balance(bytes: &[u8]) -> Result<AccountBalance, Box<dyn Error>> {
1470    let reader =
1471        capnp::serialize::read_message(&mut &bytes[..], capnp::message::ReaderOptions::new())?;
1472    let root = reader.get_root::<types_capnp::account_balance::Reader>()?;
1473    AccountBalance::from_capnp(root)
1474}
1475
1476/// Serializes a [`MarginBalance`] to Cap'n Proto bytes.
1477///
1478/// # Errors
1479///
1480/// Returns an error if Cap'n Proto serialization fails.
1481pub fn serialize_margin_balance(balance: &MarginBalance) -> Result<Vec<u8>, Box<dyn Error>> {
1482    let mut message = capnp::message::Builder::new_default();
1483    let builder = message.init_root::<types_capnp::margin_balance::Builder>();
1484    balance.to_capnp(builder);
1485
1486    let mut bytes = Vec::new();
1487    capnp::serialize::write_message(&mut bytes, &message)?;
1488    Ok(bytes)
1489}
1490
1491/// Deserializes a [`MarginBalance`] from Cap'n Proto bytes.
1492///
1493/// # Errors
1494///
1495/// Returns an error if Cap'n Proto deserialization fails.
1496pub fn deserialize_margin_balance(bytes: &[u8]) -> Result<MarginBalance, Box<dyn Error>> {
1497    let reader =
1498        capnp::serialize::read_message(&mut &bytes[..], capnp::message::ReaderOptions::new())?;
1499    let root = reader.get_root::<types_capnp::margin_balance::Reader>()?;
1500    MarginBalance::from_capnp(root)
1501}
1502
1503impl<'a> ToCapnp<'a> for QuoteTick {
1504    type Builder = market_capnp::quote_tick::Builder<'a>;
1505
1506    fn to_capnp(&self, mut builder: Self::Builder) {
1507        let instrument_id_builder = builder.reborrow().init_instrument_id();
1508        self.instrument_id.to_capnp(instrument_id_builder);
1509
1510        let bid_price_builder = builder.reborrow().init_bid_price();
1511        self.bid_price.to_capnp(bid_price_builder);
1512
1513        let ask_price_builder = builder.reborrow().init_ask_price();
1514        self.ask_price.to_capnp(ask_price_builder);
1515
1516        let bid_size_builder = builder.reborrow().init_bid_size();
1517        self.bid_size.to_capnp(bid_size_builder);
1518
1519        let ask_size_builder = builder.reborrow().init_ask_size();
1520        self.ask_size.to_capnp(ask_size_builder);
1521
1522        let mut ts_event_builder = builder.reborrow().init_ts_event();
1523        ts_event_builder.set_value(*self.ts_event);
1524
1525        let mut ts_init_builder = builder.reborrow().init_ts_init();
1526        ts_init_builder.set_value(*self.ts_init);
1527    }
1528}
1529
1530impl<'a> FromCapnp<'a> for QuoteTick {
1531    type Reader = market_capnp::quote_tick::Reader<'a>;
1532
1533    fn from_capnp(reader: Self::Reader) -> Result<Self, Box<dyn Error>> {
1534        let instrument_id_reader = reader.get_instrument_id()?;
1535        let instrument_id = InstrumentId::from_capnp(instrument_id_reader)?;
1536
1537        let bid_price_reader = reader.get_bid_price()?;
1538        let bid_price = Price::from_capnp(bid_price_reader)?;
1539
1540        let ask_price_reader = reader.get_ask_price()?;
1541        let ask_price = Price::from_capnp(ask_price_reader)?;
1542
1543        let bid_size_reader = reader.get_bid_size()?;
1544        let bid_size = Quantity::from_capnp(bid_size_reader)?;
1545
1546        let ask_size_reader = reader.get_ask_size()?;
1547        let ask_size = Quantity::from_capnp(ask_size_reader)?;
1548
1549        let ts_event_reader = reader.get_ts_event()?;
1550        let ts_event = ts_event_reader.get_value();
1551
1552        let ts_init_reader = reader.get_ts_init()?;
1553        let ts_init = ts_init_reader.get_value();
1554
1555        Ok(Self {
1556            instrument_id,
1557            bid_price,
1558            ask_price,
1559            bid_size,
1560            ask_size,
1561            ts_event: ts_event.into(),
1562            ts_init: ts_init.into(),
1563        })
1564    }
1565}
1566
1567impl<'a> ToCapnp<'a> for TradeTick {
1568    type Builder = market_capnp::trade_tick::Builder<'a>;
1569
1570    fn to_capnp(&self, mut builder: Self::Builder) {
1571        let instrument_id_builder = builder.reborrow().init_instrument_id();
1572        self.instrument_id.to_capnp(instrument_id_builder);
1573
1574        let price_builder = builder.reborrow().init_price();
1575        self.price.to_capnp(price_builder);
1576
1577        let size_builder = builder.reborrow().init_size();
1578        self.size.to_capnp(size_builder);
1579
1580        builder.set_aggressor_side(aggressor_side_to_capnp(self.aggressor_side));
1581
1582        let trade_id_builder = builder.reborrow().init_trade_id();
1583        self.trade_id.to_capnp(trade_id_builder);
1584
1585        let mut ts_event_builder = builder.reborrow().init_ts_event();
1586        ts_event_builder.set_value(*self.ts_event);
1587
1588        let mut ts_init_builder = builder.reborrow().init_ts_init();
1589        ts_init_builder.set_value(*self.ts_init);
1590    }
1591}
1592
1593impl<'a> FromCapnp<'a> for TradeTick {
1594    type Reader = market_capnp::trade_tick::Reader<'a>;
1595
1596    fn from_capnp(reader: Self::Reader) -> Result<Self, Box<dyn Error>> {
1597        let instrument_id_reader = reader.get_instrument_id()?;
1598        let instrument_id = InstrumentId::from_capnp(instrument_id_reader)?;
1599
1600        let price_reader = reader.get_price()?;
1601        let price = Price::from_capnp(price_reader)?;
1602
1603        let size_reader = reader.get_size()?;
1604        let size = Quantity::from_capnp(size_reader)?;
1605
1606        let aggressor_side = aggressor_side_from_capnp(reader.get_aggressor_side()?);
1607
1608        let trade_id_reader = reader.get_trade_id()?;
1609        let trade_id = TradeId::from_capnp(trade_id_reader)?;
1610
1611        let ts_event_reader = reader.get_ts_event()?;
1612        let ts_event = ts_event_reader.get_value();
1613
1614        let ts_init_reader = reader.get_ts_init()?;
1615        let ts_init = ts_init_reader.get_value();
1616
1617        Ok(Self {
1618            instrument_id,
1619            price,
1620            size,
1621            aggressor_side,
1622            trade_id,
1623            ts_event: ts_event.into(),
1624            ts_init: ts_init.into(),
1625        })
1626    }
1627}
1628
1629impl<'a> ToCapnp<'a> for MarkPriceUpdate {
1630    type Builder = market_capnp::mark_price_update::Builder<'a>;
1631
1632    fn to_capnp(&self, mut builder: Self::Builder) {
1633        let instrument_id_builder = builder.reborrow().init_instrument_id();
1634        self.instrument_id.to_capnp(instrument_id_builder);
1635
1636        let mark_price_builder = builder.reborrow().init_mark_price();
1637        self.value.to_capnp(mark_price_builder);
1638
1639        let mut ts_event_builder = builder.reborrow().init_ts_event();
1640        ts_event_builder.set_value(*self.ts_event);
1641
1642        let mut ts_init_builder = builder.reborrow().init_ts_init();
1643        ts_init_builder.set_value(*self.ts_init);
1644    }
1645}
1646
1647impl<'a> FromCapnp<'a> for MarkPriceUpdate {
1648    type Reader = market_capnp::mark_price_update::Reader<'a>;
1649
1650    fn from_capnp(reader: Self::Reader) -> Result<Self, Box<dyn Error>> {
1651        let instrument_id_reader = reader.get_instrument_id()?;
1652        let instrument_id = InstrumentId::from_capnp(instrument_id_reader)?;
1653
1654        let mark_price_reader = reader.get_mark_price()?;
1655        let value = Price::from_capnp(mark_price_reader)?;
1656
1657        let ts_event_reader = reader.get_ts_event()?;
1658        let ts_event = ts_event_reader.get_value();
1659
1660        let ts_init_reader = reader.get_ts_init()?;
1661        let ts_init = ts_init_reader.get_value();
1662
1663        Ok(Self {
1664            instrument_id,
1665            value,
1666            ts_event: ts_event.into(),
1667            ts_init: ts_init.into(),
1668        })
1669    }
1670}
1671
1672impl<'a> ToCapnp<'a> for IndexPriceUpdate {
1673    type Builder = market_capnp::index_price_update::Builder<'a>;
1674
1675    fn to_capnp(&self, mut builder: Self::Builder) {
1676        let instrument_id_builder = builder.reborrow().init_instrument_id();
1677        self.instrument_id.to_capnp(instrument_id_builder);
1678
1679        let index_price_builder = builder.reborrow().init_index_price();
1680        self.value.to_capnp(index_price_builder);
1681
1682        let mut ts_event_builder = builder.reborrow().init_ts_event();
1683        ts_event_builder.set_value(*self.ts_event);
1684
1685        let mut ts_init_builder = builder.reborrow().init_ts_init();
1686        ts_init_builder.set_value(*self.ts_init);
1687    }
1688}
1689
1690impl<'a> FromCapnp<'a> for IndexPriceUpdate {
1691    type Reader = market_capnp::index_price_update::Reader<'a>;
1692
1693    fn from_capnp(reader: Self::Reader) -> Result<Self, Box<dyn Error>> {
1694        let instrument_id_reader = reader.get_instrument_id()?;
1695        let instrument_id = InstrumentId::from_capnp(instrument_id_reader)?;
1696
1697        let index_price_reader = reader.get_index_price()?;
1698        let value = Price::from_capnp(index_price_reader)?;
1699
1700        let ts_event_reader = reader.get_ts_event()?;
1701        let ts_event = ts_event_reader.get_value();
1702
1703        let ts_init_reader = reader.get_ts_init()?;
1704        let ts_init = ts_init_reader.get_value();
1705
1706        Ok(Self {
1707            instrument_id,
1708            value,
1709            ts_event: ts_event.into(),
1710            ts_init: ts_init.into(),
1711        })
1712    }
1713}
1714
1715impl<'a> ToCapnp<'a> for FundingRateUpdate {
1716    type Builder = market_capnp::funding_rate_update::Builder<'a>;
1717
1718    fn to_capnp(&self, mut builder: Self::Builder) {
1719        let instrument_id_builder = builder.reborrow().init_instrument_id();
1720        self.instrument_id.to_capnp(instrument_id_builder);
1721
1722        let rate_builder = builder.reborrow().init_rate();
1723        self.rate.to_capnp(rate_builder);
1724
1725        if let Some(interval) = self.interval {
1726            builder.reborrow().set_interval(interval);
1727            builder.reborrow().set_has_interval(true);
1728        }
1729
1730        if let Some(next_funding_ns) = self.next_funding_ns {
1731            let mut next_funding_time_builder = builder.reborrow().init_next_funding_time();
1732            next_funding_time_builder.set_value(*next_funding_ns);
1733        }
1734
1735        let mut ts_event_builder = builder.reborrow().init_ts_event();
1736        ts_event_builder.set_value(*self.ts_event);
1737
1738        let mut ts_init_builder = builder.reborrow().init_ts_init();
1739        ts_init_builder.set_value(*self.ts_init);
1740    }
1741}
1742
1743impl<'a> FromCapnp<'a> for FundingRateUpdate {
1744    type Reader = market_capnp::funding_rate_update::Reader<'a>;
1745
1746    fn from_capnp(reader: Self::Reader) -> Result<Self, Box<dyn Error>> {
1747        let instrument_id_reader = reader.get_instrument_id()?;
1748        let instrument_id = InstrumentId::from_capnp(instrument_id_reader)?;
1749
1750        let rate_reader = reader.get_rate()?;
1751        let rate = Decimal::from_capnp(rate_reader)?;
1752
1753        let interval = if reader.get_has_interval() {
1754            Some(reader.get_interval())
1755        } else {
1756            None
1757        };
1758
1759        let next_funding_ns = if reader.has_next_funding_time() {
1760            let next_funding_time_reader = reader.get_next_funding_time()?;
1761            Some(next_funding_time_reader.get_value().into())
1762        } else {
1763            None
1764        };
1765
1766        let ts_event_reader = reader.get_ts_event()?;
1767        let ts_event = ts_event_reader.get_value();
1768
1769        let ts_init_reader = reader.get_ts_init()?;
1770        let ts_init = ts_init_reader.get_value();
1771
1772        Ok(Self {
1773            instrument_id,
1774            rate,
1775            interval,
1776            next_funding_ns,
1777            ts_event: ts_event.into(),
1778            ts_init: ts_init.into(),
1779        })
1780    }
1781}
1782
1783impl<'a> ToCapnp<'a> for InstrumentClose {
1784    type Builder = market_capnp::instrument_close::Builder<'a>;
1785
1786    fn to_capnp(&self, mut builder: Self::Builder) {
1787        let instrument_id_builder = builder.reborrow().init_instrument_id();
1788        self.instrument_id.to_capnp(instrument_id_builder);
1789
1790        let close_price_builder = builder.reborrow().init_close_price();
1791        self.close_price.to_capnp(close_price_builder);
1792
1793        builder.set_close_type(instrument_close_type_to_capnp(self.close_type));
1794
1795        let mut ts_event_builder = builder.reborrow().init_ts_event();
1796        ts_event_builder.set_value(*self.ts_event);
1797
1798        let mut ts_init_builder = builder.reborrow().init_ts_init();
1799        ts_init_builder.set_value(*self.ts_init);
1800    }
1801}
1802
1803impl<'a> FromCapnp<'a> for InstrumentClose {
1804    type Reader = market_capnp::instrument_close::Reader<'a>;
1805
1806    fn from_capnp(reader: Self::Reader) -> Result<Self, Box<dyn Error>> {
1807        let instrument_id_reader = reader.get_instrument_id()?;
1808        let instrument_id = InstrumentId::from_capnp(instrument_id_reader)?;
1809
1810        let close_price_reader = reader.get_close_price()?;
1811        let close_price = Price::from_capnp(close_price_reader)?;
1812
1813        let close_type = instrument_close_type_from_capnp(reader.get_close_type()?);
1814
1815        let ts_event_reader = reader.get_ts_event()?;
1816        let ts_event = ts_event_reader.get_value();
1817
1818        let ts_init_reader = reader.get_ts_init()?;
1819        let ts_init = ts_init_reader.get_value();
1820
1821        Ok(Self {
1822            instrument_id,
1823            close_price,
1824            close_type,
1825            ts_event: ts_event.into(),
1826            ts_init: ts_init.into(),
1827        })
1828    }
1829}
1830
1831impl<'a> ToCapnp<'a> for InstrumentStatus {
1832    type Builder = market_capnp::instrument_status::Builder<'a>;
1833
1834    fn to_capnp(&self, mut builder: Self::Builder) {
1835        let instrument_id_builder = builder.reborrow().init_instrument_id();
1836        self.instrument_id.to_capnp(instrument_id_builder);
1837
1838        builder.set_action(market_status_action_to_capnp(self.action));
1839
1840        if let Some(reason) = self.reason {
1841            builder.reborrow().set_reason(reason.as_str());
1842        }
1843
1844        if let Some(trading_event) = self.trading_event {
1845            builder.reborrow().set_trading_event(trading_event.as_str());
1846        }
1847
1848        builder.set_is_trading(optional_bool_to_capnp(self.is_trading));
1849        builder.set_is_quoting(optional_bool_to_capnp(self.is_quoting));
1850        builder.set_is_short_sell_restricted(optional_bool_to_capnp(self.is_short_sell_restricted));
1851
1852        let mut ts_event_builder = builder.reborrow().init_ts_event();
1853        ts_event_builder.set_value(*self.ts_event);
1854
1855        let mut ts_init_builder = builder.reborrow().init_ts_init();
1856        ts_init_builder.set_value(*self.ts_init);
1857    }
1858}
1859
1860impl<'a> FromCapnp<'a> for InstrumentStatus {
1861    type Reader = market_capnp::instrument_status::Reader<'a>;
1862
1863    fn from_capnp(reader: Self::Reader) -> Result<Self, Box<dyn Error>> {
1864        let instrument_id_reader = reader.get_instrument_id()?;
1865        let instrument_id = InstrumentId::from_capnp(instrument_id_reader)?;
1866
1867        let action = market_status_action_from_capnp(reader.get_action()?);
1868
1869        let reason = if reader.has_reason() {
1870            Some(Ustr::from(reader.get_reason()?.to_str()?))
1871        } else {
1872            None
1873        };
1874
1875        let trading_event = if reader.has_trading_event() {
1876            Some(Ustr::from(reader.get_trading_event()?.to_str()?))
1877        } else {
1878            None
1879        };
1880
1881        let is_trading = optional_bool_from_capnp(reader.get_is_trading()?);
1882        let is_quoting = optional_bool_from_capnp(reader.get_is_quoting()?);
1883        let is_short_sell_restricted =
1884            optional_bool_from_capnp(reader.get_is_short_sell_restricted()?);
1885
1886        let ts_event_reader = reader.get_ts_event()?;
1887        let ts_event = ts_event_reader.get_value();
1888
1889        let ts_init_reader = reader.get_ts_init()?;
1890        let ts_init = ts_init_reader.get_value();
1891
1892        Ok(Self {
1893            instrument_id,
1894            action,
1895            ts_event: ts_event.into(),
1896            ts_init: ts_init.into(),
1897            reason,
1898            trading_event,
1899            is_trading,
1900            is_quoting,
1901            is_short_sell_restricted,
1902        })
1903    }
1904}
1905
1906impl<'a> ToCapnp<'a> for BarSpecification {
1907    type Builder = market_capnp::bar_spec::Builder<'a>;
1908
1909    fn to_capnp(&self, mut builder: Self::Builder) {
1910        builder.set_step(self.step.get() as u32);
1911        builder.set_aggregation(bar_aggregation_to_capnp(self.aggregation));
1912        builder.set_price_type(price_type_to_capnp(self.price_type));
1913    }
1914}
1915
1916impl<'a> FromCapnp<'a> for BarSpecification {
1917    type Reader = market_capnp::bar_spec::Reader<'a>;
1918
1919    fn from_capnp(reader: Self::Reader) -> Result<Self, Box<dyn Error>> {
1920        use std::num::NonZero;
1921
1922        let step = reader.get_step();
1923        let step = NonZero::new(step as usize).ok_or("BarSpecification step must be non-zero")?;
1924
1925        let aggregation = bar_aggregation_from_capnp(reader.get_aggregation()?);
1926        let price_type = price_type_from_capnp(reader.get_price_type()?);
1927
1928        Ok(Self {
1929            step,
1930            aggregation,
1931            price_type,
1932        })
1933    }
1934}
1935
1936impl<'a> ToCapnp<'a> for BarType {
1937    type Builder = market_capnp::bar_type::Builder<'a>;
1938
1939    fn to_capnp(&self, mut builder: Self::Builder) {
1940        let instrument_id_builder = builder.reborrow().init_instrument_id();
1941        self.instrument_id().to_capnp(instrument_id_builder);
1942
1943        let spec_builder = builder.reborrow().init_spec();
1944        self.spec().to_capnp(spec_builder);
1945
1946        builder.set_aggregation_source(aggregation_source_to_capnp(self.aggregation_source()));
1947    }
1948}
1949
1950impl<'a> FromCapnp<'a> for BarType {
1951    type Reader = market_capnp::bar_type::Reader<'a>;
1952
1953    fn from_capnp(reader: Self::Reader) -> Result<Self, Box<dyn Error>> {
1954        let instrument_id_reader = reader.get_instrument_id()?;
1955        let instrument_id = InstrumentId::from_capnp(instrument_id_reader)?;
1956
1957        let spec_reader = reader.get_spec()?;
1958        let spec = BarSpecification::from_capnp(spec_reader)?;
1959
1960        let aggregation_source = aggregation_source_from_capnp(reader.get_aggregation_source()?);
1961
1962        Ok(Self::new(instrument_id, spec, aggregation_source))
1963    }
1964}
1965
1966impl<'a> ToCapnp<'a> for Bar {
1967    type Builder = market_capnp::bar::Builder<'a>;
1968
1969    fn to_capnp(&self, mut builder: Self::Builder) {
1970        let bar_type_builder = builder.reborrow().init_bar_type();
1971        self.bar_type.to_capnp(bar_type_builder);
1972
1973        let open_builder = builder.reborrow().init_open();
1974        self.open.to_capnp(open_builder);
1975
1976        let high_builder = builder.reborrow().init_high();
1977        self.high.to_capnp(high_builder);
1978
1979        let low_builder = builder.reborrow().init_low();
1980        self.low.to_capnp(low_builder);
1981
1982        let close_builder = builder.reborrow().init_close();
1983        self.close.to_capnp(close_builder);
1984
1985        let volume_builder = builder.reborrow().init_volume();
1986        self.volume.to_capnp(volume_builder);
1987
1988        let mut ts_event_builder = builder.reborrow().init_ts_event();
1989        ts_event_builder.set_value(*self.ts_event);
1990
1991        let mut ts_init_builder = builder.reborrow().init_ts_init();
1992        ts_init_builder.set_value(*self.ts_init);
1993    }
1994}
1995
1996impl<'a> FromCapnp<'a> for Bar {
1997    type Reader = market_capnp::bar::Reader<'a>;
1998
1999    fn from_capnp(reader: Self::Reader) -> Result<Self, Box<dyn Error>> {
2000        let bar_type_reader = reader.get_bar_type()?;
2001        let bar_type = BarType::from_capnp(bar_type_reader)?;
2002
2003        let open_reader = reader.get_open()?;
2004        let open = Price::from_capnp(open_reader)?;
2005
2006        let high_reader = reader.get_high()?;
2007        let high = Price::from_capnp(high_reader)?;
2008
2009        let low_reader = reader.get_low()?;
2010        let low = Price::from_capnp(low_reader)?;
2011
2012        let close_reader = reader.get_close()?;
2013        let close = Price::from_capnp(close_reader)?;
2014
2015        let volume_reader = reader.get_volume()?;
2016        let volume = Quantity::from_capnp(volume_reader)?;
2017
2018        let ts_event_reader = reader.get_ts_event()?;
2019        let ts_event = ts_event_reader.get_value();
2020
2021        let ts_init_reader = reader.get_ts_init()?;
2022        let ts_init = ts_init_reader.get_value();
2023
2024        Ok(Self {
2025            bar_type,
2026            open,
2027            high,
2028            low,
2029            close,
2030            volume,
2031            ts_event: ts_event.into(),
2032            ts_init: ts_init.into(),
2033        })
2034    }
2035}
2036
2037impl<'a> ToCapnp<'a> for BookOrder {
2038    type Builder = market_capnp::book_order::Builder<'a>;
2039
2040    fn to_capnp(&self, mut builder: Self::Builder) {
2041        let price_builder = builder.reborrow().init_price();
2042        self.price.to_capnp(price_builder);
2043
2044        let size_builder = builder.reborrow().init_size();
2045        self.size.to_capnp(size_builder);
2046
2047        builder.set_side(order_side_to_capnp(self.side));
2048        builder.set_order_id(self.order_id);
2049    }
2050}
2051
2052impl<'a> FromCapnp<'a> for BookOrder {
2053    type Reader = market_capnp::book_order::Reader<'a>;
2054
2055    fn from_capnp(reader: Self::Reader) -> Result<Self, Box<dyn Error>> {
2056        let price_reader = reader.get_price()?;
2057        let price = Price::from_capnp(price_reader)?;
2058
2059        let size_reader = reader.get_size()?;
2060        let size = Quantity::from_capnp(size_reader)?;
2061
2062        let side = order_side_from_capnp(reader.get_side()?);
2063        let order_id = reader.get_order_id();
2064
2065        Ok(Self {
2066            side,
2067            price,
2068            size,
2069            order_id,
2070        })
2071    }
2072}
2073
2074impl<'a> ToCapnp<'a> for OrderBookDelta {
2075    type Builder = market_capnp::order_book_delta::Builder<'a>;
2076
2077    fn to_capnp(&self, mut builder: Self::Builder) {
2078        let instrument_id_builder = builder.reborrow().init_instrument_id();
2079        self.instrument_id.to_capnp(instrument_id_builder);
2080
2081        builder.set_action(book_action_to_capnp(self.action));
2082
2083        let order_builder = builder.reborrow().init_order();
2084        self.order.to_capnp(order_builder);
2085
2086        builder.set_flags(self.flags);
2087        builder.set_sequence(self.sequence);
2088
2089        let mut ts_event_builder = builder.reborrow().init_ts_event();
2090        ts_event_builder.set_value(*self.ts_event);
2091
2092        let mut ts_init_builder = builder.reborrow().init_ts_init();
2093        ts_init_builder.set_value(*self.ts_init);
2094    }
2095}
2096
2097impl<'a> FromCapnp<'a> for OrderBookDelta {
2098    type Reader = market_capnp::order_book_delta::Reader<'a>;
2099
2100    fn from_capnp(reader: Self::Reader) -> Result<Self, Box<dyn Error>> {
2101        let instrument_id_reader = reader.get_instrument_id()?;
2102        let instrument_id = InstrumentId::from_capnp(instrument_id_reader)?;
2103
2104        let action = book_action_from_capnp(reader.get_action()?);
2105
2106        let order_reader = reader.get_order()?;
2107        let order = BookOrder::from_capnp(order_reader)?;
2108
2109        let flags = reader.get_flags();
2110        let sequence = reader.get_sequence();
2111
2112        let ts_event_reader = reader.get_ts_event()?;
2113        let ts_event = ts_event_reader.get_value();
2114
2115        let ts_init_reader = reader.get_ts_init()?;
2116        let ts_init = ts_init_reader.get_value();
2117
2118        Ok(Self {
2119            instrument_id,
2120            action,
2121            order,
2122            flags,
2123            sequence,
2124            ts_event: ts_event.into(),
2125            ts_init: ts_init.into(),
2126        })
2127    }
2128}
2129
2130impl<'a> ToCapnp<'a> for OrderBookDeltas {
2131    type Builder = market_capnp::order_book_deltas::Builder<'a>;
2132
2133    fn to_capnp(&self, mut builder: Self::Builder) {
2134        let instrument_id_builder = builder.reborrow().init_instrument_id();
2135        self.instrument_id.to_capnp(instrument_id_builder);
2136
2137        let mut deltas_builder = builder.reborrow().init_deltas(self.deltas.len() as u32);
2138        for (i, delta) in self.deltas.iter().enumerate() {
2139            let entry_builder = deltas_builder.reborrow().get(i as u32);
2140            delta.to_capnp(entry_builder);
2141        }
2142
2143        builder.set_flags(self.flags);
2144        builder.set_sequence(self.sequence);
2145
2146        let mut ts_event_builder = builder.reborrow().init_ts_event();
2147        ts_event_builder.set_value(*self.ts_event);
2148
2149        let mut ts_init_builder = builder.reborrow().init_ts_init();
2150        ts_init_builder.set_value(*self.ts_init);
2151    }
2152}
2153
2154impl<'a> FromCapnp<'a> for OrderBookDeltas {
2155    type Reader = market_capnp::order_book_deltas::Reader<'a>;
2156
2157    fn from_capnp(reader: Self::Reader) -> Result<Self, Box<dyn Error>> {
2158        let instrument_id_reader = reader.get_instrument_id()?;
2159        let instrument_id = InstrumentId::from_capnp(instrument_id_reader)?;
2160
2161        let deltas_reader = reader.get_deltas()?;
2162        let mut deltas = Vec::with_capacity(deltas_reader.len() as usize);
2163        for delta_reader in deltas_reader {
2164            let delta = OrderBookDelta::from_capnp(delta_reader)?;
2165            deltas.push(delta);
2166        }
2167
2168        let flags = reader.get_flags();
2169        let sequence = reader.get_sequence();
2170
2171        let ts_event_reader = reader.get_ts_event()?;
2172        let ts_event = ts_event_reader.get_value();
2173
2174        let ts_init_reader = reader.get_ts_init()?;
2175        let ts_init = ts_init_reader.get_value();
2176
2177        Ok(Self {
2178            instrument_id,
2179            deltas,
2180            flags,
2181            sequence,
2182            ts_event: ts_event.into(),
2183            ts_init: ts_init.into(),
2184        })
2185    }
2186}
2187
2188impl<'a> ToCapnp<'a> for OrderBookDepth10 {
2189    type Builder = market_capnp::order_book_depth10::Builder<'a>;
2190
2191    fn to_capnp(&self, mut builder: Self::Builder) {
2192        let instrument_id_builder = builder.reborrow().init_instrument_id();
2193        self.instrument_id.to_capnp(instrument_id_builder);
2194
2195        // Convert bids (BookOrder array to BookLevel list)
2196        let mut bids_builder = builder.reborrow().init_bids(self.bids.len() as u32);
2197        for (i, bid) in self.bids.iter().enumerate() {
2198            let mut level_builder = bids_builder.reborrow().get(i as u32);
2199            let price_builder = level_builder.reborrow().init_price();
2200            bid.price.to_capnp(price_builder);
2201            let size_builder = level_builder.init_size();
2202            bid.size.to_capnp(size_builder);
2203        }
2204
2205        // Convert asks (BookOrder array to BookLevel list)
2206        let mut asks_builder = builder.reborrow().init_asks(self.asks.len() as u32);
2207        for (i, ask) in self.asks.iter().enumerate() {
2208            let mut level_builder = asks_builder.reborrow().get(i as u32);
2209            let price_builder = level_builder.reborrow().init_price();
2210            ask.price.to_capnp(price_builder);
2211            let size_builder = level_builder.init_size();
2212            ask.size.to_capnp(size_builder);
2213        }
2214
2215        // Convert counts
2216        let mut bid_counts_builder = builder
2217            .reborrow()
2218            .init_bid_counts(self.bid_counts.len() as u32);
2219        for (i, &count) in self.bid_counts.iter().enumerate() {
2220            bid_counts_builder.set(i as u32, count);
2221        }
2222
2223        let mut ask_counts_builder = builder
2224            .reborrow()
2225            .init_ask_counts(self.ask_counts.len() as u32);
2226        for (i, &count) in self.ask_counts.iter().enumerate() {
2227            ask_counts_builder.set(i as u32, count);
2228        }
2229
2230        builder.set_flags(self.flags);
2231        builder.set_sequence(self.sequence);
2232
2233        let mut ts_event_builder = builder.reborrow().init_ts_event();
2234        ts_event_builder.set_value(*self.ts_event);
2235
2236        let mut ts_init_builder = builder.reborrow().init_ts_init();
2237        ts_init_builder.set_value(*self.ts_init);
2238    }
2239}
2240
2241impl<'a> FromCapnp<'a> for OrderBookDepth10 {
2242    type Reader = market_capnp::order_book_depth10::Reader<'a>;
2243
2244    fn from_capnp(reader: Self::Reader) -> Result<Self, Box<dyn Error>> {
2245        use nautilus_model::data::order::NULL_ORDER;
2246
2247        let instrument_id_reader = reader.get_instrument_id()?;
2248        let instrument_id = InstrumentId::from_capnp(instrument_id_reader)?;
2249
2250        // Convert bids (BookLevel list to BookOrder array)
2251        let bids_reader = reader.get_bids()?;
2252        let mut bids = [NULL_ORDER; 10];
2253
2254        for (i, level_reader) in bids_reader.iter().enumerate().take(10) {
2255            let price_reader = level_reader.get_price()?;
2256            let price = Price::from_capnp(price_reader)?;
2257
2258            let size_reader = level_reader.get_size()?;
2259            let size = Quantity::from_capnp(size_reader)?;
2260
2261            bids[i] = BookOrder::new(OrderSide::Buy, price, size, 0);
2262        }
2263
2264        // Convert asks (BookLevel list to BookOrder array)
2265        let asks_reader = reader.get_asks()?;
2266        let mut asks = [NULL_ORDER; 10];
2267
2268        for (i, level_reader) in asks_reader.iter().enumerate().take(10) {
2269            let price_reader = level_reader.get_price()?;
2270            let price = Price::from_capnp(price_reader)?;
2271
2272            let size_reader = level_reader.get_size()?;
2273            let size = Quantity::from_capnp(size_reader)?;
2274
2275            asks[i] = BookOrder::new(OrderSide::Sell, price, size, 0);
2276        }
2277
2278        // Convert counts
2279        let bid_counts_reader = reader.get_bid_counts()?;
2280        let mut bid_counts = [0u32; 10];
2281        for (i, count) in bid_counts_reader.iter().enumerate().take(10) {
2282            bid_counts[i] = count;
2283        }
2284
2285        let ask_counts_reader = reader.get_ask_counts()?;
2286        let mut ask_counts = [0u32; 10];
2287        for (i, count) in ask_counts_reader.iter().enumerate().take(10) {
2288            ask_counts[i] = count;
2289        }
2290
2291        let flags = reader.get_flags();
2292        let sequence = reader.get_sequence();
2293
2294        let ts_event_reader = reader.get_ts_event()?;
2295        let ts_event = ts_event_reader.get_value();
2296
2297        let ts_init_reader = reader.get_ts_init()?;
2298        let ts_init = ts_init_reader.get_value();
2299
2300        Ok(Self {
2301            instrument_id,
2302            bids,
2303            asks,
2304            bid_counts,
2305            ask_counts,
2306            flags,
2307            sequence,
2308            ts_event: ts_event.into(),
2309            ts_init: ts_init.into(),
2310        })
2311    }
2312}
2313
2314impl<'a> ToCapnp<'a> for OrderDenied {
2315    type Builder = order_capnp::order_denied::Builder<'a>;
2316
2317    fn to_capnp(&self, mut builder: Self::Builder) {
2318        let trader_id_builder = builder.reborrow().init_trader_id();
2319        self.trader_id.to_capnp(trader_id_builder);
2320
2321        let strategy_id_builder = builder.reborrow().init_strategy_id();
2322        self.strategy_id.to_capnp(strategy_id_builder);
2323
2324        let instrument_id_builder = builder.reborrow().init_instrument_id();
2325        self.instrument_id.to_capnp(instrument_id_builder);
2326
2327        let client_order_id_builder = builder.reborrow().init_client_order_id();
2328        self.client_order_id.to_capnp(client_order_id_builder);
2329
2330        builder.set_reason(self.reason.as_str());
2331
2332        let event_id_builder = builder.reborrow().init_event_id();
2333        self.event_id.to_capnp(event_id_builder);
2334
2335        let mut ts_init_builder = builder.reborrow().init_ts_init();
2336        ts_init_builder.set_value(*self.ts_init);
2337    }
2338}
2339
2340impl<'a> FromCapnp<'a> for OrderDenied {
2341    type Reader = order_capnp::order_denied::Reader<'a>;
2342
2343    fn from_capnp(reader: Self::Reader) -> Result<Self, Box<dyn Error>> {
2344        let trader_id_reader = reader.get_trader_id()?;
2345        let trader_id = TraderId::from_capnp(trader_id_reader)?;
2346
2347        let strategy_id_reader = reader.get_strategy_id()?;
2348        let strategy_id = StrategyId::from_capnp(strategy_id_reader)?;
2349
2350        let instrument_id_reader = reader.get_instrument_id()?;
2351        let instrument_id = InstrumentId::from_capnp(instrument_id_reader)?;
2352
2353        let client_order_id_reader = reader.get_client_order_id()?;
2354        let client_order_id = ClientOrderId::from_capnp(client_order_id_reader)?;
2355
2356        let reason = Ustr::from(reader.get_reason()?.to_str()?);
2357
2358        let event_id_reader = reader.get_event_id()?;
2359        let event_id = nautilus_core::UUID4::from_capnp(event_id_reader)?;
2360
2361        let ts_init_reader = reader.get_ts_init()?;
2362        let ts_init = ts_init_reader.get_value();
2363
2364        Ok(Self {
2365            trader_id,
2366            strategy_id,
2367            instrument_id,
2368            client_order_id,
2369            reason,
2370            event_id,
2371            ts_event: ts_init.into(), // System event - ts_event = ts_init
2372            ts_init: ts_init.into(),
2373        })
2374    }
2375}
2376
2377impl<'a> ToCapnp<'a> for OrderEmulated {
2378    type Builder = order_capnp::order_emulated::Builder<'a>;
2379
2380    fn to_capnp(&self, mut builder: Self::Builder) {
2381        let trader_id_builder = builder.reborrow().init_trader_id();
2382        self.trader_id.to_capnp(trader_id_builder);
2383
2384        let strategy_id_builder = builder.reborrow().init_strategy_id();
2385        self.strategy_id.to_capnp(strategy_id_builder);
2386
2387        let instrument_id_builder = builder.reborrow().init_instrument_id();
2388        self.instrument_id.to_capnp(instrument_id_builder);
2389
2390        let client_order_id_builder = builder.reborrow().init_client_order_id();
2391        self.client_order_id.to_capnp(client_order_id_builder);
2392
2393        let event_id_builder = builder.reborrow().init_event_id();
2394        self.event_id.to_capnp(event_id_builder);
2395
2396        let mut ts_init_builder = builder.reborrow().init_ts_init();
2397        ts_init_builder.set_value(*self.ts_init);
2398    }
2399}
2400
2401impl<'a> FromCapnp<'a> for OrderEmulated {
2402    type Reader = order_capnp::order_emulated::Reader<'a>;
2403
2404    fn from_capnp(reader: Self::Reader) -> Result<Self, Box<dyn Error>> {
2405        let trader_id_reader = reader.get_trader_id()?;
2406        let trader_id = TraderId::from_capnp(trader_id_reader)?;
2407
2408        let strategy_id_reader = reader.get_strategy_id()?;
2409        let strategy_id = StrategyId::from_capnp(strategy_id_reader)?;
2410
2411        let instrument_id_reader = reader.get_instrument_id()?;
2412        let instrument_id = InstrumentId::from_capnp(instrument_id_reader)?;
2413
2414        let client_order_id_reader = reader.get_client_order_id()?;
2415        let client_order_id = ClientOrderId::from_capnp(client_order_id_reader)?;
2416
2417        let event_id_reader = reader.get_event_id()?;
2418        let event_id = nautilus_core::UUID4::from_capnp(event_id_reader)?;
2419
2420        let ts_init_reader = reader.get_ts_init()?;
2421        let ts_init = ts_init_reader.get_value();
2422
2423        Ok(Self {
2424            trader_id,
2425            strategy_id,
2426            instrument_id,
2427            client_order_id,
2428            event_id,
2429            ts_event: ts_init.into(), // System event - ts_event = ts_init
2430            ts_init: ts_init.into(),
2431        })
2432    }
2433}
2434
2435impl<'a> ToCapnp<'a> for OrderReleased {
2436    type Builder = order_capnp::order_released::Builder<'a>;
2437
2438    fn to_capnp(&self, mut builder: Self::Builder) {
2439        let trader_id_builder = builder.reborrow().init_trader_id();
2440        self.trader_id.to_capnp(trader_id_builder);
2441
2442        let strategy_id_builder = builder.reborrow().init_strategy_id();
2443        self.strategy_id.to_capnp(strategy_id_builder);
2444
2445        let instrument_id_builder = builder.reborrow().init_instrument_id();
2446        self.instrument_id.to_capnp(instrument_id_builder);
2447
2448        let client_order_id_builder = builder.reborrow().init_client_order_id();
2449        self.client_order_id.to_capnp(client_order_id_builder);
2450
2451        let released_price_builder = builder.reborrow().init_released_price();
2452        self.released_price.to_capnp(released_price_builder);
2453
2454        let event_id_builder = builder.reborrow().init_event_id();
2455        self.event_id.to_capnp(event_id_builder);
2456
2457        let mut ts_init_builder = builder.reborrow().init_ts_init();
2458        ts_init_builder.set_value(*self.ts_init);
2459    }
2460}
2461
2462impl<'a> FromCapnp<'a> for OrderReleased {
2463    type Reader = order_capnp::order_released::Reader<'a>;
2464
2465    fn from_capnp(reader: Self::Reader) -> Result<Self, Box<dyn Error>> {
2466        let trader_id_reader = reader.get_trader_id()?;
2467        let trader_id = TraderId::from_capnp(trader_id_reader)?;
2468
2469        let strategy_id_reader = reader.get_strategy_id()?;
2470        let strategy_id = StrategyId::from_capnp(strategy_id_reader)?;
2471
2472        let instrument_id_reader = reader.get_instrument_id()?;
2473        let instrument_id = InstrumentId::from_capnp(instrument_id_reader)?;
2474
2475        let client_order_id_reader = reader.get_client_order_id()?;
2476        let client_order_id = ClientOrderId::from_capnp(client_order_id_reader)?;
2477
2478        let released_price_reader = reader.get_released_price()?;
2479        let released_price = Price::from_capnp(released_price_reader)?;
2480
2481        let event_id_reader = reader.get_event_id()?;
2482        let event_id = nautilus_core::UUID4::from_capnp(event_id_reader)?;
2483
2484        let ts_init_reader = reader.get_ts_init()?;
2485        let ts_init = ts_init_reader.get_value();
2486
2487        Ok(Self {
2488            trader_id,
2489            strategy_id,
2490            instrument_id,
2491            client_order_id,
2492            released_price,
2493            event_id,
2494            ts_event: ts_init.into(), // System event - ts_event = ts_init
2495            ts_init: ts_init.into(),
2496        })
2497    }
2498}
2499
2500// OrderSubmitted
2501impl<'a> ToCapnp<'a> for OrderSubmitted {
2502    type Builder = order_capnp::order_submitted::Builder<'a>;
2503
2504    fn to_capnp(&self, mut builder: Self::Builder) {
2505        let trader_id_builder = builder.reborrow().init_trader_id();
2506        self.trader_id.to_capnp(trader_id_builder);
2507
2508        let strategy_id_builder = builder.reborrow().init_strategy_id();
2509        self.strategy_id.to_capnp(strategy_id_builder);
2510
2511        let instrument_id_builder = builder.reborrow().init_instrument_id();
2512        self.instrument_id.to_capnp(instrument_id_builder);
2513
2514        let client_order_id_builder = builder.reborrow().init_client_order_id();
2515        self.client_order_id.to_capnp(client_order_id_builder);
2516
2517        self.account_id
2518            .write_capnp(|| builder.reborrow().init_account_id());
2519
2520        let event_id_builder = builder.reborrow().init_event_id();
2521        self.event_id.to_capnp(event_id_builder);
2522
2523        let mut ts_event_builder = builder.reborrow().init_ts_event();
2524        ts_event_builder.set_value(*self.ts_event);
2525
2526        let mut ts_init_builder = builder.reborrow().init_ts_init();
2527        ts_init_builder.set_value(*self.ts_init);
2528    }
2529}
2530
2531impl<'a> FromCapnp<'a> for OrderSubmitted {
2532    type Reader = order_capnp::order_submitted::Reader<'a>;
2533
2534    fn from_capnp(reader: Self::Reader) -> Result<Self, Box<dyn Error>> {
2535        let trader_id_reader = reader.get_trader_id()?;
2536        let trader_id = TraderId::from_capnp(trader_id_reader)?;
2537
2538        let strategy_id_reader = reader.get_strategy_id()?;
2539        let strategy_id = StrategyId::from_capnp(strategy_id_reader)?;
2540
2541        let instrument_id_reader = reader.get_instrument_id()?;
2542        let instrument_id = InstrumentId::from_capnp(instrument_id_reader)?;
2543
2544        let client_order_id_reader = reader.get_client_order_id()?;
2545        let client_order_id = ClientOrderId::from_capnp(client_order_id_reader)?;
2546
2547        let account_id_reader = reader.get_account_id()?;
2548        let account_id = AccountId::from_capnp(account_id_reader)?;
2549
2550        let event_id_reader = reader.get_event_id()?;
2551        let event_id = nautilus_core::UUID4::from_capnp(event_id_reader)?;
2552
2553        let ts_event_reader = reader.get_ts_event()?;
2554        let ts_event = ts_event_reader.get_value();
2555
2556        let ts_init_reader = reader.get_ts_init()?;
2557        let ts_init = ts_init_reader.get_value();
2558
2559        Ok(Self {
2560            trader_id,
2561            strategy_id,
2562            instrument_id,
2563            client_order_id,
2564            account_id,
2565            event_id,
2566            ts_event: ts_event.into(),
2567            ts_init: ts_init.into(),
2568        })
2569    }
2570}
2571
2572// OrderAccepted
2573impl<'a> ToCapnp<'a> for OrderAccepted {
2574    type Builder = order_capnp::order_accepted::Builder<'a>;
2575
2576    fn to_capnp(&self, mut builder: Self::Builder) {
2577        let trader_id_builder = builder.reborrow().init_trader_id();
2578        self.trader_id.to_capnp(trader_id_builder);
2579
2580        let strategy_id_builder = builder.reborrow().init_strategy_id();
2581        self.strategy_id.to_capnp(strategy_id_builder);
2582
2583        let instrument_id_builder = builder.reborrow().init_instrument_id();
2584        self.instrument_id.to_capnp(instrument_id_builder);
2585
2586        let client_order_id_builder = builder.reborrow().init_client_order_id();
2587        self.client_order_id.to_capnp(client_order_id_builder);
2588
2589        self.venue_order_id
2590            .write_capnp(|| builder.reborrow().init_venue_order_id());
2591        self.account_id
2592            .write_capnp(|| builder.reborrow().init_account_id());
2593
2594        let event_id_builder = builder.reborrow().init_event_id();
2595        self.event_id.to_capnp(event_id_builder);
2596
2597        let mut ts_event_builder = builder.reborrow().init_ts_event();
2598        ts_event_builder.set_value(*self.ts_event);
2599
2600        let mut ts_init_builder = builder.reborrow().init_ts_init();
2601        ts_init_builder.set_value(*self.ts_init);
2602
2603        builder.set_reconciliation(self.reconciliation != 0);
2604    }
2605}
2606
2607impl<'a> FromCapnp<'a> for OrderAccepted {
2608    type Reader = order_capnp::order_accepted::Reader<'a>;
2609
2610    fn from_capnp(reader: Self::Reader) -> Result<Self, Box<dyn Error>> {
2611        let trader_id_reader = reader.get_trader_id()?;
2612        let trader_id = TraderId::from_capnp(trader_id_reader)?;
2613
2614        let strategy_id_reader = reader.get_strategy_id()?;
2615        let strategy_id = StrategyId::from_capnp(strategy_id_reader)?;
2616
2617        let instrument_id_reader = reader.get_instrument_id()?;
2618        let instrument_id = InstrumentId::from_capnp(instrument_id_reader)?;
2619
2620        let client_order_id_reader = reader.get_client_order_id()?;
2621        let client_order_id = ClientOrderId::from_capnp(client_order_id_reader)?;
2622
2623        let venue_order_id_reader = reader.get_venue_order_id()?;
2624        let venue_order_id = VenueOrderId::from_capnp(venue_order_id_reader)?;
2625
2626        let account_id_reader = reader.get_account_id()?;
2627        let account_id = AccountId::from_capnp(account_id_reader)?;
2628
2629        let event_id_reader = reader.get_event_id()?;
2630        let event_id = nautilus_core::UUID4::from_capnp(event_id_reader)?;
2631
2632        let ts_event_reader = reader.get_ts_event()?;
2633        let ts_event = ts_event_reader.get_value();
2634
2635        let ts_init_reader = reader.get_ts_init()?;
2636        let ts_init = ts_init_reader.get_value();
2637
2638        let reconciliation = reader.get_reconciliation() as u8;
2639
2640        Ok(Self {
2641            trader_id,
2642            strategy_id,
2643            instrument_id,
2644            client_order_id,
2645            venue_order_id,
2646            account_id,
2647            event_id,
2648            ts_event: ts_event.into(),
2649            ts_init: ts_init.into(),
2650            reconciliation,
2651        })
2652    }
2653}
2654
2655// OrderRejected
2656impl<'a> ToCapnp<'a> for OrderRejected {
2657    type Builder = order_capnp::order_rejected::Builder<'a>;
2658
2659    fn to_capnp(&self, mut builder: Self::Builder) {
2660        let trader_id_builder = builder.reborrow().init_trader_id();
2661        self.trader_id.to_capnp(trader_id_builder);
2662
2663        let strategy_id_builder = builder.reborrow().init_strategy_id();
2664        self.strategy_id.to_capnp(strategy_id_builder);
2665
2666        let instrument_id_builder = builder.reborrow().init_instrument_id();
2667        self.instrument_id.to_capnp(instrument_id_builder);
2668
2669        let client_order_id_builder = builder.reborrow().init_client_order_id();
2670        self.client_order_id.to_capnp(client_order_id_builder);
2671
2672        self.account_id
2673            .write_capnp(|| builder.reborrow().init_account_id());
2674
2675        builder.set_reason(self.reason.as_str());
2676
2677        let event_id_builder = builder.reborrow().init_event_id();
2678        self.event_id.to_capnp(event_id_builder);
2679
2680        let mut ts_event_builder = builder.reborrow().init_ts_event();
2681        ts_event_builder.set_value(*self.ts_event);
2682
2683        let mut ts_init_builder = builder.reborrow().init_ts_init();
2684        ts_init_builder.set_value(*self.ts_init);
2685
2686        builder.set_reconciliation(self.reconciliation != 0);
2687        builder.set_due_post_only(self.due_post_only != 0);
2688    }
2689}
2690
2691impl<'a> FromCapnp<'a> for OrderRejected {
2692    type Reader = order_capnp::order_rejected::Reader<'a>;
2693
2694    fn from_capnp(reader: Self::Reader) -> Result<Self, Box<dyn Error>> {
2695        let trader_id_reader = reader.get_trader_id()?;
2696        let trader_id = TraderId::from_capnp(trader_id_reader)?;
2697
2698        let strategy_id_reader = reader.get_strategy_id()?;
2699        let strategy_id = StrategyId::from_capnp(strategy_id_reader)?;
2700
2701        let instrument_id_reader = reader.get_instrument_id()?;
2702        let instrument_id = InstrumentId::from_capnp(instrument_id_reader)?;
2703
2704        let client_order_id_reader = reader.get_client_order_id()?;
2705        let client_order_id = ClientOrderId::from_capnp(client_order_id_reader)?;
2706
2707        let account_id_reader = reader.get_account_id()?;
2708        let account_id = AccountId::from_capnp(account_id_reader)?;
2709
2710        let reason = Ustr::from(reader.get_reason()?.to_str()?);
2711
2712        let event_id_reader = reader.get_event_id()?;
2713        let event_id = nautilus_core::UUID4::from_capnp(event_id_reader)?;
2714
2715        let ts_event_reader = reader.get_ts_event()?;
2716        let ts_event = ts_event_reader.get_value();
2717
2718        let ts_init_reader = reader.get_ts_init()?;
2719        let ts_init = ts_init_reader.get_value();
2720
2721        let reconciliation = reader.get_reconciliation() as u8;
2722        let due_post_only = reader.get_due_post_only() as u8;
2723
2724        Ok(Self {
2725            trader_id,
2726            strategy_id,
2727            instrument_id,
2728            client_order_id,
2729            account_id,
2730            reason,
2731            event_id,
2732            ts_event: ts_event.into(),
2733            ts_init: ts_init.into(),
2734            reconciliation,
2735            due_post_only,
2736        })
2737    }
2738}
2739
2740// OrderCanceled
2741impl<'a> ToCapnp<'a> for OrderCanceled {
2742    type Builder = order_capnp::order_canceled::Builder<'a>;
2743
2744    fn to_capnp(&self, mut builder: Self::Builder) {
2745        let trader_id_builder = builder.reborrow().init_trader_id();
2746        self.trader_id.to_capnp(trader_id_builder);
2747
2748        let strategy_id_builder = builder.reborrow().init_strategy_id();
2749        self.strategy_id.to_capnp(strategy_id_builder);
2750
2751        let instrument_id_builder = builder.reborrow().init_instrument_id();
2752        self.instrument_id.to_capnp(instrument_id_builder);
2753
2754        let client_order_id_builder = builder.reborrow().init_client_order_id();
2755        self.client_order_id.to_capnp(client_order_id_builder);
2756
2757        if let Some(ref venue_order_id) = self.venue_order_id {
2758            let venue_order_id_builder = builder.reborrow().init_venue_order_id();
2759            venue_order_id.to_capnp(venue_order_id_builder);
2760        }
2761
2762        self.account_id
2763            .write_capnp(|| builder.reborrow().init_account_id());
2764
2765        let event_id_builder = builder.reborrow().init_event_id();
2766        self.event_id.to_capnp(event_id_builder);
2767
2768        let mut ts_event_builder = builder.reborrow().init_ts_event();
2769        ts_event_builder.set_value(*self.ts_event);
2770
2771        let mut ts_init_builder = builder.reborrow().init_ts_init();
2772        ts_init_builder.set_value(*self.ts_init);
2773
2774        builder.set_reconciliation(self.reconciliation != 0);
2775    }
2776}
2777
2778impl<'a> FromCapnp<'a> for OrderCanceled {
2779    type Reader = order_capnp::order_canceled::Reader<'a>;
2780
2781    fn from_capnp(reader: Self::Reader) -> Result<Self, Box<dyn Error>> {
2782        let trader_id_reader = reader.get_trader_id()?;
2783        let trader_id = TraderId::from_capnp(trader_id_reader)?;
2784
2785        let strategy_id_reader = reader.get_strategy_id()?;
2786        let strategy_id = StrategyId::from_capnp(strategy_id_reader)?;
2787
2788        let instrument_id_reader = reader.get_instrument_id()?;
2789        let instrument_id = InstrumentId::from_capnp(instrument_id_reader)?;
2790
2791        let client_order_id_reader = reader.get_client_order_id()?;
2792        let client_order_id = ClientOrderId::from_capnp(client_order_id_reader)?;
2793
2794        let venue_order_id = read_optional_from_capnp(
2795            || reader.has_venue_order_id(),
2796            || reader.get_venue_order_id(),
2797        )?;
2798
2799        let account_id =
2800            read_optional_from_capnp(|| reader.has_account_id(), || reader.get_account_id())?;
2801
2802        let event_id_reader = reader.get_event_id()?;
2803        let event_id = nautilus_core::UUID4::from_capnp(event_id_reader)?;
2804
2805        let ts_event_reader = reader.get_ts_event()?;
2806        let ts_event = ts_event_reader.get_value();
2807
2808        let ts_init_reader = reader.get_ts_init()?;
2809        let ts_init = ts_init_reader.get_value();
2810
2811        let reconciliation = reader.get_reconciliation() as u8;
2812
2813        Ok(Self {
2814            trader_id,
2815            strategy_id,
2816            instrument_id,
2817            client_order_id,
2818            venue_order_id,
2819            account_id,
2820            event_id,
2821            ts_event: ts_event.into(),
2822            ts_init: ts_init.into(),
2823            reconciliation,
2824        })
2825    }
2826}
2827
2828// OrderExpired
2829impl<'a> ToCapnp<'a> for OrderExpired {
2830    type Builder = order_capnp::order_expired::Builder<'a>;
2831
2832    fn to_capnp(&self, mut builder: Self::Builder) {
2833        let trader_id_builder = builder.reborrow().init_trader_id();
2834        self.trader_id.to_capnp(trader_id_builder);
2835
2836        let strategy_id_builder = builder.reborrow().init_strategy_id();
2837        self.strategy_id.to_capnp(strategy_id_builder);
2838
2839        let instrument_id_builder = builder.reborrow().init_instrument_id();
2840        self.instrument_id.to_capnp(instrument_id_builder);
2841
2842        let client_order_id_builder = builder.reborrow().init_client_order_id();
2843        self.client_order_id.to_capnp(client_order_id_builder);
2844
2845        if let Some(ref venue_order_id) = self.venue_order_id {
2846            let venue_order_id_builder = builder.reborrow().init_venue_order_id();
2847            venue_order_id.to_capnp(venue_order_id_builder);
2848        }
2849
2850        self.account_id
2851            .write_capnp(|| builder.reborrow().init_account_id());
2852
2853        let event_id_builder = builder.reborrow().init_event_id();
2854        self.event_id.to_capnp(event_id_builder);
2855
2856        let mut ts_event_builder = builder.reborrow().init_ts_event();
2857        ts_event_builder.set_value(*self.ts_event);
2858
2859        let mut ts_init_builder = builder.reborrow().init_ts_init();
2860        ts_init_builder.set_value(*self.ts_init);
2861
2862        builder.set_reconciliation(self.reconciliation != 0);
2863    }
2864}
2865
2866impl<'a> FromCapnp<'a> for OrderExpired {
2867    type Reader = order_capnp::order_expired::Reader<'a>;
2868
2869    fn from_capnp(reader: Self::Reader) -> Result<Self, Box<dyn Error>> {
2870        let trader_id_reader = reader.get_trader_id()?;
2871        let trader_id = TraderId::from_capnp(trader_id_reader)?;
2872
2873        let strategy_id_reader = reader.get_strategy_id()?;
2874        let strategy_id = StrategyId::from_capnp(strategy_id_reader)?;
2875
2876        let instrument_id_reader = reader.get_instrument_id()?;
2877        let instrument_id = InstrumentId::from_capnp(instrument_id_reader)?;
2878
2879        let client_order_id_reader = reader.get_client_order_id()?;
2880        let client_order_id = ClientOrderId::from_capnp(client_order_id_reader)?;
2881
2882        let venue_order_id = read_optional_from_capnp(
2883            || reader.has_venue_order_id(),
2884            || reader.get_venue_order_id(),
2885        )?;
2886
2887        let account_id =
2888            read_optional_from_capnp(|| reader.has_account_id(), || reader.get_account_id())?;
2889
2890        let event_id_reader = reader.get_event_id()?;
2891        let event_id = nautilus_core::UUID4::from_capnp(event_id_reader)?;
2892
2893        let ts_event_reader = reader.get_ts_event()?;
2894        let ts_event = ts_event_reader.get_value();
2895
2896        let ts_init_reader = reader.get_ts_init()?;
2897        let ts_init = ts_init_reader.get_value();
2898
2899        let reconciliation = reader.get_reconciliation() as u8;
2900
2901        Ok(Self {
2902            trader_id,
2903            strategy_id,
2904            instrument_id,
2905            client_order_id,
2906            venue_order_id,
2907            account_id,
2908            event_id,
2909            ts_event: ts_event.into(),
2910            ts_init: ts_init.into(),
2911            reconciliation,
2912        })
2913    }
2914}
2915
2916// OrderTriggered
2917impl<'a> ToCapnp<'a> for OrderTriggered {
2918    type Builder = order_capnp::order_triggered::Builder<'a>;
2919
2920    fn to_capnp(&self, mut builder: Self::Builder) {
2921        let trader_id_builder = builder.reborrow().init_trader_id();
2922        self.trader_id.to_capnp(trader_id_builder);
2923
2924        let strategy_id_builder = builder.reborrow().init_strategy_id();
2925        self.strategy_id.to_capnp(strategy_id_builder);
2926
2927        let instrument_id_builder = builder.reborrow().init_instrument_id();
2928        self.instrument_id.to_capnp(instrument_id_builder);
2929
2930        let client_order_id_builder = builder.reborrow().init_client_order_id();
2931        self.client_order_id.to_capnp(client_order_id_builder);
2932
2933        if let Some(ref venue_order_id) = self.venue_order_id {
2934            let venue_order_id_builder = builder.reborrow().init_venue_order_id();
2935            venue_order_id.to_capnp(venue_order_id_builder);
2936        }
2937
2938        self.account_id
2939            .write_capnp(|| builder.reborrow().init_account_id());
2940
2941        let event_id_builder = builder.reborrow().init_event_id();
2942        self.event_id.to_capnp(event_id_builder);
2943
2944        let mut ts_event_builder = builder.reborrow().init_ts_event();
2945        ts_event_builder.set_value(*self.ts_event);
2946
2947        let mut ts_init_builder = builder.reborrow().init_ts_init();
2948        ts_init_builder.set_value(*self.ts_init);
2949
2950        builder.set_reconciliation(self.reconciliation != 0);
2951    }
2952}
2953
2954impl<'a> FromCapnp<'a> for OrderTriggered {
2955    type Reader = order_capnp::order_triggered::Reader<'a>;
2956
2957    fn from_capnp(reader: Self::Reader) -> Result<Self, Box<dyn Error>> {
2958        let trader_id_reader = reader.get_trader_id()?;
2959        let trader_id = TraderId::from_capnp(trader_id_reader)?;
2960
2961        let strategy_id_reader = reader.get_strategy_id()?;
2962        let strategy_id = StrategyId::from_capnp(strategy_id_reader)?;
2963
2964        let instrument_id_reader = reader.get_instrument_id()?;
2965        let instrument_id = InstrumentId::from_capnp(instrument_id_reader)?;
2966
2967        let client_order_id_reader = reader.get_client_order_id()?;
2968        let client_order_id = ClientOrderId::from_capnp(client_order_id_reader)?;
2969
2970        let venue_order_id = read_optional_from_capnp(
2971            || reader.has_venue_order_id(),
2972            || reader.get_venue_order_id(),
2973        )?;
2974
2975        let account_id =
2976            read_optional_from_capnp(|| reader.has_account_id(), || reader.get_account_id())?;
2977
2978        let event_id_reader = reader.get_event_id()?;
2979        let event_id = nautilus_core::UUID4::from_capnp(event_id_reader)?;
2980
2981        let ts_event_reader = reader.get_ts_event()?;
2982        let ts_event = ts_event_reader.get_value();
2983
2984        let ts_init_reader = reader.get_ts_init()?;
2985        let ts_init = ts_init_reader.get_value();
2986
2987        let reconciliation = reader.get_reconciliation() as u8;
2988
2989        Ok(Self {
2990            trader_id,
2991            strategy_id,
2992            instrument_id,
2993            client_order_id,
2994            venue_order_id,
2995            account_id,
2996            event_id,
2997            ts_event: ts_event.into(),
2998            ts_init: ts_init.into(),
2999            reconciliation,
3000        })
3001    }
3002}
3003
3004// OrderPendingUpdate
3005impl<'a> ToCapnp<'a> for OrderPendingUpdate {
3006    type Builder = order_capnp::order_pending_update::Builder<'a>;
3007
3008    fn to_capnp(&self, mut builder: Self::Builder) {
3009        let trader_id_builder = builder.reborrow().init_trader_id();
3010        self.trader_id.to_capnp(trader_id_builder);
3011
3012        let strategy_id_builder = builder.reborrow().init_strategy_id();
3013        self.strategy_id.to_capnp(strategy_id_builder);
3014
3015        let instrument_id_builder = builder.reborrow().init_instrument_id();
3016        self.instrument_id.to_capnp(instrument_id_builder);
3017
3018        let client_order_id_builder = builder.reborrow().init_client_order_id();
3019        self.client_order_id.to_capnp(client_order_id_builder);
3020
3021        if let Some(ref venue_order_id) = self.venue_order_id {
3022            let venue_order_id_builder = builder.reborrow().init_venue_order_id();
3023            venue_order_id.to_capnp(venue_order_id_builder);
3024        }
3025
3026        let account_id_builder = builder.reborrow().init_account_id();
3027        self.account_id.to_capnp(account_id_builder);
3028
3029        let event_id_builder = builder.reborrow().init_event_id();
3030        self.event_id.to_capnp(event_id_builder);
3031
3032        let mut ts_event_builder = builder.reborrow().init_ts_event();
3033        ts_event_builder.set_value(*self.ts_event);
3034
3035        let mut ts_init_builder = builder.reborrow().init_ts_init();
3036        ts_init_builder.set_value(*self.ts_init);
3037
3038        builder.set_reconciliation(self.reconciliation != 0);
3039    }
3040}
3041
3042impl<'a> FromCapnp<'a> for OrderPendingUpdate {
3043    type Reader = order_capnp::order_pending_update::Reader<'a>;
3044
3045    fn from_capnp(reader: Self::Reader) -> Result<Self, Box<dyn Error>> {
3046        let trader_id_reader = reader.get_trader_id()?;
3047        let trader_id = TraderId::from_capnp(trader_id_reader)?;
3048
3049        let strategy_id_reader = reader.get_strategy_id()?;
3050        let strategy_id = StrategyId::from_capnp(strategy_id_reader)?;
3051
3052        let instrument_id_reader = reader.get_instrument_id()?;
3053        let instrument_id = InstrumentId::from_capnp(instrument_id_reader)?;
3054
3055        let client_order_id_reader = reader.get_client_order_id()?;
3056        let client_order_id = ClientOrderId::from_capnp(client_order_id_reader)?;
3057
3058        let venue_order_id = if reader.has_venue_order_id() {
3059            let venue_order_id_reader = reader.get_venue_order_id()?;
3060            Some(VenueOrderId::from_capnp(venue_order_id_reader)?)
3061        } else {
3062            None
3063        };
3064
3065        let account_id_reader = reader.get_account_id()?;
3066        let account_id = AccountId::from_capnp(account_id_reader)?;
3067
3068        let event_id_reader = reader.get_event_id()?;
3069        let event_id = nautilus_core::UUID4::from_capnp(event_id_reader)?;
3070
3071        let ts_event_reader = reader.get_ts_event()?;
3072        let ts_event = ts_event_reader.get_value();
3073
3074        let ts_init_reader = reader.get_ts_init()?;
3075        let ts_init = ts_init_reader.get_value();
3076
3077        let reconciliation = reader.get_reconciliation() as u8;
3078
3079        Ok(Self {
3080            trader_id,
3081            strategy_id,
3082            instrument_id,
3083            client_order_id,
3084            venue_order_id,
3085            account_id,
3086            event_id,
3087            ts_event: ts_event.into(),
3088            ts_init: ts_init.into(),
3089            reconciliation,
3090        })
3091    }
3092}
3093
3094// OrderPendingCancel
3095impl<'a> ToCapnp<'a> for OrderPendingCancel {
3096    type Builder = order_capnp::order_pending_cancel::Builder<'a>;
3097
3098    fn to_capnp(&self, mut builder: Self::Builder) {
3099        let trader_id_builder = builder.reborrow().init_trader_id();
3100        self.trader_id.to_capnp(trader_id_builder);
3101
3102        let strategy_id_builder = builder.reborrow().init_strategy_id();
3103        self.strategy_id.to_capnp(strategy_id_builder);
3104
3105        let instrument_id_builder = builder.reborrow().init_instrument_id();
3106        self.instrument_id.to_capnp(instrument_id_builder);
3107
3108        let client_order_id_builder = builder.reborrow().init_client_order_id();
3109        self.client_order_id.to_capnp(client_order_id_builder);
3110
3111        if let Some(ref venue_order_id) = self.venue_order_id {
3112            let venue_order_id_builder = builder.reborrow().init_venue_order_id();
3113            venue_order_id.to_capnp(venue_order_id_builder);
3114        }
3115
3116        let account_id_builder = builder.reborrow().init_account_id();
3117        self.account_id.to_capnp(account_id_builder);
3118
3119        let event_id_builder = builder.reborrow().init_event_id();
3120        self.event_id.to_capnp(event_id_builder);
3121
3122        let mut ts_event_builder = builder.reborrow().init_ts_event();
3123        ts_event_builder.set_value(*self.ts_event);
3124
3125        let mut ts_init_builder = builder.reborrow().init_ts_init();
3126        ts_init_builder.set_value(*self.ts_init);
3127
3128        builder.set_reconciliation(self.reconciliation != 0);
3129    }
3130}
3131
3132impl<'a> FromCapnp<'a> for OrderPendingCancel {
3133    type Reader = order_capnp::order_pending_cancel::Reader<'a>;
3134
3135    fn from_capnp(reader: Self::Reader) -> Result<Self, Box<dyn Error>> {
3136        let trader_id_reader = reader.get_trader_id()?;
3137        let trader_id = TraderId::from_capnp(trader_id_reader)?;
3138
3139        let strategy_id_reader = reader.get_strategy_id()?;
3140        let strategy_id = StrategyId::from_capnp(strategy_id_reader)?;
3141
3142        let instrument_id_reader = reader.get_instrument_id()?;
3143        let instrument_id = InstrumentId::from_capnp(instrument_id_reader)?;
3144
3145        let client_order_id_reader = reader.get_client_order_id()?;
3146        let client_order_id = ClientOrderId::from_capnp(client_order_id_reader)?;
3147
3148        let venue_order_id = if reader.has_venue_order_id() {
3149            let venue_order_id_reader = reader.get_venue_order_id()?;
3150            Some(VenueOrderId::from_capnp(venue_order_id_reader)?)
3151        } else {
3152            None
3153        };
3154
3155        let account_id_reader = reader.get_account_id()?;
3156        let account_id = AccountId::from_capnp(account_id_reader)?;
3157
3158        let event_id_reader = reader.get_event_id()?;
3159        let event_id = nautilus_core::UUID4::from_capnp(event_id_reader)?;
3160
3161        let ts_event_reader = reader.get_ts_event()?;
3162        let ts_event = ts_event_reader.get_value();
3163
3164        let ts_init_reader = reader.get_ts_init()?;
3165        let ts_init = ts_init_reader.get_value();
3166
3167        let reconciliation = reader.get_reconciliation() as u8;
3168
3169        Ok(Self {
3170            trader_id,
3171            strategy_id,
3172            instrument_id,
3173            client_order_id,
3174            venue_order_id,
3175            account_id,
3176            event_id,
3177            ts_event: ts_event.into(),
3178            ts_init: ts_init.into(),
3179            reconciliation,
3180        })
3181    }
3182}
3183
3184// OrderModifyRejected
3185impl<'a> ToCapnp<'a> for OrderModifyRejected {
3186    type Builder = order_capnp::order_modify_rejected::Builder<'a>;
3187
3188    fn to_capnp(&self, mut builder: Self::Builder) {
3189        let trader_id_builder = builder.reborrow().init_trader_id();
3190        self.trader_id.to_capnp(trader_id_builder);
3191
3192        let strategy_id_builder = builder.reborrow().init_strategy_id();
3193        self.strategy_id.to_capnp(strategy_id_builder);
3194
3195        let instrument_id_builder = builder.reborrow().init_instrument_id();
3196        self.instrument_id.to_capnp(instrument_id_builder);
3197
3198        let client_order_id_builder = builder.reborrow().init_client_order_id();
3199        self.client_order_id.to_capnp(client_order_id_builder);
3200
3201        self.venue_order_id
3202            .write_capnp(|| builder.reborrow().init_venue_order_id());
3203        self.account_id
3204            .write_capnp(|| builder.reborrow().init_account_id());
3205
3206        builder.set_reason(self.reason.as_str());
3207
3208        let event_id_builder = builder.reborrow().init_event_id();
3209        self.event_id.to_capnp(event_id_builder);
3210
3211        let mut ts_event_builder = builder.reborrow().init_ts_event();
3212        ts_event_builder.set_value(*self.ts_event);
3213
3214        let mut ts_init_builder = builder.reborrow().init_ts_init();
3215        ts_init_builder.set_value(*self.ts_init);
3216
3217        builder.set_reconciliation(self.reconciliation != 0);
3218    }
3219}
3220
3221impl<'a> FromCapnp<'a> for OrderModifyRejected {
3222    type Reader = order_capnp::order_modify_rejected::Reader<'a>;
3223
3224    fn from_capnp(reader: Self::Reader) -> Result<Self, Box<dyn Error>> {
3225        let trader_id_reader = reader.get_trader_id()?;
3226        let trader_id = TraderId::from_capnp(trader_id_reader)?;
3227
3228        let strategy_id_reader = reader.get_strategy_id()?;
3229        let strategy_id = StrategyId::from_capnp(strategy_id_reader)?;
3230
3231        let instrument_id_reader = reader.get_instrument_id()?;
3232        let instrument_id = InstrumentId::from_capnp(instrument_id_reader)?;
3233
3234        let client_order_id_reader = reader.get_client_order_id()?;
3235        let client_order_id = ClientOrderId::from_capnp(client_order_id_reader)?;
3236
3237        let venue_order_id = read_optional_from_capnp(
3238            || reader.has_venue_order_id(),
3239            || reader.get_venue_order_id(),
3240        )?;
3241
3242        let account_id =
3243            read_optional_from_capnp(|| reader.has_account_id(), || reader.get_account_id())?;
3244
3245        let reason = Ustr::from(reader.get_reason()?.to_str()?);
3246
3247        let event_id_reader = reader.get_event_id()?;
3248        let event_id = nautilus_core::UUID4::from_capnp(event_id_reader)?;
3249
3250        let ts_event_reader = reader.get_ts_event()?;
3251        let ts_event = ts_event_reader.get_value();
3252
3253        let ts_init_reader = reader.get_ts_init()?;
3254        let ts_init = ts_init_reader.get_value();
3255
3256        let reconciliation = reader.get_reconciliation() as u8;
3257
3258        Ok(Self {
3259            trader_id,
3260            strategy_id,
3261            instrument_id,
3262            client_order_id,
3263            venue_order_id,
3264            account_id,
3265            reason,
3266            event_id,
3267            ts_event: ts_event.into(),
3268            ts_init: ts_init.into(),
3269            reconciliation,
3270        })
3271    }
3272}
3273
3274// OrderCancelRejected
3275impl<'a> ToCapnp<'a> for OrderCancelRejected {
3276    type Builder = order_capnp::order_cancel_rejected::Builder<'a>;
3277
3278    fn to_capnp(&self, mut builder: Self::Builder) {
3279        let trader_id_builder = builder.reborrow().init_trader_id();
3280        self.trader_id.to_capnp(trader_id_builder);
3281
3282        let strategy_id_builder = builder.reborrow().init_strategy_id();
3283        self.strategy_id.to_capnp(strategy_id_builder);
3284
3285        let instrument_id_builder = builder.reborrow().init_instrument_id();
3286        self.instrument_id.to_capnp(instrument_id_builder);
3287
3288        let client_order_id_builder = builder.reborrow().init_client_order_id();
3289        self.client_order_id.to_capnp(client_order_id_builder);
3290
3291        self.venue_order_id
3292            .write_capnp(|| builder.reborrow().init_venue_order_id());
3293        self.account_id
3294            .write_capnp(|| builder.reborrow().init_account_id());
3295
3296        builder.set_reason(self.reason.as_str());
3297
3298        let event_id_builder = builder.reborrow().init_event_id();
3299        self.event_id.to_capnp(event_id_builder);
3300
3301        let mut ts_event_builder = builder.reborrow().init_ts_event();
3302        ts_event_builder.set_value(*self.ts_event);
3303
3304        let mut ts_init_builder = builder.reborrow().init_ts_init();
3305        ts_init_builder.set_value(*self.ts_init);
3306
3307        builder.set_reconciliation(self.reconciliation != 0);
3308    }
3309}
3310
3311impl<'a> FromCapnp<'a> for OrderCancelRejected {
3312    type Reader = order_capnp::order_cancel_rejected::Reader<'a>;
3313
3314    fn from_capnp(reader: Self::Reader) -> Result<Self, Box<dyn Error>> {
3315        let trader_id_reader = reader.get_trader_id()?;
3316        let trader_id = TraderId::from_capnp(trader_id_reader)?;
3317
3318        let strategy_id_reader = reader.get_strategy_id()?;
3319        let strategy_id = StrategyId::from_capnp(strategy_id_reader)?;
3320
3321        let instrument_id_reader = reader.get_instrument_id()?;
3322        let instrument_id = InstrumentId::from_capnp(instrument_id_reader)?;
3323
3324        let client_order_id_reader = reader.get_client_order_id()?;
3325        let client_order_id = ClientOrderId::from_capnp(client_order_id_reader)?;
3326
3327        let venue_order_id = read_optional_from_capnp(
3328            || reader.has_venue_order_id(),
3329            || reader.get_venue_order_id(),
3330        )?;
3331
3332        let account_id =
3333            read_optional_from_capnp(|| reader.has_account_id(), || reader.get_account_id())?;
3334
3335        let reason = Ustr::from(reader.get_reason()?.to_str()?);
3336
3337        let event_id_reader = reader.get_event_id()?;
3338        let event_id = nautilus_core::UUID4::from_capnp(event_id_reader)?;
3339
3340        let ts_event_reader = reader.get_ts_event()?;
3341        let ts_event = ts_event_reader.get_value();
3342
3343        let ts_init_reader = reader.get_ts_init()?;
3344        let ts_init = ts_init_reader.get_value();
3345
3346        let reconciliation = reader.get_reconciliation() as u8;
3347
3348        Ok(Self {
3349            trader_id,
3350            strategy_id,
3351            instrument_id,
3352            client_order_id,
3353            venue_order_id,
3354            account_id,
3355            reason,
3356            event_id,
3357            ts_event: ts_event.into(),
3358            ts_init: ts_init.into(),
3359            reconciliation,
3360        })
3361    }
3362}
3363
3364// OrderUpdated
3365impl<'a> ToCapnp<'a> for OrderUpdated {
3366    type Builder = order_capnp::order_updated::Builder<'a>;
3367
3368    fn to_capnp(&self, mut builder: Self::Builder) {
3369        let trader_id_builder = builder.reborrow().init_trader_id();
3370        self.trader_id.to_capnp(trader_id_builder);
3371
3372        let strategy_id_builder = builder.reborrow().init_strategy_id();
3373        self.strategy_id.to_capnp(strategy_id_builder);
3374
3375        let instrument_id_builder = builder.reborrow().init_instrument_id();
3376        self.instrument_id.to_capnp(instrument_id_builder);
3377
3378        let client_order_id_builder = builder.reborrow().init_client_order_id();
3379        self.client_order_id.to_capnp(client_order_id_builder);
3380
3381        self.venue_order_id
3382            .write_capnp(|| builder.reborrow().init_venue_order_id());
3383        self.account_id
3384            .write_capnp(|| builder.reborrow().init_account_id());
3385
3386        let quantity_builder = builder.reborrow().init_quantity();
3387        self.quantity.to_capnp(quantity_builder);
3388
3389        if let Some(price) = self.price {
3390            let price_builder = builder.reborrow().init_price();
3391            price.to_capnp(price_builder);
3392        }
3393
3394        if let Some(trigger_price) = self.trigger_price {
3395            let trigger_price_builder = builder.reborrow().init_trigger_price();
3396            trigger_price.to_capnp(trigger_price_builder);
3397        }
3398
3399        if let Some(protection_price) = self.protection_price {
3400            let protection_price_builder = builder.reborrow().init_protection_price();
3401            protection_price.to_capnp(protection_price_builder);
3402        }
3403
3404        let event_id_builder = builder.reborrow().init_event_id();
3405        self.event_id.to_capnp(event_id_builder);
3406
3407        let mut ts_event_builder = builder.reborrow().init_ts_event();
3408        ts_event_builder.set_value(*self.ts_event);
3409
3410        let mut ts_init_builder = builder.reborrow().init_ts_init();
3411        ts_init_builder.set_value(*self.ts_init);
3412
3413        builder.set_reconciliation(self.reconciliation != 0);
3414        builder.set_is_quote_quantity(self.is_quote_quantity);
3415    }
3416}
3417
3418impl<'a> FromCapnp<'a> for OrderUpdated {
3419    type Reader = order_capnp::order_updated::Reader<'a>;
3420
3421    fn from_capnp(reader: Self::Reader) -> Result<Self, Box<dyn Error>> {
3422        let trader_id_reader = reader.get_trader_id()?;
3423        let trader_id = TraderId::from_capnp(trader_id_reader)?;
3424
3425        let strategy_id_reader = reader.get_strategy_id()?;
3426        let strategy_id = StrategyId::from_capnp(strategy_id_reader)?;
3427
3428        let instrument_id_reader = reader.get_instrument_id()?;
3429        let instrument_id = InstrumentId::from_capnp(instrument_id_reader)?;
3430
3431        let client_order_id_reader = reader.get_client_order_id()?;
3432        let client_order_id = ClientOrderId::from_capnp(client_order_id_reader)?;
3433
3434        let venue_order_id = read_optional_from_capnp(
3435            || reader.has_venue_order_id(),
3436            || reader.get_venue_order_id(),
3437        )?;
3438
3439        let account_id =
3440            read_optional_from_capnp(|| reader.has_account_id(), || reader.get_account_id())?;
3441
3442        let quantity_reader = reader.get_quantity()?;
3443        let quantity = Quantity::from_capnp(quantity_reader)?;
3444
3445        let price = if reader.has_price() {
3446            let price_reader = reader.get_price()?;
3447            Some(Price::from_capnp(price_reader)?)
3448        } else {
3449            None
3450        };
3451
3452        let trigger_price = if reader.has_trigger_price() {
3453            let trigger_price_reader = reader.get_trigger_price()?;
3454            Some(Price::from_capnp(trigger_price_reader)?)
3455        } else {
3456            None
3457        };
3458
3459        let protection_price = if reader.has_protection_price() {
3460            let protection_price_reader = reader.get_protection_price()?;
3461            Some(Price::from_capnp(protection_price_reader)?)
3462        } else {
3463            None
3464        };
3465
3466        let event_id_reader = reader.get_event_id()?;
3467        let event_id = nautilus_core::UUID4::from_capnp(event_id_reader)?;
3468
3469        let ts_event_reader = reader.get_ts_event()?;
3470        let ts_event = ts_event_reader.get_value();
3471
3472        let ts_init_reader = reader.get_ts_init()?;
3473        let ts_init = ts_init_reader.get_value();
3474
3475        let reconciliation = reader.get_reconciliation() as u8;
3476
3477        Ok(Self {
3478            trader_id,
3479            strategy_id,
3480            instrument_id,
3481            client_order_id,
3482            venue_order_id,
3483            account_id,
3484            quantity,
3485            price,
3486            trigger_price,
3487            protection_price,
3488            is_quote_quantity: reader.get_is_quote_quantity(),
3489            event_id,
3490            ts_event: ts_event.into(),
3491            ts_init: ts_init.into(),
3492            reconciliation,
3493        })
3494    }
3495}
3496
3497// OrderFilled
3498impl<'a> ToCapnp<'a> for OrderFilled {
3499    type Builder = order_capnp::order_filled::Builder<'a>;
3500
3501    fn to_capnp(&self, mut builder: Self::Builder) {
3502        let trader_id_builder = builder.reborrow().init_trader_id();
3503        self.trader_id.to_capnp(trader_id_builder);
3504
3505        let strategy_id_builder = builder.reborrow().init_strategy_id();
3506        self.strategy_id.to_capnp(strategy_id_builder);
3507
3508        let instrument_id_builder = builder.reborrow().init_instrument_id();
3509        self.instrument_id.to_capnp(instrument_id_builder);
3510
3511        let client_order_id_builder = builder.reborrow().init_client_order_id();
3512        self.client_order_id.to_capnp(client_order_id_builder);
3513
3514        let venue_order_id_builder = builder.reborrow().init_venue_order_id();
3515        self.venue_order_id.to_capnp(venue_order_id_builder);
3516
3517        let account_id_builder = builder.reborrow().init_account_id();
3518        self.account_id.to_capnp(account_id_builder);
3519
3520        let trade_id_builder = builder.reborrow().init_trade_id();
3521        self.trade_id.to_capnp(trade_id_builder);
3522
3523        builder.set_order_side(order_side_to_capnp(self.order_side));
3524        builder.set_order_type(order_type_to_capnp(self.order_type));
3525
3526        let last_qty_builder = builder.reborrow().init_last_qty();
3527        self.last_qty.to_capnp(last_qty_builder);
3528
3529        let last_px_builder = builder.reborrow().init_last_px();
3530        self.last_px.to_capnp(last_px_builder);
3531
3532        let currency_builder = builder.reborrow().init_currency();
3533        self.currency.to_capnp(currency_builder);
3534
3535        builder.set_liquidity_side(liquidity_side_to_capnp(self.liquidity_side));
3536
3537        let event_id_builder = builder.reborrow().init_event_id();
3538        self.event_id.to_capnp(event_id_builder);
3539
3540        let mut ts_event_builder = builder.reborrow().init_ts_event();
3541        ts_event_builder.set_value(*self.ts_event);
3542
3543        let mut ts_init_builder = builder.reborrow().init_ts_init();
3544        ts_init_builder.set_value(*self.ts_init);
3545
3546        builder.set_reconciliation(self.reconciliation);
3547
3548        if let Some(position_id) = &self.position_id {
3549            let position_id_builder = builder.reborrow().init_position_id();
3550            position_id.to_capnp(position_id_builder);
3551        }
3552
3553        if let Some(commission) = &self.commission {
3554            let commission_builder = builder.reborrow().init_commission();
3555            commission.to_capnp(commission_builder);
3556        }
3557    }
3558}
3559
3560impl<'a> FromCapnp<'a> for OrderFilled {
3561    type Reader = order_capnp::order_filled::Reader<'a>;
3562
3563    fn from_capnp(reader: Self::Reader) -> Result<Self, Box<dyn Error>> {
3564        let trader_id_reader = reader.get_trader_id()?;
3565        let trader_id = TraderId::from_capnp(trader_id_reader)?;
3566
3567        let strategy_id_reader = reader.get_strategy_id()?;
3568        let strategy_id = StrategyId::from_capnp(strategy_id_reader)?;
3569
3570        let instrument_id_reader = reader.get_instrument_id()?;
3571        let instrument_id = InstrumentId::from_capnp(instrument_id_reader)?;
3572
3573        let client_order_id_reader = reader.get_client_order_id()?;
3574        let client_order_id = ClientOrderId::from_capnp(client_order_id_reader)?;
3575
3576        let venue_order_id_reader = reader.get_venue_order_id()?;
3577        let venue_order_id = VenueOrderId::from_capnp(venue_order_id_reader)?;
3578
3579        let account_id_reader = reader.get_account_id()?;
3580        let account_id = AccountId::from_capnp(account_id_reader)?;
3581
3582        let trade_id_reader = reader.get_trade_id()?;
3583        let trade_id = TradeId::from_capnp(trade_id_reader)?;
3584
3585        let order_side = order_side_from_capnp(reader.get_order_side()?);
3586        let order_type = order_type_from_capnp(reader.get_order_type()?);
3587
3588        let last_qty_reader = reader.get_last_qty()?;
3589        let last_qty = Quantity::from_capnp(last_qty_reader)?;
3590
3591        let last_px_reader = reader.get_last_px()?;
3592        let last_px = Price::from_capnp(last_px_reader)?;
3593
3594        let currency_reader = reader.get_currency()?;
3595        let currency = Currency::from_capnp(currency_reader)?;
3596
3597        let liquidity_side = liquidity_side_from_capnp(reader.get_liquidity_side()?);
3598
3599        let event_id_reader = reader.get_event_id()?;
3600        let event_id = nautilus_core::UUID4::from_capnp(event_id_reader)?;
3601
3602        let ts_event_reader = reader.get_ts_event()?;
3603        let ts_event = ts_event_reader.get_value();
3604
3605        let ts_init_reader = reader.get_ts_init()?;
3606        let ts_init = ts_init_reader.get_value();
3607
3608        let reconciliation = reader.get_reconciliation();
3609
3610        let position_id = if reader.has_position_id() {
3611            let position_id_reader = reader.get_position_id()?;
3612            Some(PositionId::from_capnp(position_id_reader)?)
3613        } else {
3614            None
3615        };
3616
3617        let commission = if reader.has_commission() {
3618            let commission_reader = reader.get_commission()?;
3619            Some(Money::from_capnp(commission_reader)?)
3620        } else {
3621            None
3622        };
3623
3624        Ok(Self {
3625            trader_id,
3626            strategy_id,
3627            instrument_id,
3628            client_order_id,
3629            venue_order_id,
3630            account_id,
3631            trade_id,
3632            order_side,
3633            order_type,
3634            last_qty,
3635            last_px,
3636            currency,
3637            liquidity_side,
3638            event_id,
3639            ts_event: ts_event.into(),
3640            ts_init: ts_init.into(),
3641            reconciliation,
3642            position_id,
3643            commission,
3644        })
3645    }
3646}
3647
3648// OrderInitialized - seed event
3649impl<'a> ToCapnp<'a> for OrderInitialized {
3650    type Builder = order_capnp::order_initialized::Builder<'a>;
3651
3652    fn to_capnp(&self, mut builder: Self::Builder) {
3653        let trader_id_builder = builder.reborrow().init_trader_id();
3654        self.trader_id.to_capnp(trader_id_builder);
3655
3656        let strategy_id_builder = builder.reborrow().init_strategy_id();
3657        self.strategy_id.to_capnp(strategy_id_builder);
3658
3659        let instrument_id_builder = builder.reborrow().init_instrument_id();
3660        self.instrument_id.to_capnp(instrument_id_builder);
3661
3662        let client_order_id_builder = builder.reborrow().init_client_order_id();
3663        self.client_order_id.to_capnp(client_order_id_builder);
3664
3665        builder.set_order_side(order_side_to_capnp(self.order_side));
3666        builder.set_order_type(order_type_to_capnp(self.order_type));
3667
3668        let quantity_builder = builder.reborrow().init_quantity();
3669        self.quantity.to_capnp(quantity_builder);
3670
3671        builder.set_time_in_force(time_in_force_to_capnp(self.time_in_force));
3672        builder.set_post_only(self.post_only);
3673        builder.set_reduce_only(self.reduce_only);
3674        builder.set_quote_quantity(self.quote_quantity);
3675        builder.set_reconciliation(self.reconciliation);
3676
3677        let event_id_builder = builder.reborrow().init_event_id();
3678        self.event_id.to_capnp(event_id_builder);
3679
3680        let mut ts_event_builder = builder.reborrow().init_ts_event();
3681        ts_event_builder.set_value(*self.ts_event);
3682
3683        let mut ts_init_builder = builder.reborrow().init_ts_init();
3684        ts_init_builder.set_value(*self.ts_init);
3685
3686        // Optional fields
3687        if let Some(price) = self.price {
3688            let price_builder = builder.reborrow().init_price();
3689            price.to_capnp(price_builder);
3690        }
3691
3692        if let Some(trigger_price) = self.trigger_price {
3693            let trigger_price_builder = builder.reborrow().init_trigger_price();
3694            trigger_price.to_capnp(trigger_price_builder);
3695        }
3696
3697        if let Some(trigger_type) = self.trigger_type {
3698            builder.set_trigger_type(trigger_type_to_capnp(trigger_type));
3699        }
3700
3701        if let Some(limit_offset) = self.limit_offset {
3702            let limit_offset_builder = builder.reborrow().init_limit_offset();
3703            limit_offset.to_capnp(limit_offset_builder);
3704        }
3705
3706        if let Some(trailing_offset) = self.trailing_offset {
3707            let trailing_offset_builder = builder.reborrow().init_trailing_offset();
3708            trailing_offset.to_capnp(trailing_offset_builder);
3709        }
3710
3711        if let Some(trailing_offset_type) = self.trailing_offset_type {
3712            builder.set_trailing_offset_type(trailing_offset_type_to_capnp(trailing_offset_type));
3713        }
3714
3715        if let Some(expire_time) = self.expire_time {
3716            let mut expire_time_builder = builder.reborrow().init_expire_time();
3717            expire_time_builder.set_value(*expire_time);
3718        }
3719
3720        if let Some(display_qty) = self.display_qty {
3721            let display_qty_builder = builder.reborrow().init_display_qty();
3722            display_qty.to_capnp(display_qty_builder);
3723        }
3724
3725        if let Some(emulation_trigger) = self.emulation_trigger {
3726            builder.set_emulation_trigger(trigger_type_to_capnp(emulation_trigger));
3727        }
3728
3729        if let Some(trigger_instrument_id) = &self.trigger_instrument_id {
3730            let trigger_instrument_id_builder = builder.reborrow().init_trigger_instrument_id();
3731            trigger_instrument_id.to_capnp(trigger_instrument_id_builder);
3732        }
3733
3734        if let Some(contingency_type) = self.contingency_type {
3735            builder.set_contingency_type(contingency_type_to_capnp(contingency_type));
3736        }
3737
3738        if let Some(order_list_id) = &self.order_list_id {
3739            let order_list_id_builder = builder.reborrow().init_order_list_id();
3740            order_list_id.to_capnp(order_list_id_builder);
3741        }
3742
3743        if let Some(linked_order_ids) = &self.linked_order_ids {
3744            let mut linked_order_ids_builder = builder
3745                .reborrow()
3746                .init_linked_order_ids(linked_order_ids.len() as u32);
3747            for (i, order_id) in linked_order_ids.iter().enumerate() {
3748                let order_id_builder = linked_order_ids_builder.reborrow().get(i as u32);
3749                order_id.to_capnp(order_id_builder);
3750            }
3751        }
3752
3753        if let Some(parent_order_id) = &self.parent_order_id {
3754            let parent_order_id_builder = builder.reborrow().init_parent_order_id();
3755            parent_order_id.to_capnp(parent_order_id_builder);
3756        }
3757
3758        if let Some(exec_algorithm_id) = &self.exec_algorithm_id {
3759            let exec_algorithm_id_builder = builder.reborrow().init_exec_algorithm_id();
3760            exec_algorithm_id.to_capnp(exec_algorithm_id_builder);
3761        }
3762
3763        if let Some(exec_algorithm_params) = &self.exec_algorithm_params {
3764            let mut params_builder = builder.reborrow().init_exec_algorithm_params();
3765            let mut entries_builder = params_builder
3766                .reborrow()
3767                .init_entries(exec_algorithm_params.len() as u32);
3768            for (i, (key, value)) in exec_algorithm_params.iter().enumerate() {
3769                let mut entry_builder = entries_builder.reborrow().get(i as u32);
3770                entry_builder.set_key(key.as_str());
3771                entry_builder.set_value(value.as_str());
3772            }
3773        }
3774
3775        if let Some(exec_spawn_id) = &self.exec_spawn_id {
3776            let exec_spawn_id_builder = builder.reborrow().init_exec_spawn_id();
3777            exec_spawn_id.to_capnp(exec_spawn_id_builder);
3778        }
3779
3780        if let Some(tags) = &self.tags {
3781            let mut tags_builder = builder.reborrow().init_tags(tags.len() as u32);
3782            for (i, tag) in tags.iter().enumerate() {
3783                tags_builder.set(i as u32, tag.as_str());
3784            }
3785        }
3786    }
3787}
3788
3789impl<'a> FromCapnp<'a> for OrderInitialized {
3790    type Reader = order_capnp::order_initialized::Reader<'a>;
3791
3792    fn from_capnp(reader: Self::Reader) -> Result<Self, Box<dyn Error>> {
3793        let trader_id_reader = reader.get_trader_id()?;
3794        let trader_id = TraderId::from_capnp(trader_id_reader)?;
3795
3796        let strategy_id_reader = reader.get_strategy_id()?;
3797        let strategy_id = StrategyId::from_capnp(strategy_id_reader)?;
3798
3799        let instrument_id_reader = reader.get_instrument_id()?;
3800        let instrument_id = InstrumentId::from_capnp(instrument_id_reader)?;
3801
3802        let client_order_id_reader = reader.get_client_order_id()?;
3803        let client_order_id = ClientOrderId::from_capnp(client_order_id_reader)?;
3804
3805        let order_side = order_side_from_capnp(reader.get_order_side()?);
3806        let order_type = order_type_from_capnp(reader.get_order_type()?);
3807
3808        let quantity_reader = reader.get_quantity()?;
3809        let quantity = Quantity::from_capnp(quantity_reader)?;
3810
3811        let time_in_force = time_in_force_from_capnp(reader.get_time_in_force()?);
3812        let post_only = reader.get_post_only();
3813        let reduce_only = reader.get_reduce_only();
3814        let quote_quantity = reader.get_quote_quantity();
3815        let reconciliation = reader.get_reconciliation();
3816
3817        let event_id_reader = reader.get_event_id()?;
3818        let event_id = nautilus_core::UUID4::from_capnp(event_id_reader)?;
3819
3820        let ts_event_reader = reader.get_ts_event()?;
3821        let ts_event = ts_event_reader.get_value();
3822
3823        let ts_init_reader = reader.get_ts_init()?;
3824        let ts_init = ts_init_reader.get_value();
3825
3826        // Optional fields
3827        let price = if reader.has_price() {
3828            let price_reader = reader.get_price()?;
3829            Some(Price::from_capnp(price_reader)?)
3830        } else {
3831            None
3832        };
3833
3834        let trigger_price = if reader.has_trigger_price() {
3835            let trigger_price_reader = reader.get_trigger_price()?;
3836            Some(Price::from_capnp(trigger_price_reader)?)
3837        } else {
3838            None
3839        };
3840
3841        let trigger_type = match reader.get_trigger_type()? {
3842            enums_capnp::TriggerType::NoTrigger => None,
3843            other => Some(trigger_type_from_capnp(other)),
3844        };
3845
3846        let limit_offset = if reader.has_limit_offset() {
3847            let limit_offset_reader = reader.get_limit_offset()?;
3848            Some(Decimal::from_capnp(limit_offset_reader)?)
3849        } else {
3850            None
3851        };
3852
3853        let trailing_offset = if reader.has_trailing_offset() {
3854            let trailing_offset_reader = reader.get_trailing_offset()?;
3855            Some(Decimal::from_capnp(trailing_offset_reader)?)
3856        } else {
3857            None
3858        };
3859
3860        let trailing_offset_type = match reader.get_trailing_offset_type()? {
3861            enums_capnp::TrailingOffsetType::NoTrailingOffset => None,
3862            other => Some(trailing_offset_type_from_capnp(other)),
3863        };
3864
3865        let expire_time = if reader.has_expire_time() {
3866            let expire_time_reader = reader.get_expire_time()?;
3867            let value = expire_time_reader.get_value();
3868            Some(value.into())
3869        } else {
3870            None
3871        };
3872
3873        let display_qty = if reader.has_display_qty() {
3874            let display_qty_reader = reader.get_display_qty()?;
3875            Some(Quantity::from_capnp(display_qty_reader)?)
3876        } else {
3877            None
3878        };
3879
3880        let emulation_trigger = match reader.get_emulation_trigger()? {
3881            enums_capnp::TriggerType::NoTrigger => None,
3882            other => Some(trigger_type_from_capnp(other)),
3883        };
3884
3885        let trigger_instrument_id = if reader.has_trigger_instrument_id() {
3886            let trigger_instrument_id_reader = reader.get_trigger_instrument_id()?;
3887            Some(InstrumentId::from_capnp(trigger_instrument_id_reader)?)
3888        } else {
3889            None
3890        };
3891
3892        let contingency_type = match reader.get_contingency_type()? {
3893            enums_capnp::ContingencyType::NoContingency => None,
3894            other => Some(contingency_type_from_capnp(other)),
3895        };
3896
3897        let order_list_id = if reader.has_order_list_id() {
3898            let order_list_id_reader = reader.get_order_list_id()?;
3899            Some(OrderListId::from_capnp(order_list_id_reader)?)
3900        } else {
3901            None
3902        };
3903
3904        let linked_order_ids = if reader.has_linked_order_ids() {
3905            let linked_order_ids_reader = reader.get_linked_order_ids()?;
3906            let mut linked_order_ids = Vec::with_capacity(linked_order_ids_reader.len() as usize);
3907            for order_id_reader in linked_order_ids_reader {
3908                linked_order_ids.push(ClientOrderId::from_capnp(order_id_reader)?);
3909            }
3910            Some(linked_order_ids)
3911        } else {
3912            None
3913        };
3914
3915        let parent_order_id = if reader.has_parent_order_id() {
3916            let parent_order_id_reader = reader.get_parent_order_id()?;
3917            Some(ClientOrderId::from_capnp(parent_order_id_reader)?)
3918        } else {
3919            None
3920        };
3921
3922        let exec_algorithm_id = if reader.has_exec_algorithm_id() {
3923            let exec_algorithm_id_reader = reader.get_exec_algorithm_id()?;
3924            Some(ExecAlgorithmId::from_capnp(exec_algorithm_id_reader)?)
3925        } else {
3926            None
3927        };
3928
3929        let exec_algorithm_params = if reader.has_exec_algorithm_params() {
3930            let params_reader = reader.get_exec_algorithm_params()?;
3931            let entries_reader = params_reader.get_entries()?;
3932            let mut params = IndexMap::with_capacity(entries_reader.len() as usize);
3933            for entry_reader in entries_reader {
3934                let key = Ustr::from(entry_reader.get_key()?.to_str()?);
3935                let value = Ustr::from(entry_reader.get_value()?.to_str()?);
3936                params.insert(key, value);
3937            }
3938            Some(params)
3939        } else {
3940            None
3941        };
3942
3943        let exec_spawn_id = if reader.has_exec_spawn_id() {
3944            let exec_spawn_id_reader = reader.get_exec_spawn_id()?;
3945            Some(ClientOrderId::from_capnp(exec_spawn_id_reader)?)
3946        } else {
3947            None
3948        };
3949
3950        let tags = if reader.has_tags() {
3951            let tags_reader = reader.get_tags()?;
3952            let mut tags = Vec::with_capacity(tags_reader.len() as usize);
3953            for tag in tags_reader {
3954                tags.push(Ustr::from(tag?.to_str()?));
3955            }
3956            Some(tags)
3957        } else {
3958            None
3959        };
3960
3961        Ok(Self {
3962            trader_id,
3963            strategy_id,
3964            instrument_id,
3965            client_order_id,
3966            order_side,
3967            order_type,
3968            quantity,
3969            time_in_force,
3970            post_only,
3971            reduce_only,
3972            quote_quantity,
3973            reconciliation,
3974            event_id,
3975            ts_event: ts_event.into(),
3976            ts_init: ts_init.into(),
3977            price,
3978            trigger_price,
3979            trigger_type,
3980            limit_offset,
3981            trailing_offset,
3982            trailing_offset_type,
3983            expire_time,
3984            display_qty,
3985            emulation_trigger,
3986            trigger_instrument_id,
3987            contingency_type,
3988            order_list_id,
3989            linked_order_ids,
3990            parent_order_id,
3991            exec_algorithm_id,
3992            exec_algorithm_params,
3993            exec_spawn_id,
3994            tags,
3995        })
3996    }
3997}
3998
3999// PositionOpened
4000impl<'a> ToCapnp<'a> for PositionOpened {
4001    type Builder = position_capnp::position_opened::Builder<'a>;
4002
4003    fn to_capnp(&self, mut builder: Self::Builder) {
4004        let trader_id_builder = builder.reborrow().init_trader_id();
4005        self.trader_id.to_capnp(trader_id_builder);
4006
4007        let strategy_id_builder = builder.reborrow().init_strategy_id();
4008        self.strategy_id.to_capnp(strategy_id_builder);
4009
4010        let instrument_id_builder = builder.reborrow().init_instrument_id();
4011        self.instrument_id.to_capnp(instrument_id_builder);
4012
4013        let position_id_builder = builder.reborrow().init_position_id();
4014        self.position_id.to_capnp(position_id_builder);
4015
4016        let account_id_builder = builder.reborrow().init_account_id();
4017        self.account_id.to_capnp(account_id_builder);
4018
4019        let opening_order_id_builder = builder.reborrow().init_opening_order_id();
4020        self.opening_order_id.to_capnp(opening_order_id_builder);
4021
4022        builder.set_entry(order_side_to_capnp(self.entry));
4023        builder.set_side(position_side_to_capnp(self.side));
4024        builder.set_signed_qty(self.signed_qty);
4025
4026        let quantity_builder = builder.reborrow().init_quantity();
4027        self.quantity.to_capnp(quantity_builder);
4028
4029        let last_qty_builder = builder.reborrow().init_last_qty();
4030        self.last_qty.to_capnp(last_qty_builder);
4031
4032        let last_px_builder = builder.reborrow().init_last_px();
4033        self.last_px.to_capnp(last_px_builder);
4034
4035        let currency_builder = builder.reborrow().init_currency();
4036        self.currency.to_capnp(currency_builder);
4037
4038        builder.set_avg_px_open(self.avg_px_open);
4039
4040        let event_id_builder = builder.reborrow().init_event_id();
4041        self.event_id.to_capnp(event_id_builder);
4042
4043        let mut ts_event_builder = builder.reborrow().init_ts_event();
4044        ts_event_builder.set_value(*self.ts_event);
4045
4046        let mut ts_init_builder = builder.reborrow().init_ts_init();
4047        ts_init_builder.set_value(*self.ts_init);
4048    }
4049}
4050
4051impl<'a> FromCapnp<'a> for PositionOpened {
4052    type Reader = position_capnp::position_opened::Reader<'a>;
4053
4054    fn from_capnp(reader: Self::Reader) -> Result<Self, Box<dyn Error>> {
4055        let trader_id_reader = reader.get_trader_id()?;
4056        let trader_id = TraderId::from_capnp(trader_id_reader)?;
4057
4058        let strategy_id_reader = reader.get_strategy_id()?;
4059        let strategy_id = StrategyId::from_capnp(strategy_id_reader)?;
4060
4061        let instrument_id_reader = reader.get_instrument_id()?;
4062        let instrument_id = InstrumentId::from_capnp(instrument_id_reader)?;
4063
4064        let position_id_reader = reader.get_position_id()?;
4065        let position_id = PositionId::from_capnp(position_id_reader)?;
4066
4067        let account_id_reader = reader.get_account_id()?;
4068        let account_id = AccountId::from_capnp(account_id_reader)?;
4069
4070        let opening_order_id_reader = reader.get_opening_order_id()?;
4071        let opening_order_id = ClientOrderId::from_capnp(opening_order_id_reader)?;
4072
4073        let entry = order_side_from_capnp(reader.get_entry()?);
4074        let side = position_side_from_capnp(reader.get_side()?);
4075        let signed_qty = reader.get_signed_qty();
4076
4077        let quantity_reader = reader.get_quantity()?;
4078        let quantity = Quantity::from_capnp(quantity_reader)?;
4079
4080        let last_qty_reader = reader.get_last_qty()?;
4081        let last_qty = Quantity::from_capnp(last_qty_reader)?;
4082
4083        let last_px_reader = reader.get_last_px()?;
4084        let last_px = Price::from_capnp(last_px_reader)?;
4085
4086        let currency_reader = reader.get_currency()?;
4087        let currency = Currency::from_capnp(currency_reader)?;
4088
4089        let avg_px_open = reader.get_avg_px_open();
4090
4091        let event_id_reader = reader.get_event_id()?;
4092        let event_id = nautilus_core::UUID4::from_capnp(event_id_reader)?;
4093
4094        let ts_event_reader = reader.get_ts_event()?;
4095        let ts_event = ts_event_reader.get_value();
4096
4097        let ts_init_reader = reader.get_ts_init()?;
4098        let ts_init = ts_init_reader.get_value();
4099
4100        Ok(Self {
4101            trader_id,
4102            strategy_id,
4103            instrument_id,
4104            position_id,
4105            account_id,
4106            opening_order_id,
4107            entry,
4108            side,
4109            signed_qty,
4110            quantity,
4111            last_qty,
4112            last_px,
4113            currency,
4114            avg_px_open,
4115            event_id,
4116            ts_event: ts_event.into(),
4117            ts_init: ts_init.into(),
4118        })
4119    }
4120}
4121
4122// PositionChanged
4123impl<'a> ToCapnp<'a> for PositionChanged {
4124    type Builder = position_capnp::position_changed::Builder<'a>;
4125
4126    fn to_capnp(&self, mut builder: Self::Builder) {
4127        let trader_id_builder = builder.reborrow().init_trader_id();
4128        self.trader_id.to_capnp(trader_id_builder);
4129
4130        let strategy_id_builder = builder.reborrow().init_strategy_id();
4131        self.strategy_id.to_capnp(strategy_id_builder);
4132
4133        let instrument_id_builder = builder.reborrow().init_instrument_id();
4134        self.instrument_id.to_capnp(instrument_id_builder);
4135
4136        let position_id_builder = builder.reborrow().init_position_id();
4137        self.position_id.to_capnp(position_id_builder);
4138
4139        let account_id_builder = builder.reborrow().init_account_id();
4140        self.account_id.to_capnp(account_id_builder);
4141
4142        let opening_order_id_builder = builder.reborrow().init_opening_order_id();
4143        self.opening_order_id.to_capnp(opening_order_id_builder);
4144
4145        builder.set_entry(order_side_to_capnp(self.entry));
4146        builder.set_side(position_side_to_capnp(self.side));
4147        builder.set_signed_qty(self.signed_qty);
4148
4149        let quantity_builder = builder.reborrow().init_quantity();
4150        self.quantity.to_capnp(quantity_builder);
4151
4152        let peak_quantity_builder = builder.reborrow().init_peak_quantity();
4153        self.peak_quantity.to_capnp(peak_quantity_builder);
4154
4155        let last_qty_builder = builder.reborrow().init_last_qty();
4156        self.last_qty.to_capnp(last_qty_builder);
4157
4158        let last_px_builder = builder.reborrow().init_last_px();
4159        self.last_px.to_capnp(last_px_builder);
4160
4161        let currency_builder = builder.reborrow().init_currency();
4162        self.currency.to_capnp(currency_builder);
4163
4164        builder.set_avg_px_open(self.avg_px_open);
4165        builder.set_avg_px_close(self.avg_px_close.unwrap_or(f64::NAN));
4166        builder.set_realized_return(self.realized_return);
4167
4168        self.realized_pnl
4169            .write_capnp(|| builder.reborrow().init_realized_pnl());
4170
4171        let unrealized_pnl_builder = builder.reborrow().init_unrealized_pnl();
4172        self.unrealized_pnl.to_capnp(unrealized_pnl_builder);
4173
4174        let event_id_builder = builder.reborrow().init_event_id();
4175        self.event_id.to_capnp(event_id_builder);
4176
4177        let mut ts_opened_builder = builder.reborrow().init_ts_opened();
4178        ts_opened_builder.set_value(*self.ts_opened);
4179
4180        let mut ts_event_builder = builder.reborrow().init_ts_event();
4181        ts_event_builder.set_value(*self.ts_event);
4182
4183        let mut ts_init_builder = builder.reborrow().init_ts_init();
4184        ts_init_builder.set_value(*self.ts_init);
4185    }
4186}
4187
4188impl<'a> FromCapnp<'a> for PositionChanged {
4189    type Reader = position_capnp::position_changed::Reader<'a>;
4190
4191    fn from_capnp(reader: Self::Reader) -> Result<Self, Box<dyn Error>> {
4192        let trader_id_reader = reader.get_trader_id()?;
4193        let trader_id = TraderId::from_capnp(trader_id_reader)?;
4194
4195        let strategy_id_reader = reader.get_strategy_id()?;
4196        let strategy_id = StrategyId::from_capnp(strategy_id_reader)?;
4197
4198        let instrument_id_reader = reader.get_instrument_id()?;
4199        let instrument_id = InstrumentId::from_capnp(instrument_id_reader)?;
4200
4201        let position_id_reader = reader.get_position_id()?;
4202        let position_id = PositionId::from_capnp(position_id_reader)?;
4203
4204        let account_id_reader = reader.get_account_id()?;
4205        let account_id = AccountId::from_capnp(account_id_reader)?;
4206
4207        let opening_order_id_reader = reader.get_opening_order_id()?;
4208        let opening_order_id = ClientOrderId::from_capnp(opening_order_id_reader)?;
4209
4210        let entry = order_side_from_capnp(reader.get_entry()?);
4211        let side = position_side_from_capnp(reader.get_side()?);
4212        let signed_qty = reader.get_signed_qty();
4213
4214        let quantity_reader = reader.get_quantity()?;
4215        let quantity = Quantity::from_capnp(quantity_reader)?;
4216
4217        let peak_quantity_reader = reader.get_peak_quantity()?;
4218        let peak_quantity = Quantity::from_capnp(peak_quantity_reader)?;
4219
4220        let last_qty_reader = reader.get_last_qty()?;
4221        let last_qty = Quantity::from_capnp(last_qty_reader)?;
4222
4223        let last_px_reader = reader.get_last_px()?;
4224        let last_px = Price::from_capnp(last_px_reader)?;
4225
4226        let currency_reader = reader.get_currency()?;
4227        let currency = Currency::from_capnp(currency_reader)?;
4228
4229        let avg_px_open = reader.get_avg_px_open();
4230        let avg_px_close = {
4231            let value = reader.get_avg_px_close();
4232            if value.is_nan() { None } else { Some(value) }
4233        };
4234        let realized_return = reader.get_realized_return();
4235
4236        let realized_pnl = if reader.has_realized_pnl() {
4237            let realized_pnl_reader = reader.get_realized_pnl()?;
4238            Some(Money::from_capnp(realized_pnl_reader)?)
4239        } else {
4240            None
4241        };
4242
4243        let unrealized_pnl_reader = reader.get_unrealized_pnl()?;
4244        let unrealized_pnl = Money::from_capnp(unrealized_pnl_reader)?;
4245
4246        let event_id_reader = reader.get_event_id()?;
4247        let event_id = nautilus_core::UUID4::from_capnp(event_id_reader)?;
4248
4249        let ts_opened_reader = reader.get_ts_opened()?;
4250        let ts_opened = ts_opened_reader.get_value();
4251
4252        let ts_event_reader = reader.get_ts_event()?;
4253        let ts_event = ts_event_reader.get_value();
4254
4255        let ts_init_reader = reader.get_ts_init()?;
4256        let ts_init = ts_init_reader.get_value();
4257
4258        Ok(Self {
4259            trader_id,
4260            strategy_id,
4261            instrument_id,
4262            position_id,
4263            account_id,
4264            opening_order_id,
4265            entry,
4266            side,
4267            signed_qty,
4268            quantity,
4269            peak_quantity,
4270            last_qty,
4271            last_px,
4272            currency,
4273            avg_px_open,
4274            avg_px_close,
4275            realized_return,
4276            realized_pnl,
4277            unrealized_pnl,
4278            event_id,
4279            ts_opened: ts_opened.into(),
4280            ts_event: ts_event.into(),
4281            ts_init: ts_init.into(),
4282        })
4283    }
4284}
4285
4286// PositionClosed
4287impl<'a> ToCapnp<'a> for PositionClosed {
4288    type Builder = position_capnp::position_closed::Builder<'a>;
4289
4290    fn to_capnp(&self, mut builder: Self::Builder) {
4291        let trader_id_builder = builder.reborrow().init_trader_id();
4292        self.trader_id.to_capnp(trader_id_builder);
4293
4294        let strategy_id_builder = builder.reborrow().init_strategy_id();
4295        self.strategy_id.to_capnp(strategy_id_builder);
4296
4297        let instrument_id_builder = builder.reborrow().init_instrument_id();
4298        self.instrument_id.to_capnp(instrument_id_builder);
4299
4300        let position_id_builder = builder.reborrow().init_position_id();
4301        self.position_id.to_capnp(position_id_builder);
4302
4303        let account_id_builder = builder.reborrow().init_account_id();
4304        self.account_id.to_capnp(account_id_builder);
4305
4306        let opening_order_id_builder = builder.reborrow().init_opening_order_id();
4307        self.opening_order_id.to_capnp(opening_order_id_builder);
4308
4309        self.closing_order_id
4310            .write_capnp(|| builder.reborrow().init_closing_order_id());
4311
4312        builder.set_entry(order_side_to_capnp(self.entry));
4313        builder.set_side(position_side_to_capnp(self.side));
4314        builder.set_signed_qty(self.signed_qty);
4315
4316        let quantity_builder = builder.reborrow().init_quantity();
4317        self.quantity.to_capnp(quantity_builder);
4318
4319        let peak_quantity_builder = builder.reborrow().init_peak_quantity();
4320        self.peak_quantity.to_capnp(peak_quantity_builder);
4321
4322        let last_qty_builder = builder.reborrow().init_last_qty();
4323        self.last_qty.to_capnp(last_qty_builder);
4324
4325        let last_px_builder = builder.reborrow().init_last_px();
4326        self.last_px.to_capnp(last_px_builder);
4327
4328        let currency_builder = builder.reborrow().init_currency();
4329        self.currency.to_capnp(currency_builder);
4330
4331        builder.set_avg_px_open(self.avg_px_open);
4332        builder.set_avg_px_close(self.avg_px_close.unwrap_or(f64::NAN));
4333        builder.set_realized_return(self.realized_return);
4334
4335        self.realized_pnl
4336            .write_capnp(|| builder.reborrow().init_realized_pnl());
4337
4338        let unrealized_pnl_builder = builder.reborrow().init_unrealized_pnl();
4339        self.unrealized_pnl.to_capnp(unrealized_pnl_builder);
4340
4341        builder.set_duration(self.duration);
4342
4343        let event_id_builder = builder.reborrow().init_event_id();
4344        self.event_id.to_capnp(event_id_builder);
4345
4346        let mut ts_opened_builder = builder.reborrow().init_ts_opened();
4347        ts_opened_builder.set_value(*self.ts_opened);
4348
4349        if let Some(ts_closed) = self.ts_closed {
4350            let mut ts_closed_builder = builder.reborrow().init_ts_closed();
4351            ts_closed_builder.set_value(*ts_closed);
4352        }
4353
4354        let mut ts_event_builder = builder.reborrow().init_ts_event();
4355        ts_event_builder.set_value(*self.ts_event);
4356
4357        let mut ts_init_builder = builder.reborrow().init_ts_init();
4358        ts_init_builder.set_value(*self.ts_init);
4359    }
4360}
4361
4362impl<'a> FromCapnp<'a> for PositionClosed {
4363    type Reader = position_capnp::position_closed::Reader<'a>;
4364
4365    fn from_capnp(reader: Self::Reader) -> Result<Self, Box<dyn Error>> {
4366        let trader_id_reader = reader.get_trader_id()?;
4367        let trader_id = TraderId::from_capnp(trader_id_reader)?;
4368
4369        let strategy_id_reader = reader.get_strategy_id()?;
4370        let strategy_id = StrategyId::from_capnp(strategy_id_reader)?;
4371
4372        let instrument_id_reader = reader.get_instrument_id()?;
4373        let instrument_id = InstrumentId::from_capnp(instrument_id_reader)?;
4374
4375        let position_id_reader = reader.get_position_id()?;
4376        let position_id = PositionId::from_capnp(position_id_reader)?;
4377
4378        let account_id_reader = reader.get_account_id()?;
4379        let account_id = AccountId::from_capnp(account_id_reader)?;
4380
4381        let opening_order_id_reader = reader.get_opening_order_id()?;
4382        let opening_order_id = ClientOrderId::from_capnp(opening_order_id_reader)?;
4383
4384        let closing_order_id = read_optional_from_capnp(
4385            || reader.has_closing_order_id(),
4386            || reader.get_closing_order_id(),
4387        )?;
4388
4389        let entry = order_side_from_capnp(reader.get_entry()?);
4390        let side = position_side_from_capnp(reader.get_side()?);
4391        let signed_qty = reader.get_signed_qty();
4392
4393        let quantity_reader = reader.get_quantity()?;
4394        let quantity = Quantity::from_capnp(quantity_reader)?;
4395
4396        let peak_quantity_reader = reader.get_peak_quantity()?;
4397        let peak_quantity = Quantity::from_capnp(peak_quantity_reader)?;
4398
4399        let last_qty_reader = reader.get_last_qty()?;
4400        let last_qty = Quantity::from_capnp(last_qty_reader)?;
4401
4402        let last_px_reader = reader.get_last_px()?;
4403        let last_px = Price::from_capnp(last_px_reader)?;
4404
4405        let currency_reader = reader.get_currency()?;
4406        let currency = Currency::from_capnp(currency_reader)?;
4407
4408        let avg_px_open = reader.get_avg_px_open();
4409        let avg_px_close = {
4410            let value = reader.get_avg_px_close();
4411            if value.is_nan() { None } else { Some(value) }
4412        };
4413        let realized_return = reader.get_realized_return();
4414
4415        let realized_pnl = if reader.has_realized_pnl() {
4416            let realized_pnl_reader = reader.get_realized_pnl()?;
4417            Some(Money::from_capnp(realized_pnl_reader)?)
4418        } else {
4419            None
4420        };
4421
4422        let unrealized_pnl_reader = reader.get_unrealized_pnl()?;
4423        let unrealized_pnl = Money::from_capnp(unrealized_pnl_reader)?;
4424
4425        let duration = reader.get_duration();
4426
4427        let event_id_reader = reader.get_event_id()?;
4428        let event_id = nautilus_core::UUID4::from_capnp(event_id_reader)?;
4429
4430        let ts_opened_reader = reader.get_ts_opened()?;
4431        let ts_opened = ts_opened_reader.get_value();
4432
4433        let ts_closed = if reader.has_ts_closed() {
4434            let ts_closed_reader = reader.get_ts_closed()?;
4435            Some(ts_closed_reader.get_value().into())
4436        } else {
4437            None
4438        };
4439
4440        let ts_event_reader = reader.get_ts_event()?;
4441        let ts_event = ts_event_reader.get_value();
4442
4443        let ts_init_reader = reader.get_ts_init()?;
4444        let ts_init = ts_init_reader.get_value();
4445
4446        Ok(Self {
4447            trader_id,
4448            strategy_id,
4449            instrument_id,
4450            position_id,
4451            account_id,
4452            opening_order_id,
4453            closing_order_id,
4454            entry,
4455            side,
4456            signed_qty,
4457            quantity,
4458            peak_quantity,
4459            last_qty,
4460            last_px,
4461            currency,
4462            avg_px_open,
4463            avg_px_close,
4464            realized_return,
4465            realized_pnl,
4466            unrealized_pnl,
4467            duration,
4468            event_id,
4469            ts_opened: ts_opened.into(),
4470            ts_closed,
4471            ts_event: ts_event.into(),
4472            ts_init: ts_init.into(),
4473        })
4474    }
4475}
4476
4477// PositionAdjusted
4478impl<'a> ToCapnp<'a> for PositionAdjusted {
4479    type Builder = position_capnp::position_adjusted::Builder<'a>;
4480
4481    fn to_capnp(&self, mut builder: Self::Builder) {
4482        let trader_id_builder = builder.reborrow().init_trader_id();
4483        self.trader_id.to_capnp(trader_id_builder);
4484
4485        let strategy_id_builder = builder.reborrow().init_strategy_id();
4486        self.strategy_id.to_capnp(strategy_id_builder);
4487
4488        let instrument_id_builder = builder.reborrow().init_instrument_id();
4489        self.instrument_id.to_capnp(instrument_id_builder);
4490
4491        let position_id_builder = builder.reborrow().init_position_id();
4492        self.position_id.to_capnp(position_id_builder);
4493
4494        let account_id_builder = builder.reborrow().init_account_id();
4495        self.account_id.to_capnp(account_id_builder);
4496
4497        builder.set_adjustment_type(position_adjustment_type_to_capnp(self.adjustment_type));
4498
4499        if let Some(qty_change) = self.quantity_change {
4500            let (lo, mid, hi, flags) = decimal_to_parts(&qty_change);
4501            let mut qty_change_builder = builder.reborrow().init_quantity_change();
4502            qty_change_builder.set_lo(lo);
4503            qty_change_builder.set_mid(mid);
4504            qty_change_builder.set_hi(hi);
4505            qty_change_builder.set_flags(flags);
4506        }
4507
4508        if let Some(ref pnl) = self.pnl_change {
4509            let pnl_change_builder = builder.reborrow().init_pnl_change();
4510            pnl.to_capnp(pnl_change_builder);
4511        }
4512
4513        if let Some(reason) = self.reason {
4514            builder.set_reason(reason.as_str());
4515        }
4516
4517        let event_id_builder = builder.reborrow().init_event_id();
4518        self.event_id.to_capnp(event_id_builder);
4519
4520        let mut ts_event_builder = builder.reborrow().init_ts_event();
4521        ts_event_builder.set_value(*self.ts_event);
4522
4523        let mut ts_init_builder = builder.reborrow().init_ts_init();
4524        ts_init_builder.set_value(*self.ts_init);
4525    }
4526}
4527
4528impl<'a> FromCapnp<'a> for PositionAdjusted {
4529    type Reader = position_capnp::position_adjusted::Reader<'a>;
4530
4531    fn from_capnp(reader: Self::Reader) -> Result<Self, Box<dyn Error>> {
4532        let trader_id_reader = reader.get_trader_id()?;
4533        let trader_id = TraderId::from_capnp(trader_id_reader)?;
4534
4535        let strategy_id_reader = reader.get_strategy_id()?;
4536        let strategy_id = StrategyId::from_capnp(strategy_id_reader)?;
4537
4538        let instrument_id_reader = reader.get_instrument_id()?;
4539        let instrument_id = InstrumentId::from_capnp(instrument_id_reader)?;
4540
4541        let position_id_reader = reader.get_position_id()?;
4542        let position_id = PositionId::from_capnp(position_id_reader)?;
4543
4544        let account_id_reader = reader.get_account_id()?;
4545        let account_id = AccountId::from_capnp(account_id_reader)?;
4546
4547        let adjustment_type = position_adjustment_type_from_capnp(reader.get_adjustment_type()?);
4548
4549        let quantity_change = if reader.has_quantity_change() {
4550            let qty_change_reader = reader.get_quantity_change()?;
4551            Some(decimal_from_parts(
4552                qty_change_reader.get_lo(),
4553                qty_change_reader.get_mid(),
4554                qty_change_reader.get_hi(),
4555                qty_change_reader.get_flags(),
4556            ))
4557        } else {
4558            None
4559        };
4560
4561        let pnl_change = if reader.has_pnl_change() {
4562            let pnl_change_reader = reader.get_pnl_change()?;
4563            Some(Money::from_capnp(pnl_change_reader)?)
4564        } else {
4565            None
4566        };
4567
4568        let reason = if reader.has_reason() {
4569            Some(Ustr::from(reader.get_reason()?.to_str()?))
4570        } else {
4571            None
4572        };
4573
4574        let event_id_reader = reader.get_event_id()?;
4575        let event_id = nautilus_core::UUID4::from_capnp(event_id_reader)?;
4576
4577        let ts_event_reader = reader.get_ts_event()?;
4578        let ts_event = ts_event_reader.get_value();
4579
4580        let ts_init_reader = reader.get_ts_init()?;
4581        let ts_init = ts_init_reader.get_value();
4582
4583        Ok(Self {
4584            trader_id,
4585            strategy_id,
4586            instrument_id,
4587            position_id,
4588            account_id,
4589            adjustment_type,
4590            quantity_change,
4591            pnl_change,
4592            reason,
4593            event_id,
4594            ts_event: ts_event.into(),
4595            ts_init: ts_init.into(),
4596        })
4597    }
4598}
4599
4600#[cfg(test)]
4601mod tests {
4602    use capnp::message::Builder;
4603    use nautilus_core::UnixNanos;
4604    use nautilus_model::{data::stubs::*, events::order::stubs::*};
4605    use rstest::rstest;
4606    use rust_decimal::Decimal;
4607    use rust_decimal_macros::dec;
4608
4609    use super::*;
4610
4611    macro_rules! assert_capnp_roundtrip {
4612        ($value:expr, $builder:path, $reader:path, $ty:ty) => {{
4613            let expected: $ty = $value;
4614            let mut message = Builder::new_default();
4615            {
4616                let builder = message.init_root::<$builder>();
4617                expected.to_capnp(builder);
4618            }
4619            let reader = message
4620                .get_root_as_reader::<$reader>()
4621                .expect("capnp reader");
4622            let decoded = <$ty>::from_capnp(reader).expect("capnp decode");
4623            assert_eq!(expected, decoded);
4624        }};
4625    }
4626
4627    macro_rules! capnp_simple_roundtrip_test {
4628        ($name:ident, $value:expr, $builder:path, $reader:path, $ty:ty) => {
4629            #[rstest]
4630            fn $name() {
4631                assert_capnp_roundtrip!($value, $builder, $reader, $ty);
4632            }
4633        };
4634    }
4635
4636    macro_rules! order_fixture_roundtrip_test {
4637        ($name:ident, $fixture:ident, $ty:ty, $builder:path, $reader:path) => {
4638            #[rstest]
4639            fn $name($fixture: $ty) {
4640                assert_capnp_roundtrip!($fixture, $builder, $reader, $ty);
4641            }
4642        };
4643    }
4644
4645    #[rstest]
4646    fn test_instrument_id_roundtrip() {
4647        let instrument_id = InstrumentId::from("AAPL.NASDAQ");
4648        let bytes = serialize_instrument_id(&instrument_id).unwrap();
4649        let decoded = deserialize_instrument_id(&bytes).unwrap();
4650        assert_eq!(instrument_id, decoded);
4651    }
4652
4653    #[rstest]
4654    fn test_price_roundtrip() {
4655        let price = Price::from("123.45");
4656        let bytes = serialize_price(&price).unwrap();
4657        let decoded = deserialize_price(&bytes).unwrap();
4658        assert_eq!(price, decoded);
4659    }
4660
4661    #[rstest]
4662    fn test_quantity_roundtrip() {
4663        let qty = Quantity::from("100.5");
4664        let bytes = serialize_quantity(&qty).unwrap();
4665        let decoded = deserialize_quantity(&bytes).unwrap();
4666        assert_eq!(qty, decoded);
4667    }
4668
4669    #[rstest]
4670    fn test_currency_roundtrip() {
4671        let currency = Currency::USD();
4672        let bytes = serialize_currency(&currency).unwrap();
4673        let decoded = deserialize_currency(&bytes).unwrap();
4674        assert_eq!(currency, decoded);
4675    }
4676
4677    #[rstest]
4678    fn test_currency_crypto_roundtrip() {
4679        let currency = Currency::BTC();
4680        let bytes = serialize_currency(&currency).unwrap();
4681        let decoded = deserialize_currency(&bytes).unwrap();
4682        assert_eq!(currency, decoded);
4683    }
4684
4685    #[rstest]
4686    fn test_money_roundtrip() {
4687        let money = Money::from_raw(100_000_000, Currency::USD());
4688        let bytes = serialize_money(&money).unwrap();
4689        let decoded = deserialize_money(&bytes).unwrap();
4690        assert_eq!(money, decoded);
4691    }
4692
4693    #[rstest]
4694    fn test_money_negative() {
4695        let money = Money::from_raw(-50_000_000, Currency::USD());
4696        let bytes = serialize_money(&money).unwrap();
4697        let decoded = deserialize_money(&bytes).unwrap();
4698        assert_eq!(money, decoded);
4699    }
4700
4701    #[rstest]
4702    fn test_money_zero() {
4703        let money = Money::from_raw(0, Currency::USD());
4704        let bytes = serialize_money(&money).unwrap();
4705        let decoded = deserialize_money(&bytes).unwrap();
4706        assert_eq!(money, decoded);
4707    }
4708
4709    #[rstest]
4710    fn test_decimal_serialization_layout() {
4711        let decimal = Decimal::from_parts(
4712            0x89ab_cdef,
4713            0x0123_4567,
4714            0x0fed_cba9,
4715            true, // negative to ensure sign bit set
4716            6,    // add some scale metadata
4717        );
4718        let mut message = capnp::message::Builder::new_default();
4719        {
4720            let builder = message.init_root::<types_capnp::decimal::Builder>();
4721            decimal.to_capnp(builder);
4722        }
4723
4724        let reader = message
4725            .get_root_as_reader::<types_capnp::decimal::Reader>()
4726            .expect("reader");
4727
4728        let serialized = decimal.serialize();
4729        let expected_flags = u32::from_le_bytes(serialized[0..4].try_into().expect("flags slice"));
4730
4731        assert_eq!(reader.get_flags(), expected_flags);
4732        assert_eq!(reader.get_lo(), 0x89ab_cdef);
4733        assert_eq!(reader.get_mid(), 0x0123_4567);
4734        assert_eq!(reader.get_hi(), 0x0fed_cba9);
4735    }
4736
4737    #[rstest]
4738    fn test_decimal_roundtrip_preserves_scale_and_sign() {
4739        let decimal = Decimal::from_parts(0xffff_ffff, 0x7fff_ffff, 0x0000_00ff, false, 9);
4740
4741        let mut message = capnp::message::Builder::new_default();
4742        {
4743            let builder = message.init_root::<types_capnp::decimal::Builder>();
4744            decimal.to_capnp(builder);
4745        }
4746
4747        let reader = message
4748            .get_root_as_reader::<types_capnp::decimal::Reader>()
4749            .expect("reader");
4750        let decoded = Decimal::from_capnp(reader).expect("decoded decimal");
4751        assert_eq!(decimal, decoded);
4752    }
4753
4754    #[rstest]
4755    fn test_account_balance_roundtrip() {
4756        let total = Money::new(100.0, Currency::USD());
4757        let locked = Money::new(10.0, Currency::USD());
4758        let free = Money::new(90.0, Currency::USD());
4759        let balance = AccountBalance::new(total, locked, free);
4760        let bytes = serialize_account_balance(&balance).unwrap();
4761        let decoded = deserialize_account_balance(&bytes).unwrap();
4762        assert_eq!(balance, decoded);
4763    }
4764
4765    #[rstest]
4766    fn test_margin_balance_roundtrip() {
4767        let initial = Money::new(500.0, Currency::USD());
4768        let maintenance = Money::new(250.0, Currency::USD());
4769        let instrument_id = InstrumentId::from("BTC-USD-PERP.BINANCE");
4770        let balance = MarginBalance::new(initial, maintenance, Some(instrument_id));
4771        let bytes = serialize_margin_balance(&balance).unwrap();
4772        let decoded = deserialize_margin_balance(&bytes).unwrap();
4773        assert_eq!(balance, decoded);
4774    }
4775
4776    #[rstest]
4777    fn test_margin_balance_account_scope_roundtrip() {
4778        let initial = Money::new(500.0, Currency::USD());
4779        let maintenance = Money::new(250.0, Currency::USD());
4780        let balance = MarginBalance::new(initial, maintenance, None);
4781        let bytes = serialize_margin_balance(&balance).unwrap();
4782        let decoded = deserialize_margin_balance(&bytes).unwrap();
4783        assert_eq!(balance, decoded);
4784        assert!(decoded.instrument_id.is_none());
4785    }
4786
4787    // Identifier round-trip coverage
4788    capnp_simple_roundtrip_test!(
4789        trader_id_capnp_roundtrip,
4790        TraderId::from("TRADER-CAPNP"),
4791        identifiers_capnp::trader_id::Builder,
4792        identifiers_capnp::trader_id::Reader,
4793        TraderId
4794    );
4795    capnp_simple_roundtrip_test!(
4796        strategy_id_capnp_roundtrip,
4797        StrategyId::from("STRATEGY-CAPNP"),
4798        identifiers_capnp::strategy_id::Builder,
4799        identifiers_capnp::strategy_id::Reader,
4800        StrategyId
4801    );
4802    capnp_simple_roundtrip_test!(
4803        actor_id_capnp_roundtrip,
4804        ActorId::from("ACTOR-CAPNP"),
4805        identifiers_capnp::actor_id::Builder,
4806        identifiers_capnp::actor_id::Reader,
4807        ActorId
4808    );
4809    capnp_simple_roundtrip_test!(
4810        account_id_capnp_roundtrip,
4811        AccountId::from("ACCOUNT-CAPNP"),
4812        identifiers_capnp::account_id::Builder,
4813        identifiers_capnp::account_id::Reader,
4814        AccountId
4815    );
4816    capnp_simple_roundtrip_test!(
4817        client_id_capnp_roundtrip,
4818        ClientId::from("CLIENT-CAPNP"),
4819        identifiers_capnp::client_id::Builder,
4820        identifiers_capnp::client_id::Reader,
4821        ClientId
4822    );
4823    capnp_simple_roundtrip_test!(
4824        client_order_id_capnp_roundtrip,
4825        ClientOrderId::from("O-20240101-000000-001-001-1"),
4826        identifiers_capnp::client_order_id::Builder,
4827        identifiers_capnp::client_order_id::Reader,
4828        ClientOrderId
4829    );
4830    capnp_simple_roundtrip_test!(
4831        venue_order_id_capnp_roundtrip,
4832        VenueOrderId::from("V-ORDER-1"),
4833        identifiers_capnp::venue_order_id::Builder,
4834        identifiers_capnp::venue_order_id::Reader,
4835        VenueOrderId
4836    );
4837    capnp_simple_roundtrip_test!(
4838        trade_id_capnp_roundtrip,
4839        TradeId::from("TRADE-12345"),
4840        identifiers_capnp::trade_id::Builder,
4841        identifiers_capnp::trade_id::Reader,
4842        TradeId
4843    );
4844    capnp_simple_roundtrip_test!(
4845        position_id_capnp_roundtrip,
4846        PositionId::from("POSITION-1"),
4847        identifiers_capnp::position_id::Builder,
4848        identifiers_capnp::position_id::Reader,
4849        PositionId
4850    );
4851    capnp_simple_roundtrip_test!(
4852        exec_algorithm_id_capnp_roundtrip,
4853        ExecAlgorithmId::from("EXEC-1"),
4854        identifiers_capnp::exec_algorithm_id::Builder,
4855        identifiers_capnp::exec_algorithm_id::Reader,
4856        ExecAlgorithmId
4857    );
4858    capnp_simple_roundtrip_test!(
4859        component_id_capnp_roundtrip,
4860        ComponentId::from("COMPONENT-RISK"),
4861        identifiers_capnp::component_id::Builder,
4862        identifiers_capnp::component_id::Reader,
4863        ComponentId
4864    );
4865    capnp_simple_roundtrip_test!(
4866        order_list_id_capnp_roundtrip,
4867        OrderListId::from("LIST-1"),
4868        identifiers_capnp::order_list_id::Builder,
4869        identifiers_capnp::order_list_id::Reader,
4870        OrderListId
4871    );
4872    capnp_simple_roundtrip_test!(
4873        symbol_capnp_roundtrip,
4874        Symbol::from("ETH-PERP"),
4875        identifiers_capnp::symbol::Builder,
4876        identifiers_capnp::symbol::Reader,
4877        Symbol
4878    );
4879    capnp_simple_roundtrip_test!(
4880        venue_capnp_roundtrip,
4881        Venue::from("BINANCE"),
4882        identifiers_capnp::venue::Builder,
4883        identifiers_capnp::venue::Reader,
4884        Venue
4885    );
4886    capnp_simple_roundtrip_test!(
4887        uuid4_capnp_roundtrip,
4888        uuid4(),
4889        base_capnp::u_u_i_d4::Builder,
4890        base_capnp::u_u_i_d4::Reader,
4891        nautilus_core::UUID4
4892    );
4893
4894    // Market data structures
4895    capnp_simple_roundtrip_test!(
4896        quote_tick_capnp_roundtrip,
4897        quote_ethusdt_binance(),
4898        market_capnp::quote_tick::Builder,
4899        market_capnp::quote_tick::Reader,
4900        QuoteTick
4901    );
4902    capnp_simple_roundtrip_test!(
4903        trade_tick_capnp_roundtrip,
4904        stub_trade_ethusdt_buyer(),
4905        market_capnp::trade_tick::Builder,
4906        market_capnp::trade_tick::Reader,
4907        TradeTick
4908    );
4909    capnp_simple_roundtrip_test!(
4910        bar_specification_capnp_roundtrip,
4911        sample_bar_specification(),
4912        market_capnp::bar_spec::Builder,
4913        market_capnp::bar_spec::Reader,
4914        BarSpecification
4915    );
4916    capnp_simple_roundtrip_test!(
4917        bar_type_standard_capnp_roundtrip,
4918        sample_bar_type_standard(),
4919        market_capnp::bar_type::Builder,
4920        market_capnp::bar_type::Reader,
4921        BarType
4922    );
4923    capnp_simple_roundtrip_test!(
4924        bar_capnp_roundtrip,
4925        stub_bar(),
4926        market_capnp::bar::Builder,
4927        market_capnp::bar::Reader,
4928        Bar
4929    );
4930    capnp_simple_roundtrip_test!(
4931        book_order_capnp_roundtrip,
4932        stub_book_order(),
4933        market_capnp::book_order::Builder,
4934        market_capnp::book_order::Reader,
4935        BookOrder
4936    );
4937    capnp_simple_roundtrip_test!(
4938        order_book_delta_capnp_roundtrip,
4939        stub_delta(),
4940        market_capnp::order_book_delta::Builder,
4941        market_capnp::order_book_delta::Reader,
4942        OrderBookDelta
4943    );
4944    capnp_simple_roundtrip_test!(
4945        order_book_deltas_capnp_roundtrip,
4946        stub_deltas(),
4947        market_capnp::order_book_deltas::Builder,
4948        market_capnp::order_book_deltas::Reader,
4949        OrderBookDeltas
4950    );
4951    capnp_simple_roundtrip_test!(
4952        order_book_depth10_capnp_roundtrip,
4953        sample_order_book_depth10(),
4954        market_capnp::order_book_depth10::Builder,
4955        market_capnp::order_book_depth10::Reader,
4956        OrderBookDepth10
4957    );
4958    capnp_simple_roundtrip_test!(
4959        mark_price_update_capnp_roundtrip,
4960        sample_mark_price_update(),
4961        market_capnp::mark_price_update::Builder,
4962        market_capnp::mark_price_update::Reader,
4963        MarkPriceUpdate
4964    );
4965    capnp_simple_roundtrip_test!(
4966        index_price_update_capnp_roundtrip,
4967        sample_index_price_update(),
4968        market_capnp::index_price_update::Builder,
4969        market_capnp::index_price_update::Reader,
4970        IndexPriceUpdate
4971    );
4972    capnp_simple_roundtrip_test!(
4973        funding_rate_update_capnp_roundtrip,
4974        sample_funding_rate_update(),
4975        market_capnp::funding_rate_update::Builder,
4976        market_capnp::funding_rate_update::Reader,
4977        FundingRateUpdate
4978    );
4979    capnp_simple_roundtrip_test!(
4980        instrument_close_capnp_roundtrip,
4981        stub_instrument_close(),
4982        market_capnp::instrument_close::Builder,
4983        market_capnp::instrument_close::Reader,
4984        InstrumentClose
4985    );
4986    capnp_simple_roundtrip_test!(
4987        instrument_status_capnp_roundtrip,
4988        sample_instrument_status_event(),
4989        market_capnp::instrument_status::Builder,
4990        market_capnp::instrument_status::Reader,
4991        InstrumentStatus
4992    );
4993
4994    // Order-event coverage through fixtures
4995    order_fixture_roundtrip_test!(
4996        order_filled_capnp_roundtrip,
4997        order_filled,
4998        OrderFilled,
4999        order_capnp::order_filled::Builder,
5000        order_capnp::order_filled::Reader
5001    );
5002    order_fixture_roundtrip_test!(
5003        order_denied_capnp_roundtrip,
5004        order_denied_max_submitted_rate,
5005        OrderDenied,
5006        order_capnp::order_denied::Builder,
5007        order_capnp::order_denied::Reader
5008    );
5009    order_fixture_roundtrip_test!(
5010        order_rejected_capnp_roundtrip,
5011        order_rejected_insufficient_margin,
5012        OrderRejected,
5013        order_capnp::order_rejected::Builder,
5014        order_capnp::order_rejected::Reader
5015    );
5016    order_fixture_roundtrip_test!(
5017        order_initialized_capnp_roundtrip,
5018        order_initialized_buy_limit,
5019        OrderInitialized,
5020        order_capnp::order_initialized::Builder,
5021        order_capnp::order_initialized::Reader
5022    );
5023    order_fixture_roundtrip_test!(
5024        order_submitted_capnp_roundtrip,
5025        order_submitted,
5026        OrderSubmitted,
5027        order_capnp::order_submitted::Builder,
5028        order_capnp::order_submitted::Reader
5029    );
5030    order_fixture_roundtrip_test!(
5031        order_triggered_capnp_roundtrip,
5032        order_triggered,
5033        OrderTriggered,
5034        order_capnp::order_triggered::Builder,
5035        order_capnp::order_triggered::Reader
5036    );
5037    order_fixture_roundtrip_test!(
5038        order_emulated_capnp_roundtrip,
5039        order_emulated,
5040        OrderEmulated,
5041        order_capnp::order_emulated::Builder,
5042        order_capnp::order_emulated::Reader
5043    );
5044    order_fixture_roundtrip_test!(
5045        order_released_capnp_roundtrip,
5046        order_released,
5047        OrderReleased,
5048        order_capnp::order_released::Builder,
5049        order_capnp::order_released::Reader
5050    );
5051    order_fixture_roundtrip_test!(
5052        order_updated_capnp_roundtrip,
5053        order_updated,
5054        OrderUpdated,
5055        order_capnp::order_updated::Builder,
5056        order_capnp::order_updated::Reader
5057    );
5058    order_fixture_roundtrip_test!(
5059        order_pending_update_capnp_roundtrip,
5060        order_pending_update,
5061        OrderPendingUpdate,
5062        order_capnp::order_pending_update::Builder,
5063        order_capnp::order_pending_update::Reader
5064    );
5065    order_fixture_roundtrip_test!(
5066        order_pending_cancel_capnp_roundtrip,
5067        order_pending_cancel,
5068        OrderPendingCancel,
5069        order_capnp::order_pending_cancel::Builder,
5070        order_capnp::order_pending_cancel::Reader
5071    );
5072    order_fixture_roundtrip_test!(
5073        order_modify_rejected_capnp_roundtrip,
5074        order_modify_rejected,
5075        OrderModifyRejected,
5076        order_capnp::order_modify_rejected::Builder,
5077        order_capnp::order_modify_rejected::Reader
5078    );
5079    order_fixture_roundtrip_test!(
5080        order_accepted_capnp_roundtrip,
5081        order_accepted,
5082        OrderAccepted,
5083        order_capnp::order_accepted::Builder,
5084        order_capnp::order_accepted::Reader
5085    );
5086    order_fixture_roundtrip_test!(
5087        order_cancel_rejected_capnp_roundtrip,
5088        order_cancel_rejected,
5089        OrderCancelRejected,
5090        order_capnp::order_cancel_rejected::Builder,
5091        order_capnp::order_cancel_rejected::Reader
5092    );
5093    order_fixture_roundtrip_test!(
5094        order_expired_capnp_roundtrip,
5095        order_expired,
5096        OrderExpired,
5097        order_capnp::order_expired::Builder,
5098        order_capnp::order_expired::Reader
5099    );
5100    #[rstest]
5101    fn order_canceled_capnp_roundtrip() {
5102        assert_capnp_roundtrip!(
5103            sample_order_canceled(),
5104            order_capnp::order_canceled::Builder,
5105            order_capnp::order_canceled::Reader,
5106            OrderCanceled
5107        );
5108    }
5109
5110    // Position event coverage
5111    #[rstest]
5112    fn position_opened_capnp_roundtrip() {
5113        assert_capnp_roundtrip!(
5114            sample_position_opened(),
5115            position_capnp::position_opened::Builder,
5116            position_capnp::position_opened::Reader,
5117            PositionOpened
5118        );
5119    }
5120
5121    #[rstest]
5122    fn position_changed_capnp_roundtrip() {
5123        assert_capnp_roundtrip!(
5124            sample_position_changed(),
5125            position_capnp::position_changed::Builder,
5126            position_capnp::position_changed::Reader,
5127            PositionChanged
5128        );
5129    }
5130
5131    #[rstest]
5132    fn position_closed_capnp_roundtrip() {
5133        assert_capnp_roundtrip!(
5134            sample_position_closed(),
5135            position_capnp::position_closed::Builder,
5136            position_capnp::position_closed::Reader,
5137            PositionClosed
5138        );
5139    }
5140
5141    #[rstest]
5142    fn position_adjusted_capnp_roundtrip() {
5143        assert_capnp_roundtrip!(
5144            sample_position_adjusted(),
5145            position_capnp::position_adjusted::Builder,
5146            position_capnp::position_adjusted::Reader,
5147            PositionAdjusted
5148        );
5149    }
5150
5151    fn sample_bar_specification() -> BarSpecification {
5152        BarSpecification::new(5, BarAggregation::Minute, PriceType::Last)
5153    }
5154
5155    fn sample_bar_type_standard() -> BarType {
5156        BarType::new(
5157            InstrumentId::from("AUDUSD.SIM"),
5158            sample_bar_specification(),
5159            AggregationSource::External,
5160        )
5161    }
5162
5163    fn sample_mark_price_update() -> MarkPriceUpdate {
5164        MarkPriceUpdate::new(
5165            InstrumentId::from("BTCUSD-PERP.BINANCE"),
5166            Price::from("42000.123"),
5167            UnixNanos::from(1),
5168            UnixNanos::from(2),
5169        )
5170    }
5171
5172    fn sample_index_price_update() -> IndexPriceUpdate {
5173        IndexPriceUpdate::new(
5174            InstrumentId::from("BTCUSD-PERP.BINANCE"),
5175            Price::from("41950.500"),
5176            UnixNanos::from(3),
5177            UnixNanos::from(4),
5178        )
5179    }
5180
5181    fn sample_funding_rate_update() -> FundingRateUpdate {
5182        FundingRateUpdate::new(
5183            InstrumentId::from("BTCUSD-PERP.BINANCE"),
5184            dec!(0.0001),
5185            Some(60),
5186            Some(UnixNanos::from(1_000_000)),
5187            UnixNanos::from(5),
5188            UnixNanos::from(6),
5189        )
5190    }
5191
5192    fn sample_instrument_status_event() -> InstrumentStatus {
5193        InstrumentStatus::new(
5194            InstrumentId::from("MSFT.XNAS"),
5195            MarketStatusAction::Trading,
5196            UnixNanos::from(1),
5197            UnixNanos::from(2),
5198            Some(Ustr::from("Normal trading")),
5199            Some(Ustr::from("MARKET_OPEN")),
5200            Some(true),
5201            Some(true),
5202            Some(false),
5203        )
5204    }
5205
5206    fn sample_order_canceled() -> OrderCanceled {
5207        OrderCanceled::new(
5208            trader_id(),
5209            strategy_id_ema_cross(),
5210            instrument_id_btc_usdt(),
5211            client_order_id(),
5212            uuid4(),
5213            UnixNanos::from(7),
5214            UnixNanos::from(8),
5215            true,
5216            Some(venue_order_id()),
5217            Some(account_id()),
5218        )
5219    }
5220
5221    fn sample_order_book_depth10() -> OrderBookDepth10 {
5222        const LEVELS: usize = 10;
5223        let instrument_id = InstrumentId::from("AAPL.XNAS");
5224        let mut bids = [BookOrder::default(); LEVELS];
5225        let mut asks = [BookOrder::default(); LEVELS];
5226        for i in 0..LEVELS {
5227            bids[i] = BookOrder::new(
5228                OrderSide::Buy,
5229                Price::new(100.0 - i as f64, 2),
5230                Quantity::new(1.0 + i as f64, 2),
5231                0,
5232            );
5233            asks[i] = BookOrder::new(
5234                OrderSide::Sell,
5235                Price::new(101.0 + i as f64, 2),
5236                Quantity::new(1.0 + i as f64, 2),
5237                0,
5238            );
5239        }
5240        let bid_counts = [1_u32; LEVELS];
5241        let ask_counts = [1_u32; LEVELS];
5242        OrderBookDepth10::new(
5243            instrument_id,
5244            bids,
5245            asks,
5246            bid_counts,
5247            ask_counts,
5248            0,
5249            1,
5250            UnixNanos::from(9),
5251            UnixNanos::from(10),
5252        )
5253    }
5254
5255    fn sample_position_opened() -> PositionOpened {
5256        PositionOpened {
5257            trader_id: trader_id(),
5258            strategy_id: strategy_id_ema_cross(),
5259            instrument_id: instrument_id_btc_usdt(),
5260            position_id: PositionId::from("P-OPEN"),
5261            account_id: account_id(),
5262            opening_order_id: client_order_id(),
5263            entry: OrderSide::Buy,
5264            side: PositionSide::Long,
5265            signed_qty: 100.0,
5266            quantity: Quantity::from("100"),
5267            last_qty: Quantity::from("100"),
5268            last_px: Price::from("20000"),
5269            currency: Currency::USD(),
5270            avg_px_open: 20000.0,
5271            event_id: uuid4(),
5272            ts_event: UnixNanos::from(9),
5273            ts_init: UnixNanos::from(10),
5274        }
5275    }
5276
5277    fn sample_position_changed() -> PositionChanged {
5278        PositionChanged {
5279            trader_id: trader_id(),
5280            strategy_id: strategy_id_ema_cross(),
5281            instrument_id: instrument_id_btc_usdt(),
5282            position_id: PositionId::from("P-CHANGED"),
5283            account_id: account_id(),
5284            opening_order_id: client_order_id(),
5285            entry: OrderSide::Buy,
5286            side: PositionSide::Long,
5287            signed_qty: 150.0,
5288            quantity: Quantity::from("150"),
5289            peak_quantity: Quantity::from("175"),
5290            last_qty: Quantity::from("50"),
5291            last_px: Price::from("20100"),
5292            currency: Currency::USD(),
5293            avg_px_open: 19950.0,
5294            avg_px_close: Some(20100.0),
5295            realized_return: 0.01,
5296            realized_pnl: Some(Money::new(150.0, Currency::USD())),
5297            unrealized_pnl: Money::new(75.0, Currency::USD()),
5298            event_id: uuid4(),
5299            ts_opened: UnixNanos::from(11),
5300            ts_event: UnixNanos::from(12),
5301            ts_init: UnixNanos::from(13),
5302        }
5303    }
5304
5305    fn sample_position_closed() -> PositionClosed {
5306        PositionClosed {
5307            trader_id: trader_id(),
5308            strategy_id: strategy_id_ema_cross(),
5309            instrument_id: instrument_id_btc_usdt(),
5310            position_id: PositionId::from("P-CLOSED"),
5311            account_id: account_id(),
5312            opening_order_id: client_order_id(),
5313            closing_order_id: Some(ClientOrderId::from("O-19700101-000000-001-001-9")),
5314            entry: OrderSide::Buy,
5315            side: PositionSide::Flat,
5316            signed_qty: 0.0,
5317            quantity: Quantity::from("0"),
5318            peak_quantity: Quantity::from("200"),
5319            last_qty: Quantity::from("200"),
5320            last_px: Price::from("20500"),
5321            currency: Currency::USD(),
5322            avg_px_open: 20000.0,
5323            avg_px_close: Some(20500.0),
5324            realized_return: 0.025,
5325            realized_pnl: Some(Money::new(1000.0, Currency::USD())),
5326            unrealized_pnl: Money::new(0.0, Currency::USD()),
5327            duration: 1_000_000,
5328            event_id: uuid4(),
5329            ts_opened: UnixNanos::from(14),
5330            ts_closed: Some(UnixNanos::from(15)),
5331            ts_event: UnixNanos::from(15),
5332            ts_init: UnixNanos::from(16),
5333        }
5334    }
5335
5336    fn sample_position_adjusted() -> PositionAdjusted {
5337        PositionAdjusted::new(
5338            trader_id(),
5339            strategy_id_ema_cross(),
5340            instrument_id_btc_usdt(),
5341            PositionId::from("P-ADJUST"),
5342            account_id(),
5343            PositionAdjustmentType::Funding,
5344            Some(dec!(-0.001)),
5345            Some(Money::new(-5.5, Currency::USD())),
5346            Some(Ustr::from("funding_2024-01-15")),
5347            uuid4(),
5348            UnixNanos::from(17),
5349            UnixNanos::from(18),
5350        )
5351    }
5352}