use std::{fmt::Debug, hash::Hash};
use serde::{Deserialize, Serialize};
use crate::{
data::{
common::ProfileAggregation,
domain::{
CountryCode, DataBroker, EconomicCategory, EconomicDataSource, EconomicEventImpact,
Exchange, Period, Symbol,
},
event::{EconomicCalendarId, OhlcvId, TpoId, TradesId, VolumeProfileId},
indicator::{EmaWindow, RsiWindow, SmaWindow, TechnicalIndicator},
},
error::ChapatyResult,
};
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct OhlcvSpotConfig {
pub broker: DataBroker,
pub symbol: Symbol,
pub exchange: Option<Exchange>,
pub period: Period,
pub batch_size: i32,
pub indicators: Vec<TechnicalIndicator>,
}
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct OhlcvFutureConfig {
pub broker: DataBroker,
pub symbol: Symbol,
pub exchange: Option<Exchange>,
pub period: Period,
pub batch_size: i32,
pub indicators: Vec<TechnicalIndicator>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, Serialize, Deserialize)]
pub struct TradeSpotConfig {
pub broker: DataBroker,
pub symbol: Symbol,
pub exchange: Option<Exchange>,
pub batch_size: i32,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, Serialize, Deserialize)]
pub struct TpoSpotConfig {
pub broker: DataBroker,
pub symbol: Symbol,
pub exchange: Option<Exchange>,
pub aggregation: Option<ProfileAggregation>,
pub batch_size: i32,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, Serialize, Deserialize)]
pub struct TpoFutureConfig {
pub broker: DataBroker,
pub symbol: Symbol,
pub exchange: Option<Exchange>,
pub aggregation: Option<ProfileAggregation>,
pub batch_size: i32,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, Serialize, Deserialize)]
pub struct VolumeProfileSpotConfig {
pub broker: DataBroker,
pub symbol: Symbol,
pub exchange: Option<Exchange>,
pub aggregation: Option<ProfileAggregation>,
pub batch_size: i32,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, Serialize, Deserialize)]
pub struct EconomicCalendarConfig {
pub broker: DataBroker,
pub data_source: Option<EconomicDataSource>,
pub country_code: Option<CountryCode>,
pub category: Option<EconomicCategory>,
pub importance: Option<EconomicEventImpact>,
pub batch_size: i32,
}
pub trait TechnicalAnalysis {
fn add_indicator(&mut self, kind: TechnicalIndicator);
fn with_indicator(mut self, kind: TechnicalIndicator) -> Self
where
Self: Sized,
{
self.add_indicator(kind);
self
}
fn with_sma(self, window: u16) -> Self
where
Self: Sized,
{
self.with_indicator(TechnicalIndicator::Sma(SmaWindow(window)))
}
fn with_ema(self, window: u16) -> Self
where
Self: Sized,
{
self.with_indicator(TechnicalIndicator::Ema(EmaWindow(window)))
}
fn with_rsi(self, window: u16) -> Self
where
Self: Sized,
{
self.with_indicator(TechnicalIndicator::Rsi(RsiWindow(window)))
}
fn with_indicators(mut self, kinds: Vec<TechnicalIndicator>) -> Self
where
Self: Sized,
{
for kind in kinds {
self.add_indicator(kind);
}
self
}
fn with_smas(mut self, windows: &[u16]) -> Self
where
Self: Sized,
{
for &window in windows {
self.add_indicator(TechnicalIndicator::Sma(SmaWindow(window)));
}
self
}
fn with_emas(mut self, windows: &[u16]) -> Self
where
Self: Sized,
{
for &window in windows {
self.add_indicator(TechnicalIndicator::Ema(EmaWindow(window)));
}
self
}
}
impl TechnicalAnalysis for OhlcvSpotConfig {
fn add_indicator(&mut self, kind: TechnicalIndicator) {
self.indicators.push(kind);
}
}
impl TechnicalAnalysis for OhlcvFutureConfig {
fn add_indicator(&mut self, kind: TechnicalIndicator) {
self.indicators.push(kind);
}
}
pub trait ConfigId {
type Id: Copy + PartialEq + Eq + Hash + PartialOrd + Ord + Debug + Send + Sync;
fn to_id(&self) -> ChapatyResult<Self::Id>;
}
impl ConfigId for OhlcvSpotConfig {
type Id = OhlcvId;
fn to_id(&self) -> ChapatyResult<Self::Id> {
let exchange = match self.exchange {
Some(ex) => ex,
None => self.broker.try_into()?,
};
Ok(OhlcvId {
broker: self.broker,
exchange,
symbol: self.symbol,
period: self.period,
})
}
}
impl ConfigId for OhlcvFutureConfig {
type Id = OhlcvId;
fn to_id(&self) -> ChapatyResult<Self::Id> {
let exchange = match self.exchange {
Some(ex) => ex,
None => self.broker.try_into()?,
};
Ok(OhlcvId {
broker: self.broker,
exchange,
symbol: self.symbol,
period: self.period,
})
}
}
impl ConfigId for TradeSpotConfig {
type Id = TradesId;
fn to_id(&self) -> ChapatyResult<Self::Id> {
let exchange = match self.exchange {
Some(ex) => ex,
None => self.broker.try_into()?,
};
Ok(TradesId {
broker: self.broker,
exchange,
symbol: self.symbol,
})
}
}
impl ConfigId for TpoSpotConfig {
type Id = TpoId;
fn to_id(&self) -> ChapatyResult<Self::Id> {
let exchange = match self.exchange {
Some(ex) => ex,
None => self.broker.try_into()?,
};
Ok(TpoId {
broker: self.broker,
exchange,
symbol: self.symbol,
aggregation: self.aggregation.unwrap_or_default(),
})
}
}
impl ConfigId for TpoFutureConfig {
type Id = TpoId;
fn to_id(&self) -> ChapatyResult<Self::Id> {
let exchange = match self.exchange {
Some(ex) => ex,
None => self.broker.try_into()?,
};
Ok(TpoId {
broker: self.broker,
exchange,
symbol: self.symbol,
aggregation: self.aggregation.unwrap_or_default(),
})
}
}
impl ConfigId for VolumeProfileSpotConfig {
type Id = VolumeProfileId;
fn to_id(&self) -> ChapatyResult<Self::Id> {
let exchange = match self.exchange {
Some(ex) => ex,
None => self.broker.try_into()?,
};
Ok(VolumeProfileId {
broker: self.broker,
exchange,
symbol: self.symbol,
aggregation: self.aggregation.unwrap_or_default(),
})
}
}
impl ConfigId for EconomicCalendarConfig {
type Id = EconomicCalendarId;
fn to_id(&self) -> ChapatyResult<Self::Id> {
Ok(EconomicCalendarId {
broker: self.broker,
data_source: self.data_source,
country_code: self.country_code,
category: self.category,
importance: self.importance,
})
}
}