1use nautilus_core::UnixNanos;
17use rust_decimal::Decimal;
18use ustr::Ustr;
19
20use super::{
21 betting::BettingInstrument, binary_option::BinaryOption, crypto_future::CryptoFuture,
22 crypto_perpetual::CryptoPerpetual, currency_pair::CurrencyPair, equity::Equity,
23 futures_contract::FuturesContract, futures_spread::FuturesSpread,
24 option_contract::OptionContract, option_spread::OptionSpread, Instrument,
25};
26use crate::{
27 enums::InstrumentClass,
28 identifiers::{InstrumentId, Symbol, Venue},
29 types::{Currency, Money, Price, Quantity},
30};
31
32#[derive(Clone, Debug)]
33pub enum InstrumentAny {
34 Betting(BettingInstrument),
35 BinaryOption(BinaryOption),
36 CryptoFuture(CryptoFuture),
37 CryptoPerpetual(CryptoPerpetual),
38 CurrencyPair(CurrencyPair),
39 Equity(Equity),
40 FuturesContract(FuturesContract),
41 FuturesSpread(FuturesSpread),
42 OptionContract(OptionContract),
43 OptionSpread(OptionSpread),
44}
45
46impl InstrumentAny {
47 #[must_use]
49 pub fn into_instrument(self) -> Box<dyn Instrument> {
50 match self {
51 Self::Betting(inst) => Box::new(inst),
52 Self::BinaryOption(inst) => Box::new(inst),
53 Self::CryptoFuture(inst) => Box::new(inst),
54 Self::CryptoPerpetual(inst) => Box::new(inst),
55 Self::CurrencyPair(inst) => Box::new(inst),
56 Self::Equity(inst) => Box::new(inst),
57 Self::FuturesContract(inst) => Box::new(inst),
58 Self::FuturesSpread(inst) => Box::new(inst),
59 Self::OptionContract(inst) => Box::new(inst),
60 Self::OptionSpread(inst) => Box::new(inst),
61 }
62 }
63
64 #[must_use]
65 pub fn instrument_class(&self) -> InstrumentClass {
66 match self {
67 Self::Betting(inst) => inst.instrument_class(),
68 Self::BinaryOption(inst) => inst.instrument_class(),
69 Self::CryptoFuture(inst) => inst.instrument_class(),
70 Self::CryptoPerpetual(inst) => inst.instrument_class(),
71 Self::CurrencyPair(inst) => inst.instrument_class(),
72 Self::Equity(inst) => inst.instrument_class(),
73 Self::FuturesContract(inst) => inst.instrument_class(),
74 Self::FuturesSpread(inst) => inst.instrument_class(),
75 Self::OptionContract(inst) => inst.instrument_class(),
76 Self::OptionSpread(inst) => inst.instrument_class(),
77 }
78 }
79
80 #[must_use]
81 pub fn id(&self) -> InstrumentId {
82 match self {
83 Self::Betting(inst) => inst.id,
84 Self::BinaryOption(inst) => inst.id,
85 Self::CryptoFuture(inst) => inst.id,
86 Self::CryptoPerpetual(inst) => inst.id,
87 Self::CurrencyPair(inst) => inst.id,
88 Self::Equity(inst) => inst.id,
89 Self::FuturesContract(inst) => inst.id,
90 Self::FuturesSpread(inst) => inst.id,
91 Self::OptionContract(inst) => inst.id,
92 Self::OptionSpread(inst) => inst.id,
93 }
94 }
95
96 #[must_use]
97 pub fn symbol(&self) -> Symbol {
98 match self {
99 Self::Betting(inst) => inst.id.symbol,
100 Self::BinaryOption(inst) => inst.id.symbol,
101 Self::CryptoFuture(inst) => inst.id.symbol,
102 Self::CryptoPerpetual(inst) => inst.id.symbol,
103 Self::CurrencyPair(inst) => inst.id.symbol,
104 Self::Equity(inst) => inst.id.symbol,
105 Self::FuturesContract(inst) => inst.id.symbol,
106 Self::FuturesSpread(inst) => inst.id.symbol,
107 Self::OptionContract(inst) => inst.id.symbol,
108 Self::OptionSpread(inst) => inst.id.symbol,
109 }
110 }
111
112 #[must_use]
113 pub fn venue(&self) -> Venue {
114 match self {
115 Self::Betting(inst) => inst.id.venue,
116 Self::BinaryOption(inst) => inst.id.venue,
117 Self::CryptoFuture(inst) => inst.id.venue,
118 Self::CryptoPerpetual(inst) => inst.id.venue,
119 Self::CurrencyPair(inst) => inst.id.venue,
120 Self::Equity(inst) => inst.id.venue,
121 Self::FuturesContract(inst) => inst.id.venue,
122 Self::FuturesSpread(inst) => inst.id.venue,
123 Self::OptionContract(inst) => inst.id.venue,
124 Self::OptionSpread(inst) => inst.id.venue,
125 }
126 }
127
128 #[must_use]
129 pub fn raw_symbol(&self) -> Symbol {
130 match self {
131 Self::Betting(inst) => inst.raw_symbol(),
132 Self::BinaryOption(inst) => inst.raw_symbol(),
133 Self::CryptoFuture(inst) => inst.raw_symbol(),
134 Self::CryptoPerpetual(inst) => inst.raw_symbol(),
135 Self::CurrencyPair(inst) => inst.raw_symbol(),
136 Self::Equity(inst) => inst.raw_symbol(),
137 Self::FuturesContract(inst) => inst.raw_symbol(),
138 Self::FuturesSpread(inst) => inst.raw_symbol(),
139 Self::OptionContract(inst) => inst.raw_symbol(),
140 Self::OptionSpread(inst) => inst.raw_symbol(),
141 }
142 }
143
144 #[must_use]
145 pub fn underlying(&self) -> Option<&Ustr> {
146 match self {
147 Self::Betting(_) => None,
148 Self::BinaryOption(_) => None,
149 Self::CryptoFuture(inst) => Some(&inst.underlying.code),
150 Self::CryptoPerpetual(_) => None,
151 Self::CurrencyPair(_) => None,
152 Self::Equity(_) => None,
153 Self::FuturesContract(inst) => Some(&inst.underlying),
154 Self::FuturesSpread(inst) => Some(&inst.underlying),
155 Self::OptionContract(inst) => Some(&inst.underlying),
156 Self::OptionSpread(inst) => Some(&inst.underlying),
157 }
158 }
159
160 #[must_use]
161 pub fn base_currency(&self) -> Option<Currency> {
162 match self {
163 Self::Betting(inst) => inst.base_currency(),
164 Self::BinaryOption(inst) => inst.base_currency(),
165 Self::CryptoFuture(inst) => inst.base_currency(),
166 Self::CryptoPerpetual(inst) => inst.base_currency(),
167 Self::CurrencyPair(inst) => inst.base_currency(),
168 Self::Equity(inst) => inst.base_currency(),
169 Self::FuturesContract(inst) => inst.base_currency(),
170 Self::FuturesSpread(inst) => inst.base_currency(),
171 Self::OptionContract(inst) => inst.base_currency(),
172 Self::OptionSpread(inst) => inst.base_currency(),
173 }
174 }
175
176 #[must_use]
177 pub fn quote_currency(&self) -> Currency {
178 match self {
179 Self::Betting(inst) => inst.quote_currency(),
180 Self::BinaryOption(inst) => inst.quote_currency(),
181 Self::CryptoFuture(inst) => inst.quote_currency(),
182 Self::CryptoPerpetual(inst) => inst.quote_currency(),
183 Self::CurrencyPair(inst) => inst.quote_currency(),
184 Self::Equity(inst) => inst.quote_currency(),
185 Self::FuturesContract(inst) => inst.quote_currency(),
186 Self::FuturesSpread(inst) => inst.quote_currency(),
187 Self::OptionContract(inst) => inst.quote_currency(),
188 Self::OptionSpread(inst) => inst.quote_currency(),
189 }
190 }
191
192 #[must_use]
193 pub fn settlement_currency(&self) -> Currency {
194 match self {
195 Self::Betting(inst) => inst.settlement_currency(),
196 Self::BinaryOption(inst) => inst.settlement_currency(),
197 Self::CryptoFuture(inst) => inst.settlement_currency(),
198 Self::CryptoPerpetual(inst) => inst.settlement_currency(),
199 Self::CurrencyPair(inst) => inst.settlement_currency(),
200 Self::Equity(inst) => inst.settlement_currency(),
201 Self::FuturesContract(inst) => inst.settlement_currency(),
202 Self::FuturesSpread(inst) => inst.settlement_currency(),
203 Self::OptionContract(inst) => inst.settlement_currency(),
204 Self::OptionSpread(inst) => inst.settlement_currency(),
205 }
206 }
207
208 #[must_use]
209 pub fn is_inverse(&self) -> bool {
210 match self {
211 Self::Betting(inst) => inst.is_inverse(),
212 Self::BinaryOption(inst) => inst.is_inverse(),
213 Self::CryptoFuture(inst) => inst.is_inverse(),
214 Self::CryptoPerpetual(inst) => inst.is_inverse(),
215 Self::CurrencyPair(inst) => inst.is_inverse(),
216 Self::Equity(inst) => inst.is_inverse(),
217 Self::FuturesContract(inst) => inst.is_inverse(),
218 Self::FuturesSpread(inst) => inst.is_inverse(),
219 Self::OptionContract(inst) => inst.is_inverse(),
220 Self::OptionSpread(inst) => inst.is_inverse(),
221 }
222 }
223
224 #[must_use]
225 pub fn price_precision(&self) -> u8 {
226 match self {
227 Self::Betting(inst) => inst.price_precision(),
228 Self::BinaryOption(inst) => inst.price_precision(),
229 Self::CryptoFuture(inst) => inst.price_precision(),
230 Self::CryptoPerpetual(inst) => inst.price_precision(),
231 Self::CurrencyPair(inst) => inst.price_precision(),
232 Self::Equity(inst) => inst.price_precision(),
233 Self::FuturesContract(inst) => inst.price_precision(),
234 Self::FuturesSpread(inst) => inst.price_precision(),
235 Self::OptionContract(inst) => inst.price_precision(),
236 Self::OptionSpread(inst) => inst.price_precision(),
237 }
238 }
239
240 #[must_use]
241 pub fn size_precision(&self) -> u8 {
242 match self {
243 Self::Betting(inst) => inst.size_precision(),
244 Self::BinaryOption(inst) => inst.size_precision(),
245 Self::CryptoFuture(inst) => inst.size_precision(),
246 Self::CryptoPerpetual(inst) => inst.size_precision(),
247 Self::CurrencyPair(inst) => inst.size_precision(),
248 Self::Equity(inst) => inst.size_precision(),
249 Self::FuturesContract(inst) => inst.size_precision(),
250 Self::FuturesSpread(inst) => inst.size_precision(),
251 Self::OptionContract(inst) => inst.size_precision(),
252 Self::OptionSpread(inst) => inst.size_precision(),
253 }
254 }
255
256 #[must_use]
257 pub fn price_increment(&self) -> Price {
258 match self {
259 Self::Betting(inst) => inst.price_increment(),
260 Self::BinaryOption(inst) => inst.price_increment(),
261 Self::CryptoFuture(inst) => inst.price_increment(),
262 Self::CryptoPerpetual(inst) => inst.price_increment(),
263 Self::CurrencyPair(inst) => inst.price_increment(),
264 Self::Equity(inst) => inst.price_increment(),
265 Self::FuturesContract(inst) => inst.price_increment(),
266 Self::FuturesSpread(inst) => inst.price_increment(),
267 Self::OptionContract(inst) => inst.price_increment(),
268 Self::OptionSpread(inst) => inst.price_increment(),
269 }
270 }
271
272 #[must_use]
273 pub fn size_increment(&self) -> Quantity {
274 match self {
275 Self::Betting(inst) => inst.size_increment(),
276 Self::BinaryOption(inst) => inst.size_increment(),
277 Self::CryptoFuture(inst) => inst.size_increment(),
278 Self::CryptoPerpetual(inst) => inst.size_increment(),
279 Self::CurrencyPair(inst) => inst.size_increment(),
280 Self::Equity(inst) => inst.size_increment(),
281 Self::FuturesContract(inst) => inst.size_increment(),
282 Self::FuturesSpread(inst) => inst.size_increment(),
283 Self::OptionContract(inst) => inst.size_increment(),
284 Self::OptionSpread(inst) => inst.size_increment(),
285 }
286 }
287
288 #[must_use]
289 pub fn multiplier(&self) -> Quantity {
290 match self {
291 Self::Betting(inst) => inst.multiplier(),
292 Self::BinaryOption(inst) => inst.multiplier(),
293 Self::CryptoFuture(inst) => inst.multiplier(),
294 Self::CryptoPerpetual(inst) => inst.multiplier(),
295 Self::CurrencyPair(inst) => inst.multiplier(),
296 Self::Equity(inst) => inst.multiplier(),
297 Self::FuturesContract(inst) => inst.multiplier(),
298 Self::FuturesSpread(inst) => inst.multiplier(),
299 Self::OptionContract(inst) => inst.multiplier(),
300 Self::OptionSpread(inst) => inst.multiplier(),
301 }
302 }
303
304 #[must_use]
305 pub fn activation_ns(&self) -> Option<UnixNanos> {
306 match self {
307 Self::Betting(inst) => inst.activation_ns(),
308 Self::BinaryOption(inst) => inst.activation_ns(),
309 Self::CryptoFuture(inst) => inst.activation_ns(),
310 Self::CryptoPerpetual(inst) => inst.activation_ns(),
311 Self::CurrencyPair(inst) => inst.activation_ns(),
312 Self::Equity(inst) => inst.activation_ns(),
313 Self::FuturesContract(inst) => inst.activation_ns(),
314 Self::FuturesSpread(inst) => inst.activation_ns(),
315 Self::OptionContract(inst) => inst.activation_ns(),
316 Self::OptionSpread(inst) => inst.activation_ns(),
317 }
318 }
319
320 #[must_use]
321 pub fn expiration_ns(&self) -> Option<UnixNanos> {
322 match self {
323 Self::Betting(inst) => inst.expiration_ns(),
324 Self::BinaryOption(inst) => inst.expiration_ns(),
325 Self::CryptoFuture(inst) => inst.expiration_ns(),
326 Self::CryptoPerpetual(inst) => inst.expiration_ns(),
327 Self::CurrencyPair(inst) => inst.expiration_ns(),
328 Self::Equity(inst) => inst.expiration_ns(),
329 Self::FuturesContract(inst) => inst.expiration_ns(),
330 Self::FuturesSpread(inst) => inst.expiration_ns(),
331 Self::OptionContract(inst) => inst.expiration_ns(),
332 Self::OptionSpread(inst) => inst.expiration_ns(),
333 }
334 }
335
336 pub fn max_quantity(&self) -> Option<Quantity> {
337 match self {
338 Self::Betting(inst) => inst.max_quantity(),
339 Self::BinaryOption(inst) => inst.max_quantity(),
340 Self::CryptoFuture(inst) => inst.max_quantity(),
341 Self::CryptoPerpetual(inst) => inst.max_quantity(),
342 Self::CurrencyPair(inst) => inst.max_quantity(),
343 Self::Equity(inst) => inst.max_quantity(),
344 Self::FuturesContract(inst) => inst.max_quantity(),
345 Self::FuturesSpread(inst) => inst.max_quantity(),
346 Self::OptionContract(inst) => inst.max_quantity(),
347 Self::OptionSpread(inst) => inst.max_quantity(),
348 }
349 }
350
351 pub fn min_quantity(&self) -> Option<Quantity> {
352 match self {
353 Self::Betting(inst) => inst.min_quantity(),
354 Self::BinaryOption(inst) => inst.min_quantity(),
355 Self::CryptoFuture(inst) => inst.min_quantity(),
356 Self::CryptoPerpetual(inst) => inst.min_quantity(),
357 Self::CurrencyPair(inst) => inst.min_quantity(),
358 Self::Equity(inst) => inst.min_quantity(),
359 Self::FuturesContract(inst) => inst.min_quantity(),
360 Self::FuturesSpread(inst) => inst.min_quantity(),
361 Self::OptionContract(inst) => inst.min_quantity(),
362 Self::OptionSpread(inst) => inst.min_quantity(),
363 }
364 }
365
366 pub fn max_notional(&self) -> Option<Money> {
367 match self {
368 Self::Betting(inst) => inst.max_notional(),
369 Self::BinaryOption(inst) => inst.max_notional(),
370 Self::CryptoFuture(inst) => inst.max_notional(),
371 Self::CryptoPerpetual(inst) => inst.max_notional(),
372 Self::CurrencyPair(inst) => inst.max_notional(),
373 Self::Equity(inst) => inst.max_notional(),
374 Self::FuturesContract(inst) => inst.max_notional(),
375 Self::FuturesSpread(inst) => inst.max_notional(),
376 Self::OptionContract(inst) => inst.max_notional(),
377 Self::OptionSpread(inst) => inst.max_notional(),
378 }
379 }
380
381 pub fn min_notional(&self) -> Option<Money> {
382 match self {
383 Self::Betting(inst) => inst.min_notional(),
384 Self::BinaryOption(inst) => inst.min_notional(),
385 Self::CryptoFuture(inst) => inst.min_notional(),
386 Self::CryptoPerpetual(inst) => inst.min_notional(),
387 Self::CurrencyPair(inst) => inst.min_notional(),
388 Self::Equity(inst) => inst.min_notional(),
389 Self::FuturesContract(inst) => inst.min_notional(),
390 Self::FuturesSpread(inst) => inst.min_notional(),
391 Self::OptionContract(inst) => inst.min_notional(),
392 Self::OptionSpread(inst) => inst.min_notional(),
393 }
394 }
395
396 pub fn make_price(&self, value: f64) -> Price {
397 match self {
398 Self::Betting(inst) => inst.make_price(value),
399 Self::BinaryOption(inst) => inst.make_price(value),
400 Self::CryptoFuture(inst) => inst.make_price(value),
401 Self::CryptoPerpetual(inst) => inst.make_price(value),
402 Self::CurrencyPair(inst) => inst.make_price(value),
403 Self::Equity(inst) => inst.make_price(value),
404 Self::FuturesContract(inst) => inst.make_price(value),
405 Self::FuturesSpread(inst) => inst.make_price(value),
406 Self::OptionContract(inst) => inst.make_price(value),
407 Self::OptionSpread(inst) => inst.make_price(value),
408 }
409 }
410
411 pub fn make_qty(&self, value: f64) -> Quantity {
412 match self {
413 Self::Betting(inst) => inst.make_qty(value),
414 Self::BinaryOption(inst) => inst.make_qty(value),
415 Self::CryptoFuture(inst) => inst.make_qty(value),
416 Self::CryptoPerpetual(inst) => inst.make_qty(value),
417 Self::CurrencyPair(inst) => inst.make_qty(value),
418 Self::Equity(inst) => inst.make_qty(value),
419 Self::FuturesContract(inst) => inst.make_qty(value),
420 Self::FuturesSpread(inst) => inst.make_qty(value),
421 Self::OptionContract(inst) => inst.make_qty(value),
422 Self::OptionSpread(inst) => inst.make_qty(value),
423 }
424 }
425
426 #[must_use]
427 pub fn calculate_notional_value(
428 &self,
429 quantity: Quantity,
430 price: Price,
431 use_quote_for_inverse: Option<bool>,
432 ) -> Money {
433 match self {
434 Self::Betting(inst) => {
435 inst.calculate_notional_value(quantity, price, use_quote_for_inverse)
436 }
437 Self::BinaryOption(inst) => {
438 inst.calculate_notional_value(quantity, price, use_quote_for_inverse)
439 }
440 Self::CryptoFuture(inst) => {
441 inst.calculate_notional_value(quantity, price, use_quote_for_inverse)
442 }
443 Self::CryptoPerpetual(inst) => {
444 inst.calculate_notional_value(quantity, price, use_quote_for_inverse)
445 }
446 Self::CurrencyPair(inst) => {
447 inst.calculate_notional_value(quantity, price, use_quote_for_inverse)
448 }
449 Self::Equity(inst) => {
450 inst.calculate_notional_value(quantity, price, use_quote_for_inverse)
451 }
452 Self::FuturesContract(inst) => {
453 inst.calculate_notional_value(quantity, price, use_quote_for_inverse)
454 }
455 Self::FuturesSpread(inst) => {
456 inst.calculate_notional_value(quantity, price, use_quote_for_inverse)
457 }
458 Self::OptionContract(inst) => {
459 inst.calculate_notional_value(quantity, price, use_quote_for_inverse)
460 }
461 Self::OptionSpread(inst) => {
462 inst.calculate_notional_value(quantity, price, use_quote_for_inverse)
463 }
464 }
465 }
466
467 #[must_use]
469 pub fn maker_fee(&self) -> Decimal {
470 match self {
471 Self::Betting(inst) => inst.maker_fee(),
472 Self::BinaryOption(inst) => inst.maker_fee(),
473 Self::CryptoFuture(inst) => inst.maker_fee(),
474 Self::CryptoPerpetual(inst) => inst.maker_fee(),
475 Self::CurrencyPair(inst) => inst.maker_fee(),
476 Self::Equity(inst) => inst.maker_fee(),
477 Self::FuturesContract(inst) => inst.maker_fee(),
478 Self::FuturesSpread(inst) => inst.maker_fee(),
479 Self::OptionContract(inst) => inst.maker_fee(),
480 Self::OptionSpread(inst) => inst.maker_fee(),
481 }
482 }
483
484 #[must_use]
486 pub fn taker_fee(&self) -> Decimal {
487 match self {
488 Self::Betting(inst) => inst.taker_fee(),
489 Self::BinaryOption(inst) => inst.taker_fee(),
490 Self::CryptoFuture(inst) => inst.taker_fee(),
491 Self::CryptoPerpetual(inst) => inst.taker_fee(),
492 Self::CurrencyPair(inst) => inst.taker_fee(),
493 Self::Equity(inst) => inst.taker_fee(),
494 Self::FuturesContract(inst) => inst.taker_fee(),
495 Self::FuturesSpread(inst) => inst.taker_fee(),
496 Self::OptionContract(inst) => inst.taker_fee(),
497 Self::OptionSpread(inst) => inst.taker_fee(),
498 }
499 }
500
501 pub fn get_base_quantity(&self, quantity: Quantity, last_px: Price) -> Quantity {
502 match self {
503 Self::Betting(inst) => inst.calculate_base_quantity(quantity, last_px),
504 Self::BinaryOption(inst) => inst.calculate_base_quantity(quantity, last_px),
505 Self::CryptoFuture(inst) => inst.calculate_base_quantity(quantity, last_px),
506 Self::CryptoPerpetual(inst) => inst.calculate_base_quantity(quantity, last_px),
507 Self::CurrencyPair(inst) => inst.calculate_base_quantity(quantity, last_px),
508 Self::Equity(inst) => inst.calculate_base_quantity(quantity, last_px),
509 Self::FuturesContract(inst) => inst.calculate_base_quantity(quantity, last_px),
510 Self::FuturesSpread(inst) => inst.calculate_base_quantity(quantity, last_px),
511 Self::OptionContract(inst) => inst.calculate_base_quantity(quantity, last_px),
512 Self::OptionSpread(inst) => inst.calculate_base_quantity(quantity, last_px),
513 }
514 }
515}
516
517impl PartialEq for InstrumentAny {
518 fn eq(&self, other: &Self) -> bool {
519 self.id() == other.id()
520 }
521}