Learn QuantScript by example — from simple indicators to complete trading strategies. Copy any example and run it with the CLI.
The simplest QuantScript script — declare an indicator and print to the console.
indicator("Hello World");
console.log("Hello, World!");Declare variables with let and const, perform arithmetic, and output results.
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));Access Open, High, Low, Close, Volume data for each bar using df.forEach().
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(" Open: " + tostring(openPrice));
console.log(" Close: " + tostring(closePrice));
console.log(" Volume: " + tostring(volume));
}
});Calculate and plot a Simple Moving Average using ta.sma().
indicator("SMA Indicator");
const SMA_LENGTH = 20;
df.forEach((frame) => {
let sma = ta.sma(frame.close, SMA_LENGTH);
chart.plot(sma, "SMA 20", "#FF0000");
});Plot multiple moving averages and detect bullish/bearish crossover signals.
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");
let isCrossUp = ta.crossover(fastSMA, slowSMA);
let isCrossDown = ta.crossunder(fastSMA, slowSMA);
if (isCrossUp) {
console.log("BULLISH CROSSOVER at bar " + tostring(bar_index));
}
if (isCrossDown) {
console.log("BEARISH CROSSOVER at bar " + tostring(bar_index));
}
});A complete backtestable strategy that enters long on SMA crossover and exits on crossunder.
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);
chart.plot(fastSMA, "Fast SMA", "#00FF00");
chart.plot(slowSMA, "Slow SMA", "#FF0000");
let crossUp = ta.crossover(fastSMA, slowSMA);
let crossDown = ta.crossunder(fastSMA, slowSMA);
if (crossUp) {
strategy.entry("Long", "long");
}
if (crossDown) {
strategy.close("Long");
}
});Buy when RSI is oversold (<30), sell when overbought (>70).
strategy("RSI Strategy",
initial_capital: 50000,
default_qty_type: "percent_of_equity",
default_qty_value: 10
);
const RSI_LENGTH = 14;
df.forEach((frame) => {
let rsi = ta.rsi(frame.close, RSI_LENGTH);
chart.plot(rsi, "RSI", "#FF00FF");
chart.hline(30, "Oversold", "#00FF00");
chart.hline(70, "Overbought", "#FF0000");
if (rsi < 30 && strategy.position_size == 0) {
strategy.entry("RSI Long", "long");
}
if (rsi > 70 && strategy.position_size > 0) {
strategy.close("RSI Long");
}
});Enter on SMA breakout with automatic exit orders for risk management.
strategy("Strategy with Exits",
initial_capital: 100000,
default_qty_type: "fixed",
default_qty_value: 50
);
const STOP_LOSS_PCTS = 2.0;
const TAKE_PROFIT_PCTS = 4.0;
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", "long");
let entryPrice = frame.close;
let stopPrice = entryPrice * (1 - STOP_LOSS_PCTS / 100);
let targetPrice = entryPrice * (1 + TAKE_PROFIT_PCTS / 100);
strategy.exit("Exit Long", "Breakout Long",
stop: stopPrice,
limit: targetPrice
);
}
});Use array destructuring to unpack the three MACD components and plot them.
indicator("MACD");
df.forEach((frame) => {
let [macdLine, signalLine, histogram] = ta.macd(frame.close, 12, 26, 9);
chart.plot(macdLine, "MACD", "#0000FF");
chart.plot(signalLine, "Signal", "#FF0000");
chart.plot(histogram, "Histogram", "#00FF00");
});Plot Bollinger Bands using array destructuring on the ta.bbands() return value.
indicator("Bollinger Bands");
df.forEach((frame) => {
let [lower, middle, upper] = ta.bbands(frame.close, 20, 2);
chart.plot(lower, "Lower Band", "#808080");
chart.plot(middle, "Middle Band", "#0000FF");
chart.plot(upper, "Upper Band", "#808080");
});