1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
//! Market-Data client implementation

use crate::{
    errors::MarketResult,
    indicators::{EnhancedMarketSeries, EnhancedSeries},
    publishers::Publisher,
    MarketError,
};
use chrono::NaiveDate;
use serde::{Deserialize, Serialize};
use std::fmt;

/// MarketClient holds the Publisher
pub struct MarketClient<T: Publisher> {
    inner: T,
}

impl<T: Publisher> MarketClient<T> {
    pub fn new(site: T) -> Self {
        MarketClient { inner: site }
    }

    /// Creates the final query URL for the selected Provider
    pub fn create_endpoint(mut self) -> MarketResult<Self> {
        self.inner.create_endpoint()?;
        Ok(self)
    }

    /// Download the data series in the Provider format
    #[cfg(feature = "use-async")]
    pub async fn get_data(mut self) -> MarketResult<Self> {
        self.inner.get_data().await?;
        Ok(self)
    }

    /// Download the data series in the Provider format
    #[cfg(feature = "use-sync")]
    pub fn get_data(mut self) -> MarketResult<Self> {
        self.inner.get_data()?;
        Ok(self)
    }

    /// Write the downloaded data to anything that implements std::io::Write , like File, TcpStream, Stdout, etc
    pub fn to_writer(&self, writer: impl std::io::Write) -> MarketResult<()> {
        self.inner.to_writer(writer)?;
        Ok(())
    }

    /// Transform the downloaded Provider series into MarketSeries format
    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)
    }
}

/// Holds the parsed data from Publishers
#[derive(Debug, Serialize, Deserialize)]
pub struct MarketSeries {
    pub symbol: String,
    pub data: Vec<Series>,
}

/// Series part of the MarketSeries
#[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
        )
    }
}