nautilus_model/instruments/
mod.rspub mod any;
pub mod betting;
pub mod binary_option;
pub mod crypto_future;
pub mod crypto_perpetual;
pub mod currency_pair;
pub mod equity;
pub mod futures_contract;
pub mod futures_spread;
pub mod options_contract;
pub mod options_spread;
pub mod synthetic;
#[cfg(feature = "stubs")]
pub mod stubs;
use nautilus_core::nanos::UnixNanos;
use rust_decimal::Decimal;
use rust_decimal_macros::dec;
use ustr::Ustr;
use self::any::InstrumentAny;
use crate::{
enums::{AssetClass, InstrumentClass, OptionKind},
identifiers::{InstrumentId, Symbol, Venue},
types::{currency::Currency, money::Money, price::Price, quantity::Quantity},
};
pub trait Instrument: 'static + Send {
fn into_any(self) -> InstrumentAny;
fn id(&self) -> InstrumentId;
fn symbol(&self) -> Symbol {
self.id().symbol
}
fn venue(&self) -> Venue {
self.id().venue
}
fn raw_symbol(&self) -> Symbol;
fn asset_class(&self) -> AssetClass;
fn instrument_class(&self) -> InstrumentClass;
fn underlying(&self) -> Option<Ustr>;
fn base_currency(&self) -> Option<Currency>;
fn quote_currency(&self) -> Currency;
fn settlement_currency(&self) -> Currency;
fn isin(&self) -> Option<Ustr>;
fn option_kind(&self) -> Option<OptionKind>;
fn exchange(&self) -> Option<Ustr>;
fn strike_price(&self) -> Option<Price>;
fn activation_ns(&self) -> Option<UnixNanos>;
fn expiration_ns(&self) -> Option<UnixNanos>;
fn is_inverse(&self) -> bool;
fn price_precision(&self) -> u8;
fn size_precision(&self) -> u8;
fn price_increment(&self) -> Price;
fn size_increment(&self) -> Quantity;
fn multiplier(&self) -> Quantity;
fn lot_size(&self) -> Option<Quantity>;
fn max_quantity(&self) -> Option<Quantity>;
fn min_quantity(&self) -> Option<Quantity>;
fn max_notional(&self) -> Option<Money>;
fn min_notional(&self) -> Option<Money>;
fn max_price(&self) -> Option<Price>;
fn min_price(&self) -> Option<Price>;
fn margin_init(&self) -> Decimal {
dec!(0) }
fn margin_maint(&self) -> Decimal {
dec!(0) }
fn maker_fee(&self) -> Decimal {
dec!(0) }
fn taker_fee(&self) -> Decimal {
dec!(0) }
fn ts_event(&self) -> UnixNanos;
fn ts_init(&self) -> UnixNanos;
fn make_price(&self, value: f64) -> Price {
Price::new(value, self.price_precision())
}
fn make_qty(&self, value: f64) -> Quantity {
Quantity::new(value, self.size_precision())
}
fn calculate_notional_value(
&self,
quantity: Quantity,
price: Price,
use_quote_for_inverse: Option<bool>,
) -> Money {
let use_quote_for_inverse = use_quote_for_inverse.unwrap_or(false);
let (amount, currency) = if self.is_inverse() {
if use_quote_for_inverse {
(quantity.as_f64(), self.quote_currency())
} else {
let amount =
quantity.as_f64() * self.multiplier().as_f64() * (1.0 / price.as_f64());
let currency = self
.base_currency()
.expect("Error: no base currency for notional calculation");
(amount, currency)
}
} else {
let amount = quantity.as_f64() * self.multiplier().as_f64() * price.as_f64();
let currency = self.quote_currency();
(amount, currency)
};
Money::new(amount, currency)
}
fn calculate_base_quantity(&self, quantity: Quantity, last_px: Price) -> Quantity {
let value = quantity.as_f64() * (1.0 / last_px.as_f64());
Quantity::new(value, self.size_precision())
}
}
pub const EXPIRING_INSTRUMENT_TYPES: [InstrumentClass; 4] = [
InstrumentClass::Future,
InstrumentClass::FutureSpread,
InstrumentClass::Option,
InstrumentClass::OptionSpread,
];