ursatoro

Package Version Hex Docs

Gleam trading technical indicators library. Pure functions that take OHLCV candle data and return computed indicator values.

The brain of a trading signal bot — equivalent to Python’s TA-Lib/pandas-ta, but for the Gleam ecosystem.

Install

gleam add ursatoro@1

Indicators

CategoryFunctionDescription
TrendsmaSimple Moving Average
TrendemaExponential Moving Average
TrendmacdMoving Average Convergence Divergence → MacdResult
MomentumrsiRelative Strength Index (Wilder’s smoothing)
MomentumstochasticStochastic Oscillator (%K, %D) → StochasticResult
Momentummomentum_factorRolling momentum via log returns
Volatilitybollinger_bandsBollinger Bands (upper, middle, lower) → BollingerBandsResult
VolatilityatrAverage True Range (Wilder’s smoothing)
Volatilityhar_volatilityHAR volatility model (daily/weekly/monthly) → HarResult
VolumevwapVolume Weighted Average Price
VolumeobvOn-Balance Volume
Filterkalman_newInitialize Kalman filter state → KalmanState
Filterkalman_updateUpdate Kalman state with new observation → KalmanState
Filterkalman_smoothBatch Kalman smoothing over price series
MicrostructurevpinVolume-Synchronized Probability of Informed Trading
Microstructureroll_measureRoll measure (liquidity proxy)
MicrostructureamihudAmihud illiquidity measure

Usage

import ursatoro

pub fn main() {
  let candles = [
    ursatoro.candle(open: 10.0, high: 12.0, low: 9.0, close: 11.0, volume: 1000.0),
    ursatoro.candle(open: 11.0, high: 13.0, low: 10.0, close: 12.0, volume: 1500.0),
    ursatoro.candle(open: 12.0, high: 14.0, low: 11.0, close: 13.0, volume: 2000.0),
    ursatoro.candle(open: 13.0, high: 15.0, low: 12.0, close: 14.0, volume: 1800.0),
    ursatoro.candle(open: 14.0, high: 16.0, low: 13.0, close: 15.0, volume: 2200.0),
  ]

  // Simple Moving Average (period 3)
  let assert Ok(sma_values) = ursatoro.sma(candles, period: 3)

  // Exponential Moving Average (period 3)
  let assert Ok(ema_values) = ursatoro.ema(candles, period: 3)

  // MACD (fast 12, slow 26, signal 9)
  let assert Ok(macd_values) = ursatoro.macd(candles, fast: 12, slow: 26, signal: 9)

  // RSI (period 14) — needs at least period + 1 candles
  let assert Ok(rsi_values) = ursatoro.rsi(candles, period: 14)

  // Stochastic Oscillator (%K period 14, %D period 3)
  let assert Ok(stoch_values) = ursatoro.stochastic(candles, k_period: 14, d_period: 3)

  // Bollinger Bands (period 20, 2 standard deviations)
  let assert Ok(bb_values) = ursatoro.bollinger_bands(candles, period: 20, num_std: 2.0)

  // Average True Range (period 14)
  let assert Ok(atr_values) = ursatoro.atr(candles, period: 14)

  // VWAP
  let assert Ok(vwap_values) = ursatoro.vwap(candles)

  // OBV
  let assert Ok(obv_values) = ursatoro.obv(candles)

  // Momentum factor (30-day rolling)
  let assert Ok(mom_values) = ursatoro.momentum_factor(candles, window: 30)

  // HAR volatility model
  let assert Ok(har_values) = ursatoro.har_volatility(candles, daily: 1, weekly: 5, monthly: 22)

  // Kalman filter — batch smoothing
  let prices = [10.0, 11.0, 12.0, 13.0, 14.0]
  let assert Ok(smoothed) = ursatoro.kalman_smooth(prices, 0.01, 1.0)

  // Kalman filter — streaming
  let state = ursatoro.kalman_new(10.0)
  let state = ursatoro.kalman_update(state, 11.0, 0.01, 1.0)

  // VPIN (requires TradeBar list)
  let trade_bars = [ursatoro.TradeBar(buy_volume: 100.0, sell_volume: 50.0, total_volume: 150.0, price_change: 0.5)]
  let assert Ok(vpin_values) = ursatoro.vpin(trade_bars, window: 10)

  // Roll measure (liquidity proxy)
  let assert Ok(roll_values) = ursatoro.roll_measure(prices, window: 3)

  // Amihud illiquidity
  let volumes = [1000.0, 1500.0, 2000.0, 1800.0, 2200.0]
  let assert Ok(amihud_values) = ursatoro.amihud(prices, volumes, window: 3)
}

Error Handling

All indicator functions return Result(List(value), IndicatorError). Possible errors:

import ursatoro

case ursatoro.sma(candles, period: 20) {
  Ok(values) -> // use values
  Error(ursatoro.InsufficientData(required, got)) -> // handle
  Error(ursatoro.InvalidPeriod(period)) -> // handle
  Error(ursatoro.DivisionByZero) -> // handle
}

Precision

All internal calculations use bigdecimal for arbitrary-precision decimal arithmetic. Float values are only produced at the API boundary. This prevents floating-point drift in financial calculations.

Development

gleam build   # Build the project
gleam test    # Run the tests
gleam format src test  # Format code

License

Blue Oak Model License 1.0.0

Search Document