Building Custom Indicators with Pine-Script-like Syntax
How our strategy lab's scripting layer borrows the readability of Pine Script to help you go from idea to plotted indicator in minutes.
If you’ve written a Pine Script indicator before, the strategy lab’s scripting layer should feel immediately familiar — that’s on purpose. Rather than inventing a new domain-specific language, we leaned on syntax and conventions traders already know, and compiled it down to something that runs safely inside our sandboxed executor.
Why not just use raw JavaScript?
We considered it. The problem is that raw JavaScript gives you too much rope: file
system access, network calls, unbounded loops. A scripting surface meant for market
logic should make the easy things easy — sma(), stdev(), crossover() — and make
the dangerous things impossible, not just discouraged. Pine-Script-like syntax gets us
both: a small, declarative vocabulary for describing a series, and a runtime that never
has to trust the script.
A minimal example
study("Momentum Band", overlay = true)
length = input(20)
basis = sma(close, length)
band = stdev(close, length) * 2
plot(basis, color = color.accent)
plot(basis + band, color = color.muted)
plot(basis - band, color = color.muted)
That’s a full indicator: a 20-period moving average with a two-standard-deviation band around it, plotted directly on the price pane. Compile it, attach it to a chart, and it updates on every new candle the same way a built-in indicator would.
What happens after you hit compile
- The script is parsed and type-checked against the available series functions.
- It’s compiled into a bounded, callback-driven program the Node executor can run per-candle without holding onto state it shouldn’t.
- Successful compilations are persisted, so re-running the same strategy later doesn’t recompile from scratch.
- Output is streamed back over the run’s WebSocket channel as plot points, so the chart updates live while the run is in flight.
Where to go from here
Start from one of the built-in indicator templates in the Code drawer, change one
input, and recompile. Once you’re comfortable with plot() and the built-in series
functions, move on to conditional logic — if crossover(fast, slow) is usually the
first real “strategy” moment for people coming from simple indicators.