Running an Indicator
Compiling AlgoBeamScript, executing it against bars, and reading the result object.
There are two ways to run an indicator. The indicators namespace exposes the standard library as ready-made TypeScript factories, which is the fastest path when you only need an RSI or a moving average. For anything you wrote yourself, read the .algo file and pass it to compile, which returns a compiled script you can execute many times without paying the parse cost again.
Compilation is a pure function from source text to a script object. It reports errors with line and column and never throws for a runtime reason, because there is no runtime yet. Compile once at process start, or at build time, and keep the result — recompiling on every request is the most common performance mistake in a server deployment.
Execution takes the compiled script and the loaded bars and returns a result. The result carries plots keyed by their titles, each with the full value series and the last value; the alert conditions that evaluated true and on which bars; any labels the script emitted; and diagnostics such as the number of bars where a value was na. Everything is plain data and serialises to JSON without a transform.
Inputs can be overridden at run time by passing an inputs object to run. Keys are the input labels declared in the script, and unknown keys are rejected rather than ignored so a typo does not silently leave the default in place. That is how one compiled script serves many parameter sets — a sweep is a loop over an array of input objects, not a loop over files.
Results are deterministic. The same bars and the same inputs produce byte-identical output on any platform, which is what makes it reasonable to cache a result by a hash of its inputs and to assert on exact values in tests.
Example
Load bars and run an indicator
import { AlgoBeamTS, Provider, indicators } from 'algobeam-ts'
// provider, symbol, timeframe, how many bars of history to load
const algobeam = new AlgoBeamTS(Provider.Binance, 'BTCUSDT', '1h', 100)
async function main() {
const bars = await algobeam.load()
const last = bars.at(-1)
if (!last) throw new Error('provider returned no bars')
const rsi = await algobeam.run(indicators.rsi({ length: 14 }))
const ema = await algobeam.run(indicators.ema({ length: 50, source: 'close' }))
console.log('bars loaded ', bars.length)
console.log('last close ', last.close.toFixed(2))
console.log('rsi(14) ', rsi.last.toFixed(2))
console.log('ema(50) ', ema.last.toFixed(2))
console.log('regime ', rsi.last > 55 && ema.rising ? 'expansion' : 'neutral')
}
main().catch((error: unknown) => {
console.error('[algobeam] run failed', error)
process.exitCode = 1
})Copy it, change one input, and run it again — the numbers are deterministic, so a difference in the output is always a difference you made.