C++ scripts: the WebAssembly Clang toolchain and ABI v1
Senzoukria can compile a C++17 script to WebAssembly inside its sandbox with a real Clang, then run it on the chart's bars. The toolchain is downloaded once on request, verified by size and SHA-256, and exposes a small ABI: of_compute plots one value per bar, of_strategy returns buy/sell intents for the simulated account.
Senzoukria · Documentation · Updated September 2026
Where to find it
- Where
- Scripting page → language selector → C++ (a "C++ toolchain" strip appears above the code editor)
- Toolchain
- Clang 8.0.1 + LLD + libc++ compiled to WebAssembly, pinned to Binji wasm-clang commit 648c4a89; about 60.4 MB (shown as "60.4 Mo") downloaded once
- Capacity
- 256 most recent bars per call; source up to 64 KiB; 2 s per run; compile timeout 45 s
- Strategy scope
- Simulated account only; the app never turns a C++ intent into a broker order
What it does
The C++ engine is the third scripting language next to JavaScript and Python. Choosing C++ in the language selector of the Scripting page shows the "C++ toolchain" strip. Its first state is "Not installed" with the button "Install the C++ toolchain" and the note "About 60.4 Mo to download, once (Clang 8.0.1 + LLD + libc++, Apache-2.0).". The five files (clang, lld, memfs, sysroot.tar, shared.js) are fetched from the pinned GitHub commit, each one rejected if its byte count or SHA-256 differs from the value written in the app, and stored in IndexedDB so the download happens only once.
Starting the engine compiles about 50 MB of WebAssembly, which is why "Starting the engine…" is a visible state distinct from a script run. Once ready, the strip prints "Version wasm-clang-648c4a89, started in {ms} ms" followed by the limits line. Each script is compiled once, keyed by the SHA-256 of the composed source (host header + your code); re-running the same script at chart cadence never recompiles. The host keeps up to 8 compiled modules, the worker keeps 8 as well.
The ABI your script sees
| Symbol | Meaning | Notes |
|---|---|---|
| struct OfBar | bucket_ts_ns (int64), open, high, low, close, volume, delta (double), trades (uint32) | 64 bytes, oldest bar first, n ≤ 256 |
| int of_compute(const OfBar* bars, uint32_t n, double* out, uint32_t out_len) | Write one value per bar into out[i]; NaN means no value; return n | Plotted as a single green line (#7ed321, width 1) on the chart |
| int of_strategy(const OfBar* bars, uint32_t n, int32_t* out, uint32_t out_len) | Write one intent per bar: −1 sell, 0 nothing, +1 buy | Only the last bar's intent is read; qty, stopTicks and targetTicks come from the script parameters |
| OF_CAPACITY | 256 | Bars older than the capacity are not transmitted; a warning line says how many were skipped |
| #line 1 "script.cpp" | Line numbers in diagnostics match your editor | The first "script.cpp:N:M: error" sets the highlighted line |
Engine states and controls
| State | Shown as | Available action |
|---|---|---|
| absent | Not installed + size note | Install the C++ toolchain |
| downloading | Downloading the engine… {percent}% | Cancel the download |
| starting | Starting the engine… | none (boot timeout 120 s) |
| ready | Engine ready, version and start time, limits | Remove the engine (purges worker modules and the IndexedDB cache) |
| error | Engine unavailable + message | Try again |
How to use it
Create a new script, pick C++ and start from the default template: a 20-period simple moving average written with a running sum, NaN during warm-up, returning n. Run it with the same Run button as JavaScript scripts. Compiler warnings and errors arrive in the console as log lines; a run that exceeds the 2-second budget fails like any other script. Only one C++ template ships today, that moving average; there is no ready-made C++ strategy. Writing of_strategy yourself is enough: its intents follow the same decision path as JavaScript strategies, toward the simulated evaluation account only.
If a chart holds more than 256 bars, the console prints "C++ ABI v1 computes the 256 most recent bars: N older bar(s) have no value." Older bars are simply drawn without a value rather than filled with a guess.
Limits and pitfalls
- C++17 is supported; C++20 is explicitly not promised. Headers such as <cmath>, <vector> and <numeric> are available from libc++.
- Source is limited to 64 KiB including the host header; the compiled module may use up to 64 MiB of memory.
- The engine downloads from raw.githubusercontent.com only; a redirect is refused and a file whose size or hash differs is rejected before it reaches the sandbox.
- If the sandbox restarts or the toolchain is removed during a compilation, the run reports "sandbox restarted or toolchain removed during compilation — run again".
- Running a C++ script before the toolchain is installed returns "C++ toolchain not started — install it from the Scripting page"; the run succeeds automatically once the engine is ready.
Related pages
- User indicator editor on the chart
- Script outputs: overlay, pane, table and panel
- Script assistant (AI)
- Test a trading strategy
This page in other languages
Frequently asked questions
- Does the C++ toolchain need an internet connection every time?
- No. The five files are downloaded once, verified and kept in IndexedDB. Later starts read the cache and run entirely offline; "Remove the engine" clears that cache.
- Can a C++ strategy send orders to my broker?
- No. of_strategy produces −1/0/+1 intents that are converted into decisions for the simulated account, through the same path as JavaScript strategies. No script in Senzoukria places a broker order.
- Why does my indicator stop after 256 bars?
- ABI v1 transmits the 256 most recent bars per call. Older bars have no value and the console says how many were skipped.