1use jiff::{Timestamp, civil::Date, tz::Offset};
17use nautilus_core::UnixNanos;
18use rstest::fixture;
19use rust_decimal::Decimal;
20use rust_decimal_macros::dec;
21use ustr::Ustr;
22
23use super::{
24 CryptoOption, betting::BettingInstrument, binary_option::BinaryOption, cfd::Cfd,
25 commodity::Commodity, futures_spread::FuturesSpread, index_instrument::IndexInstrument,
26 option_spread::OptionSpread, perpetual_contract::PerpetualContract,
27 synthetic::SyntheticInstrument, tokenized_asset::TokenizedAsset,
28};
29use crate::{
30 enums::{AssetClass, OptionKind},
31 identifiers::{InstrumentId, Symbol, Venue},
32 instruments::{
33 CryptoFuture, CryptoFuturesSpread, CryptoOptionSpread, CryptoPerpetual, CurrencyPair,
34 Equity, FuturesContract, OptionContract,
35 },
36 types::{Currency, Money, Price, Quantity},
37};
38
39fn timestamp(year: i16, month: i8, day: i8, hour: i8, minute: i8, second: i8) -> Timestamp {
40 let datetime = Date::new(year, month, day)
41 .expect("valid date")
42 .at(hour, minute, second, 0);
43 Offset::UTC.to_timestamp(datetime).expect("valid timestamp")
44}
45
46impl Default for SyntheticInstrument {
47 fn default() -> Self {
49 let btc_binance = InstrumentId::from("BTC.BINANCE");
50 let ltc_binance = InstrumentId::from("LTC.BINANCE");
51 let formula = "(BTC.BINANCE + LTC.BINANCE) / 2.0";
52 Self::builder()
53 .symbol(Symbol::new("BTC-LTC"))
54 .price_precision(2)
55 .components(vec![btc_binance, ltc_binance])
56 .formula(formula)
57 .ts_event(0.into())
58 .ts_init(0.into())
59 .build()
60 .unwrap()
61 }
62}
63
64#[fixture]
65pub fn crypto_future_btcusdt(
66 #[default(2)] price_precision: u8,
67 #[default(6)] size_precision: u8,
68 #[default(Price::from("0.01"))] price_increment: Price,
69 #[default(Quantity::from("0.000001"))] size_increment: Quantity,
70) -> CryptoFuture {
71 let activation = timestamp(2014, 4, 8, 0, 0, 0);
72 let expiration = timestamp(2014, 7, 8, 0, 0, 0);
73 CryptoFuture::builder()
74 .instrument_id(InstrumentId::from("ETHUSDT-123.BINANCE"))
75 .raw_symbol(Symbol::from("BTCUSDT"))
76 .underlying(Currency::from("BTC"))
77 .quote_currency(Currency::from("USDT"))
78 .settlement_currency(Currency::from("USDT"))
79 .is_inverse(false)
80 .activation_ns(UnixNanos::from(activation))
81 .expiration_ns(UnixNanos::from(expiration))
82 .price_precision(price_precision)
83 .size_precision(size_precision)
84 .price_increment(price_increment)
85 .size_increment(size_increment)
86 .max_quantity(Quantity::from("9000.0"))
87 .min_quantity(Quantity::from("0.000001"))
88 .min_notional(Money::new(10.00, Currency::from("USDT")))
89 .max_price(Price::from("1000000.00"))
90 .min_price(Price::from("0.01"))
91 .ts_event(0.into())
92 .ts_init(0.into())
93 .build()
94 .unwrap()
95}
96
97#[fixture]
98pub fn ethbtc_quanto(
99 #[default(5)] price_precision: u8,
100 #[default(3)] size_precision: u8,
101 #[default(Price::from("0.00001"))] price_increment: Price,
102 #[default(Quantity::from("0.001"))] size_increment: Quantity,
103) -> CryptoFuture {
104 let activation = timestamp(2014, 4, 8, 0, 0, 0);
105 let expiration = timestamp(2014, 7, 8, 0, 0, 0);
106 CryptoFuture::builder()
107 .instrument_id(InstrumentId::from("ETHBTC-123.BINANCE"))
108 .raw_symbol(Symbol::from("ETHBTC"))
109 .underlying(Currency::from("ETH"))
110 .quote_currency(Currency::from("BTC"))
111 .settlement_currency(Currency::from("USDT"))
112 .is_inverse(false)
113 .activation_ns(UnixNanos::from(activation))
114 .expiration_ns(UnixNanos::from(expiration))
115 .price_precision(price_precision)
116 .size_precision(size_precision)
117 .price_increment(price_increment)
118 .size_increment(size_increment)
119 .max_quantity(Quantity::from("9000.0"))
120 .min_quantity(Quantity::from("0.001"))
121 .min_notional(Money::new(1.0, Currency::from("USDT")))
122 .max_price(Price::from("1.0"))
123 .min_price(Price::from("0.00001"))
124 .ts_event(0.into())
125 .ts_init(0.into())
126 .build()
127 .unwrap()
128}
129
130#[fixture]
131pub fn btcusd_inverse_perp(
132 #[default(1)] price_precision: u8,
134 #[default(0)] size_precision: u8,
135 #[default(Price::from("0.5"))] price_increment: Price,
136 #[default(Quantity::from("1"))] size_increment: Quantity,
137) -> CryptoPerpetual {
138 CryptoPerpetual::builder()
139 .instrument_id(InstrumentId::from("BTCUSD-PERP.BYBIT"))
141 .raw_symbol(Symbol::from("BTCUSD"))
142 .base_currency(Currency::BTC())
144 .quote_currency(Currency::USD())
146 .settlement_currency(Currency::BTC())
148 .is_inverse(true)
149 .price_precision(price_precision)
150 .size_precision(size_precision)
151 .price_increment(price_increment)
152 .size_increment(size_increment)
153 .lot_size(Quantity::from("1"))
154 .max_notional(Money::from("10000000 USD"))
155 .min_notional(Money::from("1 USD"))
156 .max_price(Price::from("10000000"))
157 .min_price(Price::from("0.01"))
158 .margin_init(dec!(0.01))
159 .margin_maint(dec!(0.0035))
160 .ts_event(UnixNanos::default())
161 .ts_init(UnixNanos::default())
162 .build()
163 .unwrap()
164}
165
166#[fixture]
167pub fn crypto_option_btc_deribit(
168 #[default(3)] price_precision: u8,
169 #[default(1)] size_precision: u8,
170 #[default(Price::from("0.001"))] price_increment: Price,
171 #[default(Quantity::from("0.1"))] size_increment: Quantity,
172) -> CryptoOption {
173 let activation = UnixNanos::from(1_671_696_002_000_000_000);
174 let expiration = UnixNanos::from(1_673_596_800_000_000_000);
175 CryptoOption::builder()
176 .instrument_id(InstrumentId::from("BTC-13JAN23-16000-P.DERIBIT"))
177 .raw_symbol(Symbol::from("BTC-13JAN23-16000-P"))
178 .underlying(Currency::from("BTC"))
179 .quote_currency(Currency::from("USD"))
180 .settlement_currency(Currency::from("BTC"))
181 .is_inverse(false)
182 .option_kind(OptionKind::Put)
183 .strike_price(Price::from("16000.000"))
184 .activation_ns(activation)
185 .expiration_ns(expiration)
186 .price_precision(price_precision)
187 .size_precision(size_precision)
188 .price_increment(price_increment)
189 .size_increment(size_increment)
190 .multiplier(Quantity::from(1))
191 .lot_size(Quantity::from(1))
192 .max_quantity(Quantity::from("9000.0"))
193 .min_quantity(Quantity::from("0.1"))
194 .min_notional(Money::new(10.00, Currency::from("USD")))
195 .ts_event(0.into())
196 .ts_init(0.into())
197 .build()
198 .unwrap()
199}
200
201#[fixture]
202pub fn crypto_perpetual_ethusdt() -> CryptoPerpetual {
203 CryptoPerpetual::builder()
204 .instrument_id(InstrumentId::from("ETHUSDT-PERP.BINANCE"))
205 .raw_symbol(Symbol::from("ETHUSDT"))
206 .base_currency(Currency::from("ETH"))
207 .quote_currency(Currency::from("USDT"))
208 .settlement_currency(Currency::from("USDT"))
209 .is_inverse(false)
210 .price_precision(2)
211 .size_precision(3)
212 .price_increment(Price::from("0.01"))
213 .size_increment(Quantity::from("0.001"))
214 .max_quantity(Quantity::from("10000.0"))
215 .min_quantity(Quantity::from("0.001"))
216 .min_notional(Money::new(10.00, Currency::from("USDT")))
217 .max_price(Price::from("15000.00"))
218 .min_price(Price::from("1.0"))
219 .margin_init(dec!(1.0))
220 .margin_maint(dec!(0.35))
221 .ts_event(UnixNanos::default())
222 .ts_init(UnixNanos::default())
223 .build()
224 .unwrap()
225}
226
227#[fixture]
228pub fn btcusd_bybit() -> CryptoPerpetual {
229 CryptoPerpetual::builder()
230 .instrument_id(InstrumentId::from("BTCUSD.BYBIT"))
231 .raw_symbol(Symbol::from("BTCUSD"))
232 .base_currency(Currency::BTC())
233 .quote_currency(Currency::USD())
234 .settlement_currency(Currency::BTC())
235 .is_inverse(true)
236 .price_precision(1)
237 .size_precision(0)
238 .price_increment(Price::from("0.5"))
239 .size_increment(Quantity::from("1"))
240 .max_notional(Money::from("10000000 USD"))
241 .min_notional(Money::from("1 USD"))
242 .max_price(Price::from("10000000"))
243 .min_price(Price::from("0.01"))
244 .margin_init(dec!(0.01))
245 .margin_maint(dec!(0.0035))
246 .ts_event(UnixNanos::default())
247 .ts_init(UnixNanos::default())
248 .build()
249 .unwrap()
250}
251
252#[fixture]
253pub fn ethusd_bybit() -> CryptoPerpetual {
254 CryptoPerpetual::builder()
255 .instrument_id(InstrumentId::from("ETHUSD.BYBIT"))
256 .raw_symbol(Symbol::from("ETHUSD"))
257 .base_currency(Currency::ETH())
258 .quote_currency(Currency::USD())
259 .settlement_currency(Currency::ETH())
260 .is_inverse(true)
261 .price_precision(2)
262 .size_precision(0)
263 .price_increment(Price::from("0.05"))
264 .size_increment(Quantity::from("1"))
265 .max_price(Price::from("10000000"))
266 .min_price(Price::from("0.01"))
267 .margin_init(dec!(0.01))
268 .margin_maint(dec!(0.0035))
269 .ts_event(UnixNanos::default())
270 .ts_init(UnixNanos::default())
271 .build()
272 .unwrap()
273}
274
275#[fixture]
276pub fn currency_pair_btcusdt() -> CurrencyPair {
277 CurrencyPair::builder()
278 .instrument_id(InstrumentId::from("BTCUSDT.BINANCE"))
279 .raw_symbol(Symbol::from("BTCUSDT"))
280 .base_currency(Currency::from("BTC"))
281 .quote_currency(Currency::from("USDT"))
282 .price_precision(2)
283 .size_precision(6)
284 .price_increment(Price::from("0.01"))
285 .size_increment(Quantity::from("0.000001"))
286 .max_quantity(Quantity::from("9000"))
287 .min_quantity(Quantity::from("0.000001"))
288 .max_price(Price::from("1000000"))
289 .min_price(Price::from("0.01"))
290 .margin_init(dec!(0.001))
291 .margin_maint(dec!(0.001))
292 .ts_event(UnixNanos::default())
293 .ts_init(UnixNanos::default())
294 .build()
295 .unwrap()
296}
297
298#[fixture]
299pub fn currency_pair_ethusdt() -> CurrencyPair {
300 CurrencyPair::builder()
301 .instrument_id(InstrumentId::from("ETHUSDT.BINANCE"))
302 .raw_symbol(Symbol::from("ETHUSDT"))
303 .base_currency(Currency::from("ETH"))
304 .quote_currency(Currency::from("USDT"))
305 .price_precision(2)
306 .size_precision(5)
307 .price_increment(Price::from("0.01"))
308 .size_increment(Quantity::from("0.00001"))
309 .max_quantity(Quantity::from("9000"))
310 .min_quantity(Quantity::from("0.00001"))
311 .max_price(Price::from("1000000"))
312 .min_price(Price::from("0.01"))
313 .margin_init(dec!(0.01))
314 .margin_maint(dec!(0.0035))
315 .ts_event(UnixNanos::default())
316 .ts_init(UnixNanos::default())
317 .build()
318 .unwrap()
319}
320
321#[must_use]
325pub fn default_fx_ccy(symbol: Symbol, venue: Option<Venue>) -> CurrencyPair {
326 let target_venue = venue.unwrap_or(Venue::from("SIM"));
327 let instrument_id = InstrumentId::new(symbol, target_venue);
328 let base_currency = symbol.as_str().split('/').next().unwrap();
329 let quote_currency = symbol.as_str().split('/').next_back().unwrap();
330 let price_precision = if quote_currency == "JPY" { 3 } else { 5 };
331 let tick_scheme = if quote_currency == "JPY" {
332 "FOREX_3DECIMAL"
333 } else {
334 "FOREX_5DECIMAL"
335 };
336 let price_increment = Price::new(
337 1.0 / 10.0f64.powi(i32::from(price_precision)),
338 price_precision,
339 );
340 CurrencyPair::builder()
341 .instrument_id(instrument_id)
342 .raw_symbol(symbol)
343 .base_currency(Currency::from(base_currency))
344 .quote_currency(Currency::from(quote_currency))
345 .price_precision(price_precision)
346 .size_precision(0)
347 .price_increment(price_increment)
348 .size_increment(Quantity::from("1"))
349 .lot_size(Quantity::from("1000"))
350 .max_quantity(Quantity::from("1000000"))
351 .min_quantity(Quantity::from("100"))
352 .margin_init(dec!(0.03))
353 .margin_maint(dec!(0.03))
354 .tick_scheme(Ustr::from(tick_scheme))
355 .ts_event(UnixNanos::default())
356 .ts_init(UnixNanos::default())
357 .build()
358 .unwrap()
359}
360
361#[fixture]
362pub fn audusd_sim() -> CurrencyPair {
363 default_fx_ccy(Symbol::from("AUD/USD"), Some(Venue::from("SIM")))
364}
365
366#[fixture]
367pub fn gbpusd_sim() -> CurrencyPair {
368 default_fx_ccy(Symbol::from("GBP/USD"), Some(Venue::from("SIM")))
369}
370
371#[fixture]
372pub fn usdjpy_idealpro() -> CurrencyPair {
373 default_fx_ccy(Symbol::from("USD/JPY"), Some(Venue::from("IDEALPRO")))
374}
375
376#[fixture]
377pub fn equity_aapl() -> Equity {
378 Equity::builder()
379 .instrument_id(InstrumentId::from("AAPL.XNAS"))
380 .raw_symbol(Symbol::from("AAPL"))
381 .isin(Ustr::from("US0378331005"))
382 .currency(Currency::from("USD"))
383 .price_precision(2)
384 .price_increment(Price::from("0.01"))
385 .ts_event(UnixNanos::default())
386 .ts_init(UnixNanos::default())
387 .build()
388 .unwrap()
389}
390
391#[must_use]
397pub fn equity_aapl_itch() -> Equity {
398 Equity::builder()
399 .instrument_id(InstrumentId::from("AAPL.XNAS"))
400 .raw_symbol(Symbol::from("AAPL"))
401 .isin(Ustr::from("US0378331005"))
402 .currency(Currency::from("USD"))
403 .price_precision(4)
404 .price_increment(Price::from("0.0001"))
405 .ts_event(UnixNanos::default())
406 .ts_init(UnixNanos::default())
407 .build()
408 .unwrap()
409}
410
411#[must_use]
416pub fn futures_contract_es(
417 activation: Option<UnixNanos>,
418 expiration: Option<UnixNanos>,
419) -> FuturesContract {
420 let activation = activation.unwrap_or(UnixNanos::from(timestamp(2021, 9, 10, 0, 0, 0)));
421 let expiration = expiration.unwrap_or(UnixNanos::from(timestamp(2021, 12, 17, 0, 0, 0)));
422 FuturesContract::builder()
423 .instrument_id(InstrumentId::from("ESZ21.GLBX"))
424 .raw_symbol(Symbol::from("ESZ21"))
425 .asset_class(AssetClass::Index)
426 .exchange(Ustr::from("XCME"))
427 .underlying(Ustr::from("ES"))
428 .activation_ns(activation)
429 .expiration_ns(expiration)
430 .currency(Currency::USD())
431 .price_precision(2)
432 .price_increment(Price::from("0.01"))
433 .multiplier(Quantity::from(1))
434 .lot_size(Quantity::from(1))
435 .ts_event(UnixNanos::default())
436 .ts_init(UnixNanos::default())
437 .build()
438 .unwrap()
439}
440
441#[fixture]
442pub fn futures_spread_es() -> FuturesSpread {
443 let activation = timestamp(2022, 6, 21, 13, 30, 0);
444 let expiration = timestamp(2024, 6, 21, 13, 30, 0);
445 FuturesSpread::builder()
446 .instrument_id(InstrumentId::from("ESM4-ESU4.GLBX"))
447 .raw_symbol(Symbol::from("ESM4-ESU4"))
448 .asset_class(AssetClass::Index)
449 .exchange(Ustr::from("XCME"))
450 .underlying(Ustr::from("ES"))
451 .strategy_type(Ustr::from("EQ"))
452 .activation_ns(UnixNanos::from(activation))
453 .expiration_ns(UnixNanos::from(expiration))
454 .currency(Currency::USD())
455 .price_precision(2)
456 .price_increment(Price::from("0.01"))
457 .multiplier(Quantity::from(1))
458 .lot_size(Quantity::from(1))
459 .ts_event(UnixNanos::default())
460 .ts_init(UnixNanos::default())
461 .build()
462 .unwrap()
463}
464
465#[fixture]
466pub fn option_contract_appl() -> OptionContract {
467 let activation = timestamp(2021, 9, 17, 0, 0, 0);
468 let expiration = timestamp(2021, 12, 17, 0, 0, 0);
469 OptionContract::builder()
470 .instrument_id(InstrumentId::from("AAPL211217C00150000.OPRA"))
471 .raw_symbol(Symbol::from("AAPL211217C00150000"))
472 .asset_class(AssetClass::Equity)
473 .exchange(Ustr::from("GMNI"))
474 .underlying(Ustr::from("AAPL"))
475 .option_kind(OptionKind::Call)
476 .strike_price(Price::from("149.0"))
477 .currency(Currency::USD())
478 .activation_ns(UnixNanos::from(activation))
479 .expiration_ns(UnixNanos::from(expiration))
480 .price_precision(2)
481 .price_increment(Price::from("0.01"))
482 .multiplier(Quantity::from(1))
483 .lot_size(Quantity::from(1))
484 .ts_event(UnixNanos::default())
485 .ts_init(UnixNanos::default())
486 .build()
487 .unwrap()
488}
489
490#[fixture]
491pub fn option_spread() -> OptionSpread {
492 let activation = timestamp(2023, 11, 6, 20, 54, 7);
493 let expiration = timestamp(2024, 2, 23, 22, 59, 0);
494 OptionSpread::builder()
495 .instrument_id(InstrumentId::from("UD:U$: GN 2534559.GLBX"))
496 .raw_symbol(Symbol::from("UD:U$: GN 2534559"))
497 .asset_class(AssetClass::FX)
498 .exchange(Ustr::from("XCME"))
499 .underlying(Ustr::from("SR3"))
500 .strategy_type(Ustr::from("GN"))
501 .activation_ns(UnixNanos::from(activation))
502 .expiration_ns(UnixNanos::from(expiration))
503 .currency(Currency::USD())
504 .price_precision(2)
505 .price_increment(Price::from("0.01"))
506 .multiplier(Quantity::from(1))
507 .lot_size(Quantity::from(1))
508 .ts_event(UnixNanos::default())
509 .ts_init(UnixNanos::default())
510 .build()
511 .unwrap()
512}
513
514#[fixture]
515pub fn crypto_futures_spread_btc_deribit() -> CryptoFuturesSpread {
516 let activation = timestamp(2026, 5, 12, 0, 0, 0);
517 let expiration = timestamp(2026, 5, 19, 8, 0, 0);
518 CryptoFuturesSpread::builder()
519 .instrument_id(InstrumentId::from("BTC-FS-19MAY26_PERP.DERIBIT"))
520 .raw_symbol(Symbol::from("BTC-FS-19MAY26_PERP"))
521 .underlying(Currency::BTC())
522 .quote_currency(Currency::USD())
523 .settlement_currency(Currency::BTC())
524 .is_inverse(false)
525 .strategy_type(Ustr::from("FS"))
526 .activation_ns(UnixNanos::from(activation))
527 .expiration_ns(UnixNanos::from(expiration))
528 .price_precision(1)
529 .size_precision(0)
530 .price_increment(Price::from("0.5"))
531 .size_increment(Quantity::from("1"))
532 .multiplier(Quantity::from("10"))
533 .min_quantity(Quantity::from("1"))
534 .ts_event(0.into())
535 .ts_init(0.into())
536 .build()
537 .unwrap()
538}
539
540#[fixture]
541pub fn crypto_option_spread_btc_deribit() -> CryptoOptionSpread {
542 let activation = timestamp(2026, 5, 12, 0, 0, 0);
543 let expiration = timestamp(2026, 5, 19, 8, 0, 0);
544 CryptoOptionSpread::builder()
545 .instrument_id(InstrumentId::from("BTC-CS-19MAY26-70000_75000.DERIBIT"))
546 .raw_symbol(Symbol::from("BTC-CS-19MAY26-70000_75000"))
547 .underlying(Currency::BTC())
548 .quote_currency(Currency::USD())
549 .settlement_currency(Currency::BTC())
550 .is_inverse(false)
551 .strategy_type(Ustr::from("CS"))
552 .activation_ns(UnixNanos::from(activation))
553 .expiration_ns(UnixNanos::from(expiration))
554 .price_precision(4)
555 .size_precision(1)
556 .price_increment(Price::from("0.0001"))
557 .size_increment(Quantity::from("0.1"))
558 .multiplier(Quantity::from(1))
559 .min_quantity(Quantity::from("0.1"))
560 .ts_event(0.into())
561 .ts_init(0.into())
562 .build()
563 .unwrap()
564}
565
566#[fixture]
567pub fn betting() -> BettingInstrument {
568 let raw_symbol = Symbol::new("1-123456789");
569 let id = InstrumentId::from(format!("{raw_symbol}.BETFAIR"));
570 let event_type_id = 6423;
571 let event_type_name = Ustr::from("American Football");
572 let competition_id = 12_282_733;
573 let competition_name = Ustr::from("NFL");
574 let event_id = 29_678_534;
575 let event_name = Ustr::from("NFL");
576 let event_country_code = Ustr::from("GB");
577 let event_open_date = UnixNanos::from(timestamp(2022, 2, 7, 23, 30, 0));
578 let betting_type = Ustr::from("ODDS");
579 let market_id = Ustr::from("1-123456789");
580 let market_name = Ustr::from("AFC Conference Winner");
581 let market_type = Ustr::from("SPECIAL");
582 let market_start_time = UnixNanos::from(timestamp(2022, 2, 7, 23, 30, 0));
583 let selection_id = 50214;
584 let selection_name = Ustr::from("Kansas City Chiefs");
585 let selection_handicap = 0.0;
586 let currency = Currency::GBP();
587 let price_increment = Price::from("0.01");
588 let size_increment = Quantity::from("0.01");
589 let max_quantity = Some(Quantity::from("1000"));
590 let min_quantity = Some(Quantity::from("1"));
591 let max_notional = Some(Money::from("10000 GBP"));
592 let min_notional = Some(Money::from("10 GBP"));
593 let max_price = Some(Price::from("100.00"));
594 let min_price = Some(Price::from("1.00"));
595 let margin_init = Some(Decimal::from(1));
596 let margin_maint = Some(Decimal::from(1));
597 let ts_event = UnixNanos::default();
598 let ts_init = UnixNanos::default();
599
600 BettingInstrument::builder()
601 .instrument_id(id)
602 .raw_symbol(raw_symbol)
603 .event_type_id(event_type_id)
604 .event_type_name(event_type_name)
605 .competition_id(competition_id)
606 .competition_name(competition_name)
607 .event_id(event_id)
608 .event_name(event_name)
609 .event_country_code(event_country_code)
610 .event_open_date(event_open_date)
611 .betting_type(betting_type)
612 .market_id(market_id)
613 .market_name(market_name)
614 .market_type(market_type)
615 .market_start_time(market_start_time)
616 .selection_id(selection_id)
617 .selection_name(selection_name)
618 .selection_handicap(selection_handicap)
619 .currency(currency)
620 .price_precision(price_increment.precision)
621 .size_precision(size_increment.precision)
622 .price_increment(price_increment)
623 .size_increment(size_increment)
624 .maybe_max_quantity(max_quantity)
625 .maybe_min_quantity(min_quantity)
626 .maybe_max_notional(max_notional)
627 .maybe_min_notional(min_notional)
628 .maybe_max_price(max_price)
629 .maybe_min_price(min_price)
630 .maybe_margin_init(margin_init)
631 .maybe_margin_maint(margin_maint)
632 .ts_event(ts_event)
633 .ts_init(ts_init)
634 .build()
635 .unwrap()
636}
637
638#[fixture]
639pub fn commodity_gold() -> Commodity {
640 Commodity::builder()
641 .instrument_id(InstrumentId::from("GOLD.COMEX"))
642 .raw_symbol(Symbol::from("GOLD"))
643 .asset_class(AssetClass::Commodity)
644 .quote_currency(Currency::from("USD"))
645 .price_precision(2)
646 .size_precision(0)
647 .price_increment(Price::from("0.01"))
648 .size_increment(Quantity::from("1"))
649 .lot_size(Quantity::from("1"))
650 .ts_event(UnixNanos::default())
651 .ts_init(UnixNanos::default())
652 .build()
653 .unwrap()
654}
655
656#[fixture]
657pub fn index_instrument_spx() -> IndexInstrument {
658 IndexInstrument::builder()
659 .instrument_id(InstrumentId::from("SPX.INDEX"))
660 .raw_symbol(Symbol::from("SPX"))
661 .currency(Currency::from("USD"))
662 .price_precision(2)
663 .size_precision(0)
664 .price_increment(Price::from("0.01"))
665 .size_increment(Quantity::from("1"))
666 .ts_event(UnixNanos::default())
667 .ts_init(UnixNanos::default())
668 .build()
669 .unwrap()
670}
671
672#[fixture]
673pub fn cfd_gold() -> Cfd {
674 Cfd::builder()
675 .instrument_id(InstrumentId::from("GOLD-CFD.SIM"))
676 .raw_symbol(Symbol::from("GOLD-CFD"))
677 .asset_class(AssetClass::Commodity)
678 .quote_currency(Currency::from("USD"))
679 .price_precision(2)
680 .size_precision(0)
681 .price_increment(Price::from("0.01"))
682 .size_increment(Quantity::from("1"))
683 .lot_size(Quantity::from("1"))
684 .ts_event(UnixNanos::default())
685 .ts_init(UnixNanos::default())
686 .build()
687 .unwrap()
688}
689
690#[fixture]
691pub fn perpetual_contract_eurusd() -> PerpetualContract {
692 PerpetualContract::builder()
693 .instrument_id(InstrumentId::from("EURUSD-PERP.AX"))
694 .raw_symbol(Symbol::from("EURUSD-PERP"))
695 .underlying(Ustr::from("EURUSD"))
696 .asset_class(AssetClass::FX)
697 .base_currency(Currency::from("EUR"))
698 .quote_currency(Currency::from("USD"))
699 .settlement_currency(Currency::from("USD"))
700 .is_inverse(false)
701 .price_precision(5)
702 .size_precision(0)
703 .price_increment(Price::from("0.00001"))
704 .size_increment(Quantity::from("1"))
705 .margin_init(dec!(0.03))
706 .margin_maint(dec!(0.03))
707 .ts_event(UnixNanos::default())
708 .ts_init(UnixNanos::default())
709 .build()
710 .unwrap()
711}
712
713#[fixture]
714pub fn binary_option() -> BinaryOption {
715 let raw_symbol = Symbol::new(
716 "0x12a0cb60174abc437bf1178367c72d11f069e1a3add20b148fb0ab4279b772b2-92544998123698303655208967887569360731013655782348975589292031774495159624905",
717 );
718 let activation = timestamp(2023, 11, 6, 20, 54, 7);
719 let expiration = timestamp(2024, 2, 23, 22, 59, 0);
720 let price_increment = Price::from("0.001");
721 let size_increment = Quantity::from("0.01");
722 BinaryOption::builder()
723 .instrument_id(InstrumentId::from("{raw_symbol}.POLYMARKET"))
724 .raw_symbol(raw_symbol)
725 .asset_class(AssetClass::Alternative)
726 .currency(Currency::USDC())
727 .activation_ns(UnixNanos::from(activation))
728 .expiration_ns(UnixNanos::from(expiration))
729 .price_precision(price_increment.precision)
730 .size_precision(size_increment.precision)
731 .price_increment(price_increment)
732 .size_increment(size_increment)
733 .ts_event(UnixNanos::default())
734 .ts_init(UnixNanos::default())
735 .build()
736 .unwrap()
737}
738
739#[fixture]
740pub fn tokenized_asset_aaplx() -> TokenizedAsset {
741 TokenizedAsset::builder()
742 .instrument_id(InstrumentId::from("AAPLx/USD.KRAKEN"))
743 .raw_symbol(Symbol::from("AAPLxUSD"))
744 .asset_class(AssetClass::Equity)
745 .base_currency(Currency::get_or_create_crypto("AAPLx"))
746 .quote_currency(Currency::from("USD"))
747 .price_precision(2)
748 .size_precision(4)
749 .price_increment(Price::from("0.01"))
750 .size_increment(Quantity::from("0.0001"))
751 .min_quantity(Quantity::from("0.0001"))
752 .ts_event(UnixNanos::default())
753 .ts_init(UnixNanos::default())
754 .build()
755 .unwrap()
756}