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

Declarations added by the host before your code (do not redeclare them)
SymbolMeaningNotes
struct OfBarbucket_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 nPlotted 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 buyOnly the last bar's intent is read; qty, stopTicks and targetTicks come from the script parameters
OF_CAPACITY256Bars 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 editorThe first "script.cpp:N:M: error" sets the highlighted line

Engine states and controls

States of the C++ toolchain strip and the buttons shown in each
StateShown asAvailable action
absentNot installed + size noteInstall the C++ toolchain
downloadingDownloading the engine… {percent}%Cancel the download
startingStarting the engine…none (boot timeout 120 s)
readyEngine ready, version and start time, limitsRemove the engine (purges worker modules and the IndexedDB cache)
errorEngine unavailable + messageTry 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.

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.

Keep reading