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.
| Parameter | Type | Description |
|---|---|---|
source | TimeSeries | Price series |
period | number | Window 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.
| Parameter | Type | Description |
|---|---|---|
source | TimeSeries | Price series |
period | number | Smoothing 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.
| Parameter | Type | Description |
|---|---|---|
source | TimeSeries | Price series |
period | number | Window 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.
| Parameter | Type | Description |
|---|---|---|
source | TimeSeries | Price series |
period | number | Window 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.
| Parameter | Type | Description |
|---|---|---|
source | TimeSeries | Price series |
length | number | Gaussian window length |
offset | number | Gaussian center offset, default 0.85 |
sigma | number | Gaussian 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.
| Parameter | Type | Description |
|---|---|---|
source | TimeSeries | Price 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.
| Parameter | Type | Description |
|---|---|---|
source | TimeSeries | OHLC series (needs volume) |
period | number | Window 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.
| Parameter | Type | Description |
|---|---|---|
source | TimeSeries | Price series |
period | number | Smoothing 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.
| Parameter | Type | Description |
|---|---|---|
source | TimeSeries | Price series |
period | number | Regression window |
offset | number | Shift 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.
| Parameter | Type | Description |
|---|---|---|
source | TimeSeries | Price series |
period | number | Basis and stdev window (default 20) |
mult | number | Standard-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.
| Parameter | Type | Description |
|---|---|---|
source | TimeSeries | OHLC series |
period | number | Basis EMA window (default 20) |
mult | number | ATR multiplier (default 1.5) |
atrPeriod | number | ATR 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.
| Parameter | Type | Description |
|---|---|---|
source | TimeSeries | OHLC series |
period | number | Lookback 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.
//@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.
//@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.
//@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"])