From 120b6ac26523619ee059b622ababae36bf4f420b Mon Sep 17 00:00:00 2001 From: kingchenc Date: Mon, 15 Jun 2026 05:07:52 +0200 Subject: [PATCH] docs+ci: surface 10-language golden verification (#303) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * docs+ci: surface 10-language golden verification; add WASM golden CI - README: add C++ to the Quickstart list and state prominently that all 514 indicators are replayed through all 10 languages and checked bit-for-bit against the Rust reference. - CHANGELOG: document the cross-language golden suite, the Java and R C-ABI bool-marshalling fixes, the C# nullable directive and the live_binance rename. - ci.yml: run the WASM golden suite (nodejs-target build + node --test); the C/C++ golden tests already run via the C-ABI job's ctest and the other bindings pick up their golden runners in their existing test suites. * readme: add verified badge + prominent per-language throughput table - Add the 'verified across 10 languages' badge to the badge row, linking to the FAQ that explains the cross-language golden parity. - Surface a per-binding throughput table (the cost of each language's FFI boundary) so readers can pick a binding that keeps up with streaming hot loops — the cross-library benchmarks stay in BENCHMARKS.md. * changelog: note the verified badge and per-binding throughput table * docs: fix cross-language consistency (audit) - docs/README.md: add the missing C++ quickstart link. - README testing section: the golden parity now covers all 10 languages and all 514 indicators (was 'four C-ABI bindings, 7 archetype indicators'). - CHANGELOG: the live_binance rename also covers the C examples. --- .github/workflows/ci.yml | 6 +++++ CHANGELOG.md | 36 ++++++++++++++++++++++++++++ README.md | 51 ++++++++++++++++++++++++++++++++++------ docs/README.md | 1 + 4 files changed, 87 insertions(+), 7 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1d78ab26..7a39b126 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -566,6 +566,12 @@ jobs: test -f bindings/wasm/pkg/wickra_wasm_bg.wasm test -f bindings/wasm/pkg/wickra_wasm.d.ts + - name: Build WASM package (nodejs target) for the golden suite + run: wasm-pack build bindings/wasm --target nodejs --release --out-dir pkg + + - name: Golden parity — all 514 indicators vs the Rust reference + run: node --test bindings/wasm/tests/golden.test.js + node: name: Node ${{ matrix.node-version }} on ${{ matrix.os }} runs-on: ${{ matrix.os }} diff --git a/CHANGELOG.md b/CHANGELOG.md index 9e5b02ea..c5c40f39 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,7 +7,43 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Added +- **Cross-language golden parity for all 514 indicators across all 10 languages.** + A new `gen_golden` reference emits a deterministic OHLCV input series plus the + Rust output of every one of the 514 indicators to `testdata/golden/`. Each + binding now replays that shared input and is checked **bit-for-bit against the + Rust reference**, covering every archetype (scalar, multi-output, pairwise, + derivatives-tick, cross-section, order-book, trade, profile, alt-chart bars, + footprint): + - Python, Node.js, Java and R via reflection-driven runners. + - Go, C# and C/C++ via generated dispatch (`golden_all_test.go`, + `GoldenAllTests.g.cs`, `examples/c/golden_test.c` compiled as both C and C++). + - WASM via a `node --test` runner over the nodejs-target build. +- CI now runs the WASM golden suite; the C/C++ golden tests run as `ctest` + targets in the existing C-ABI job, and the Python/Node/Go/C#/Java/R suites pick + up their golden runners automatically. +- **README:** a "verified across 10 languages" badge (linking to the FAQ that + explains the cross-language golden parity) and a per-binding throughput table so + readers can pick a binding by its streaming FFI cost. + +### Fixed +- **Java binding marshalled C ABI `bool` parameters incorrectly.** The + cross-section state flags (`newHigh`, `newLow`, `aboveMa`, `onBuySignal`) were + allocated as `JAVA_DOUBLE` arrays and passed to `const bool*` parameters, so the + native side read the low byte of each 8-byte double and saw every flag as + `false` (affecting e.g. `NewHighsNewLows`, `HighLowIndex`, `BullishPercentIndex`, + `PercentAboveMa`). They are now packed into a real `bool` buffer. `MacdExt`'s + `MaType` arguments are now passed as `byte` to match the `uint8_t` downcall. +- **R binding marshalled C ABI `bool` flags incorrectly.** `(bool *)REAL(x)` + reinterpreted the 8-byte doubles as 1-byte bools across the 15 cross-section + update wrappers, reading every flag as `false`; the flags are now converted into + a real C `bool` buffer. +- C# binding: added the `#nullable enable` directive the generated + `Indicators.g.cs` requires, clearing four `CS8669` warnings. + ### Changed +- Renamed the `live_trading` examples to `live_binance` across the Python, Node.js, + WASM and C examples — they poll Binance market data, they do not place trades. - **Breaking — de-duplicated four indicators that computed identically to another one.** Each is now its own distinct, correctly-defined indicator (the catalogue stays at the same count): diff --git a/README.md b/README.md index fb539524..5f99721f 100644 --- a/README.md +++ b/README.md @@ -18,6 +18,7 @@ [![OpenSSF Best Practices](https://raw.githubusercontent.com/wickra-lib/.github/main/profile/badges/best-practices.svg)](https://www.bestpractices.dev/projects/13094) [![Build provenance](https://raw.githubusercontent.com/wickra-lib/.github/main/profile/badges/provenance.svg)](https://github.com/wickra-lib/wickra/attestations) [![Docs](https://raw.githubusercontent.com/wickra-lib/.github/main/profile/badges/docs.svg)](https://docs.wickra.org) +[![Verified across 10 languages](https://raw.githubusercontent.com/wickra-lib/.github/main/profile/badges/verified.svg)](https://docs.wickra.org/FAQ#do-all-the-language-bindings-compute-the-same-values) **Streaming-first technical indicators. Install with `pip install wickra` — no system dependencies.** @@ -53,6 +54,7 @@ Full documentation lives at **[docs.wickra.org](https://docs.wickra.org)**: [Node](https://docs.wickra.org/Quickstart-Node), [WASM](https://docs.wickra.org/Quickstart-WASM), [C](https://docs.wickra.org/Quickstart-C), + [C++](https://docs.wickra.org/Quickstart-C), [C#](https://docs.wickra.org/Quickstart-CSharp), [Go](https://docs.wickra.org/Quickstart-Go), [Java](https://docs.wickra.org/Quickstart-Java), @@ -89,6 +91,11 @@ times to get there. runs a real warmup, and returns an `Option` so a single bad tick can't silently poison state. `batch == streaming` is **bit-exact, fuzzed and 100 %-line-covered for all 514 indicators**. +- **Identical across every language — proven, not promised.** All 514 indicators + are replayed through **all 10 languages** (Rust · Python · Node.js · WASM · C · + C++ · C# · Go · Java · R) and checked **bit-for-bit against the Rust reference** + via shared golden fixtures in CI. The math is verifiably the same everywhere — + this very check caught and fixed two real cross-language marshalling bugs. - **Orders of magnitude faster where it counts.** In streaming Wickra is **11–56×** faster than the only other incremental peer and **thousands of times** faster than recompute-on-every-tick libraries. On batch it wins several rows outright @@ -137,12 +144,38 @@ elsewhere for `None`-warmup, NaN-safety and bit-exact `batch == streaming`. Full tables (Rust + Python, streaming + batch) and how to reproduce them live in **[BENCHMARKS.md](BENCHMARKS.md)**. +### Pick your language with eyes open — per-binding throughput + +Every binding calls the **same** Rust core, so this is **not** a speed claim — it +is the raw cost of crossing each language's FFI boundary (`SMA(20)`, 200 000 bars, +Ryzen 9 9950X, million updates/sec). **Batch is near-core everywhere; streaming is +where the boundary shows** — so if you stream tick-by-tick, the table tells you +which binding keeps up and which to avoid for hot loops. + +| Language | streaming (Mupd/s) | batch (Mupd/s) | +|-----------------|-------------------:|---------------:| +| Rust (no FFI) | 391 | 500 | +| C / C++ | 383 | 330 | +| C# | 337 | 244 | +| Python | 33 | 488 | +| Java | 28 | 175 | +| Go | 24 | 400 | +| WASM | 19 | 167 | +| Node.js | 17 | 10 | +| R | 0.1 | 193 | + +All ten share one verified implementation (see the verification badge above), so +the *numbers* differ but the *values* are bit-for-bit identical. Methodology and +the per-indicator breakdown are in [BENCHMARKS.md](BENCHMARKS.md#3-per-binding-throughput--the-cost-of-the-boundary). + ## Indicators 514 streaming-first indicators across twenty-four families. Every one passes the `batch == streaming` equivalence test, reference-value tests, and reset -semantics tests. Each has a per-indicator deep dive (formula, parameters, -warmup) at [docs.wickra.org](https://docs.wickra.org/Indicators-Overview). +semantics tests — and is replayed through **all 10 languages** and checked +bit-for-bit against the Rust reference (golden fixtures, in CI). Each has a +per-indicator deep dive (formula, parameters, warmup) at +[docs.wickra.org](https://docs.wickra.org/Indicators-Overview). | Family | Indicators | |--------|-----------| @@ -381,11 +414,15 @@ Every layer is covered; run the suites with the commands in - `bindings/java`: JUnit cases covering one indicator per FFI archetype (scalar/batch, multi-output, bars, profile, array input) plus batch equivalence. -The four C-ABI bindings (C#, Go, Java, R) additionally replay a shared, -language-neutral golden fixture (`testdata/golden/*.csv`, generated by -`cargo run -p wickra-examples --bin gen_golden`) and assert exact parity with the -Rust reference outputs across every archetype (SMA, EMA, RSI, ATR, MACD, ADX, -Beta), catching FFI wiring bugs the math-only core tests cannot see. +On top of those per-binding tests, **all 10 languages** (Rust, Python, Node.js, +WASM, C, C++, C#, Go, Java, R) replay a shared, language-neutral golden fixture +(`testdata/golden/*.csv`, generated by +`cargo run -p wickra-examples --bin gen_golden`) and assert **bit-for-bit parity +with the Rust reference for every one of the 514 indicators** across every +archetype (scalar, multi-output, pairwise, derivatives-tick, cross-section, +order-book, trade, profile, alt-chart bars, footprint). This catches FFI wiring +bugs the math-only core tests cannot see — it has already found and fixed real +cross-language marshalling bugs in the Java and R bindings. ## Contributing diff --git a/docs/README.md b/docs/README.md index 15d089c7..9b394557 100644 --- a/docs/README.md +++ b/docs/README.md @@ -9,6 +9,7 @@ That includes: [Node](https://docs.wickra.org/Quickstart-Node), [WASM](https://docs.wickra.org/Quickstart-WASM), [C](https://docs.wickra.org/Quickstart-C), + [C++](https://docs.wickra.org/Quickstart-C), [C#](https://docs.wickra.org/Quickstart-CSharp), [Go](https://docs.wickra.org/Quickstart-Go), [Java](https://docs.wickra.org/Quickstart-Java), and