docs(core): add runnable rustdoc examples to 23 indicators (#293)

The fib_* / auto_fib / golden_pocket Fibonacci indicators, the harami_cross /
tristar / tower_top_bottom candlestick patterns and the td_* DeMark family
lacked the `/// # Example` runnable doctest that ARCHITECTURE.md requires of
every indicator. Add a minimal construct-and-feed example to each. The
swing-tracker helper `pattern_swing` is not an `Indicator` and is left out.
All 23 pass `cargo test --doc` (487 doctests green).
This commit is contained in:
kingchenc
2026-06-14 00:09:07 +02:00
committed by GitHub
parent db5bd5e028
commit 8003572d92
23 changed files with 345 additions and 0 deletions
@@ -40,6 +40,21 @@ pub struct AutoFibOutput {
/// have confirmed.
///
/// See `crates/wickra-core/src/indicators/auto_fib.rs`.
/// # Example
///
/// ```
/// use wickra_core::{AutoFib, Candle, Indicator};
///
/// let mut indicator = AutoFib::new();
/// // `None` during warmup, then `Some(_)` once enough bars are seen.
/// let mut out = None;
/// for i in 0..40i64 {
/// let p = 100.0 + (i as f64 * 0.4).sin() * 5.0;
/// let candle = Candle::new(p, p + 1.5, p - 1.5, p + 0.3, 1_000.0, i).unwrap();
/// out = indicator.update(candle);
/// }
/// let _ = out;
/// ```
#[derive(Debug, Clone)]
pub struct AutoFib {
swing: SwingTracker,
@@ -33,6 +33,21 @@ pub struct FibConfluenceOutput {
/// legs (three pivots) exist.
///
/// See `crates/wickra-core/src/indicators/fib_confluence.rs`.
/// # Example
///
/// ```
/// use wickra_core::{FibConfluence, Candle, Indicator};
///
/// let mut indicator = FibConfluence::new();
/// // `None` during warmup, then `Some(_)` once enough bars are seen.
/// let mut out = None;
/// for i in 0..40i64 {
/// let p = 100.0 + (i as f64 * 0.4).sin() * 5.0;
/// let candle = Candle::new(p, p + 1.5, p - 1.5, p + 0.3, 1_000.0, i).unwrap();
/// out = indicator.update(candle);
/// }
/// let _ = out;
/// ```
#[derive(Debug, Clone)]
pub struct FibConfluence {
swing: SwingTracker,
@@ -37,6 +37,21 @@ pub struct FibExtensionOutput {
/// leg is complete.
///
/// See `crates/wickra-core/src/indicators/fib_extension.rs`.
/// # Example
///
/// ```
/// use wickra_core::{FibExtension, Candle, Indicator};
///
/// let mut indicator = FibExtension::new();
/// // `None` during warmup, then `Some(_)` once enough bars are seen.
/// let mut out = None;
/// for i in 0..40i64 {
/// let p = 100.0 + (i as f64 * 0.4).sin() * 5.0;
/// let candle = Candle::new(p, p + 1.5, p - 1.5, p + 0.3, 1_000.0, i).unwrap();
/// out = indicator.update(candle);
/// }
/// let _ = out;
/// ```
#[derive(Debug, Clone)]
pub struct FibExtension {
swing: SwingTracker,
@@ -31,6 +31,21 @@ pub struct FibProjectionOutput {
/// pivots have confirmed.
///
/// See `crates/wickra-core/src/indicators/fib_projection.rs`.
/// # Example
///
/// ```
/// use wickra_core::{FibProjection, Candle, Indicator};
///
/// let mut indicator = FibProjection::new();
/// // `None` during warmup, then `Some(_)` once enough bars are seen.
/// let mut out = None;
/// for i in 0..40i64 {
/// let p = 100.0 + (i as f64 * 0.4).sin() * 5.0;
/// let candle = Candle::new(p, p + 1.5, p - 1.5, p + 0.3, 1_000.0, i).unwrap();
/// out = indicator.update(candle);
/// }
/// let _ = out;
/// ```
#[derive(Debug, Clone)]
pub struct FibProjection {
swing: SwingTracker,
@@ -46,6 +46,21 @@ pub struct FibRetracementOutput {
/// chart- and harmonic-pattern detectors, so construction is infallible.
///
/// See `crates/wickra-core/src/indicators/fib_retracement.rs`.
/// # Example
///
/// ```
/// use wickra_core::{FibRetracement, Candle, Indicator};
///
/// let mut indicator = FibRetracement::new();
/// // `None` during warmup, then `Some(_)` once enough bars are seen.
/// let mut out = None;
/// for i in 0..40i64 {
/// let p = 100.0 + (i as f64 * 0.4).sin() * 5.0;
/// let candle = Candle::new(p, p + 1.5, p - 1.5, p + 0.3, 1_000.0, i).unwrap();
/// out = indicator.update(candle);
/// }
/// let _ = out;
/// ```
#[derive(Debug, Clone)]
pub struct FibRetracement {
swing: SwingTracker,
@@ -28,6 +28,21 @@ pub struct FibTimeZonesOutput {
/// pivot has confirmed.
///
/// See `crates/wickra-core/src/indicators/fib_time_zones.rs`.
/// # Example
///
/// ```
/// use wickra_core::{FibTimeZones, Candle, Indicator};
///
/// let mut indicator = FibTimeZones::new();
/// // `None` during warmup, then `Some(_)` once enough bars are seen.
/// let mut out = None;
/// for i in 0..40i64 {
/// let p = 100.0 + (i as f64 * 0.4).sin() * 5.0;
/// let candle = Candle::new(p, p + 1.5, p - 1.5, p + 0.3, 1_000.0, i).unwrap();
/// out = indicator.update(candle);
/// }
/// let _ = out;
/// ```
#[derive(Debug, Clone)]
pub struct FibTimeZones {
swing: SwingTracker,
@@ -32,6 +32,21 @@ pub struct GoldenPocketOutput {
/// leg is complete.
///
/// See `crates/wickra-core/src/indicators/golden_pocket.rs`.
/// # Example
///
/// ```
/// use wickra_core::{GoldenPocket, Candle, Indicator};
///
/// let mut indicator = GoldenPocket::new();
/// // `None` during warmup, then `Some(_)` once enough bars are seen.
/// let mut out = None;
/// for i in 0..40i64 {
/// let p = 100.0 + (i as f64 * 0.4).sin() * 5.0;
/// let candle = Candle::new(p, p + 1.5, p - 1.5, p + 0.3, 1_000.0, i).unwrap();
/// out = indicator.update(candle);
/// }
/// let _ = out;
/// ```
#[derive(Debug, Clone)]
pub struct GoldenPocket {
swing: SwingTracker,
@@ -26,6 +26,21 @@ fn is_doji(candle: Candle) -> bool {
}
/// Harami Cross — large-body-then-contained-doji reversal detector.
/// # Example
///
/// ```
/// use wickra_core::{HaramiCross, Candle, Indicator};
///
/// let mut indicator = HaramiCross::new();
/// // `None` during warmup, then `Some(_)` once enough bars are seen.
/// let mut out = None;
/// for i in 0..40i64 {
/// let p = 100.0 + (i as f64 * 0.4).sin() * 5.0;
/// let candle = Candle::new(p, p + 1.5, p - 1.5, p + 0.3, 1_000.0, i).unwrap();
/// out = indicator.update(candle);
/// }
/// let _ = out;
/// ```
#[derive(Debug, Clone, Default)]
pub struct HaramiCross {
prev: Option<Candle>,
@@ -18,6 +18,21 @@ use crate::ohlcv::Candle;
use crate::traits::Indicator;
/// TD Camouflage — 1-bar hidden-strength/weakness reversal detector.
/// # Example
///
/// ```
/// use wickra_core::{TdCamouflage, Candle, Indicator};
///
/// let mut indicator = TdCamouflage::new();
/// // `None` during warmup, then `Some(_)` once enough bars are seen.
/// let mut out = None;
/// for i in 0..40i64 {
/// let p = 100.0 + (i as f64 * 0.4).sin() * 5.0;
/// let candle = Candle::new(p, p + 1.5, p - 1.5, p + 0.3, 1_000.0, i).unwrap();
/// out = indicator.update(candle);
/// }
/// let _ = out;
/// ```
#[derive(Debug, Clone, Default)]
pub struct TdCamouflage {
prev: Option<Candle>,
@@ -19,6 +19,21 @@ use crate::ohlcv::Candle;
use crate::traits::Indicator;
/// TD Clop — 2-bar open/close engulfing reversal detector.
/// # Example
///
/// ```
/// use wickra_core::{TdClop, Candle, Indicator};
///
/// let mut indicator = TdClop::new();
/// // `None` during warmup, then `Some(_)` once enough bars are seen.
/// let mut out = None;
/// for i in 0..40i64 {
/// let p = 100.0 + (i as f64 * 0.4).sin() * 5.0;
/// let candle = Candle::new(p, p + 1.5, p - 1.5, p + 0.3, 1_000.0, i).unwrap();
/// out = indicator.update(candle);
/// }
/// let _ = out;
/// ```
#[derive(Debug, Clone, Default)]
pub struct TdClop {
prev: Option<Candle>,
@@ -19,6 +19,21 @@ use crate::ohlcv::Candle;
use crate::traits::Indicator;
/// TD Clopwin — 2-bar inside-body compression pattern detector.
/// # Example
///
/// ```
/// use wickra_core::{TdClopwin, Candle, Indicator};
///
/// let mut indicator = TdClopwin::new();
/// // `None` during warmup, then `Some(_)` once enough bars are seen.
/// let mut out = None;
/// for i in 0..40i64 {
/// let p = 100.0 + (i as f64 * 0.4).sin() * 5.0;
/// let candle = Candle::new(p, p + 1.5, p - 1.5, p + 0.3, 1_000.0, i).unwrap();
/// out = indicator.update(candle);
/// }
/// let _ = out;
/// ```
#[derive(Debug, Clone, Default)]
pub struct TdClopwin {
prev: Option<Candle>,
@@ -38,6 +38,21 @@ enum Direction {
}
/// TD Combo — aggressive countdown variant.
/// # Example
///
/// ```
/// use wickra_core::{TdCombo, Candle, Indicator};
///
/// let mut indicator = TdCombo::new(4, 9, 2, 13).unwrap();
/// // `None` during warmup, then `Some(_)` once enough bars are seen.
/// let mut out = None;
/// for i in 0..40i64 {
/// let p = 100.0 + (i as f64 * 0.4).sin() * 5.0;
/// let candle = Candle::new(p, p + 1.5, p - 1.5, p + 0.3, 1_000.0, i).unwrap();
/// out = indicator.update(candle);
/// }
/// let _ = out;
/// ```
#[derive(Debug, Clone)]
pub struct TdCombo {
setup_lookback: usize,
@@ -41,6 +41,21 @@ enum Direction {
}
/// TD Countdown — standalone 13-bar countdown.
/// # Example
///
/// ```
/// use wickra_core::{TdCountdown, Candle, Indicator};
///
/// let mut indicator = TdCountdown::new(4, 9, 2, 13).unwrap();
/// // `None` during warmup, then `Some(_)` once enough bars are seen.
/// let mut out = None;
/// for i in 0..40i64 {
/// let p = 100.0 + (i as f64 * 0.4).sin() * 5.0;
/// let candle = Candle::new(p, p + 1.5, p - 1.5, p + 0.3, 1_000.0, i).unwrap();
/// out = indicator.update(candle);
/// }
/// let _ = out;
/// ```
#[derive(Debug, Clone)]
pub struct TdCountdown {
setup_lookback: usize,
@@ -24,6 +24,21 @@ use crate::ohlcv::Candle;
use crate::traits::Indicator;
/// TD Differential — 2-bar reversal pattern detector.
/// # Example
///
/// ```
/// use wickra_core::{TdDifferential, Candle, Indicator};
///
/// let mut indicator = TdDifferential::new();
/// // `None` during warmup, then `Some(_)` once enough bars are seen.
/// let mut out = None;
/// for i in 0..40i64 {
/// let p = 100.0 + (i as f64 * 0.4).sin() * 5.0;
/// let candle = Candle::new(p, p + 1.5, p - 1.5, p + 0.3, 1_000.0, i).unwrap();
/// out = indicator.update(candle);
/// }
/// let _ = out;
/// ```
#[derive(Debug, Clone, Default)]
pub struct TdDifferential {
prev: Option<Candle>,
@@ -42,6 +42,21 @@ pub struct TdLinesOutput {
}
/// TD Lines (TDST) — setup-derived horizontal support / resistance.
/// # Example
///
/// ```
/// use wickra_core::{TdLines, Candle, Indicator};
///
/// let mut indicator = TdLines::new(4, 9).unwrap();
/// // `None` during warmup, then `Some(_)` once enough bars are seen.
/// let mut out = None;
/// for i in 0..40i64 {
/// let p = 100.0 + (i as f64 * 0.4).sin() * 5.0;
/// let candle = Candle::new(p, p + 1.5, p - 1.5, p + 0.3, 1_000.0, i).unwrap();
/// out = indicator.update(candle);
/// }
/// let _ = out;
/// ```
#[derive(Debug, Clone)]
pub struct TdLines {
lookback: usize,
@@ -21,6 +21,21 @@ use crate::ohlcv::Candle;
use crate::traits::Indicator;
/// TD Open — gap-and-fade reversal detector.
/// # Example
///
/// ```
/// use wickra_core::{TdOpen, Candle, Indicator};
///
/// let mut indicator = TdOpen::new();
/// // `None` during warmup, then `Some(_)` once enough bars are seen.
/// let mut out = None;
/// for i in 0..40i64 {
/// let p = 100.0 + (i as f64 * 0.4).sin() * 5.0;
/// let candle = Candle::new(p, p + 1.5, p - 1.5, p + 0.3, 1_000.0, i).unwrap();
/// out = indicator.update(candle);
/// }
/// let _ = out;
/// ```
#[derive(Debug, Clone, Default)]
pub struct TdOpen {
prev: Option<Candle>,
@@ -17,6 +17,21 @@ use crate::ohlcv::Candle;
use crate::traits::Indicator;
/// TD Propulsion — 2-bar trend-continuation thrust detector.
/// # Example
///
/// ```
/// use wickra_core::{TdPropulsion, Candle, Indicator};
///
/// let mut indicator = TdPropulsion::new();
/// // `None` during warmup, then `Some(_)` once enough bars are seen.
/// let mut out = None;
/// for i in 0..40i64 {
/// let p = 100.0 + (i as f64 * 0.4).sin() * 5.0;
/// let candle = Candle::new(p, p + 1.5, p - 1.5, p + 0.3, 1_000.0, i).unwrap();
/// out = indicator.update(candle);
/// }
/// let _ = out;
/// ```
#[derive(Debug, Clone, Default)]
pub struct TdPropulsion {
prev: Option<Candle>,
@@ -50,6 +50,21 @@ struct ExtremeBar {
}
/// TD Risk Level — setup-derived protective-stop levels.
/// # Example
///
/// ```
/// use wickra_core::{TdRiskLevel, Candle, Indicator};
///
/// let mut indicator = TdRiskLevel::new(4, 9).unwrap();
/// // `None` during warmup, then `Some(_)` once enough bars are seen.
/// let mut out = None;
/// for i in 0..40i64 {
/// let p = 100.0 + (i as f64 * 0.4).sin() * 5.0;
/// let candle = Candle::new(p, p + 1.5, p - 1.5, p + 0.3, 1_000.0, i).unwrap();
/// out = indicator.update(candle);
/// }
/// let _ = out;
/// ```
#[derive(Debug, Clone)]
pub struct TdRiskLevel {
lookback: usize,
@@ -58,6 +58,21 @@ pub struct TdSequentialOutput {
}
/// TD Sequential state machine: combined Setup (1-9) + Countdown (1-13).
/// # Example
///
/// ```
/// use wickra_core::{TdSequential, Candle, Indicator};
///
/// let mut indicator = TdSequential::new(4, 9, 2, 13).unwrap();
/// // `None` during warmup, then `Some(_)` once enough bars are seen.
/// let mut out = None;
/// for i in 0..40i64 {
/// let p = 100.0 + (i as f64 * 0.4).sin() * 5.0;
/// let candle = Candle::new(p, p + 1.5, p - 1.5, p + 0.3, 1_000.0, i).unwrap();
/// out = indicator.update(candle);
/// }
/// let _ = out;
/// ```
#[derive(Debug, Clone)]
pub struct TdSequential {
// Rolling window of recent candles. We need up to 5 closes back (for the
@@ -33,6 +33,21 @@ use crate::traits::Indicator;
/// TD Setup state machine: counts consecutive bars meeting DeMark's setup
/// comparison rule against the close `lookback` bars earlier.
/// # Example
///
/// ```
/// use wickra_core::{TdSetup, Candle, Indicator};
///
/// let mut indicator = TdSetup::new(4, 9).unwrap();
/// // `None` during warmup, then `Some(_)` once enough bars are seen.
/// let mut out = None;
/// for i in 0..40i64 {
/// let p = 100.0 + (i as f64 * 0.4).sin() * 5.0;
/// let candle = Candle::new(p, p + 1.5, p - 1.5, p + 0.3, 1_000.0, i).unwrap();
/// out = indicator.update(candle);
/// }
/// let _ = out;
/// ```
#[derive(Debug, Clone)]
pub struct TdSetup {
lookback: usize,
@@ -19,6 +19,21 @@ use crate::ohlcv::Candle;
use crate::traits::Indicator;
/// TD Trap — inside-bar breakout signal detector.
/// # Example
///
/// ```
/// use wickra_core::{TdTrap, Candle, Indicator};
///
/// let mut indicator = TdTrap::new();
/// // `None` during warmup, then `Some(_)` once enough bars are seen.
/// let mut out = None;
/// for i in 0..40i64 {
/// let p = 100.0 + (i as f64 * 0.4).sin() * 5.0;
/// let candle = Candle::new(p, p + 1.5, p - 1.5, p + 0.3, 1_000.0, i).unwrap();
/// out = indicator.update(candle);
/// }
/// let _ = out;
/// ```
#[derive(Debug, Clone, Default)]
pub struct TdTrap {
prev1: Option<Candle>,
@@ -37,6 +37,21 @@ fn is_small(candle: Candle) -> bool {
}
/// Tower Top / Bottom — three-bar reversal detector.
/// # Example
///
/// ```
/// use wickra_core::{TowerTopBottom, Candle, Indicator};
///
/// let mut indicator = TowerTopBottom::new();
/// // `None` during warmup, then `Some(_)` once enough bars are seen.
/// let mut out = None;
/// for i in 0..40i64 {
/// let p = 100.0 + (i as f64 * 0.4).sin() * 5.0;
/// let candle = Candle::new(p, p + 1.5, p - 1.5, p + 0.3, 1_000.0, i).unwrap();
/// out = indicator.update(candle);
/// }
/// let _ = out;
/// ```
#[derive(Debug, Clone, Default)]
pub struct TowerTopBottom {
c1: Option<Candle>,
@@ -30,6 +30,21 @@ fn is_doji(candle: Candle) -> bool {
}
/// Tristar — three-doji star reversal detector.
/// # Example
///
/// ```
/// use wickra_core::{Tristar, Candle, Indicator};
///
/// let mut indicator = Tristar::new();
/// // `None` during warmup, then `Some(_)` once enough bars are seen.
/// let mut out = None;
/// for i in 0..40i64 {
/// let p = 100.0 + (i as f64 * 0.4).sin() * 5.0;
/// let candle = Candle::new(p, p + 1.5, p - 1.5, p + 0.3, 1_000.0, i).unwrap();
/// out = indicator.update(candle);
/// }
/// let _ = out;
/// ```
#[derive(Debug, Clone, Default)]
pub struct Tristar {
c1: Option<Candle>,