use crate::model::{Bar, Provenance, SeriesIdentity};
#[derive(Debug, Clone, PartialEq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct HeikinAshiBar {
pub timestamp: i64,
pub open: f64,
pub high: f64,
pub low: f64,
pub close: f64,
pub volume: f64,
pub source: Bar,
}
impl HeikinAshiBar {
pub fn to_bar(&self) -> Bar {
Bar::new(
self.timestamp,
self.open,
self.high,
self.low,
self.close,
self.volume,
)
}
pub fn synthetic_identity(base: &SeriesIdentity) -> SeriesIdentity {
let mut identity = base.clone();
identity.provenance = Provenance::Synthetic;
identity
}
}
#[derive(Debug, Clone, Default)]
pub struct HeikinAshi {
prev: Option<(f64, f64)>,
}
impl HeikinAshi {
pub fn new() -> Self {
Self::default()
}
pub fn update(&mut self, bar: &Bar) -> HeikinAshiBar {
let close = (bar.open + bar.high + bar.low + bar.close) / 4.0;
let open = match self.prev {
None => (bar.open + bar.close) / 2.0,
Some((prev_open, prev_close)) => (prev_open + prev_close) / 2.0,
};
self.prev = Some((open, close));
HeikinAshiBar {
timestamp: bar.timestamp,
open,
high: bar.high.max(open).max(close),
low: bar.low.min(open).min(close),
close,
volume: bar.volume,
source: bar.clone(),
}
}
pub fn reset(&mut self) {
self.prev = None;
}
}