egui_charts/studies/builtin/
net_volume.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)]
10pub struct NetVolume {
11 values: IndicatorValues,
12 stepper: Stepper<Option<f64>>,
13 colors: Vec<Color32>,
14 visible: bool,
15}
16
17impl NetVolume {
18 pub fn new() -> Self {
20 Self {
21 values: IndicatorValues::new(),
22 stepper: Stepper::default(),
23 colors: vec![palette::BLUE], visible: true,
25 }
26 }
27}
28
29impl Default for NetVolume {
30 fn default() -> Self {
31 Self::new()
32 }
33}
34
35impl Indicator for NetVolume {
36 fn source(&self) -> Option<crate::studies::StudySource> {
37 Some(crate::studies::StudySource::Price(
38 crate::model::PriceSource::Close,
39 ))
40 }
41
42 fn plot_style(&self, _line: usize) -> crate::studies::PlotStyle {
43 crate::studies::PlotStyle {
44 color: self.colors[0],
45 width: 1.0,
46 pattern: crate::model::LineStyle::Solid,
47 plot_type: crate::studies::PlotType::Line,
48 visible: true,
49 }
50 }
51
52 fn value_format(&self) -> crate::scales::StudyFormat {
53 crate::scales::StudyFormat::Volume
54 }
55
56 fn name(&self) -> &str {
57 "Net Volume"
58 }
59
60 fn desc(&self) -> &str {
61 "Net Volume - Volume signed by the change from the previous close"
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, |previous, bar| {
71 if !bar.close.is_finite() || !bar.volume.is_finite() {
72 return IndicatorValue::None;
73 }
74 let value = match *previous {
75 None => IndicatorValue::None,
76 Some(close) => IndicatorValue::Single(if bar.close > close {
77 bar.volume
78 } else if bar.close < close {
79 -bar.volume
80 } else {
81 0.0
82 }),
83 };
84 *previous = Some(bar.close);
85 value
86 });
87 }
88
89 fn is_incremental(&self) -> bool {
90 true
91 }
92
93 fn values(&self) -> &IndicatorValues {
94 &self.values
95 }
96
97 fn colors(&self) -> Vec<Color32> {
98 self.colors.clone()
99 }
100
101 fn set_colors(&mut self, colors: Vec<Color32>) {
102 if !colors.is_empty() {
103 self.colors = colors;
104 }
105 }
106
107 fn is_overlay(&self) -> bool {
108 false
109 }
110
111 fn is_visible(&self) -> bool {
112 self.visible
113 }
114
115 fn set_visible(&mut self, visible: bool) {
116 self.visible = visible;
117 }
118
119 fn clone_box(&self) -> Box<dyn Indicator> {
120 Box::new(self.clone())
121 }
122
123 fn line_names(&self) -> Vec<String> {
124 vec!["Net Volume".to_string()]
125 }
126}