---
title: Moving Averages
description: 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.

| Parameter | Type | Description |
| --- | --- | --- |
| `source` | TimeSeries | Price series |
| `period` | number | Window length |

Returns one stream. Warmup is `period` bars.

```javascript
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 |

```javascript
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 |

```javascript
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 |

```javascript
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` |

```javascript
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 |

```javascript
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 |

```javascript
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 |

```javascript
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`) |

```javascript
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`.

```javascript
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`.

```javascript
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.

```javascript
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.

```javascript title="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.

```javascript title="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.

```javascript title="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"])
```
