From 4b3227a15ff574f876d06f95de2532466efe5a95 Mon Sep 17 00:00:00 2001 From: kingchenc Date: Fri, 22 May 2026 16:41:43 +0200 Subject: [PATCH] E15: add a runnable doctest to every indicator type Only two doctests existed in wickra-core; none of the 25 indicator types carried a runnable rustdoc example. Add an "# Example" doctest to every public indicator type (all 26, including RollingVwap): construct the indicator and stream 80 inputs through update, asserting a value is produced. The candle-input indicators build valid OHLCV candles inline. cargo test --doc -p wickra-core now runs 28 doctests, all passing; fmt and clippy clean. --- crates/wickra-core/src/indicators/adx.rs | 16 ++++++++++ crates/wickra-core/src/indicators/aroon.rs | 16 ++++++++++ crates/wickra-core/src/indicators/atr.rs | 16 ++++++++++ .../src/indicators/awesome_oscillator.rs | 16 ++++++++++ .../wickra-core/src/indicators/bollinger.rs | 13 ++++++++ crates/wickra-core/src/indicators/cci.rs | 16 ++++++++++ crates/wickra-core/src/indicators/dema.rs | 13 ++++++++ crates/wickra-core/src/indicators/donchian.rs | 16 ++++++++++ crates/wickra-core/src/indicators/ema.rs | 13 ++++++++ crates/wickra-core/src/indicators/hma.rs | 13 ++++++++ crates/wickra-core/src/indicators/kama.rs | 13 ++++++++ crates/wickra-core/src/indicators/keltner.rs | 16 ++++++++++ crates/wickra-core/src/indicators/macd.rs | 13 ++++++++ crates/wickra-core/src/indicators/mfi.rs | 16 ++++++++++ crates/wickra-core/src/indicators/obv.rs | 16 ++++++++++ crates/wickra-core/src/indicators/psar.rs | 16 ++++++++++ crates/wickra-core/src/indicators/roc.rs | 13 ++++++++ crates/wickra-core/src/indicators/rsi.rs | 13 ++++++++ crates/wickra-core/src/indicators/sma.rs | 13 ++++++++ .../wickra-core/src/indicators/stochastic.rs | 16 ++++++++++ crates/wickra-core/src/indicators/tema.rs | 13 ++++++++ crates/wickra-core/src/indicators/trix.rs | 13 ++++++++ crates/wickra-core/src/indicators/vwap.rs | 32 +++++++++++++++++++ .../wickra-core/src/indicators/williams_r.rs | 16 ++++++++++ crates/wickra-core/src/indicators/wma.rs | 13 ++++++++ 25 files changed, 380 insertions(+) diff --git a/crates/wickra-core/src/indicators/adx.rs b/crates/wickra-core/src/indicators/adx.rs index c825b47d..5f15bdec 100644 --- a/crates/wickra-core/src/indicators/adx.rs +++ b/crates/wickra-core/src/indicators/adx.rs @@ -21,6 +21,22 @@ pub struct AdxOutput { /// movement / true range sums; the next `period` candles produce DX values that /// seed the ADX. The first complete `AdxOutput` is emitted after `2 * period` /// candles. +/// +/// # Example +/// +/// ``` +/// use wickra_core::{Candle, Indicator, Adx}; +/// +/// let mut indicator = Adx::new(5).unwrap(); +/// let mut last = None; +/// for i in 0..80 { +/// let base = 100.0 + f64::from(i); +/// let candle = +/// Candle::new(base, base + 2.0, base - 2.0, base + 1.0, 10.0, i64::from(i)).unwrap(); +/// last = indicator.update(candle); +/// } +/// assert!(last.is_some()); +/// ``` #[allow(clippy::struct_field_names)] // adx_value pairs with adx (the output line) — renaming hurts clarity #[derive(Debug, Clone)] pub struct Adx { diff --git a/crates/wickra-core/src/indicators/aroon.rs b/crates/wickra-core/src/indicators/aroon.rs index dd43c6e9..485fad20 100644 --- a/crates/wickra-core/src/indicators/aroon.rs +++ b/crates/wickra-core/src/indicators/aroon.rs @@ -17,6 +17,22 @@ pub struct AroonOutput { /// Aroon indicator: tracks how many bars since the highest high and lowest low /// inside a `period + 1`-bar window. Returned as a percentage. +/// +/// # Example +/// +/// ``` +/// use wickra_core::{Candle, Indicator, Aroon}; +/// +/// let mut indicator = Aroon::new(5).unwrap(); +/// let mut last = None; +/// for i in 0..80 { +/// let base = 100.0 + f64::from(i); +/// let candle = +/// Candle::new(base, base + 2.0, base - 2.0, base + 1.0, 10.0, i64::from(i)).unwrap(); +/// last = indicator.update(candle); +/// } +/// assert!(last.is_some()); +/// ``` #[derive(Debug, Clone)] pub struct Aroon { period: usize, diff --git a/crates/wickra-core/src/indicators/atr.rs b/crates/wickra-core/src/indicators/atr.rs index 621b0336..e9267f6c 100644 --- a/crates/wickra-core/src/indicators/atr.rs +++ b/crates/wickra-core/src/indicators/atr.rs @@ -9,6 +9,22 @@ use crate::traits::Indicator; /// The first emitted value, by convention, appears after `period` candles: the /// first `period − 1` true-range values seed the Wilder average alongside the /// `period`-th, then the smoothed update begins. +/// +/// # Example +/// +/// ``` +/// use wickra_core::{Candle, Indicator, Atr}; +/// +/// let mut indicator = Atr::new(5).unwrap(); +/// let mut last = None; +/// for i in 0..80 { +/// let base = 100.0 + f64::from(i); +/// let candle = +/// Candle::new(base, base + 2.0, base - 2.0, base + 1.0, 10.0, i64::from(i)).unwrap(); +/// last = indicator.update(candle); +/// } +/// assert!(last.is_some()); +/// ``` #[derive(Debug, Clone)] pub struct Atr { period: usize, diff --git a/crates/wickra-core/src/indicators/awesome_oscillator.rs b/crates/wickra-core/src/indicators/awesome_oscillator.rs index 5e19ac5e..0fce501f 100644 --- a/crates/wickra-core/src/indicators/awesome_oscillator.rs +++ b/crates/wickra-core/src/indicators/awesome_oscillator.rs @@ -6,6 +6,22 @@ use crate::ohlcv::Candle; use crate::traits::Indicator; /// Awesome Oscillator: `SMA(median_price, 5) - SMA(median_price, 34)`. +/// +/// # Example +/// +/// ``` +/// use wickra_core::{Candle, Indicator, AwesomeOscillator}; +/// +/// let mut indicator = AwesomeOscillator::new(3, 10).unwrap(); +/// let mut last = None; +/// for i in 0..80 { +/// let base = 100.0 + f64::from(i); +/// let candle = +/// Candle::new(base, base + 2.0, base - 2.0, base + 1.0, 10.0, i64::from(i)).unwrap(); +/// last = indicator.update(candle); +/// } +/// assert!(last.is_some()); +/// ``` #[derive(Debug, Clone)] pub struct AwesomeOscillator { fast: Sma, diff --git a/crates/wickra-core/src/indicators/bollinger.rs b/crates/wickra-core/src/indicators/bollinger.rs index d18c7c54..db3fbc7d 100644 --- a/crates/wickra-core/src/indicators/bollinger.rs +++ b/crates/wickra-core/src/indicators/bollinger.rs @@ -24,6 +24,19 @@ pub struct BollingerOutput { /// Standard parameters are `period = 20`, `multiplier = 2.0`. Bollinger's original /// publication uses population (not sample) standard deviation, which matches every /// reference implementation (TA-Lib, pandas-ta, etc.). +/// +/// # Example +/// +/// ``` +/// use wickra_core::{Indicator, BollingerBands}; +/// +/// let mut indicator = BollingerBands::new(5, 2.0).unwrap(); +/// let mut last = None; +/// for i in 0..80 { +/// last = indicator.update(100.0 + f64::from(i)); +/// } +/// assert!(last.is_some()); +/// ``` #[derive(Debug, Clone)] pub struct BollingerBands { period: usize, diff --git a/crates/wickra-core/src/indicators/cci.rs b/crates/wickra-core/src/indicators/cci.rs index 517c8cdc..adc70a51 100644 --- a/crates/wickra-core/src/indicators/cci.rs +++ b/crates/wickra-core/src/indicators/cci.rs @@ -10,6 +10,22 @@ use crate::traits::Indicator; /// /// `CCI = (TP - SMA(TP)) / (0.015 * mean absolute deviation of TP)`, where /// `TP = (high + low + close) / 3`. +/// +/// # Example +/// +/// ``` +/// use wickra_core::{Candle, Indicator, Cci}; +/// +/// let mut indicator = Cci::new(5).unwrap(); +/// let mut last = None; +/// for i in 0..80 { +/// let base = 100.0 + f64::from(i); +/// let candle = +/// Candle::new(base, base + 2.0, base - 2.0, base + 1.0, 10.0, i64::from(i)).unwrap(); +/// last = indicator.update(candle); +/// } +/// assert!(last.is_some()); +/// ``` #[derive(Debug, Clone)] pub struct Cci { period: usize, diff --git a/crates/wickra-core/src/indicators/dema.rs b/crates/wickra-core/src/indicators/dema.rs index ee72167c..c8c240cc 100644 --- a/crates/wickra-core/src/indicators/dema.rs +++ b/crates/wickra-core/src/indicators/dema.rs @@ -8,6 +8,19 @@ use crate::traits::Indicator; /// /// Designed by Patrick Mulloy to reduce the lag of a single EMA while keeping /// the smoothing benefit. +/// +/// # Example +/// +/// ``` +/// use wickra_core::{Indicator, Dema}; +/// +/// let mut indicator = Dema::new(3).unwrap(); +/// let mut last = None; +/// for i in 0..80 { +/// last = indicator.update(100.0 + f64::from(i)); +/// } +/// assert!(last.is_some()); +/// ``` #[derive(Debug, Clone)] pub struct Dema { ema1: Ema, diff --git a/crates/wickra-core/src/indicators/donchian.rs b/crates/wickra-core/src/indicators/donchian.rs index 8627a816..5e99252e 100644 --- a/crates/wickra-core/src/indicators/donchian.rs +++ b/crates/wickra-core/src/indicators/donchian.rs @@ -18,6 +18,22 @@ pub struct DonchianOutput { } /// Donchian Channels: rolling highest high / lowest low envelopes. +/// +/// # Example +/// +/// ``` +/// use wickra_core::{Candle, Indicator, Donchian}; +/// +/// let mut indicator = Donchian::new(5).unwrap(); +/// let mut last = None; +/// for i in 0..80 { +/// let base = 100.0 + f64::from(i); +/// let candle = +/// Candle::new(base, base + 2.0, base - 2.0, base + 1.0, 10.0, i64::from(i)).unwrap(); +/// last = indicator.update(candle); +/// } +/// assert!(last.is_some()); +/// ``` #[derive(Debug, Clone)] pub struct Donchian { period: usize, diff --git a/crates/wickra-core/src/indicators/ema.rs b/crates/wickra-core/src/indicators/ema.rs index f35ac639..ace731ee 100644 --- a/crates/wickra-core/src/indicators/ema.rs +++ b/crates/wickra-core/src/indicators/ema.rs @@ -8,6 +8,19 @@ use crate::traits::Indicator; /// The first value is seeded with the simple mean of the first `period` inputs /// (the classical TA-Lib convention). From then on each new input contributes /// `alpha * input + (1 - alpha) * previous`. +/// +/// # Example +/// +/// ``` +/// use wickra_core::{Indicator, Ema}; +/// +/// let mut indicator = Ema::new(3).unwrap(); +/// let mut last = None; +/// for i in 0..80 { +/// last = indicator.update(100.0 + f64::from(i)); +/// } +/// assert!(last.is_some()); +/// ``` #[derive(Debug, Clone)] pub struct Ema { period: usize, diff --git a/crates/wickra-core/src/indicators/hma.rs b/crates/wickra-core/src/indicators/hma.rs index dabdc6f4..3c1acbf3 100644 --- a/crates/wickra-core/src/indicators/hma.rs +++ b/crates/wickra-core/src/indicators/hma.rs @@ -8,6 +8,19 @@ use crate::traits::Indicator; /// /// Designed by Alan Hull as a lag-free moving average that is also responsive. /// The square root of the period is rounded to the nearest integer (minimum 1). +/// +/// # Example +/// +/// ``` +/// use wickra_core::{Indicator, Hma}; +/// +/// let mut indicator = Hma::new(9).unwrap(); +/// let mut last = None; +/// for i in 0..80 { +/// last = indicator.update(100.0 + f64::from(i)); +/// } +/// assert!(last.is_some()); +/// ``` #[derive(Debug, Clone)] pub struct Hma { period: usize, diff --git a/crates/wickra-core/src/indicators/kama.rs b/crates/wickra-core/src/indicators/kama.rs index 6aa40c66..a10740cd 100644 --- a/crates/wickra-core/src/indicators/kama.rs +++ b/crates/wickra-core/src/indicators/kama.rs @@ -11,6 +11,19 @@ use crate::traits::Indicator; /// get a fast smoothing constant, choppy markets get a slow one. Parameters are /// the efficiency-ratio lookback (`er_period`, default 10), the fast EMA period /// (`fast`, default 2) and the slow EMA period (`slow`, default 30). +/// +/// # Example +/// +/// ``` +/// use wickra_core::{Indicator, Kama}; +/// +/// let mut indicator = Kama::new(10, 2, 30).unwrap(); +/// let mut last = None; +/// for i in 0..80 { +/// last = indicator.update(100.0 + f64::from(i)); +/// } +/// assert!(last.is_some()); +/// ``` #[derive(Debug, Clone)] pub struct Kama { er_period: usize, diff --git a/crates/wickra-core/src/indicators/keltner.rs b/crates/wickra-core/src/indicators/keltner.rs index ba5b083f..ebf5e5ba 100644 --- a/crates/wickra-core/src/indicators/keltner.rs +++ b/crates/wickra-core/src/indicators/keltner.rs @@ -18,6 +18,22 @@ pub struct KeltnerOutput { } /// Keltner Channels: an EMA centerline with bands sized by ATR. +/// +/// # Example +/// +/// ``` +/// use wickra_core::{Candle, Indicator, Keltner}; +/// +/// let mut indicator = Keltner::new(5, 5, 2.0).unwrap(); +/// let mut last = None; +/// for i in 0..80 { +/// let base = 100.0 + f64::from(i); +/// let candle = +/// Candle::new(base, base + 2.0, base - 2.0, base + 1.0, 10.0, i64::from(i)).unwrap(); +/// last = indicator.update(candle); +/// } +/// assert!(last.is_some()); +/// ``` #[derive(Debug, Clone)] pub struct Keltner { ema: Ema, diff --git a/crates/wickra-core/src/indicators/macd.rs b/crates/wickra-core/src/indicators/macd.rs index 64d365b6..1d6e821f 100644 --- a/crates/wickra-core/src/indicators/macd.rs +++ b/crates/wickra-core/src/indicators/macd.rs @@ -21,6 +21,19 @@ pub struct MacdOutput { /// is seeded from the first `signal` raw MACD values, so the first full /// [`MacdOutput`] is emitted after `slow + signal − 1` inputs (assuming the /// slow EMA seeded by then). +/// +/// # Example +/// +/// ``` +/// use wickra_core::{Indicator, MacdIndicator}; +/// +/// let mut indicator = MacdIndicator::new(3, 6, 3).unwrap(); +/// let mut last = None; +/// for i in 0..80 { +/// last = indicator.update(100.0 + f64::from(i)); +/// } +/// assert!(last.is_some()); +/// ``` #[derive(Debug, Clone)] pub struct MacdIndicator { fast: Ema, diff --git a/crates/wickra-core/src/indicators/mfi.rs b/crates/wickra-core/src/indicators/mfi.rs index 092c83d7..0b70092d 100644 --- a/crates/wickra-core/src/indicators/mfi.rs +++ b/crates/wickra-core/src/indicators/mfi.rs @@ -11,6 +11,22 @@ use crate::traits::Indicator; /// `MFI = 100 - 100 / (1 + positive_money_flow / negative_money_flow)` where /// money flow is `typical_price * volume`, classified positive when TP increases /// and negative when it decreases. +/// +/// # Example +/// +/// ``` +/// use wickra_core::{Candle, Indicator, Mfi}; +/// +/// let mut indicator = Mfi::new(5).unwrap(); +/// let mut last = None; +/// for i in 0..80 { +/// let base = 100.0 + f64::from(i); +/// let candle = +/// Candle::new(base, base + 2.0, base - 2.0, base + 1.0, 10.0, i64::from(i)).unwrap(); +/// last = indicator.update(candle); +/// } +/// assert!(last.is_some()); +/// ``` #[derive(Debug, Clone)] pub struct Mfi { period: usize, diff --git a/crates/wickra-core/src/indicators/obv.rs b/crates/wickra-core/src/indicators/obv.rs index 96d722e9..5bc6af5a 100644 --- a/crates/wickra-core/src/indicators/obv.rs +++ b/crates/wickra-core/src/indicators/obv.rs @@ -8,6 +8,22 @@ use crate::traits::Indicator; /// Each candle adds `+volume`, `-volume`, or `0` depending on whether its close /// is above, below, or equal to the previous close. The first value (after the /// first candle) is conventionally `0`. +/// +/// # Example +/// +/// ``` +/// use wickra_core::{Candle, Indicator, Obv}; +/// +/// let mut indicator = Obv::new(); +/// let mut last = None; +/// for i in 0..80 { +/// let base = 100.0 + f64::from(i); +/// let candle = +/// Candle::new(base, base + 2.0, base - 2.0, base + 1.0, 10.0, i64::from(i)).unwrap(); +/// last = indicator.update(candle); +/// } +/// assert!(last.is_some()); +/// ``` #[derive(Debug, Clone, Default)] pub struct Obv { prev_close: Option, diff --git a/crates/wickra-core/src/indicators/psar.rs b/crates/wickra-core/src/indicators/psar.rs index 877d83d2..b549628c 100644 --- a/crates/wickra-core/src/indicators/psar.rs +++ b/crates/wickra-core/src/indicators/psar.rs @@ -16,6 +16,22 @@ enum Trend { /// Implementation follows Wilder's original recursion: each step computes a new /// SAR from the previous SAR, extreme point (EP) and acceleration factor (AF); /// the trend flips when price crosses the SAR. +/// +/// # Example +/// +/// ``` +/// use wickra_core::{Candle, Indicator, Psar}; +/// +/// let mut indicator = Psar::new(0.02, 0.02, 0.2).unwrap(); +/// let mut last = None; +/// for i in 0..80 { +/// let base = 100.0 + f64::from(i); +/// let candle = +/// Candle::new(base, base + 2.0, base - 2.0, base + 1.0, 10.0, i64::from(i)).unwrap(); +/// last = indicator.update(candle); +/// } +/// assert!(last.is_some()); +/// ``` #[derive(Debug, Clone)] pub struct Psar { af_start: f64, diff --git a/crates/wickra-core/src/indicators/roc.rs b/crates/wickra-core/src/indicators/roc.rs index 23d9d2da..f2143669 100644 --- a/crates/wickra-core/src/indicators/roc.rs +++ b/crates/wickra-core/src/indicators/roc.rs @@ -9,6 +9,19 @@ use crate::traits::Indicator; /// /// Non-finite inputs are ignored and leave the window untouched; the last /// computed value is returned instead, matching the SMA / EMA convention. +/// +/// # Example +/// +/// ``` +/// use wickra_core::{Indicator, Roc}; +/// +/// let mut indicator = Roc::new(3).unwrap(); +/// let mut last = None; +/// for i in 0..80 { +/// last = indicator.update(100.0 + f64::from(i)); +/// } +/// assert!(last.is_some()); +/// ``` #[derive(Debug, Clone)] pub struct Roc { period: usize, diff --git a/crates/wickra-core/src/indicators/rsi.rs b/crates/wickra-core/src/indicators/rsi.rs index 69612bbc..cabaeb08 100644 --- a/crates/wickra-core/src/indicators/rsi.rs +++ b/crates/wickra-core/src/indicators/rsi.rs @@ -9,6 +9,19 @@ use crate::traits::Indicator; /// is produced after `period + 1` inputs: the seed averages the first `period` /// gains and losses, and the first emitted RSI corresponds to the input at /// index `period`. +/// +/// # Example +/// +/// ``` +/// use wickra_core::{Indicator, Rsi}; +/// +/// let mut indicator = Rsi::new(3).unwrap(); +/// let mut last = None; +/// for i in 0..80 { +/// last = indicator.update(100.0 + f64::from(i)); +/// } +/// assert!(last.is_some()); +/// ``` #[derive(Debug, Clone)] pub struct Rsi { period: usize, diff --git a/crates/wickra-core/src/indicators/sma.rs b/crates/wickra-core/src/indicators/sma.rs index b58f3891..cf75a1d3 100644 --- a/crates/wickra-core/src/indicators/sma.rs +++ b/crates/wickra-core/src/indicators/sma.rs @@ -9,6 +9,19 @@ use crate::traits::Indicator; /// /// Maintains a rolling sum so each update is O(1). Output equals /// `sum(last `period` prices) / period` once the window is full; `None` before. +/// +/// # Example +/// +/// ``` +/// use wickra_core::{Indicator, Sma}; +/// +/// let mut indicator = Sma::new(3).unwrap(); +/// let mut last = None; +/// for i in 0..80 { +/// last = indicator.update(100.0 + f64::from(i)); +/// } +/// assert!(last.is_some()); +/// ``` #[derive(Debug, Clone)] pub struct Sma { period: usize, diff --git a/crates/wickra-core/src/indicators/stochastic.rs b/crates/wickra-core/src/indicators/stochastic.rs index 48e98cb1..9df886ba 100644 --- a/crates/wickra-core/src/indicators/stochastic.rs +++ b/crates/wickra-core/src/indicators/stochastic.rs @@ -20,6 +20,22 @@ pub struct StochasticOutput { /// /// Maintains rolling highest-high and lowest-low over the lookback period via a /// monotonic deque, giving O(1) amortized updates. %D is an SMA of the %K series. +/// +/// # Example +/// +/// ``` +/// use wickra_core::{Candle, Indicator, Stochastic}; +/// +/// let mut indicator = Stochastic::new(5, 3).unwrap(); +/// let mut last = None; +/// for i in 0..80 { +/// let base = 100.0 + f64::from(i); +/// let candle = +/// Candle::new(base, base + 2.0, base - 2.0, base + 1.0, 10.0, i64::from(i)).unwrap(); +/// last = indicator.update(candle); +/// } +/// assert!(last.is_some()); +/// ``` #[derive(Debug, Clone)] pub struct Stochastic { k_period: usize, diff --git a/crates/wickra-core/src/indicators/tema.rs b/crates/wickra-core/src/indicators/tema.rs index c4d78fc5..ef872f40 100644 --- a/crates/wickra-core/src/indicators/tema.rs +++ b/crates/wickra-core/src/indicators/tema.rs @@ -8,6 +8,19 @@ use crate::traits::Indicator; /// where `EMA2 = EMA(EMA1)` and `EMA3 = EMA(EMA2)`. /// /// Reduces lag further than DEMA at the cost of more responsiveness to noise. +/// +/// # Example +/// +/// ``` +/// use wickra_core::{Indicator, Tema}; +/// +/// let mut indicator = Tema::new(3).unwrap(); +/// let mut last = None; +/// for i in 0..80 { +/// last = indicator.update(100.0 + f64::from(i)); +/// } +/// assert!(last.is_some()); +/// ``` #[derive(Debug, Clone)] pub struct Tema { ema1: Ema, diff --git a/crates/wickra-core/src/indicators/trix.rs b/crates/wickra-core/src/indicators/trix.rs index c1afcb2f..4eb02a73 100644 --- a/crates/wickra-core/src/indicators/trix.rs +++ b/crates/wickra-core/src/indicators/trix.rs @@ -8,6 +8,19 @@ use crate::traits::Indicator; /// /// `TRIX = 100 * (TR_t - TR_{t-1}) / TR_{t-1}` where /// `TR_t = EMA(EMA(EMA(price)))`. +/// +/// # Example +/// +/// ``` +/// use wickra_core::{Indicator, Trix}; +/// +/// let mut indicator = Trix::new(3).unwrap(); +/// let mut last = None; +/// for i in 0..80 { +/// last = indicator.update(100.0 + f64::from(i)); +/// } +/// assert!(last.is_some()); +/// ``` #[derive(Debug, Clone)] pub struct Trix { ema1: Ema, diff --git a/crates/wickra-core/src/indicators/vwap.rs b/crates/wickra-core/src/indicators/vwap.rs index 23b95b2e..1d54982f 100644 --- a/crates/wickra-core/src/indicators/vwap.rs +++ b/crates/wickra-core/src/indicators/vwap.rs @@ -12,6 +12,22 @@ use crate::traits::Indicator; /// Cumulative session VWAP. Call [`Indicator::reset`] at the start of each /// session (e.g. trading-day boundary) to restart the accumulation. +/// +/// # Example +/// +/// ``` +/// use wickra_core::{Candle, Indicator, Vwap}; +/// +/// let mut indicator = Vwap::new(); +/// let mut last = None; +/// for i in 0..80 { +/// let base = 100.0 + f64::from(i); +/// let candle = +/// Candle::new(base, base + 2.0, base - 2.0, base + 1.0, 10.0, i64::from(i)).unwrap(); +/// last = indicator.update(candle); +/// } +/// assert!(last.is_some()); +/// ``` #[derive(Debug, Clone, Default)] pub struct Vwap { sum_pv: f64, @@ -75,6 +91,22 @@ impl Indicator for Vwap { /// Rolling-window VWAP: a finite-memory variant for bots that don't want /// unbounded accumulation. +/// +/// # Example +/// +/// ``` +/// use wickra_core::{Candle, Indicator, RollingVwap}; +/// +/// let mut indicator = RollingVwap::new(5).unwrap(); +/// let mut last = None; +/// for i in 0..80 { +/// let base = 100.0 + f64::from(i); +/// let candle = +/// Candle::new(base, base + 2.0, base - 2.0, base + 1.0, 10.0, i64::from(i)).unwrap(); +/// last = indicator.update(candle); +/// } +/// assert!(last.is_some()); +/// ``` #[derive(Debug, Clone)] pub struct RollingVwap { period: usize, diff --git a/crates/wickra-core/src/indicators/williams_r.rs b/crates/wickra-core/src/indicators/williams_r.rs index 48c59e5a..63db48af 100644 --- a/crates/wickra-core/src/indicators/williams_r.rs +++ b/crates/wickra-core/src/indicators/williams_r.rs @@ -10,6 +10,22 @@ use crate::traits::Indicator; /// /// Values lie in `[-100, 0]` and approximate the mirror image of the fast /// Stochastic %K. +/// +/// # Example +/// +/// ``` +/// use wickra_core::{Candle, Indicator, WilliamsR}; +/// +/// let mut indicator = WilliamsR::new(5).unwrap(); +/// let mut last = None; +/// for i in 0..80 { +/// let base = 100.0 + f64::from(i); +/// let candle = +/// Candle::new(base, base + 2.0, base - 2.0, base + 1.0, 10.0, i64::from(i)).unwrap(); +/// last = indicator.update(candle); +/// } +/// assert!(last.is_some()); +/// ``` #[derive(Debug, Clone)] pub struct WilliamsR { period: usize, diff --git a/crates/wickra-core/src/indicators/wma.rs b/crates/wickra-core/src/indicators/wma.rs index d66df301..1a696f0e 100644 --- a/crates/wickra-core/src/indicators/wma.rs +++ b/crates/wickra-core/src/indicators/wma.rs @@ -9,6 +9,19 @@ use crate::traits::Indicator; /// /// Output is `sum(weight_i * price_i) / sum(weights)`. Maintained incrementally in /// O(1) by keeping the rolling sum of values and the rolling weighted sum. +/// +/// # Example +/// +/// ``` +/// use wickra_core::{Indicator, Wma}; +/// +/// let mut indicator = Wma::new(3).unwrap(); +/// let mut last = None; +/// for i in 0..80 { +/// last = indicator.update(100.0 + f64::from(i)); +/// } +/// assert!(last.is_some()); +/// ``` #[derive(Debug, Clone)] pub struct Wma { period: usize,