blob: e0a5cbebc9846ab8b588f6e3dee9586ec994d159 [file] [log] [blame]
Jakub Kotur835fea42020-12-21 17:28:14 +01001//! "Candlestick" plots
2
3use std::borrow::Cow;
4use std::iter::IntoIterator;
5
6use crate::data::Matrix;
7use crate::traits::{self, Data, Set};
8use crate::{Color, Default, Display, Figure, Label, LineType, LineWidth, Plot, Script};
9
10/// Properties common to candlestick plots
11pub struct Properties {
12 color: Option<Color>,
13 label: Option<Cow<'static, str>>,
14 line_type: LineType,
15 linewidth: Option<f64>,
16}
17
18impl Default for Properties {
19 fn default() -> Properties {
20 Properties {
21 color: None,
22 label: None,
23 line_type: LineType::Solid,
24 linewidth: None,
25 }
26 }
27}
28
29impl Script for Properties {
30 fn script(&self) -> String {
31 let mut script = String::from("with candlesticks ");
32
33 script.push_str(&format!("lt {} ", self.line_type.display()));
34
35 if let Some(lw) = self.linewidth {
36 script.push_str(&format!("lw {} ", lw))
37 }
38
39 if let Some(color) = self.color {
40 script.push_str(&format!("lc rgb '{}' ", color.display()));
41 }
42
43 if let Some(ref label) = self.label {
44 script.push_str("title '");
45 script.push_str(label);
46 script.push('\'')
47 } else {
48 script.push_str("notitle")
49 }
50
51 script
52 }
53}
54
55impl Set<Color> for Properties {
56 /// Sets the line color
57 fn set(&mut self, color: Color) -> &mut Properties {
58 self.color = Some(color);
59 self
60 }
61}
62
63impl Set<Label> for Properties {
64 /// Sets the legend label
65 fn set(&mut self, label: Label) -> &mut Properties {
66 self.label = Some(label.0);
67 self
68 }
69}
70
71impl Set<LineType> for Properties {
72 /// Changes the line type
73 ///
74 /// **Note** By default `Solid` lines are used
75 fn set(&mut self, lt: LineType) -> &mut Properties {
76 self.line_type = lt;
77 self
78 }
79}
80
81impl Set<LineWidth> for Properties {
82 /// Changes the width of the line
83 ///
84 /// # Panics
85 ///
86 /// Panics if `width` is a non-positive value
87 fn set(&mut self, lw: LineWidth) -> &mut Properties {
88 let lw = lw.0;
89
90 assert!(lw > 0.);
91
92 self.linewidth = Some(lw);
93 self
94 }
95}
96
97/// A candlestick consists of a box and two whiskers that extend beyond the box
98pub struct Candlesticks<X, WM, BM, BH, WH> {
99 /// X coordinate of the candlestick
100 pub x: X,
101 /// Y coordinate of the end point of the bottom whisker
102 pub whisker_min: WM,
103 /// Y coordinate of the bottom of the box
104 pub box_min: BM,
105 /// Y coordinate of the top of the box
106 pub box_high: BH,
107 /// Y coordinate of the end point of the top whisker
108 pub whisker_high: WH,
109}
110
111impl<X, WM, BM, BH, WH> traits::Plot<Candlesticks<X, WM, BM, BH, WH>> for Figure
112where
113 BH: IntoIterator,
114 BH::Item: Data,
115 BM: IntoIterator,
116 BM::Item: Data,
117 WH: IntoIterator,
118 WH::Item: Data,
119 WM: IntoIterator,
120 WM::Item: Data,
121 X: IntoIterator,
122 X::Item: Data,
123{
124 type Properties = Properties;
125
126 fn plot<F>(
127 &mut self,
128 candlesticks: Candlesticks<X, WM, BM, BH, WH>,
129 configure: F,
130 ) -> &mut Figure
131 where
132 F: FnOnce(&mut Properties) -> &mut Properties,
133 {
134 let (x_factor, y_factor) = crate::scale_factor(&self.axes, crate::Axes::BottomXLeftY);
135 let Candlesticks {
136 x,
137 whisker_min,
138 box_min,
139 box_high,
140 whisker_high,
141 } = candlesticks;
142
143 let data = Matrix::new(
144 izip!(x, box_min, whisker_min, whisker_high, box_high),
145 (x_factor, y_factor, y_factor, y_factor, y_factor),
146 );
147 self.plots
148 .push(Plot::new(data, configure(&mut Default::default())));
149 self
150 }
151}