1use std::{cell::RefCell, rc::Rc};
19
20use nautilus_common::{
21 cache::Cache,
22 clients::DataClient,
23 messages::data::{
24 RequestBars, RequestBookSnapshot, RequestCustomData, RequestForwardPrices,
25 RequestInstrument, RequestInstruments, RequestQuotes, RequestTrades, SubscribeBars,
26 SubscribeBookDeltas, SubscribeBookDepth10, SubscribeCustomData, SubscribeIndexPrices,
27 SubscribeInstrument, SubscribeInstrumentClose, SubscribeInstrumentStatus,
28 SubscribeInstruments, SubscribeMarkPrices, SubscribeQuotes, SubscribeTrades,
29 UnsubscribeBars, UnsubscribeBookDeltas, UnsubscribeBookDepth10, UnsubscribeCustomData,
30 UnsubscribeIndexPrices, UnsubscribeInstrument, UnsubscribeInstrumentClose,
31 UnsubscribeInstrumentStatus, UnsubscribeInstruments, UnsubscribeMarkPrices,
32 UnsubscribeQuotes, UnsubscribeTrades,
33 },
34};
35use nautilus_model::identifiers::{ClientId, Venue};
36
37#[derive(Debug)]
44pub struct BacktestDataClient {
45 pub client_id: ClientId,
46 pub venue: Venue,
47 _cache: Rc<RefCell<Cache>>,
48}
49
50impl BacktestDataClient {
51 #[must_use]
53 pub const fn new(client_id: ClientId, venue: Venue, cache: Rc<RefCell<Cache>>) -> Self {
54 Self {
55 client_id,
56 venue,
57 _cache: cache,
58 }
59 }
60}
61
62#[async_trait::async_trait(?Send)]
63impl DataClient for BacktestDataClient {
64 fn client_id(&self) -> ClientId {
65 self.client_id
66 }
67
68 fn venue(&self) -> Option<Venue> {
69 Some(self.venue)
70 }
71
72 fn start(&mut self) -> anyhow::Result<()> {
73 Ok(())
74 }
75
76 fn stop(&mut self) -> anyhow::Result<()> {
77 Ok(())
78 }
79
80 fn reset(&mut self) -> anyhow::Result<()> {
81 Ok(())
82 }
83
84 fn dispose(&mut self) -> anyhow::Result<()> {
85 Ok(())
86 }
87
88 fn is_connected(&self) -> bool {
89 true
90 }
91
92 fn is_disconnected(&self) -> bool {
93 false
94 }
95
96 fn subscribe(&mut self, _cmd: SubscribeCustomData) -> anyhow::Result<()> {
97 Ok(())
98 }
99
100 fn subscribe_instruments(&mut self, _cmd: SubscribeInstruments) -> anyhow::Result<()> {
101 Ok(())
102 }
103
104 fn subscribe_instrument(&mut self, _cmd: SubscribeInstrument) -> anyhow::Result<()> {
105 Ok(())
106 }
107
108 fn subscribe_book_deltas(&mut self, _cmd: SubscribeBookDeltas) -> anyhow::Result<()> {
109 Ok(())
110 }
111
112 fn subscribe_book_depth10(&mut self, _cmd: SubscribeBookDepth10) -> anyhow::Result<()> {
113 Ok(())
114 }
115
116 fn subscribe_quotes(&mut self, _cmd: SubscribeQuotes) -> anyhow::Result<()> {
117 Ok(())
118 }
119
120 fn subscribe_trades(&mut self, _cmd: SubscribeTrades) -> anyhow::Result<()> {
121 Ok(())
122 }
123
124 fn subscribe_bars(&mut self, _cmd: SubscribeBars) -> anyhow::Result<()> {
125 Ok(())
126 }
127
128 fn subscribe_mark_prices(&mut self, _cmd: SubscribeMarkPrices) -> anyhow::Result<()> {
129 Ok(())
130 }
131
132 fn subscribe_index_prices(&mut self, _cmd: SubscribeIndexPrices) -> anyhow::Result<()> {
133 Ok(())
134 }
135
136 fn subscribe_instrument_status(
137 &mut self,
138 _cmd: SubscribeInstrumentStatus,
139 ) -> anyhow::Result<()> {
140 Ok(())
141 }
142
143 fn subscribe_instrument_close(&mut self, _cmd: SubscribeInstrumentClose) -> anyhow::Result<()> {
144 Ok(())
145 }
146
147 fn unsubscribe(&mut self, _cmd: &UnsubscribeCustomData) -> anyhow::Result<()> {
148 Ok(())
149 }
150
151 fn unsubscribe_instruments(&mut self, _cmd: &UnsubscribeInstruments) -> anyhow::Result<()> {
152 Ok(())
153 }
154
155 fn unsubscribe_instrument(&mut self, _cmd: &UnsubscribeInstrument) -> anyhow::Result<()> {
156 Ok(())
157 }
158
159 fn unsubscribe_book_deltas(&mut self, _cmd: &UnsubscribeBookDeltas) -> anyhow::Result<()> {
160 Ok(())
161 }
162
163 fn unsubscribe_book_depth10(&mut self, _cmd: &UnsubscribeBookDepth10) -> anyhow::Result<()> {
164 Ok(())
165 }
166
167 fn unsubscribe_quotes(&mut self, _cmd: &UnsubscribeQuotes) -> anyhow::Result<()> {
168 Ok(())
169 }
170
171 fn unsubscribe_trades(&mut self, _cmd: &UnsubscribeTrades) -> anyhow::Result<()> {
172 Ok(())
173 }
174
175 fn unsubscribe_bars(&mut self, _cmd: &UnsubscribeBars) -> anyhow::Result<()> {
176 Ok(())
177 }
178
179 fn unsubscribe_mark_prices(&mut self, _cmd: &UnsubscribeMarkPrices) -> anyhow::Result<()> {
180 Ok(())
181 }
182
183 fn unsubscribe_index_prices(&mut self, _cmd: &UnsubscribeIndexPrices) -> anyhow::Result<()> {
184 Ok(())
185 }
186
187 fn unsubscribe_instrument_status(
188 &mut self,
189 _cmd: &UnsubscribeInstrumentStatus,
190 ) -> anyhow::Result<()> {
191 Ok(())
192 }
193
194 fn unsubscribe_instrument_close(
195 &mut self,
196 _cmd: &UnsubscribeInstrumentClose,
197 ) -> anyhow::Result<()> {
198 Ok(())
199 }
200
201 fn request_data(&self, _request: RequestCustomData) -> anyhow::Result<()> {
202 Ok(())
204 }
205
206 fn request_instruments(&self, _request: RequestInstruments) -> anyhow::Result<()> {
207 Ok(())
209 }
210
211 fn request_instrument(&self, _request: RequestInstrument) -> anyhow::Result<()> {
212 Ok(())
214 }
215
216 fn request_book_snapshot(&self, _request: RequestBookSnapshot) -> anyhow::Result<()> {
217 Ok(())
219 }
220
221 fn request_quotes(&self, _request: RequestQuotes) -> anyhow::Result<()> {
222 Ok(())
224 }
225
226 fn request_trades(&self, _request: RequestTrades) -> anyhow::Result<()> {
227 Ok(())
229 }
230
231 fn request_bars(&self, _request: RequestBars) -> anyhow::Result<()> {
232 Ok(())
234 }
235
236 fn request_forward_prices(&self, _request: RequestForwardPrices) -> anyhow::Result<()> {
237 anyhow::bail!("backtest data client cannot fetch forward prices")
240 }
241}
242
243#[cfg(test)]
244mod tests {
245 use nautilus_core::{UUID4, UnixNanos};
246 use rstest::rstest;
247 use ustr::Ustr;
248
249 use super::*;
250
251 #[rstest]
252 fn test_request_forward_prices_returns_err_for_engine_fallback() {
253 let client_id = ClientId::new("BACKTEST");
254 let venue = Venue::new("BACKTEST");
255 let cache = Rc::new(RefCell::new(Cache::default()));
256 let client = BacktestDataClient::new(client_id, venue, cache);
257
258 let request = RequestForwardPrices::new(
259 venue,
260 Ustr::from("BTC"),
261 None,
262 Some(client_id),
263 UUID4::new(),
264 UnixNanos::default(),
265 None,
266 );
267
268 let result = client.request_forward_prices(request);
269 assert!(result.is_err());
270 let msg = result.unwrap_err().to_string();
271 assert!(msg.contains("backtest data client"));
272 }
273}