plotlars/components/
direction.rs

1use plotly::common::{Direction as DirectionPlotly, Line as LinePlotly};
2
3use crate::components::Rgb;
4
5/// A structure representing the styling for candlestick directions (increasing/decreasing).
6///
7/// The `Direction` struct allows customization of how candlestick lines appear when the closing price
8/// is higher (increasing) or lower (decreasing) than the opening price. This includes setting
9/// the line color and width for the candlesticks.
10///
11/// Note: Fill color is not currently supported by the underlying plotly library.
12///
13/// # Example
14///
15/// ```rust
16/// use plotlars::{CandlestickPlot, Direction, Plot, Rgb};
17/// use polars::prelude::*;
18///
19/// let dates = vec!["2024-01-01", "2024-01-02", "2024-01-03"];
20/// let open_prices = vec![100.0, 102.5, 101.0];
21/// let high_prices = vec![103.0, 104.0, 103.5];
22/// let low_prices = vec![99.0, 101.5, 100.0];
23/// let close_prices = vec![102.5, 101.0, 103.5];
24///
25/// let stock_data = df! {
26///     "date" => dates,
27///     "open" => open_prices,
28///     "high" => high_prices,
29///     "low" => low_prices,
30///     "close" => close_prices,
31/// }
32/// .unwrap();
33///
34/// let increasing = Direction::new()
35///     .line_color(Rgb(0, 150, 255))
36///     .line_width(2.0);
37///
38/// let decreasing = Direction::new()
39///     .line_color(Rgb(200, 0, 100))
40///     .line_width(2.0);
41///
42/// CandlestickPlot::builder()
43///     .data(&stock_data)
44///     .dates("date")
45///     .open("open")
46///     .high("high")
47///     .low("low")
48///     .close("close")
49///     .increasing(&increasing)
50///     .decreasing(&decreasing)
51///     .build()
52///     .plot();
53/// ```
54///
55/// ![Example](https://imgur.com/SygxOCm.png)
56#[derive(Clone, Default)]
57pub struct Direction {
58    pub(crate) line_color: Option<Rgb>,
59    pub(crate) line_width: Option<f64>,
60}
61
62impl Direction {
63    /// Creates a new `Direction` instance with default settings.
64    ///
65    /// # Returns
66    ///
67    /// A new `Direction` instance with no customizations applied.
68    pub fn new() -> Self {
69        Self::default()
70    }
71
72    /// Sets the line color for the candlestick outline and wicks.
73    ///
74    /// # Arguments
75    ///
76    /// * `color` - An `Rgb` color for the candlestick lines.
77    ///
78    /// # Returns
79    ///
80    /// The modified `Direction` instance for method chaining.
81    pub fn line_color(mut self, color: Rgb) -> Self {
82        self.line_color = Some(color);
83        self
84    }
85
86    /// Sets the line width for the candlestick outline and wicks.
87    ///
88    /// # Arguments
89    ///
90    /// * `width` - The width of the candlestick lines in pixels.
91    ///
92    /// # Returns
93    ///
94    /// The modified `Direction` instance for method chaining.
95    pub fn line_width(mut self, width: f64) -> Self {
96        self.line_width = Some(width);
97        self
98    }
99
100    /// Converts the `Direction` to plotly's Direction::Increasing type.
101    ///
102    /// # Returns
103    ///
104    /// A `DirectionPlotly::Increasing` instance with the configured settings.
105    pub(crate) fn to_plotly_increasing(&self) -> DirectionPlotly {
106        let mut line = LinePlotly::new();
107
108        if let Some(line_color) = &self.line_color {
109            line = line.color(line_color.to_plotly());
110        }
111
112        if let Some(width) = self.line_width {
113            line = line.width(width);
114        }
115
116        DirectionPlotly::Increasing { line }
117    }
118
119    /// Converts the `Direction` to plotly's Direction::Decreasing type.
120    ///
121    /// # Returns
122    ///
123    /// A `DirectionPlotly::Decreasing` instance with the configured settings.
124    pub(crate) fn to_plotly_decreasing(&self) -> DirectionPlotly {
125        let mut line = LinePlotly::new();
126
127        if let Some(line_color) = &self.line_color {
128            line = line.color(line_color.to_plotly());
129        }
130
131        if let Some(width) = self.line_width {
132            line = line.width(width);
133        }
134
135        DirectionPlotly::Decreasing { line }
136    }
137}