nautilus_serialization/capnp/
conversions.rs

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