egui_charts/studies/builtin/
williams_ad.rs1use crate::model::Bar;
2use crate::studies::palette;
3use crate::studies::stepper::Stepper;
4use crate::studies::{Indicator, IndicatorValue, IndicatorValues};
5use egui::Color32;
6
7#[derive(Clone)]
11pub struct WilliamsAD {
12 values: IndicatorValues,
13 stepper: Stepper<State>,
14 color: Color32,
15 visible: bool,
16}
17
18#[derive(Clone, Default)]
19struct State {
20 bars: usize,
21 count: usize,
22 first: Option<usize>,
23 previous: Option<Bar>,
24 total: f64,
25}
26
27impl WilliamsAD {
28 pub fn new() -> Self {
30 Self {
31 values: IndicatorValues::new(),
32 stepper: Stepper::default(),
33 color: palette::UP, visible: true,
35 }
36 }
37
38 pub fn with_color(mut self, color: Color32) -> Self {
40 self.color = color;
41 self
42 }
43}
44
45impl Default for WilliamsAD {
46 fn default() -> Self {
47 Self::new()
48 }
49}
50
51impl Indicator for WilliamsAD {
52 fn value_format(&self) -> crate::scales::StudyFormat {
53 crate::scales::StudyFormat::Price
54 }
55
56 fn name(&self) -> &str {
57 "WAD"
58 }
59
60 fn desc(&self) -> &str {
61 "Williams Accumulation/Distribution - Buying/selling pressure"
62 }
63
64 fn calculate(&mut self, data: &[Bar]) {
65 self.update(data, 0);
66 }
67
68 fn update(&mut self, data: &[Bar], from: usize) {
69 self.stepper
70 .run(data, from, &mut self.values, |state, bar| {
71 let index = state.bars;
72 state.bars += 1;
73 if !([bar.high, bar.low, bar.close].iter().all(|x| x.is_finite())) {
74 return IndicatorValue::None;
75 }
76 state.count += 1;
77 if let Some(previous) = &state.previous {
78 state.total += if bar.close > previous.close {
79 bar.close - bar.low.min(previous.close)
80 } else if bar.close < previous.close {
81 bar.close - bar.high.max(previous.close)
82 } else {
83 0.0
84 };
85 }
86 state.first.get_or_insert(index);
87 state.previous = Some(bar.clone());
88 IndicatorValue::Single(state.total)
89 });
90 if let Some(first) = self.stepper.state().first {
92 self.values.set(
93 first,
94 if self.stepper.state().count < 2 {
95 IndicatorValue::None
96 } else {
97 IndicatorValue::Single(0.0)
98 },
99 );
100 }
101 }
102
103 fn is_incremental(&self) -> bool {
104 true
105 }
106
107 fn values(&self) -> &IndicatorValues {
108 &self.values
109 }
110
111 fn colors(&self) -> Vec<Color32> {
112 vec![self.color]
113 }
114
115 fn set_colors(&mut self, colors: Vec<Color32>) {
116 if !colors.is_empty() {
117 self.color = colors[0];
118 }
119 }
120
121 fn is_overlay(&self) -> bool {
122 false
123 }
124
125 fn is_visible(&self) -> bool {
126 self.visible
127 }
128
129 fn set_visible(&mut self, visible: bool) {
130 self.visible = visible;
131 }
132
133 fn clone_box(&self) -> Box<dyn Indicator> {
134 Box::new(self.clone())
135 }
136
137 fn line_names(&self) -> Vec<String> {
138 vec!["WAD".to_string()]
139 }
140}