F-Abschluss: wire the Python package, refresh docs and extend the test suites

Finalises the F1-F12 indicator expansion (25 -> 63 indicators).

- Python `wickra/__init__.py`: import and re-export all 63 indicators,
  grouped by family, with a matching `__all__`. The package previously
  exposed only the original 25 even though the compiled module and the
  `.pyi` stubs already carried the rest.
- Docs: `Home.md` and `README.md` indicator counts and family tables
  updated to 63; `Indicators-Overview.md` already restructured per family
  in F10-F12; `Warmup-Periods.md` gains all 38 new indicators across the
  single- and multi-output tables (and the stale two-arg `Psar::new`
  example is corrected to three args); `CHANGELOG.md` `[Unreleased]` lists
  every new indicator by family.
- Tests: `bindings/node/__tests__/indicators.test.js` covers all 63
  indicators (streaming==batch plus four new reference-value checks),
  80/80 green; new `bindings/python/tests/test_new_indicators.py` covers
  the 38 additions (streaming==batch, shapes, reference values,
  lifecycle), Python suite 105/105 green.
- `bindings/node/index.js` regenerated by `napi build`.

cargo fmt + clippy (core/wickra/data/wasm/node) clean; 454 core tests,
25 data tests, 66 doctests, 80 Node tests and 105 Python tests green;
`cargo check -p wickra-wasm --tests` green.
This commit is contained in:
kingchenc
2026-05-22 20:04:13 +02:00
parent 2d0ee926c5
commit 2f3b5cc3be
8 changed files with 534 additions and 73 deletions
+4 -3
View File
@@ -7,9 +7,10 @@ Node.js, WebAssembly, and Rust itself. The same `update` call you write inside
a live trading loop also drives the historical backtest of that same
strategy — there is no second code path that drifts behind the streaming one.
The project ships 25 indicators across the four classical families (trend,
momentum, volatility, volume) and a small set of supporting types (`Candle`,
`Tick`, `Chain`). The Rust core forbids `unsafe`, so every binding inherits a
The project ships 63 indicators across the four classical families (trend,
momentum, volatility, volume) plus a statistics group, and a small set of
supporting types (`Candle`, `Tick`, `Chain`). The Rust core forbids `unsafe`,
so every binding inherits a
memory-safe implementation. Install is one command on every supported
platform: `pip install wickra`, `cargo add wickra`, `npm install wickra` — no
system compilers, no C dependencies, no headers.
+39 -1
View File
@@ -38,10 +38,44 @@ index" in 0-indexed terms is `warmup_period 1`.
| `Trix` | `Trix::new(15)` | `3 * period - 1` | 44 | 44th |
| `AwesomeOscillator` | `AwesomeOscillator::new(5, 34)` | `slow_period` | 34 | 34th |
| `Atr` | `Atr::new(14)` | `period` | 14 | 14th |
| `Psar` | `Psar::new(0.02, 0.20)` | constant `2` | 2 | 2nd |
| `Psar` | `Psar::new(0.02, 0.02, 0.20)` | constant `2` | 2 | 2nd |
| `Obv` | `Obv::new()` | constant `1` | 1 | 1st |
| `Vwap` | `Vwap::new()` | constant `1` | 1 | 1st |
| `RollingVwap` | `RollingVwap::new(20)` | `period` | 20 | 20th |
| `Smma` | `Smma::new(14)` | `period` | 14 | 14th |
| `Trima` | `Trima::new(20)` | `period` | 20 | 20th |
| `Zlema` | `Zlema::new(14)` | `lag + period` (`lag = (period 1) / 2`) | 20 | 20th |
| `T3` | `T3::new(5, 0.7)` | `6 * period - 5` | 25 | 25th |
| `Vwma` | `Vwma::new(20)` | `period` | 20 | 20th |
| `Mom` | `Mom::new(10)` | `period + 1` | 11 | 11th |
| `Cmo` | `Cmo::new(14)` | `period + 1` | 15 | 15th |
| `Tsi` | `Tsi::new(25, 13)` | `long + short` | 38 | 38th |
| `Pmo` | `Pmo::new(35, 20)` | constant `2` | 2 | 2nd |
| `StochRsi` | `StochRsi::new(14, 14)` | `rsi_period + stoch_period` | 28 | 28th |
| `UltimateOscillator` | `UltimateOscillator::new(7, 14, 28)` | `max(short, mid, long) + 1` | 29 | 29th |
| `Ppo` | `Ppo::new(12, 26)` | `slow` | 26 | 26th |
| `Dpo` | `Dpo::new(20)` | `max(period, period / 2 + 2)` | 20 | 20th |
| `Coppock` | `Coppock::new(14, 11, 10)` | `max(roc_long, roc_short) + wma_period` | 24 | 24th |
| `AroonOscillator` | `AroonOscillator::new(14)` | `period + 1` | 15 | 15th |
| `MassIndex` | `MassIndex::new(9, 25)` | `2 * ema_period + sum_period - 2` | 41 | 41st |
| `Natr` | `Natr::new(14)` | `period` | 14 | 14th |
| `StdDev` | `StdDev::new(20)` | `period` | 20 | 20th |
| `UlcerIndex` | `UlcerIndex::new(14)` | `2 * period - 1` | 27 | 27th |
| `HistoricalVolatility` | `HistoricalVolatility::new(20, 252)` | `period + 1` | 21 | 21st |
| `BollingerBandwidth` | `BollingerBandwidth::new(20, 2.0)` | `period` | 20 | 20th |
| `PercentB` | `PercentB::new(20, 2.0)` | `period` | 20 | 20th |
| `AtrTrailingStop` | `AtrTrailingStop::new(14, 3.0)` | `atr_period` | 14 | 14th |
| `Adl` | `Adl::new()` | constant `1` | 1 | 1st |
| `VolumePriceTrend` | `VolumePriceTrend::new()` | constant `1` | 1 | 1st |
| `ChaikinMoneyFlow` | `ChaikinMoneyFlow::new(20)` | `period` | 20 | 20th |
| `ChaikinOscillator` | `ChaikinOscillator::new(3, 10)` | `slow` | 10 | 10th |
| `ForceIndex` | `ForceIndex::new(13)` | `period + 1` | 14 | 14th |
| `EaseOfMovement` | `EaseOfMovement::new(14)` | `period + 1` | 15 | 15th |
| `TypicalPrice` | `TypicalPrice::new()` | constant `1` | 1 | 1st |
| `MedianPrice` | `MedianPrice::new()` | constant `1` | 1 | 1st |
| `WeightedClose` | `WeightedClose::new()` | constant `1` | 1 | 1st |
| `LinearRegression` | `LinearRegression::new(14)` | `period` | 14 | 14th |
| `LinRegSlope` | `LinRegSlope::new(14)` | `period` | 14 | 14th |
## Multi-output indicators
@@ -59,6 +93,10 @@ ready" to "ready" together — there are no rows that have a `signal` but no
| `Aroon` | `Aroon::new(14)` | `period + 1` | 15 | 15th | `up`, `down` |
| `Keltner` | `Keltner::new(20, 10, 2.0)` | `ema_period.max(atr_period)` | 20 | 20th | `upper`, `middle`, `lower` |
| `Donchian` | `Donchian::new(20)` | `period` | 20 | 20th | `upper`, `middle`, `lower` |
| `Vortex` | `Vortex::new(14)` | `period + 1` | 15 | 15th | `plus`, `minus` |
| `SuperTrend` | `SuperTrend::new(10, 3.0)` | `atr_period` | 10 | 10th | `value`, `direction` |
| `ChandelierExit` | `ChandelierExit::new(22, 3.0)` | `period` | 22 | 22nd | `long_stop`, `short_stop` |
| `ChandeKrollStop` | `ChandeKrollStop::new(10, 1.0, 9)` | `atr_period + stop_period - 1` | 18 | 18th | `stop_long`, `stop_short` |
## "Off-by-one" cases worth memorising