Core Concepts

Named Streams

Multi-output indicators like bb, macd, and stoch return a result whose components you read by name, such as bb.upper, macd.signal, and stoch.k. No positional guessing.

Beginner 5 min read

Introduction

Some indicators produce more than one line. Bollinger Bands give you an upper band, a basis, and a lower band. MACD gives a MACD line, a signal line, and a histogram. In kScript these multi-output indicators return a single result whose components you read by name:

//@version=2
define(title="Bollinger bands", position="overlay", axis=true)

timeseries d = ohlcv(symbol=currentSymbol, exchange=currentExchange)
var bands = bb(source=d.close, period=20, mult=2)

plotLine(value=bands.upper, colors=["#2563eb"], width=2, label=["BB upper"], desc=["upper Bollinger band"])
plotLine(value=bands.basis, colors=["#64748b"], width=2, label=["BB basis"], desc=["Bollinger basis (the moving average)"])
plotLine(value=bands.lower, colors=["#2563eb"], width=2, label=["BB lower"], desc=["lower Bollinger band"])

bb(...) hands back a Bollinger result; bands.upper, bands.basis, and bands.lower are its three lines. You name what you want. There is no "is the upper band index 0 or index 2?" guesswork, and a typo like bands.upperr is a compile error rather than a silently-wrong line.

How it works

A multi-output builtin returns one value that carries several named series. Read a component with a dot, exactly like an OHLCV field (d.close). Each component is an ordinary series, so it flows straight into math, other indicators, conditions, and plots:

var m = macd(source=d.close, fastPeriod=12, slowPeriod=26, signalPeriod=9)

var risingMomentum = m.histogram > m.histogram[1]      // compare bars
var smoothSignal   = ema(source=m.signal, period=5)     // feed into another indicator

You can keep the whole result in one var and pull fields as needed, or read a single field inline when that is all you use.

The named streams

These are the multi-output builtins and the field names each one exposes:

BuiltinFields
bb.upper, .basis, .lower
keltner.upper, .basis, .lower
macd.macd, .signal, .histogram
stoch.k, .d
supertrend.line, .direction

A few worth calling out:

  • stoch splits into the fast %K (.k) and its smoothed %D (.d). The classic crossover is stoch.k crossing stoch.d.
  • supertrend returns the trailing stop level as .line and the trend side as .direction. Use .direction to color or gate; use .line to draw the stop.
  • macd.histogram is the MACD line minus the signal line, ready to plot as bars.

Reading every stream at once

This script reads all five multi-output indicators and plots each of their named components.

scripts/probes/lang-named-streams/multi_output_members.ks
//@version=2
define(title="Named Stream Members", position="offchart", axis=true)

timeseries trade = ohlcv(symbol=currentSymbol, exchange=currentExchange)
timeseries closeSeries = trade.close

var bands = bb(source=closeSeries, period=20, mult=2)
var macdValue = macd(source=closeSeries, fastPeriod=12, slowPeriod=26, signalPeriod=9)
var stochValue = stoch(periodK=14, smoothK=3, periodD=3)
var keltnerValue = keltner(source=trade, period=20, mult=1.5, atrPeriod=10)
var trendValue = supertrend(factor=3, atrPeriod=10)

plotLine(value=bands.upper, colors=["#2563eb"], width=2, label=["BB upper"], desc=["bb.upper named stream"])
plotLine(value=bands.basis, colors=["#64748b"], width=2, label=["BB basis"], desc=["bb.basis named stream"])
plotLine(value=bands.lower, colors=["#dc2626"], width=2, label=["BB lower"], desc=["bb.lower named stream"])
plotLine(value=macdValue.macd, colors=["#1d4ed8"], width=2, label=["MACD"], desc=["macd.macd named stream"])
plotLine(value=macdValue.signal, colors=["#ea580c"], width=2, label=["Signal"], desc=["macd.signal named stream"])
plotLine(value=macdValue.histogram, colors=["#15803d"], width=2, label=["Histogram"], desc=["macd.histogram named stream"])
plotLine(value=stochValue.k, colors=["#0891b2"], width=2, label=["Stoch K"], desc=["stoch.k named stream"])
plotLine(value=stochValue.d, colors=["#be123c"], width=2, label=["Stoch D"], desc=["stoch.d named stream"])
plotLine(value=keltnerValue.upper, colors=["#16a34a"], width=2, label=["Keltner upper"], desc=["keltner.upper named stream"])
plotLine(value=keltnerValue.basis, colors=["#94a3b8"], width=2, label=["Keltner basis"], desc=["keltner.basis named stream"])
plotLine(value=keltnerValue.lower, colors=["#b91c1c"], width=2, label=["Keltner lower"], desc=["keltner.lower named stream"])
plotLine(value=trendValue.line, colors=["#7c3aed"], width=2, label=["Supertrend line"], desc=["supertrend.line named stream"])
plotLine(value=trendValue.direction, colors=["#111827"], width=2, label=["Supertrend direction"], desc=["supertrend.direction named stream"])

What to expect: each band-style indicator (bb, keltner) starts drawing once its lookback window fills, and the three lines track together. macd produces its three components in lockstep. supertrend.line is a price-level series while supertrend.direction flips between trend states.