nautilus_model/instruments/
mod.rs1pub mod any;
19pub mod betting;
20pub mod binary_option;
21pub mod crypto_future;
22pub mod crypto_perpetual;
23pub mod currency_pair;
24pub mod equity;
25pub mod futures_contract;
26pub mod futures_spread;
27pub mod option_contract;
28pub mod option_spread;
29pub mod synthetic;
30
31#[cfg(feature = "stubs")]
32pub mod stubs;
33
34use nautilus_core::UnixNanos;
35use rust_decimal::Decimal;
36use rust_decimal_macros::dec;
37use ustr::Ustr;
38
39pub use crate::instruments::{
41 any::InstrumentAny, betting::BettingInstrument, binary_option::BinaryOption,
42 crypto_future::CryptoFuture, crypto_perpetual::CryptoPerpetual, currency_pair::CurrencyPair,
43 equity::Equity, futures_contract::FuturesContract, futures_spread::FuturesSpread,
44 option_contract::OptionContract, option_spread::OptionSpread, synthetic::SyntheticInstrument,
45};
46use crate::{
47 enums::{AssetClass, InstrumentClass, OptionKind},
48 identifiers::{InstrumentId, Symbol, Venue},
49 types::{Currency, Money, Price, Quantity},
50};
51
52pub trait Instrument: 'static + Send {
53 fn into_any(self) -> InstrumentAny;
54 fn id(&self) -> InstrumentId;
55 fn symbol(&self) -> Symbol {
56 self.id().symbol
57 }
58 fn venue(&self) -> Venue {
59 self.id().venue
60 }
61 fn raw_symbol(&self) -> Symbol;
62 fn asset_class(&self) -> AssetClass;
63 fn instrument_class(&self) -> InstrumentClass;
64 fn underlying(&self) -> Option<Ustr>;
65 fn base_currency(&self) -> Option<Currency>;
66 fn quote_currency(&self) -> Currency;
67 fn settlement_currency(&self) -> Currency;
68 fn isin(&self) -> Option<Ustr>;
69 fn option_kind(&self) -> Option<OptionKind>;
70 fn exchange(&self) -> Option<Ustr>;
71 fn strike_price(&self) -> Option<Price>;
72 fn activation_ns(&self) -> Option<UnixNanos>;
73 fn expiration_ns(&self) -> Option<UnixNanos>;
74 fn is_inverse(&self) -> bool;
75 fn price_precision(&self) -> u8;
76 fn size_precision(&self) -> u8;
77 fn price_increment(&self) -> Price;
78 fn size_increment(&self) -> Quantity;
79 fn multiplier(&self) -> Quantity;
80 fn lot_size(&self) -> Option<Quantity>;
81 fn max_quantity(&self) -> Option<Quantity>;
82 fn min_quantity(&self) -> Option<Quantity>;
83 fn max_notional(&self) -> Option<Money>;
84 fn min_notional(&self) -> Option<Money>;
85 fn max_price(&self) -> Option<Price>;
86 fn min_price(&self) -> Option<Price>;
87 fn margin_init(&self) -> Decimal {
88 dec!(0) }
90
91 fn margin_maint(&self) -> Decimal {
92 dec!(0) }
94
95 fn maker_fee(&self) -> Decimal {
96 dec!(0) }
98
99 fn taker_fee(&self) -> Decimal {
100 dec!(0) }
102 fn ts_event(&self) -> UnixNanos;
103 fn ts_init(&self) -> UnixNanos;
104
105 fn make_price(&self, value: f64) -> Price {
107 Price::new(value, self.price_precision())
108 }
109
110 fn make_qty(&self, value: f64) -> Quantity {
112 Quantity::new(value, self.size_precision())
113 }
114
115 fn calculate_notional_value(
123 &self,
124 quantity: Quantity,
125 price: Price,
126 use_quote_for_inverse: Option<bool>,
127 ) -> Money {
128 let use_quote_for_inverse = use_quote_for_inverse.unwrap_or(false);
129 let (amount, currency) = if self.is_inverse() {
130 if use_quote_for_inverse {
131 (quantity.as_f64(), self.quote_currency())
132 } else {
133 let amount =
134 quantity.as_f64() * self.multiplier().as_f64() * (1.0 / price.as_f64());
135 let currency = self
136 .base_currency()
137 .expect("Error: no base currency for notional calculation");
138 (amount, currency)
139 }
140 } else {
141 let amount = quantity.as_f64() * self.multiplier().as_f64() * price.as_f64();
142 let currency = self.quote_currency();
143 (amount, currency)
144 };
145
146 Money::new(amount, currency)
147 }
148
149 fn calculate_base_quantity(&self, quantity: Quantity, last_px: Price) -> Quantity {
151 let value = quantity.as_f64() * (1.0 / last_px.as_f64());
152 Quantity::new(value, self.size_precision())
153 }
154}
155
156pub const EXPIRING_INSTRUMENT_TYPES: [InstrumentClass; 4] = [
157 InstrumentClass::Future,
158 InstrumentClass::FuturesSpread,
159 InstrumentClass::Option,
160 InstrumentClass::OptionSpread,
161];