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