Architecture
From source to a bounded run
What happens to a script, in order, and what holds it in check. This describes the engine that runs member scripts in MillionChart.
The stages
- Source
- A script is text. It carries an explicit edition, so that a later edition can change the language without changing the meaning of an old script.
- Lex and parse
- The text becomes a tree. Every node keeps its place in the source, so that a message can point at a line.
- Check
- Names, types, effects and limits are checked before anything runs. Problems are reported with a stable code.
- Lower
- The tree is reduced to one small core form, so that the later stages handle few cases.
- Compile
- The core form becomes closures. The compiler does not generate source code and does not evaluate text as code.
- Run
- The closures run once per bar, from the first to the last, inside the limits.
- Output
- Plots, marks, drawings, tables, alerts and simulated trades.
The execution model
- A script runs once per bar, from the top to the bottom.
- A call that keeps state moves that state only when execution reaches the call. If control flow skips it on a bar, its state does not change on that bar.
- The chart runs this language only. There is no second syntax at run time; a script written for another platform reaches it only through the experimental converter in the editor, which turns a limited subset into a Cuprel script before it is saved. See Import.
- A script cannot place real orders, read data the chart does not have, or run without limits.
- A failure is a result with a code and a place in the source, not an uncontrolled crash.
Classes of effect
Every built-in function is recorded with what it does, and the same is derived for functions written in a script. The checker, the converter, the replay and the memory ledger read one table, so they cannot disagree about what a call does.
| Class | What it means |
|---|---|
| Temporal | Keeps a state for each call site and advances it when the call is reached. |
| Mutating | Changes a collection in place. |
| Drawing and output | Makes or changes something on the chart, or writes to an output channel of the run. |
| Alert | Can raise an alert, or end the run with the script's own error. |
| Simulated order | Places, changes or cancels a simulated order or a risk rule. Nothing reaches a broker. |
| Data request | Reads data that the chart did not load for the script, such as another symbol or timeframe. |
| Allocation | Builds or grows a collection, a text or a drawing, and so counts against memory. |
| Account read | Reads the simulated account. It cannot be moved across an order. |
| Configuration | May appear only before the run and is evaluated once. |
The sandbox
A script is code we did not write. Scripts are private to your account and, in this release, run in your browser only. Sharing is not available. Where a server runs one, the script does not run in the server's own process.
- It runs in a worker thread that has an empty environment, so the host's secrets are not there to read.
- The worker has a memory limit, and it is stopped from outside when its time is spent.
- The only way in for member code is one job interface; a failure comes back as a result.
- Logs about a stopped job carry a short hash of the source, never the text.
The limits are listed on Resources.