nautilus_backtest/
execution_client.rs1#![allow(dead_code)]
18#![allow(unused_variables)]
19
20use std::{cell::RefCell, fmt::Debug, rc::Rc};
23
24use nautilus_common::{
25 cache::Cache,
26 clock::Clock,
27 messages::execution::{
28 BatchCancelOrders, CancelAllOrders, CancelOrder, ModifyOrder, QueryOrder, SubmitOrder,
29 SubmitOrderList, TradingCommand,
30 },
31};
32use nautilus_core::UnixNanos;
33use nautilus_execution::client::{ExecutionClient, base::BaseExecutionClient};
34use nautilus_model::{
35 accounts::AccountAny,
36 enums::OmsType,
37 identifiers::{AccountId, ClientId, TraderId, Venue},
38 orders::Order,
39 types::{AccountBalance, MarginBalance},
40};
41
42use crate::exchange::SimulatedExchange;
43
44pub struct BacktestExecutionClient {
51 base: BaseExecutionClient,
52 exchange: Rc<RefCell<SimulatedExchange>>,
53 clock: Rc<RefCell<dyn Clock>>,
54 is_connected: bool,
55 routing: bool,
56 frozen_account: bool,
57}
58
59impl Debug for BacktestExecutionClient {
60 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
61 f.debug_struct(stringify!(BacktestExecutionClient))
62 .field("client_id", &self.base.client_id)
63 .field("routing", &self.routing)
64 .finish()
65 }
66}
67
68impl BacktestExecutionClient {
69 #[allow(clippy::too_many_arguments)]
70 pub fn new(
71 trader_id: TraderId,
72 account_id: AccountId,
73 exchange: Rc<RefCell<SimulatedExchange>>,
74 cache: Rc<RefCell<Cache>>,
75 clock: Rc<RefCell<dyn Clock>>,
76 routing: Option<bool>,
77 frozen_account: Option<bool>,
78 ) -> Self {
79 let routing = routing.unwrap_or(false);
80 let frozen_account = frozen_account.unwrap_or(false);
81 let exchange_id = exchange.borrow().id;
82 let base_client = BaseExecutionClient::new(
83 trader_id,
84 ClientId::from(exchange_id.as_str()),
85 Venue::from(exchange_id.as_str()),
86 exchange.borrow().oms_type,
87 account_id,
88 exchange.borrow().account_type,
89 exchange.borrow().base_currency,
90 clock.clone(),
91 cache,
92 );
93
94 if !frozen_account {
95 }
97
98 Self {
99 exchange,
100 clock,
101 base: base_client,
102 is_connected: false,
103 routing,
104 frozen_account,
105 }
106 }
107}
108
109impl ExecutionClient for BacktestExecutionClient {
110 fn is_connected(&self) -> bool {
111 self.is_connected
112 }
113
114 fn client_id(&self) -> ClientId {
115 self.base.client_id
116 }
117
118 fn account_id(&self) -> AccountId {
119 self.base.account_id
120 }
121
122 fn venue(&self) -> Venue {
123 self.base.venue
124 }
125
126 fn oms_type(&self) -> OmsType {
127 self.base.oms_type
128 }
129
130 fn get_account(&self) -> Option<AccountAny> {
131 self.base.get_account()
132 }
133
134 fn generate_account_state(
135 &self,
136 balances: Vec<AccountBalance>,
137 margins: Vec<MarginBalance>,
138 reported: bool,
139 ts_event: UnixNanos,
140 ) -> anyhow::Result<()> {
141 self.base
142 .generate_account_state(balances, margins, reported, ts_event)
143 }
144
145 fn start(&mut self) -> anyhow::Result<()> {
146 self.is_connected = true;
147 log::info!("Backtest execution client started");
148 Ok(())
149 }
150
151 fn stop(&mut self) -> anyhow::Result<()> {
152 self.is_connected = false;
153 log::info!("Backtest execution client stopped");
154 Ok(())
155 }
156
157 fn submit_order(&self, cmd: &SubmitOrder) -> anyhow::Result<()> {
158 self.base.generate_order_submitted(
159 cmd.strategy_id,
160 cmd.instrument_id,
161 cmd.client_order_id,
162 self.clock.borrow().timestamp_ns(),
163 );
164
165 self.exchange
166 .borrow_mut()
167 .send(TradingCommand::SubmitOrder(cmd.clone())); Ok(())
169 }
170
171 fn submit_order_list(&self, cmd: &SubmitOrderList) -> anyhow::Result<()> {
172 for order in &cmd.order_list.orders {
173 self.base.generate_order_submitted(
174 cmd.strategy_id,
175 order.instrument_id(),
176 order.client_order_id(),
177 self.clock.borrow().timestamp_ns(),
178 );
179 }
180
181 self.exchange
182 .borrow_mut()
183 .send(TradingCommand::SubmitOrderList(cmd.clone()));
184 Ok(())
185 }
186
187 fn modify_order(&self, cmd: &ModifyOrder) -> anyhow::Result<()> {
188 self.exchange
189 .borrow_mut()
190 .send(TradingCommand::ModifyOrder(cmd.clone()));
191 Ok(())
192 }
193
194 fn cancel_order(&self, cmd: &CancelOrder) -> anyhow::Result<()> {
195 self.exchange
196 .borrow_mut()
197 .send(TradingCommand::CancelOrder(cmd.clone()));
198 Ok(())
199 }
200
201 fn cancel_all_orders(&self, cmd: &CancelAllOrders) -> anyhow::Result<()> {
202 self.exchange
203 .borrow_mut()
204 .send(TradingCommand::CancelAllOrders(cmd.clone()));
205 Ok(())
206 }
207
208 fn batch_cancel_orders(&self, cmd: &BatchCancelOrders) -> anyhow::Result<()> {
209 self.exchange
210 .borrow_mut()
211 .send(TradingCommand::BatchCancelOrders(cmd.clone()));
212 Ok(())
213 }
214
215 fn query_order(&self, cmd: &QueryOrder) -> anyhow::Result<()> {
216 self.exchange
217 .borrow_mut()
218 .send(TradingCommand::QueryOrder(cmd.clone()));
219 Ok(())
220 }
221}