wickra-backtest-wasm 0.1.5 → 0.1.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +71 -71
- package/package.json +1 -1
- package/wickra_backtest_wasm_bg.wasm +0 -0
package/README.md
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
<p align="center">
|
|
2
|
-
<a href="https://wickra.org"><img src="https://raw.githubusercontent.com/wickra-lib/.github/main/profile/wickra-banner.webp?v=514" alt="Wickra Backtest — backtest and live are byte-identical" width="100%"></a>
|
|
2
|
+
<a href="https://wickra.org"><img src="https://raw.githubusercontent.com/wickra-lib/.github/main/profile/wickra-banner.webp?v=514-7" alt="Wickra Backtest — backtest and live are byte-identical" width="100%"></a>
|
|
3
3
|
</p>
|
|
4
4
|
|
|
5
5
|
[](https://github.com/wickra-lib/wickra)
|
|
6
|
-
[](https://github.com/wickra-lib/wickra-backtest)
|
|
7
7
|
[](https://github.com/wickra-lib/wickra-backtest/actions/workflows/ci.yml)
|
|
8
8
|
[](https://github.com/wickra-lib/wickra-backtest/actions/workflows/codeql.yml)
|
|
9
9
|
[](https://codecov.io/gh/wickra-lib/wickra-backtest)
|
|
@@ -29,9 +29,11 @@
|
|
|
29
29
|
event-driven backtester built on the [Wickra](https://github.com/wickra-lib/wickra)
|
|
30
30
|
indicator core.
|
|
31
31
|
|
|
32
|
-
> **▶ Live
|
|
32
|
+
> **▶ Live demos:** the backtester compiled to WebAssembly, an equity curve building bar by bar — **[backtest-live.wickra.org](https://backtest-live.wickra.org)**;
|
|
33
|
+
> one StrategySpec side by side in Python, Rust, JS and Go — **[playground.wickra.org](https://playground.wickra.org)**;
|
|
34
|
+
> all 514 indicators of the core over a real Binance feed — **[live.wickra.org](https://live.wickra.org)**. Zero backend, all of them.
|
|
33
35
|
|
|
34
|
-
|
|
36
|
+
**Part of the [Wickra ecosystem](#ecosystem):** the same data-driven core and ten-language binding surface also power [wickra-exchange](https://github.com/wickra-lib/wickra-exchange), [wickra-terminal](https://github.com/wickra-lib/wickra-terminal), [wickra-screener](https://github.com/wickra-lib/wickra-screener) and 20 more — see [the full list](https://github.com/wickra-lib).
|
|
35
37
|
|
|
36
38
|
The engine consumes the **exact same `wickra-core` O(1) indicator kernels** that
|
|
37
39
|
power live Wickra, and a strategy is **data (a JSON spec), not code** — so a
|
|
@@ -78,6 +80,13 @@ with wbt.StreamingBacktest(spec=spec) as live:
|
|
|
78
80
|
The two reports are byte-identical. That is the whole claim, and a shared
|
|
79
81
|
[golden corpus](golden/) holds every one of the ten bindings to it.
|
|
80
82
|
|
|
83
|
+
## Status
|
|
84
|
+
|
|
85
|
+
**0.1.7 — the current release.** The engine, the data-driven `StrategySpec`, the
|
|
86
|
+
full execution and cost model, the microstructure feeds and all ten language
|
|
87
|
+
bindings are implemented and tested; a shared [golden corpus](golden/) pins the
|
|
88
|
+
cross-language equality byte-for-byte.
|
|
89
|
+
|
|
81
90
|
## Documentation
|
|
82
91
|
|
|
83
92
|
- **[Strategy spec reference](docs/STRATEGY_SPEC.md)** — the full DSL: operands,
|
|
@@ -123,15 +132,6 @@ runs unchanged from ten languages and a shared golden corpus pins every one of
|
|
|
123
132
|
them to the same report, byte for byte. No other engine in this table offers that
|
|
124
133
|
because none of them needs to.
|
|
125
134
|
|
|
126
|
-
## Status
|
|
127
|
-
|
|
128
|
-
**Alpha / work in progress.** The engine, the data-driven `StrategySpec`, the
|
|
129
|
-
full execution and cost model, the microstructure feeds and all ten language
|
|
130
|
-
bindings are implemented and tested; a shared [golden corpus](golden/) pins the
|
|
131
|
-
cross-language equality byte-for-byte. Released as **v0.1.0** to every registry:
|
|
132
|
-
crates.io, PyPI, npm, NuGet, Maven Central, the Go module proxy and
|
|
133
|
-
R-universe.
|
|
134
|
-
|
|
135
135
|
## Quickstart
|
|
136
136
|
|
|
137
137
|
A strategy is **data** — a JSON spec. Run one over a candle file with the `wkbt` CLI:
|
|
@@ -174,7 +174,7 @@ the **same engine** one bar at a time — backtest and live are one code path. A
|
|
|
174
174
|
single `run_json` request bundles candles, the spec and any feeds, and is the
|
|
175
175
|
uniform entry point every binding wraps.
|
|
176
176
|
|
|
177
|
-
##
|
|
177
|
+
## Use in any language
|
|
178
178
|
|
|
179
179
|
Every binding takes the same OHLCV arrays (or a `run_json` request) and JSON spec
|
|
180
180
|
and returns the same report — byte-identical (a dict in Python). Each has a
|
|
@@ -201,63 +201,6 @@ The C, C++, C#, Go, Java and R bindings all call through the same C ABI hub; the
|
|
|
201
201
|
both the plain OHLCV path and the order-book / trade / derivatives /
|
|
202
202
|
cross-section feed paths.
|
|
203
203
|
|
|
204
|
-
## Benchmarks
|
|
205
|
-
|
|
206
|
-
O(1) per bar — about **1.7M bars/second** on one core (a year of 1-minute bars in
|
|
207
|
-
~0.3 s). The cost of a bar is bounded by the indicators the spec configures, never
|
|
208
|
-
by how much history precedes it. Full tables and how to reproduce them live in
|
|
209
|
-
**[BENCHMARKS.md](BENCHMARKS.md)**.
|
|
210
|
-
|
|
211
|
-
### Pick your language with eyes open — per-binding throughput
|
|
212
|
-
|
|
213
|
-
Every binding drives the **same** Rust engine, so this is **not** a speed claim —
|
|
214
|
-
it is the raw cost of crossing each language's FFI boundary, measured with the
|
|
215
|
-
[shared example strategy](examples/ema-cross.json) over 100,000 bars (median of
|
|
216
|
-
three runs, one development machine). **Batch collapses towards the floor;
|
|
217
|
-
streaming is where the boundary shows** — so if you drive a live loop bar by bar,
|
|
218
|
-
the table tells you which binding keeps up.
|
|
219
|
-
|
|
220
|
-
| Binding | streaming | ns/bar | batch | ns/bar |
|
|
221
|
-
|---------|----------:|-------:|------:|-------:|
|
|
222
|
-
| C | 6,750,000 b/s | 148 | 6,548,000 b/s | 153 |
|
|
223
|
-
| C# | 6,188,000 b/s | 162 | 6,315,000 b/s | 158 |
|
|
224
|
-
| Go | 4,621,000 b/s | 216 | 6,448,000 b/s | 155 |
|
|
225
|
-
| Java | 4,493,000 b/s | 223 | 5,565,000 b/s | 180 |
|
|
226
|
-
| WASM | 4,127,000 b/s | 242 | 4,878,000 b/s | 205 |
|
|
227
|
-
| Node | 3,438,000 b/s | 291 | 2,530,000 b/s | 395 |
|
|
228
|
-
| Python | 1,411,000 b/s | 709 | 1,486,000 b/s | 673 |
|
|
229
|
-
| R | 284,000 b/s | 3,527 | 6,213,000 b/s | 161 |
|
|
230
|
-
|
|
231
|
-
**C is the floor**: it calls the exported functions directly, with no marshalling
|
|
232
|
-
of its own, so its ~148 ns/bar is the engine plus a function call — every other
|
|
233
|
-
row is that number plus what the language adds. Two results are the opposite of
|
|
234
|
-
what one might assume: **Node's batch path is slower than its streaming path**
|
|
235
|
-
(marshalling six JavaScript arrays across napi costs more than 100,000 scalar
|
|
236
|
-
calls), and **WASM beats the native Node binding on both paths**. All ten share
|
|
237
|
-
one verified implementation, so the *numbers* differ but the *values* do not.
|
|
238
|
-
Methodology and the per-binding discussion are in
|
|
239
|
-
[BENCHMARKS.md](BENCHMARKS.md#per-binding-throughput--the-cost-of-the-boundary).
|
|
240
|
-
|
|
241
|
-
## Requirements
|
|
242
|
-
|
|
243
|
-
The minimum supported version per language. The same engine kernel runs behind
|
|
244
|
-
every binding; the C-ABI bindings that compile on install — Go (cgo) and R
|
|
245
|
-
(`.Call`) — also need a C compiler, and Java runs with
|
|
246
|
-
`--enable-native-access=ALL-UNNAMED`.
|
|
247
|
-
|
|
248
|
-
| Language | Package | Minimum supported |
|
|
249
|
-
|----------|-------------------------------------------|----------------------------|
|
|
250
|
-
| Rust | crates.io · `wickra-backtest` | 1.86 (MSRV) |
|
|
251
|
-
| Python | PyPI · `wickra-backtest` (abi3 wheel) | 3.9 (tested through 3.13) |
|
|
252
|
-
| Node.js | npm · `wickra-backtest` (N-API 8) | 22 (tested on 22 · 24 LTS) |
|
|
253
|
-
| WASM | npm · `wickra-backtest-wasm` | any modern JS engine |
|
|
254
|
-
| C | `wickra_backtest.h` + library (releases) | C99 compiler |
|
|
255
|
-
| C++ | the C ABI + optional `wickra_backtest.hpp` | C++14 compiler |
|
|
256
|
-
| C# | NuGet · `Wickra.Backtest` | .NET 8 (`net8.0`) |
|
|
257
|
-
| Go | module · `wickra-lib/wickra-backtest-go` | Go 1.23 (cgo) |
|
|
258
|
-
| Java | Maven Central · `org.wickra:wickra-backtest` | Java 22 (FFM / Panama) |
|
|
259
|
-
| R | r-universe · `wickrabacktest` | R ≥ 2.10 (Rtools on Win.) |
|
|
260
|
-
|
|
261
204
|
## Project layout
|
|
262
205
|
|
|
263
206
|
```
|
|
@@ -364,6 +307,63 @@ than argued.
|
|
|
364
307
|
> compare to a relative tolerance instead. None currently does, and that is a
|
|
365
308
|
> property of the corpus worth keeping deliberately rather than by accident.
|
|
366
309
|
|
|
310
|
+
## Requirements
|
|
311
|
+
|
|
312
|
+
The minimum supported version per language. The same engine kernel runs behind
|
|
313
|
+
every binding; the C-ABI bindings that compile on install — Go (cgo) and R
|
|
314
|
+
(`.Call`) — also need a C compiler, and Java runs with
|
|
315
|
+
`--enable-native-access=ALL-UNNAMED`.
|
|
316
|
+
|
|
317
|
+
| Language | Package | Minimum supported |
|
|
318
|
+
|----------|-------------------------------------------|----------------------------|
|
|
319
|
+
| Rust | crates.io · `wickra-backtest` | 1.86 (MSRV) |
|
|
320
|
+
| Python | PyPI · `wickra-backtest` (abi3 wheel) | 3.9 (tested through 3.13) |
|
|
321
|
+
| Node.js | npm · `wickra-backtest` (N-API 8) | 22 (tested on 22 · 24 LTS) |
|
|
322
|
+
| WASM | npm · `wickra-backtest-wasm` | any modern JS engine |
|
|
323
|
+
| C | `wickra_backtest.h` + library (releases) | C99 compiler |
|
|
324
|
+
| C++ | the C ABI + optional `wickra_backtest.hpp` | C++14 compiler |
|
|
325
|
+
| C# | NuGet · `Wickra.Backtest` | .NET 8 (`net8.0`) |
|
|
326
|
+
| Go | module · `wickra-lib/wickra-backtest-go` | Go 1.23 (cgo) |
|
|
327
|
+
| Java | Maven Central · `org.wickra:wickra-backtest` | Java 22 (FFM / Panama) |
|
|
328
|
+
| R | r-universe · `wickrabacktest` | R ≥ 4.1 (Rtools on Win.) |
|
|
329
|
+
|
|
330
|
+
## Benchmarks
|
|
331
|
+
|
|
332
|
+
O(1) per bar — about **1.7M bars/second** on one core (a year of 1-minute bars in
|
|
333
|
+
~0.3 s). The cost of a bar is bounded by the indicators the spec configures, never
|
|
334
|
+
by how much history precedes it. Full tables and how to reproduce them live in
|
|
335
|
+
**[BENCHMARKS.md](BENCHMARKS.md)**.
|
|
336
|
+
|
|
337
|
+
### Pick your language with eyes open — per-binding throughput
|
|
338
|
+
|
|
339
|
+
Every binding drives the **same** Rust engine, so this is **not** a speed claim —
|
|
340
|
+
it is the raw cost of crossing each language's FFI boundary, measured with the
|
|
341
|
+
[shared example strategy](examples/ema-cross.json) over 100,000 bars (median of
|
|
342
|
+
three runs, one development machine). **Batch collapses towards the floor;
|
|
343
|
+
streaming is where the boundary shows** — so if you drive a live loop bar by bar,
|
|
344
|
+
the table tells you which binding keeps up.
|
|
345
|
+
|
|
346
|
+
| Binding | streaming | ns/bar | batch | ns/bar |
|
|
347
|
+
|---------|----------:|-------:|------:|-------:|
|
|
348
|
+
| C | 6,750,000 b/s | 148 | 6,548,000 b/s | 153 |
|
|
349
|
+
| C# | 6,188,000 b/s | 162 | 6,315,000 b/s | 158 |
|
|
350
|
+
| Go | 4,621,000 b/s | 216 | 6,448,000 b/s | 155 |
|
|
351
|
+
| Java | 4,493,000 b/s | 223 | 5,565,000 b/s | 180 |
|
|
352
|
+
| WASM | 4,127,000 b/s | 242 | 4,878,000 b/s | 205 |
|
|
353
|
+
| Node | 3,438,000 b/s | 291 | 2,530,000 b/s | 395 |
|
|
354
|
+
| Python | 1,411,000 b/s | 709 | 1,486,000 b/s | 673 |
|
|
355
|
+
| R | 284,000 b/s | 3,527 | 6,213,000 b/s | 161 |
|
|
356
|
+
|
|
357
|
+
**C is the floor**: it calls the exported functions directly, with no marshalling
|
|
358
|
+
of its own, so its ~148 ns/bar is the engine plus a function call — every other
|
|
359
|
+
row is that number plus what the language adds. Two results are the opposite of
|
|
360
|
+
what one might assume: **Node's batch path is slower than its streaming path**
|
|
361
|
+
(marshalling six JavaScript arrays across napi costs more than 100,000 scalar
|
|
362
|
+
calls), and **WASM beats the native Node binding on both paths**. All ten share
|
|
363
|
+
one verified implementation, so the *numbers* differ but the *values* do not.
|
|
364
|
+
Methodology and the per-binding discussion are in
|
|
365
|
+
[BENCHMARKS.md](BENCHMARKS.md#per-binding-throughput--the-cost-of-the-boundary).
|
|
366
|
+
|
|
367
367
|
## Ecosystem
|
|
368
368
|
|
|
369
369
|
Part of the [Wickra](https://github.com/wickra-lib/wickra) family — each one a
|
package/package.json
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
"kingchenc <support@wickra.org>"
|
|
6
6
|
],
|
|
7
7
|
"description": "WebAssembly bindings for the wickra-backtest streaming backtester — backtest in the browser.",
|
|
8
|
-
"version": "0.1.
|
|
8
|
+
"version": "0.1.7",
|
|
9
9
|
"license": "MIT OR Apache-2.0",
|
|
10
10
|
"repository": {
|
|
11
11
|
"type": "git",
|
|
Binary file
|