2026-05-22 16:17:15 +02:00
|
|
|
|
# Changelog
|
|
|
|
|
|
|
|
|
|
|
|
All notable changes to Wickra are documented in this file.
|
|
|
|
|
|
|
|
|
|
|
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
|
|
|
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
|
|
|
|
|
|
|
|
|
|
## [Unreleased]
|
|
|
|
|
|
|
2026-06-01 14:37:20 +02:00
|
|
|
|
### Added
|
2026-06-01 16:06:22 +02:00
|
|
|
|
- **Microstructure family — order book (part 1).** A new family of indicators
|
|
|
|
|
|
that consume an order-book depth snapshot (`OrderBook` of sorted, uncrossed
|
|
|
|
|
|
bid/ask `Level`s) rather than OHLCV, exposed in Rust, Python, Node and WASM:
|
|
|
|
|
|
- **Order-Book Imbalance** — `OrderBookImbalanceTop1`, `OrderBookImbalanceTopN`
|
|
|
|
|
|
(configurable depth) and `OrderBookImbalanceFull` measure signed depth
|
|
|
|
|
|
pressure `(bidDepth − askDepth) / (bidDepth + askDepth)` over the top level,
|
|
|
|
|
|
the top-N levels, or the full book.
|
|
|
|
|
|
- **Microprice** — the size-weighted fair value
|
|
|
|
|
|
`(bidPx·askSz + askPx·bidSz) / (bidSz + askSz)`, tilting the mid toward the
|
|
|
|
|
|
side more likely to be hit.
|
|
|
|
|
|
- **Quoted Spread** — the top-of-book spread in basis points of the mid.
|
|
|
|
|
|
|
|
|
|
|
|
New public value types `Level`, `OrderBook`, `Side`, `Trade` and `TradeQuote`
|
|
|
|
|
|
back this and the upcoming trade-flow and price-impact indicators. Python and
|
|
|
|
|
|
Node accept a batch over a list of snapshots; WASM exposes per-snapshot
|
|
|
|
|
|
`update`.
|
2026-06-01 14:37:20 +02:00
|
|
|
|
- **Signed Doji encoding.** `Doji` gains an opt-in `.signed()` mode
|
|
|
|
|
|
(`Doji(signed=True)` in Python, `new Doji(true)` in Node and WASM) that
|
|
|
|
|
|
classifies a detected Doji by the position of its body within the bar range —
|
|
|
|
|
|
a dragonfly (long lower shadow) emits `+1.0` (bullish), a gravestone (long
|
|
|
|
|
|
upper shadow) emits `−1.0` (bearish), and a long-legged / standard Doji emits
|
|
|
|
|
|
`0.0` (neutral). The default construction is unchanged — a direction-less
|
|
|
|
|
|
`+1.0` / `0.0` detection flag — so existing callers are unaffected. This
|
|
|
|
|
|
completes the uniform `+1` bull / `−1` bear / `0` none sign convention across
|
|
|
|
|
|
every candlestick pattern, making the family a drop-in machine-learning
|
|
|
|
|
|
feature where bullish and bearish instances share a single dimension.
|
|
|
|
|
|
|
2026-06-01 13:58:50 +02:00
|
|
|
|
## [0.4.1] - 2026-06-01
|
|
|
|
|
|
|
2026-06-01 13:45:21 +02:00
|
|
|
|
### Added
|
|
|
|
|
|
- **Cross-asset pairwise indicators.** A new two-series family of
|
|
|
|
|
|
`Indicator<Input = (f64, f64)>` implementations that relate two distinct
|
|
|
|
|
|
assets rather than a single OHLCV stream. Each is exposed in Rust, Python,
|
|
|
|
|
|
Node, and WASM:
|
|
|
|
|
|
- **Pairwise Beta** (`PairwiseBeta`) — rolling OLS slope of one asset's
|
|
|
|
|
|
**log-returns** on another's. Unlike `Beta`, which regresses the raw inputs
|
|
|
|
|
|
it is fed, `PairwiseBeta` differences consecutive prices into log-returns
|
|
|
|
|
|
internally — the conventional way to measure cross-asset beta, where a beta
|
|
|
|
|
|
on price levels would be dominated by the shared trend.
|
|
|
|
|
|
- **Pair Spread Z-Score** (`PairSpreadZScore`) — the standardised log-spread
|
|
|
|
|
|
`ln(a) − β·ln(b)` of a pair, where `β` is a rolling-OLS hedge ratio and the
|
|
|
|
|
|
spread is z-scored over its own look-back. The canonical mean-reversion /
|
|
|
|
|
|
statistical-arbitrage entry signal, with independent `beta_period` and
|
|
|
|
|
|
`z_period` windows.
|
|
|
|
|
|
- **Lead–Lag Cross-Correlation** (`LeadLagCrossCorrelation`) — the integer
|
|
|
|
|
|
offset `k ∈ [−max_lag, max_lag]` that maximises `|corr(a[t], b[t+k])|`,
|
|
|
|
|
|
answering which of two assets leads the other and by how many bars. Emits
|
|
|
|
|
|
`{ lag, correlation }`; a positive lag means `a` leads `b`.
|
|
|
|
|
|
- **Cointegration** (`Cointegration`) — the Engle–Granger two-step screen for
|
|
|
|
|
|
pairs trading: a rolling OLS hedge ratio `β`, the spread (residual)
|
|
|
|
|
|
`a − (α + β·b)`, and an augmented Dickey–Fuller `t`-statistic on the spread
|
|
|
|
|
|
(configurable `adf_lags`). A strongly negative statistic flags a
|
|
|
|
|
|
mean-reverting, tradeable spread. Emits `{ hedge_ratio, spread, adf_stat }`.
|
|
|
|
|
|
- **Relative Strength A-vs-B** (`RelativeStrengthAB`) — the comparative
|
|
|
|
|
|
relative strength of two assets: the ratio line `a / b` together with its
|
|
|
|
|
|
moving average and its RSI, the classic asset-vs-asset / asset-vs-index
|
|
|
|
|
|
rotation screen. Emits `{ ratio, ratio_ma, ratio_rsi }`.
|
|
|
|
|
|
|
2026-06-01 01:28:53 +02:00
|
|
|
|
## [0.4.0] - 2026-06-01
|
|
|
|
|
|
|
2026-06-01 01:08:14 +02:00
|
|
|
|
### Added
|
|
|
|
|
|
- **Build-provenance attestations for release artifacts.** The release workflow
|
|
|
|
|
|
now emits signed SLSA build-provenance attestations for the published crates
|
|
|
|
|
|
and Python wheels/sdist (`actions/attest-build-provenance`); npm packages
|
|
|
|
|
|
carry inline Sigstore provenance from `npm publish --provenance`. Every
|
|
|
|
|
|
published artifact is cryptographically traceable to this repository's release
|
|
|
|
|
|
workflow run.
|
|
|
|
|
|
|
|
|
|
|
|
### Security
|
|
|
|
|
|
- **CodeQL static analysis and OpenSSF Scorecard run in CI.** CodeQL (Rust,
|
|
|
|
|
|
Python, JavaScript) and the OpenSSF Scorecard workflow now run on every push;
|
|
|
|
|
|
results appear under Security → Code scanning and a public Scorecard badge is
|
|
|
|
|
|
shown in the README.
|
|
|
|
|
|
- **CI workflows hardened against script injection.** Untrusted event contexts
|
|
|
|
|
|
(PR branch names, `workflow_dispatch` inputs) are passed through the step
|
|
|
|
|
|
environment instead of being interpolated directly into shell commands.
|
|
|
|
|
|
|
2026-05-31 05:22:56 +02:00
|
|
|
|
### Changed
|
|
|
|
|
|
- **Node binding: invalid indicator periods now throw instead of being silently
|
|
|
|
|
|
clamped.** The scalar-indicator constructors previously clamped `period = 0`
|
|
|
|
|
|
to `1`; every Node constructor now propagates the core's validation error
|
|
|
|
|
|
(e.g. `period must be greater than zero`), matching the Python and WASM
|
|
|
|
|
|
bindings and the Rust core. Constructing with a valid period is unaffected.
|
2026-05-31 05:30:34 +02:00
|
|
|
|
- **Binding package READMEs are now per-ecosystem.** The Python, Node.js, and
|
|
|
|
|
|
WebAssembly READMEs were byte-identical 314-line copies of the workspace
|
|
|
|
|
|
README and had drifted out of sync (stale indicator count, Python snippets
|
|
|
|
|
|
shown on the Node and WASM package pages). Each is now a focused landing page
|
|
|
|
|
|
with the correct install command, a language-correct quick-start snippet, and
|
|
|
|
|
|
links to the canonical documentation — removing the manual three-way sync
|
|
|
|
|
|
burden. No code or API changes.
|
|
|
|
|
|
- **CONTRIBUTING now states the correct MSRV (1.86 workspace / 1.88
|
|
|
|
|
|
`bindings/node`)** and documents that these are the dependency-forced floors,
|
|
|
|
|
|
kept minimal on purpose. The previous text claimed 1.75 / 1.77, which the
|
|
|
|
|
|
`msrv` CI job has enforced against since the criterion and napi-build bumps.
|
2026-05-31 05:22:56 +02:00
|
|
|
|
|
2026-05-30 19:50:45 +02:00
|
|
|
|
## [0.3.1] - 2026-05-30
|
|
|
|
|
|
|
|
|
|
|
|
### Fixed
|
|
|
|
|
|
- **Release pipeline — CycloneDX SBOM generation.** `cargo-cyclonedx` has no
|
|
|
|
|
|
`-p`/`--package` selector; it walks the whole workspace in a single pass.
|
|
|
|
|
|
The `release.yml` SBOM step invoked it as `cargo cyclonedx … -p <crate>` and
|
|
|
|
|
|
aborted with `error: unexpected argument '-p' found`, which failed the
|
|
|
|
|
|
crates.io publish job *after* the crates were already published and skipped
|
|
|
|
|
|
the GitHub Release attach-assets job (no release page, no SBOM artefacts).
|
|
|
|
|
|
The step now runs a single workspace pass and collects the three crates.io
|
|
|
|
|
|
crate SBOMs. No library changes relative to 0.3.0 — this patch republishes
|
|
|
|
|
|
the same code with a working release pipeline.
|
|
|
|
|
|
|
|
|
|
|
|
## [0.3.0] - 2026-05-30
|
|
|
|
|
|
|
2026-05-25 15:01:14 +02:00
|
|
|
|
### Added
|
2026-05-26 20:44:21 +02:00
|
|
|
|
- **Family 15 — Risk / Performance metrics (17 new indicators).** Implemented
|
|
|
|
|
|
pragmatically as standard `Indicator`s rather than a separate
|
|
|
|
|
|
`wickra-metrics` crate; the input is a scalar `f64` per bar (period return,
|
|
|
|
|
|
equity sample, or trade P&L depending on the metric).
|
|
|
|
|
|
- **Scalar `Indicator<f64>` — 14 metrics:** Sharpe Ratio, Sortino Ratio,
|
|
|
|
|
|
Calmar Ratio, Omega Ratio, Max Drawdown (rolling), Average Drawdown,
|
|
|
|
|
|
Drawdown Duration (time-under-water), Pain Index, Value at Risk
|
|
|
|
|
|
(historical, linear-interpolated percentile), Conditional Value at Risk
|
|
|
|
|
|
(Expected Shortfall), Profit Factor, Gain/Loss Ratio, Recovery Factor,
|
|
|
|
|
|
Kelly Criterion.
|
|
|
|
|
|
- **Two-series `Indicator<(f64, f64)>` — 3 metrics on `(asset_return,
|
|
|
|
|
|
benchmark_return)` pairs:** Treynor Ratio, Information Ratio,
|
|
|
|
|
|
Jensen's Alpha (CAPM).
|
2026-05-26 00:54:11 +02:00
|
|
|
|
- **Candlestick patterns family (15 indicators).** A new "Candlestick
|
|
|
|
|
|
Patterns" family covers the standard 1- to 3-bar reversal and
|
|
|
|
|
|
continuation shapes: `Doji`, `Hammer`, `InvertedHammer`, `HangingMan`,
|
|
|
|
|
|
`ShootingStar`, `Engulfing`, `Harami`, `MorningEveningStar`,
|
|
|
|
|
|
`ThreeSoldiersOrCrows`, `PiercingDarkCloud`, `Marubozu`, `Tweezer`,
|
|
|
|
|
|
`SpinningTop`, `ThreeInside` and `ThreeOutside`. Every detector takes a
|
|
|
|
|
|
`Candle` and emits a signed `f64` (`+1.0` bullish, `-1.0` bearish, `0.0`
|
|
|
|
|
|
no pattern; `Doji` is direction-less and emits `+1.0`/`0.0`). The MVP is
|
|
|
|
|
|
a pattern-shape check only — no trend filter is applied. Available
|
|
|
|
|
|
across Rust, Python, Node and WASM bindings. Harmonic and chart
|
|
|
|
|
|
patterns remain out of scope and will follow once the pattern-detection
|
|
|
|
|
|
framework (pivot detector + multi-bar state machines) lands.
|
2026-05-26 00:14:30 +02:00
|
|
|
|
- **Market Profile family** (3 new indicators, opens family #9 across the
|
|
|
|
|
|
catalogue):
|
|
|
|
|
|
- `ValueArea(period, bin_count, value_area_pct)` — rolling
|
|
|
|
|
|
bin-approximation volume profile over the last `period` candles.
|
|
|
|
|
|
Outputs `{poc, vah, val}`: Point of Control is the bin with the highest
|
|
|
|
|
|
cumulative volume; the Value Area expands symmetrically from POC and
|
|
|
|
|
|
always absorbs the higher-volume neighbour next, until the configured
|
|
|
|
|
|
percentage of total volume (default 70%) is enclosed. Each candle's
|
|
|
|
|
|
volume is spread uniformly across its `[low, high]` range; single-print
|
|
|
|
|
|
bars (`low == high`) drop their entire volume into one bin.
|
|
|
|
|
|
- `InitialBalance(period)` — first-N-bar session high / low, frozen
|
|
|
|
|
|
once `period` bars have been ingested. Outputs `{high, low}`. Default
|
|
|
|
|
|
`period = 12` (one-hour IB on 5-minute bars for US equities). Callers
|
|
|
|
|
|
MUST invoke `reset()` at every session boundary, otherwise the IB
|
|
|
|
|
|
locks and stays fixed for the lifetime of the instance.
|
|
|
|
|
|
- `OpeningRange(period)` — same lock-after-N-bars semantics as IB but
|
|
|
|
|
|
with a smaller default window (`period = 6`, 30 min on 5-minute
|
|
|
|
|
|
bars) and a third output `breakout_distance` = `close - or_mid`,
|
|
|
|
|
|
signed (positive above the range, negative below).
|
|
|
|
|
|
- Histogram-output Market Profile variants (Volume Profile / VPVR /
|
|
|
|
|
|
Composite Profile) and tick-data-only variants (TPO / Single Print /
|
|
|
|
|
|
Cumulative Delta / Order Flow Delta / Volume-Weighted Open) are
|
|
|
|
|
|
deliberately out of scope of this PR: the former need a new
|
|
|
|
|
|
histogram-output API layer, the latter need tick / L2 data which
|
|
|
|
|
|
`wickra-data` does not yet expose.
|
2026-05-25 23:42:05 +02:00
|
|
|
|
- **Family 12 — Statistik / Regression (13 indicators).** A complete
|
|
|
|
|
|
statistical toolkit for analysing rolling price distributions and
|
|
|
|
|
|
cross-series relationships. Every indicator ships in the Rust core
|
|
|
|
|
|
plus all three bindings (Python, Node, WASM), with full streaming +
|
|
|
|
|
|
batch parity, fuzz coverage, and benches against the BTCUSDT
|
|
|
|
|
|
dataset:
|
|
|
|
|
|
- **Variance** — rolling population variance (`StdDev` squared).
|
|
|
|
|
|
- **CoefficientOfVariation** — `StdDev / Mean`, dimensionless dispersion.
|
|
|
|
|
|
- **Skewness** — rolling third standardised moment (Pearson skewness).
|
|
|
|
|
|
- **Kurtosis** — rolling excess kurtosis (fourth moment minus `3`).
|
|
|
|
|
|
- **StandardError** — standard error of estimate for the rolling OLS
|
|
|
|
|
|
fit, with `n − 2` residual degrees of freedom.
|
|
|
|
|
|
- **DetrendedStdDev** — population standard deviation of OLS
|
|
|
|
|
|
residuals (the StdDev that remains after subtracting the linear
|
|
|
|
|
|
trend).
|
|
|
|
|
|
- **RSquared** — coefficient of determination of the rolling OLS
|
|
|
|
|
|
fit; the trend-quality filter.
|
|
|
|
|
|
- **MedianAbsoluteDeviation** — robust dispersion measure that
|
|
|
|
|
|
survives outliers (median of absolute deviations from the median).
|
|
|
|
|
|
- **Autocorrelation** — rolling lag-`k` Pearson autocorrelation;
|
|
|
|
|
|
detects periodicity and tests for white-noise behaviour.
|
|
|
|
|
|
- **HurstExponent** — R/S-analysis estimator of trend-persistence
|
|
|
|
|
|
vs. mean-reversion regime (`0.5` is random walk).
|
|
|
|
|
|
- **PearsonCorrelation** — rolling correlation between two
|
|
|
|
|
|
synchronised series; takes `(x, y)` pairs.
|
|
|
|
|
|
- **Beta** — rolling OLS slope of an asset on a benchmark; the CAPM
|
|
|
|
|
|
sensitivity coefficient.
|
|
|
|
|
|
- **SpearmanCorrelation** — rolling rank correlation (monotone,
|
|
|
|
|
|
outlier-robust analogue of Pearson).
|
|
|
|
|
|
|
|
|
|
|
|
Indicator count: 71 → 84.
|
2026-05-25 23:02:29 +02:00
|
|
|
|
- **Family 13 — Ichimoku & alternative charts.** Two new indicators:
|
|
|
|
|
|
- `Ichimoku` (Ichimoku Kinko Hyo) — the full five-line cloud system
|
|
|
|
|
|
(Tenkan-sen, Kijun-sen, Senkou Span A/B, Chikou Span) with the
|
|
|
|
|
|
classic `(9, 26, 52, 26)` defaults and configurable periods. Forward
|
|
|
|
|
|
displacement is handled in a streaming ring buffer so the
|
|
|
|
|
|
currently-visible Senkou A/B at bar *n* are the values computed
|
|
|
|
|
|
from bar *n − displacement*.
|
|
|
|
|
|
- `HeikinAshi` — the candle smoothing transform that recursively
|
|
|
|
|
|
averages OHLC into a four-component output (`ha_open`, `ha_high`,
|
|
|
|
|
|
`ha_low`, `ha_close`). Seeds `ha_open` from the first bar's
|
|
|
|
|
|
`(open + close) / 2`.
|
|
|
|
|
|
|
|
|
|
|
|
Exposed in all four bindings (Rust, Python, Node, WASM). Renko,
|
|
|
|
|
|
Kagi, and Point & Figure from the family ideas list are deferred:
|
|
|
|
|
|
they are custom bar generators rather than indicators and belong in
|
|
|
|
|
|
`wickra-data`.
|
2026-05-25 22:14:27 +02:00
|
|
|
|
- **Family 10 — Ehlers / Cycle (DSP) indicators.** 16 new
|
|
|
|
|
|
streaming-first indicators implementing John Ehlers'
|
|
|
|
|
|
digital-signal-processing school of cycle analytics — a strong
|
|
|
|
|
|
differentiation feature versus TA-Lib and pandas-ta, which only
|
|
|
|
|
|
ship fragments of this catalogue:
|
|
|
|
|
|
- **MAMA / FAMA** (MESA Adaptive Moving Average + Following
|
|
|
|
|
|
Adaptive Moving Average) — phase-rate-adaptive smoothing pair
|
|
|
|
|
|
from the 2001 MESA paper, exposed both jointly via `Mama` (multi-
|
|
|
|
|
|
output) and as a scalar `Fama` wrapper.
|
|
|
|
|
|
- **Fisher Transform** and **Inverse Fisher Transform** — Gaussian
|
|
|
|
|
|
normalisation of price (Ehlers 2002) and its tanh-based bounded
|
|
|
|
|
|
counterpart for oscillators.
|
|
|
|
|
|
- **SuperSmoother**, **Roofing Filter**, **Decycler** and **Decycler
|
|
|
|
|
|
Oscillator** — 2-pole Butterworth lowpass, bandpass and
|
|
|
|
|
|
high-pass complement building blocks from *Cycle Analytics for
|
|
|
|
|
|
Traders* (2013).
|
|
|
|
|
|
- **Hilbert Dominant Cycle**, **Sine Wave** and **Adaptive Cycle**
|
|
|
|
|
|
— Hilbert-transform-based period estimation from *Rocket Science
|
|
|
|
|
|
for Traders* (2001).
|
|
|
|
|
|
- **Center of Gravity**, **Cybernetic Cycle Component**,
|
|
|
|
|
|
**Instantaneous Trendline**, **Ehlers Stochastic** and
|
|
|
|
|
|
**Empirical Mode Decomposition** — EasyLanguage classics from
|
|
|
|
|
|
Ehlers' published catalogue.
|
|
|
|
|
|
- All sixteen are exposed across Rust, Python, Node.js and WASM
|
|
|
|
|
|
bindings, fuzz-tested, benchmarked against real BTCUSDT
|
|
|
|
|
|
1-minute data, and pass `batch == streaming` equivalence.
|
|
|
|
|
|
- Indicator count rises from 71 to **87** across **nine** families.
|
2026-05-25 20:36:36 +02:00
|
|
|
|
- **DeMark family (family 11) — 12 new indicators.** TD Setup (9-bar
|
|
|
|
|
|
buy/sell setup counter with parameterised lookback and target), TD
|
|
|
|
|
|
Sequential (Setup + Countdown phase machine emitting setup count,
|
|
|
|
|
|
countdown count and active countdown direction), TD DeMarker
|
|
|
|
|
|
(bounded [0, 1] range oscillator built from high/low expansions),
|
|
|
|
|
|
TD REI (Range Expansion Index — bounded ±100 oscillator with the
|
|
|
|
|
|
classic 5-bar default), TD Pressure (volume-weighted buying /
|
|
|
|
|
|
selling pressure normalised to ±100), TD Combo (aggressive
|
|
|
|
|
|
countdown variant with extra monotone-low / monotone-close
|
|
|
|
|
|
strictness conditions on top of the classic countdown rule), TD
|
|
|
|
|
|
Countdown (standalone 13-bar countdown phase machine emitting
|
|
|
|
|
|
only the signed countdown count and direction — smaller streaming
|
|
|
|
|
|
payload than the full TD Sequential), TD Lines (TDST horizontal
|
|
|
|
|
|
support / resistance levels derived from the highs and lows of
|
|
|
|
|
|
the most-recently-completed setup), TD Range Projection (next-bar
|
|
|
|
|
|
high / low projection from the current bar's OHLC via DeMark's
|
|
|
|
|
|
open-vs-close-weighted pivot), TD Differential (2-bar
|
|
|
|
|
|
buying-pressure-vs-selling-pressure reversal pattern emitting
|
|
|
|
|
|
+1 / -1 / 0), TD Open (gap-and-fade reversal pattern emitting
|
|
|
|
|
|
+1 / -1 / 0 when the open prints outside the prior bar's range
|
|
|
|
|
|
but the subsequent action recovers back into it), and TD Risk
|
|
|
|
|
|
Level (protective stop levels derived from the lowest-low / highest-
|
|
|
|
|
|
high setup bar's true range). All twelve are exposed through the
|
|
|
|
|
|
Rust, Python, Node, and WASM bindings with `batch == streaming`
|
|
|
|
|
|
equivalence tests, candle-stream fuzz coverage, and benchmark
|
|
|
|
|
|
entries on the BTCUSDT 1-minute dataset.
|
2026-05-25 20:06:46 +02:00
|
|
|
|
- **Family 08 — Pivots & Support/Resistance.** Seven new indicators land
|
|
|
|
|
|
the previously empty pivot family: Classic (Floor-Trader) Pivot Points
|
|
|
|
|
|
with three resistance and support tiers, Fibonacci Pivots spaced by
|
|
|
|
|
|
0.382 / 0.618 / 1.000 of the prior range, Camarilla Pivots
|
|
|
|
|
|
(Nick Stott's four-tier `(H − L) · 1.1 / {12, 6, 4, 2}` levels),
|
|
|
|
|
|
Woodie Pivots with the close-weighted `PP = (H + L + 2·C) / 4`,
|
|
|
|
|
|
DeMark Pivots whose conditional `X` depends on whether the bar closed
|
|
|
|
|
|
up, down or flat, Williams Fractals as a five-bar swing detector and
|
|
|
|
|
|
ZigZag as a percent-threshold swing tracker. Every level/swing is
|
|
|
|
|
|
exposed across Rust, Python, Node and WASM with the standard
|
|
|
|
|
|
`update` / `batch` / `reset` / `is_ready` / `warmup_period` surface
|
|
|
|
|
|
and matching streaming-vs-batch and reference-value tests. The fuzz
|
|
|
|
|
|
candle target now covers all seven.
|
2026-05-25 19:36:14 +02:00
|
|
|
|
- **Family 09 — Trailing Stops, seven new indicators.** Rounds out the
|
|
|
|
|
|
trailing-stop family from 5 to 12: `HiLoActivator` (Crabel's
|
|
|
|
|
|
SMA-of-high / SMA-of-low trail), `VoltyStop` (Cynthia Kase's
|
|
|
|
|
|
extreme-anchor ATR stop), `YoyoExit` (long-only ATR trail with a
|
|
|
|
|
|
re-entry trigger), `DonchianStop` (the original Turtle exit, lowest
|
|
|
|
|
|
low / highest high), `PercentageTrailingStop` (fixed-percent trail),
|
|
|
|
|
|
`StepTrailingStop` (round-number grid trail) and `RenkoTrailingStop`
|
|
|
|
|
|
(block-anchored Renko-style trail). All wired into the four bindings
|
|
|
|
|
|
(Rust, Python, Node, WASM), the streaming + batch fuzz targets, and
|
|
|
|
|
|
the bench harness.
|
2026-05-25 19:15:22 +02:00
|
|
|
|
- **Klinger Volume Oscillator (KVO).** Stephen J. Klinger's trend-aware
|
|
|
|
|
|
volume-force oscillator: `EMA(vf, fast) − EMA(vf, slow)` over a daily
|
|
|
|
|
|
volume force scaled by cumulative-measurement ratio. Classic
|
|
|
|
|
|
`(fast, slow) = (34, 55)` exposed via `Kvo::classic()`.
|
|
|
|
|
|
- **Volume Oscillator (VO).** Percent difference between a fast and a
|
|
|
|
|
|
slow SMA of bar volume: `100 · (SMA(vol, fast) − SMA(vol, slow)) /
|
|
|
|
|
|
SMA(vol, slow)`. Default `(14, 28)`.
|
|
|
|
|
|
- **Negative Volume Index (NVI).** Paul Dysart's cumulative index that
|
|
|
|
|
|
only updates on volume-contraction bars (`volume_t < volume_{t−1}`),
|
|
|
|
|
|
absorbing the percent close change on those quiet days. Fosback
|
|
|
|
|
|
baseline `1000.0`, configurable via `Nvi::with_baseline`.
|
|
|
|
|
|
- **Positive Volume Index (PVI).** The complementary index that
|
|
|
|
|
|
updates on volume-expansion bars (`volume_t > volume_{t−1}`).
|
|
|
|
|
|
- **Williams Accumulation/Distribution.** Larry Williams' volume-less
|
|
|
|
|
|
cumulative flow that anchors to the previous close (true high/low) and
|
|
|
|
|
|
classifies each bar as accumulation, distribution, or neutral by the
|
|
|
|
|
|
sign of the close-to-close change.
|
|
|
|
|
|
- **Anchored VWAP.** A cumulative VWAP whose accumulation begins at a
|
|
|
|
|
|
user-chosen anchor bar rather than the session open. Re-anchor at
|
|
|
|
|
|
runtime via `AnchoredVwap::set_anchor` for click-to-anchor trader
|
|
|
|
|
|
workflows.
|
|
|
|
|
|
- **Demand Index (Sibbet).** James Sibbet's smoothed buying-vs-selling
|
|
|
|
|
|
pressure ratio in the streaming-friendly textbook form
|
|
|
|
|
|
`EMA(volume · close-return · (1 + range/close), period)`.
|
|
|
|
|
|
- **Time Segmented Volume (TSV).** Don Worden's rolling sum of signed
|
|
|
|
|
|
volume weighted by the close-to-close move: a window-sum measure of
|
|
|
|
|
|
net accumulation/distribution.
|
|
|
|
|
|
- **Volume Zone Oscillator (VZO).** Walid Khalil's normalised
|
|
|
|
|
|
volume-flow oscillator bounded in `[−100, 100]`, defined as
|
|
|
|
|
|
`100 · EMA(signed_volume) / EMA(volume)`.
|
|
|
|
|
|
- **Market Facilitation Index (Bill Williams).** Per-bar
|
|
|
|
|
|
`(high − low) / volume` — how much price movement the market produces
|
|
|
|
|
|
per unit of volume.
|
2026-05-25 19:00:13 +02:00
|
|
|
|
- **ADXR (Average Directional Movement Index Rating)** in the Trend &
|
|
|
|
|
|
Directional family. Wilder's directional-strength smoother: the
|
|
|
|
|
|
average of the current `ADX` and the `ADX` from `period - 1` bars
|
|
|
|
|
|
ago. Warmup is `3 * period - 1` (e.g. 41 for the default `period =
|
|
|
|
|
|
14`). Shipped across all four bindings (Rust core, Python, Node,
|
|
|
|
|
|
WASM) plus fuzz/test/bench coverage.
|
|
|
|
|
|
- **Random Walk Index (RWI)** in the Trend & Directional family. Mike
|
|
|
|
|
|
Poulos' trend-vs.-random-walk gauge: for each lookback `i ∈ [2,
|
|
|
|
|
|
period]` the ratio of actual displacement to the random-walk
|
|
|
|
|
|
expectation `ATR_i * sqrt(i)` is taken; the per-bar output is the
|
|
|
|
|
|
maximum across lookbacks for both the high (`RWI_High`) and low
|
|
|
|
|
|
(`RWI_Low`) directions. Multi-output `(high, low)` across all four
|
|
|
|
|
|
bindings; warmup `= period`.
|
|
|
|
|
|
- **Trend Intensity Index (TII)** in the Trend & Directional family.
|
|
|
|
|
|
M.H. Pee's `[0, 100]` oscillator: the share of the most recent
|
|
|
|
|
|
`dev_period` SMA-deviations that are positive, scaled to
|
|
|
|
|
|
`[0, 100]`. Saturates at 100 on a pure uptrend, at 0 on a pure
|
|
|
|
|
|
downtrend, and returns the neutral 50 on a perfectly flat market.
|
|
|
|
|
|
Canonical Python defaults `(sma_period=60, dev_period=30)`; warmup
|
|
|
|
|
|
`= sma_period + dev_period − 1`.
|
|
|
|
|
|
- **Wave Trend Oscillator (LazyBear)** in the Trend & Directional
|
|
|
|
|
|
family. Two-line mean-reverting momentum gauge built from the
|
|
|
|
|
|
typical price and three cascaded EMAs:
|
|
|
|
|
|
`esa = EMA(ap, channel)`, `d = EMA(|ap − esa|, channel)`,
|
|
|
|
|
|
`ci = (ap − esa) / (0.015 · d)`, `wt1 = EMA(ci, average)`,
|
|
|
|
|
|
`wt2 = SMA(wt1, signal)`. `WaveTrend::classic()` exposes the
|
|
|
|
|
|
LazyBear defaults `(channel = 10, average = 21, signal = 4)`;
|
|
|
|
|
|
warmup `= 2 · channel + average + signal − 3` (42 for the classic
|
|
|
|
|
|
defaults). Includes a sub-ULP flat-tolerance guard on `ci` so a
|
|
|
|
|
|
perfectly flat market reports `(0, 0)` instead of the
|
|
|
|
|
|
mathematically indeterminate `−1 / 0.015 = −66.67`. Multi-output
|
|
|
|
|
|
`(wt1, wt2)` across all four bindings.
|
2026-05-25 18:37:12 +02:00
|
|
|
|
- **Family 05 — Bands & Channels (11 new indicators).** Eleven additional
|
|
|
|
|
|
price-envelope overlays organised into the new "Bands & Channels"
|
|
|
|
|
|
family, exposed across all four bindings (Rust, Python, Node, WASM):
|
|
|
|
|
|
- `MaEnvelope` — SMA centerline with fixed-percent envelope (the oldest
|
|
|
|
|
|
band overlay still in use).
|
|
|
|
|
|
- `AccelerationBands` — Price Headley's momentum-biased bands that widen
|
|
|
|
|
|
with the bar's relative range `(H − L) / (H + L)`.
|
|
|
|
|
|
- `StarcBands` — Stoller Average Range Channel: SMA(close) ± k·ATR
|
|
|
|
|
|
(Keltner's SMA-centerline sibling).
|
|
|
|
|
|
- `AtrBands` — Close-anchored envelope of width `k · ATR`, the standard
|
|
|
|
|
|
volatility-targeting stop/target band.
|
|
|
|
|
|
- `HurstChannel` — SMA centerline wrapped by the rolling high-low range
|
|
|
|
|
|
(Brian Millard / Hurst-cycle channel).
|
|
|
|
|
|
- `LinRegChannel` — Linear-regression endpoint ± k·σ of the residuals,
|
|
|
|
|
|
measuring dispersion about the *trend* rather than the mean.
|
|
|
|
|
|
- `StandardErrorBands` — Linear regression with the OLS standard error
|
|
|
|
|
|
(denominator `n − 2`) for prediction-interval bands.
|
|
|
|
|
|
- `DoubleBollinger` — Kathy Lien's `±1σ` plus `±2σ` zone-partition setup.
|
|
|
|
|
|
- `TtmSqueeze` — John Carter's BB-inside-KC squeeze flag paired with a
|
|
|
|
|
|
detrended-close momentum reading.
|
|
|
|
|
|
- `FractalChaosBands` — Bill Williams 5-bar fractal high/low envelope.
|
|
|
|
|
|
- `VwapStdDevBands` — Cumulative VWAP with volume-weighted standard
|
|
|
|
|
|
deviation bands.
|
|
|
|
|
|
Indicator count rises from 71 to 82 across nine families; the README
|
|
|
|
|
|
family table and the wiki overview/sidebar/warmup pages were updated to
|
|
|
|
|
|
match.
|
2026-05-25 18:18:20 +02:00
|
|
|
|
- **Yang-Zhang Volatility.** Yang & Zhang (2000) gold-standard OHLC
|
|
|
|
|
|
estimator: a convex blend of overnight (close-to-open), open-to-close
|
|
|
|
|
|
and Rogers-Satchell variances. The blending factor
|
|
|
|
|
|
`k = 0.34 / (1.34 + (n+1)/(n-1))` is the one that minimises
|
|
|
|
|
|
estimator variance under driftless GBM with overnight gaps. The
|
|
|
|
|
|
overnight and open-to-close pieces use sample variance (Bessel's
|
|
|
|
|
|
correction, divisor `n−1`), so the indicator needs `period + 1` bars
|
|
|
|
|
|
to emit. Output annualised to a percent. Defaults: `period = 20`,
|
|
|
|
|
|
`trading_periods = 252`. The recommended OHLC estimator for equities,
|
|
|
|
|
|
futures, and any asset with material close-to-open gaps.
|
|
|
|
|
|
- **Rogers-Satchell Volatility.** Drift-free OHLC realised-volatility
|
|
|
|
|
|
estimator from Rogers, Satchell & Yoon (1994). Per-bar sample is
|
|
|
|
|
|
`ln(H/C)·ln(H/O) + ln(L/C)·ln(L/O)`; every term is non-negative by
|
|
|
|
|
|
construction (high >= open, close; low <= open, close), so the
|
|
|
|
|
|
rolling mean is exact, not biased, under arbitrary drift. The
|
|
|
|
|
|
algebraic drift-cancellation is what differentiates it from
|
|
|
|
|
|
Garman-Klass. Output annualised to a percent. Defaults:
|
|
|
|
|
|
`period = 20`, `trading_periods = 252`.
|
|
|
|
|
|
- **Garman-Klass Volatility.** Garman & Klass (1980) OHLC realised
|
|
|
|
|
|
volatility estimator: per-bar sample is
|
|
|
|
|
|
`0.5·(ln H/L)² − (2·ln2 − 1)·(ln C/O)²`, then take the annualised
|
|
|
|
|
|
square root of the rolling mean. Roughly 7.4× more statistically
|
|
|
|
|
|
efficient than close-to-close stddev under driftless GBM. Output
|
|
|
|
|
|
annualised to a percent. Defaults: `period = 20`,
|
|
|
|
|
|
`trading_periods = 252`.
|
|
|
|
|
|
- **Parkinson Volatility.** Michael Parkinson's (1980) high-low realised
|
|
|
|
|
|
volatility estimator: `sigma² = (1 / (4n·ln2)) · Σ (ln(H/L))²`. Output
|
|
|
|
|
|
annualised to a percent in the same style as `HistoricalVolatility`
|
|
|
|
|
|
(pass `trading_periods = 1` for the raw per-bar `sigma·100` figure).
|
|
|
|
|
|
Roughly 5× more statistically efficient than close-to-close stddev
|
|
|
|
|
|
under a driftless-GBM assumption. Defaults: `period = 20`,
|
|
|
|
|
|
`trading_periods = 252`.
|
|
|
|
|
|
- **RVIVolatility (Relative Volatility Index).** Donald Dorsey's
|
|
|
|
|
|
RSI-shaped volatility gauge: partition the rolling standard
|
|
|
|
|
|
deviation of close into "up" (close rose) and "down" (close fell)
|
|
|
|
|
|
samples, Wilder-smooth each side, and compute
|
|
|
|
|
|
`100 · AvgUp / (AvgUp + AvgDown)`. Bounded on `[0, 100]`; saturates
|
|
|
|
|
|
at `100` in pure uptrends, `0` in pure downtrends, and falls back to
|
|
|
|
|
|
`50` on a completely flat series (same undefined-RS convention as
|
|
|
|
|
|
`RSI`). Single `period` parameter (default `10`) drives both the
|
|
|
|
|
|
stddev window and the Wilder smoothing. Named `RVIVolatility` rather
|
|
|
|
|
|
than plain `RVI` to disambiguate from Relative Vigor Index, which
|
|
|
|
|
|
ships in Family 02 under the shorter `RVI` name.
|
2026-05-25 17:26:46 +02:00
|
|
|
|
- **Family 03 — MACD & Price Oscillators.** `Stc` (Schaff Trend Cycle,
|
|
|
|
|
|
Doug Schaff): doubly-`Stochastic`-smoothed MACD producing a bounded
|
|
|
|
|
|
`[0, 100]` reading that reacts faster than `MACD` itself. Four
|
|
|
|
|
|
parameters `(fast = 23, slow = 50, schaff_period = 10, factor = 0.5)`.
|
|
|
|
|
|
Output is clamped to `[0, 100]` to absorb floating-point rounding.
|
|
|
|
|
|
Exposed in all four bindings.
|
|
|
|
|
|
- **Family 03 — MACD & Price Oscillators.** `ElderImpulse` (Alexander
|
|
|
|
|
|
Elder's Impulse System): tri-state momentum gauge combining `EMA`
|
|
|
|
|
|
trend slope with `MACD` histogram slope. Returns `+1` (green/buy)
|
|
|
|
|
|
when both rise, `−1` (red/sell) when both fall, `0` (blue/neutral)
|
|
|
|
|
|
on disagreement. Four parameters
|
|
|
|
|
|
`(ema_period, macd_fast, macd_slow, macd_signal)`; defaults
|
|
|
|
|
|
`(13, 12, 26, 9)` track *Come Into My Trading Room*. Exposed in all
|
|
|
|
|
|
four bindings.
|
|
|
|
|
|
- **Family 03 — MACD & Price Oscillators.** `ZeroLagMacd`: classic
|
|
|
|
|
|
MACD topology with `ZLEMA` substituted for `EMA` everywhere — faster
|
|
|
|
|
|
reaction to trend changes at the cost of slightly noisier readings.
|
|
|
|
|
|
Multi-output `ZeroLagMacdOutput { macd, signal, histogram }`. Three
|
|
|
|
|
|
parameters `(fast = 12, slow = 26, signal = 9)`; `fast` must be
|
|
|
|
|
|
strictly less than `slow`. Exposed in all four bindings.
|
|
|
|
|
|
- **Family 03 — MACD & Price Oscillators.** `CFO` (Chande Forecast
|
|
|
|
|
|
Oscillator): `100 · (close − LinReg(close, period)) / close`. Positive
|
|
|
|
|
|
when the close overshoots the linear forecast, negative when it
|
|
|
|
|
|
undershoots. Holds the previous value if the close is zero. Default
|
|
|
|
|
|
period 14. Exposed in all four bindings.
|
|
|
|
|
|
- **Family 03 — MACD & Price Oscillators.** `AwesomeOscillatorHistogram`:
|
|
|
|
|
|
`AO − SMA(AO, sma_period)`. A configurable variant of the existing
|
|
|
|
|
|
`AcceleratorOscillator` (which fixes `(fast, slow, sma) = (5, 34, 5)`).
|
|
|
|
|
|
Three parameters; defaults match Bill Williams' Accelerator. Exposed
|
|
|
|
|
|
in all four bindings.
|
|
|
|
|
|
- **Family 03 — MACD & Price Oscillators.** `APO` (Absolute Price
|
|
|
|
|
|
Oscillator): `EMA(close, fast) − EMA(close, slow)`. Like MACD's line
|
|
|
|
|
|
without the signal EMA. Default `(fast = 12, slow = 26)`. `fast` must
|
|
|
|
|
|
be strictly less than `slow`. Exposed in all four bindings.
|
2026-05-25 15:28:56 +02:00
|
|
|
|
- **Family 02 — Momentum Oscillators.** `Inertia` (Dorsey): a
|
|
|
|
|
|
`LinearRegression` smoothing of the `RVI` series — preserves trend
|
|
|
|
|
|
direction while damping the underlying ratio. Candle input, two
|
|
|
|
|
|
parameters `(rvi_period, linreg_period)` (defaults 14 / 20). Exposed
|
|
|
|
|
|
in all four bindings.
|
|
|
|
|
|
- **Family 02 — Momentum Oscillators.** `ConnorsRsi`: Larry Connors'
|
|
|
|
|
|
3-component aggregate — `RSI(close)`, `RSI(streak)`, and the
|
|
|
|
|
|
percentile rank of the 1-bar return over the recent `period_rank`
|
|
|
|
|
|
returns. Bounded in `[0, 100]`. Three parameters
|
|
|
|
|
|
`(period_rsi, period_streak, period_rank)` (defaults 3 / 2 / 100).
|
|
|
|
|
|
Exposed in all four bindings.
|
|
|
|
|
|
- **Family 02 — Momentum Oscillators.** `LaguerreRsi` (Ehlers):
|
|
|
|
|
|
four-stage Laguerre polynomial filter wrapped in an RSI-style up/down
|
|
|
|
|
|
accumulator. Single parameter `gamma` in `[0, 1]` (default 0.5) trades
|
|
|
|
|
|
lag for smoothness. State is seeded to the first input so a constant
|
|
|
|
|
|
series stays at the neutral 50. Output clamped to `[0, 100]`. Exposed
|
|
|
|
|
|
in all four bindings.
|
|
|
|
|
|
- **Family 02 — Momentum Oscillators.** `SMI` (Stochastic Momentum
|
|
|
|
|
|
Index, Blau): doubly-`EMA`-smoothed bounded oscillator measuring the
|
|
|
|
|
|
close's displacement from the centre of the recent high-low range,
|
|
|
|
|
|
scaled by the smoothed range. Candle input, three parameters
|
|
|
|
|
|
`(period, d_period, d2_period)` (defaults 5 / 3 / 3). Exposed in all
|
|
|
|
|
|
four bindings.
|
|
|
|
|
|
- **Family 02 — Momentum Oscillators.** `KST` (Know Sure Thing, Pring):
|
|
|
|
|
|
weighted sum of four `SMA`-smoothed `ROC` series with Pring's fixed
|
|
|
|
|
|
weights `1, 2, 3, 4`, plus an `SMA` signal line. Nine parameters
|
|
|
|
|
|
(four ROC periods, four SMA periods, signal period); `Kst::classic()`
|
|
|
|
|
|
uses Pring's recommended defaults. Multi-output indicator emitting
|
|
|
|
|
|
`KstOutput { kst, signal }`. Exposed in all four bindings.
|
|
|
|
|
|
- **Family 02 — Momentum Oscillators.** `PGO` (Pretty Good Oscillator,
|
|
|
|
|
|
Mark Johnson): `(close − SMA(close, period)) / EMA(TR, period)`.
|
|
|
|
|
|
Candle input, single parameter `period` (default 14). Roughly counts
|
|
|
|
|
|
how many ATR-equivalents the close is from its mean. Exposed in all
|
|
|
|
|
|
four bindings.
|
|
|
|
|
|
- **Family 02 — Momentum Oscillators.** `RVI` (Relative Vigor Index,
|
|
|
|
|
|
Dorsey): per-bar ratio `SMA(close - open, period) / SMA(high - low,
|
|
|
|
|
|
period)`. Candle input, single parameter `period` (default 10).
|
|
|
|
|
|
Positive on average-bullish windows, negative on average-bearish.
|
|
|
|
|
|
Holds previous value if the entire window has zero range. Exposed in
|
|
|
|
|
|
all four bindings.
|
2026-05-25 15:01:14 +02:00
|
|
|
|
- **Family 01 — Moving Averages.** `ALMA` (Arnaud Legoux Moving Average):
|
|
|
|
|
|
Gaussian-weighted moving average with configurable centre (`offset` in
|
|
|
|
|
|
`[0, 1]`) and kernel width (`sigma > 0`). Community-standard defaults
|
|
|
|
|
|
`(period = 9, offset = 0.85, sigma = 6.0)` available via `Alma::classic()`.
|
|
|
|
|
|
Exposed in all four bindings (Rust, Python, Node, WASM).
|
|
|
|
|
|
- **Family 01 — Moving Averages.** `EVWMA` (Elastic Volume-Weighted
|
|
|
|
|
|
Moving Average, Fries 2001): an "elastic" recurrence whose smoothing
|
|
|
|
|
|
weight is the bar's volume relative to the running window-volume.
|
|
|
|
|
|
Candle input (uses close + volume), single parameter `period`
|
|
|
|
|
|
(default 20). Holds its previous value if the entire window has zero
|
|
|
|
|
|
volume. Exposed in all four bindings.
|
|
|
|
|
|
- **Family 01 — Moving Averages.** `Alligator` (Bill Williams): three
|
|
|
|
|
|
SMMA lines (Jaw / Teeth / Lips) of the median price `(high + low) / 2`
|
|
|
|
|
|
with default periods 13 / 8 / 5. Multi-output indicator emitting
|
|
|
|
|
|
`AlligatorOutput { jaw, teeth, lips }`. Visual chart shift is left to
|
|
|
|
|
|
the consumer. Exposed in all four bindings.
|
|
|
|
|
|
- **Family 01 — Moving Averages.** `JMA` (Jurik Moving Average):
|
|
|
|
|
|
three-stage filter reconstruction of Mark Jurik's adaptive MA.
|
|
|
|
|
|
Three parameters: `period` (14), `phase` in `[-100, 100]` (0), `power`
|
|
|
|
|
|
in `1..=4` (2). State is seeded to the first input so a constant series
|
|
|
|
|
|
is reproduced exactly. Exposed in all four bindings.
|
|
|
|
|
|
- **Family 01 — Moving Averages.** `VIDYA` (Variable Index Dynamic
|
|
|
|
|
|
Average, Chande 1992): EMA whose smoothing factor is scaled by the
|
|
|
|
|
|
absolute Chande Momentum Oscillator. Two parameters `period` and
|
|
|
|
|
|
`cmo_period` (defaults 14 / 9). Exposed in all four bindings.
|
|
|
|
|
|
- **Family 01 — Moving Averages.** `FRAMA` (Fractal Adaptive Moving
|
|
|
|
|
|
Average, Ehlers 2005): adapts its smoothing constant to the fractal
|
|
|
|
|
|
dimension of the recent window — fast in trends, slow in chop. Single
|
|
|
|
|
|
parameter `period` (must be even, default 16). Exposed in all four
|
|
|
|
|
|
bindings.
|
|
|
|
|
|
- **Family 01 — Moving Averages.** `McGinleyDynamic`: John McGinley's
|
|
|
|
|
|
self-adjusting MA. Single parameter `period`; the recurrence
|
|
|
|
|
|
`MD + (price - MD) / (0.6 * period * (price / MD)^4)` speeds up when price
|
|
|
|
|
|
falls below the indicator and damps when price runs above. Seeded with the
|
|
|
|
|
|
simple average of the first `period` inputs. Exposed in all four bindings.
|
|
|
|
|
|
|
2026-05-24 11:46:49 +02:00
|
|
|
|
## [0.2.7] - 2026-05-24
|
|
|
|
|
|
|
|
|
|
|
|
### Added
|
|
|
|
|
|
- **Windows ARM64 is back.** npm Support unblocked the
|
|
|
|
|
|
`wickra-win32-arm64-msvc` sub-package name (same path
|
|
|
|
|
|
`wickra-win32-x64-msvc` took through 0.1.4) and transferred write
|
|
|
|
|
|
access to @kingchenc. 0.2.7 ships the binding for
|
|
|
|
|
|
`aarch64-pc-windows-msvc` alongside the existing five platforms:
|
|
|
|
|
|
the `napi.triples.additional` entry, the `optionalDependencies`
|
|
|
|
|
|
pin, the `bindings/node/npm/win32-arm64-msvc/` sub-package and the
|
|
|
|
|
|
`windows-11-arm` row of the release.yml node-build matrix are all
|
|
|
|
|
|
restored from 8aa74cb. `npm install wickra` on Windows ARM64 now
|
|
|
|
|
|
resolves to a native build instead of failing the loader's
|
|
|
|
|
|
optional-dep lookup. PyPI's `win_arm64` wheel was unaffected and
|
|
|
|
|
|
carries through as before.
|
|
|
|
|
|
|
|
|
|
|
|
### Changed
|
|
|
|
|
|
- **Benchmark CPU renamed.** The "Reproduced on" line in every
|
|
|
|
|
|
README listed an AMD Ryzen 9 7950X3D; the canonical machine is
|
|
|
|
|
|
actually a Ryzen 9 9950X. Speedup ratios in the tables are
|
|
|
|
|
|
unchanged (they're relative across libraries on the same machine),
|
|
|
|
|
|
only the labelling is corrected. The performance-regression issue
|
|
|
|
|
|
template's CPU example was updated for consistency.
|
|
|
|
|
|
|
2026-05-24 03:20:13 +02:00
|
|
|
|
## [0.2.6] - 2026-05-24
|
|
|
|
|
|
|
|
|
|
|
|
### Fixed
|
|
|
|
|
|
- **docs.rs build.** Rust 1.92 removed the `doc_auto_cfg` feature gate
|
|
|
|
|
|
and folded it back into `doc_cfg` (rust-lang/rust#138907). docs.rs
|
|
|
|
|
|
builds against the latest nightly and sets `--cfg docsrs`, so every
|
|
|
|
|
|
published 0.2.x failed with E0557 on the
|
|
|
|
|
|
`#![cfg_attr(docsrs, feature(doc_auto_cfg))]` line at the top of
|
|
|
|
|
|
`wickra`, `wickra-core`, and `wickra-data`. GitHub CI didn't see
|
|
|
|
|
|
this — stable rustc never enables the `docsrs` cfg. The three
|
|
|
|
|
|
library crates now gate on `doc_cfg` (same intent, same rendered
|
|
|
|
|
|
output on docs.rs, builds again on nightly).
|
|
|
|
|
|
|
|
|
|
|
|
### Changed
|
|
|
|
|
|
- **README — Wickra is now the top row of every comparison table.**
|
|
|
|
|
|
The "Why Wickra exists" library matrix and the per-indicator
|
|
|
|
|
|
benchmark tables previously placed Wickra at the bottom; a reader
|
|
|
|
|
|
landing on the README is here to compare *against* Wickra, so the
|
|
|
|
|
|
pivot row belongs at the top with a ★ marker. Same column data,
|
|
|
|
|
|
same winner annotations — only row order changed. Mirrored across
|
|
|
|
|
|
the umbrella README and every binding README so crates.io / PyPI /
|
|
|
|
|
|
npm landing pages stay in sync.
|
|
|
|
|
|
|
2026-05-24 02:16:40 +02:00
|
|
|
|
## [0.2.5] - 2026-05-24
|
|
|
|
|
|
|
|
|
|
|
|
### Added
|
|
|
|
|
|
- `BinanceConfig` plus `BinanceKlineStream::connect_with_config(symbols, interval, config)`
|
|
|
|
|
|
in `wickra-data`'s `live::binance` module. `connect()` keeps its previous
|
|
|
|
|
|
signature and now forwards to the new entry-point with the defaults, so the
|
|
|
|
|
|
public API is backwards-compatible. The config lets callers point the
|
|
|
|
|
|
stream at Binance Testnet (`wss://testnet.binance.vision`) or tune the
|
|
|
|
|
|
read timeout, reconnect attempt count, initial / capped backoff and frame
|
|
|
|
|
|
size limits without rewriting the connector.
|
|
|
|
|
|
- README **Disclaimer** section clarifying that Wickra is an indicator
|
|
|
|
|
|
toolkit (not a trading system) and that any production-trading use is at
|
|
|
|
|
|
the caller's own risk. The legal terms in [LICENSE](LICENSE) are
|
|
|
|
|
|
unchanged.
|
|
|
|
|
|
|
|
|
|
|
|
### Changed
|
|
|
|
|
|
- `BinanceKlineStream::next_event` now writes the Pong reply to a server
|
|
|
|
|
|
`Ping` on a best-effort basis. A failed write means the connection is
|
|
|
|
|
|
already dead, so the existing timeout / read-error reconnect arm one
|
|
|
|
|
|
loop iteration later picks it up — the previous explicit reconnect on
|
|
|
|
|
|
Pong-write failure is gone. Observable behaviour is unchanged for every
|
|
|
|
|
|
healthy connection.
|
|
|
|
|
|
|
2026-05-23 22:20:20 +02:00
|
|
|
|
## [0.2.1] - 2026-05-23
|
|
|
|
|
|
|
2026-05-23 20:22:35 +02:00
|
|
|
|
### Changed
|
2026-05-23 22:20:20 +02:00
|
|
|
|
- **MSRV bumped.** Workspace minimum supported Rust version is now **1.86**
|
2026-05-23 20:22:35 +02:00
|
|
|
|
(was 1.75) and the Node binding (`wickra-node`) is now **1.88** (was 1.77).
|
|
|
|
|
|
The bumps are driven by transitive-dependency floors that were lifted in
|
2026-05-23 22:20:20 +02:00
|
|
|
|
recent updates: `criterion 0.8.2` (the bench dev-dep) requires Rust 1.86,
|
|
|
|
|
|
and `napi-build >= 2.3.2` requires Rust 1.88. Pinning those deps to the
|
2026-05-23 20:30:46 +02:00
|
|
|
|
older versions would have frozen us out of future security fixes from
|
|
|
|
|
|
those upstreams, so lifting the MSRV is the cleaner path for a young 0.x
|
2026-05-23 20:22:35 +02:00
|
|
|
|
library. Downstream consumers on older Rust toolchains can stay on
|
|
|
|
|
|
Wickra 0.2.0.
|
2026-05-23 22:20:20 +02:00
|
|
|
|
- Bumped the bench dev-dep `criterion` from 0.5 to 0.8 and migrated
|
|
|
|
|
|
`bindings/wickra/benches/indicators.rs` from the deprecated
|
|
|
|
|
|
`criterion::black_box` re-export to the stable `std::hint::black_box`.
|
|
|
|
|
|
- Bumped `tokio-tungstenite` from 0.24 to 0.29. `WebSocketConfig` became
|
|
|
|
|
|
`#[non_exhaustive]` upstream, so the struct-literal construction in
|
|
|
|
|
|
`crates/wickra-data/src/live/binance.rs` is rewritten to the
|
|
|
|
|
|
builder-style `WebSocketConfig::default().max_message_size(..).max_frame_size(..)`.
|
|
|
|
|
|
Same caps, same semantics, same default carry-over.
|
|
|
|
|
|
- Bumped every committed CI/release GitHub Action to its latest pinned
|
|
|
|
|
|
SHA: `actions/checkout` 4 → 6, `actions/setup-node` 4 → 6,
|
|
|
|
|
|
`actions/setup-python` 5 → 6, `actions/upload-artifact` 4 → 7,
|
|
|
|
|
|
`actions/download-artifact` 4 → 8, `softprops/action-gh-release` 2 → 3,
|
|
|
|
|
|
`codecov/codecov-action` 5 → 6, `taiki-e/install-action` patch.
|
|
|
|
|
|
|
|
|
|
|
|
### Fixed
|
|
|
|
|
|
- `tick_aggregator` gap-fill no longer allocates an unbounded number of
|
|
|
|
|
|
placeholder candles. The new `MAX_GAP_FILL_CANDLES = 1_000_000` cap
|
|
|
|
|
|
surfaces an adversarial timestamp jump (e.g. a clock-glitch tick years
|
|
|
|
|
|
in the future) as `Error::Malformed` instead of an OOM panic. Found by
|
|
|
|
|
|
the new `tick_aggregator` fuzz target.
|
|
|
|
|
|
- `HistoricalVolatility::geometric_series_yields_zero` now uses an `1e-6`
|
|
|
|
|
|
tolerance instead of `1e-9`. The mathematical result on a perfectly
|
|
|
|
|
|
geometric price series is exactly zero, but the underlying
|
|
|
|
|
|
`1.01_f64.powi(i)` + log-return + std-dev cascade accumulates
|
|
|
|
|
|
platform-sensitive FP drift on the order of 1e-7 on x86_64 Linux and
|
|
|
|
|
|
macOS. The widened tolerance stays four decimal places below any
|
|
|
|
|
|
realistic annualised volatility value while absorbing the drift across
|
|
|
|
|
|
every supported platform.
|
|
|
|
|
|
- Replaced every `(high + low) / 2.0` test-helper and three real call
|
|
|
|
|
|
sites (`Ohlcv::median_price`, `Donchian.middle`, `EaseOfMovement.mid`,
|
|
|
|
|
|
`SuperTrend.hl2`) with `f64::midpoint(high, low)`. The change satisfies
|
|
|
|
|
|
clippy 1.95's new `manual_midpoint` lint without affecting values
|
|
|
|
|
|
(`f64::midpoint` matches the naive average to better than 1 ULP for the
|
|
|
|
|
|
inputs used here).
|
|
|
|
|
|
- Replaced `i.is_multiple_of(2)` (unstable on Rust 1.85) with `i % 2 == 0`
|
|
|
|
|
|
in the SMA / Bollinger long-stream-drift tests so the workspace MSRV
|
|
|
|
|
|
job builds cleanly on Rust 1.86.
|
|
|
|
|
|
- The `Compile examples` CI step now invokes
|
|
|
|
|
|
`cargo build -p wickra-examples --bins` instead of the now-deleted
|
|
|
|
|
|
`cargo build -p wickra --example backtest` / `-p wickra-data --example
|
|
|
|
|
|
live_binance` (the Z5 reorganisation moved every runnable example into
|
|
|
|
|
|
the dedicated `wickra-examples` crate, but the CI step had not been
|
|
|
|
|
|
updated).
|
|
|
|
|
|
- The `Fuzz (smoke)` CI job installs `cargo-fuzz` from a prebuilt binary
|
|
|
|
|
|
via `taiki-e/install-action` instead of `cargo install cargo-fuzz`.
|
|
|
|
|
|
The source install resolved against `rustix 0.36.5`, which uses
|
|
|
|
|
|
internal `#[rustc_*]` attributes the current nightly compiler rejects.
|
|
|
|
|
|
- The fuzz targets now build with an explicit
|
|
|
|
|
|
`--target x86_64-unknown-linux-gnu`; cargo-fuzz was defaulting to
|
|
|
|
|
|
`x86_64-unknown-linux-musl`, which is not installed on the standard
|
|
|
|
|
|
GitHub-hosted Ubuntu runner.
|
|
|
|
|
|
|
|
|
|
|
|
### Removed
|
|
|
|
|
|
- **`wickra-win32-arm64-msvc` is temporarily omitted from this release.**
|
|
|
|
|
|
The npm spam-detection filter blocks the first publish of this brand-new
|
|
|
|
|
|
package name (same situation that affected `wickra-win32-x64-msvc`
|
|
|
|
|
|
through 0.1.4 until npm Support unblocked it). A support ticket is open;
|
|
|
|
|
|
once the new name is unblocked the
|
|
|
|
|
|
`aarch64-pc-windows-msvc` triple will be restored in
|
|
|
|
|
|
`bindings/node/package.json` (`napi.triples.additional` +
|
|
|
|
|
|
`optionalDependencies`), in the `release.yml` `node-build` matrix, and
|
|
|
|
|
|
as a fresh `bindings/node/npm/win32-arm64-msvc/` template. Until then,
|
|
|
|
|
|
`npm install wickra@0.2.1` on Windows ARM64 will surface the loader's
|
|
|
|
|
|
standard `Cannot find module 'wickra-win32-arm64-msvc'` error; every
|
|
|
|
|
|
other platform (Linux x64 / Linux ARM64 / macOS x64 / macOS ARM64 /
|
|
|
|
|
|
Windows x64) ships normally. The PyPI wheel for Windows ARM64 is
|
|
|
|
|
|
unaffected and still published.
|
2026-05-23 20:22:35 +02:00
|
|
|
|
|
2026-05-23 19:58:02 +02:00
|
|
|
|
## [0.2.0] - 2026-05-23
|
2026-05-23 10:58:08 +02:00
|
|
|
|
|
2026-05-23 10:28:18 +02:00
|
|
|
|
### Fixed
|
2026-05-23 10:46:52 +02:00
|
|
|
|
- `HistoricalVolatility::update` no longer substitutes a `0.0` log-return on
|
|
|
|
|
|
non-positive prices (audit finding R13). Negative or zero prices are
|
|
|
|
|
|
semantically invalid for a log-return calculation; silently treating them as
|
|
|
|
|
|
"no movement" underreported realised volatility. They are now skipped — the
|
|
|
|
|
|
previous valid value is returned and the indicator's state (`prev_price`,
|
|
|
|
|
|
window, sums) is left untouched — matching how every other indicator handles
|
|
|
|
|
|
invalid inputs.
|
|
|
|
|
|
- `Tick::new` now returns the new `Error::InvalidTick` variant for negative
|
|
|
|
|
|
volume instead of `Error::InvalidCandle` (audit finding R14). A tick is not
|
|
|
|
|
|
a candle, and downstream tick-stream pipelines should be able to match on a
|
|
|
|
|
|
semantically-correct error. The Python binding's `map_err` was extended to
|
|
|
|
|
|
forward the new variant as a `ValueError`; the Node and WASM bindings format
|
|
|
|
|
|
via `Error::to_string()` and pick the new variant up automatically.
|
2026-05-23 10:28:18 +02:00
|
|
|
|
- `Psar::is_ready` now matches the convention shared by every other indicator:
|
|
|
|
|
|
`is_ready() == true` iff a real value has been produced (audit finding R6).
|
|
|
|
|
|
The previous implementation returned `self.initialised`, which flipped to
|
|
|
|
|
|
`true` after the seed candle even though the seed candle itself returns
|
|
|
|
|
|
`None`. A streaming consumer that wrote
|
|
|
|
|
|
`if ind.is_ready() { use(ind.update(c)?) }` would hit an unexpected `None`
|
|
|
|
|
|
on the first post-seed update. The fix introduces a `has_emitted` gate set
|
|
|
|
|
|
when the first `Some` value is returned.
|
|
|
|
|
|
- `Psar::reset` now restores the compute fields (`prev_high`, `prev_low`,
|
|
|
|
|
|
`sar`, `ep`) to `f64::NAN` sentinels instead of `0.0` (audit Opus-Bonus 1).
|
|
|
|
|
|
The fields are gated by `initialised` today, so the `0.0` sentinel never
|
|
|
|
|
|
leaked into output — but a future refactor that read them pre-init would
|
|
|
|
|
|
have silently treated `0.0` as a real price. A `debug_assert!` at the read
|
|
|
|
|
|
site makes the invariant explicit.
|
|
|
|
|
|
|
2026-05-23 01:46:24 +02:00
|
|
|
|
### Changed
|
2026-05-23 10:42:50 +02:00
|
|
|
|
- `Sma` and `BollingerBands` now reseed their incremental `sum` (and `sum_sq`
|
|
|
|
|
|
for Bollinger) from the live window every `16 · period` finite updates,
|
|
|
|
|
|
capping floating-point drift on long-running streams (audit findings R7 and
|
|
|
|
|
|
L2-Rust). Previously the incremental single-subtract `sum -= old` could
|
|
|
|
|
|
accumulate catastrophic-cancellation error on streams with alternating
|
|
|
|
|
|
large/small magnitudes; the misleading `sma.rs` comment that claimed the
|
|
|
|
|
|
drift was already bounded "by recomputing the sum after each pop" is
|
|
|
|
|
|
replaced with an accurate description of the new reseed strategy. Amortised
|
|
|
|
|
|
cost stays at O(1) (`O(period)` work amortised over `O(period)` updates),
|
|
|
|
|
|
values are bit-identical on inputs that did not drift to begin with, and
|
|
|
|
|
|
two new `long_stream_drift_stays_bounded` tests stress the recompute by
|
|
|
|
|
|
alternating `1e9` / `1.0` (SMA) and `1e6` / `1.0` (Bollinger) for several
|
|
|
|
|
|
recompute cycles and verify the reported values track a fresh from-scratch
|
|
|
|
|
|
computation over the live window.
|
2026-05-23 10:36:45 +02:00
|
|
|
|
- `LinearRegression`, `LinRegSlope` and `LinRegAngle` (via composition over
|
|
|
|
|
|
`LinRegSlope`) now run their rolling ordinary-least-squares fit
|
|
|
|
|
|
**incrementally** in O(1) per update (audit finding R2). Previously every
|
|
|
|
|
|
tick refit the line from scratch in O(period). The OLS denominators (`Σx`
|
|
|
|
|
|
and `Σxx`) depend only on `period`, so they were already precomputed; this
|
|
|
|
|
|
release adds running `Σy` and `Σxy` accumulators and slides them in closed
|
|
|
|
|
|
form via the identity
|
|
|
|
|
|
`new_Σxy = old_Σxy − old_Σy + popped_y₀` (then `Σxy += (n − 1) · new_value`
|
|
|
|
|
|
and `Σy += new_value`). New per-bar equivalence tests compare the O(1)
|
|
|
|
|
|
output against a fresh O(n) refit on noisy ramps, step functions, and
|
|
|
|
|
|
constants — values agree to within 1e-9.
|
2026-05-23 10:33:05 +02:00
|
|
|
|
- Fuzz suite expanded from 2 indicators to the full catalogue (audit finding
|
|
|
|
|
|
R9). The existing `indicator_update` target now exercises every scalar-input
|
|
|
|
|
|
indicator (~33 classes including MACD and Bollinger Bands); a new
|
|
|
|
|
|
`indicator_update_candle` target exercises every candle-input indicator (~37
|
|
|
|
|
|
classes, including ATR, ADX, Stochastic, PSAR, Keltner, SuperTrend,
|
|
|
|
|
|
ChandelierExit, AwesomeOscillator, OBV, MFI, VWAP, RollingVWAP, and the rest
|
|
|
|
|
|
of the volume / volatility / trailing-stop / price-statistics families). Each
|
|
|
|
|
|
iteration sweeps every indicator through both the streaming `update` loop
|
|
|
|
|
|
and a full `batch` call so any state-mutation bug surfaces on either path.
|
|
|
|
|
|
CI gains a `fuzz-smoke` job that runs each of the five targets for 30 s on
|
|
|
|
|
|
every push and pull-request.
|
2026-05-23 01:46:24 +02:00
|
|
|
|
- `UlcerIndex::update` now tracks the trailing maximum with a monotonically-
|
|
|
|
|
|
decreasing deque of `(index, price)` pairs instead of scanning the whole
|
|
|
|
|
|
trailing window on every tick. The indicator now honours the `Indicator`
|
|
|
|
|
|
trait's O(1)-per-tick contract; values and warmup semantics are unchanged
|
|
|
|
|
|
(verified by a new adversarial-input test that compares the deque output
|
|
|
|
|
|
bar-by-bar against a naive O(n) trailing-max scan on strictly increasing,
|
|
|
|
|
|
strictly decreasing, constant, and sawtooth inputs). The doc comment on
|
|
|
|
|
|
`warmup_period()` is also corrected: the two windows overlap by one bar, so
|
|
|
|
|
|
the formula is `2 * period - 1`.
|
|
|
|
|
|
|
2026-05-23 01:34:54 +02:00
|
|
|
|
### Added
|
2026-05-23 01:43:00 +02:00
|
|
|
|
- `RollingVWAP` is now exposed in Python, Node and WASM under that name
|
|
|
|
|
|
(previously the rolling-window VWAP existed only in the Rust core, even
|
|
|
|
|
|
though the README's volume-family table already advertised
|
|
|
|
|
|
`VWAP (cumulative + rolling)`). All four bindings now ship the same
|
|
|
|
|
|
cumulative `VWAP` plus the finite-window `RollingVWAP(period)`. The wiki page
|
|
|
|
|
|
`Indicator-Vwap.md` adds Python, Node and WASM examples and drops the
|
|
|
|
|
|
"Rust-only" caveat.
|
2026-05-23 01:34:54 +02:00
|
|
|
|
- WASM binding now exposes the streaming `update()` method on every candle-input
|
|
|
|
|
|
indicator: `Adx`, `WilliamsR`, `Cci`, `Mfi`, `Psar`, `Keltner`, `Donchian`,
|
|
|
|
|
|
`Vwap`, `AwesomeOscillator`, `Aroon`, `Stochastic`, and `Obv`. Multi-output
|
|
|
|
|
|
indicators (`Adx`, `Keltner`, `Donchian`, `Aroon`, `Stochastic`) return a
|
|
|
|
|
|
named JS object (`{ plusDi, minusDi, adx }`, `{ upper, middle, lower }`,
|
|
|
|
|
|
`{ up, down }`, `{ k, d }`) once warm, or `null` during warmup — matching the
|
|
|
|
|
|
existing `SuperTrend` convention. Each class also gains `reset()`, `isReady()`
|
|
|
|
|
|
and `warmupPeriod()`, bringing the WASM surface to full parity with Python
|
|
|
|
|
|
and Node so browser-side streaming code no longer has to replay `batch()`
|
|
|
|
|
|
on every tick. `WasmKama` gains the previously missing `warmupPeriod()`.
|
|
|
|
|
|
- New `wasm-bindgen` integration test exercises `update == batch` plus the full
|
|
|
|
|
|
lifecycle (`reset` / `isReady` / `warmupPeriod`) for all twelve newly wired
|
|
|
|
|
|
classes against a deterministic 40-bar synthetic OHLCV stream.
|
|
|
|
|
|
|
2026-05-23 01:26:55 +02:00
|
|
|
|
### Security
|
|
|
|
|
|
- Upgrade `pyo3` (0.22 → 0.28) and `numpy` (0.22 → 0.28) in the Python binding.
|
|
|
|
|
|
Fixes [RUSTSEC-2025-0020](https://rustsec.org/advisories/RUSTSEC-2025-0020) —
|
|
|
|
|
|
a buffer overflow in `PyString::from_object` that affected the published
|
|
|
|
|
|
Python wheels. The `cargo-deny` ignore entry that previously suppressed the
|
|
|
|
|
|
advisory has been removed; `cargo deny check` is now clean without
|
|
|
|
|
|
suppression. Migrated `into_pyarray_bound` to `into_pyarray`,
|
|
|
|
|
|
`downcast::<PyDict>` to `cast::<PyDict>`, and opted every `#[pyclass]` out of
|
|
|
|
|
|
the deprecated automatic `FromPyObject` derive via `skip_from_py_object`.
|
|
|
|
|
|
|
2026-05-22 16:17:15 +02:00
|
|
|
|
### Added
|
2026-05-22 21:21:56 +02:00
|
|
|
|
- 46 new technical indicators, taking the library from 25 to 71 and
|
|
|
|
|
|
reorganising the catalogue into **eight families**, each with at least five
|
|
|
|
|
|
members. Every indicator is implemented once in the Rust core and wired
|
|
|
|
|
|
through the Python, Node and WASM bindings, with reference-value tests and a
|
|
|
|
|
|
dedicated wiki page:
|
|
|
|
|
|
- Moving Averages: `Smma`, `Trima`, `Zlema`, `T3`, `Vwma`.
|
|
|
|
|
|
- Momentum Oscillators: `Mom`, `Cmo`, `Tsi`, `Pmo`, `StochRsi`,
|
|
|
|
|
|
`UltimateOscillator`.
|
|
|
|
|
|
- Trend & Directional: `AroonOscillator`, `Vortex`, `MassIndex`,
|
|
|
|
|
|
`ChoppinessIndex`, `VerticalHorizontalFilter`.
|
|
|
|
|
|
- Price Oscillators: `Ppo`, `Dpo`, `Coppock`, `AcceleratorOscillator`,
|
|
|
|
|
|
`BalanceOfPower`.
|
|
|
|
|
|
- Volatility & Bands: `Natr`, `StdDev`, `UlcerIndex`,
|
|
|
|
|
|
`HistoricalVolatility`, `BollingerBandwidth`, `PercentB`, `TrueRange`,
|
|
|
|
|
|
`ChaikinVolatility`.
|
|
|
|
|
|
- Trailing Stops: `SuperTrend`, `ChandelierExit`, `ChandeKrollStop`,
|
|
|
|
|
|
`AtrTrailingStop`.
|
2026-05-22 20:04:13 +02:00
|
|
|
|
- Volume: `Adl`, `VolumePriceTrend`, `ChaikinMoneyFlow`,
|
|
|
|
|
|
`ChaikinOscillator`, `ForceIndex`, `EaseOfMovement`.
|
2026-05-22 21:21:56 +02:00
|
|
|
|
- Price Statistics: `TypicalPrice`, `MedianPrice`, `WeightedClose`,
|
|
|
|
|
|
`LinearRegression`, `LinRegSlope`, `ZScore`, `LinRegAngle`.
|
2026-05-22 16:17:15 +02:00
|
|
|
|
- `TickAggregator::with_gap_fill` — opt-in mode that emits a flat placeholder
|
|
|
|
|
|
candle for every empty bucket between two ticks, keeping the candle series
|
|
|
|
|
|
evenly spaced for downstream indicators.
|
|
|
|
|
|
- CSV reader: a leading UTF-8 byte-order mark is stripped, fields are trimmed,
|
|
|
|
|
|
and the header is validated against the required OHLCV columns.
|
|
|
|
|
|
- CI: an `msrv` job that builds and tests the workspace on Rust 1.75 and the
|
|
|
|
|
|
node binding on Rust 1.77.
|
|
|
|
|
|
- Community health files: `CONTRIBUTING.md`, `SECURITY.md`,
|
|
|
|
|
|
`CODE_OF_CONDUCT.md`, issue / pull-request templates, `CODEOWNERS`, and a
|
|
|
|
|
|
Dependabot configuration.
|
2026-05-23 00:01:52 +02:00
|
|
|
|
- Seven example OHLCV datasets under `examples/data/`, one per timeframe
|
|
|
|
|
|
(1m / 5m / 15m / 1h / 12h / 1d / 1month), holding real BTCUSDT spot klines,
|
|
|
|
|
|
alongside the `fetch_btcusdt` example that regenerates them from the
|
|
|
|
|
|
Binance REST API.
|
2026-05-22 22:20:26 +02:00
|
|
|
|
- `Timeframe::minutes`, `Timeframe::hours` and `Timeframe::days` convenience
|
|
|
|
|
|
constructors, each building on seconds with a checked-multiplication
|
|
|
|
|
|
overflow guard.
|
2026-05-22 16:17:15 +02:00
|
|
|
|
|
|
|
|
|
|
### Changed
|
2026-05-22 21:21:56 +02:00
|
|
|
|
- The indicator wiki is reorganised into eight family folders under
|
|
|
|
|
|
`docs/wiki/indicators/` (`moving-averages/`, `momentum-oscillators/`,
|
|
|
|
|
|
`trend-directional/`, `price-oscillators/`, `volatility-bands/`,
|
|
|
|
|
|
`trailing-stops/`, `volume/`, `price-statistics/`); `Indicators-Overview.md`,
|
|
|
|
|
|
`Home.md` and the README indicator table follow the same eight families.
|
2026-05-22 16:17:15 +02:00
|
|
|
|
- `TickAggregator::push` returns `Result<Vec<Candle>>` (was
|
|
|
|
|
|
`Result<Option<Candle>>`) so a single tick can yield a closed bar plus gap
|
|
|
|
|
|
fillers.
|
|
|
|
|
|
- `Resampler::push` returns `Result<Option<Candle>>`: a candle in a bucket
|
|
|
|
|
|
earlier than the open bar is now rejected as out of order.
|
|
|
|
|
|
- Aggregated candles are finalised through the validating `Candle::new`, so a
|
|
|
|
|
|
volume that overflows to a non-finite value is surfaced as an error instead
|
|
|
|
|
|
of producing a poisoned candle.
|
|
|
|
|
|
- All GitHub Actions are pinned to commit SHAs; the four publish jobs run in a
|
|
|
|
|
|
protected `release` environment.
|
2026-05-22 22:20:26 +02:00
|
|
|
|
- The indicator benchmarks (`crates/wickra/benches/indicators.rs`) now run
|
|
|
|
|
|
against the checked-in real BTCUSDT 1-minute dataset instead of a synthetic
|
|
|
|
|
|
price series.
|
2026-05-23 00:23:00 +02:00
|
|
|
|
- Every language's examples now live under a uniform `examples/<lang>/`
|
|
|
|
|
|
tree: Rust moved into a new `examples/rust/` workspace member crate
|
|
|
|
|
|
(`wickra-examples`, run via `cargo run -p wickra-examples --bin <name>`),
|
|
|
|
|
|
Node into `examples/node/` with its own `package.json` linking `wickra` via
|
2026-05-23 00:45:51 +02:00
|
|
|
|
`file:../../bindings/node`, and the WASM browser demos into
|
2026-05-23 00:23:00 +02:00
|
|
|
|
`examples/wasm/`. The bundled BTCUSDT datasets move alongside them at
|
|
|
|
|
|
`examples/data/`. Six new examples close the cross-language parity matrix:
|
|
|
|
|
|
streaming demos for Python and Rust; multi-timeframe and parallel-assets
|
|
|
|
|
|
demos for both Rust and Node.
|
2026-05-23 00:45:51 +02:00
|
|
|
|
- Cross-language data-generator parity: `examples/python/fetch_btcusdt.py`
|
|
|
|
|
|
(stdlib only: `urllib` + `json` + `csv`) and `examples/node/fetch_btcusdt.js`
|
|
|
|
|
|
(Node 18+ built-in `fetch`) mirror the Rust `fetch_btcusdt` binary —
|
|
|
|
|
|
byte-for-byte identical CSV output on the same Binance snapshot.
|
|
|
|
|
|
- Four additional WebAssembly browser demos under `examples/wasm/`
|
|
|
|
|
|
alongside the original `index.html`: `backtest.html` (fetch + basket of
|
|
|
|
|
|
indicators), `live_trading.html` (browser-native `WebSocket` to
|
|
|
|
|
|
Binance), `multi_timeframe.html` (in-page resample) and
|
|
|
|
|
|
`parallel_assets.html` + `parallel_worker.js` (module-Worker pool with
|
|
|
|
|
|
serial-vs-parallel speedup). The cross-language matrix is now closed
|
|
|
|
|
|
for every cell where the pattern makes sense.
|
|
|
|
|
|
- Three new wiki pages: `TA-Lib-Migration.md` (full mapping table from
|
|
|
|
|
|
`talib.X(...)` calls to Wickra), `Cookbook.md` (seven concrete
|
|
|
|
|
|
strategy recipes — RSI mean reversion, MACD crossover, Bollinger
|
|
|
|
|
|
breakout, ADX-gated trend, multi-timeframe confirmation, SuperTrend,
|
|
|
|
|
|
chained indicators) and `FAQ.md`. All three linked from `Home.md`.
|
2026-05-22 16:17:15 +02:00
|
|
|
|
|
|
|
|
|
|
### Fixed
|
|
|
|
|
|
- `Timeframe::floor` no longer overflows for timestamps near `i64::MIN`.
|
|
|
|
|
|
- The aggregator rejects same-bucket ticks that arrive out of order instead of
|
|
|
|
|
|
silently overwriting the bar's close with a stale price.
|
|
|
|
|
|
- The Binance live stream reconnects with exponential backoff, skips non-kline
|
|
|
|
|
|
frames, applies a read timeout and message-size limits, and tracks a closed
|
|
|
|
|
|
flag.
|
|
|
|
|
|
- Example scripts: `live_trading.py` skips non-kline frames and validates the
|
|
|
|
|
|
symbol/interval; `backtest.py` and `multi_timeframe.py` report clear errors
|
|
|
|
|
|
for malformed CSV input.
|
|
|
|
|
|
|
|
|
|
|
|
## [0.1.4] - 2026-05-21
|
|
|
|
|
|
|
|
|
|
|
|
### Added
|
|
|
|
|
|
- GitHub Release runs now attach every built artefact (wheels, sdist, native
|
|
|
|
|
|
Node binaries, npm-pack tarballs, cargo `.crate` files) to the tag's
|
|
|
|
|
|
release page.
|
|
|
|
|
|
|
|
|
|
|
|
## [0.1.3] - 2026-05-21
|
|
|
|
|
|
|
|
|
|
|
|
### Fixed
|
|
|
|
|
|
- npm package ships the napi-generated loader and is built with `--platform`
|
|
|
|
|
|
so the per-platform binary is resolved correctly.
|
|
|
|
|
|
|
|
|
|
|
|
## [0.1.2] - 2026-05-21
|
|
|
|
|
|
|
|
|
|
|
|
### Fixed
|
|
|
|
|
|
- Release pipeline: per-platform idempotent npm publishing with a spam-filter
|
|
|
|
|
|
retry, and committed `npm/<platform>/` package templates.
|
|
|
|
|
|
|
|
|
|
|
|
## [0.1.1] - 2026-05-21
|
|
|
|
|
|
|
|
|
|
|
|
### Fixed
|
|
|
|
|
|
- Node publish step and coordinated version bump across all bindings.
|
|
|
|
|
|
|
|
|
|
|
|
## [0.1.0] - 2026-05-21
|
|
|
|
|
|
|
|
|
|
|
|
### Added
|
|
|
|
|
|
- Initial release: a streaming-first technical-analysis library with 25
|
|
|
|
|
|
indicators (SMA, EMA, WMA, DEMA, TEMA, HMA, KAMA, RSI, MACD, ROC, Stochastic,
|
|
|
|
|
|
CCI, Williams %R, ADX, MFI, TRIX, Aroon, Awesome Oscillator, Bollinger Bands,
|
|
|
|
|
|
ATR, Keltner Channels, Donchian Channels, Parabolic SAR, OBV, VWAP).
|
|
|
|
|
|
- Rust core (`wickra-core`), umbrella crate (`wickra`), and a data layer
|
|
|
|
|
|
(`wickra-data`) with a CSV reader, tick aggregator, resampler, and an
|
|
|
|
|
|
optional Binance live feed.
|
|
|
|
|
|
- Bindings for Python, Node.js, and WebAssembly.
|
|
|
|
|
|
|
2026-06-01 13:58:50 +02:00
|
|
|
|
[Unreleased]: https://github.com/wickra-lib/wickra/compare/v0.4.1...HEAD
|
|
|
|
|
|
[0.4.1]: https://github.com/wickra-lib/wickra/compare/v0.4.0...v0.4.1
|
2026-06-01 01:28:53 +02:00
|
|
|
|
[0.4.0]: https://github.com/wickra-lib/wickra/compare/v0.3.1...v0.4.0
|
2026-05-30 19:50:45 +02:00
|
|
|
|
[0.3.1]: https://github.com/wickra-lib/wickra/compare/v0.3.0...v0.3.1
|
|
|
|
|
|
[0.3.0]: https://github.com/wickra-lib/wickra/compare/v0.2.7...v0.3.0
|
2026-05-30 12:18:10 +02:00
|
|
|
|
[0.2.7]: https://github.com/wickra-lib/wickra/compare/v0.2.6...v0.2.7
|
|
|
|
|
|
[0.2.6]: https://github.com/wickra-lib/wickra/compare/v0.2.5...v0.2.6
|
|
|
|
|
|
[0.2.5]: https://github.com/wickra-lib/wickra/compare/v0.2.1...v0.2.5
|
|
|
|
|
|
[0.2.1]: https://github.com/wickra-lib/wickra/compare/v0.2.0...v0.2.1
|
|
|
|
|
|
[0.2.0]: https://github.com/wickra-lib/wickra/compare/v0.1.4...v0.2.0
|
|
|
|
|
|
[0.1.4]: https://github.com/wickra-lib/wickra/compare/v0.1.3...v0.1.4
|
|
|
|
|
|
[0.1.3]: https://github.com/wickra-lib/wickra/compare/v0.1.2...v0.1.3
|
|
|
|
|
|
[0.1.2]: https://github.com/wickra-lib/wickra/compare/v0.1.1...v0.1.2
|
|
|
|
|
|
[0.1.1]: https://github.com/wickra-lib/wickra/compare/v0.1.0...v0.1.1
|
|
|
|
|
|
[0.1.0]: https://github.com/wickra-lib/wickra/releases/tag/v0.1.0
|