egui_charts/studies/builtin/
elder_ray.rs1use super::smoothing::Smoothing;
2use crate::model::Bar;
3use crate::studies::palette;
4use crate::studies::stepper::Stepper;
5use crate::studies::{Indicator, IndicatorValue, IndicatorValues};
6use egui::Color32;
7
8#[derive(Clone)]
12pub struct ElderRay {
13 period: usize,
15 values: IndicatorValues,
16 stepper: Stepper<Smoothing>,
17 colors: Vec<Color32>,
19 visible: bool,
20}
21
22impl ElderRay {
23 pub fn new(period: usize) -> Self {
25 Self {
26 period: period.max(1),
27 values: IndicatorValues::new(),
28 stepper: Stepper::default(),
29 colors: vec![
30 palette::TEAL, palette::RED, ],
33 visible: true,
34 }
35 }
36
37 pub fn with_colors(mut self, colors: Vec<Color32>) -> Self {
39 self.colors = colors;
40 self
41 }
42}
43
44impl Default for ElderRay {
46 fn default() -> Self {
47 Self::new(13)
48 }
49}
50
51impl Indicator for ElderRay {
52 fn plot_style(&self, line: usize) -> crate::studies::PlotStyle {
53 crate::studies::PlotStyle {
54 color: self.colors.get(line).copied().unwrap_or(Color32::WHITE),
55 plot_type: crate::studies::PlotType::Columns,
56 width: 1.0,
57 pattern: crate::model::LineStyle::Solid,
58 visible: true,
59 }
60 }
61
62 crate::studies::inputs::study_inputs!(self;
63 period: length("Period", 1, usize::MAX)
64 ; {});
65
66 fn value_format(&self) -> crate::scales::StudyFormat {
67 crate::scales::StudyFormat::Price
68 }
69
70 fn name(&self) -> &str {
71 "Elder Ray"
72 }
73
74 fn desc(&self) -> &str {
75 "Elder Ray - Bull and Bear Power indicators"
76 }
77
78 fn calculate(&mut self, data: &[Bar]) {
79 self.update(data, 0);
80 }
81
82 fn update(&mut self, data: &[Bar], from: usize) {
83 self.stepper
84 .run(data, from, &mut self.values, |state, bar| {
85 if ![bar.high, bar.low, bar.close].iter().all(|x| x.is_finite()) {
86 return IndicatorValue::None;
87 }
88 let ema = state.next(bar.close, self.period, 2.0 / (self.period as f64 + 1.0));
89 if ema.is_nan() {
90 IndicatorValue::None
91 } else {
92 IndicatorValue::Multiple(vec![bar.high - ema, bar.low - ema])
93 }
94 });
95 }
96
97 fn is_incremental(&self) -> bool {
98 true
99 }
100
101 fn values(&self) -> &IndicatorValues {
102 &self.values
103 }
104
105 fn colors(&self) -> Vec<Color32> {
106 self.colors.clone()
107 }
108
109 fn set_colors(&mut self, colors: Vec<Color32>) {
110 if colors.len() >= 2 {
111 self.colors = colors;
112 }
113 }
114
115 fn is_overlay(&self) -> bool {
116 false }
118
119 fn is_visible(&self) -> bool {
120 self.visible
121 }
122
123 fn set_visible(&mut self, visible: bool) {
124 self.visible = visible;
125 }
126
127 fn clone_box(&self) -> Box<dyn Indicator> {
128 Box::new(self.clone())
129 }
130
131 fn line_names(&self) -> Vec<String> {
132 vec![
133 format!("Bull({})", self.period),
134 format!("Bear({})", self.period),
135 ]
136 }
137}