Skip to main content

Streaming-first technical indicators: incremental, fast, install-free.

Project description

Wickra

CI codecov crates.io PyPI npm License: PolyForm-NC

Streaming-first technical indicators. Install with pip install wickra — no system dependencies.

Wickra is a multi-language technical-analysis library with a Rust core and bindings for Python, Node.js, and WebAssembly. Every indicator is a state machine that updates in O(1) per new data point, so live trading bots and historical backtests share the exact same implementation.

import numpy as np
import wickra as ta

# Batch: classic TA-Lib-style usage
prices = np.linspace(100, 200, 1000)
rsi = ta.RSI(14)
values = rsi.batch(prices)              # numpy array, NaN during warmup

# Streaming: same indicator, fed tick by tick
rsi = ta.RSI(14)
for price in live_feed:
    value = rsi.update(price)           # O(1) — no recomputation over history
    if value is not None and value > 70:
        print("overbought")

Why Wickra exists

The Python TA ecosystem has plenty of libraries — TA-Lib, pandas-ta, finta, talipp, tulipy — and every one of them shares the same blind spot:

Library Install pain Streaming Multi-language Active
★ Wickra clean yes Python + Node + WASM + Rust yes
TA-Lib (Python) yes (C deps) no no barely
pandas-ta clean no no slow
finta clean no no stale
ta-lib-python yes (C deps) no no barely
talipp clean yes no yes
Tulip Indicators yes (C deps) no partial stale
ooples (C#) clean no C# only yes

Wickra is the only library that combines all of: clean install, streaming, multi-language reach, and active maintenance.

Benchmark: how much faster is "streaming-first"?

The numbers below were measured on a single developer workstation and are not guaranteed to reproduce identically on different hardware — absolute µs values depend on CPU, memory clock and OS scheduler. Read them as relative speedups between libraries on identical input, not as a universal performance contract.

  • Reproduced on: Windows 11 Pro 26200, AMD Ryzen 9 7950X3D, 64 GB DDR5, Rust 1.92 (release profile, lto = "fat", codegen-units = 1), Python 3.12, Node 20.
  • Reproduce yourself: pip install -e bindings/python[bench] then python -m benchmarks.compare_libraries. The script auto-detects every installed peer library and runs them on the same generated inputs as Wickra. The CI job cross-library-bench runs the same script on every push and uploads the raw report as a build artefact.

Lower µs/op = faster. Wickra wins every batch category outright, and the streaming gap widens linearly with how much history a batch-only library has to recompute on every tick.

Batch — single full pass over a 20 000-bar series

Reading the table: each cell shows that library's runtime, plus how many times slower it is than Wickra in parentheses. marks the winner per row.

Indicator ★ Wickra finta talipp
SMA(20) 95.6 µs ★ 343.5 µs (3.6× slower) 7 640.6 µs (79.9× slower)
EMA(20) 64.6 µs ★ 223.1 µs (3.5× slower) 12 160.9 µs (188.2× slower)
RSI(14) 126.2 µs ★ 1 107.1 µs (8.8× slower) 15 792.2 µs (125.1× slower)
MACD(12, 26, 9) 119.0 µs ★ 531.8 µs (4.5× slower) 49 788.1 µs (418.2× slower)
Bollinger(20, 2.0) 105.3 µs ★ 812.0 µs (7.7× slower) 130 938.3 µs (1 243.7× slower)
ATR(14) 123.5 µs ★ 5 144.8 µs (41.7× slower) 28 816.0 µs (233.4× slower)

Streaming — per-tick latency after seeding with 5 000 historical bars

A batch-only library has to re-run its full indicator over the entire history on every new tick; Wickra updates state in O(1).

Indicator ★ Wickra (per tick) talipp (per tick)
RSI(14) 0.119 µs ★ 1.644 µs (13.8× slower)

TA-Lib and pandas-ta are not included here because both fail to install cleanly on Windows without C build tooling — which is precisely the install pain Wickra was built to remove. The benchmark script auto-detects every peer library it can find and runs them on the same inputs as Wickra; install them in your environment to see those rows light up too.

Run the suite yourself:

pip install -e bindings/python[bench]
python -m benchmarks.compare_libraries

Indicators

71 streaming-first indicators across eight families. Every one passes the batch == streaming equivalence test, reference-value tests, and reset semantics tests.

Family Indicators
Moving Averages SMA, EMA, WMA, DEMA, TEMA, HMA, KAMA, SMMA, TRIMA, ZLEMA, T3, VWMA
Momentum Oscillators RSI (Wilder), Stochastic, CCI, ROC, Williams %R, MFI, Awesome Oscillator, MOM, CMO, TSI, PMO, StochRSI, Ultimate Oscillator
Trend & Directional MACD, ADX (+DI/-DI), Aroon, TRIX, Aroon Oscillator, Vortex, Mass Index, Choppiness Index, Vertical Horizontal Filter
Price Oscillators PPO, DPO, Coppock, Accelerator Oscillator, Balance of Power
Volatility & Bands ATR, Bollinger Bands, Keltner Channels, Donchian Channels, NATR, StdDev, Ulcer Index, Historical Volatility, Bollinger Bandwidth, %B, True Range, Chaikin Volatility
Trailing Stops Parabolic SAR, SuperTrend, Chandelier Exit, Chande Kroll Stop, ATR Trailing Stop
Volume OBV, VWAP (cumulative + rolling), ADL, Volume-Price Trend, Chaikin Money Flow, Chaikin Oscillator, Force Index, Ease of Movement
Price Statistics Typical Price, Median Price, Weighted Close, Linear Regression, Linear Regression Slope, Z-Score, Linear Regression Angle

Adding a new indicator means implementing one trait in Rust; all four bindings inherit it automatically.

Languages

Binding Install Example
Python (PyO3) pip install wickra examples/python/backtest.py
Node.js (napi-rs) npm install wickra examples/node/backtest.js
Browser / WASM npm install wickra-wasm examples/wasm/index.html
Rust cargo add wickra examples/rust/src/bin/backtest.rs

Each binding ships several runnable examples (streaming, backtest, live feed); examples/README.md is the full cross-language index.

The wickra-core crate is unsafe-forbidden, so every binding inherits a memory-safe implementation.

Rust API

use wickra::{Indicator, BatchExt, Chain, Ema, Rsi, Sma};

// Streaming or batch — same trait, same code.
let mut sma = Sma::new(14)?;
let out: Vec<Option<f64>> = sma.batch(&[1.0, 2.0, 3.0, 4.0, 5.0]);

let mut rsi = Rsi::new(14)?;
for price in live_feed {
    if let Some(v) = rsi.update(price) {
        println!("RSI = {v}");
    }
}

// Compose indicators: RSI(7) on top of EMA(14).
let mut chain = Chain::new(Ema::new(14)?, Rsi::new(7)?);
chain.update(price);

Live data sources

wickra-data (separate crate, opt-in) ships:

  • A streaming OHLCV CSV reader.
  • A tick-to-candle aggregator with arbitrary timeframes.
  • A candle resampler for multi-timeframe analysis (1m → 5m → 1h on the fly).
  • A Binance Spot WebSocket kline adapter (feature live-binance).
use wickra::{Indicator, Rsi};
use wickra_data::live::binance::{BinanceKlineStream, Interval};

let mut stream = BinanceKlineStream::connect(&["BTCUSDT".into()], Interval::OneMinute).await?;
let mut rsi = Rsi::new(14)?;
while let Some(event) = stream.next_event().await? {
    if event.is_closed {
        if let Some(v) = rsi.update(event.candle.close) {
            println!("RSI = {v:.2}");
        }
    }
}

A Python live-trading example using the public websockets package lives at examples/python/live_trading.py.

Project layout

wickra/
├── crates/
│   ├── wickra-core/         core engine + all 71 indicators
│   ├── wickra/              top-level facade crate (publishes on crates.io) + benches/
│   └── wickra-data/         CSV reader, tick aggregator, live exchange feeds
├── bindings/
│   ├── python/              PyO3 + maturin (publishes on PyPI)
│   ├── node/                napi-rs (publishes on npm)
│   └── wasm/                wasm-bindgen (browsers, bundlers, Node)
├── examples/                examples/README.md indexes every language
│   ├── data/                real BTCUSDT OHLCV datasets, one per timeframe
│   ├── rust/                Rust workspace member (`wickra-examples`)
│   ├── python/              backtest, live trading, parallel assets, multi-tf
│   ├── node/                streaming, backtest, live trading (load `wickra`)
│   └── wasm/                browser demo for `wickra-wasm`
└── .github/workflows/       CI and release pipelines

Rust benchmarks live in crates/wickra/benches/; runnable Rust examples live in the workspace member crate at examples/rust/. There is no top-level benches/ directory.

Building everything from source

# Rust core + tests
cargo test --workspace
cargo clippy --workspace --all-targets -- -D warnings
cargo bench -p wickra

# Python binding (requires Rust toolchain + maturin)
cd bindings/python
maturin develop --release
pytest

# WASM binding (requires wasm-pack + wasm32-unknown-unknown target)
wasm-pack build bindings/wasm --target web --release --features panic-hook

# Node binding (requires @napi-rs/cli)
cd bindings/node && npm install && npm run build && npm test

Testing

Every layer is covered; run the suites with the commands in Building everything from source.

  • wickra-core: unit tests per indicator — textbook reference values (Wilder RSI, Bollinger Bands, MACD, ATR, Stochastic), batch == streaming equivalence, reset semantics, NaN/Inf handling, and property tests.
  • wickra-data: unit tests for CSV decoding, the tick aggregator, the resampler, and the Binance payload parser.
  • bindings/python: pytest covering smoke checks, streaming/batch equivalence, reference values, lifecycle, input validation, and dict/tuple candle inputs.
  • bindings/node: node --test cases for batch, streaming, and reference values across all indicators.
  • bindings/wasm: wasm-bindgen-test cases for constructors, equivalence, and reference values.

Contributing

Contributions are very welcome — issues, bug reports, ideas, and pull requests all land in the same place: https://github.com/kingchenc/wickra.

A short orientation for first-time contributors:

  • Adding an indicator. Implement the Indicator trait in crates/wickra-core/src/indicators/<name>.rs, wire it into indicators/mod.rs and the crate root, and add reference-value tests, a batch == streaming equivalence test, and (where it makes sense) a proptest. The four bindings inherit your indicator automatically once you expose it in the language wrappers.
  • Fixing a numeric bug. Add a failing test that pins the textbook value first, then fix the math. Property tests in crates/wickra-core catch most regressions; please don't disable them.
  • Improving a binding. Each binding lives under bindings/<lang> with its own tests; please keep the batch == streaming invariant.
  • Style. cargo fmt --all + cargo clippy --workspace --all-targets -- -D warnings are CI gates; running them locally before pushing keeps reviews short.

For larger architectural changes, open an issue first so we can sketch the shape together before you invest the time.

License

Licensed under the PolyForm Noncommercial License 1.0.0. See LICENSE.

In plain English: use it, fork it, modify it, redistribute it, file issues, send pull requests — all welcome. Personal projects, research, education, non-profits, government, hobby trading bots: all fine. The one thing that's not allowed is commercial sale of the software or of services built around it. If you want to use Wickra commercially, get in touch about a license.

Disclaimer

Wickra is an indicator toolkit, not a trading system. Values it computes are deterministic transforms of the input data — they are not financial advice and they do not predict the market. Any use of this library in a production trading context is at your own risk.

The library is provided as is, without warranty of any kind; see LICENSE for the full terms.


GitHub stars GitHub forks GitHub issues

If Wickra saved you time, the cheapest way to say thanks is to ⭐ the repo.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

wickra-0.2.6.tar.gz (162.0 kB view details)

Uploaded Source

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

wickra-0.2.6-cp39-abi3-win_arm64.whl (298.3 kB view details)

Uploaded CPython 3.9+Windows ARM64

wickra-0.2.6-cp39-abi3-win_amd64.whl (339.9 kB view details)

Uploaded CPython 3.9+Windows x86-64

wickra-0.2.6-cp39-abi3-musllinux_1_2_x86_64.whl (675.5 kB view details)

Uploaded CPython 3.9+musllinux: musl 1.2+ x86-64

wickra-0.2.6-cp39-abi3-musllinux_1_2_aarch64.whl (594.6 kB view details)

Uploaded CPython 3.9+musllinux: musl 1.2+ ARM64

wickra-0.2.6-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (456.4 kB view details)

Uploaded CPython 3.9+manylinux: glibc 2.17+ x86-64

wickra-0.2.6-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (416.9 kB view details)

Uploaded CPython 3.9+manylinux: glibc 2.17+ ARM64

wickra-0.2.6-cp39-abi3-macosx_11_0_arm64.whl (379.3 kB view details)

Uploaded CPython 3.9+macOS 11.0+ ARM64

wickra-0.2.6-cp39-abi3-macosx_10_12_x86_64.whl (429.7 kB view details)

Uploaded CPython 3.9+macOS 10.12+ x86-64

File details

Details for the file wickra-0.2.6.tar.gz.

File metadata

  • Download URL: wickra-0.2.6.tar.gz
  • Upload date:
  • Size: 162.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: maturin/1.13.3

File hashes

Hashes for wickra-0.2.6.tar.gz
Algorithm Hash digest
SHA256 73856dba425a238e191e956c70cca4387b04223b4ed54e0797fd172f06bc671c
MD5 0944a598f5d0175b4dd9a1e9a1e01c03
BLAKE2b-256 02e799aad51a82de826c5a4b88bf1a3bba17eacf4782c143f818a25ae6a3bc76

See more details on using hashes here.

File details

Details for the file wickra-0.2.6-cp39-abi3-win_arm64.whl.

File metadata

  • Download URL: wickra-0.2.6-cp39-abi3-win_arm64.whl
  • Upload date:
  • Size: 298.3 kB
  • Tags: CPython 3.9+, Windows ARM64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: maturin/1.13.3

File hashes

Hashes for wickra-0.2.6-cp39-abi3-win_arm64.whl
Algorithm Hash digest
SHA256 88dd0553e353915729792e9759619b0c79b5f17376be5e1e252bd69b7455435e
MD5 a48a104a66f124fe25a1f194f4b3600c
BLAKE2b-256 b707e0123556e046b23c56bd0d34f2da7935062575a08345a8a999fadd5952d3

See more details on using hashes here.

File details

Details for the file wickra-0.2.6-cp39-abi3-win_amd64.whl.

File metadata

  • Download URL: wickra-0.2.6-cp39-abi3-win_amd64.whl
  • Upload date:
  • Size: 339.9 kB
  • Tags: CPython 3.9+, Windows x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: maturin/1.13.3

File hashes

Hashes for wickra-0.2.6-cp39-abi3-win_amd64.whl
Algorithm Hash digest
SHA256 c43265abfb4ae5026f622e351087c7a66d24d2a0c11453a90261b67a8b5b64d0
MD5 18dee985a642bd1a668dc15cd64b74b8
BLAKE2b-256 d80f6052d3394a1b70fc658665b2ee5193cf3d44e6c5ff67e1ef8c32c289c263

See more details on using hashes here.

File details

Details for the file wickra-0.2.6-cp39-abi3-musllinux_1_2_x86_64.whl.

File metadata

File hashes

Hashes for wickra-0.2.6-cp39-abi3-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 d344cd19d5515dc7a9eeb0f101e3a3e8af98d8b3aff1333f99127b7918b1206e
MD5 c2af1738232323f6f14745876c0da3b1
BLAKE2b-256 ef2ba055afcd5f868c1277909ccd2607987ed3f639abe537001e91335e7156f3

See more details on using hashes here.

File details

Details for the file wickra-0.2.6-cp39-abi3-musllinux_1_2_aarch64.whl.

File metadata

File hashes

Hashes for wickra-0.2.6-cp39-abi3-musllinux_1_2_aarch64.whl
Algorithm Hash digest
SHA256 a1fe9d679ce6dd4207586de86248d32d9bf608de232168c5c773fd72feab971f
MD5 097c8dc3f57fb1a98e6c92671386c00b
BLAKE2b-256 582dd30a25b3e4aa3d198dfc09ab2cc90a086e1201b86540f0351bac8cee6b0e

See more details on using hashes here.

File details

Details for the file wickra-0.2.6-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for wickra-0.2.6-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 7902b1054aeb48d521270389bf6ccc7cc49d2d568b78586412f8bb8d0798b473
MD5 9557bc2ad551bd36954291847f9c5ed3
BLAKE2b-256 ca5df3ee3ab61d47b93200ee1b83c672b0a35131bf323ba29ec880fdf23a4d83

See more details on using hashes here.

File details

Details for the file wickra-0.2.6-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for wickra-0.2.6-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 be794306445603251363770d46455cf2478d14c4d0ecb281f5dc8fa698eda684
MD5 1be95cc86bc1f0a5cbf6afa221c481d5
BLAKE2b-256 409012e3bcfda07896f5d93629d22865a2d09d4ad4051c41e8e4deb0d9cfd883

See more details on using hashes here.

File details

Details for the file wickra-0.2.6-cp39-abi3-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for wickra-0.2.6-cp39-abi3-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 0984f2d24a61b1edb549d48f628852f4a880cdfa3436d788304ad0ca80ea18b8
MD5 f005813903ff19c9f0cab7327a39dd7c
BLAKE2b-256 7f206954b9827e31809184fd73a01c75de7f2a03b67051e23392d0013ab26106

See more details on using hashes here.

File details

Details for the file wickra-0.2.6-cp39-abi3-macosx_10_12_x86_64.whl.

File metadata

File hashes

Hashes for wickra-0.2.6-cp39-abi3-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 a4c2608a5e6cbcbec905fe7fd8fccfc3cdcb74c039120e13447abbff6d225384
MD5 198cece167371887b5d43dd4c94e43d3
BLAKE2b-256 e9224e789ee7a213736df9095243364b2776ca8161891b2a0f357a7a0a57f705

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page