Files
kingchenc 3ebcb3f758 Per-binding throughput benchmarks + test-coverage gaps (#246)
Adds a `throughput` benchmark to every target and closes two small
test-coverage documentation/QA gaps. One PR, no merge of binding code beyond
the additive benchmarks and one C test.

## 1. Per-binding throughput benchmarks (all 9 targets)

Each benchmark feeds a deterministic synthetic OHLCV series through three
indicators chosen by **FFI call-signature archetype** (not algorithm — the same
Rust core runs underneath all bindings):

- `SMA(20)` — 1-in → 1-out (baseline boundary cost)
- `ATR(14)` — multi-in → 1-out (input marshalling)
- `MACD(12,26,9)` — 1-in → multi-out (output marshalling)

Streaming is timed for all three; batch for the single-output SMA and ATR
(median of 3 runs, after a warmup pass).

New: Python (PyO3), WASM, C (CMake), C# (Stopwatch), Go, Java (FFM), R, and the
Rust core baseline (`examples/rust/.../throughput.rs`, **no FFI** — the ceiling
the bindings are measured against and the value their batch paths converge
towards). Node already had `throughput.js`.

**Not a speed claim:** there is no comparable streaming TA library for C, C#,
Go, Java, R or WASM to compare against, so these are raw per-binding throughput
numbers documenting each language's FFI overhead — see BENCHMARKS.md §3. The
"Wickra is fast" claim still lives in §1/§2 (Rust core + the Python/Rust
cross-library runs).

## 2. README `## Testing`: C# and C bullets

The section listed every layer except C# and C, even though both have suites.
Adds the two missing bullets.

## 3. C archetype ctest

`examples/c/archetypes.c` drives one indicator per FFI archetype through the
real C boundary (scalar + batch==streaming, multi-output, bars, profile, array
input) plus reset, invalid-parameter and NULL-safety — the C counterpart of the
Go/R/Java archetype suites. Runs on three OSes via the existing CMake/ctest.

## Notes

- Benchmarks are not CI-gated (manual-run scripts, like the existing
  `throughput.js`); no `ci.yml`/`release.yml` changes.
- Docs: BENCHMARKS.md §3, a `## Benchmark` section in every binding README, a
  CHANGELOG entry.
- Verified locally by running: Rust, Python, C, C#, Go, Java (real numbers); the
  C archetype ctest with `-Wall -Wextra -Wpedantic -Werror`. WASM and R are
  API-correct and syntax-checked but need their own toolchains to run.
2026-06-10 03:46:38 +02:00
..

Wickra — C / C++ examples

The Wickra C ABI is a single shared/static library plus a generated header (bindings/c/include/wickra.h). Any C-capable language links against the same artifact; these examples show the plain-C path.

Build the library

From the workspace root:

cargo build -p wickra-c --release

This produces, in target/release/:

Platform Shared library Link target
Linux libwickra.so -lwickra
macOS libwickra.dylib -lwickra
Windows (MSVC) wickra.dll wickra.dll.lib (import lib)

A static library (libwickra.a / wickra.lib) is emitted alongside.

Build and run the smoke example

With CMake (portable, used by CI)

cmake -S examples/c -B examples/c/build -DWICKRA_LIB_DIR="$PWD/target/release"
cmake --build examples/c/build
ctest --test-dir examples/c/build --output-on-failure

Directly with a compiler

# Linux / macOS
cc examples/c/smoke.c -I bindings/c/include -L target/release -lwickra -lm -o smoke
LD_LIBRARY_PATH=target/release ./smoke        # macOS: DYLD_LIBRARY_PATH

# Windows (MinGW gcc, linking the DLL directly)
gcc examples/c/smoke.c -I bindings/c/include target/release/wickra.dll -lm -o smoke.exe

Expected output:

OK: wickra C ABI smoke passed (SMA streaming + batch + reset + NULL-safety + free)

The examples

Example What it does
smoke.c Links the boundary and asserts SMA streaming / batch / reset / NULL-safety values.
streaming.c Feeds a synthetic price series through SMA / EMA / RSI / MACD tick by tick.
backtest.c Runs an indicator basket over an OHLCV CSV (defaults to the bundled daily dataset).
multi_timeframe.c Resamples the bundled 1-minute CSV to 5m / 15m / 1h / 4h / 1d and prints indicators per timeframe.
parallel_assets.c Serial vs OpenMP fan-out over a synthetic panel (one handle per asset), with speedup.
strategy_rsi_mean_reversion.c Hourly RSI(14) mean-reversion with a PnL / Sharpe / max-drawdown summary.
strategy_macd_adx.c Hourly MACD crossover gated by ADX(14) > 20.
strategy_bollinger_squeeze.c Daily Bollinger-squeeze breakout with an ATR(14) stop.
fetch_btcusdt.c Downloads BTCUSDT klines from the Binance REST API into examples/data/ (shells out to curl).
live_binance.c Polls the Binance REST klines endpoint via curl and streams closed candles through RSI(14).
smoke.cpp C++ RAII via wickra::Handle from wickra.hpp.

ctest builds and runs every example except fetch_btcusdt and live_binance, which reach the network and are built only — run those two by hand. The C ABI exposes only the indicators, not the wickra-data IO layer, so the examples read CSV (wickra_csv.h) and resample themselves; the network ones shell out to the system curl rather than adding an HTTP/TLS dependency.

Usage shape

Every indicator follows the same five-function pattern over an opaque handle:

#include "wickra.h"

struct Sma *sma = wickra_sma_new(14);     /* NULL on invalid params */
double v = wickra_sma_update(sma, 42.0);  /* NaN during warmup */
wickra_sma_reset(sma);                     /* back to fresh state */
wickra_sma_free(sma);                      /* exactly once per _new */

There is no RAII across the C boundary: every wickra_<ind>_new must be paired with exactly one wickra_<ind>_free. All functions are NULL-safe (a NULL handle yields NaN / a no-op, never a crash).