#![allow(unused)]
use std::sync::{Arc, OnceLock};
use async_trait::async_trait;
use quantoxide::{
error::Result,
models::{Lookback, MinIterationInterval, OhlcCandleRow, OhlcResolution},
trade::{RawOperator, TradeExecutor, TradingState},
tui::TuiLogger,
};
pub struct RawOperatorTemplate {
trade_executor: OnceLock<Arc<dyn TradeExecutor>>,
logger: Option<Arc<dyn TuiLogger>>,
}
impl RawOperatorTemplate {
pub fn new() -> Box<Self> {
Box::new(Self {
trade_executor: OnceLock::new(),
logger: None,
})
}
pub fn with_logger(logger: Arc<dyn TuiLogger>) -> Box<Self> {
Box::new(Self {
trade_executor: OnceLock::new(),
logger: Some(logger),
})
}
fn trade_executor(&self) -> Result<&Arc<dyn TradeExecutor>> {
if let Some(trade_executor) = self.trade_executor.get() {
return Ok(trade_executor);
}
Err("trade executor was not set".into())
}
async fn log(&self, text: String) -> Result<()> {
if let Some(logger) = self.logger.as_ref() {
logger.log(text).await?;
}
Ok(())
}
}
#[async_trait]
impl RawOperator for RawOperatorTemplate {
fn set_trade_executor(&mut self, trade_executor: Arc<dyn TradeExecutor>) -> Result<()> {
if self.trade_executor.set(trade_executor).is_err() {
return Err("trade executor was already set".into());
}
Ok(())
}
fn lookback(&self) -> Option<Lookback> {
Some(Lookback::new(OhlcResolution::FifteenMinutes, 10).expect("is valid"))
}
fn min_iteration_interval(&self) -> MinIterationInterval {
MinIterationInterval::MIN }
async fn iterate(&self, candles: &[OhlcCandleRow]) -> Result<()> {
let trade_executor = self.trade_executor()?;
let trading_state: TradingState = trade_executor.trading_state().await?;
let iteration_time = trading_state.last_tick_time();
let balance = trading_state.balance();
let market_price = trading_state.market_price();
let running_trades_map = trading_state.running_map();
for ((creation_time, trade_id), (trade, tsl)) in running_trades_map {
let client_id = trade.client_id();
let side = trade.side();
let pl = trade.est_pl(market_price);
}
Ok(())
}
}