Core Concepts

Variables: var, timeseries, persist

Variable declaration and bar-state behavior in kScript: var, timeseries, and persist.

Declaration Roles

timeseries is the declaration to use for source data and values you want to read with history indexing such as closeSeries[1].

var is a per-bar simple value. It is valid for scalar calculations and for current-bar indicator values. Assigning a series-returning builtin to var does not, by itself, make that value flat or all-na; the var/timeseries boundary is history indexing.

persist carries state across bars, so a counter incremented on each bar keeps its running total for the whole run.

Bar-State Globals

isConfirmed and isFirst are bar-state globals. isConfirmed is true on confirmed historical bars; use it as an anti-repaint guard when logic should wait for a finalized bar. isFirst is true only while processing bar 0, which makes it the right place for one-time initialization.

On a historical run every bar is already confirmed, so isConfirmed holds throughout, while isFirst holds only on the first bar.

Bar-state globals
//@version=2
define(title="Bar State Globals", position="offchart", axis=true)

timeseries trade = ohlcv(symbol=currentSymbol, exchange=currentExchange)

var confirmedState = (isConfirmed ? 200 : 0) + barIndex / 1000
var firstState = (isFirst ? 100 : 0) + barIndex / 1000

plotLine(value=confirmedState, colors=["#2563eb"], width=2, label=["Confirmed"], desc=["isConfirmed is true on historical confirmed bars"])
plotLine(value=firstState, colors=["#16a34a"], width=2, label=["First"], desc=["isFirst is true only on bar zero"])

Tuple Destructuring

A line such as [macdLine, signalLine, histLine] = macd(source=trade) binds the separate streams returned by multi-output builtins, including macd, bb, and stoch. If the target list asks for more outputs than the builtin returns, the missing slots are filled with na. The destructuring target is a bracketed identifier list, [identifier, ...]; non-identifier targets are rejected.

A destructuring line can sit directly after a declaration with no trailing semicolon: the parser treats a leading [identifier, ...] = line as destructuring.

Tuple destructuring
//@version=2
define(title="Tuple Destructuring", position="offchart", axis=true)
timeseries trade = ohlcv(symbol=currentSymbol, exchange=currentExchange)
[macdLine, signalLine, histLine] = macd(source=trade)
plotLine(value=macdLine, colors=["#2563eb"], width=2, label=["macd line"], desc=["destructured from macd"])

Timeseries Example

Timeseries declarations
//@version=2
define(title="Timeseries Source Moves", position="offchart", axis=true)

timeseries trade = ohlcv(symbol=currentSymbol, exchange=currentExchange)
timeseries closeSeries = trade.close
timeseries movingAverage = sma(source=closeSeries, period=20)

plotLine(value=closeSeries, colors=["#2563eb"], width=2, label=["Close"], desc=["ohlcv close declared as timeseries"])
plotLine(value=movingAverage, colors=["#dc2626"], width=2, label=["SMA"], desc=["sma declared as timeseries preserves history"])

Persist Example

Persist counter
//@version=2
define(title="Persist Counter", position="offchart", axis=true)

timeseries trade = ohlcv(symbol=currentSymbol, exchange=currentExchange)

persist barsSeen = 0
barsSeen += 1

var carriedScore = barsSeen + (trade.close - trade.open)

plotLine(value=carriedScore, colors=["#16a34a"], width=2, label=["Persist"], desc=["persist value carried across bars"])

Boundaries

History indexing a var is rejected: the script below fails to compile with Indexing is only allowed on timeseries and arrays at 6:21. Promote the value to a timeseries when you need history.

Indexing a var fails to compile
//@version=2
define(title="Var History Index Boundary", position="offchart", axis=true)

timeseries trade = ohlcv(symbol=currentSymbol, exchange=currentExchange)
var closeNow = trade.close
var previousClose = closeNow[1]

plotLine(value=previousClose, colors=["#dc2626"], width=2, label=["Previous"], desc=["var history indexing boundary"])