nautilus_model/instruments/
any.rs1use enum_dispatch::enum_dispatch;
17use serde::{Deserialize, Serialize};
18
19use super::{
20 Instrument, betting::BettingInstrument, binary_option::BinaryOption, cfd::Cfd,
21 commodity::Commodity, crypto_future::CryptoFuture, crypto_futures_spread::CryptoFuturesSpread,
22 crypto_option::CryptoOption, crypto_option_spread::CryptoOptionSpread,
23 crypto_perpetual::CryptoPerpetual, currency_pair::CurrencyPair, equity::Equity,
24 futures_contract::FuturesContract, futures_spread::FuturesSpread,
25 index_instrument::IndexInstrument, option_contract::OptionContract,
26 option_spread::OptionSpread, perpetual_contract::PerpetualContract,
27 tokenized_asset::TokenizedAsset,
28};
29use crate::types::{Price, Quantity};
30
31#[derive(Clone, Debug, Serialize, Deserialize)]
32#[enum_dispatch(Instrument)]
33pub enum InstrumentAny {
34 Betting(BettingInstrument),
35 BinaryOption(BinaryOption),
36 Cfd(Cfd),
37 Commodity(Commodity),
38 CryptoFuture(CryptoFuture),
39 CryptoFuturesSpread(CryptoFuturesSpread),
40 CryptoOption(CryptoOption),
41 CryptoOptionSpread(CryptoOptionSpread),
42 CryptoPerpetual(CryptoPerpetual),
43 CurrencyPair(CurrencyPair),
44 Equity(Equity),
45 FuturesContract(FuturesContract),
46 FuturesSpread(FuturesSpread),
47 IndexInstrument(IndexInstrument),
48 OptionContract(OptionContract),
49 OptionSpread(OptionSpread),
50 PerpetualContract(PerpetualContract),
51 TokenizedAsset(TokenizedAsset),
52}
53
54impl InstrumentAny {
56 #[must_use]
57 pub fn get_base_quantity(&self, quantity: Quantity, last_px: Price) -> Quantity {
58 match self {
59 Self::Betting(inst) => inst.calculate_base_quantity(quantity, last_px),
60 Self::BinaryOption(inst) => inst.calculate_base_quantity(quantity, last_px),
61 Self::Cfd(inst) => inst.calculate_base_quantity(quantity, last_px),
62 Self::Commodity(inst) => inst.calculate_base_quantity(quantity, last_px),
63 Self::CryptoFuture(inst) => inst.calculate_base_quantity(quantity, last_px),
64 Self::CryptoFuturesSpread(inst) => inst.calculate_base_quantity(quantity, last_px),
65 Self::CryptoOption(inst) => inst.calculate_base_quantity(quantity, last_px),
66 Self::CryptoOptionSpread(inst) => inst.calculate_base_quantity(quantity, last_px),
67 Self::CryptoPerpetual(inst) => inst.calculate_base_quantity(quantity, last_px),
68 Self::CurrencyPair(inst) => inst.calculate_base_quantity(quantity, last_px),
69 Self::Equity(inst) => inst.calculate_base_quantity(quantity, last_px),
70 Self::FuturesContract(inst) => inst.calculate_base_quantity(quantity, last_px),
71 Self::FuturesSpread(inst) => inst.calculate_base_quantity(quantity, last_px),
72 Self::IndexInstrument(inst) => inst.calculate_base_quantity(quantity, last_px),
73 Self::OptionContract(inst) => inst.calculate_base_quantity(quantity, last_px),
74 Self::OptionSpread(inst) => inst.calculate_base_quantity(quantity, last_px),
75 Self::PerpetualContract(inst) => inst.calculate_base_quantity(quantity, last_px),
76 Self::TokenizedAsset(inst) => inst.calculate_base_quantity(quantity, last_px),
77 }
78 }
79
80 #[must_use]
82 pub fn is_spread(&self) -> bool {
83 matches!(
84 self,
85 Self::FuturesSpread(_)
86 | Self::OptionSpread(_)
87 | Self::CryptoFuturesSpread(_)
88 | Self::CryptoOptionSpread(_)
89 )
90 }
91}
92
93impl PartialEq for InstrumentAny {
94 fn eq(&self, other: &Self) -> bool {
95 self.id() == other.id()
96 }
97}
98
99impl crate::data::HasTsInit for InstrumentAny {
100 fn ts_init(&self) -> nautilus_core::UnixNanos {
101 Instrument::ts_init(self)
102 }
103}
104
105#[cfg(test)]
106mod tests {
107 use rstest::rstest;
108
109 use super::*;
110 use crate::instruments::stubs::*;
111
112 #[rstest]
113 #[case::futures_spread(InstrumentAny::FuturesSpread(futures_spread_es()), true)]
114 #[case::option_spread(InstrumentAny::OptionSpread(option_spread()), true)]
115 #[case::crypto_futures_spread(
116 InstrumentAny::CryptoFuturesSpread(crypto_futures_spread_btc_deribit()),
117 true
118 )]
119 #[case::crypto_option_spread(
120 InstrumentAny::CryptoOptionSpread(crypto_option_spread_btc_deribit()),
121 true
122 )]
123 #[case::crypto_future(
124 InstrumentAny::CryptoFuture(crypto_future_btcusdt(
125 2,
126 6,
127 crate::types::Price::from("0.01"),
128 crate::types::Quantity::from("0.000001"),
129 )),
130 false
131 )]
132 #[case::crypto_option(
133 InstrumentAny::CryptoOption(crypto_option_btc_deribit(
134 3,
135 1,
136 crate::types::Price::from("0.001"),
137 crate::types::Quantity::from("0.1"),
138 )),
139 false
140 )]
141 fn test_is_spread(#[case] instrument: InstrumentAny, #[case] expected: bool) {
142 assert_eq!(instrument.is_spread(), expected);
143 }
144}