docs+ci: surface 10-language golden verification (#303)

* 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.
This commit is contained in:
kingchenc
2026-06-15 05:07:52 +02:00
committed by GitHub
parent 4f708d410d
commit 120b6ac265
4 changed files with 87 additions and 7 deletions
+6
View File
@@ -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 }}
+36
View File
@@ -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):
+44 -7
View File
@@ -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 **1156×**
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
+1
View File
@@ -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