Walk through writing your first QuantScript programs, from Hello World to building trading indicators and strategies.
First, install QuantScript dependencies:
npm installCompile the QuantScript language package:
npm run buildYou can run QuantScript scripts using the CLI:
# Using the built CLI
quantscript run your-script.qs
# Or during development, use tsx directly
npm run dev -- run your-script.qsThe CLI automatically provides sample OHLCV data (100 bars of simulated price data) when you run a script.
Create a file called hello.qs:
indicator("Hello World");
console.log("Hello, World!");Run it:
quantscript run hello.qsOutput:
── QuantScript Indicator ──
Hello, World!
Execution complete.What's happening:
indicator("Hello World") declares this as an indicator script with a titleconsole.log() prints text to the consoleEvery QuantScript script follows this pattern:
// 1. Declaration (required)
indicator("My Script Name");
// OR
strategy("My Strategy Name");
// 2. Global code (executed once)
let myVariable = 10;
// 3. DataFrame iteration (executed per bar)
df.forEach((frame) => {
// Process each bar
});Create math-example.qs:
indicator("Math Example");
let x = 10;
const PI = 3.14159;
let sum = x + 5;
let product = x * 2;
let power = 2 ** 8;
console.log("Sum: " + tostring(sum));
console.log("Product: " + tostring(product));
console.log("Power: " + tostring(power));QuantScript uses a DataFrame to represent market data. The CLI automatically provides sample OHLCV (Open, High, Low, Close, Volume) data.
Use df.forEach() to iterate through each bar:
indicator("OHLCV Display");
df.forEach((frame) => {
let openPrice = frame.open;
let highPrice = frame.high;
let lowPrice = frame.low;
let closePrice = frame.close;
let volume = frame.volume;
if (bar_index < 5) {
console.log("Bar " + tostring(bar_index));
console.log(" Close: " + tostring(closePrice));
}
});QuantScript provides pre-computed derived bar values:
df.forEach((frame) => {
let midpoint = frame.hl2; // (high + low) / 2
let avgThree = frame.hlc3; // (high + low + close) / 3
let avgFour = frame.ohlc4; // (open + high + low + close) / 4
});Available: frame.hl2, frame.hlc3, frame.hlcc4, frame.ohlc4.
Access previous bars using bracket notation:
df.forEach((frame) => {
let currentClose = frame.close;
let previousClose = close[1]; // 1 bar ago
let twoBarsAgo = close[2]; // 2 bars ago
});indicator("SMA Indicator");
const SMA_LENGTH = 20;
df.forEach((frame) => {
let sma = ta.sma(frame.close, SMA_LENGTH);
chart.plot(sma, "SMA", "#FF0000");
});indicator("Multiple Indicators");
df.forEach((frame) => {
let fastSMA = ta.sma(frame.close, 10);
let slowSMA = ta.sma(frame.close, 20);
let ema = ta.ema(frame.close, 20);
chart.plot(fastSMA, "Fast SMA", "#00FF00");
chart.plot(slowSMA, "Slow SMA", "#FF0000");
chart.plot(ema, "EMA", "#0000FF");
if (ta.crossover(fastSMA, slowSMA)) {
console.log("BULLISH CROSSOVER");
}
});strategy("SMA Crossover",
initial_capital: 100000,
default_qty_type: "fixed",
default_qty_value: 100
);
df.forEach((frame) => {
let fastSMA = ta.sma(frame.close, 10);
let slowSMA = ta.sma(frame.close, 20);
let crossUp = ta.crossover(fastSMA, slowSMA);
let crossDown = ta.crossunder(fastSMA, slowSMA);
if (crossUp) {
strategy.entry("Long", "long");
}
if (crossDown) {
strategy.close("Long");
}
});strategy("RSI Strategy",
initial_capital: 50000
);
const RSI_LENGTH = 14;
df.forEach((frame) => {
let rsi = ta.rsi(frame.close, RSI_LENGTH);
if (rsi < 30 && strategy.position_size == 0) {
strategy.entry("RSI Long", "long");
}
if (rsi > 70 && strategy.position_size > 0) {
strategy.close("RSI Long");
}
});strategy("Strategy with Exits",
initial_capital: 100000
);
df.forEach((frame) => {
let sma = ta.sma(frame.close, 20);
let crossUp = ta.crossover(frame.close, sma);
if (crossUp && strategy.position_size == 0) {
strategy.entry("Breakout", "long");
let entryPrice = frame.close;
strategy.exit("Exit", "Breakout",
stop: entryPrice * 0.98,
limit: entryPrice * 1.04
);
}
});If you're familiar with Pine Script, here's how to translate common patterns.
Pine Script:
//@version=5
indicator("My Indicator")
plot(close)QuantScript:
indicator("My Indicator");
df.forEach((frame) => {
chart.plot(frame.close, "Close");
});Pine Script:
smaValue = ta.sma(close, 20)
plot(smaValue, "SMA", color.blue)QuantScript:
df.forEach((frame) => {
let smaValue = ta.sma(frame.close, 20);
chart.plot(smaValue, "SMA", "#0000FF");
});df.forEach((frame) => { ... }).close directly. QuantScript uses frame.close inside the loop.close[1] syntax.color.blue. QuantScript uses hex: "#0000FF".ta. for technical analysis.For a full comparison, see the Coming from Pine Script page.
Now that you understand the basics: