pub struct Stepper<S> { /* private fields */ }Expand description
Runs a causal study one step per bar and keeps the state before the last bar, so a
last-bar update or an append resumes instead of recomputing the whole series.
calculate is run(data, 0, ..), so batch and streaming share one code path.
A custom study with a three-bar mean of squared closes, available without
the studies feature:
use egui_charts::model::Bar;
use egui_charts::studies::{helpers, Indicator, IndicatorValue, IndicatorValues, Stepper};
use std::collections::VecDeque;
#[derive(Clone, Default)]
struct MeanSquare {
driver: Stepper<VecDeque<f64>>,
values: IndicatorValues,
}
impl Indicator for MeanSquare {
fn name(&self) -> &str { "Mean square" }
fn calculate(&mut self, bars: &[Bar]) { self.update(bars, 0); }
fn update(&mut self, bars: &[Bar], from: usize) {
self.driver.run(bars, from, &mut self.values, |window, bar| {
window.push_back(bar.close * bar.close);
if window.len() > 3 { window.pop_front(); }
let mean = helpers::sma(window.make_contiguous(), 3);
IndicatorValue::Single(*mean.last().unwrap())
});
}
fn is_incremental(&self) -> bool { true }
fn values(&self) -> &IndicatorValues { &self.values }
fn colors(&self) -> Vec<ecolor::Color32> { vec![ecolor::Color32::YELLOW] }
fn set_colors(&mut self, _: Vec<ecolor::Color32>) {}
fn set_visible(&mut self, _: bool) {}
fn clone_box(&self) -> Box<dyn Indicator> { Box::new(self.clone()) }
}
let mut bars: Vec<_> = [1.0, 2.0, 4.0].into_iter().enumerate().map(|(i, p)| {
Bar::new(chrono::DateTime::from_timestamp(i as i64, 0).unwrap(), p, p, p, p, 1.0)
}).collect();
let mut study = MeanSquare::default();
study.calculate(&bars);
assert_eq!(study.values().value(0, 2), Some(7.0)); // (1 + 4 + 16) / 3
bars[2].close = 5.0;
study.update(&bars, 2);
let mut fresh = MeanSquare::default();
fresh.calculate(&bars);
assert_eq!(format!("{:?}", study.values()), format!("{:?}", fresh.values()));
bars.push(Bar::new(chrono::DateTime::from_timestamp(3, 0).unwrap(), 6.0, 6.0, 6.0, 6.0, 1.0));
study.update(&bars, 3);
fresh.calculate(&bars);
assert_eq!(format!("{:?}", study.values()), format!("{:?}", fresh.values()));Implementations§
Source§impl<S: Clone + Default> Stepper<S>
impl<S: Clone + Default> Stepper<S>
Sourcepub fn run(
&mut self,
data: &[Bar],
from: usize,
out: &mut IndicatorValues,
step: impl FnMut(&mut S, &Bar) -> IndicatorValue,
)
pub fn run( &mut self, data: &[Bar], from: usize, out: &mut IndicatorValues, step: impl FnMut(&mut S, &Bar) -> IndicatorValue, )
Recomputes out[from..], given that data[..from] is unchanged since the previous run.
Resumes when from >= len - 1 (last bar changed or bars appended), restarts from bar 0
otherwise (correction deep in history, prepended page, removed bars).
Trait Implementations§
Auto Trait Implementations§
impl<S> Freeze for Stepper<S>where
S: Freeze,
impl<S> RefUnwindSafe for Stepper<S>where
S: RefUnwindSafe,
impl<S> Send for Stepper<S>where
S: Send,
impl<S> Sync for Stepper<S>where
S: Sync,
impl<S> Unpin for Stepper<S>where
S: Unpin,
impl<S> UnsafeUnpin for Stepper<S>where
S: UnsafeUnpin,
impl<S> UnwindSafe for Stepper<S>where
S: UnwindSafe,
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Mutably borrows from an owned value. Read more
impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
Converts
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
Converts
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more