plotly_fork/traces/
ohlc.rs

1//! Open-high-low-close (OHLC) trace
2
3use plotly_derive::FieldSetter;
4use serde::Serialize;
5
6use crate::{
7    common::{
8        Calendar, Dim, Direction, HoverInfo, Label, LegendGroupTitle, Line, PlotType, Visible,
9    },
10    Trace,
11};
12
13/// Construct an OHLC trace.
14///
15/// # Examples
16///
17/// ```
18/// use plotly::Ohlc;
19///
20/// let trace = Ohlc::new(
21///     vec!["2022-08-22", "2022-08-23"],
22///     vec![5, 6],
23///     vec![8, 10],
24///     vec![2, 4],
25///     vec![6, 7],
26/// );
27///
28/// let expected = serde_json::json!({
29///     "type": "ohlc",
30///     "x": ["2022-08-22", "2022-08-23"],
31///     "open": [5, 6],        
32///     "high": [8, 10],
33///     "low": [2, 4],
34///     "close": [6, 7]
35/// });
36///
37/// assert_eq!(serde_json::to_value(trace).unwrap(), expected);
38/// ```
39#[serde_with::skip_serializing_none]
40#[derive(Serialize, Debug, Clone, FieldSetter)]
41pub struct Ohlc<X, O>
42where
43    X: Serialize + Clone,
44    O: Serialize + Clone,
45{
46    #[field_setter(default = "PlotType::Ohlc")]
47    r#type: PlotType,
48    x: Option<Vec<X>>,
49    open: Option<Vec<O>>,
50    high: Option<Vec<O>>,
51    low: Option<Vec<O>>,
52    close: Option<Vec<O>>,
53    decreasing: Option<Direction>,
54    #[serde(rename = "hoverinfo")]
55    hover_info: Option<HoverInfo>,
56    #[serde(rename = "hoverlabel")]
57    hover_label: Option<Label>,
58    #[serde(rename = "hovertext")]
59    hover_text: Option<Dim<String>>,
60    increasing: Option<Direction>,
61    #[serde(rename = "legendgroup")]
62    legend_group: Option<String>,
63    #[serde(rename = "legendgrouptitle")]
64    legend_group_title: Option<LegendGroupTitle>,
65    line: Option<Line>,
66    name: Option<String>,
67    opacity: Option<f64>,
68    #[serde(rename = "showlegend")]
69    show_legend: Option<bool>,
70    text: Option<Dim<String>>,
71    #[serde(rename = "tickwidth")]
72    tick_width: Option<f64>,
73    visible: Option<Visible>,
74    #[serde(rename = "xcalendar")]
75    x_calendar: Option<Calendar>,
76}
77
78impl<X, O> Ohlc<X, O>
79where
80    X: Serialize + Clone,
81    O: Serialize + Clone,
82{
83    pub fn new(x: Vec<X>, open: Vec<O>, high: Vec<O>, low: Vec<O>, close: Vec<O>) -> Box<Self> {
84        Box::new(Ohlc {
85            r#type: PlotType::Ohlc,
86            x: Some(x),
87            open: Some(open),
88            high: Some(high),
89            low: Some(low),
90            close: Some(close),
91            ..Default::default()
92        })
93    }
94}
95
96impl<X, O> Trace for Ohlc<X, O>
97where
98    X: Serialize + Clone,
99    O: Serialize + Clone,
100{
101    fn to_json(&self) -> String {
102        serde_json::to_string(self).unwrap()
103    }
104}
105
106#[cfg(test)]
107mod test {
108    use serde_json::{json, to_value};
109
110    use super::*;
111
112    #[test]
113    fn test_serialize_default_ohlc() {
114        let trace = Ohlc::<u32, u32>::default();
115        let expected = json!({"type": "ohlc"});
116
117        assert_eq!(to_value(trace).unwrap(), expected);
118    }
119
120    #[test]
121    fn test_serialize_ohlc() {
122        let trace = Ohlc::new(
123            vec![0, 1],
124            vec![5.0, 6.0],
125            vec![10.0, 15.0],
126            vec![4.0, 2.0],
127            vec![6.0, 13.0],
128        )
129        .decreasing(Direction::Decreasing { line: Line::new() })
130        .hover_info(HoverInfo::X)
131        .hover_label(Label::new())
132        .hover_text_array(vec!["1", "2"])
133        .hover_text("1")
134        .increasing(Direction::Increasing { line: Line::new() })
135        .legend_group("legendgroup")
136        .legend_group_title(LegendGroupTitle::new("Legend Group Title"))
137        .line(Line::new())
138        .name("ohlc_trace")
139        .opacity(0.4)
140        .show_legend(true)
141        .text_array(vec!["3", "4"])
142        .text("3")
143        .tick_width(0.1)
144        .visible(Visible::LegendOnly)
145        .x_calendar(Calendar::Nepali);
146
147        let expected = json!({
148            "type": "ohlc",
149            "x": [0, 1],
150            "open": [5.0, 6.0],
151            "high": [10.0, 15.0],
152            "low": [4.0, 2.0],
153            "close": [6.0, 13.0],
154            "decreasing": {"line": {}},
155            "hoverinfo": "x",
156            "hoverlabel": {},
157            "hovertext": "1",
158            "increasing": {"line": {}},
159            "legendgroup": "legendgroup",
160            "legendgrouptitle": {"text": "Legend Group Title"},
161            "line": {},
162            "name": "ohlc_trace",
163            "opacity": 0.4,
164            "showlegend": true,
165            "text": "3",
166            "tickwidth": 0.1,
167            "visible": "legendonly",
168            "xcalendar": "nepali"
169        });
170
171        assert_eq!(to_value(trace).unwrap(), expected);
172    }
173}