Version bump for the **v0.6.5** release shipping the **B10 Ehlers / Cycle** family (#199): 452 -> 462 indicators. Bumps workspace + Python/Node/WASM package versions, lockfiles and CHANGELOG. No code changes.
Version bump for the **v0.6.4** release shipping the **B9 Price Statistics** family (#197): 447 -> 452 indicators. Bumps workspace + Python/Node/WASM package versions, lockfiles and CHANGELOG. No code changes.
Version bump for the **v0.6.3** release shipping the **B8 Volume** family (#195): 440 -> 447 indicators. Bumps workspace + Python/Node/WASM package versions, lockfiles and CHANGELOG. No code changes.
Version bump for the **v0.6.2** release shipping the **B7 Trailing Stops** family (#193): 434 -> 440 indicators.
Bumps workspace + Python/Node/WASM package versions, lockfiles and CHANGELOG (cuts the `[0.6.2]` section). No code changes.
Version bump for the **v0.6.0** release (ships the B5 Volatility & Bands batch, #189 — 423 -> 429 indicators).
Bumps version strings across Cargo workspace, pyproject, node package.json + 6 platform packages, both package-lock.json files, and Cargo.lock; CHANGELOG `[Unreleased]` -> `[0.6.0]`. No code changes.
Versioning note: patch never reaches two digits — `0.5.9` rolls to the next minor `0.6.0` (not 0.5.10).
Patch release: streaming/batch perf (SMA, Bollinger, RSI, EMA, ATR; outputs unchanged), cross-library benchmark harness, honest tiered README. No new indicators, no API changes.
## Summary
An honest, tiered cross-library benchmark — and the optimization pass it triggered.
### Performance (wickra-core, outputs unchanged)
Profiling against the other Rust TA crates exposed real inefficiencies. Each
benchmarked indicator is now **5–79% faster** in both streaming and batch:
- **SMA, Bollinger**: flat `Box<[f64]>` ring buffers replace `VecDeque` (−69…79%).
- **RSI**: `100·ag/(ag+al)` collapses three divisions into one; Wilder smoothing
hoists `1/period` out of the hot path (−46%).
- **ATR**: reciprocal hoisted (−42%).
- **EMA/RSI/ATR**: per-tick `Option<f64>` hot state → bare `f64` + ready flag.
Net result vs `kand`: Wickra now wins **RSI, Bollinger and ATR** (streaming), and
ties `ta-rs` on SMA — up from losing every indicator 1.5–6× before.
### Benchmark harness
New `crates/wickra-bench` (publish=false): a Criterion benchmark comparing Wickra
against `kand`, `ta-rs` and `yata` on an identical BTCUSDT candle series, in
streaming and batch modes. Peer APIs were verified against their source, not
guessed. Wired into the nightly `cross-library-bench` workflow as a separate job.
### Honest README
The benchmark section is rewritten into three layered tables (Rust core vs Rust
crates; Python vs the Python ecosystem) that **show the losses as well as the
wins**. The "only library that combines…" claim is gone; the new framing is
breadth + multi-language reach + the deliberate safety trade-off that costs raw
speed. Added an origin/why-slower rationale and a star CTA.
### Python benchmark
Added `tulipy` runners and expanded per-tick streaming coverage to SMA/EMA/RSI/
MACD/Bollinger. `bench.in`/`bench.txt` now lock `TA-Lib` + `tulipy` (hash-pinned);
`pandas-ta` stays out (it requires Python ≥ 3.12, the bench runs on 3.11).
### Notes
- TA-Lib/tulipy numbers in the README Python table are marked ⧗ — they are
produced by the CI Linux job (C extensions don't build cleanly on every
desktop), not measured locally.
- The matching `wickra-docs` prose update is committed separately and will be
pushed with the release, per the docs-don't-lead-the-registries rule.
Verified locally: `cargo fmt`, `cargo test --workspace --all-features` (3413 core
+ bindings), `cargo clippy --workspace --all-targets --all-features -D warnings`,
Node build + 498 tests, and pytest all green.
Version bump 0.5.6 → 0.5.7 for the **B3 — Trend & Directional** batch (#181):
seven new indicators (`Qstick`, `TtmTrend`, `TrendStrengthIndex`,
`PolarizedFractalEfficiency`, `WavePm`, `GatorOscillator`,
`KasePermissionStochastic`), catalog 413 → 420.
Bumps: workspace `Cargo.toml` + `Cargo.lock`, `bindings/python/pyproject.toml`,
`bindings/node/package.json` + the six `npm/*/package.json` platform manifests,
both `package-lock.json` files, and the `CHANGELOG.md` `[Unreleased]` → `[0.5.7]`
roll with compare URLs.
Release bump `0.5.5 → 0.5.6` for the Momentum Oscillators family deepening
(#179): ten new indicators (DisparityIndex, FisherRsi, Rmi, DerivativeOscillator,
Rsx, DynamicMomentumIndex, IntradayMomentumIndex, StochasticCci, ElderRay, Qqe),
counter now 413.
Version strings only across all manifests + lockfiles; CHANGELOG `[Unreleased]`
rolled to `[0.5.6] - 2026-06-04` with the new compare links.
Release bump `0.5.4 → 0.5.5` for the Moving Averages family deepening
(#177): seven new indicators (`SineWeightedMa`, `GeometricMa`, `Ehma`,
`MedianMa`, `AdaptiveLaguerreFilter`, `GeneralizedDema`, `HoltWinters`),
counter now 403.
Version strings only across all manifests + lockfiles; CHANGELOG `[Unreleased]`
rolled to `[0.5.5] - 2026-06-04` with the new compare links.
Version bump for the 0.5.0 release, which ships the relicense to MIT OR Apache-2.0.
Stacked on #158 (base branch `chore/relicense-mit-apache`) so this PR's diff is the bump only. After #158 merges to main, GitHub retargets this PR to main; merge it, then tag `v0.5.0` to publish.
## Changes
- Bump 0.4.7 -> 0.5.0 across the Cargo workspace, Python `pyproject.toml`, Node `package.json` + 6 platform manifests + 2 lockfiles, and `Cargo.lock`.
- CHANGELOG: cut the [0.5.0] section (the relicense) and add compare URLs.
- SECURITY.md: supported versions 0.4.x -> 0.5.x.
Minor (not patch) bump: a relicense is a significant change. No code changes.
NOTE: do not tag/release until you give the go (irreversible publish to crates.io/PyPI/npm). Suggested merge order: #158 -> this -> tag `v0.5.0` -> then the downstream PRs.
Relicenses Wickra from PolyForm Noncommercial 1.0.0 to the dual, OSI-approved **MIT OR Apache-2.0** (the de-facto Rust convention). Wickra becomes permissive, commercial-use-permitted open source; users may choose either license.
## Changes
- Replace `LICENSE` (PolyForm) with `LICENSE-MIT` + `LICENSE-APACHE` (full texts).
- Cargo: workspace `license = "MIT OR Apache-2.0"` (SPDX) + all 7 sub-crates switched from `license-file.workspace` to `license.workspace`.
- `deny.toml`: drop PolyForm from the allowlist.
- Python: `pyproject.toml` PEP 639 SPDX expression; remove the non-commercial classifier (verified: sdist metadata emits `License-Expression: MIT OR Apache-2.0`).
- Node: `package.json`, the 6 platform manifests and both lockfiles.
- README + Python/Node/WASM binding READMEs, CONTRIBUTING, CITATION.cff, PR template, and the WASM `pkg.license` step in `release.yml`.
- SECURITY.md: refresh supported versions 0.1.x -> 0.4.x.
- CHANGELOG: note the relicense under [Unreleased].
## Notes
- No code changes; metadata/text only. `cargo build` and `cargo deny check licenses` pass locally.
- GitHub will auto-detect "MIT, Apache-2.0" once this lands (currently NOASSERTION).
- Matching downstream changes (org `.github` profile, webpage, docs) are in separate PRs; merge those together with the relicense release so the live sites and org profile do not claim MIT before the packages do.
Version bump for 0.4.5: ships Anchored RSI, Volume Profile, TPO Profile and the Alt-Chart Bars family (Renko/Kagi/Point & Figure). Indicator count 289 -> 295.
Release 0.4.4.
Version bump only — no code changes. Ships the 40 TA-Lib candlestick patterns
(parts 2–9, #132–#141, 249 → 289 indicators) plus the candlestick rejection-
guard coverage tests (#142) that landed on `main` since 0.4.3.
Bumped: workspace `Cargo.toml` (+ `wickra-core` dep) and `Cargo.lock`,
`bindings/python/pyproject.toml`, `bindings/node/package.json` (+ 6 platform
`optionalDependencies`), the 6 `bindings/node/npm/*/package.json`, both
`package-lock.json` files, and `CHANGELOG.md` ([Unreleased] → [0.4.4]).
The LICENSE now carries an Additional Permissions section on top of
PolyForm Noncommercial 1.0.0, so the bare SPDX id no longer describes
it exactly. Update the package manifests to reference the actual file
instead of claiming the unmodified standard:
- Cargo (workspace + all crates): license -> license-file = "LICENSE"
- npm (main + 6 platform packages): LicenseRef-Wickra-Noncommercial-1.0.0
- PyPI: license text notes the additional personal-account permissions
Releases the cross-asset / pairwise indicator family (PR #109):
PairwiseBeta, PairSpreadZScore, LeadLagCrossCorrelation, Cointegration,
RelativeStrengthAB. Indicator count 214 -> 219.
Bumps workspace + binding versions and the CHANGELOG ([Unreleased] ->
[0.4.1]) with the new compare URL.
Minor release. The headline user-facing change is the Node binding now
rejecting invalid indicator periods instead of silently clamping period 0
to 1 (matches Python/WASM/core); plus per-ecosystem binding READMEs and a
corrected MSRV statement in CONTRIBUTING. See CHANGELOG [0.4.0].
- Cargo.toml (workspace.package + wickra-core dep) + Cargo.lock (6 members)
- bindings/python/pyproject.toml
- bindings/node/package.json (version + 6 optionalDependencies) + package-lock.json
- bindings/node/npm/*/package.json (6 platform subpackages)
- examples/node/package-lock.json (wickra-* platform pins)
- CHANGELOG: [Unreleased] -> [0.4.0] - 2026-05-31 + compare URL
No tag pushed (release publish is a separate, user-confirmed step).
The documentation now lives in the wickra-lib/wickra-docs VitePress repo and
will deploy to docs.wickra.org. Rewrite every tracked, user-facing wiki link
in the main repo to the new canonical site:
- docs/README.md, CONTRIBUTING.md, PULL_REQUEST_TEMPLATE.md
- bindings/{node,python,wasm}/README.md, examples/wasm/README.md
- repo-metadata.toml: wiki_url/wiki_git -> docs_url/docs_git
Page paths map 1:1 to VitePress clean URLs (e.g. /wiki/Quickstart-Rust.md ->
docs.wickra.org/Quickstart-Rust). The sync-about.yml wiki-sync step is left
untouched on purpose: it stays until the docs site is live (tracked as P8.3).
The GitHub wiki itself is not deleted yet for the same reason.
* examples(node): add RSI mean-reversion strategy
Node counterpart of strategy_rsi_mean_reversion.{py,rs}: RSI(14) < 30 long,
> 70 exit, 0.1% fees, hourly BTCUSDT. Output verified byte-identical to the
Rust reference (37 trades W24/L13, -17.84% return, 46.89% max drawdown).
* examples(node): add MACD + ADX trend-filter strategy
Node counterpart of strategy_macd_adx.{py,rs}: MACD(12,26,9) histogram
crossover entries gated by ADX(14) > 20, hourly BTCUSDT, 0.1% fees. Output
verified byte-identical to the Rust reference (246 trades W90/L156, -47.19%
return, 53.75% max drawdown).
* examples(node): add Bollinger-squeeze breakout strategy
Node counterpart of strategy_bollinger_squeeze.{py,rs}: enter on a fresh
180-bar Bollinger-bandwidth low + close above the upper band, exit on a
2*ATR(14) stop or upper-band collapse, daily BTCUSDT, 0.1% fees. Output
verified byte-identical to the Rust reference (1 trade, -7.82% return,
13.01% max drawdown).
* examples(wasm): add RSI mean-reversion strategy demo
Browser counterpart of strategy_rsi_mean_reversion.{py,js,rs}: RSI(14) < 30
long, > 70 exit, 0.1% fees, summary table. Same signal/fill/PnL/equity loop as
the runtime-verified Node example; loads via the established wickra_wasm.js
init + fetch-CSV pattern. (wasm32 build runs in CI.)
* examples(wasm): add MACD + ADX trend-filter strategy demo
Browser counterpart of strategy_macd_adx.{py,js,rs}: MACD(12,26,9) histogram
crossover gated by ADX(14) > 20, hourly BTCUSDT, 0.1% fees. Logic identical to
the runtime-verified Node example; standard wickra_wasm.js init + fetch-CSV
loader. (wasm32 build runs in CI.)
* examples(wasm): add Bollinger-squeeze breakout strategy demo
Browser counterpart of strategy_bollinger_squeeze.{py,js,rs}: fresh 180-bar
Bollinger-bandwidth low + upper-band breakout, 2*ATR(14) stop, daily BTCUSDT,
0.1% fees. Logic identical to the runtime-verified Node example; standard
wickra_wasm.js init + fetch-CSV loader. (wasm32 build runs in CI.)
* ci: add examples syntax-smoke job (P2.3)
The Rust examples are built by 'cargo build -p wickra-examples --bins'; the
Node, browser-WASM and Python examples had no build gate. New job parse-checks
every examples/{node,wasm}/*.js, extracts and node --checks each WASM .html
module script, and python -m py_compile's every examples/python/*.py — so a
broken example edit fails CI instead of landing silently.
* docs(examples): list the new Node + WASM strategy examples
Add the three Node strategy scripts and three WASM strategy demos to the
examples README tables, bringing Node and WASM to parity with the existing
Rust and Python strategy rows.
* chore(examples): refresh examples/node lockfile for the linked wickra binding
npm install rewrote the file: dependency snapshot of the local wickra binding
that the examples link against (version 0.1.4 -> 0.3.1, license + engines
fields), which had gone stale in the committed lockfile.
* test(node): add input-validation suite
Node counterpart of bindings/python/tests/test_input_validation.py: invalid
constructor parameters (ATR zero period, MACD non-increasing fast/slow,
BollingerBands negative multiplier, PSAR step > max, ValueArea period/pct,
InitialBalance/OpeningRange zero period, Ichimoku non-increasing periods,
Ehlers-family ordering) and unequal-length candle/ValueArea batch inputs all
throw a JS Error. Validated against the built binding.
* test(node): add indicator completeness contract
Introspects every exported indicator class and asserts the full interface
(update / batch / reset / isReady / warmupPeriod) plus the pre-warmup contract
for zero-arg indicators, and guards that the full catalogue (>= 200 classes)
is exported. Catches a new indicator wired without the standard methods, or a
stale/partial native build dropping exports, with no per-indicator boilerplate.
* test(wasm): broaden scalar streaming-vs-batch coverage
Extend the inline wasm-bindgen-test suite with a streaming==batch check across
~70 scalar indicators spanning moving averages, momentum, volatility,
statistics/regression, Ehlers/cycle and risk/performance families (previously
only EMA + the candle-input group were covered per-indicator), plus four more
invalid-constructor assertions. Constructor args mirror the CI-passing Node
factories. Host-compiles (cargo test -p wickra-wasm --no-run); executed in CI
via wasm-pack test --node.
* bench(node): add indicator throughput benchmark
Node counterpart of the Rust criterion benches / Python compare_libraries:
measures streaming (per-tick update) and batch throughput in Mupd/s across a
representative indicator set over a synthetic OHLCV series (--bars, default
200k). Dependency-free; wired as 'npm run bench'.
* docs(wasm): list strategy demos + document the benchmark story
Add the three new strategy demos to the WASM examples table and a Performance
section: parallel_assets.html is the in-browser benchmark, with raw throughput
covered by the Rust criterion / Python / Node benchmarks (the WASM engine is the
same core compiled to wasm32).
* chore: remove ROADMAP.md from the public repo
ROADMAP is kept as a local-only draft (ghost-ignored via
.git/info/exclude); it is not part of the published package surface.
* release: bump 0.3.0 -> 0.3.1
CI-only patch: fixes the release.yml CycloneDX SBOM step (cargo-cyclonedx
has no -p flag, see #79) that skipped the GitHub Release attach-assets job
on 0.3.0. No library changes — republishes the same code with a working
release pipeline.
- Cargo.toml (workspace.package + wickra-core dep) + Cargo.lock
- bindings/python/pyproject.toml
- bindings/node/package.json (version + 6 optionalDependencies) + package-lock.json
- bindings/node/npm/*/package.json (6 platform subpackages)
- CHANGELOG: finalize [0.3.0] (was still under [Unreleased]), add [0.3.1]
* chore: track examples/node/package-lock.json
Since the global package-lock ignore rule was dropped (#68) this file was
left untracked. Commit it for reproducible example installs, consistent
with bindings/node (findings P4.1).
Wires real indicators into complete signal -> fill -> PnL -> equity
loops over the checked-in BTCUSDT datasets, with per-trade Sharpe and
max-drawdown reported on stdout. Closes the gap where existing
examples showed only the mechanics of calling `update`/`batch` but not
how Wickra plugs into a trading-system shape.
Three strategies, each in Rust + Python (six files total):
- strategy_rsi_mean_reversion — RSI(14) thresholds (30/70) on 1h
BTCUSDT. Binary position, 0.1% per-trade fee.
- strategy_macd_adx — MACD crossover entries gated by ADX(14) > 20 on
1h BTCUSDT. Trend-follower demo of multi-indicator gating.
- strategy_bollinger_squeeze — Bollinger-bandwidth 180-day-low squeeze
+ upper-band breakout entry, ATR(14) * 2 stop. On 1d BTCUSDT for
interpretable lookback.
Each file is self-contained — print_summary is inlined per script so
the example stays a single-file read. Every script prints a
NOT-financial-advice notice next to its results.
examples/README.md updated to list the new bins/scripts.
Introduce repo-metadata.toml as single source of truth for repo identity
(org slug, maintainer email, canonical URLs) and add sync-metadata.yml
workflow with a Python audit script that fails CI if any tracked file
drifts back to pre-migration values.
Bulk-replace across 24 tracked files:
- kingchenc/wickra -> wickra-lib/wickra (URL segment)
- kingchencp@gmail.com -> wickra.lib@gmail.com (maintainer email)
- @kingchenc -> @wickra-lib (CODEOWNERS mention only)
Person-name credits are preserved: LICENSE copyright holder, Cargo.toml
authors handle, and CHANGELOG historical @kingchenc reference all remain
unchanged. Crate / PyPI / npm package names also untouched.
Merge this PR only after the kingchenc/wickra -> wickra-lib/wickra org
transfer has happened on the GitHub side, otherwise all badges and
repository links 404 until the transfer is performed.
The 84 markdown files under docs/wiki/ are now published to the
project's GitHub Wiki at https://github.com/kingchenc/wickra/wiki —
a separate git repository (https://github.com/kingchenc/wickra.wiki.git)
that GitHub hosts natively with its own UI, search and history. The
flat layout that the GitHub Wiki requires has been generated, all
internal cross-links rewritten, and a _Sidebar.md groups the 71
indicators by their canonical 8 families.
Effects:
- docs/wiki/ is removed from the main repo (-84 files). docs/README.md
now just points readers at the Wiki.
- PR template + CONTRIBUTING text updated to point at the Wiki instead
of the in-repo path. The Wiki repo is separately cloneable and
editable via the GitHub web UI.
- examples/wasm/README.md cross-link fixed to use the Wiki URL.
- The (still in-repo) CHANGELOG keeps its historical references to
docs/wiki/ paths — those describe what the tree looked like at past
releases and stay accurate as history.
- README.md, license, all source unaffected.
The Wiki itself ships with _Sidebar.md / _Footer.md generated from the
8-families taxonomy and 503/503 cross-links resolved.
* examples/README.md — replace the single-row WASM section with a build
block (one-time `wasm-pack` build), a serve note, and the full
five-row table (`index`, `backtest`, `live_trading`, `multi_timeframe`,
`parallel_assets`).
* examples/wasm/README.md — new dedicated index for the WASM demos
with the build and serve commands and a description of every file
including the module worker companion.
* CHANGELOG.md `[Unreleased]` gains three bullets: the Python and Node
`fetch_btcusdt` siblings; the four new WASM browser demos; and the
three new wiki pages from Z6 (TA-Lib-Migration, Cookbook, FAQ).
Close the final "parallel assets" cell of the cross-language matrix for
WASM.
* examples/wasm/parallel_assets.html — generates a synthetic
`(assets, bars)` panel deterministically (the LCG matches the Node
and Rust siblings so timings are directly comparable), runs the
serial baseline on the main thread, then dispatches the same workload
to a pool of module Workers and reports the speedup. The render is
three cards (serial / parallel / speedup) plus a sanity-check line
asserting per-asset agreement between the two paths.
* examples/wasm/parallel_worker.js — companion module worker that
loads its own copy of the WebAssembly module via `init()` and
processes whichever slice of the panel its parent dispatches.
Modern browsers ship module-worker support (`new Worker(url, {
type: "module" })`) which lets every worker do `import init, { SMA, RSI
} from "../../bindings/wasm/pkg/wickra_wasm.js"` without bundler
glue. The inline page module and the worker module both syntax-check
cleanly under `node --check`.
Close the "multi-timeframe" cell of the cross-language matrix for WASM.
* examples/wasm/multi_timeframe.html — fetches the bundled 1-minute
BTCUSDT CSV (or any 1-minute OHLCV CSV), rolls it up in-page to 5m,
15m, 1h, 4h and 1d buckets, and prints RSI(14), MACD(12,26,9)
histogram and ADX(14) per timeframe via the WebAssembly bindings.
Same inline-bucket aggregation as the Node sibling, same indicator
set as the Python and Rust siblings — the Rust version uses
`wickra-data::Resampler` directly which is currently a Rust-only API.
The render is a single table (one row per timeframe) so the cross-
language outputs sit side-by-side cleanly. The inline module script
syntax-checks cleanly under `node --check`.
Close the "live trading" cell of the cross-language matrix for WASM.
* examples/wasm/live_trading.html — opens a native browser `WebSocket`
to Binance's public kline stream, feeds every close through RSI(14),
MACD(12,26,9) and Bollinger(20, 2.0) via the WebAssembly bindings, and
flags BUY/SELL candidates when all three indicators agree. Mirrors
the Node and Python live-trading examples in indicator set, signal
logic and symbol/interval validation — the symbol is checked against
`^[A-Za-z0-9]+$` before being spliced into the stream URL, the
interval against the public-API allow-list.
The UI shows live close / RSI / MACD-histogram / Bollinger-band cards,
plus a scrolling log of the last 200 ticks with signal rows highlighted.
Browser-native `WebSocket` means no library dependency. Build the WASM
module once (`wasm-pack build bindings/wasm --target web --release
--features panic-hook`), serve the repository root and open
`examples/wasm/live_trading.html`.
The WASM example set had only `index.html` (the streaming canvas demo);
the "backtest" cell of the cross-language matrix was empty. Close it.
* examples/wasm/backtest.html — loads the wasm-pack `--target web`
bundle, fetches an OHLCV CSV from the same `examples/data/` directory
the other languages use (default: `btcusdt-1d.csv`), parses it
in-page and streams every candle through SMA, EMA, RSI, MACD,
Bollinger, ATR, ADX and OBV via the WebAssembly bindings. Renders a
summary table with mean / min / max / last per series — mirrors the
Rust, Python and Node backtest examples both in indicator set and in
output shape.
Build the WASM module once (`wasm-pack build bindings/wasm --target web
--release --features panic-hook`), then serve the repository root and
open `examples/wasm/backtest.html`. The inline module script
syntax-checks cleanly under `node --check` on the extracted body.
Node had no sibling for the Rust and Python `fetch_btcusdt`
data-generators — adding it closes the "fetch (data-gen)" cell for the
last remaining row of the cross-language example matrix where the
pattern makes sense.
* examples/node/fetch_btcusdt.js — uses Node 18+'s built-in global
`fetch` (no npm dependencies); same pagination logic as the Rust and
Python siblings (paginate backwards via `endTime`, drop the
in-progress bucket, sort and trim to the configured target). Applies
the same OHLC validity check the Rust `Candle::new` constructor
enforces so a malformed kline is skipped rather than written.
* JavaScript's `String(v)` already gives the shortest round-trip
representation and strips the `.0` suffix for whole-number floats, so
the CSV output is byte-for-byte identical to what the Rust and
Python fetchers produce on the same Binance snapshot. Verified by
running it and `git diff`-ing against the checked-in dataset: every
row older than the run is unchanged; only the most recent ~24 hours
drift because the market kept moving.
examples/README.md gains the new row.
Python had no sibling for the Rust `fetch_btcusdt` data-generator —
adding it closes the "fetch (data-gen)" cell for Python and lets users
without a Rust toolchain regenerate the bundled BTCUSDT datasets.
* examples/python/fetch_btcusdt.py — uses only the standard library
(urllib.request + json + csv); same pagination strategy as the Rust
version (paginate backwards via `endTime`, drop the in-progress
bucket, sort and trim to the configured target). Applies the same
OHLC validity check the Rust `Candle::new` constructor enforces
(finite fields, high >= low/open/close, low <= open/close,
volume >= 0) so a malformed kline is skipped rather than written.
* Number formatting matches Rust's `f64` Display: shortest round-trip,
no trailing `.0` for whole-number floats. Verified by running the
script and `git diff`-ing against the checked-in dataset: every row
older than the run is byte-identical to Rust's output; the diff only
shows the most recent ~24 hours where Binance has produced fresh
candles since the original snapshot.
examples/README.md gains the new row.
Python's parallel_assets.py demoed GIL-release multi-core throughput;
Rust and Node both lacked a sibling that shows their own native
parallelism. Close the gap with two real, runnable examples.
* examples/rust/src/bin/parallel_assets.rs — synthesises an (assets,
bars) panel with a deterministic per-asset LCG, runs a serial baseline,
then `Sma::batch_parallel` / `Rsi::batch_parallel` via rayon, asserts
the two outputs are element-wise identical and prints the speedup.
Toggle indicator with `--indicator sma|rsi`.
* examples/node/parallel_assets.js — same shape, but the parallel run is
a `worker_threads` pool that re-loads the native binding in each
worker. Each worker computes the last non-null indicator value for its
slice; the main thread aggregates and verifies serial == parallel
per asset.
Both examples report timings and the serial-vs-parallel sanity check
passes. Defaults (200 × 5000) keep the example fast on dev hardware;
larger `--assets`/`--bars` is where the speedup numbers move (Node's
worker spawn cost dominates the smallest sizes, which is honest and
educational).
examples/README.md gains the two new rows.
Python's examples/python/multi_timeframe.py had no Rust or Node sibling.
Add both — the Rust version uses wickra-data's `Resampler` /
`resample_all` (the canonical path; no manual roll-up), the Node version
mirrors the Python one's inline aggregation because wickra-data's
resampler is currently Rust-only.
* examples/rust/src/bin/multi_timeframe.rs — reads the bundled 1m CSV via
`CandleReader`, resamples to 5m / 15m / 1h / 4h / 1d via `resample_all`,
prints last RSI(14), MACD(12,26,9) histogram and ADX(14) per timeframe.
* examples/node/multi_timeframe.js — same outputs from a hand-rolled
bucket aggregator; reuses the new examples/data/ default path.
* examples/README.md gains the new rows.
Run side by side: the Rust and Node summaries are bit-identical at every
timeframe (50000 / 10000 / 3334 / 834 / 209 / 35 bars; same RSI, MACD
histogram and ADX to two decimals) — confirming both the Rust resampler
and the inline Node aggregator produce the same OHLC buckets.
Python and Rust both lacked a standalone "streaming indicators" example
that mirrors examples/node/streaming.js — the quickstart docs cover the
pattern, but a runnable file makes the parity visible across all four
languages.
* examples/python/streaming.py — argparse-driven synthetic streaming demo
feeding SMA(20) / EMA(20) / RSI(14) / MACD(12,26,9), tagging BUY?/SELL?
candidates when RSI extremes and MACD-histogram direction agree.
* examples/rust/src/bin/streaming.rs — same demo as a wickra-examples
binary, reusing the seeded LCG so its first 40 rows are bit-identical
to the Python (and Node) sibling — a strong cross-language consistency
signal verified by running both side by side.
* examples/README.md gains a `streaming` row in the Rust and Python tables.
Finish the per-language `examples/<lang>/` restructure by relocating the
WASM browser demo from bindings/wasm/examples/ to examples/wasm/.
* `examples/wasm/index.html` is the moved file; its WASM module import
becomes `../../bindings/wasm/pkg/wickra_wasm.js` so the demo still loads
the wasm-pack output without copying it.
* bindings/wasm/README.md, Quickstart-WASM.md, examples/README.md and the
root README "Languages" + project-layout block all point at the new
path. The serve command in the docs now says "serve the repository root
and open examples/wasm/index.html".
`bindings/wasm/examples/` is empty after the move; the now-empty
directory is removed.
Continue the per-language `examples/<lang>/` restructure: move the three
Node example files (streaming.js, backtest.js, live_trading.js) out of
bindings/node/examples/ and into a top-level examples/node/ directory.
* `examples/node/package.json` is a `private` package that pulls the
native binding via `file:../../bindings/node` and lists `ws` as a
dev-dependency for the live-trading example. `require('..')` in each
file becomes `require('wickra')` — exactly what a downstream user would
write — and the file-header run instructions are updated to the new
two-step workflow (`npm install` in bindings/node, then in
examples/node).
* `backtest.js`'s default-CSV path becomes the much shorter
`__dirname/../data/btcusdt-1d.csv` from the new location.
* `bindings/node/package.json` drops the now-unused `ws` devDependency.
* `.gitignore` is broadened from `bindings/node/node_modules/` to
`**/node_modules/` so the new `examples/node/node_modules/` directory is
not tracked.
* The README "Languages" table, project-layout block and
`examples/README.md` Node section are updated for the new paths and run
commands.
Verified by running `node backtest.js` (3200 BTCUSDT daily bars, matching
output), `node streaming.js`, and `node --check live_trading.js` from the
new location.
The three Rust examples (backtest, fetch_btcusdt, live_binance) used to
live each in their own crate's examples/ dir, splitting the example set
across crates and burying it inside the source tree. Move them into a new
workspace member crate at `examples/rust/` (package `wickra-examples`,
`publish = false`) so all language examples sit under one top-level
`examples/<lang>/` tree.
* `examples/rust/Cargo.toml` declares the per-binary deps (wickra,
wickra-data with the `live-binance` feature always on, serde_json, tokio
for the macro and current-thread runtime).
* `examples/rust/src/bin/{backtest,fetch_btcusdt,live_binance}.rs` are the
three migrated binaries; their doc-comments and the fetch_btcusdt output
path are updated for the new location and run command
(`cargo run -p wickra-examples --bin <name>`).
* Workspace `Cargo.toml` lists the new member; the now-empty
`[dev-dependencies]` extras (`wickra`, `tokio` in wickra-data and
`serde_json` in wickra) that existed only for these examples are dropped.
* The `[[example]] live_binance` table is removed from wickra-data's
manifest since the file moved out.
* README "Languages" + project-layout, examples/README.md, Quickstart-Rust
and Data-Layer are pointed at the new paths and commands.
`cargo build -p wickra-examples` and `cargo run --release -p wickra-examples
--bin backtest -- examples/data/btcusdt-1d.csv` both succeed; the rest of
the workspace (core, data, wickra) builds, clippies (`--all-targets -D
warnings`) and tests (508 core + 28 data + 1 integration + 74+3+1
doctests) all stay green.
The seven BTCUSDT OHLCV datasets used to live under
crates/wickra/examples/data/, which buried them inside a Rust crate even
though the Node backtest example and the upcoming Rust/Node/WASM example
restructure need to reach them too. Move them to the workspace-level
examples/data/ so every language's examples can resolve the same path.
The bench (crates/wickra/benches/indicators.rs), the example_data
integration test, fetch_btcusdt.rs and the Node backtest example all take
the new ../../examples/data/ path; Data-Layer.md, examples/README.md and
the CHANGELOG entry are updated to match. No data file content changes.
The top-level examples/ directory held only python/, which made the
examples look Python-only even though Rust, Node and WASM all ship their
own. Add examples/README.md: a single index of every runnable example
across Rust, Python, Node and WASM, each with its run command, plus a note
on the bundled BTCUSDT datasets.
Point the README "Languages" table at the Node backtest example and link
the new index from both the table and the project-layout section.