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