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