Skip to main content

nautilus_serialization/capnp/
conversions.rs

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