1use nautilus_core::UnixNanos;
17use nautilus_model::{
18 currencies::CURRENCY_MAP,
19 enums::{AssetClass, CurrencyType},
20 identifiers::{InstrumentId, Symbol},
21 instruments::{CryptoFuture, CryptoPerpetual, CurrencyPair, InstrumentAny, OptionContract},
22 types::{Currency, Price, Quantity},
23};
24use rust_decimal::Decimal;
25use ustr::Ustr;
26
27use super::models::InstrumentInfo;
28use crate::parse::parse_option_kind;
29
30fn get_currency(code: &str) -> Currency {
32 CURRENCY_MAP
33 .lock()
34 .unwrap()
35 .get(code)
36 .copied()
37 .unwrap_or(Currency::new(code, 8, 0, code, CurrencyType::Crypto))
38}
39
40#[allow(clippy::too_many_arguments)]
41#[must_use]
42pub fn create_currency_pair(
43 info: &InstrumentInfo,
44 instrument_id: InstrumentId,
45 raw_symbol: Symbol,
46 price_increment: Price,
47 size_increment: Quantity,
48 margin_init: Decimal,
49 margin_maint: Decimal,
50 maker_fee: Decimal,
51 taker_fee: Decimal,
52 ts_event: UnixNanos,
53 ts_init: UnixNanos,
54) -> InstrumentAny {
55 InstrumentAny::CurrencyPair(CurrencyPair::new(
56 instrument_id,
57 raw_symbol,
58 get_currency(info.base_currency.to_uppercase().as_str()),
59 get_currency(info.quote_currency.to_uppercase().as_str()),
60 price_increment.precision,
61 size_increment.precision,
62 price_increment,
63 size_increment,
64 None, None,
66 Some(Quantity::from(info.min_trade_amount.to_string().as_str())),
67 None,
68 None,
69 None,
70 None,
71 Some(margin_init),
72 Some(margin_maint),
73 Some(maker_fee),
74 Some(taker_fee),
75 ts_event,
76 ts_init,
77 ))
78}
79
80#[allow(clippy::too_many_arguments)]
81#[must_use]
82pub fn create_crypto_perpetual(
83 info: &InstrumentInfo,
84 instrument_id: InstrumentId,
85 raw_symbol: Symbol,
86 price_increment: Price,
87 size_increment: Quantity,
88 multiplier: Option<Quantity>,
89 margin_init: Decimal,
90 margin_maint: Decimal,
91 maker_fee: Decimal,
92 taker_fee: Decimal,
93 ts_event: UnixNanos,
94 ts_init: UnixNanos,
95) -> InstrumentAny {
96 InstrumentAny::CryptoPerpetual(CryptoPerpetual::new(
97 instrument_id,
98 raw_symbol,
99 get_currency(info.base_currency.to_uppercase().as_str()),
100 get_currency(info.quote_currency.to_uppercase().as_str()),
101 get_currency(
102 info.settlement_currency
103 .unwrap_or(info.quote_currency)
104 .to_uppercase()
105 .as_str(),
106 ),
107 info.inverse.expect("Perpetual should have `inverse` field"),
108 price_increment.precision,
109 size_increment.precision,
110 price_increment,
111 size_increment,
112 multiplier,
113 None, None,
115 Some(Quantity::from(info.min_trade_amount.to_string().as_str())),
116 None,
117 None,
118 None,
119 None,
120 Some(margin_init),
121 Some(margin_maint),
122 Some(maker_fee),
123 Some(taker_fee),
124 ts_event,
125 ts_init,
126 ))
127}
128
129#[allow(clippy::too_many_arguments)]
130#[must_use]
131pub fn create_crypto_future(
132 info: &InstrumentInfo,
133 instrument_id: InstrumentId,
134 raw_symbol: Symbol,
135 activation: UnixNanos,
136 expiration: UnixNanos,
137 price_increment: Price,
138 size_increment: Quantity,
139 multiplier: Option<Quantity>,
140 margin_init: Decimal,
141 margin_maint: Decimal,
142 maker_fee: Decimal,
143 taker_fee: Decimal,
144 ts_event: UnixNanos,
145 ts_init: UnixNanos,
146) -> InstrumentAny {
147 InstrumentAny::CryptoFuture(CryptoFuture::new(
148 instrument_id,
149 raw_symbol,
150 get_currency(info.base_currency.to_uppercase().as_str()),
151 get_currency(info.quote_currency.to_uppercase().as_str()),
152 get_currency(info.base_currency.to_uppercase().as_str()),
153 info.inverse.expect("Future should have `inverse` field"),
154 activation,
155 expiration,
156 price_increment.precision,
157 size_increment.precision,
158 price_increment,
159 size_increment,
160 multiplier,
161 None, None,
163 Some(Quantity::from(info.min_trade_amount.to_string().as_str())),
164 None,
165 None,
166 None,
167 None,
168 Some(margin_init),
169 Some(margin_maint),
170 Some(maker_fee),
171 Some(taker_fee),
172 ts_event,
173 ts_init,
174 ))
175}
176
177#[allow(clippy::too_many_arguments)]
178#[must_use]
179pub fn create_option_contract(
180 info: &InstrumentInfo,
181 instrument_id: InstrumentId,
182 raw_symbol: Symbol,
183 activation: UnixNanos,
184 expiration: UnixNanos,
185 price_increment: Price,
186 multiplier: Option<Quantity>,
187 margin_init: Decimal,
188 margin_maint: Decimal,
189 maker_fee: Decimal,
190 taker_fee: Decimal,
191 ts_event: UnixNanos,
192 ts_init: UnixNanos,
193) -> InstrumentAny {
194 InstrumentAny::OptionContract(OptionContract::new(
195 instrument_id,
196 raw_symbol,
197 AssetClass::Cryptocurrency,
198 Some(Ustr::from(instrument_id.venue.as_str())),
199 Ustr::from(info.base_currency.to_string().to_uppercase().as_str()),
200 parse_option_kind(
201 info.option_type
202 .clone()
203 .expect("Option should have `option_type` field"),
204 ),
205 Price::new(
206 info.strike_price
207 .expect("Option should have `strike_price` field"),
208 price_increment.precision,
209 ),
210 get_currency(info.quote_currency.to_uppercase().as_str()),
211 activation,
212 expiration,
213 price_increment.precision,
214 price_increment,
215 multiplier.unwrap_or(Quantity::from(1)),
216 Quantity::from(1), None,
218 Some(Quantity::from(info.min_trade_amount.to_string().as_str())),
219 None,
220 None,
221 Some(margin_init),
222 Some(margin_maint),
223 Some(maker_fee),
224 Some(taker_fee),
225 ts_event,
226 ts_init,
227 ))
228}