Functions

Moving Averages

Moving averages and price-band helpers — SMA, EMA, ALMA, SWMA, HMA, WMA, VWMA, RMA, LinReg, Bollinger, Keltner, Donchian.

These functions smooth price into a trend line or wrap it in a band. The single-line averages (sma, ema, alma, swma, hma, wma, vwma, rma, linreg) each return one stream. The band helpers (bb, keltner, donchian) return three levels at once; Bollinger and Keltner expose them as named streams .upper / .basis / .lower, ready to hand to fillBetween.

Every windowed average is na until its window fills. An SMA(20) plots nothing for its first bars, then begins once 20 bars have loaded; HMA warms up a little longer because of its internal weighted sub-windows. Donchian is the exception: it reads the rolling high/low and can be finite from the very first bar.

Single-line averages

sma

sma(source, period?) — Simple Moving Average, the unweighted mean of the last period values.

ParameterTypeDescription
sourceTimeSeriesPrice series
periodnumberWindow length

Returns one stream. Warmup is period bars.

var smaValue = sma(source=close, period=20)

ema

ema(source, period?) — Exponential Moving Average. Weights recent bars more heavily, so it turns faster than sma.

ParameterTypeDescription
sourceTimeSeriesPrice series
periodnumberSmoothing length
var emaValue = ema(source=close, period=20)

hma

hma(source, period?) — Hull Moving Average. Very low lag and smooth; built from weighted sub-windows, so it warms up a few bars past period.

ParameterTypeDescription
sourceTimeSeriesPrice series
periodnumberWindow length
var hmaValue = hma(source=close, period=21)

wma

wma(source, period?) — Weighted Moving Average. Linear weights favor recent bars, between sma and ema in responsiveness.

ParameterTypeDescription
sourceTimeSeriesPrice series
periodnumberWindow length
var wmaValue = wma(source=close, period=20)

alma

alma(source, length, offset?, sigma?) — Arnaud Legoux Moving Average, a Gaussian-weighted smoother. Omitting offset and sigma is equivalent to offset=0.85 and sigma=6.

ParameterTypeDescription
sourceTimeSeriesPrice series
lengthnumberGaussian window length
offsetnumberGaussian center offset, default 0.85
sigmanumberGaussian width, default 6
var almaValue = alma(source=close, length=10, offset=0.85, sigma=6)

swma

swma(source) — Symmetrically Weighted Moving Average, the fixed four-tap smoother (source + 2 * source[1] + 2 * source[2] + source[3]) / 6.

ParameterTypeDescription
sourceTimeSeriesPrice series
var swmaValue = swma(source=close)

vwma

vwma(source, period?) — Volume-Weighted Moving Average. Bars with more volume pull the average harder, so it tracks where trading actually happened.

ParameterTypeDescription
sourceTimeSeriesOHLC series (needs volume)
periodnumberWindow length
var vwmaValue = vwma(source=trade, period=20)

rma

rma(source, period?) — Running (Wilder) Moving Average, the smoothing used inside RSI and ATR. Smoother and slower than ema for the same period.

ParameterTypeDescription
sourceTimeSeriesPrice series
periodnumberSmoothing length
var rmaValue = rma(source=close, period=20)

linreg

linreg(source, period?, offset?) — Linear Regression. Fits a least-squares line over the last period bars and returns its value; the trend's fitted price rather than an average.

ParameterTypeDescription
sourceTimeSeriesPrice series
periodnumberRegression window
offsetnumberShift the read point along the fitted line (default 0)
var linregValue = linreg(source=close, period=20, offset=0)

Band helpers

bb

bb(source, period?, mult?) — Bollinger Bands. A basis (SMA) with upper and lower bands set mult standard deviations away, so the band widens with volatility.

ParameterTypeDescription
sourceTimeSeriesPrice series
periodnumberBasis and stdev window (default 20)
multnumberStandard-deviation multiplier (default 2)

Returns [upper, basis, lower], named .upper, .basis, .lower.

var bands = bb(source=close, period=20, mult=2)
plotLine(value=bands.upper, colors=["#64748b"], width=1, label=["BB upper"], desc=["upper band"])
plotLine(value=bands.lower, colors=["#64748b"], width=1, label=["BB lower"], desc=["lower band"])
fillBetween(bands.upper, bands.lower, "#2563eb", 0.12)

keltner

keltner(source, period?, mult?, atrPeriod?) — Keltner Channels. Like Bollinger, but the band width comes from ATR instead of standard deviation, so it reacts to range rather than dispersion.

ParameterTypeDescription
sourceTimeSeriesOHLC series
periodnumberBasis EMA window (default 20)
multnumberATR multiplier (default 1.5)
atrPeriodnumberATR lookback (default 10)

Returns [upper, basis, lower], named .upper, .basis, .lower.

var kc = keltner(source=trade, period=20, mult=1.5, atrPeriod=10)

donchian

donchian(source, period?) — Donchian Channel. The highest high and lowest low over period bars, with their midpoint as the basis.

ParameterTypeDescription
sourceTimeSeriesOHLC series
periodnumberLookback for the high/low (default 20)

Returns three levels [upper, basis, lower]. Because it reads the rolling extreme rather than averaging, it can be finite from the first loaded bar.

var dc = donchian(source=trade, period=20)

Putting them together

Every average and band on one panel. Band helpers are plotted whole here by passing the value directly; pass .upper / .basis / .lower instead when you want a single level.

all_moving_averages.ks
//@version=2
define(title="Moving Averages", position="offchart", axis=true)

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

var smaValue = sma(source=closeSeries, period=20)
var emaValue = ema(source=closeSeries, period=20)
var hmaValue = hma(source=closeSeries, period=21)
var wmaValue = wma(source=closeSeries, period=20)
var vwmaValue = vwma(source=trade, period=20)
var rmaValue = rma(source=closeSeries, period=20)
var linregValue = linreg(source=closeSeries, period=20, offset=0)
var bands = bb(source=closeSeries, period=20, mult=2)
var keltnerBands = keltner(source=trade, period=20, mult=1.5, atrPeriod=10)
var donchianBands = donchian(source=trade, period=20)

plotLine(value=smaValue, colors=["#2563eb"], width=2, label=["SMA"], desc=["20 period simple moving average"])
plotLine(value=emaValue, colors=["#dc2626"], width=2, label=["EMA"], desc=["20 period exponential moving average"])
plotLine(value=hmaValue, colors=["#7c3aed"], width=2, label=["HMA"], desc=["21 period hull moving average"])
plotLine(value=wmaValue, colors=["#ea580c"], width=2, label=["WMA"], desc=["20 period weighted moving average"])
plotLine(value=vwmaValue, colors=["#0891b2"], width=2, label=["VWMA"], desc=["20 period volume weighted moving average"])
plotLine(value=rmaValue, colors=["#059669"], width=2, label=["RMA"], desc=["20 period running moving average"])
plotLine(value=linregValue, colors=["#4b5563"], width=2, label=["LinReg"], desc=["20 period linear regression"])
plotLine(value=bands, colors=["#0f766e", "#64748b", "#be123c"], width=1, label=["Bollinger bands"], desc=["Bollinger bands multi output"])
plotLine(value=keltnerBands, colors=["#16a34a", "#94a3b8", "#dc2626"], width=1, label=["Keltner bands"], desc=["Keltner channel multi output"])
plotLine(value=donchianBands, colors=["#0ea5e9", "#94a3b8", "#f97316"], width=1, label=["Donchian bands"], desc=["Donchian channel multi output"])

Warmup and named streams

This isolates the two ideas worth seeing: an average is blank until its window fills, and Bollinger's .upper / .basis / .lower are independent streams you can plot one at a time. All four lines here begin together once the 20-bar window completes.

warmup_named_streams.ks
//@version=2
define(title="Moving Average Warmup Boundary", position="offchart", axis=true)

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

var sma20 = sma(source=closeSeries, period=20)
var bands = bb(source=closeSeries, period=20, mult=2)

plotLine(value=sma20, colors=["#2563eb"], width=2, label=["SMA 20"], desc=["SMA is na until the 20 bar window is complete"])
plotLine(value=bands.upper, colors=["#16a34a"], 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"])

ALMA and SWMA boundaries

ALMA's omitted offset and sigma default to 0.85 and 6, matching the explicit call; SWMA uses the fixed four-tap symmetric weighting. The script below plots each line only where the builtin agrees with the manual form.

alma_swma.ks
//@version=2
define(title="ALMA and SWMA", position="offchart", axis=true)

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

var almaDefault = alma(source=closeSeries, length=10)
var almaExplicit = alma(source=closeSeries, length=10, offset=0.85, sigma=6)
var swmaValue = swma(source=closeSeries)
var swmaManual = (closeSeries + 2 * closeSeries[1] + 2 * closeSeries[2] + closeSeries[3]) / 6
var almaCheck = math.abs(almaDefault - almaExplicit) < 0.000001 ? almaExplicit : na
var swmaCheck = math.abs(swmaValue - swmaManual) < 0.000001 ? swmaValue : na

plotLine(value=almaCheck, colors=["#2563eb"], width=2, label=["ALMA"], desc=["ALMA default offset 0.85 and sigma 6"])
plotLine(value=swmaCheck, colors=["#16a34a"], width=2, label=["SWMA"], desc=["SWMA fixed four tap symmetric average"])