Skip to content

Indicators

The SDK includes common technical indicators. All implement the Indicator trait:

rust
pub trait Indicator {
    fn update(&mut self, value: f64);
    fn value(&self) -> f64;
    fn ready(&self) -> bool;
}

Call .update(value) to feed data, .value() to get the current result, and .ready() to check if enough samples have been collected.

Simple Moving Average (Sma)

rust
let mut sma = Sma::new(20);
sma.update(price);
if sma.ready() {
    let value = sma.value();
}

Exponential Moving Average (Ema)

rust
let mut ema = Ema::new(12);
ema.update(price);
if ema.ready() {
    let value = ema.value();
}

Relative Strength Index (Rsi)

rust
let mut rsi = Rsi::new(14);
rsi.update(price);
if rsi.ready() {
    let value = rsi.value(); // 0-100
}

Bollinger Bands

rust
let mut bb = BollingerBands::new(20, 2.0);
bb.update(price);
if bb.ready() {
    let mid = bb.value();     // Middle band (SMA)
    let upper = bb.upper();   // Upper band
    let lower = bb.lower();   // Lower band
}

MACD

rust
let mut macd = Macd::new(12, 26, 9);
macd.update(price);
if macd.ready() {
    let macd_line = macd.value();
    let signal = macd.signal();
    let histogram = macd.histogram();
}

Average True Range (Atr)

rust
let mut atr = Atr::new(14);
atr.update_hlc(high, low, close);  // Use HLC data for accuracy
if atr.ready() {
    let value = atr.value();
}

The standard .update(value) method also works but uses the value as-is (less accurate without high/low).

Standard Deviation (StdDev)

rust
let mut std = StdDev::new(20);
std.update(price);
if std.ready() {
    let value = std.value();
}

Volume-Weighted Average Price (Vwap)

rust
let mut vwap = Vwap::new();
vwap.update_pv(price, volume);  // Feed price and volume
let value = vwap.value();
vwap.reset();  // Reset at session boundaries

Custom Indicators

Build your own by implementing the Indicator trait or using a ring buffer:

rust
pub struct MyIndicator {
    buffer: Vec<f64>,
    period: usize,
}

impl MyIndicator {
    pub fn new(period: usize) -> Self {
        Self {
            buffer: Vec::with_capacity(period),
            period,
        }
    }
}

impl Indicator for MyIndicator {
    fn update(&mut self, value: f64) {
        if self.buffer.len() >= self.period {
            self.buffer.remove(0);
        }
        self.buffer.push(value);
    }

    fn value(&self) -> f64 {
        self.buffer.iter().sum::<f64>() / self.buffer.len() as f64
    }

    fn ready(&self) -> bool {
        self.buffer.len() >= self.period
    }
}

tradectl — Automate Crypto Trading