use crate::{
errors::MarketResult,
indicators::{EnhancedMarketSeries, EnhancedSeries},
publishers::Publisher,
MarketError,
};
use chrono::NaiveDate;
use serde::{Deserialize, Serialize};
use std::fmt;
pub struct MarketClient<T: Publisher> {
inner: T,
}
impl<T: Publisher> MarketClient<T> {
pub fn new(site: T) -> Self {
MarketClient { inner: site }
}
pub fn create_endpoint(mut self) -> MarketResult<Self> {
self.inner.create_endpoint()?;
Ok(self)
}
#[cfg(feature = "use-async")]
pub async fn get_data(mut self) -> MarketResult<Self> {
self.inner.get_data().await?;
Ok(self)
}
#[cfg(feature = "use-sync")]
pub fn get_data(mut self) -> MarketResult<Self> {
self.inner.get_data()?;
Ok(self)
}
pub fn to_writer(&self, writer: impl std::io::Write) -> MarketResult<()> {
self.inner.to_writer(writer)?;
Ok(())
}
pub fn transform_data(&self) -> MarketResult<MarketSeries> {
let data = self.inner.transform_data().map_err(|err| {
MarketError::DownloadedData(format!("Unable to transform the data: {}", err))
})?;
Ok(data)
}
}
#[derive(Debug, Serialize, Deserialize)]
pub struct MarketSeries {
pub symbol: String,
pub data: Vec<Series>,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct Series {
pub date: NaiveDate,
pub open: f32,
pub close: f32,
pub high: f32,
pub low: f32,
pub volume: f32,
}
impl MarketSeries {
pub fn enhance_data(&self) -> EnhancedMarketSeries {
let enhanced_series: Vec<EnhancedSeries> = self
.data
.iter()
.map(|item| EnhancedSeries {
date: item.date,
open: item.open,
close: item.close,
high: item.high,
low: item.low,
volume: item.volume,
..Default::default()
})
.collect();
EnhancedMarketSeries {
symbol: self.symbol.clone(),
indicators: Vec::new(),
data: enhanced_series,
}
}
}
impl fmt::Display for MarketSeries {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"MarketSeries: Symbol={}, Series=\n{}",
self.symbol,
self.data
.iter()
.map(|series| format!(" {}", series))
.collect::<Vec<String>>()
.join("\n")
)
}
}
impl fmt::Display for Series {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"Date: {}, Open: {}, Close: {}, High: {}, Low: {}, Volume: {}",
self.date, self.open, self.close, self.high, self.low, self.volume
)
}
}