Skip to main content

nautilus_serialization/capnp/
instruments.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 instruments and Cap'n Proto.
17
18use std::error::Error;
19
20use nautilus_core::{Params, UnixNanos};
21use nautilus_model::{
22    identifiers::{InstrumentId, Symbol},
23    instruments::{
24        BettingInstrument, BinaryOption, Cfd, Commodity, CryptoFuture, CryptoFuturesSpread,
25        CryptoOption, CryptoOptionSpread, CryptoPerpetual, CurrencyPair, Equity, FuturesContract,
26        FuturesSpread, IndexInstrument, InstrumentAny, OptionContract, OptionSpread,
27        PerpetualContract, SyntheticInstrument, TokenizedAsset,
28    },
29    types::{Currency, Price, Quantity},
30};
31use rust_decimal::Decimal;
32use ustr::Ustr;
33
34use super::{
35    FromCapnp, ToCapnp,
36    conversions::{
37        CapnpWriteExt, asset_class_from_capnp, asset_class_to_capnp, option_kind_from_capnp,
38        option_kind_to_capnp, read_optional_from_capnp,
39    },
40};
41use crate::{base_capnp, instruments_capnp};
42
43fn write_unix_nanos(value: UnixNanos, mut builder: base_capnp::unix_nanos::Builder<'_>) {
44    builder.set_value(*value);
45}
46
47fn read_unix_nanos<'a>(
48    get: impl FnOnce() -> capnp::Result<base_capnp::unix_nanos::Reader<'a>>,
49) -> Result<UnixNanos, Box<dyn Error>> {
50    Ok(get()?.get_value().into())
51}
52
53fn write_optional_ustr(value: Option<Ustr>, mut set: impl FnMut(&str)) {
54    if let Some(value) = value {
55        set(value.as_str());
56    }
57}
58
59fn read_optional_ustr<'a>(
60    has: bool,
61    get: impl FnOnce() -> capnp::Result<capnp::text::Reader<'a>>,
62) -> Result<Option<Ustr>, Box<dyn Error>> {
63    if has {
64        Ok(Some(Ustr::from(get()?.to_str()?)))
65    } else {
66        Ok(None)
67    }
68}
69
70fn read_ustr<'a>(
71    get: impl FnOnce() -> capnp::Result<capnp::text::Reader<'a>>,
72) -> Result<Ustr, Box<dyn Error>> {
73    Ok(Ustr::from(get()?.to_str()?))
74}
75
76fn write_optional_info(info: Option<&Params>, mut set: impl FnMut(&[u8])) {
77    if let Some(info) = info {
78        let bytes = serde_json::to_vec(info).expect("Params serializes to JSON");
79        set(&bytes);
80    }
81}
82
83fn read_optional_info<'a>(
84    has: bool,
85    get: impl FnOnce() -> capnp::Result<&'a [u8]>,
86) -> Result<Option<Params>, Box<dyn Error>> {
87    if has {
88        Ok(Some(serde_json::from_slice(get()?)?))
89    } else {
90        Ok(None)
91    }
92}
93
94impl<'a> ToCapnp<'a> for BettingInstrument {
95    type Builder = instruments_capnp::betting_instrument::Builder<'a>;
96
97    fn to_capnp(&self, mut builder: Self::Builder) {
98        self.id.write_capnp(|| builder.reborrow().init_id());
99        self.raw_symbol
100            .write_capnp(|| builder.reborrow().init_raw_symbol());
101        builder.set_event_type_id(self.event_type_id);
102        builder.set_event_type_name(self.event_type_name.as_str());
103        builder.set_competition_id(self.competition_id);
104        builder.set_competition_name(self.competition_name.as_str());
105        builder.set_event_id(self.event_id);
106        builder.set_event_name(self.event_name.as_str());
107        builder.set_event_country_code(self.event_country_code.as_str());
108        write_unix_nanos(
109            self.event_open_date,
110            builder.reborrow().init_event_open_date(),
111        );
112        builder.set_betting_type(self.betting_type.as_str());
113        builder.set_market_id(self.market_id.as_str());
114        builder.set_market_name(self.market_name.as_str());
115        builder.set_market_type(self.market_type.as_str());
116        write_unix_nanos(
117            self.market_start_time,
118            builder.reborrow().init_market_start_time(),
119        );
120        builder.set_selection_id(self.selection_id);
121        builder.set_selection_name(self.selection_name.as_str());
122        builder.set_selection_handicap(self.selection_handicap);
123        self.currency
124            .write_capnp(|| builder.reborrow().init_currency());
125        builder.set_price_precision(self.price_precision);
126        builder.set_size_precision(self.size_precision);
127        self.price_increment
128            .write_capnp(|| builder.reborrow().init_price_increment());
129        self.size_increment
130            .write_capnp(|| builder.reborrow().init_size_increment());
131        self.margin_init
132            .write_capnp(|| builder.reborrow().init_margin_init());
133        self.margin_maint
134            .write_capnp(|| builder.reborrow().init_margin_maint());
135        self.max_quantity
136            .write_capnp(|| builder.reborrow().init_max_quantity());
137        self.min_quantity
138            .write_capnp(|| builder.reborrow().init_min_quantity());
139        self.max_notional
140            .write_capnp(|| builder.reborrow().init_max_notional());
141        self.min_notional
142            .write_capnp(|| builder.reborrow().init_min_notional());
143        self.max_price
144            .write_capnp(|| builder.reborrow().init_max_price());
145        self.min_price
146            .write_capnp(|| builder.reborrow().init_min_price());
147        write_optional_ustr(self.tick_scheme, |value| {
148            builder.reborrow().set_tick_scheme(value);
149        });
150
151        write_optional_info(self.info.as_ref(), |bytes| {
152            builder.reborrow().set_info(bytes);
153        });
154
155        write_unix_nanos(self.ts_event, builder.reborrow().init_ts_event());
156        write_unix_nanos(self.ts_init, builder.init_ts_init());
157    }
158}
159
160impl<'a> FromCapnp<'a> for BettingInstrument {
161    type Reader = instruments_capnp::betting_instrument::Reader<'a>;
162
163    fn from_capnp(reader: Self::Reader) -> Result<Self, Box<dyn Error>> {
164        Ok(Self {
165            id: InstrumentId::from_capnp(reader.get_id()?)?,
166            raw_symbol: Symbol::from_capnp(reader.get_raw_symbol()?)?,
167            event_type_id: reader.get_event_type_id(),
168            event_type_name: read_ustr(|| reader.get_event_type_name())?,
169            competition_id: reader.get_competition_id(),
170            competition_name: read_ustr(|| reader.get_competition_name())?,
171            event_id: reader.get_event_id(),
172            event_name: read_ustr(|| reader.get_event_name())?,
173            event_country_code: read_ustr(|| reader.get_event_country_code())?,
174            event_open_date: read_unix_nanos(|| reader.get_event_open_date())?,
175            betting_type: read_ustr(|| reader.get_betting_type())?,
176            market_id: read_ustr(|| reader.get_market_id())?,
177            market_name: read_ustr(|| reader.get_market_name())?,
178            market_type: read_ustr(|| reader.get_market_type())?,
179            market_start_time: read_unix_nanos(|| reader.get_market_start_time())?,
180            selection_id: reader.get_selection_id(),
181            selection_name: read_ustr(|| reader.get_selection_name())?,
182            selection_handicap: reader.get_selection_handicap(),
183            currency: Currency::from_capnp(reader.get_currency()?)?,
184            price_precision: reader.get_price_precision(),
185            size_precision: reader.get_size_precision(),
186            price_increment: Price::from_capnp(reader.get_price_increment()?)?,
187            size_increment: Quantity::from_capnp(reader.get_size_increment()?)?,
188            margin_init: Decimal::from_capnp(reader.get_margin_init()?)?,
189            margin_maint: Decimal::from_capnp(reader.get_margin_maint()?)?,
190            max_quantity: read_optional_from_capnp(
191                || reader.has_max_quantity(),
192                || reader.get_max_quantity(),
193            )?,
194            min_quantity: read_optional_from_capnp(
195                || reader.has_min_quantity(),
196                || reader.get_min_quantity(),
197            )?,
198            max_notional: read_optional_from_capnp(
199                || reader.has_max_notional(),
200                || reader.get_max_notional(),
201            )?,
202            min_notional: read_optional_from_capnp(
203                || reader.has_min_notional(),
204                || reader.get_min_notional(),
205            )?,
206            max_price: read_optional_from_capnp(
207                || reader.has_max_price(),
208                || reader.get_max_price(),
209            )?,
210            min_price: read_optional_from_capnp(
211                || reader.has_min_price(),
212                || reader.get_min_price(),
213            )?,
214            tick_scheme: read_optional_ustr(reader.has_tick_scheme(), || reader.get_tick_scheme())?,
215            info: read_optional_info(reader.has_info(), || reader.get_info())?,
216            ts_event: read_unix_nanos(|| reader.get_ts_event())?,
217            ts_init: read_unix_nanos(|| reader.get_ts_init())?,
218        })
219    }
220}
221
222impl<'a> ToCapnp<'a> for BinaryOption {
223    type Builder = instruments_capnp::binary_option::Builder<'a>;
224
225    fn to_capnp(&self, mut builder: Self::Builder) {
226        self.id.write_capnp(|| builder.reborrow().init_id());
227        self.raw_symbol
228            .write_capnp(|| builder.reborrow().init_raw_symbol());
229        builder.set_asset_class(asset_class_to_capnp(self.asset_class));
230        self.currency
231            .write_capnp(|| builder.reborrow().init_currency());
232        write_unix_nanos(self.activation_ns, builder.reborrow().init_activation_ns());
233        write_unix_nanos(self.expiration_ns, builder.reborrow().init_expiration_ns());
234        builder.set_price_precision(self.price_precision);
235        builder.set_size_precision(self.size_precision);
236        self.price_increment
237            .write_capnp(|| builder.reborrow().init_price_increment());
238        self.size_increment
239            .write_capnp(|| builder.reborrow().init_size_increment());
240        self.margin_init
241            .write_capnp(|| builder.reborrow().init_margin_init());
242        self.margin_maint
243            .write_capnp(|| builder.reborrow().init_margin_maint());
244        write_optional_ustr(self.event_id, |value| {
245            builder.reborrow().set_event_id(value);
246        });
247
248        write_optional_ustr(self.outcome, |value| {
249            builder.reborrow().set_outcome(value);
250        });
251
252        write_optional_ustr(self.description, |value| {
253            builder.reborrow().set_description(value);
254        });
255
256        self.max_quantity
257            .write_capnp(|| builder.reborrow().init_max_quantity());
258        self.min_quantity
259            .write_capnp(|| builder.reborrow().init_min_quantity());
260        self.max_notional
261            .write_capnp(|| builder.reborrow().init_max_notional());
262        self.min_notional
263            .write_capnp(|| builder.reborrow().init_min_notional());
264        self.max_price
265            .write_capnp(|| builder.reborrow().init_max_price());
266        self.min_price
267            .write_capnp(|| builder.reborrow().init_min_price());
268        write_optional_ustr(self.tick_scheme, |value| {
269            builder.reborrow().set_tick_scheme(value);
270        });
271
272        write_optional_info(self.info.as_ref(), |bytes| {
273            builder.reborrow().set_info(bytes);
274        });
275
276        write_unix_nanos(self.ts_event, builder.reborrow().init_ts_event());
277        write_unix_nanos(self.ts_init, builder.init_ts_init());
278    }
279}
280
281impl<'a> FromCapnp<'a> for BinaryOption {
282    type Reader = instruments_capnp::binary_option::Reader<'a>;
283
284    fn from_capnp(reader: Self::Reader) -> Result<Self, Box<dyn Error>> {
285        Ok(Self {
286            id: InstrumentId::from_capnp(reader.get_id()?)?,
287            raw_symbol: Symbol::from_capnp(reader.get_raw_symbol()?)?,
288            asset_class: asset_class_from_capnp(reader.get_asset_class()?),
289            currency: Currency::from_capnp(reader.get_currency()?)?,
290            activation_ns: read_unix_nanos(|| reader.get_activation_ns())?,
291            expiration_ns: read_unix_nanos(|| reader.get_expiration_ns())?,
292            price_precision: reader.get_price_precision(),
293            size_precision: reader.get_size_precision(),
294            price_increment: Price::from_capnp(reader.get_price_increment()?)?,
295            size_increment: Quantity::from_capnp(reader.get_size_increment()?)?,
296            margin_init: Decimal::from_capnp(reader.get_margin_init()?)?,
297            margin_maint: Decimal::from_capnp(reader.get_margin_maint()?)?,
298            event_id: read_optional_ustr(reader.has_event_id(), || reader.get_event_id())?,
299            outcome: read_optional_ustr(reader.has_outcome(), || reader.get_outcome())?,
300            description: read_optional_ustr(reader.has_description(), || reader.get_description())?,
301            max_quantity: read_optional_from_capnp(
302                || reader.has_max_quantity(),
303                || reader.get_max_quantity(),
304            )?,
305            min_quantity: read_optional_from_capnp(
306                || reader.has_min_quantity(),
307                || reader.get_min_quantity(),
308            )?,
309            max_notional: read_optional_from_capnp(
310                || reader.has_max_notional(),
311                || reader.get_max_notional(),
312            )?,
313            min_notional: read_optional_from_capnp(
314                || reader.has_min_notional(),
315                || reader.get_min_notional(),
316            )?,
317            max_price: read_optional_from_capnp(
318                || reader.has_max_price(),
319                || reader.get_max_price(),
320            )?,
321            min_price: read_optional_from_capnp(
322                || reader.has_min_price(),
323                || reader.get_min_price(),
324            )?,
325            tick_scheme: read_optional_ustr(reader.has_tick_scheme(), || reader.get_tick_scheme())?,
326            info: read_optional_info(reader.has_info(), || reader.get_info())?,
327            ts_event: read_unix_nanos(|| reader.get_ts_event())?,
328            ts_init: read_unix_nanos(|| reader.get_ts_init())?,
329        })
330    }
331}
332
333impl<'a> ToCapnp<'a> for Cfd {
334    type Builder = instruments_capnp::cfd::Builder<'a>;
335
336    fn to_capnp(&self, mut builder: Self::Builder) {
337        self.id.write_capnp(|| builder.reborrow().init_id());
338        self.raw_symbol
339            .write_capnp(|| builder.reborrow().init_raw_symbol());
340        builder.set_asset_class(asset_class_to_capnp(self.asset_class));
341        self.base_currency
342            .write_capnp(|| builder.reborrow().init_base_currency());
343        self.quote_currency
344            .write_capnp(|| builder.reborrow().init_quote_currency());
345        builder.set_price_precision(self.price_precision);
346        builder.set_size_precision(self.size_precision);
347        self.price_increment
348            .write_capnp(|| builder.reborrow().init_price_increment());
349        self.size_increment
350            .write_capnp(|| builder.reborrow().init_size_increment());
351        self.margin_init
352            .write_capnp(|| builder.reborrow().init_margin_init());
353        self.margin_maint
354            .write_capnp(|| builder.reborrow().init_margin_maint());
355        self.lot_size
356            .write_capnp(|| builder.reborrow().init_lot_size());
357        self.max_quantity
358            .write_capnp(|| builder.reborrow().init_max_quantity());
359        self.min_quantity
360            .write_capnp(|| builder.reborrow().init_min_quantity());
361        self.max_notional
362            .write_capnp(|| builder.reborrow().init_max_notional());
363        self.min_notional
364            .write_capnp(|| builder.reborrow().init_min_notional());
365        self.max_price
366            .write_capnp(|| builder.reborrow().init_max_price());
367        self.min_price
368            .write_capnp(|| builder.reborrow().init_min_price());
369        write_optional_ustr(self.tick_scheme, |value| {
370            builder.reborrow().set_tick_scheme(value);
371        });
372
373        write_optional_info(self.info.as_ref(), |bytes| {
374            builder.reborrow().set_info(bytes);
375        });
376
377        write_unix_nanos(self.ts_event, builder.reborrow().init_ts_event());
378        write_unix_nanos(self.ts_init, builder.init_ts_init());
379    }
380}
381
382impl<'a> FromCapnp<'a> for Cfd {
383    type Reader = instruments_capnp::cfd::Reader<'a>;
384
385    fn from_capnp(reader: Self::Reader) -> Result<Self, Box<dyn Error>> {
386        Ok(Self {
387            id: InstrumentId::from_capnp(reader.get_id()?)?,
388            raw_symbol: Symbol::from_capnp(reader.get_raw_symbol()?)?,
389            asset_class: asset_class_from_capnp(reader.get_asset_class()?),
390            base_currency: read_optional_from_capnp(
391                || reader.has_base_currency(),
392                || reader.get_base_currency(),
393            )?,
394            quote_currency: Currency::from_capnp(reader.get_quote_currency()?)?,
395            price_precision: reader.get_price_precision(),
396            size_precision: reader.get_size_precision(),
397            price_increment: Price::from_capnp(reader.get_price_increment()?)?,
398            size_increment: Quantity::from_capnp(reader.get_size_increment()?)?,
399            margin_init: Decimal::from_capnp(reader.get_margin_init()?)?,
400            margin_maint: Decimal::from_capnp(reader.get_margin_maint()?)?,
401            lot_size: read_optional_from_capnp(|| reader.has_lot_size(), || reader.get_lot_size())?,
402            max_quantity: read_optional_from_capnp(
403                || reader.has_max_quantity(),
404                || reader.get_max_quantity(),
405            )?,
406            min_quantity: read_optional_from_capnp(
407                || reader.has_min_quantity(),
408                || reader.get_min_quantity(),
409            )?,
410            max_notional: read_optional_from_capnp(
411                || reader.has_max_notional(),
412                || reader.get_max_notional(),
413            )?,
414            min_notional: read_optional_from_capnp(
415                || reader.has_min_notional(),
416                || reader.get_min_notional(),
417            )?,
418            max_price: read_optional_from_capnp(
419                || reader.has_max_price(),
420                || reader.get_max_price(),
421            )?,
422            min_price: read_optional_from_capnp(
423                || reader.has_min_price(),
424                || reader.get_min_price(),
425            )?,
426            tick_scheme: read_optional_ustr(reader.has_tick_scheme(), || reader.get_tick_scheme())?,
427            info: read_optional_info(reader.has_info(), || reader.get_info())?,
428            ts_event: read_unix_nanos(|| reader.get_ts_event())?,
429            ts_init: read_unix_nanos(|| reader.get_ts_init())?,
430        })
431    }
432}
433
434impl<'a> ToCapnp<'a> for Commodity {
435    type Builder = instruments_capnp::commodity::Builder<'a>;
436
437    fn to_capnp(&self, mut builder: Self::Builder) {
438        self.id.write_capnp(|| builder.reborrow().init_id());
439        self.raw_symbol
440            .write_capnp(|| builder.reborrow().init_raw_symbol());
441        builder.set_asset_class(asset_class_to_capnp(self.asset_class));
442        self.quote_currency
443            .write_capnp(|| builder.reborrow().init_quote_currency());
444        builder.set_price_precision(self.price_precision);
445        builder.set_size_precision(self.size_precision);
446        self.price_increment
447            .write_capnp(|| builder.reborrow().init_price_increment());
448        self.size_increment
449            .write_capnp(|| builder.reborrow().init_size_increment());
450        self.margin_init
451            .write_capnp(|| builder.reborrow().init_margin_init());
452        self.margin_maint
453            .write_capnp(|| builder.reborrow().init_margin_maint());
454        self.lot_size
455            .write_capnp(|| builder.reborrow().init_lot_size());
456        self.max_quantity
457            .write_capnp(|| builder.reborrow().init_max_quantity());
458        self.min_quantity
459            .write_capnp(|| builder.reborrow().init_min_quantity());
460        self.max_notional
461            .write_capnp(|| builder.reborrow().init_max_notional());
462        self.min_notional
463            .write_capnp(|| builder.reborrow().init_min_notional());
464        self.max_price
465            .write_capnp(|| builder.reborrow().init_max_price());
466        self.min_price
467            .write_capnp(|| builder.reborrow().init_min_price());
468        write_optional_ustr(self.tick_scheme, |value| {
469            builder.reborrow().set_tick_scheme(value);
470        });
471
472        write_optional_info(self.info.as_ref(), |bytes| {
473            builder.reborrow().set_info(bytes);
474        });
475
476        write_unix_nanos(self.ts_event, builder.reborrow().init_ts_event());
477        write_unix_nanos(self.ts_init, builder.init_ts_init());
478    }
479}
480
481impl<'a> FromCapnp<'a> for Commodity {
482    type Reader = instruments_capnp::commodity::Reader<'a>;
483
484    fn from_capnp(reader: Self::Reader) -> Result<Self, Box<dyn Error>> {
485        Ok(Self {
486            id: InstrumentId::from_capnp(reader.get_id()?)?,
487            raw_symbol: Symbol::from_capnp(reader.get_raw_symbol()?)?,
488            asset_class: asset_class_from_capnp(reader.get_asset_class()?),
489            quote_currency: Currency::from_capnp(reader.get_quote_currency()?)?,
490            price_precision: reader.get_price_precision(),
491            size_precision: reader.get_size_precision(),
492            price_increment: Price::from_capnp(reader.get_price_increment()?)?,
493            size_increment: Quantity::from_capnp(reader.get_size_increment()?)?,
494            margin_init: Decimal::from_capnp(reader.get_margin_init()?)?,
495            margin_maint: Decimal::from_capnp(reader.get_margin_maint()?)?,
496            lot_size: read_optional_from_capnp(|| reader.has_lot_size(), || reader.get_lot_size())?,
497            max_quantity: read_optional_from_capnp(
498                || reader.has_max_quantity(),
499                || reader.get_max_quantity(),
500            )?,
501            min_quantity: read_optional_from_capnp(
502                || reader.has_min_quantity(),
503                || reader.get_min_quantity(),
504            )?,
505            max_notional: read_optional_from_capnp(
506                || reader.has_max_notional(),
507                || reader.get_max_notional(),
508            )?,
509            min_notional: read_optional_from_capnp(
510                || reader.has_min_notional(),
511                || reader.get_min_notional(),
512            )?,
513            max_price: read_optional_from_capnp(
514                || reader.has_max_price(),
515                || reader.get_max_price(),
516            )?,
517            min_price: read_optional_from_capnp(
518                || reader.has_min_price(),
519                || reader.get_min_price(),
520            )?,
521            tick_scheme: read_optional_ustr(reader.has_tick_scheme(), || reader.get_tick_scheme())?,
522            info: read_optional_info(reader.has_info(), || reader.get_info())?,
523            ts_event: read_unix_nanos(|| reader.get_ts_event())?,
524            ts_init: read_unix_nanos(|| reader.get_ts_init())?,
525        })
526    }
527}
528
529impl<'a> ToCapnp<'a> for CryptoFuture {
530    type Builder = instruments_capnp::crypto_future::Builder<'a>;
531
532    fn to_capnp(&self, mut builder: Self::Builder) {
533        self.id.write_capnp(|| builder.reborrow().init_id());
534        self.raw_symbol
535            .write_capnp(|| builder.reborrow().init_raw_symbol());
536        self.underlying
537            .write_capnp(|| builder.reborrow().init_underlying());
538        self.quote_currency
539            .write_capnp(|| builder.reborrow().init_quote_currency());
540        self.settlement_currency
541            .write_capnp(|| builder.reborrow().init_settlement_currency());
542        builder.set_is_inverse(self.is_inverse);
543        write_unix_nanos(self.activation_ns, builder.reborrow().init_activation_ns());
544        write_unix_nanos(self.expiration_ns, builder.reborrow().init_expiration_ns());
545        builder.set_price_precision(self.price_precision);
546        builder.set_size_precision(self.size_precision);
547        self.price_increment
548            .write_capnp(|| builder.reborrow().init_price_increment());
549        self.size_increment
550            .write_capnp(|| builder.reborrow().init_size_increment());
551        self.multiplier
552            .write_capnp(|| builder.reborrow().init_multiplier());
553        self.lot_size
554            .write_capnp(|| builder.reborrow().init_lot_size());
555        self.margin_init
556            .write_capnp(|| builder.reborrow().init_margin_init());
557        self.margin_maint
558            .write_capnp(|| builder.reborrow().init_margin_maint());
559        self.max_quantity
560            .write_capnp(|| builder.reborrow().init_max_quantity());
561        self.min_quantity
562            .write_capnp(|| builder.reborrow().init_min_quantity());
563        self.max_notional
564            .write_capnp(|| builder.reborrow().init_max_notional());
565        self.min_notional
566            .write_capnp(|| builder.reborrow().init_min_notional());
567        self.max_price
568            .write_capnp(|| builder.reborrow().init_max_price());
569        self.min_price
570            .write_capnp(|| builder.reborrow().init_min_price());
571        write_optional_ustr(self.tick_scheme, |value| {
572            builder.reborrow().set_tick_scheme(value);
573        });
574
575        write_optional_info(self.info.as_ref(), |bytes| {
576            builder.reborrow().set_info(bytes);
577        });
578
579        write_unix_nanos(self.ts_event, builder.reborrow().init_ts_event());
580        write_unix_nanos(self.ts_init, builder.init_ts_init());
581    }
582}
583
584impl<'a> FromCapnp<'a> for CryptoFuture {
585    type Reader = instruments_capnp::crypto_future::Reader<'a>;
586
587    fn from_capnp(reader: Self::Reader) -> Result<Self, Box<dyn Error>> {
588        Ok(Self {
589            id: InstrumentId::from_capnp(reader.get_id()?)?,
590            raw_symbol: Symbol::from_capnp(reader.get_raw_symbol()?)?,
591            underlying: Currency::from_capnp(reader.get_underlying()?)?,
592            quote_currency: Currency::from_capnp(reader.get_quote_currency()?)?,
593            settlement_currency: Currency::from_capnp(reader.get_settlement_currency()?)?,
594            is_inverse: reader.get_is_inverse(),
595            activation_ns: read_unix_nanos(|| reader.get_activation_ns())?,
596            expiration_ns: read_unix_nanos(|| reader.get_expiration_ns())?,
597            price_precision: reader.get_price_precision(),
598            size_precision: reader.get_size_precision(),
599            price_increment: Price::from_capnp(reader.get_price_increment()?)?,
600            size_increment: Quantity::from_capnp(reader.get_size_increment()?)?,
601            multiplier: Quantity::from_capnp(reader.get_multiplier()?)?,
602            lot_size: Quantity::from_capnp(reader.get_lot_size()?)?,
603            margin_init: Decimal::from_capnp(reader.get_margin_init()?)?,
604            margin_maint: Decimal::from_capnp(reader.get_margin_maint()?)?,
605            max_quantity: read_optional_from_capnp(
606                || reader.has_max_quantity(),
607                || reader.get_max_quantity(),
608            )?,
609            min_quantity: read_optional_from_capnp(
610                || reader.has_min_quantity(),
611                || reader.get_min_quantity(),
612            )?,
613            max_notional: read_optional_from_capnp(
614                || reader.has_max_notional(),
615                || reader.get_max_notional(),
616            )?,
617            min_notional: read_optional_from_capnp(
618                || reader.has_min_notional(),
619                || reader.get_min_notional(),
620            )?,
621            max_price: read_optional_from_capnp(
622                || reader.has_max_price(),
623                || reader.get_max_price(),
624            )?,
625            min_price: read_optional_from_capnp(
626                || reader.has_min_price(),
627                || reader.get_min_price(),
628            )?,
629            tick_scheme: read_optional_ustr(reader.has_tick_scheme(), || reader.get_tick_scheme())?,
630            info: read_optional_info(reader.has_info(), || reader.get_info())?,
631            ts_event: read_unix_nanos(|| reader.get_ts_event())?,
632            ts_init: read_unix_nanos(|| reader.get_ts_init())?,
633        })
634    }
635}
636
637impl<'a> ToCapnp<'a> for CryptoFuturesSpread {
638    type Builder = instruments_capnp::crypto_futures_spread::Builder<'a>;
639
640    fn to_capnp(&self, mut builder: Self::Builder) {
641        self.id.write_capnp(|| builder.reborrow().init_id());
642        self.raw_symbol
643            .write_capnp(|| builder.reborrow().init_raw_symbol());
644        self.underlying
645            .write_capnp(|| builder.reborrow().init_underlying());
646        self.quote_currency
647            .write_capnp(|| builder.reborrow().init_quote_currency());
648        self.settlement_currency
649            .write_capnp(|| builder.reborrow().init_settlement_currency());
650        builder.set_is_inverse(self.is_inverse);
651        builder.set_strategy_type(self.strategy_type.as_str());
652        write_unix_nanos(self.activation_ns, builder.reborrow().init_activation_ns());
653        write_unix_nanos(self.expiration_ns, builder.reborrow().init_expiration_ns());
654        builder.set_price_precision(self.price_precision);
655        builder.set_size_precision(self.size_precision);
656        self.price_increment
657            .write_capnp(|| builder.reborrow().init_price_increment());
658        self.size_increment
659            .write_capnp(|| builder.reborrow().init_size_increment());
660        self.multiplier
661            .write_capnp(|| builder.reborrow().init_multiplier());
662        self.lot_size
663            .write_capnp(|| builder.reborrow().init_lot_size());
664        self.margin_init
665            .write_capnp(|| builder.reborrow().init_margin_init());
666        self.margin_maint
667            .write_capnp(|| builder.reborrow().init_margin_maint());
668        self.max_quantity
669            .write_capnp(|| builder.reborrow().init_max_quantity());
670        self.min_quantity
671            .write_capnp(|| builder.reborrow().init_min_quantity());
672        self.max_notional
673            .write_capnp(|| builder.reborrow().init_max_notional());
674        self.min_notional
675            .write_capnp(|| builder.reborrow().init_min_notional());
676        self.max_price
677            .write_capnp(|| builder.reborrow().init_max_price());
678        self.min_price
679            .write_capnp(|| builder.reborrow().init_min_price());
680        write_optional_ustr(self.tick_scheme, |value| {
681            builder.reborrow().set_tick_scheme(value);
682        });
683
684        write_optional_info(self.info.as_ref(), |bytes| {
685            builder.reborrow().set_info(bytes);
686        });
687
688        write_unix_nanos(self.ts_event, builder.reborrow().init_ts_event());
689        write_unix_nanos(self.ts_init, builder.init_ts_init());
690    }
691}
692
693impl<'a> FromCapnp<'a> for CryptoFuturesSpread {
694    type Reader = instruments_capnp::crypto_futures_spread::Reader<'a>;
695
696    fn from_capnp(reader: Self::Reader) -> Result<Self, Box<dyn Error>> {
697        Ok(Self {
698            id: InstrumentId::from_capnp(reader.get_id()?)?,
699            raw_symbol: Symbol::from_capnp(reader.get_raw_symbol()?)?,
700            underlying: Currency::from_capnp(reader.get_underlying()?)?,
701            quote_currency: Currency::from_capnp(reader.get_quote_currency()?)?,
702            settlement_currency: Currency::from_capnp(reader.get_settlement_currency()?)?,
703            is_inverse: reader.get_is_inverse(),
704            strategy_type: read_ustr(|| reader.get_strategy_type())?,
705            activation_ns: read_unix_nanos(|| reader.get_activation_ns())?,
706            expiration_ns: read_unix_nanos(|| reader.get_expiration_ns())?,
707            price_precision: reader.get_price_precision(),
708            size_precision: reader.get_size_precision(),
709            price_increment: Price::from_capnp(reader.get_price_increment()?)?,
710            size_increment: Quantity::from_capnp(reader.get_size_increment()?)?,
711            multiplier: Quantity::from_capnp(reader.get_multiplier()?)?,
712            lot_size: Quantity::from_capnp(reader.get_lot_size()?)?,
713            margin_init: Decimal::from_capnp(reader.get_margin_init()?)?,
714            margin_maint: Decimal::from_capnp(reader.get_margin_maint()?)?,
715            max_quantity: read_optional_from_capnp(
716                || reader.has_max_quantity(),
717                || reader.get_max_quantity(),
718            )?,
719            min_quantity: read_optional_from_capnp(
720                || reader.has_min_quantity(),
721                || reader.get_min_quantity(),
722            )?,
723            max_notional: read_optional_from_capnp(
724                || reader.has_max_notional(),
725                || reader.get_max_notional(),
726            )?,
727            min_notional: read_optional_from_capnp(
728                || reader.has_min_notional(),
729                || reader.get_min_notional(),
730            )?,
731            max_price: read_optional_from_capnp(
732                || reader.has_max_price(),
733                || reader.get_max_price(),
734            )?,
735            min_price: read_optional_from_capnp(
736                || reader.has_min_price(),
737                || reader.get_min_price(),
738            )?,
739            tick_scheme: read_optional_ustr(reader.has_tick_scheme(), || reader.get_tick_scheme())?,
740            info: read_optional_info(reader.has_info(), || reader.get_info())?,
741            ts_event: read_unix_nanos(|| reader.get_ts_event())?,
742            ts_init: read_unix_nanos(|| reader.get_ts_init())?,
743        })
744    }
745}
746
747impl<'a> ToCapnp<'a> for CryptoOption {
748    type Builder = instruments_capnp::crypto_option::Builder<'a>;
749
750    fn to_capnp(&self, mut builder: Self::Builder) {
751        self.id.write_capnp(|| builder.reborrow().init_id());
752        self.raw_symbol
753            .write_capnp(|| builder.reborrow().init_raw_symbol());
754        self.underlying
755            .write_capnp(|| builder.reborrow().init_underlying());
756        self.quote_currency
757            .write_capnp(|| builder.reborrow().init_quote_currency());
758        self.settlement_currency
759            .write_capnp(|| builder.reborrow().init_settlement_currency());
760        builder.set_is_inverse(self.is_inverse);
761        builder.set_option_kind(option_kind_to_capnp(self.option_kind));
762        self.strike_price
763            .write_capnp(|| builder.reborrow().init_strike_price());
764        write_unix_nanos(self.activation_ns, builder.reborrow().init_activation_ns());
765        write_unix_nanos(self.expiration_ns, builder.reborrow().init_expiration_ns());
766        builder.set_price_precision(self.price_precision);
767        builder.set_size_precision(self.size_precision);
768        self.price_increment
769            .write_capnp(|| builder.reborrow().init_price_increment());
770        self.size_increment
771            .write_capnp(|| builder.reborrow().init_size_increment());
772        self.multiplier
773            .write_capnp(|| builder.reborrow().init_multiplier());
774        self.lot_size
775            .write_capnp(|| builder.reborrow().init_lot_size());
776        self.margin_init
777            .write_capnp(|| builder.reborrow().init_margin_init());
778        self.margin_maint
779            .write_capnp(|| builder.reborrow().init_margin_maint());
780        self.max_quantity
781            .write_capnp(|| builder.reborrow().init_max_quantity());
782        self.min_quantity
783            .write_capnp(|| builder.reborrow().init_min_quantity());
784        self.max_notional
785            .write_capnp(|| builder.reborrow().init_max_notional());
786        self.min_notional
787            .write_capnp(|| builder.reborrow().init_min_notional());
788        self.max_price
789            .write_capnp(|| builder.reborrow().init_max_price());
790        self.min_price
791            .write_capnp(|| builder.reborrow().init_min_price());
792        write_optional_ustr(self.tick_scheme, |value| {
793            builder.reborrow().set_tick_scheme(value);
794        });
795
796        write_optional_info(self.info.as_ref(), |bytes| {
797            builder.reborrow().set_info(bytes);
798        });
799
800        write_unix_nanos(self.ts_event, builder.reborrow().init_ts_event());
801        write_unix_nanos(self.ts_init, builder.init_ts_init());
802    }
803}
804
805impl<'a> FromCapnp<'a> for CryptoOption {
806    type Reader = instruments_capnp::crypto_option::Reader<'a>;
807
808    fn from_capnp(reader: Self::Reader) -> Result<Self, Box<dyn Error>> {
809        Ok(Self {
810            id: InstrumentId::from_capnp(reader.get_id()?)?,
811            raw_symbol: Symbol::from_capnp(reader.get_raw_symbol()?)?,
812            underlying: Currency::from_capnp(reader.get_underlying()?)?,
813            quote_currency: Currency::from_capnp(reader.get_quote_currency()?)?,
814            settlement_currency: Currency::from_capnp(reader.get_settlement_currency()?)?,
815            is_inverse: reader.get_is_inverse(),
816            option_kind: option_kind_from_capnp(reader.get_option_kind()?),
817            strike_price: Price::from_capnp(reader.get_strike_price()?)?,
818            activation_ns: read_unix_nanos(|| reader.get_activation_ns())?,
819            expiration_ns: read_unix_nanos(|| reader.get_expiration_ns())?,
820            price_precision: reader.get_price_precision(),
821            size_precision: reader.get_size_precision(),
822            price_increment: Price::from_capnp(reader.get_price_increment()?)?,
823            size_increment: Quantity::from_capnp(reader.get_size_increment()?)?,
824            multiplier: Quantity::from_capnp(reader.get_multiplier()?)?,
825            lot_size: Quantity::from_capnp(reader.get_lot_size()?)?,
826            margin_init: Decimal::from_capnp(reader.get_margin_init()?)?,
827            margin_maint: Decimal::from_capnp(reader.get_margin_maint()?)?,
828            max_quantity: read_optional_from_capnp(
829                || reader.has_max_quantity(),
830                || reader.get_max_quantity(),
831            )?,
832            min_quantity: read_optional_from_capnp(
833                || reader.has_min_quantity(),
834                || reader.get_min_quantity(),
835            )?,
836            max_notional: read_optional_from_capnp(
837                || reader.has_max_notional(),
838                || reader.get_max_notional(),
839            )?,
840            min_notional: read_optional_from_capnp(
841                || reader.has_min_notional(),
842                || reader.get_min_notional(),
843            )?,
844            max_price: read_optional_from_capnp(
845                || reader.has_max_price(),
846                || reader.get_max_price(),
847            )?,
848            min_price: read_optional_from_capnp(
849                || reader.has_min_price(),
850                || reader.get_min_price(),
851            )?,
852            tick_scheme: read_optional_ustr(reader.has_tick_scheme(), || reader.get_tick_scheme())?,
853            info: read_optional_info(reader.has_info(), || reader.get_info())?,
854            ts_event: read_unix_nanos(|| reader.get_ts_event())?,
855            ts_init: read_unix_nanos(|| reader.get_ts_init())?,
856        })
857    }
858}
859
860impl<'a> ToCapnp<'a> for CryptoOptionSpread {
861    type Builder = instruments_capnp::crypto_option_spread::Builder<'a>;
862
863    fn to_capnp(&self, mut builder: Self::Builder) {
864        self.id.write_capnp(|| builder.reborrow().init_id());
865        self.raw_symbol
866            .write_capnp(|| builder.reborrow().init_raw_symbol());
867        self.underlying
868            .write_capnp(|| builder.reborrow().init_underlying());
869        self.quote_currency
870            .write_capnp(|| builder.reborrow().init_quote_currency());
871        self.settlement_currency
872            .write_capnp(|| builder.reborrow().init_settlement_currency());
873        builder.set_is_inverse(self.is_inverse);
874        builder.set_strategy_type(self.strategy_type.as_str());
875        write_unix_nanos(self.activation_ns, builder.reborrow().init_activation_ns());
876        write_unix_nanos(self.expiration_ns, builder.reborrow().init_expiration_ns());
877        builder.set_price_precision(self.price_precision);
878        builder.set_size_precision(self.size_precision);
879        self.price_increment
880            .write_capnp(|| builder.reborrow().init_price_increment());
881        self.size_increment
882            .write_capnp(|| builder.reborrow().init_size_increment());
883        self.multiplier
884            .write_capnp(|| builder.reborrow().init_multiplier());
885        self.lot_size
886            .write_capnp(|| builder.reborrow().init_lot_size());
887        self.margin_init
888            .write_capnp(|| builder.reborrow().init_margin_init());
889        self.margin_maint
890            .write_capnp(|| builder.reborrow().init_margin_maint());
891        self.max_quantity
892            .write_capnp(|| builder.reborrow().init_max_quantity());
893        self.min_quantity
894            .write_capnp(|| builder.reborrow().init_min_quantity());
895        self.max_notional
896            .write_capnp(|| builder.reborrow().init_max_notional());
897        self.min_notional
898            .write_capnp(|| builder.reborrow().init_min_notional());
899        self.max_price
900            .write_capnp(|| builder.reborrow().init_max_price());
901        self.min_price
902            .write_capnp(|| builder.reborrow().init_min_price());
903        write_optional_ustr(self.tick_scheme, |value| {
904            builder.reborrow().set_tick_scheme(value);
905        });
906
907        write_optional_info(self.info.as_ref(), |bytes| {
908            builder.reborrow().set_info(bytes);
909        });
910
911        write_unix_nanos(self.ts_event, builder.reborrow().init_ts_event());
912        write_unix_nanos(self.ts_init, builder.init_ts_init());
913    }
914}
915
916impl<'a> FromCapnp<'a> for CryptoOptionSpread {
917    type Reader = instruments_capnp::crypto_option_spread::Reader<'a>;
918
919    fn from_capnp(reader: Self::Reader) -> Result<Self, Box<dyn Error>> {
920        Ok(Self {
921            id: InstrumentId::from_capnp(reader.get_id()?)?,
922            raw_symbol: Symbol::from_capnp(reader.get_raw_symbol()?)?,
923            underlying: Currency::from_capnp(reader.get_underlying()?)?,
924            quote_currency: Currency::from_capnp(reader.get_quote_currency()?)?,
925            settlement_currency: Currency::from_capnp(reader.get_settlement_currency()?)?,
926            is_inverse: reader.get_is_inverse(),
927            strategy_type: read_ustr(|| reader.get_strategy_type())?,
928            activation_ns: read_unix_nanos(|| reader.get_activation_ns())?,
929            expiration_ns: read_unix_nanos(|| reader.get_expiration_ns())?,
930            price_precision: reader.get_price_precision(),
931            size_precision: reader.get_size_precision(),
932            price_increment: Price::from_capnp(reader.get_price_increment()?)?,
933            size_increment: Quantity::from_capnp(reader.get_size_increment()?)?,
934            multiplier: Quantity::from_capnp(reader.get_multiplier()?)?,
935            lot_size: Quantity::from_capnp(reader.get_lot_size()?)?,
936            margin_init: Decimal::from_capnp(reader.get_margin_init()?)?,
937            margin_maint: Decimal::from_capnp(reader.get_margin_maint()?)?,
938            max_quantity: read_optional_from_capnp(
939                || reader.has_max_quantity(),
940                || reader.get_max_quantity(),
941            )?,
942            min_quantity: read_optional_from_capnp(
943                || reader.has_min_quantity(),
944                || reader.get_min_quantity(),
945            )?,
946            max_notional: read_optional_from_capnp(
947                || reader.has_max_notional(),
948                || reader.get_max_notional(),
949            )?,
950            min_notional: read_optional_from_capnp(
951                || reader.has_min_notional(),
952                || reader.get_min_notional(),
953            )?,
954            max_price: read_optional_from_capnp(
955                || reader.has_max_price(),
956                || reader.get_max_price(),
957            )?,
958            min_price: read_optional_from_capnp(
959                || reader.has_min_price(),
960                || reader.get_min_price(),
961            )?,
962            tick_scheme: read_optional_ustr(reader.has_tick_scheme(), || reader.get_tick_scheme())?,
963            info: read_optional_info(reader.has_info(), || reader.get_info())?,
964            ts_event: read_unix_nanos(|| reader.get_ts_event())?,
965            ts_init: read_unix_nanos(|| reader.get_ts_init())?,
966        })
967    }
968}
969
970impl<'a> ToCapnp<'a> for CryptoPerpetual {
971    type Builder = instruments_capnp::crypto_perpetual::Builder<'a>;
972
973    fn to_capnp(&self, mut builder: Self::Builder) {
974        self.id.write_capnp(|| builder.reborrow().init_id());
975        self.raw_symbol
976            .write_capnp(|| builder.reborrow().init_raw_symbol());
977        self.base_currency
978            .write_capnp(|| builder.reborrow().init_base_currency());
979        self.quote_currency
980            .write_capnp(|| builder.reborrow().init_quote_currency());
981        self.settlement_currency
982            .write_capnp(|| builder.reborrow().init_settlement_currency());
983        builder.set_is_inverse(self.is_inverse);
984        builder.set_price_precision(self.price_precision);
985        builder.set_size_precision(self.size_precision);
986        self.price_increment
987            .write_capnp(|| builder.reborrow().init_price_increment());
988        self.size_increment
989            .write_capnp(|| builder.reborrow().init_size_increment());
990        self.multiplier
991            .write_capnp(|| builder.reborrow().init_multiplier());
992        self.lot_size
993            .write_capnp(|| builder.reborrow().init_lot_size());
994        self.margin_init
995            .write_capnp(|| builder.reborrow().init_margin_init());
996        self.margin_maint
997            .write_capnp(|| builder.reborrow().init_margin_maint());
998        self.max_quantity
999            .write_capnp(|| builder.reborrow().init_max_quantity());
1000        self.min_quantity
1001            .write_capnp(|| builder.reborrow().init_min_quantity());
1002        self.max_notional
1003            .write_capnp(|| builder.reborrow().init_max_notional());
1004        self.min_notional
1005            .write_capnp(|| builder.reborrow().init_min_notional());
1006        self.max_price
1007            .write_capnp(|| builder.reborrow().init_max_price());
1008        self.min_price
1009            .write_capnp(|| builder.reborrow().init_min_price());
1010        write_optional_ustr(self.tick_scheme, |value| {
1011            builder.reborrow().set_tick_scheme(value);
1012        });
1013
1014        write_optional_info(self.info.as_ref(), |bytes| {
1015            builder.reborrow().set_info(bytes);
1016        });
1017
1018        write_unix_nanos(self.ts_event, builder.reborrow().init_ts_event());
1019        write_unix_nanos(self.ts_init, builder.init_ts_init());
1020    }
1021}
1022
1023impl<'a> FromCapnp<'a> for CryptoPerpetual {
1024    type Reader = instruments_capnp::crypto_perpetual::Reader<'a>;
1025
1026    fn from_capnp(reader: Self::Reader) -> Result<Self, Box<dyn Error>> {
1027        Ok(Self {
1028            id: InstrumentId::from_capnp(reader.get_id()?)?,
1029            raw_symbol: Symbol::from_capnp(reader.get_raw_symbol()?)?,
1030            base_currency: Currency::from_capnp(reader.get_base_currency()?)?,
1031            quote_currency: Currency::from_capnp(reader.get_quote_currency()?)?,
1032            settlement_currency: Currency::from_capnp(reader.get_settlement_currency()?)?,
1033            is_inverse: reader.get_is_inverse(),
1034            price_precision: reader.get_price_precision(),
1035            size_precision: reader.get_size_precision(),
1036            price_increment: Price::from_capnp(reader.get_price_increment()?)?,
1037            size_increment: Quantity::from_capnp(reader.get_size_increment()?)?,
1038            multiplier: Quantity::from_capnp(reader.get_multiplier()?)?,
1039            lot_size: Quantity::from_capnp(reader.get_lot_size()?)?,
1040            margin_init: Decimal::from_capnp(reader.get_margin_init()?)?,
1041            margin_maint: Decimal::from_capnp(reader.get_margin_maint()?)?,
1042            max_quantity: read_optional_from_capnp(
1043                || reader.has_max_quantity(),
1044                || reader.get_max_quantity(),
1045            )?,
1046            min_quantity: read_optional_from_capnp(
1047                || reader.has_min_quantity(),
1048                || reader.get_min_quantity(),
1049            )?,
1050            max_notional: read_optional_from_capnp(
1051                || reader.has_max_notional(),
1052                || reader.get_max_notional(),
1053            )?,
1054            min_notional: read_optional_from_capnp(
1055                || reader.has_min_notional(),
1056                || reader.get_min_notional(),
1057            )?,
1058            max_price: read_optional_from_capnp(
1059                || reader.has_max_price(),
1060                || reader.get_max_price(),
1061            )?,
1062            min_price: read_optional_from_capnp(
1063                || reader.has_min_price(),
1064                || reader.get_min_price(),
1065            )?,
1066            tick_scheme: read_optional_ustr(reader.has_tick_scheme(), || reader.get_tick_scheme())?,
1067            info: read_optional_info(reader.has_info(), || reader.get_info())?,
1068            ts_event: read_unix_nanos(|| reader.get_ts_event())?,
1069            ts_init: read_unix_nanos(|| reader.get_ts_init())?,
1070        })
1071    }
1072}
1073
1074impl<'a> ToCapnp<'a> for CurrencyPair {
1075    type Builder = instruments_capnp::currency_pair::Builder<'a>;
1076
1077    fn to_capnp(&self, mut builder: Self::Builder) {
1078        self.id.write_capnp(|| builder.reborrow().init_id());
1079        self.raw_symbol
1080            .write_capnp(|| builder.reborrow().init_raw_symbol());
1081        self.base_currency
1082            .write_capnp(|| builder.reborrow().init_base_currency());
1083        self.quote_currency
1084            .write_capnp(|| builder.reborrow().init_quote_currency());
1085        builder.set_price_precision(self.price_precision);
1086        builder.set_size_precision(self.size_precision);
1087        self.price_increment
1088            .write_capnp(|| builder.reborrow().init_price_increment());
1089        self.size_increment
1090            .write_capnp(|| builder.reborrow().init_size_increment());
1091        self.multiplier
1092            .write_capnp(|| builder.reborrow().init_multiplier());
1093        self.lot_size
1094            .write_capnp(|| builder.reborrow().init_lot_size());
1095        self.margin_init
1096            .write_capnp(|| builder.reborrow().init_margin_init());
1097        self.margin_maint
1098            .write_capnp(|| builder.reborrow().init_margin_maint());
1099        self.max_quantity
1100            .write_capnp(|| builder.reborrow().init_max_quantity());
1101        self.min_quantity
1102            .write_capnp(|| builder.reborrow().init_min_quantity());
1103        self.max_notional
1104            .write_capnp(|| builder.reborrow().init_max_notional());
1105        self.min_notional
1106            .write_capnp(|| builder.reborrow().init_min_notional());
1107        self.max_price
1108            .write_capnp(|| builder.reborrow().init_max_price());
1109        self.min_price
1110            .write_capnp(|| builder.reborrow().init_min_price());
1111        write_optional_ustr(self.tick_scheme, |value| {
1112            builder.reborrow().set_tick_scheme(value);
1113        });
1114
1115        write_optional_info(self.info.as_ref(), |bytes| {
1116            builder.reborrow().set_info(bytes);
1117        });
1118
1119        write_unix_nanos(self.ts_event, builder.reborrow().init_ts_event());
1120        write_unix_nanos(self.ts_init, builder.init_ts_init());
1121    }
1122}
1123
1124impl<'a> FromCapnp<'a> for CurrencyPair {
1125    type Reader = instruments_capnp::currency_pair::Reader<'a>;
1126
1127    fn from_capnp(reader: Self::Reader) -> Result<Self, Box<dyn Error>> {
1128        Ok(Self {
1129            id: InstrumentId::from_capnp(reader.get_id()?)?,
1130            raw_symbol: Symbol::from_capnp(reader.get_raw_symbol()?)?,
1131            base_currency: Currency::from_capnp(reader.get_base_currency()?)?,
1132            quote_currency: Currency::from_capnp(reader.get_quote_currency()?)?,
1133            price_precision: reader.get_price_precision(),
1134            size_precision: reader.get_size_precision(),
1135            price_increment: Price::from_capnp(reader.get_price_increment()?)?,
1136            size_increment: Quantity::from_capnp(reader.get_size_increment()?)?,
1137            multiplier: Quantity::from_capnp(reader.get_multiplier()?)?,
1138            lot_size: read_optional_from_capnp(|| reader.has_lot_size(), || reader.get_lot_size())?,
1139            margin_init: Decimal::from_capnp(reader.get_margin_init()?)?,
1140            margin_maint: Decimal::from_capnp(reader.get_margin_maint()?)?,
1141            max_quantity: read_optional_from_capnp(
1142                || reader.has_max_quantity(),
1143                || reader.get_max_quantity(),
1144            )?,
1145            min_quantity: read_optional_from_capnp(
1146                || reader.has_min_quantity(),
1147                || reader.get_min_quantity(),
1148            )?,
1149            max_notional: read_optional_from_capnp(
1150                || reader.has_max_notional(),
1151                || reader.get_max_notional(),
1152            )?,
1153            min_notional: read_optional_from_capnp(
1154                || reader.has_min_notional(),
1155                || reader.get_min_notional(),
1156            )?,
1157            max_price: read_optional_from_capnp(
1158                || reader.has_max_price(),
1159                || reader.get_max_price(),
1160            )?,
1161            min_price: read_optional_from_capnp(
1162                || reader.has_min_price(),
1163                || reader.get_min_price(),
1164            )?,
1165            tick_scheme: read_optional_ustr(reader.has_tick_scheme(), || reader.get_tick_scheme())?,
1166            info: read_optional_info(reader.has_info(), || reader.get_info())?,
1167            ts_event: read_unix_nanos(|| reader.get_ts_event())?,
1168            ts_init: read_unix_nanos(|| reader.get_ts_init())?,
1169        })
1170    }
1171}
1172
1173impl<'a> ToCapnp<'a> for Equity {
1174    type Builder = instruments_capnp::equity::Builder<'a>;
1175
1176    fn to_capnp(&self, mut builder: Self::Builder) {
1177        self.id.write_capnp(|| builder.reborrow().init_id());
1178        self.raw_symbol
1179            .write_capnp(|| builder.reborrow().init_raw_symbol());
1180        write_optional_ustr(self.isin, |value| {
1181            builder.reborrow().set_isin(value);
1182        });
1183
1184        self.currency
1185            .write_capnp(|| builder.reborrow().init_currency());
1186        builder.set_price_precision(self.price_precision);
1187        self.price_increment
1188            .write_capnp(|| builder.reborrow().init_price_increment());
1189        self.margin_init
1190            .write_capnp(|| builder.reborrow().init_margin_init());
1191        self.margin_maint
1192            .write_capnp(|| builder.reborrow().init_margin_maint());
1193        self.lot_size
1194            .write_capnp(|| builder.reborrow().init_lot_size());
1195        self.max_quantity
1196            .write_capnp(|| builder.reborrow().init_max_quantity());
1197        self.min_quantity
1198            .write_capnp(|| builder.reborrow().init_min_quantity());
1199        self.max_price
1200            .write_capnp(|| builder.reborrow().init_max_price());
1201        self.min_price
1202            .write_capnp(|| builder.reborrow().init_min_price());
1203        write_optional_ustr(self.tick_scheme, |value| {
1204            builder.reborrow().set_tick_scheme(value);
1205        });
1206
1207        write_optional_info(self.info.as_ref(), |bytes| {
1208            builder.reborrow().set_info(bytes);
1209        });
1210
1211        write_unix_nanos(self.ts_event, builder.reborrow().init_ts_event());
1212        write_unix_nanos(self.ts_init, builder.init_ts_init());
1213    }
1214}
1215
1216impl<'a> FromCapnp<'a> for Equity {
1217    type Reader = instruments_capnp::equity::Reader<'a>;
1218
1219    fn from_capnp(reader: Self::Reader) -> Result<Self, Box<dyn Error>> {
1220        Ok(Self {
1221            id: InstrumentId::from_capnp(reader.get_id()?)?,
1222            raw_symbol: Symbol::from_capnp(reader.get_raw_symbol()?)?,
1223            isin: read_optional_ustr(reader.has_isin(), || reader.get_isin())?,
1224            currency: Currency::from_capnp(reader.get_currency()?)?,
1225            price_precision: reader.get_price_precision(),
1226            price_increment: Price::from_capnp(reader.get_price_increment()?)?,
1227            margin_init: Decimal::from_capnp(reader.get_margin_init()?)?,
1228            margin_maint: Decimal::from_capnp(reader.get_margin_maint()?)?,
1229            lot_size: read_optional_from_capnp(|| reader.has_lot_size(), || reader.get_lot_size())?,
1230            max_quantity: read_optional_from_capnp(
1231                || reader.has_max_quantity(),
1232                || reader.get_max_quantity(),
1233            )?,
1234            min_quantity: read_optional_from_capnp(
1235                || reader.has_min_quantity(),
1236                || reader.get_min_quantity(),
1237            )?,
1238            max_price: read_optional_from_capnp(
1239                || reader.has_max_price(),
1240                || reader.get_max_price(),
1241            )?,
1242            min_price: read_optional_from_capnp(
1243                || reader.has_min_price(),
1244                || reader.get_min_price(),
1245            )?,
1246            tick_scheme: read_optional_ustr(reader.has_tick_scheme(), || reader.get_tick_scheme())?,
1247            info: read_optional_info(reader.has_info(), || reader.get_info())?,
1248            ts_event: read_unix_nanos(|| reader.get_ts_event())?,
1249            ts_init: read_unix_nanos(|| reader.get_ts_init())?,
1250        })
1251    }
1252}
1253
1254impl<'a> ToCapnp<'a> for FuturesContract {
1255    type Builder = instruments_capnp::futures_contract::Builder<'a>;
1256
1257    fn to_capnp(&self, mut builder: Self::Builder) {
1258        self.id.write_capnp(|| builder.reborrow().init_id());
1259        self.raw_symbol
1260            .write_capnp(|| builder.reborrow().init_raw_symbol());
1261        builder.set_asset_class(asset_class_to_capnp(self.asset_class));
1262        write_optional_ustr(self.exchange, |value| {
1263            builder.reborrow().set_exchange(value);
1264        });
1265
1266        builder.set_underlying(self.underlying.as_str());
1267        write_unix_nanos(self.activation_ns, builder.reborrow().init_activation_ns());
1268        write_unix_nanos(self.expiration_ns, builder.reborrow().init_expiration_ns());
1269        self.currency
1270            .write_capnp(|| builder.reborrow().init_currency());
1271        builder.set_price_precision(self.price_precision);
1272        self.price_increment
1273            .write_capnp(|| builder.reborrow().init_price_increment());
1274        self.size_increment
1275            .write_capnp(|| builder.reborrow().init_size_increment());
1276        builder.set_size_precision(self.size_precision);
1277        self.multiplier
1278            .write_capnp(|| builder.reborrow().init_multiplier());
1279        self.lot_size
1280            .write_capnp(|| builder.reborrow().init_lot_size());
1281        self.margin_init
1282            .write_capnp(|| builder.reborrow().init_margin_init());
1283        self.margin_maint
1284            .write_capnp(|| builder.reborrow().init_margin_maint());
1285        self.max_quantity
1286            .write_capnp(|| builder.reborrow().init_max_quantity());
1287        self.min_quantity
1288            .write_capnp(|| builder.reborrow().init_min_quantity());
1289        self.max_price
1290            .write_capnp(|| builder.reborrow().init_max_price());
1291        self.min_price
1292            .write_capnp(|| builder.reborrow().init_min_price());
1293        write_optional_ustr(self.tick_scheme, |value| {
1294            builder.reborrow().set_tick_scheme(value);
1295        });
1296
1297        write_optional_info(self.info.as_ref(), |bytes| {
1298            builder.reborrow().set_info(bytes);
1299        });
1300
1301        write_unix_nanos(self.ts_event, builder.reborrow().init_ts_event());
1302        write_unix_nanos(self.ts_init, builder.init_ts_init());
1303    }
1304}
1305
1306impl<'a> FromCapnp<'a> for FuturesContract {
1307    type Reader = instruments_capnp::futures_contract::Reader<'a>;
1308
1309    fn from_capnp(reader: Self::Reader) -> Result<Self, Box<dyn Error>> {
1310        Ok(Self {
1311            id: InstrumentId::from_capnp(reader.get_id()?)?,
1312            raw_symbol: Symbol::from_capnp(reader.get_raw_symbol()?)?,
1313            asset_class: asset_class_from_capnp(reader.get_asset_class()?),
1314            exchange: read_optional_ustr(reader.has_exchange(), || reader.get_exchange())?,
1315            underlying: read_ustr(|| reader.get_underlying())?,
1316            activation_ns: read_unix_nanos(|| reader.get_activation_ns())?,
1317            expiration_ns: read_unix_nanos(|| reader.get_expiration_ns())?,
1318            currency: Currency::from_capnp(reader.get_currency()?)?,
1319            price_precision: reader.get_price_precision(),
1320            price_increment: Price::from_capnp(reader.get_price_increment()?)?,
1321            size_increment: Quantity::from_capnp(reader.get_size_increment()?)?,
1322            size_precision: reader.get_size_precision(),
1323            multiplier: Quantity::from_capnp(reader.get_multiplier()?)?,
1324            lot_size: Quantity::from_capnp(reader.get_lot_size()?)?,
1325            margin_init: Decimal::from_capnp(reader.get_margin_init()?)?,
1326            margin_maint: Decimal::from_capnp(reader.get_margin_maint()?)?,
1327            max_quantity: read_optional_from_capnp(
1328                || reader.has_max_quantity(),
1329                || reader.get_max_quantity(),
1330            )?,
1331            min_quantity: read_optional_from_capnp(
1332                || reader.has_min_quantity(),
1333                || reader.get_min_quantity(),
1334            )?,
1335            max_price: read_optional_from_capnp(
1336                || reader.has_max_price(),
1337                || reader.get_max_price(),
1338            )?,
1339            min_price: read_optional_from_capnp(
1340                || reader.has_min_price(),
1341                || reader.get_min_price(),
1342            )?,
1343            tick_scheme: read_optional_ustr(reader.has_tick_scheme(), || reader.get_tick_scheme())?,
1344            info: read_optional_info(reader.has_info(), || reader.get_info())?,
1345            ts_event: read_unix_nanos(|| reader.get_ts_event())?,
1346            ts_init: read_unix_nanos(|| reader.get_ts_init())?,
1347        })
1348    }
1349}
1350
1351impl<'a> ToCapnp<'a> for FuturesSpread {
1352    type Builder = instruments_capnp::futures_spread::Builder<'a>;
1353
1354    fn to_capnp(&self, mut builder: Self::Builder) {
1355        self.id.write_capnp(|| builder.reborrow().init_id());
1356        self.raw_symbol
1357            .write_capnp(|| builder.reborrow().init_raw_symbol());
1358        builder.set_asset_class(asset_class_to_capnp(self.asset_class));
1359        write_optional_ustr(self.exchange, |value| {
1360            builder.reborrow().set_exchange(value);
1361        });
1362
1363        builder.set_underlying(self.underlying.as_str());
1364        builder.set_strategy_type(self.strategy_type.as_str());
1365        write_unix_nanos(self.activation_ns, builder.reborrow().init_activation_ns());
1366        write_unix_nanos(self.expiration_ns, builder.reborrow().init_expiration_ns());
1367        self.currency
1368            .write_capnp(|| builder.reborrow().init_currency());
1369        builder.set_price_precision(self.price_precision);
1370        self.price_increment
1371            .write_capnp(|| builder.reborrow().init_price_increment());
1372        self.size_increment
1373            .write_capnp(|| builder.reborrow().init_size_increment());
1374        builder.set_size_precision(self.size_precision);
1375        self.multiplier
1376            .write_capnp(|| builder.reborrow().init_multiplier());
1377        self.lot_size
1378            .write_capnp(|| builder.reborrow().init_lot_size());
1379        self.margin_init
1380            .write_capnp(|| builder.reborrow().init_margin_init());
1381        self.margin_maint
1382            .write_capnp(|| builder.reborrow().init_margin_maint());
1383        self.max_quantity
1384            .write_capnp(|| builder.reborrow().init_max_quantity());
1385        self.min_quantity
1386            .write_capnp(|| builder.reborrow().init_min_quantity());
1387        self.max_price
1388            .write_capnp(|| builder.reborrow().init_max_price());
1389        self.min_price
1390            .write_capnp(|| builder.reborrow().init_min_price());
1391        write_optional_ustr(self.tick_scheme, |value| {
1392            builder.reborrow().set_tick_scheme(value);
1393        });
1394
1395        write_optional_info(self.info.as_ref(), |bytes| {
1396            builder.reborrow().set_info(bytes);
1397        });
1398
1399        write_unix_nanos(self.ts_event, builder.reborrow().init_ts_event());
1400        write_unix_nanos(self.ts_init, builder.init_ts_init());
1401    }
1402}
1403
1404impl<'a> FromCapnp<'a> for FuturesSpread {
1405    type Reader = instruments_capnp::futures_spread::Reader<'a>;
1406
1407    fn from_capnp(reader: Self::Reader) -> Result<Self, Box<dyn Error>> {
1408        Ok(Self {
1409            id: InstrumentId::from_capnp(reader.get_id()?)?,
1410            raw_symbol: Symbol::from_capnp(reader.get_raw_symbol()?)?,
1411            asset_class: asset_class_from_capnp(reader.get_asset_class()?),
1412            exchange: read_optional_ustr(reader.has_exchange(), || reader.get_exchange())?,
1413            underlying: read_ustr(|| reader.get_underlying())?,
1414            strategy_type: read_ustr(|| reader.get_strategy_type())?,
1415            activation_ns: read_unix_nanos(|| reader.get_activation_ns())?,
1416            expiration_ns: read_unix_nanos(|| reader.get_expiration_ns())?,
1417            currency: Currency::from_capnp(reader.get_currency()?)?,
1418            price_precision: reader.get_price_precision(),
1419            price_increment: Price::from_capnp(reader.get_price_increment()?)?,
1420            size_increment: Quantity::from_capnp(reader.get_size_increment()?)?,
1421            size_precision: reader.get_size_precision(),
1422            multiplier: Quantity::from_capnp(reader.get_multiplier()?)?,
1423            lot_size: Quantity::from_capnp(reader.get_lot_size()?)?,
1424            margin_init: Decimal::from_capnp(reader.get_margin_init()?)?,
1425            margin_maint: Decimal::from_capnp(reader.get_margin_maint()?)?,
1426            max_quantity: read_optional_from_capnp(
1427                || reader.has_max_quantity(),
1428                || reader.get_max_quantity(),
1429            )?,
1430            min_quantity: read_optional_from_capnp(
1431                || reader.has_min_quantity(),
1432                || reader.get_min_quantity(),
1433            )?,
1434            max_price: read_optional_from_capnp(
1435                || reader.has_max_price(),
1436                || reader.get_max_price(),
1437            )?,
1438            min_price: read_optional_from_capnp(
1439                || reader.has_min_price(),
1440                || reader.get_min_price(),
1441            )?,
1442            tick_scheme: read_optional_ustr(reader.has_tick_scheme(), || reader.get_tick_scheme())?,
1443            info: read_optional_info(reader.has_info(), || reader.get_info())?,
1444            ts_event: read_unix_nanos(|| reader.get_ts_event())?,
1445            ts_init: read_unix_nanos(|| reader.get_ts_init())?,
1446        })
1447    }
1448}
1449
1450impl<'a> ToCapnp<'a> for IndexInstrument {
1451    type Builder = instruments_capnp::index_instrument::Builder<'a>;
1452
1453    fn to_capnp(&self, mut builder: Self::Builder) {
1454        self.id.write_capnp(|| builder.reborrow().init_id());
1455        self.raw_symbol
1456            .write_capnp(|| builder.reborrow().init_raw_symbol());
1457        self.currency
1458            .write_capnp(|| builder.reborrow().init_currency());
1459        builder.set_price_precision(self.price_precision);
1460        builder.set_size_precision(self.size_precision);
1461        self.price_increment
1462            .write_capnp(|| builder.reborrow().init_price_increment());
1463        self.size_increment
1464            .write_capnp(|| builder.reborrow().init_size_increment());
1465        write_optional_ustr(self.tick_scheme, |value| {
1466            builder.reborrow().set_tick_scheme(value);
1467        });
1468
1469        write_optional_info(self.info.as_ref(), |bytes| {
1470            builder.reborrow().set_info(bytes);
1471        });
1472
1473        write_unix_nanos(self.ts_event, builder.reborrow().init_ts_event());
1474        write_unix_nanos(self.ts_init, builder.init_ts_init());
1475    }
1476}
1477
1478impl<'a> FromCapnp<'a> for IndexInstrument {
1479    type Reader = instruments_capnp::index_instrument::Reader<'a>;
1480
1481    fn from_capnp(reader: Self::Reader) -> Result<Self, Box<dyn Error>> {
1482        Ok(Self {
1483            id: InstrumentId::from_capnp(reader.get_id()?)?,
1484            raw_symbol: Symbol::from_capnp(reader.get_raw_symbol()?)?,
1485            currency: Currency::from_capnp(reader.get_currency()?)?,
1486            price_precision: reader.get_price_precision(),
1487            size_precision: reader.get_size_precision(),
1488            price_increment: Price::from_capnp(reader.get_price_increment()?)?,
1489            size_increment: Quantity::from_capnp(reader.get_size_increment()?)?,
1490            tick_scheme: read_optional_ustr(reader.has_tick_scheme(), || reader.get_tick_scheme())?,
1491            info: read_optional_info(reader.has_info(), || reader.get_info())?,
1492            ts_event: read_unix_nanos(|| reader.get_ts_event())?,
1493            ts_init: read_unix_nanos(|| reader.get_ts_init())?,
1494        })
1495    }
1496}
1497
1498impl<'a> ToCapnp<'a> for OptionContract {
1499    type Builder = instruments_capnp::option_contract::Builder<'a>;
1500
1501    fn to_capnp(&self, mut builder: Self::Builder) {
1502        self.id.write_capnp(|| builder.reborrow().init_id());
1503        self.raw_symbol
1504            .write_capnp(|| builder.reborrow().init_raw_symbol());
1505        builder.set_asset_class(asset_class_to_capnp(self.asset_class));
1506        write_optional_ustr(self.exchange, |value| {
1507            builder.reborrow().set_exchange(value);
1508        });
1509
1510        builder.set_underlying(self.underlying.as_str());
1511        builder.set_option_kind(option_kind_to_capnp(self.option_kind));
1512        self.strike_price
1513            .write_capnp(|| builder.reborrow().init_strike_price());
1514        write_unix_nanos(self.activation_ns, builder.reborrow().init_activation_ns());
1515        write_unix_nanos(self.expiration_ns, builder.reborrow().init_expiration_ns());
1516        self.currency
1517            .write_capnp(|| builder.reborrow().init_currency());
1518        builder.set_price_precision(self.price_precision);
1519        self.price_increment
1520            .write_capnp(|| builder.reborrow().init_price_increment());
1521        self.size_increment
1522            .write_capnp(|| builder.reborrow().init_size_increment());
1523        builder.set_size_precision(self.size_precision);
1524        self.multiplier
1525            .write_capnp(|| builder.reborrow().init_multiplier());
1526        self.lot_size
1527            .write_capnp(|| builder.reborrow().init_lot_size());
1528        self.margin_init
1529            .write_capnp(|| builder.reborrow().init_margin_init());
1530        self.margin_maint
1531            .write_capnp(|| builder.reborrow().init_margin_maint());
1532        self.max_quantity
1533            .write_capnp(|| builder.reborrow().init_max_quantity());
1534        self.min_quantity
1535            .write_capnp(|| builder.reborrow().init_min_quantity());
1536        self.max_price
1537            .write_capnp(|| builder.reborrow().init_max_price());
1538        self.min_price
1539            .write_capnp(|| builder.reborrow().init_min_price());
1540        write_optional_ustr(self.tick_scheme, |value| {
1541            builder.reborrow().set_tick_scheme(value);
1542        });
1543
1544        write_optional_info(self.info.as_ref(), |bytes| {
1545            builder.reborrow().set_info(bytes);
1546        });
1547
1548        write_unix_nanos(self.ts_event, builder.reborrow().init_ts_event());
1549        write_unix_nanos(self.ts_init, builder.init_ts_init());
1550    }
1551}
1552
1553impl<'a> FromCapnp<'a> for OptionContract {
1554    type Reader = instruments_capnp::option_contract::Reader<'a>;
1555
1556    fn from_capnp(reader: Self::Reader) -> Result<Self, Box<dyn Error>> {
1557        Ok(Self {
1558            id: InstrumentId::from_capnp(reader.get_id()?)?,
1559            raw_symbol: Symbol::from_capnp(reader.get_raw_symbol()?)?,
1560            asset_class: asset_class_from_capnp(reader.get_asset_class()?),
1561            exchange: read_optional_ustr(reader.has_exchange(), || reader.get_exchange())?,
1562            underlying: read_ustr(|| reader.get_underlying())?,
1563            option_kind: option_kind_from_capnp(reader.get_option_kind()?),
1564            strike_price: Price::from_capnp(reader.get_strike_price()?)?,
1565            activation_ns: read_unix_nanos(|| reader.get_activation_ns())?,
1566            expiration_ns: read_unix_nanos(|| reader.get_expiration_ns())?,
1567            currency: Currency::from_capnp(reader.get_currency()?)?,
1568            price_precision: reader.get_price_precision(),
1569            price_increment: Price::from_capnp(reader.get_price_increment()?)?,
1570            size_increment: Quantity::from_capnp(reader.get_size_increment()?)?,
1571            size_precision: reader.get_size_precision(),
1572            multiplier: Quantity::from_capnp(reader.get_multiplier()?)?,
1573            lot_size: Quantity::from_capnp(reader.get_lot_size()?)?,
1574            margin_init: Decimal::from_capnp(reader.get_margin_init()?)?,
1575            margin_maint: Decimal::from_capnp(reader.get_margin_maint()?)?,
1576            max_quantity: read_optional_from_capnp(
1577                || reader.has_max_quantity(),
1578                || reader.get_max_quantity(),
1579            )?,
1580            min_quantity: read_optional_from_capnp(
1581                || reader.has_min_quantity(),
1582                || reader.get_min_quantity(),
1583            )?,
1584            max_price: read_optional_from_capnp(
1585                || reader.has_max_price(),
1586                || reader.get_max_price(),
1587            )?,
1588            min_price: read_optional_from_capnp(
1589                || reader.has_min_price(),
1590                || reader.get_min_price(),
1591            )?,
1592            tick_scheme: read_optional_ustr(reader.has_tick_scheme(), || reader.get_tick_scheme())?,
1593            info: read_optional_info(reader.has_info(), || reader.get_info())?,
1594            ts_event: read_unix_nanos(|| reader.get_ts_event())?,
1595            ts_init: read_unix_nanos(|| reader.get_ts_init())?,
1596        })
1597    }
1598}
1599
1600impl<'a> ToCapnp<'a> for OptionSpread {
1601    type Builder = instruments_capnp::option_spread::Builder<'a>;
1602
1603    fn to_capnp(&self, mut builder: Self::Builder) {
1604        self.id.write_capnp(|| builder.reborrow().init_id());
1605        self.raw_symbol
1606            .write_capnp(|| builder.reborrow().init_raw_symbol());
1607        builder.set_asset_class(asset_class_to_capnp(self.asset_class));
1608        write_optional_ustr(self.exchange, |value| {
1609            builder.reborrow().set_exchange(value);
1610        });
1611
1612        builder.set_underlying(self.underlying.as_str());
1613        builder.set_strategy_type(self.strategy_type.as_str());
1614        write_unix_nanos(self.activation_ns, builder.reborrow().init_activation_ns());
1615        write_unix_nanos(self.expiration_ns, builder.reborrow().init_expiration_ns());
1616        self.currency
1617            .write_capnp(|| builder.reborrow().init_currency());
1618        builder.set_price_precision(self.price_precision);
1619        self.price_increment
1620            .write_capnp(|| builder.reborrow().init_price_increment());
1621        self.size_increment
1622            .write_capnp(|| builder.reborrow().init_size_increment());
1623        builder.set_size_precision(self.size_precision);
1624        self.multiplier
1625            .write_capnp(|| builder.reborrow().init_multiplier());
1626        self.lot_size
1627            .write_capnp(|| builder.reborrow().init_lot_size());
1628        self.margin_init
1629            .write_capnp(|| builder.reborrow().init_margin_init());
1630        self.margin_maint
1631            .write_capnp(|| builder.reborrow().init_margin_maint());
1632        self.max_quantity
1633            .write_capnp(|| builder.reborrow().init_max_quantity());
1634        self.min_quantity
1635            .write_capnp(|| builder.reborrow().init_min_quantity());
1636        self.max_price
1637            .write_capnp(|| builder.reborrow().init_max_price());
1638        self.min_price
1639            .write_capnp(|| builder.reborrow().init_min_price());
1640        write_optional_ustr(self.tick_scheme, |value| {
1641            builder.reborrow().set_tick_scheme(value);
1642        });
1643
1644        write_optional_info(self.info.as_ref(), |bytes| {
1645            builder.reborrow().set_info(bytes);
1646        });
1647
1648        write_unix_nanos(self.ts_event, builder.reborrow().init_ts_event());
1649        write_unix_nanos(self.ts_init, builder.init_ts_init());
1650    }
1651}
1652
1653impl<'a> FromCapnp<'a> for OptionSpread {
1654    type Reader = instruments_capnp::option_spread::Reader<'a>;
1655
1656    fn from_capnp(reader: Self::Reader) -> Result<Self, Box<dyn Error>> {
1657        Ok(Self {
1658            id: InstrumentId::from_capnp(reader.get_id()?)?,
1659            raw_symbol: Symbol::from_capnp(reader.get_raw_symbol()?)?,
1660            asset_class: asset_class_from_capnp(reader.get_asset_class()?),
1661            exchange: read_optional_ustr(reader.has_exchange(), || reader.get_exchange())?,
1662            underlying: read_ustr(|| reader.get_underlying())?,
1663            strategy_type: read_ustr(|| reader.get_strategy_type())?,
1664            activation_ns: read_unix_nanos(|| reader.get_activation_ns())?,
1665            expiration_ns: read_unix_nanos(|| reader.get_expiration_ns())?,
1666            currency: Currency::from_capnp(reader.get_currency()?)?,
1667            price_precision: reader.get_price_precision(),
1668            price_increment: Price::from_capnp(reader.get_price_increment()?)?,
1669            size_increment: Quantity::from_capnp(reader.get_size_increment()?)?,
1670            size_precision: reader.get_size_precision(),
1671            multiplier: Quantity::from_capnp(reader.get_multiplier()?)?,
1672            lot_size: Quantity::from_capnp(reader.get_lot_size()?)?,
1673            margin_init: Decimal::from_capnp(reader.get_margin_init()?)?,
1674            margin_maint: Decimal::from_capnp(reader.get_margin_maint()?)?,
1675            max_quantity: read_optional_from_capnp(
1676                || reader.has_max_quantity(),
1677                || reader.get_max_quantity(),
1678            )?,
1679            min_quantity: read_optional_from_capnp(
1680                || reader.has_min_quantity(),
1681                || reader.get_min_quantity(),
1682            )?,
1683            max_price: read_optional_from_capnp(
1684                || reader.has_max_price(),
1685                || reader.get_max_price(),
1686            )?,
1687            min_price: read_optional_from_capnp(
1688                || reader.has_min_price(),
1689                || reader.get_min_price(),
1690            )?,
1691            tick_scheme: read_optional_ustr(reader.has_tick_scheme(), || reader.get_tick_scheme())?,
1692            info: read_optional_info(reader.has_info(), || reader.get_info())?,
1693            ts_event: read_unix_nanos(|| reader.get_ts_event())?,
1694            ts_init: read_unix_nanos(|| reader.get_ts_init())?,
1695        })
1696    }
1697}
1698
1699impl<'a> ToCapnp<'a> for PerpetualContract {
1700    type Builder = instruments_capnp::perpetual_contract::Builder<'a>;
1701
1702    fn to_capnp(&self, mut builder: Self::Builder) {
1703        self.id.write_capnp(|| builder.reborrow().init_id());
1704        self.raw_symbol
1705            .write_capnp(|| builder.reborrow().init_raw_symbol());
1706        builder.set_underlying(self.underlying.as_str());
1707        builder.set_asset_class(asset_class_to_capnp(self.asset_class));
1708        self.base_currency
1709            .write_capnp(|| builder.reborrow().init_base_currency());
1710        self.quote_currency
1711            .write_capnp(|| builder.reborrow().init_quote_currency());
1712        self.settlement_currency
1713            .write_capnp(|| builder.reborrow().init_settlement_currency());
1714        builder.set_is_inverse(self.is_inverse);
1715        builder.set_price_precision(self.price_precision);
1716        builder.set_size_precision(self.size_precision);
1717        self.price_increment
1718            .write_capnp(|| builder.reborrow().init_price_increment());
1719        self.size_increment
1720            .write_capnp(|| builder.reborrow().init_size_increment());
1721        self.multiplier
1722            .write_capnp(|| builder.reborrow().init_multiplier());
1723        self.lot_size
1724            .write_capnp(|| builder.reborrow().init_lot_size());
1725        self.margin_init
1726            .write_capnp(|| builder.reborrow().init_margin_init());
1727        self.margin_maint
1728            .write_capnp(|| builder.reborrow().init_margin_maint());
1729        self.max_quantity
1730            .write_capnp(|| builder.reborrow().init_max_quantity());
1731        self.min_quantity
1732            .write_capnp(|| builder.reborrow().init_min_quantity());
1733        self.max_notional
1734            .write_capnp(|| builder.reborrow().init_max_notional());
1735        self.min_notional
1736            .write_capnp(|| builder.reborrow().init_min_notional());
1737        self.max_price
1738            .write_capnp(|| builder.reborrow().init_max_price());
1739        self.min_price
1740            .write_capnp(|| builder.reborrow().init_min_price());
1741        write_optional_ustr(self.tick_scheme, |value| {
1742            builder.reborrow().set_tick_scheme(value);
1743        });
1744
1745        write_optional_info(self.info.as_ref(), |bytes| {
1746            builder.reborrow().set_info(bytes);
1747        });
1748
1749        write_unix_nanos(self.ts_event, builder.reborrow().init_ts_event());
1750        write_unix_nanos(self.ts_init, builder.init_ts_init());
1751    }
1752}
1753
1754impl<'a> FromCapnp<'a> for PerpetualContract {
1755    type Reader = instruments_capnp::perpetual_contract::Reader<'a>;
1756
1757    fn from_capnp(reader: Self::Reader) -> Result<Self, Box<dyn Error>> {
1758        Ok(Self {
1759            id: InstrumentId::from_capnp(reader.get_id()?)?,
1760            raw_symbol: Symbol::from_capnp(reader.get_raw_symbol()?)?,
1761            underlying: read_ustr(|| reader.get_underlying())?,
1762            asset_class: asset_class_from_capnp(reader.get_asset_class()?),
1763            base_currency: read_optional_from_capnp(
1764                || reader.has_base_currency(),
1765                || reader.get_base_currency(),
1766            )?,
1767            quote_currency: Currency::from_capnp(reader.get_quote_currency()?)?,
1768            settlement_currency: Currency::from_capnp(reader.get_settlement_currency()?)?,
1769            is_inverse: reader.get_is_inverse(),
1770            price_precision: reader.get_price_precision(),
1771            size_precision: reader.get_size_precision(),
1772            price_increment: Price::from_capnp(reader.get_price_increment()?)?,
1773            size_increment: Quantity::from_capnp(reader.get_size_increment()?)?,
1774            multiplier: Quantity::from_capnp(reader.get_multiplier()?)?,
1775            lot_size: Quantity::from_capnp(reader.get_lot_size()?)?,
1776            margin_init: Decimal::from_capnp(reader.get_margin_init()?)?,
1777            margin_maint: Decimal::from_capnp(reader.get_margin_maint()?)?,
1778            max_quantity: read_optional_from_capnp(
1779                || reader.has_max_quantity(),
1780                || reader.get_max_quantity(),
1781            )?,
1782            min_quantity: read_optional_from_capnp(
1783                || reader.has_min_quantity(),
1784                || reader.get_min_quantity(),
1785            )?,
1786            max_notional: read_optional_from_capnp(
1787                || reader.has_max_notional(),
1788                || reader.get_max_notional(),
1789            )?,
1790            min_notional: read_optional_from_capnp(
1791                || reader.has_min_notional(),
1792                || reader.get_min_notional(),
1793            )?,
1794            max_price: read_optional_from_capnp(
1795                || reader.has_max_price(),
1796                || reader.get_max_price(),
1797            )?,
1798            min_price: read_optional_from_capnp(
1799                || reader.has_min_price(),
1800                || reader.get_min_price(),
1801            )?,
1802            tick_scheme: read_optional_ustr(reader.has_tick_scheme(), || reader.get_tick_scheme())?,
1803            info: read_optional_info(reader.has_info(), || reader.get_info())?,
1804            ts_event: read_unix_nanos(|| reader.get_ts_event())?,
1805            ts_init: read_unix_nanos(|| reader.get_ts_init())?,
1806        })
1807    }
1808}
1809
1810impl<'a> ToCapnp<'a> for TokenizedAsset {
1811    type Builder = instruments_capnp::tokenized_asset::Builder<'a>;
1812
1813    fn to_capnp(&self, mut builder: Self::Builder) {
1814        self.id.write_capnp(|| builder.reborrow().init_id());
1815        self.raw_symbol
1816            .write_capnp(|| builder.reborrow().init_raw_symbol());
1817        builder.set_asset_class(asset_class_to_capnp(self.asset_class));
1818        self.base_currency
1819            .write_capnp(|| builder.reborrow().init_base_currency());
1820        self.quote_currency
1821            .write_capnp(|| builder.reborrow().init_quote_currency());
1822        write_optional_ustr(self.isin, |value| {
1823            builder.reborrow().set_isin(value);
1824        });
1825
1826        builder.set_price_precision(self.price_precision);
1827        builder.set_size_precision(self.size_precision);
1828        self.price_increment
1829            .write_capnp(|| builder.reborrow().init_price_increment());
1830        self.size_increment
1831            .write_capnp(|| builder.reborrow().init_size_increment());
1832        self.multiplier
1833            .write_capnp(|| builder.reborrow().init_multiplier());
1834        self.lot_size
1835            .write_capnp(|| builder.reborrow().init_lot_size());
1836        self.margin_init
1837            .write_capnp(|| builder.reborrow().init_margin_init());
1838        self.margin_maint
1839            .write_capnp(|| builder.reborrow().init_margin_maint());
1840        self.max_quantity
1841            .write_capnp(|| builder.reborrow().init_max_quantity());
1842        self.min_quantity
1843            .write_capnp(|| builder.reborrow().init_min_quantity());
1844        self.max_notional
1845            .write_capnp(|| builder.reborrow().init_max_notional());
1846        self.min_notional
1847            .write_capnp(|| builder.reborrow().init_min_notional());
1848        self.max_price
1849            .write_capnp(|| builder.reborrow().init_max_price());
1850        self.min_price
1851            .write_capnp(|| builder.reborrow().init_min_price());
1852        write_optional_ustr(self.tick_scheme, |value| {
1853            builder.reborrow().set_tick_scheme(value);
1854        });
1855
1856        write_optional_info(self.info.as_ref(), |bytes| {
1857            builder.reborrow().set_info(bytes);
1858        });
1859
1860        write_unix_nanos(self.ts_event, builder.reborrow().init_ts_event());
1861        write_unix_nanos(self.ts_init, builder.init_ts_init());
1862    }
1863}
1864
1865impl<'a> FromCapnp<'a> for TokenizedAsset {
1866    type Reader = instruments_capnp::tokenized_asset::Reader<'a>;
1867
1868    fn from_capnp(reader: Self::Reader) -> Result<Self, Box<dyn Error>> {
1869        Ok(Self {
1870            id: InstrumentId::from_capnp(reader.get_id()?)?,
1871            raw_symbol: Symbol::from_capnp(reader.get_raw_symbol()?)?,
1872            asset_class: asset_class_from_capnp(reader.get_asset_class()?),
1873            base_currency: Currency::from_capnp(reader.get_base_currency()?)?,
1874            quote_currency: Currency::from_capnp(reader.get_quote_currency()?)?,
1875            isin: read_optional_ustr(reader.has_isin(), || reader.get_isin())?,
1876            price_precision: reader.get_price_precision(),
1877            size_precision: reader.get_size_precision(),
1878            price_increment: Price::from_capnp(reader.get_price_increment()?)?,
1879            size_increment: Quantity::from_capnp(reader.get_size_increment()?)?,
1880            multiplier: Quantity::from_capnp(reader.get_multiplier()?)?,
1881            lot_size: read_optional_from_capnp(|| reader.has_lot_size(), || reader.get_lot_size())?,
1882            margin_init: Decimal::from_capnp(reader.get_margin_init()?)?,
1883            margin_maint: Decimal::from_capnp(reader.get_margin_maint()?)?,
1884            max_quantity: read_optional_from_capnp(
1885                || reader.has_max_quantity(),
1886                || reader.get_max_quantity(),
1887            )?,
1888            min_quantity: read_optional_from_capnp(
1889                || reader.has_min_quantity(),
1890                || reader.get_min_quantity(),
1891            )?,
1892            max_notional: read_optional_from_capnp(
1893                || reader.has_max_notional(),
1894                || reader.get_max_notional(),
1895            )?,
1896            min_notional: read_optional_from_capnp(
1897                || reader.has_min_notional(),
1898                || reader.get_min_notional(),
1899            )?,
1900            max_price: read_optional_from_capnp(
1901                || reader.has_max_price(),
1902                || reader.get_max_price(),
1903            )?,
1904            min_price: read_optional_from_capnp(
1905                || reader.has_min_price(),
1906                || reader.get_min_price(),
1907            )?,
1908            tick_scheme: read_optional_ustr(reader.has_tick_scheme(), || reader.get_tick_scheme())?,
1909            info: read_optional_info(reader.has_info(), || reader.get_info())?,
1910            ts_event: read_unix_nanos(|| reader.get_ts_event())?,
1911            ts_init: read_unix_nanos(|| reader.get_ts_init())?,
1912        })
1913    }
1914}
1915
1916impl<'a> ToCapnp<'a> for SyntheticInstrument {
1917    type Builder = instruments_capnp::synthetic_instrument::Builder<'a>;
1918
1919    fn to_capnp(&self, mut builder: Self::Builder) {
1920        self.id.write_capnp(|| builder.reborrow().init_id());
1921        builder.set_price_precision(self.price_precision);
1922        self.price_increment
1923            .write_capnp(|| builder.reborrow().init_price_increment());
1924        let mut components = builder
1925            .reborrow()
1926            .init_components(self.components.len() as u32);
1927        for (index, component) in self.components.iter().enumerate() {
1928            component.to_capnp(components.reborrow().get(index as u32));
1929        }
1930
1931        builder.set_formula(&self.formula);
1932        write_unix_nanos(self.ts_event, builder.reborrow().init_ts_event());
1933        write_unix_nanos(self.ts_init, builder.init_ts_init());
1934    }
1935}
1936
1937impl<'a> FromCapnp<'a> for SyntheticInstrument {
1938    type Reader = instruments_capnp::synthetic_instrument::Reader<'a>;
1939
1940    fn from_capnp(reader: Self::Reader) -> Result<Self, Box<dyn Error>> {
1941        let id = InstrumentId::from_capnp(reader.get_id()?)?;
1942        let price_increment = Price::from_capnp(reader.get_price_increment()?)?;
1943        let components_reader = reader.get_components()?;
1944        let mut components = Vec::with_capacity(components_reader.len() as usize);
1945        for component in components_reader {
1946            components.push(InstrumentId::from_capnp(component)?);
1947        }
1948
1949        let formula = reader.get_formula()?.to_str()?.to_owned();
1950
1951        // The builder compiles the formula and forces Venue::synthetic() plus a derived
1952        // increment. Restore the stored public fields so Cap'n Proto matches serde.
1953        let mut instrument = Self::builder()
1954            .symbol(id.symbol)
1955            .price_precision(reader.get_price_precision())
1956            .components(components)
1957            .formula(&formula)
1958            .ts_event(read_unix_nanos(|| reader.get_ts_event())?)
1959            .ts_init(read_unix_nanos(|| reader.get_ts_init())?)
1960            .build()?;
1961        instrument.id = id;
1962        instrument.price_increment = price_increment;
1963        Ok(instrument)
1964    }
1965}
1966
1967impl<'a> ToCapnp<'a> for InstrumentAny {
1968    type Builder = instruments_capnp::instrument_any::Builder<'a>;
1969
1970    fn to_capnp(&self, builder: Self::Builder) {
1971        match self {
1972            Self::Betting(value) => value.to_capnp(builder.init_betting()),
1973            Self::BinaryOption(value) => value.to_capnp(builder.init_binary_option()),
1974            Self::Cfd(value) => value.to_capnp(builder.init_cfd()),
1975            Self::Commodity(value) => value.to_capnp(builder.init_commodity()),
1976            Self::CryptoFuture(value) => value.to_capnp(builder.init_crypto_future()),
1977            Self::CryptoFuturesSpread(value) => {
1978                value.to_capnp(builder.init_crypto_futures_spread());
1979            }
1980            Self::CryptoOption(value) => value.to_capnp(builder.init_crypto_option()),
1981            Self::CryptoOptionSpread(value) => value.to_capnp(builder.init_crypto_option_spread()),
1982            Self::CryptoPerpetual(value) => value.to_capnp(builder.init_crypto_perpetual()),
1983            Self::CurrencyPair(value) => value.to_capnp(builder.init_currency_pair()),
1984            Self::Equity(value) => value.to_capnp(builder.init_equity()),
1985            Self::FuturesContract(value) => value.to_capnp(builder.init_futures_contract()),
1986            Self::FuturesSpread(value) => value.to_capnp(builder.init_futures_spread()),
1987            Self::IndexInstrument(value) => value.to_capnp(builder.init_index_instrument()),
1988            Self::OptionContract(value) => value.to_capnp(builder.init_option_contract()),
1989            Self::OptionSpread(value) => value.to_capnp(builder.init_option_spread()),
1990            Self::PerpetualContract(value) => value.to_capnp(builder.init_perpetual_contract()),
1991            Self::TokenizedAsset(value) => value.to_capnp(builder.init_tokenized_asset()),
1992        }
1993    }
1994}
1995
1996impl<'a> FromCapnp<'a> for InstrumentAny {
1997    type Reader = instruments_capnp::instrument_any::Reader<'a>;
1998
1999    #[rustfmt::skip]
2000    fn from_capnp(reader: Self::Reader) -> Result<Self, Box<dyn Error>> {
2001        match reader.which()? {
2002            instruments_capnp::instrument_any::Betting(reader) => Ok(Self::Betting(BettingInstrument::from_capnp(reader?)?)),
2003            instruments_capnp::instrument_any::BinaryOption(reader) => Ok(Self::BinaryOption(BinaryOption::from_capnp(reader?)?)),
2004            instruments_capnp::instrument_any::Cfd(reader) => Ok(Self::Cfd(Cfd::from_capnp(reader?)?)),
2005            instruments_capnp::instrument_any::Commodity(reader) => Ok(Self::Commodity(Commodity::from_capnp(reader?)?)),
2006            instruments_capnp::instrument_any::CryptoFuture(reader) => Ok(Self::CryptoFuture(CryptoFuture::from_capnp(reader?)?)),
2007            instruments_capnp::instrument_any::CryptoFuturesSpread(reader) => Ok(Self::CryptoFuturesSpread(CryptoFuturesSpread::from_capnp(reader?)?)),
2008            instruments_capnp::instrument_any::CryptoOption(reader) => Ok(Self::CryptoOption(CryptoOption::from_capnp(reader?)?)),
2009            instruments_capnp::instrument_any::CryptoOptionSpread(reader) => Ok(Self::CryptoOptionSpread(CryptoOptionSpread::from_capnp(reader?)?)),
2010            instruments_capnp::instrument_any::CryptoPerpetual(reader) => Ok(Self::CryptoPerpetual(CryptoPerpetual::from_capnp(reader?)?)),
2011            instruments_capnp::instrument_any::CurrencyPair(reader) => Ok(Self::CurrencyPair(CurrencyPair::from_capnp(reader?)?)),
2012            instruments_capnp::instrument_any::Equity(reader) => Ok(Self::Equity(Equity::from_capnp(reader?)?)),
2013            instruments_capnp::instrument_any::FuturesContract(reader) => Ok(Self::FuturesContract(FuturesContract::from_capnp(reader?)?)),
2014            instruments_capnp::instrument_any::FuturesSpread(reader) => Ok(Self::FuturesSpread(FuturesSpread::from_capnp(reader?)?)),
2015            instruments_capnp::instrument_any::IndexInstrument(reader) => Ok(Self::IndexInstrument(IndexInstrument::from_capnp(reader?)?)),
2016            instruments_capnp::instrument_any::OptionContract(reader) => Ok(Self::OptionContract(OptionContract::from_capnp(reader?)?)),
2017            instruments_capnp::instrument_any::OptionSpread(reader) => Ok(Self::OptionSpread(OptionSpread::from_capnp(reader?)?)),
2018            instruments_capnp::instrument_any::PerpetualContract(reader) => Ok(Self::PerpetualContract(PerpetualContract::from_capnp(reader?)?)),
2019            instruments_capnp::instrument_any::TokenizedAsset(reader) => Ok(Self::TokenizedAsset(TokenizedAsset::from_capnp(reader?)?)),
2020        }
2021    }
2022}
2023
2024/// Serializes an [`InstrumentAny`] to Cap'n Proto bytes.
2025///
2026/// # Errors
2027///
2028/// Returns an error if Cap'n Proto serialization fails.
2029pub fn serialize_instrument_any(instrument: &InstrumentAny) -> Result<Vec<u8>, Box<dyn Error>> {
2030    let mut message = capnp::message::Builder::new_default();
2031    let builder = message.init_root::<instruments_capnp::instrument_any::Builder>();
2032    instrument.to_capnp(builder);
2033
2034    let mut bytes = Vec::new();
2035    capnp::serialize::write_message(&mut bytes, &message)?;
2036    Ok(bytes)
2037}
2038
2039/// Deserializes an [`InstrumentAny`] from Cap'n Proto bytes.
2040///
2041/// # Errors
2042///
2043/// Returns an error if Cap'n Proto deserialization fails.
2044pub fn deserialize_instrument_any(bytes: &[u8]) -> Result<InstrumentAny, Box<dyn Error>> {
2045    let reader =
2046        capnp::serialize::read_message(&mut &bytes[..], capnp::message::ReaderOptions::new())?;
2047    let root = reader.get_root::<instruments_capnp::instrument_any::Reader>()?;
2048    InstrumentAny::from_capnp(root)
2049}