* docs: standardise language naming and add binding security sections
Canonical binding list everywhere: Rust, Python, Node.js, WASM, C, C++, C#,
Go, Java, R. Use C# (not .NET) as the language label, WASM (not WebAssembly)
in prose, and frame the C ABI as a hub rather than a list item.
- Bump stale indicator counts (200+ -> 514) and family count (sixteen ->
twenty-four) in the Node/Python/WASM and docs READMEs.
- Add a short Security section to all eight binding READMEs.
- Relabel benchmark rows (C -> C / C++, C# / .NET -> C#).
- Fix the 'language stecker' wording in the C#/Go/R API intros.
- Documentation only; no code or public API changes.
* release.yml: extend install snippets and expose version output
Add the missing registry installs to the release body (dotnet, go, Gradle/
Maven Central, r-universe) alongside cargo/pip/npm, and expose a v-stripped
'version' output from the tag step for the Gradle coordinate. Also fix the
C-ABI language order in the assets note (C# before Go).
* release.yml: correct the release body (10 languages, all registries)
Reframe the tagline to '10 languages' (native Rust/Python/Node.js/WASM + a C
ABI hub for C, C++, C#, Go, Java, R) instead of '4 language registries', note
that C#/Java/Go/R publish to NuGet/Maven/Go/r-universe via their own jobs, and
tidy the Node.js label and the C-ABI hub list.
The first language stecker on the C ABI hub: a .NET binding exposing all 514
indicators as idiomatic `IDisposable` classes, generated from `wickra.h`.
## What's here
- **`bindings/csharp/`** — the `Wickra` .NET 8 package. `[LibraryImport]`
source-generated P/Invoke (`NativeMethods.g.cs`) plus idiomatic wrappers
(`Indicators.g.cs`), both generated from the committed `bindings/c/include/wickra.h`.
The binding owns no indicator maths — it only marshals types across the C ABI.
- **Marshalling, verified end-to-end against the native library.** Opaque handles
cross as `nint` kept alive per call via a `SafeHandle`; `bool` as
`[MarshalAs(U1)]` (Rust `bool` is one byte); a self-correcting
`DllImportResolver` validates the loaded library actually exports the Wickra
ABI. Tests cover one representative per FFI archetype (scalar, candle, pairwise,
multi-output, bars, profile, values-profile, order-book / array-input) plus
exact Sma reference values.
- **NuGet packaging** — `dotnet pack` produces `Wickra.<version>.nupkg`; the
release pipeline stages prebuilt native libraries under `runtimes/<rid>/native/`
for six target triples (win/linux/osx × x64/arm64).
- **`examples/csharp/`** — nine examples mirroring `examples/c/`: streaming,
backtest, multi_timeframe, parallel_assets, three strategies, and
fetch_btcusdt + live_binance.
- **CI** — a `csharp` job on the three OSes builds the C ABI, tests the binding,
and runs the offline examples. **Release** — a gated `csharp-publish` job packs
and pushes to NuGet (gated on `NUGET_API_KEY`, independent of the GitHub-release
job so a C# hiccup never blocks the C/C++ asset release).
- **Docs consistency wave** — README, CONTRIBUTING, CHANGELOG, examples/README,
the issue / PR templates, `sync-about.yml`, and `.gitattributes`.
The native Python / Node / WASM bindings and the C ABI are untouched; this is
additive. Publishing to NuGet stays gated behind the release tag and the secret.
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).
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.
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.