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