1 //! "Candlestick" plots 2 3 use std::borrow::Cow; 4 use std::iter::IntoIterator; 5 6 use crate::data::Matrix; 7 use crate::traits::{self, Data, Set}; 8 use crate::{Color, Default, Display, Figure, Label, LineType, LineWidth, Plot, Script}; 9 10 /// Properties common to candlestick plots 11 pub struct Properties { 12 color: Option<Color>, 13 label: Option<Cow<'static, str>>, 14 line_type: LineType, 15 linewidth: Option<f64>, 16 } 17 18 impl Default for Properties { default() -> Properties19 fn default() -> Properties { 20 Properties { 21 color: None, 22 label: None, 23 line_type: LineType::Solid, 24 linewidth: None, 25 } 26 } 27 } 28 29 impl Script for Properties { script(&self) -> String30 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 55 impl Set<Color> for Properties { 56 /// Sets the line color set(&mut self, color: Color) -> &mut Properties57 fn set(&mut self, color: Color) -> &mut Properties { 58 self.color = Some(color); 59 self 60 } 61 } 62 63 impl Set<Label> for Properties { 64 /// Sets the legend label set(&mut self, label: Label) -> &mut Properties65 fn set(&mut self, label: Label) -> &mut Properties { 66 self.label = Some(label.0); 67 self 68 } 69 } 70 71 impl Set<LineType> for Properties { 72 /// Changes the line type 73 /// 74 /// **Note** By default `Solid` lines are used set(&mut self, lt: LineType) -> &mut Properties75 fn set(&mut self, lt: LineType) -> &mut Properties { 76 self.line_type = lt; 77 self 78 } 79 } 80 81 impl Set<LineWidth> for Properties { 82 /// Changes the width of the line 83 /// 84 /// # Panics 85 /// 86 /// Panics if `width` is a non-positive value set(&mut self, lw: LineWidth) -> &mut Properties87 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 98 pub 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 111 impl<X, WM, BM, BH, WH> traits::Plot<Candlesticks<X, WM, BM, BH, WH>> for Figure 112 where 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 plot<F>( &mut self, candlesticks: Candlesticks<X, WM, BM, BH, WH>, configure: F, ) -> &mut Figure where F: FnOnce(&mut Properties) -> &mut Properties,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 } 152