quant_indicators/indicator.rs
1//! Core indicator trait definitions.
2//!
3//! These are domain abstractions: pure computation contracts with no I/O.
4//! Concrete implementations live alongside these traits in `quant-indicators`.
5
6use quant_primitives::Candle;
7
8use crate::{IndicatorError, Series};
9
10/// A technical indicator that computes a continuous numeric time series.
11///
12/// All indicators are pure functions - no I/O, no async, no side effects.
13/// This makes them easy to test, compose, and potentially compile to WASM.
14///
15/// For discrete classification outputs (e.g., `VolumeAnomaly`), use
16/// [`ClassificationIndicator<T>`] instead.
17pub trait Indicator: Send + Sync {
18 /// The name of this indicator (e.g., "SMA(20)").
19 #[must_use]
20 fn name(&self) -> &str;
21
22 /// Minimum number of candles required before output is valid.
23 #[must_use]
24 fn warmup_period(&self) -> usize;
25
26 /// Compute the indicator values from candle data.
27 fn compute(&self, candles: &[Candle]) -> Result<Series, IndicatorError>;
28}
29
30/// A classification indicator that maps each candle to a typed domain outcome.
31///
32/// Unlike [`Indicator`] (which produces a continuous `Decimal` series),
33/// `ClassificationIndicator<T>` produces rich domain types (enums, structs).
34///
35/// Returns `None` for candles within the warmup window, and `Some(T)` once
36/// sufficient history is available.
37pub trait ClassificationIndicator<T>: Send + Sync {
38 /// Number of prior candles consumed before first `Some` result is emitted.
39 #[must_use]
40 fn lookback(&self) -> usize;
41
42 /// Classify each candle. Returns one `Option<T>` per input candle.
43 fn compute(&self, candles: &[Candle]) -> Result<Vec<Option<T>>, IndicatorError>;
44}