nautilus_testkit/testers/exec/
config.rs1use std::num::NonZeroUsize;
17
18use nautilus_core::Params;
19use nautilus_model::{
20 enums::{BookType, OrderType, TimeInForce, TrailingOffsetType, TriggerType},
21 identifiers::{ClientId, InstrumentId, StrategyId},
22 types::Quantity,
23};
24use nautilus_trading::strategy::StrategyConfig;
25use rust_decimal::Decimal;
26use serde::{Deserialize, Serialize};
27
28#[derive(Debug, Clone, Deserialize, Serialize, bon::Builder)]
30#[serde(default, deny_unknown_fields)]
31pub struct ExecTesterConfig {
32 #[builder(default)]
34 pub base: StrategyConfig,
35 #[builder(default = InstrumentId::from("BTCUSDT-PERP.BINANCE"))]
37 pub instrument_id: InstrumentId,
38 #[builder(default = Quantity::from("0.001"))]
40 pub order_qty: Quantity,
41 pub order_display_qty: Option<Quantity>,
43 pub order_expire_time_delta_mins: Option<u64>,
45 pub order_params: Option<Params>,
47 pub client_id: Option<ClientId>,
49 #[builder(default = false)]
51 pub subscribe_book: bool,
52 #[builder(default = true)]
54 pub subscribe_quotes: bool,
55 #[builder(default = true)]
57 pub subscribe_trades: bool,
58 #[builder(default = BookType::L2_MBP)]
60 pub book_type: BookType,
61 pub book_depth: Option<NonZeroUsize>,
63 #[builder(default = NonZeroUsize::new(1000).unwrap())]
65 pub book_interval_ms: NonZeroUsize,
66 #[builder(default = 10)]
68 pub book_levels_to_print: usize,
69 pub open_position_on_start_qty: Option<Decimal>,
71 #[builder(default = TimeInForce::Gtc)]
73 pub open_position_time_in_force: TimeInForce,
74 #[builder(default = true)]
76 pub enable_limit_buys: bool,
77 #[builder(default = true)]
79 pub enable_limit_sells: bool,
80 #[builder(default = false)]
82 pub enable_stop_buys: bool,
83 #[builder(default = false)]
85 pub enable_stop_sells: bool,
86 #[builder(default = 500)]
88 pub tob_offset_ticks: u64,
89 pub limit_time_in_force: Option<TimeInForce>,
91 #[builder(default = OrderType::StopMarket)]
93 pub stop_order_type: OrderType,
94 #[builder(default = 100)]
96 pub stop_offset_ticks: u64,
97 pub stop_limit_offset_ticks: Option<u64>,
99 #[builder(default = TriggerType::Default)]
101 pub stop_trigger_type: TriggerType,
102 pub stop_time_in_force: Option<TimeInForce>,
104 pub trailing_offset: Option<Decimal>,
106 #[builder(default = TrailingOffsetType::BasisPoints)]
108 pub trailing_offset_type: TrailingOffsetType,
109 #[builder(default = false)]
111 pub enable_brackets: bool,
112 #[builder(default = false)]
114 pub batch_submit_limit_pair: bool,
115 #[builder(default = OrderType::Limit)]
117 pub bracket_entry_order_type: OrderType,
118 #[builder(default = 500)]
120 pub bracket_offset_ticks: u64,
121 #[builder(default = false)]
123 pub modify_orders_to_maintain_tob_offset: bool,
124 #[builder(default = false)]
126 pub modify_stop_orders_to_maintain_offset: bool,
127 #[builder(default = false)]
129 pub cancel_replace_orders_to_maintain_tob_offset: bool,
130 #[builder(default = false)]
132 pub cancel_replace_stop_orders_to_maintain_offset: bool,
133 #[builder(default = false)]
135 pub use_post_only: bool,
136 #[builder(default = false)]
138 pub use_quote_quantity: bool,
139 pub emulation_trigger: Option<TriggerType>,
141 #[builder(default = true)]
143 pub cancel_orders_on_stop: bool,
144 #[builder(default = true)]
146 pub close_positions_on_stop: bool,
147 pub close_positions_time_in_force: Option<TimeInForce>,
149 #[builder(default = true)]
151 pub reduce_only_on_stop: bool,
152 #[builder(default = false)]
154 pub use_individual_cancels_on_stop: bool,
155 #[builder(default = false)]
157 pub use_batch_cancel_on_stop: bool,
158 #[builder(default = false)]
160 pub dry_run: bool,
161 #[builder(default = true)]
163 pub log_data: bool,
164 #[builder(default = false)]
166 pub test_reject_post_only: bool,
167 #[builder(default = false)]
169 pub test_reject_reduce_only: bool,
170 #[builder(default = true)]
172 pub can_unsubscribe: bool,
173}
174
175impl ExecTesterConfig {
176 #[must_use]
182 pub fn new(
183 strategy_id: StrategyId,
184 instrument_id: InstrumentId,
185 client_id: ClientId,
186 order_qty: Quantity,
187 ) -> Self {
188 Self {
189 base: StrategyConfig {
190 strategy_id: Some(strategy_id),
191 order_id_tag: None,
192 ..Default::default()
193 },
194 instrument_id,
195 order_qty,
196 order_display_qty: None,
197 order_expire_time_delta_mins: None,
198 order_params: None,
199 client_id: Some(client_id),
200 subscribe_quotes: true,
201 subscribe_trades: true,
202 subscribe_book: false,
203 book_type: BookType::L2_MBP,
204 book_depth: None,
205 book_interval_ms: NonZeroUsize::new(1000).unwrap(),
206 book_levels_to_print: 10,
207 open_position_on_start_qty: None,
208 open_position_time_in_force: TimeInForce::Gtc,
209 enable_limit_buys: true,
210 enable_limit_sells: true,
211 enable_stop_buys: false,
212 enable_stop_sells: false,
213 tob_offset_ticks: 500,
214 limit_time_in_force: None,
215 stop_order_type: OrderType::StopMarket,
216 stop_offset_ticks: 100,
217 stop_limit_offset_ticks: None,
218 stop_trigger_type: TriggerType::Default,
219 stop_time_in_force: None,
220 trailing_offset: None,
221 trailing_offset_type: TrailingOffsetType::BasisPoints,
222 enable_brackets: false,
223 batch_submit_limit_pair: false,
224 bracket_entry_order_type: OrderType::Limit,
225 bracket_offset_ticks: 500,
226 modify_orders_to_maintain_tob_offset: false,
227 modify_stop_orders_to_maintain_offset: false,
228 cancel_replace_orders_to_maintain_tob_offset: false,
229 cancel_replace_stop_orders_to_maintain_offset: false,
230 use_post_only: false,
231 use_quote_quantity: false,
232 emulation_trigger: None,
233 cancel_orders_on_stop: true,
234 close_positions_on_stop: true,
235 close_positions_time_in_force: None,
236 reduce_only_on_stop: true,
237 use_individual_cancels_on_stop: false,
238 use_batch_cancel_on_stop: false,
239 dry_run: false,
240 log_data: true,
241 test_reject_post_only: false,
242 test_reject_reduce_only: false,
243 can_unsubscribe: true,
244 }
245 }
246}
247
248impl Default for ExecTesterConfig {
249 fn default() -> Self {
250 Self::builder().build()
251 }
252}