egui_charts/studies/builtin/
anchored_vwap_study.rs1use crate::model::Bar;
2use crate::studies::stepper::Stepper;
3use crate::studies::{Indicator, IndicatorValue, IndicatorValues};
4use egui::Color32;
5
6#[derive(Clone)]
10pub struct AnchoredVWAP {
11 anchor_bar: usize,
12 values: IndicatorValues,
13 stepper: Stepper<(usize, f64, f64)>,
14 colors: Vec<Color32>,
15 visible: bool,
16}
17
18impl AnchoredVWAP {
19 pub fn new(anchor_bar: usize) -> Self {
21 Self {
22 anchor_bar,
23 values: IndicatorValues::new(),
24 stepper: Stepper::default(),
25 colors: vec![Color32::from_rgb(30, 136, 229)],
26 visible: true,
27 }
28 }
29}
30
31impl Default for AnchoredVWAP {
32 fn default() -> Self {
33 Self::new(0)
34 }
35}
36
37impl Indicator for AnchoredVWAP {
38 fn source(&self) -> Option<crate::studies::StudySource> {
39 Some(crate::studies::StudySource::Price(
40 crate::model::PriceSource::HLC3,
41 ))
42 }
43
44 crate::studies::inputs::study_inputs!(self;
45 anchor_bar: length("Anchor bar", 0, usize::MAX)
46 ; {});
47
48 fn name(&self) -> &str {
49 "AVWAP"
50 }
51
52 fn desc(&self) -> &str {
53 "Anchored VWAP - Volume weighted average price from anchor bar"
54 }
55
56 fn calculate(&mut self, data: &[Bar]) {
57 self.update(data, 0);
58 }
59
60 fn update(&mut self, data: &[Bar], from: usize) {
61 self.stepper
62 .run(data, from, &mut self.values, |state, bar| {
63 let index = state.0;
64 state.0 += 1;
65 if index < self.anchor_bar
66 || ![bar.high, bar.low, bar.close, bar.volume]
67 .iter()
68 .all(|x| x.is_finite())
69 {
70 return IndicatorValue::None;
71 }
72 let price = bar.typical_price();
73 state.1 += price * bar.volume;
74 state.2 += bar.volume;
75 IndicatorValue::Single(if state.2 == 0.0 {
76 price
77 } else {
78 state.1 / state.2
79 })
80 });
81 }
82
83 fn is_incremental(&self) -> bool {
84 true
85 }
86
87 fn values(&self) -> &IndicatorValues {
88 &self.values
89 }
90
91 fn colors(&self) -> Vec<Color32> {
92 self.colors.clone()
93 }
94
95 fn set_colors(&mut self, colors: Vec<Color32>) {
96 if !colors.is_empty() {
97 self.colors = colors;
98 }
99 }
100
101 fn is_overlay(&self) -> bool {
102 true
103 }
104
105 fn is_visible(&self) -> bool {
106 self.visible
107 }
108
109 fn set_visible(&mut self, visible: bool) {
110 self.visible = visible;
111 }
112
113 fn clone_box(&self) -> Box<dyn Indicator> {
114 Box::new(self.clone())
115 }
116
117 fn line_names(&self) -> Vec<String> {
118 vec![format!("AVWAP({})", self.anchor_bar)]
119 }
120}