Technical indicators
Textbook indicators written with the built-in technical functions: bands, channels, oscillators and trend strength.
Each program here uses the built-in functions of tech. They are the standard definitions: the pages of the reference say exactly what each one computes.
ATR channel#
A moving average widened by a multiple of the Average True Range.
Cuprel
// Average True Range: the Wilder mean of max(high - low, |high - previous close|, |low - previous close|).
// The channel is a moving average of the close, widened by a multiple of the ATR.
indicator "ATR channel"
edition = 1
display = price
input length: int = 20, name = "Length", min = 2
input mult: float = 2.0, name = "Multiple", min = 0.1, step = 0.1
let basis = tech.ema(close, length)
let range = tech.atr(length)
let upper = basis + mult * range
let lower = basis - mult * range
plot(upper, name = "Upper", color = color.red)
plot(lower, name = "Lower", color = color.green)
plot(basis, name = "Basis", color = color.gray)Bollinger bands#
A moving average with bands a number of standard deviations away, shaded between them.
Cuprel
// Bollinger Bands: a simple moving average and bands a number of standard deviations above and below it.
indicator "Bollinger bands"
edition = 1
display = price
input length: int = 20, name = "Length", min = 2
input mult: float = 2.0, name = "Deviations", min = 0.1, step = 0.1
let basis = tech.sma(close, length)
let deviation = mult * tech.stdev(close, length)
let upper = basis + deviation
let lower = basis - deviation
let top = plot(upper, name = "Upper", color = color.blue)
let bottom = plot(lower, name = "Lower", color = color.blue)
plot(basis, name = "Basis", color = color.orange)
shade(top, bottom, color = color.fade(color.blue, 92), name = "Band")MACD#
MACD line, signal line and histogram taken apart from a tuple.
Cuprel
// MACD: the difference of a fast and a slow EMA, a signal EMA of that difference, and the gap between them as a histogram.
indicator "MACD"
edition = 1
display = pane
input fast_length: int = 12, name = "Fast length", min = 1
input slow_length: int = 26, name = "Slow length", min = 2
input signal_length: int = 9, name = "Signal length", min = 1
let (macd_line, signal_line, hist_value) = tech.macd(
close,
fast_length = fast_length,
slow_length = slow_length,
signal_length = signal_length,
)
plot(
hist_value,
name = "Histogram",
style = histogram,
color = if hist_value >= 0 then color.green else color.red,
)
plot(macd_line, name = "MACD", color = color.blue)
plot(signal_line, name = "Signal", color = color.orange)Donchian channel#
Highest high, lowest low and their middle over a window.
Cuprel
// Donchian Channel: the highest high and the lowest low of the last `length` bars, and their middle.
indicator "Donchian channel"
edition = 1
display = price
input length: int = 20, name = "Length", min = 1
let upper = tech.highest(high, length)
let lower = tech.lowest(low, length)
let middle = (upper + lower) / 2
plot(upper, name = "Upper", color = color.green)
plot(lower, name = "Lower", color = color.red)
plot(middle, name = "Middle", color = color.gray)Stochastic oscillator#
Raw %K from the range of the window, smoothed into %K and %D.
Cuprel
// The stochastic oscillator: where the close sits inside the last `length` bars' range, smoothed into %K and %D.
// raw %K = 100 * (close - lowest low) / (highest high - lowest low)
indicator "Stochastic"
edition = 1
display = pane
input length: int = 14, name = "Length", min = 1
input smooth: int = 3, name = "Smoothing", min = 1
let lowest_low = tech.lowest(low, length)
let highest_high = tech.highest(high, length)
let raw = 100 * (close - lowest_low) / (highest_high - lowest_low)
let k = tech.sma(raw, smooth)
let d = tech.sma(k, smooth)
plot(k, name = "%K", color = color.blue)
plot(d, name = "%D", color = color.orange)
level(80, name = "Upper", color = color.gray, style = dashed)
level(20, name = "Lower", color = color.gray, style = dashed)ADX with directional indicators#
The built-in directional movement tuple: +DI, -DI and ADX.
Cuprel
// Average Directional Index: how strong a trend is, whichever way it points, with the two directional indicators.
indicator "ADX"
edition = 1
display = pane
input di_length: int = 14, name = "DI length", min = 1
input adx_length: int = 14, name = "ADX smoothing", min = 1
let (plus, minus, adx) = tech.dmi(di_length, adx_length)
plot(adx, name = "ADX", color = color.black, width = 2)
plot(plus, name = "Plus DI", color = color.green)
plot(minus, name = "Minus DI", color = color.red)
level(25, name = "Trend", color = color.gray, style = dashed)On-balance volume#
A running total of signed volume with a signal average.
Cuprel
// On-Balance Volume: add the volume on an up close, subtract it on a down close, and smooth the running total.
indicator "On-balance volume"
edition = 1
display = pane
input length: int = 20, name = "Signal length", min = 1
let direction = math.sign(close - close[1])
let obv = tech.cum_sum(direction * volume)
plot(obv, name = "OBV", color = color.blue)
plot(tech.ema(obv, length), name = "Signal", color = color.orange)