cli_candlestick_chart/
chart.rs

1use crate::{
2    chart_data::ChartData, chart_renderer::ChartRenderer, info_bar::InfoBar,
3    volume_pane::VolumePane, y_axis::YAxis,
4};
5use std::cell::RefCell;
6use std::rc::Rc;
7
8#[derive(Debug, Clone)]
9#[cfg_attr(feature = "serde", derive(serde::Deserialize))]
10pub struct Candle {
11    pub open: f64,
12    pub high: f64,
13    pub low: f64,
14    pub close: f64,
15    pub volume: Option<f64>,
16    pub timestamp: Option<i64>,
17}
18
19pub(crate) enum CandleType {
20    Bearish,
21    Bullish,
22}
23
24impl Candle {
25    #[allow(dead_code)]
26    pub fn new(
27        open: f64,
28        high: f64,
29        low: f64,
30        close: f64,
31        volume: Option<f64>,
32        timestamp: Option<i64>,
33    ) -> Candle {
34        Candle {
35            open,
36            high,
37            low,
38            close,
39            volume,
40            timestamp,
41        }
42    }
43
44    pub(crate) fn get_type(&self) -> CandleType {
45        match self.open < self.close {
46            true => CandleType::Bullish,
47            false => CandleType::Bearish,
48        }
49    }
50}
51
52pub struct Chart {
53    pub(crate) renderer: ChartRenderer,
54    pub(crate) y_axis: YAxis,
55    pub(crate) chart_data: Rc<RefCell<ChartData>>,
56    pub(crate) info_bar: InfoBar,
57    pub(crate) volume_pane: VolumePane,
58}
59
60impl Chart {
61    pub fn new(candles: &[Candle]) -> Self {
62        let renderer = ChartRenderer::new();
63        let chart_data = Rc::new(RefCell::new(ChartData::new(candles.to_vec())));
64        let y_axis = YAxis::new(chart_data.clone());
65        let info_bar = InfoBar::new("APPLE".to_string(), chart_data.clone());
66
67        let volume_pane = VolumePane::new(
68            chart_data.clone(),
69            (chart_data.borrow().terminal_size.1 / 6) as i64,
70        );
71
72        chart_data.borrow_mut().compute_height(&volume_pane);
73
74        Chart {
75            renderer,
76            y_axis,
77            chart_data,
78            info_bar,
79            volume_pane,
80        }
81    }
82
83    /// Draws the chart by outputting multiples strings in the terminal.
84    pub fn draw(&self) {
85        self.renderer.render(self);
86    }
87
88    /// Set the name of the chart in the info bar.
89    pub fn set_name(&mut self, name: String) {
90        self.info_bar.name = name;
91    }
92
93    /// Set the color of the bearish candle
94    /// The default color is  (234, 74, 90).
95    pub fn set_bear_color(&mut self, r: u8, g: u8, b: u8) {
96        self.renderer.bearish_color = (r, g, b);
97    }
98
99    /// Set the color of the bullish candle
100    /// The default color is  (52, 208, 88).
101    pub fn set_bull_color(&mut self, r: u8, g: u8, b: u8) {
102        self.renderer.bullish_color = (r, g, b);
103    }
104
105    /// Sets the color of the volume when the candle is bearish.
106    /// The default color is  (234, 74, 90).
107    pub fn set_vol_bear_color(&mut self, r: u8, g: u8, b: u8) {
108        self.volume_pane.bearish_color = (r, g, b);
109    }
110
111    /// Sets the color of the volume when the candle is bullish.
112    /// The default color is  (52, 208, 88).
113    pub fn set_vol_bull_color(&mut self, r: u8, g: u8, b: u8) {
114        self.volume_pane.bullish_color = (r, g, b);
115    }
116
117    /// Hide or show the volume pane.
118    pub fn set_volume_pane_enabled(&mut self, enabled: bool) {
119        self.volume_pane.enabled = enabled;
120    }
121
122    /// Set the character for drawing the volume bars.
123    pub fn set_volume_pane_unicode_fill(&mut self, unicode_fill: char) {
124        self.volume_pane.unicode_fill = unicode_fill;
125    }
126
127    /// Set the volume pane height.
128    /// Default is 1/6 of the terminal height.
129    pub fn set_volume_pane_height(&mut self, height: i64) {
130        self.volume_pane.height = height;
131    }
132}