egui_charts/studies/builtin/
acc_dist.rs1use crate::model::Bar;
26use crate::studies::stepper::Stepper;
27use crate::studies::{Indicator, IndicatorValue, IndicatorValues};
28use egui::Color32;
29
30#[derive(Clone)]
32pub struct AccumulationDistribution {
33 values: IndicatorValues,
34 stepper: Stepper<f64>,
35 color: Color32,
36 visible: bool,
37}
38
39impl AccumulationDistribution {
40 pub fn new() -> Self {
42 Self {
43 values: IndicatorValues::new(),
44 stepper: Stepper::default(),
45 color: Color32::from_rgb(153, 153, 21), visible: true,
47 }
48 }
49
50 pub fn with_color(mut self, color: Color32) -> Self {
52 self.color = color;
53 self
54 }
55}
56
57impl Default for AccumulationDistribution {
58 fn default() -> Self {
59 Self::new()
60 }
61}
62
63impl Indicator for AccumulationDistribution {
64 fn value_format(&self) -> crate::scales::StudyFormat {
65 crate::scales::StudyFormat::Volume
66 }
67
68 fn name(&self) -> &str {
69 "A/D"
70 }
71
72 fn desc(&self) -> &str {
73 "Accumulation/Distribution Line - Measures buying/selling pressure"
74 }
75
76 fn calculate(&mut self, data: &[Bar]) {
77 self.update(data, 0);
78 }
79
80 fn update(&mut self, data: &[Bar], from: usize) {
81 self.stepper
82 .run(data, from, &mut self.values, |state, bar| {
83 if ![bar.high, bar.low, bar.close, bar.volume]
84 .iter()
85 .all(|x| x.is_finite())
86 {
87 return IndicatorValue::None;
88 }
89 let range = bar.high - bar.low;
90 if range > 0.0 {
91 let multiplier = (2.0 * bar.close - bar.high - bar.low) / range;
92 *state += multiplier * bar.volume;
93 }
94 IndicatorValue::Single(*state)
95 });
96 }
97
98 fn is_incremental(&self) -> bool {
99 true
100 }
101
102 fn values(&self) -> &IndicatorValues {
103 &self.values
104 }
105
106 fn colors(&self) -> Vec<Color32> {
107 vec![self.color]
108 }
109
110 fn set_colors(&mut self, colors: Vec<Color32>) {
111 if !colors.is_empty() {
112 self.color = colors[0];
113 }
114 }
115
116 fn is_overlay(&self) -> bool {
117 false }
119
120 fn line_count(&self) -> usize {
121 1
122 }
123
124 fn is_visible(&self) -> bool {
125 self.visible
126 }
127
128 fn set_visible(&mut self, visible: bool) {
129 self.visible = visible;
130 }
131
132 fn clone_box(&self) -> Box<dyn Indicator> {
133 Box::new(self.clone())
134 }
135
136 fn line_names(&self) -> Vec<String> {
137 vec!["A/D Line".to_string()]
138 }
139}