wickra 0.2.1 → 0.2.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,45 +1,316 @@
1
- # wickra
1
+ # Wickra
2
2
 
3
- Node.js bindings for the Wickra streaming-first technical indicators library.
3
+ [![CI](https://github.com/kingchenc/wickra/actions/workflows/ci.yml/badge.svg)](https://github.com/kingchenc/wickra/actions/workflows/ci.yml)
4
+ [![codecov](https://codecov.io/gh/kingchenc/wickra/branch/main/graph/badge.svg)](https://codecov.io/gh/kingchenc/wickra)
5
+ [![crates.io](https://img.shields.io/crates/v/wickra.svg?logo=rust&color=orange)](https://crates.io/crates/wickra)
6
+ [![PyPI](https://img.shields.io/pypi/v/wickra.svg?logo=pypi&color=blue)](https://pypi.org/project/wickra/)
7
+ [![npm](https://img.shields.io/npm/v/wickra.svg?logo=npm&color=red)](https://www.npmjs.com/package/wickra)
8
+ [![License: PolyForm-NC](https://img.shields.io/badge/license-PolyForm--NC--1.0.0-purple)](LICENSE)
4
9
 
5
- ## Install
10
+ **Streaming-first technical indicators. Install with `pip install wickra` — no system dependencies.**
6
11
 
7
- Once published, install per platform via the precompiled native package:
12
+ Wickra is a multi-language technical-analysis library with a Rust core and
13
+ bindings for Python, Node.js, and WebAssembly. Every indicator is a state
14
+ machine that updates in O(1) per new data point, so live trading bots and
15
+ historical backtests share the exact same implementation.
8
16
 
9
- ```bash
10
- npm install wickra
17
+ ```python
18
+ import numpy as np
19
+ import wickra as ta
20
+
21
+ # Batch: classic TA-Lib-style usage
22
+ prices = np.linspace(100, 200, 1000)
23
+ rsi = ta.RSI(14)
24
+ values = rsi.batch(prices) # numpy array, NaN during warmup
25
+
26
+ # Streaming: same indicator, fed tick by tick
27
+ rsi = ta.RSI(14)
28
+ for price in live_feed:
29
+ value = rsi.update(price) # O(1) — no recomputation over history
30
+ if value is not None and value > 70:
31
+ print("overbought")
11
32
  ```
12
33
 
13
- ## Build from source
34
+ ## Why Wickra exists
35
+
36
+ The Python TA ecosystem has plenty of libraries — TA-Lib, pandas-ta, finta,
37
+ talipp, tulipy — and every one of them shares the same blind spot:
38
+
39
+ | Library | Install pain | Streaming | Multi-language | Active |
40
+ |------------------------|-----------------|-----------|----------------|--------|
41
+ | **★ Wickra** | **clean** | **yes** | **Python + Node + WASM + Rust** | **yes** |
42
+ | TA-Lib (Python) | yes (C deps) | no | no | barely |
43
+ | pandas-ta | clean | no | no | slow |
44
+ | finta | clean | no | no | stale |
45
+ | ta-lib-python | yes (C deps) | no | no | barely |
46
+ | talipp | clean | yes | no | yes |
47
+ | Tulip Indicators | yes (C deps) | no | partial | stale |
48
+ | ooples (C#) | clean | no | C# only | yes |
49
+
50
+ Wickra is the only library that combines all of: clean install, streaming,
51
+ multi-language reach, and active maintenance.
52
+
53
+ ## Benchmark: how much faster is "streaming-first"?
54
+
55
+ The numbers below were measured on a single developer workstation and are not
56
+ guaranteed to reproduce identically on different hardware — absolute µs values
57
+ depend on CPU, memory clock and OS scheduler. Read them as **relative
58
+ speedups** between libraries on identical input, not as a universal
59
+ performance contract.
60
+
61
+ - **Reproduced on:** Windows 11 Pro 26200, AMD Ryzen 9 7950X3D, 64 GB DDR5,
62
+ Rust 1.92 (release profile, `lto = "fat"`, `codegen-units = 1`),
63
+ Python 3.12, Node 20.
64
+ - **Reproduce yourself:** `pip install -e bindings/python[bench]` then
65
+ `python -m benchmarks.compare_libraries`. The script auto-detects every
66
+ installed peer library and runs them on the same generated inputs as
67
+ Wickra. The CI job `cross-library-bench` runs the same script on every
68
+ push and uploads the raw report as a build artefact.
69
+
70
+ Lower µs/op = faster. Wickra wins every batch category outright, and the
71
+ streaming gap widens linearly with how much history a batch-only library has
72
+ to recompute on every tick.
73
+
74
+ ### Batch — single full pass over a 20 000-bar series
75
+
76
+ Reading the table: each cell shows that library's runtime, plus how many times
77
+ slower it is than Wickra in parentheses. **★** marks the winner per row.
78
+
79
+ | Indicator | **★ Wickra** | finta | talipp |
80
+ |---------------------|---------------------|-----------------------------|-------------------------------|
81
+ | SMA(20) | **95.6 µs ★** | 343.5 µs (3.6× slower) | 7 640.6 µs (79.9× slower) |
82
+ | EMA(20) | **64.6 µs ★** | 223.1 µs (3.5× slower) | 12 160.9 µs (188.2× slower) |
83
+ | RSI(14) | **126.2 µs ★** | 1 107.1 µs (8.8× slower) | 15 792.2 µs (125.1× slower) |
84
+ | MACD(12, 26, 9) | **119.0 µs ★** | 531.8 µs (4.5× slower) | 49 788.1 µs (418.2× slower) |
85
+ | Bollinger(20, 2.0) | **105.3 µs ★** | 812.0 µs (7.7× slower) | 130 938.3 µs (1 243.7× slower)|
86
+ | ATR(14) | **123.5 µs ★** | 5 144.8 µs (41.7× slower) | 28 816.0 µs (233.4× slower) |
87
+
88
+ ### Streaming — per-tick latency after seeding with 5 000 historical bars
89
+
90
+ A batch-only library has to re-run its full indicator over the entire history on
91
+ every new tick; Wickra updates state in O(1).
92
+
93
+ | Indicator | **★ Wickra (per tick)** | talipp (per tick) |
94
+ |-----------|---------------------|---------------------------|
95
+ | RSI(14) | **0.119 µs ★** | 1.644 µs (13.8× slower) |
96
+
97
+ > TA-Lib and pandas-ta are not included here because both fail to install
98
+ > cleanly on Windows without C build tooling — which is precisely the install
99
+ > pain Wickra was built to remove. The benchmark script auto-detects every
100
+ > peer library it can find and runs them on the same inputs as Wickra; install
101
+ > them in your environment to see those rows light up too.
102
+
103
+ Run the suite yourself:
14
104
 
15
105
  ```bash
16
- cd bindings/node
17
- npm install
18
- npm run build
19
- npm test
106
+ pip install -e bindings/python[bench]
107
+ python -m benchmarks.compare_libraries
20
108
  ```
21
109
 
22
- The native module is built via [napi-rs](https://napi.rs/). The build script
23
- produces a `wickra.<platform>-<arch>.node` binary in the package root that
24
- `index.js` loads at runtime.
110
+ ## Indicators
111
+
112
+ 71 streaming-first indicators across eight families. Every one passes the
113
+ `batch == streaming` equivalence test, reference-value tests, and reset
114
+ semantics tests.
115
+
116
+ | Family | Indicators |
117
+ |--------|-----------|
118
+ | Moving Averages | SMA, EMA, WMA, DEMA, TEMA, HMA, KAMA, SMMA, TRIMA, ZLEMA, T3, VWMA |
119
+ | Momentum Oscillators | RSI (Wilder), Stochastic, CCI, ROC, Williams %R, MFI, Awesome Oscillator, MOM, CMO, TSI, PMO, StochRSI, Ultimate Oscillator |
120
+ | Trend & Directional | MACD, ADX (+DI/-DI), Aroon, TRIX, Aroon Oscillator, Vortex, Mass Index, Choppiness Index, Vertical Horizontal Filter |
121
+ | Price Oscillators | PPO, DPO, Coppock, Accelerator Oscillator, Balance of Power |
122
+ | Volatility & Bands | ATR, Bollinger Bands, Keltner Channels, Donchian Channels, NATR, StdDev, Ulcer Index, Historical Volatility, Bollinger Bandwidth, %B, True Range, Chaikin Volatility |
123
+ | Trailing Stops | Parabolic SAR, SuperTrend, Chandelier Exit, Chande Kroll Stop, ATR Trailing Stop |
124
+ | Volume | OBV, VWAP (cumulative + rolling), ADL, Volume-Price Trend, Chaikin Money Flow, Chaikin Oscillator, Force Index, Ease of Movement |
125
+ | Price Statistics | Typical Price, Median Price, Weighted Close, Linear Regression, Linear Regression Slope, Z-Score, Linear Regression Angle |
126
+
127
+ Adding a new indicator means implementing one trait in Rust; all four bindings
128
+ inherit it automatically.
129
+
130
+ ## Languages
131
+
132
+ | Binding | Install | Example |
133
+ |-------------------|-----------------------------------------------|---------|
134
+ | Python (PyO3) | `pip install wickra` | `examples/python/backtest.py` |
135
+ | Node.js (napi-rs) | `npm install wickra` | `examples/node/backtest.js` |
136
+ | Browser / WASM | `npm install wickra-wasm` | `examples/wasm/index.html` |
137
+ | Rust | `cargo add wickra` | `examples/rust/src/bin/backtest.rs` |
138
+
139
+ Each binding ships several runnable examples (streaming, backtest, live feed);
140
+ [`examples/README.md`](examples/README.md) is the full cross-language index.
25
141
 
26
- ## Usage
142
+ The wickra-core crate is `unsafe`-forbidden, so every binding inherits a
143
+ memory-safe implementation.
27
144
 
28
- ```js
29
- import { SMA, RSI, MACD, version } from 'wickra';
145
+ ## Rust API
30
146
 
31
- console.log('wickra', version());
147
+ ```rust
148
+ use wickra::{Indicator, BatchExt, Chain, Ema, Rsi, Sma};
32
149
 
33
- // Batch:
34
- const prices = Array.from({ length: 1000 }, (_, i) => 100 + Math.sin(i * 0.1) * 5);
35
- const rsi = new RSI(14).batch(prices);
150
+ // Streaming or batch — same trait, same code.
151
+ let mut sma = Sma::new(14)?;
152
+ let out: Vec<Option<f64>> = sma.batch(&[1.0, 2.0, 3.0, 4.0, 5.0]);
36
153
 
37
- // Streaming:
38
- const macd = new MACD(12, 26, 9);
39
- for (const p of livePriceStream) {
40
- const v = macd.update(p);
41
- if (v && v.histogram > 0) console.log('bullish crossover candidate');
154
+ let mut rsi = Rsi::new(14)?;
155
+ for price in live_feed {
156
+ if let Some(v) = rsi.update(price) {
157
+ println!("RSI = {v}");
158
+ }
42
159
  }
160
+
161
+ // Compose indicators: RSI(7) on top of EMA(14).
162
+ let mut chain = Chain::new(Ema::new(14)?, Rsi::new(7)?);
163
+ chain.update(price);
43
164
  ```
44
165
 
45
- See `index.d.ts` for the full TypeScript surface.
166
+ ## Live data sources
167
+
168
+ `wickra-data` (separate crate, opt-in) ships:
169
+
170
+ - A streaming OHLCV **CSV reader**.
171
+ - A **tick-to-candle aggregator** with arbitrary timeframes.
172
+ - A **candle resampler** for multi-timeframe analysis (1m → 5m → 1h on the fly).
173
+ - A **Binance Spot WebSocket** kline adapter (feature `live-binance`).
174
+
175
+ ```rust
176
+ use wickra::{Indicator, Rsi};
177
+ use wickra_data::live::binance::{BinanceKlineStream, Interval};
178
+
179
+ let mut stream = BinanceKlineStream::connect(&["BTCUSDT".into()], Interval::OneMinute).await?;
180
+ let mut rsi = Rsi::new(14)?;
181
+ while let Some(event) = stream.next_event().await? {
182
+ if event.is_closed {
183
+ if let Some(v) = rsi.update(event.candle.close) {
184
+ println!("RSI = {v:.2}");
185
+ }
186
+ }
187
+ }
188
+ ```
189
+
190
+ A Python live-trading example using the public `websockets` package lives at
191
+ `examples/python/live_trading.py`.
192
+
193
+ ## Project layout
194
+
195
+ ```
196
+ wickra/
197
+ ├── crates/
198
+ │ ├── wickra-core/ core engine + all 71 indicators
199
+ │ ├── wickra/ top-level facade crate (publishes on crates.io) + benches/
200
+ │ └── wickra-data/ CSV reader, tick aggregator, live exchange feeds
201
+ ├── bindings/
202
+ │ ├── python/ PyO3 + maturin (publishes on PyPI)
203
+ │ ├── node/ napi-rs (publishes on npm)
204
+ │ └── wasm/ wasm-bindgen (browsers, bundlers, Node)
205
+ ├── examples/ examples/README.md indexes every language
206
+ │ ├── data/ real BTCUSDT OHLCV datasets, one per timeframe
207
+ │ ├── rust/ Rust workspace member (`wickra-examples`)
208
+ │ ├── python/ backtest, live trading, parallel assets, multi-tf
209
+ │ ├── node/ streaming, backtest, live trading (load `wickra`)
210
+ │ └── wasm/ browser demo for `wickra-wasm`
211
+ └── .github/workflows/ CI and release pipelines
212
+ ```
213
+
214
+ Rust benchmarks live in `crates/wickra/benches/`; runnable Rust examples live
215
+ in the workspace member crate at `examples/rust/`. There is no top-level
216
+ `benches/` directory.
217
+
218
+ ## Building everything from source
219
+
220
+ ```bash
221
+ # Rust core + tests
222
+ cargo test --workspace
223
+ cargo clippy --workspace --all-targets -- -D warnings
224
+ cargo bench -p wickra
225
+
226
+ # Python binding (requires Rust toolchain + maturin)
227
+ cd bindings/python
228
+ maturin develop --release
229
+ pytest
230
+
231
+ # WASM binding (requires wasm-pack + wasm32-unknown-unknown target)
232
+ wasm-pack build bindings/wasm --target web --release --features panic-hook
233
+
234
+ # Node binding (requires @napi-rs/cli)
235
+ cd bindings/node && npm install && npm run build && npm test
236
+ ```
237
+
238
+ ## Testing
239
+
240
+ Every layer is covered; run the suites with the commands in
241
+ [Building everything from source](#building-everything-from-source).
242
+
243
+ - `wickra-core`: unit tests per indicator — textbook reference values
244
+ (Wilder RSI, Bollinger Bands, MACD, ATR, Stochastic), `batch == streaming`
245
+ equivalence, `reset` semantics, NaN/Inf handling, and property tests.
246
+ - `wickra-data`: unit tests for CSV decoding, the tick aggregator, the
247
+ resampler, and the Binance payload parser.
248
+ - `bindings/python`: pytest covering smoke checks, streaming/batch
249
+ equivalence, reference values, lifecycle, input validation, and
250
+ dict/tuple candle inputs.
251
+ - `bindings/node`: `node --test` cases for batch, streaming, and reference
252
+ values across all indicators.
253
+ - `bindings/wasm`: `wasm-bindgen-test` cases for constructors, equivalence,
254
+ and reference values.
255
+
256
+ ## Contributing
257
+
258
+ Contributions are very welcome — issues, bug reports, ideas, and pull requests
259
+ all land in the same place: <https://github.com/kingchenc/wickra>.
260
+
261
+ A short orientation for first-time contributors:
262
+
263
+ - **Adding an indicator.** Implement the `Indicator` trait in
264
+ `crates/wickra-core/src/indicators/<name>.rs`, wire it into
265
+ `indicators/mod.rs` and the crate root, and add reference-value tests,
266
+ a `batch == streaming` equivalence test, and (where it makes sense) a
267
+ proptest. The four bindings inherit your indicator automatically once
268
+ you expose it in the language wrappers.
269
+ - **Fixing a numeric bug.** Add a failing test that pins the textbook value
270
+ first, then fix the math. Property tests in `crates/wickra-core` catch
271
+ most regressions; please don't disable them.
272
+ - **Improving a binding.** Each binding lives under `bindings/<lang>` with
273
+ its own tests; please keep the `batch == streaming` invariant.
274
+ - **Style.** `cargo fmt --all` + `cargo clippy --workspace --all-targets -- -D warnings`
275
+ are CI gates; running them locally before pushing keeps reviews short.
276
+
277
+ For larger architectural changes, open an issue first so we can sketch the
278
+ shape together before you invest the time.
279
+
280
+ ## License
281
+
282
+ Licensed under the **PolyForm Noncommercial License 1.0.0**. See [LICENSE](LICENSE).
283
+
284
+ In plain English: use it, fork it, modify it, redistribute it, file issues, send
285
+ pull requests — all welcome. Personal projects, research, education, non-profits,
286
+ government, hobby trading bots: all fine. The one thing that's not allowed is
287
+ commercial sale of the software or of services built around it. If you want to
288
+ use Wickra commercially, get in touch about a license.
289
+
290
+ ## Disclaimer
291
+
292
+ Wickra is an indicator toolkit, not a trading system. Values it computes are
293
+ deterministic transforms of the input data — they are not financial advice and
294
+ they do not predict the market. Any use of this library in a production
295
+ trading context is at your own risk.
296
+
297
+ The library is provided **as is**, without warranty of any kind; see
298
+ [LICENSE](LICENSE) for the full terms.
299
+
300
+ ---
301
+
302
+ <p align="center">
303
+ <a href="https://github.com/kingchenc/wickra/stargazers">
304
+ <img alt="GitHub stars" src="https://img.shields.io/github/stars/kingchenc/wickra?style=for-the-badge&logo=github&logoColor=white&color=ffd866">
305
+ </a>
306
+ <a href="https://github.com/kingchenc/wickra/network/members">
307
+ <img alt="GitHub forks" src="https://img.shields.io/github/forks/kingchenc/wickra?style=for-the-badge&logo=github&logoColor=white&color=78dce8">
308
+ </a>
309
+ <a href="https://github.com/kingchenc/wickra/issues">
310
+ <img alt="GitHub issues" src="https://img.shields.io/github/issues/kingchenc/wickra?style=for-the-badge&logo=github&logoColor=white&color=ff6188">
311
+ </a>
312
+ </p>
313
+
314
+ <p align="center">
315
+ If Wickra saved you time, the cheapest way to say thanks is to ⭐ the repo.
316
+ </p>
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wickra-darwin-arm64",
3
- "version": "0.2.1",
3
+ "version": "0.2.6",
4
4
  "description": "Native binding for wickra (macOS Apple Silicon). Installed automatically as an optional dependency of wickra on matching platforms.",
5
5
  "main": "wickra.darwin-arm64.node",
6
6
  "files": [
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wickra-darwin-x64",
3
- "version": "0.2.1",
3
+ "version": "0.2.6",
4
4
  "description": "Native binding for wickra (macOS Intel). Installed automatically as an optional dependency of wickra on matching platforms.",
5
5
  "main": "wickra.darwin-x64.node",
6
6
  "files": [
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wickra-linux-arm64-gnu",
3
- "version": "0.2.1",
3
+ "version": "0.2.6",
4
4
  "description": "Native binding for wickra (linux arm64 GNU). Installed automatically as an optional dependency of wickra on matching platforms.",
5
5
  "main": "wickra.linux-arm64-gnu.node",
6
6
  "files": [
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wickra-linux-x64-gnu",
3
- "version": "0.2.1",
3
+ "version": "0.2.6",
4
4
  "description": "Native binding for wickra (linux x64 GNU). Installed automatically as an optional dependency of wickra on matching platforms.",
5
5
  "main": "wickra.linux-x64-gnu.node",
6
6
  "files": [
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wickra-win32-x64-msvc",
3
- "version": "0.2.1",
3
+ "version": "0.2.6",
4
4
  "description": "Native binding for wickra (Windows x64 MSVC). Installed automatically as an optional dependency of wickra on matching platforms.",
5
5
  "main": "wickra.win32-x64-msvc.node",
6
6
  "files": [
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wickra",
3
- "version": "0.2.1",
3
+ "version": "0.2.6",
4
4
  "description": "Streaming-first technical indicators: incremental, fast, install-free. Node bindings powered by Rust.",
5
5
  "author": "kingchenc <kingchencp@gmail.com>",
6
6
  "main": "index.js",
@@ -46,11 +46,11 @@
46
46
  "node": ">= 18"
47
47
  },
48
48
  "optionalDependencies": {
49
- "wickra-linux-x64-gnu": "0.2.1",
50
- "wickra-linux-arm64-gnu": "0.2.1",
51
- "wickra-darwin-x64": "0.2.1",
52
- "wickra-darwin-arm64": "0.2.1",
53
- "wickra-win32-x64-msvc": "0.2.1"
49
+ "wickra-linux-x64-gnu": "0.2.6",
50
+ "wickra-linux-arm64-gnu": "0.2.6",
51
+ "wickra-darwin-x64": "0.2.6",
52
+ "wickra-darwin-arm64": "0.2.6",
53
+ "wickra-win32-x64-msvc": "0.2.6"
54
54
  },
55
55
  "scripts": {
56
56
  "build": "napi build --platform --release",
Binary file
Binary file
Binary file
Binary file
Binary file