Skip to main content

egui_charts/drawings/domain/
vwap.rs

1//! Bands of the anchored VWAP drawing.
2
3use serde::{Deserialize, Serialize};
4
5/// A line above and a line below an anchored VWAP, a multiple of the volume-weighted standard
6/// deviation of the typical price away from it.
7#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)]
8#[serde(try_from = "VwapBandFields")]
9pub struct VwapBand {
10    /// Whether the band is drawn.
11    pub enabled: bool,
12    multiplier: f64,
13}
14
15/// Stored settings of a band, checked by [`VwapBand::new`] on load.
16#[derive(Deserialize)]
17struct VwapBandFields {
18    enabled: bool,
19    multiplier: f64,
20}
21
22impl TryFrom<VwapBandFields> for VwapBand {
23    type Error = &'static str;
24
25    fn try_from(fields: VwapBandFields) -> Result<Self, Self::Error> {
26        Self::new(fields.enabled, fields.multiplier)
27            .ok_or("anchored VWAP band multiplier out of bounds")
28    }
29}
30
31impl VwapBand {
32    /// A band `multiplier` standard deviations either side of the VWAP (above 0, at most 10);
33    /// `None` when out of bounds.
34    pub fn new(enabled: bool, multiplier: f64) -> Option<Self> {
35        (multiplier > 0.0 && multiplier <= 10.0).then_some(Self {
36            enabled,
37            multiplier,
38        })
39    }
40
41    /// Distance of the band's lines from the VWAP, in standard deviations.
42    pub fn multiplier(&self) -> f64 {
43        self.multiplier
44    }
45}
46
47/// The bands of an anchored VWAP drawing; a drawing without one uses the default.
48#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)]
49#[non_exhaustive]
50pub struct VwapConfig {
51    /// The bands, each drawn when enabled; the first one is also filled.
52    pub bands: [VwapBand; 3],
53}
54
55impl Default for VwapConfig {
56    /// The band one standard deviation away is on; the bands two and three away are off.
57    fn default() -> Self {
58        let band = |enabled, multiplier| VwapBand {
59            enabled,
60            multiplier,
61        };
62        Self {
63            bands: [band(true, 1.0), band(false, 2.0), band(false, 3.0)],
64        }
65    }
66}