use std::{cell::RefCell, rc::Rc};
use nautilus_common::{
cache::Cache,
clients::DataClient,
messages::data::{
RequestBars, RequestBookSnapshot, RequestCustomData, RequestForwardPrices,
RequestInstrument, RequestInstruments, RequestQuotes, RequestTrades, SubscribeBars,
SubscribeBookDeltas, SubscribeBookDepth10, SubscribeCustomData, SubscribeIndexPrices,
SubscribeInstrument, SubscribeInstrumentClose, SubscribeInstrumentStatus,
SubscribeInstruments, SubscribeMarkPrices, SubscribeQuotes, SubscribeTrades,
UnsubscribeBars, UnsubscribeBookDeltas, UnsubscribeBookDepth10, UnsubscribeCustomData,
UnsubscribeIndexPrices, UnsubscribeInstrument, UnsubscribeInstrumentClose,
UnsubscribeInstrumentStatus, UnsubscribeInstruments, UnsubscribeMarkPrices,
UnsubscribeQuotes, UnsubscribeTrades,
},
};
use nautilus_model::identifiers::{ClientId, Venue};
#[derive(Debug)]
pub struct BacktestDataClient {
pub client_id: ClientId,
pub venue: Venue,
_cache: Rc<RefCell<Cache>>,
}
impl BacktestDataClient {
#[must_use]
pub const fn new(client_id: ClientId, venue: Venue, cache: Rc<RefCell<Cache>>) -> Self {
Self {
client_id,
venue,
_cache: cache,
}
}
}
#[async_trait::async_trait(?Send)]
impl DataClient for BacktestDataClient {
fn client_id(&self) -> ClientId {
self.client_id
}
fn venue(&self) -> Option<Venue> {
Some(self.venue)
}
fn start(&mut self) -> anyhow::Result<()> {
Ok(())
}
fn stop(&mut self) -> anyhow::Result<()> {
Ok(())
}
fn reset(&mut self) -> anyhow::Result<()> {
Ok(())
}
fn dispose(&mut self) -> anyhow::Result<()> {
Ok(())
}
fn is_connected(&self) -> bool {
true
}
fn is_disconnected(&self) -> bool {
false
}
fn subscribe(&mut self, _cmd: SubscribeCustomData) -> anyhow::Result<()> {
Ok(())
}
fn subscribe_instruments(&mut self, _cmd: SubscribeInstruments) -> anyhow::Result<()> {
Ok(())
}
fn subscribe_instrument(&mut self, _cmd: SubscribeInstrument) -> anyhow::Result<()> {
Ok(())
}
fn subscribe_book_deltas(&mut self, _cmd: SubscribeBookDeltas) -> anyhow::Result<()> {
Ok(())
}
fn subscribe_book_depth10(&mut self, _cmd: SubscribeBookDepth10) -> anyhow::Result<()> {
Ok(())
}
fn subscribe_quotes(&mut self, _cmd: SubscribeQuotes) -> anyhow::Result<()> {
Ok(())
}
fn subscribe_trades(&mut self, _cmd: SubscribeTrades) -> anyhow::Result<()> {
Ok(())
}
fn subscribe_bars(&mut self, _cmd: SubscribeBars) -> anyhow::Result<()> {
Ok(())
}
fn subscribe_mark_prices(&mut self, _cmd: SubscribeMarkPrices) -> anyhow::Result<()> {
Ok(())
}
fn subscribe_index_prices(&mut self, _cmd: SubscribeIndexPrices) -> anyhow::Result<()> {
Ok(())
}
fn subscribe_instrument_status(
&mut self,
_cmd: SubscribeInstrumentStatus,
) -> anyhow::Result<()> {
Ok(())
}
fn subscribe_instrument_close(&mut self, _cmd: SubscribeInstrumentClose) -> anyhow::Result<()> {
Ok(())
}
fn unsubscribe(&mut self, _cmd: &UnsubscribeCustomData) -> anyhow::Result<()> {
Ok(())
}
fn unsubscribe_instruments(&mut self, _cmd: &UnsubscribeInstruments) -> anyhow::Result<()> {
Ok(())
}
fn unsubscribe_instrument(&mut self, _cmd: &UnsubscribeInstrument) -> anyhow::Result<()> {
Ok(())
}
fn unsubscribe_book_deltas(&mut self, _cmd: &UnsubscribeBookDeltas) -> anyhow::Result<()> {
Ok(())
}
fn unsubscribe_book_depth10(&mut self, _cmd: &UnsubscribeBookDepth10) -> anyhow::Result<()> {
Ok(())
}
fn unsubscribe_quotes(&mut self, _cmd: &UnsubscribeQuotes) -> anyhow::Result<()> {
Ok(())
}
fn unsubscribe_trades(&mut self, _cmd: &UnsubscribeTrades) -> anyhow::Result<()> {
Ok(())
}
fn unsubscribe_bars(&mut self, _cmd: &UnsubscribeBars) -> anyhow::Result<()> {
Ok(())
}
fn unsubscribe_mark_prices(&mut self, _cmd: &UnsubscribeMarkPrices) -> anyhow::Result<()> {
Ok(())
}
fn unsubscribe_index_prices(&mut self, _cmd: &UnsubscribeIndexPrices) -> anyhow::Result<()> {
Ok(())
}
fn unsubscribe_instrument_status(
&mut self,
_cmd: &UnsubscribeInstrumentStatus,
) -> anyhow::Result<()> {
Ok(())
}
fn unsubscribe_instrument_close(
&mut self,
_cmd: &UnsubscribeInstrumentClose,
) -> anyhow::Result<()> {
Ok(())
}
fn request_data(&self, _request: RequestCustomData) -> anyhow::Result<()> {
Ok(())
}
fn request_instruments(&self, _request: RequestInstruments) -> anyhow::Result<()> {
Ok(())
}
fn request_instrument(&self, _request: RequestInstrument) -> anyhow::Result<()> {
Ok(())
}
fn request_book_snapshot(&self, _request: RequestBookSnapshot) -> anyhow::Result<()> {
Ok(())
}
fn request_quotes(&self, _request: RequestQuotes) -> anyhow::Result<()> {
Ok(())
}
fn request_trades(&self, _request: RequestTrades) -> anyhow::Result<()> {
Ok(())
}
fn request_bars(&self, _request: RequestBars) -> anyhow::Result<()> {
Ok(())
}
fn request_forward_prices(&self, _request: RequestForwardPrices) -> anyhow::Result<()> {
anyhow::bail!("backtest data client cannot fetch forward prices")
}
}
#[cfg(test)]
mod tests {
use nautilus_core::{UUID4, UnixNanos};
use rstest::rstest;
use ustr::Ustr;
use super::*;
#[rstest]
fn test_request_forward_prices_returns_err_for_engine_fallback() {
let client_id = ClientId::new("BACKTEST");
let venue = Venue::new("BACKTEST");
let cache = Rc::new(RefCell::new(Cache::default()));
let client = BacktestDataClient::new(client_id, venue, cache);
let request = RequestForwardPrices::new(
venue,
Ustr::from("BTC"),
None,
Some(client_id),
UUID4::new(),
UnixNanos::default(),
None,
);
let result = client.request_forward_prices(request);
assert!(result.is_err());
let msg = result.unwrap_err().to_string();
assert!(msg.contains("backtest data client"));
}
}