egui_charts/studies/builtin/
average_price.rs1use super::over_finite_bars;
5use crate::model::Bar;
6use crate::studies::palette;
7use crate::studies::stepper::{update_window, usable_behind};
8use crate::studies::{Indicator, IndicatorValue, IndicatorValues};
9use egui::Color32;
10
11#[derive(Clone)]
13pub struct OHLC4 {
14 values: IndicatorValues,
15 color: Color32,
16 visible: bool,
17}
18
19impl OHLC4 {
20 pub fn new() -> Self {
22 Self {
23 values: IndicatorValues::new(),
24 color: palette::LIGHT_BLUE,
25 visible: true,
26 }
27 }
28
29 pub fn with_color(mut self, color: Color32) -> Self {
31 self.color = color;
32 self
33 }
34}
35
36impl Default for OHLC4 {
37 fn default() -> Self {
38 Self::new()
39 }
40}
41
42impl Indicator for OHLC4 {
43 fn name(&self) -> &str {
44 "OHLC4"
45 }
46
47 fn desc(&self) -> &str {
48 "OHLC4 - (Open + High + Low + Close) / 4"
49 }
50
51 fn calculate(&mut self, data: &[Bar]) {
52 self.update(data, 0);
53 }
54
55 fn update(&mut self, data: &[Bar], from: usize) {
56 let from = from.min(self.values.len()).min(data.len());
57 self.values.truncate(from);
58 for bar in &data[from..] {
59 let ohlc4 = (bar.open + bar.high + bar.low + bar.close) / 4.0;
60 self.values.push(IndicatorValue::Single(ohlc4));
61 }
62 }
63
64 fn is_incremental(&self) -> bool {
65 true
66 }
67
68 fn values(&self) -> &IndicatorValues {
69 &self.values
70 }
71
72 fn colors(&self) -> Vec<Color32> {
73 vec![self.color]
74 }
75
76 fn set_colors(&mut self, colors: Vec<Color32>) {
77 if !colors.is_empty() {
78 self.color = colors[0];
79 }
80 }
81
82 fn is_overlay(&self) -> bool {
83 true
84 }
85
86 fn is_visible(&self) -> bool {
87 self.visible
88 }
89
90 fn set_visible(&mut self, visible: bool) {
91 self.visible = visible;
92 }
93
94 fn clone_box(&self) -> Box<dyn Indicator> {
95 Box::new(self.clone())
96 }
97
98 fn line_names(&self) -> Vec<String> {
99 vec!["OHLC4".to_string()]
100 }
101}
102
103#[derive(Clone)]
107pub struct HLC3 {
108 values: IndicatorValues,
109 color: Color32,
110 visible: bool,
111}
112
113impl HLC3 {
114 pub fn new() -> Self {
116 Self {
117 values: IndicatorValues::new(),
118 color: palette::ORANGE,
119 visible: true,
120 }
121 }
122
123 pub fn with_color(mut self, color: Color32) -> Self {
125 self.color = color;
126 self
127 }
128}
129
130impl Default for HLC3 {
131 fn default() -> Self {
132 Self::new()
133 }
134}
135
136impl Indicator for HLC3 {
137 fn name(&self) -> &str {
138 "HLC3"
139 }
140
141 fn desc(&self) -> &str {
142 "HLC3 - (High + Low + Close) / 3"
143 }
144
145 fn calculate(&mut self, data: &[Bar]) {
146 self.update(data, 0);
147 }
148
149 fn update(&mut self, data: &[Bar], from: usize) {
150 let from = from.min(self.values.len()).min(data.len());
151 self.values.truncate(from);
152 for bar in &data[from..] {
153 let hlc3 = (bar.high + bar.low + bar.close) / 3.0;
154 self.values.push(IndicatorValue::Single(hlc3));
155 }
156 }
157
158 fn is_incremental(&self) -> bool {
159 true
160 }
161
162 fn values(&self) -> &IndicatorValues {
163 &self.values
164 }
165
166 fn colors(&self) -> Vec<Color32> {
167 vec![self.color]
168 }
169
170 fn set_colors(&mut self, colors: Vec<Color32>) {
171 if !colors.is_empty() {
172 self.color = colors[0];
173 }
174 }
175
176 fn is_overlay(&self) -> bool {
177 true
178 }
179
180 fn is_visible(&self) -> bool {
181 self.visible
182 }
183
184 fn set_visible(&mut self, visible: bool) {
185 self.visible = visible;
186 }
187
188 fn clone_box(&self) -> Box<dyn Indicator> {
189 Box::new(self.clone())
190 }
191
192 fn line_names(&self) -> Vec<String> {
193 vec!["HLC3".to_string()]
194 }
195}
196
197#[derive(Clone)]
201pub struct HL2 {
202 values: IndicatorValues,
203 color: Color32,
204 visible: bool,
205}
206
207impl HL2 {
208 pub fn new() -> Self {
210 Self {
211 values: IndicatorValues::new(),
212 color: palette::ORANGE,
213 visible: true,
214 }
215 }
216
217 pub fn with_color(mut self, color: Color32) -> Self {
219 self.color = color;
220 self
221 }
222}
223
224impl Default for HL2 {
225 fn default() -> Self {
226 Self::new()
227 }
228}
229
230impl Indicator for HL2 {
231 fn name(&self) -> &str {
232 "HL2"
233 }
234
235 fn desc(&self) -> &str {
236 "HL2 - (High + Low) / 2 - Midpoint price"
237 }
238
239 fn calculate(&mut self, data: &[Bar]) {
240 self.update(data, 0);
241 }
242
243 fn update(&mut self, data: &[Bar], from: usize) {
244 let from = from.min(self.values.len()).min(data.len());
245 self.values.truncate(from);
246 for bar in &data[from..] {
247 let hl2 = (bar.high + bar.low) / 2.0;
248 self.values.push(IndicatorValue::Single(hl2));
249 }
250 }
251
252 fn is_incremental(&self) -> bool {
253 true
254 }
255
256 fn values(&self) -> &IndicatorValues {
257 &self.values
258 }
259
260 fn colors(&self) -> Vec<Color32> {
261 vec![self.color]
262 }
263
264 fn set_colors(&mut self, colors: Vec<Color32>) {
265 if !colors.is_empty() {
266 self.color = colors[0];
267 }
268 }
269
270 fn is_overlay(&self) -> bool {
271 true
272 }
273
274 fn is_visible(&self) -> bool {
275 self.visible
276 }
277
278 fn set_visible(&mut self, visible: bool) {
279 self.visible = visible;
280 }
281
282 fn clone_box(&self) -> Box<dyn Indicator> {
283 Box::new(self.clone())
284 }
285
286 fn line_names(&self) -> Vec<String> {
287 vec!["HL2".to_string()]
288 }
289}
290
291#[derive(Clone)]
293pub struct TrueRange {
294 values: IndicatorValues,
295 color: Color32,
296 visible: bool,
297}
298
299impl TrueRange {
300 pub fn new() -> Self {
302 Self {
303 values: IndicatorValues::new(),
304 color: palette::RED,
305 visible: true,
306 }
307 }
308
309 pub fn with_color(mut self, color: Color32) -> Self {
311 self.color = color;
312 self
313 }
314}
315
316impl Default for TrueRange {
317 fn default() -> Self {
318 Self::new()
319 }
320}
321
322impl TrueRange {
323 fn compute(&self, data: &[Bar]) -> IndicatorValues {
325 let mut values = IndicatorValues::new();
326 if data.is_empty() {
327 return values;
328 }
329
330 values.push(IndicatorValue::Single(data[0].high - data[0].low));
332
333 for i in 1..data.len() {
334 let prev_close = data[i - 1].close;
335 let hl = data[i].high - data[i].low;
336 let hc = (data[i].high - prev_close).abs();
337 let lc = (data[i].low - prev_close).abs();
338 let tr = hl.max(hc).max(lc);
339 values.push(IndicatorValue::Single(tr));
340 }
341
342 values
343 }
344}
345
346impl Indicator for TrueRange {
347 fn value_format(&self) -> crate::scales::StudyFormat {
348 crate::scales::StudyFormat::Price
349 }
350
351 fn name(&self) -> &str {
352 "TR"
353 }
354
355 fn desc(&self) -> &str {
356 "True Range - Max of H-L, |H-Cp|, |L-Cp|"
357 }
358
359 fn calculate(&mut self, data: &[Bar]) {
360 self.update(data, 0);
361 }
362
363 fn update(&mut self, data: &[Bar], from: usize) {
364 let mut values = std::mem::take(&mut self.values);
365 update_window(
366 &mut values,
367 data,
368 from,
369 usable_behind(1, |b| {
370 b.high.is_finite() && b.low.is_finite() && b.close.is_finite()
371 }),
372 |data| {
373 over_finite_bars(
374 data,
375 |b| b.high.is_finite() && b.low.is_finite() && b.close.is_finite(),
376 |data| self.compute(data),
377 )
378 },
379 );
380 self.values = values;
381 }
382
383 fn is_incremental(&self) -> bool {
384 true
385 }
386
387 fn values(&self) -> &IndicatorValues {
388 &self.values
389 }
390
391 fn colors(&self) -> Vec<Color32> {
392 vec![self.color]
393 }
394
395 fn set_colors(&mut self, colors: Vec<Color32>) {
396 if !colors.is_empty() {
397 self.color = colors[0];
398 }
399 }
400
401 fn is_overlay(&self) -> bool {
402 false
403 }
404
405 fn is_visible(&self) -> bool {
406 self.visible
407 }
408
409 fn set_visible(&mut self, visible: bool) {
410 self.visible = visible;
411 }
412
413 fn clone_box(&self) -> Box<dyn Indicator> {
414 Box::new(self.clone())
415 }
416
417 fn line_names(&self) -> Vec<String> {
418 vec!["TR".to_string()]
419 }
420}