Skip to content

Language Reference

This page documents the public Rune language surface shipping today: script(version=1).

Comments

Rune supports full-line comments only.

# Comment
// Also a comment

Inline comments are not supported. Put comments on their own line.

Script Header

Every Rune script starts with script(...):

script(name="My Script", version=1, mode=indicator, overlay=true)

Supported header keys:

KeyValuesNotes
namestringDisplay name for the script
version1Launch Rune version
modeindicator, strategyDefault is indicator
overlaytrue, falsetrue draws over price, false uses a sub-pane

Additional numeric and boolean header keys are treated as backtest defaults when the script runs as a strategy. Common examples include:

  • initial_capital
  • commission_pct
  • fee_discount_pct
  • size_pct
  • reverse
  • hedging
  • pyramiding
  • max_entries

Parameters

Parameters create editor controls and runtime inputs.

param fast = int("Fast EMA", 20, min=1, max=200, group="Trend")
param mode = string("Mode", "ATR", options=["ATR", "Percent"], group="Entry")
param accent = color("Accent", "#00E676", group="Style")

Parameter Types

TypeDescription
int / integerWhole-number input
float / numberDecimal input
bool / booleanTrue/false toggle
stringText input, optionally constrained with options=[...]
colorColor picker / color value
timeframeTimeframe selector
sessionTrading session window like "0900-1700"
sourceSource selector
symbolSymbol selector

Common Parameter Options

OptionDescription
labelDisplay label
defaultDefault value
min / maxNumeric bounds
stepNumeric step size
hintTooltip/help text
groupGroup label in the UI
optionsAllowed option list for string, timeframe, and similar selector params

Streams

Streams bind OHLCV data into the script.

stream market = ohlcv()
stream htf = ohlcv(timeframe="15m")
stream external = ohlcv(exchange="blofin", symbol="ETH-USDT", bar="1H")

Supported Forms

FormMeaning
ohlcv()Current chart candles
ohlcv(timeframe="15m")Same instrument, higher/same timeframe
ohlcv(timeframe=higher_tf)Same instrument, expression-backed timeframe
ohlcv(bar="1H")Alias for timeframe=...
ohlcv(exchange="...", symbol="...", timeframe="...")External OHLCV feed supplied by the host runtime

Rules:

  • timeframe, bar, exchange, and symbol may come from literals or params
  • external or lower-timeframe streams require host-supplied candles through streamSources / streamCandles
  • same-timeframe and higher-timeframe internal streams can be auto-aligned from chart candles
  • stream aliases expose .time, .open, .high, .low, .close, and .volume

Top-Level Blocks

Rune supports these top-level declarations:

  • script(...)
  • param ...
  • stream ...
  • keep ...
  • helper calc blocks
  • panel ...:
  • risk:
  • bar:

keep

keep declares persistent state that survives from bar to bar.

keep breakout_side = 0
keep trend_count = 0

Update kept state with set inside bar:.

Helper calc Blocks

Top-level calc blocks declare reusable pure helper functions:

calc rising(current, prior):
  return current > prior

Helper functions:

  • are pure
  • support positional and named arguments
  • may return tuples
  • may only use return inside helper blocks

panel

Panels provide lightweight dashboards in preview and backtest results.

panel status:
  title "Trend"
  metric fast = ema(close, 20) format="price"
  status bias = close > ema(close, 50) tone="success"
  trade_log limit=5

risk:

Strategy scripts can declare top-level portfolio risk controls:

risk:
  max_open_positions = 1
  daily_loss_limit = equity_pct(2)
  daily_trade_limit = 4
  reset_tz = "UTC"

The bar: Section

bar: contains the per-candle logic.

bar:
  let fast = ema(close, 20)
  guard trend_ok = close > fast
  signal long = trend_ok
  alert breakout = long
  draw(type=line, series=fast, color=signal_long)

Supported Statements in bar:

StatementPurpose
let name = exprDerived value
calc name = exprAlias assignment form for derived values
set name = exprUpdate a keep value
guard name = exprNamed boolean condition
rule name: + require ...AND-composed rule block
flag name = exprNamed boolean series
signal name = exprAlias for flag
alert name = exprNamed alert series
draw(...)Declarative chart rendering
trade(...)Entries and exits in strategy mode
protect(...)Managed stop/take updates in strategy mode

Named and Positional Arguments

Expression calls support both positional and named arguments:

let fast = ema(close, 20)
let day_vwap = vwap(reset="day", tz="UTC")
let stamp = timestamp(year=2026, month=4, day=5, hour=12, minute=30, tz="UTC")

Rules:

  • positional arguments may come first
  • after the first named argument, all remaining arguments must be named
  • duplicate named arguments are invalid
  • unknown named arguments are rejected

Tuple Assignment

Tuple returns can be unpacked directly:

let macd_line, signal_line, hist = macd(close, 12, 26, 9)
let upper, basis, lower = bbands(close, 20, 2)

Guards and Rules

guard is a named boolean series. rule groups multiple require lines into one named setup.

bar:
  guard trend_ok = close > ema(close, 50)
 
  rule long_setup:
    require trend_ok
    require volume > sma(volume, 20)
 
  signal long = long_setup

Rules:

  • guards and rules can reference earlier calculations and earlier guards/rules
  • they cannot reference future declarations
  • rule bodies may not contain side effects

Strategy Statements

Strategy mode adds:

  • trade(...)
  • protect(...)
  • position-state builtins such as position_avg_entry(...) and position_open_r(...)
  • optional risk: blocks

See Strategies & Backtesting for the full trade model.

Deliberate Non-Goals

Rune does not currently support:

  • loops
  • maps or dictionaries, or array literals — the only collection is the chart-only bounded list
  • imports or modules
  • imperative drawing APIs like line.new(...) or label.new(...)
  • Pine namespaces like strategy.* or request.security(...)

That is intentional. Rune stays declarative and product-focused.