// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © TradingView
//@version=5
library("ta")
// ta Library
// v7, 2023.11.02
// This code was written using the recommendations from the Pine Script™ User Manual's Style Guide:
// https://www.tradingview.com/pine-script-docs/en/v5/writing/Style_guide.html
import TradingView/RelativeValue/2 as TVrv
// This library exports the following functions:
// • ao: Awesome Oscillator
// • aroon: Aroon Oscillator
// • atr2: Average True Range (Alternate Version)
// • cagr: Compound Annual Growth Rate
// • changePercent: Calculate percentage change
// • coppock: Coppock Curve
// • dema: Double Exponential Moving Average
// • dema2: Double Exponential Moving Average (Alternate Version)
// • dm: Demarker Indicator
// • donchian: Donchian Channel
// • ema2: Exponential Moving Average (Alternate Version)
// • eom: Ease of Movement
// • frama: Fractal Adaptive Moving Average
// • ft: Fisher Transform
// • highestSince: Highest value since condition
// • ht: Hilbert Transform function
// • ichimoku: Ichimoku Cloud
// • ift: Inverse Fisher Transform
// • kvo: Klinger Volume Oscillator
// • lowestSince: Lowest value since condition
// • relativeVolume: Compare volume to its historical average
// • rma2: Rolling Moving Average (Alternate Version)
// • rms: Root Mean Square
// • rwi: Random Walk Index
// • stc: Schaff Trend Cycle
// • stochFull: Full Stochastic Oscillator
// • stochRsi: Stochastic RSI
// • supertrend: SuperTrend Indicator
// • supertrend2: SuperTrend Indicator (Alternate Version)
// • szo: Sentiment Zone Oscillator
// • t3: Tilson Moving Average (T3)
// • t3Alt: Tilson Moving Average (T3 Alternate Version)
// • tema: Triple Exponential Moving Average
// • tema2: Triple Exponential Moving Average (Alternate Version)
// • trima: Triangular Moving Average
// • trix: TRIX indicator
// • uo: Ultimate Oscillator
// • vhf: Vertical Horizontal Filter
// • vi: Vortex Indicator
// • vStop: Volatility Stop
// • vStop2: Volatility Stop (Alternate Version)
// • vzo: Volume Zone Oscillator
// • williamsFractal: Williams' Fractal
// • wpo: Wave Period Oscillator
// @function Calculates the dynamic Exponentially Weighted Moving Average used in
// `atr2()`, `ema2()`, `frama()`, and `rma2()`.
// @param source (series int/float) Series of values to process.
// @param alpha (series int/float) The smoothing parameter of the filter.
// @returns The dynamic exponentially weighted moving average value.
ewma(series float source, series float alpha) =>
float result = na
result := alpha * source + (1.0 - alpha) * nz(result[1], source)
// @function Calculates the value of the Awesome Oscillator.
// @param source (series int/float) Series of values to process.
// @param shortLength (simple int) Number of bars for the fast moving average (length).
// @param longLength (simple int) Number of bars for the slow moving average (length).
// @returns (float) The oscillator value.
export ao(series float source = hl2, simple int shortLength = 5, simple int longLength = 34) =>
float result = ta.sma(source, shortLength) - ta.sma(source, longLength)
// @function Calculates the values of the Aroon indicator.
// @param length (simple int) Number of bars (length).
// @returns ([float, float]) A tuple of the Aroon-Up and Aroon-Down values.
export aroon(simple int length) =>
float aroonDown = 100 * (ta.lowestbars(low, length) + length) / length
float aroonUp = 100 * (ta.highestbars(high, length) + length) / length
[aroonUp, aroonDown]
// @function An alternate ATR function to the `ta.atr()` built-in, which allows a "series float"
// `length` argument.
// @param length (series int/float) Length for the smoothing parameter calculation.
// @returns (float) The ATR value.
export atr2(series float length) =>
float alpha = 1.0 / math.max(1.0, length)
float result = ewma(ta.tr(true), alpha)
// @function Calculates the "Compound Annual Growth Rate" between two points in time.
// @param entryTime (series int) The starting timestamp.
// @param entryPrice (series int/float) The starting point's price.
// @param exitTime (series int) The ending timestamp.
// @param exitPrice (series int/float) The ending point's price.
// @returns (float) CAGR in % (50 is 50%). Returns `na` if there is not >=1D between `entryTime` and
// `exitTime`, or until the two time points have not been reached by the script.
export cagr(series int entryTime, series float entryPrice, series int exitTime, series float exitPrice) =>
int MS_IN_ONE_DAY = 24 * 60 * 60 * 1000
float daysBetween = (exitTime - entryTime) / MS_IN_ONE_DAY
float result = if daysBetween >= 1 and not (na(entryPrice) or na(exitPrice))
float years = daysBetween / 365.
float rate = exitPrice / entryPrice
100 * (math.pow(rate, 1 / years) - 1)
else
na
// @function Calculates the percentage difference between two distinct values.
// @param newValue (series int/float) The current value.
// @param oldValue (series int/float) The previous value.
// @returns (float) The percentage change from the `oldValue` to the `newValue`.
export changePercent(series float newValue, series float oldValue) =>
float result = 100 * (newValue - oldValue) / oldValue
// @function Calculates the value of the Coppock Curve indicator.
// @param source (series int/float) Series of values to process.
// @param longLength (simple int) Number of bars for the fast ROC value (length).
// @param shortLength (simple int) Number of bars for the slow ROC value (length).
// @param smoothLength (simple int) Number of bars for the weigted moving average value (length).
// @returns (float) The oscillator value.
export coppock(series float source, simple int longLength, simple int shortLength, simple int smoothLength) =>
float result = ta.wma(ta.roc(source, longLength) + ta.roc(source, shortLength), smoothLength)
// @function Calculates the value of the Double Exponential Moving Average (DEMA).
// @param source (series int/float) Series of values to process.
// @param length (simple int) Length for the smoothing parameter calculation.
// @returns (float) The double exponentially weighted moving average of the `source`.
export dema(series float source, simple int length) =>
float ema1 = ta.ema(source, length)
float ema2 = ta.ema(ema1, length)
float result = 2 * ema1 - ema2
// @function An alternate EMA function to the `ta.ema()` built-in, which allows a "series float"
// `length` argument.
// @param source (series int/float) Series of values to process.
// @param length (series int/float) Length for the smoothing parameter calculation.
// @returns (float) The exponentially weighted moving average of the `source`.
export ema2(series float source, series float length) =>
float alpha = 2.0 / (math.max(1.0, length) + 1.0)
float result = ewma(source, alpha)
// @function An alternate Double Exponential Moving Average (DEMA) function to `dema()`, which allows a
// "series float" `length` argument.
// @param source (series int/float) Series of values to process.
// @param length (series int/float) Length for the smoothing parameter calculation.
// @returns (float) The double exponentially weighted moving average of the `source`.
export dema2(series float source, series float length) =>
float ema1 = ema2(source, length)
float ema2 = ema2(ema1, length)
float result = 2 * ema1 - ema2
// @function Calculates the value of the "Demarker" indicator.
// "DeMark®" is a registered trademark of DeMark Analytics, LLC. This code is neither
// endorsed, nor sponsored, nor affiliated with them.
// @param length (simple int) Number of bars (length).
// @returns (float) The oscillator value.
export dm(simple int length) =>
float demax = math.max(ta.change(high), 0)
float demin = -math.min(ta.change(low), 0)
float result = ta.sma(demax, length) / (ta.sma(demax, length) + ta.sma(demin, length))
// @function Calculates the values of a Donchian Channel using `high` and `low` over a given `length`.
// @param length (series int) Number of bars (length).
// @returns ([float, float, float]) A tuple containing the channel high, low, and median, respectively.
export donchian(series int length) =>
float highest = ta.highest(length)
float lowest = ta.lowest(length)
[highest, lowest, math.avg(highest, lowest)]
// @function Calculates the value of the Ease of Movement indicator.
// @param length (simple int) Number of bars (length).
// @param div (simple int) Divisor used for normalzing values. Optional. The default is 10000.
// @returns (float) The oscillator value.
export eom(simple int length, simple int div = 10000) =>
float result = ta.sma(div * ta.change(hl2) * (high - low) / volume, length)
// @function The Fractal Adaptive Moving Average (FRAMA), developed by John Ehlers, is an adaptive
// moving average that dynamically adjusts its lookback period based on fractal geometry.
// @param source (series int/float) Series of values to process.
// @param length (series int) Number of bars (length).
// @returns (float) The fractal adaptive moving average of the `source`.
export frama(series float source, series int length) =>
int len = math.round(length / 2)
float hh = ta.highest(len)
float ll = ta.lowest(len)
float n1 = (hh - ll) / len
float n2 = (hh[len] - ll[len]) / len
float n3 = (ta.highest(length) - ta.lowest(length)) / length
float D = math.log((n1 + n2) / n3) / math.log(2)
float alpha = math.exp(-4.6 * (D - 1))
float result = ewma(source, alpha)
// @function Calculates the value of the Fisher Transform indicator.
// @param source (series int/float) Series of values to process.
// @param length (simple int) Number of bars (length).
// @returns (float) The oscillator value.
export ft(series float source, simple int length) =>
float value1 = 0.0
float fish = 0.0
float hh = ta.highest(source, length)
float ll = ta.lowest(source, length)
value1 := 0.66 * ((source - ll) / (hh - ll) - 0.5) + 0.67 * nz(value1[1])
float value2 = value1 > 0.99 ? 0.999 : value1 < -0.99 ? -0.999 : value1
fish := 0.5 * math.log((1 + value2) / (1 - value2)) + 0.5 * nz(fish[1])
float result = fish
// @function Tracks the highest value of a series since the last occurrence of a condition.
// @param cond (series bool) A condition which, when `true`, resets the tracking of the highest `source`.
// @param source (series int/float) Series of values to process. Optional. The default is `high`.
// @returns (float) The highest `source` value since the last time the `cond` was `true`.
export highestSince(series bool cond, series float source = high) =>
var float result = na
if cond
result := source
result := math.max(nz(source, result), nz(result, source))
// @function Calculates the value of the Hilbert Transform indicator.
// @param source (series int/float) Series of values to process.
// @returns (float) The oscillator value.
export ht(series float source) =>
float result = 0.0962 * source + 0.5769 * nz(source[2]) - 0.5769 * nz(source[4]) - 0.0962 * nz(source[6])
// @function Calculates the midpoint between the highest `high` and lowest `low` over `length` bars.
// @param length (series int) Number of bars (length).
// @returns The midpoint of the data.
midpoint(series int length) =>
float result = math.avg(ta.highest(length), ta.lowest(length))
// @function Calculates values of the Ichimoku Cloud indicator, including tenkan, kijun, senkouSpan1,
// senkouSpan2, and chikou.
// NOTE: offsets forward or backward can be done using the `offset` argument in `plot()`.
// @param conLength (series int) Length for the Conversion Line (Tenkan). The default is 9 periods, which
// returns the mid-point of the 9 period Donchian Channel.
// @param baseLength (series int) Length for the Base Line (Kijun-sen). The default is 26 periods, which returns
// the mid-point of the 26 period Donchian Channel.
// @param senkouLength (series int) Length for the Senkou Span 2 (Leading Span B). The default is 52 periods,
// which returns the mid-point of the 52 period Donchian Channel.
// @returns ([float, float, float, float, float]) A tuple of the Tenkan, Kijun, Senkou Span 1,
// Senkou Span 2, and Chikou Span values. NOTE: by default, the senkouSpan1 and senkouSpan2
// should be plotted 26 periods in the future, and the Chikou Span plotted 26 days in the past.
export ichimoku(series int conLength = 9, series int baseLength = 26, series int senkouLength = 52) =>
float tenkan = midpoint(conLength)
float kijun = midpoint(baseLength)
float senkouSpan1 = math.avg(tenkan, kijun)
float senkouSpan2 = midpoint(senkouLength)
float chikou = close
[tenkan, kijun, senkouSpan1, senkouSpan2, chikou]
// @function Calculates the value of the Inverse Fisher Transform indicator.
// @param source (series int/float) Series of values to process.
// @returns (float) The oscillator value.
export ift(series float source) =>
float exp = math.exp(2.0 * source)
float result = (exp - 1.0) / (1.0 + exp)
// @function Calculates the values of the Klinger Volume Oscillator.
// @param fastLen (simple int) Length for the fast moving average smoothing parameter calculation.
// @param slowLen (simple int) Length for the slow moving average smoothing parameter calculation.
// @param trigLen (simple int) Length for the trigger moving average smoothing parameter calculation.
// @returns ([float, float]) A tuple of the KVO value, and the trigger value.
export kvo(simple int fastLen, simple int slowLen, simple int trigLen) =>
float trend = math.sign(ta.change(hlc3)) * volume * 100
float fast = ta.ema(trend, fastLen)
float slow = ta.ema(trend, slowLen)
float kvo = fast - slow
float trigger = ta.ema(kvo, trigLen)
[kvo, trigger]
// @function Tracks the lowest value of a series since the last occurrence of a condition.
// @param cond (series bool) A condition which, when `true`, resets the tracking of the lowest `source`.
// @param source (series int/float) Series of values to process. Optional. The default is `low`.
// @returns (float) The lowest `source` value since the last time the `cond` was `true`.
export lowestSince(series bool cond, series float source = low) =>
var float result = na
if cond
result := source
result := math.min(nz(source, result), nz(result, source))
// @function The "zone" calculation used in `pzo()` and `vzo()` functions.
// @param source (series float) Series of values to process.
// @param length (simple int) Length for the smoothing parameter calculation.
// @returns (float) The oscillator value.
zone(series float source, simple int length) =>
float result = 100 * nz(ta.ema(math.sign(ta.change(close)) * source, length) / ta.ema(source, length))
// @function Calculates the value of the Price Zone Oscillator.
// @param length (simple int) Length for the smoothing parameter calculation.
// @returns (float) The oscillator value.
export pzo(simple int length) =>
float result = zone(close, length)
// @function Calculates the volume since the last change in the time value from the
// `anchorTimeframe`, the historical average volume using bars from past periods
// that have the same relative time offset as the current bar from the start of its
// period, and the ratio of these volumes. The volume values are cumulative by default,
// but can be adjusted to non-accumulated with the `isCumulative` parameter.
// @param length (simple int) The number of periods to use for the historical average calculation.
// @param anchorTimeframe (simple string) The anchor timeframe used in the calculation. Optional. Default is "D".
// @param isCumulative (simple bool) If `true`, the volume values will be accumulated since the start of the last
// `anchorTimeframe`. If `false`, values will be used without accumulation. Optional. The
// default is `true`.
// @param adjustRealtime (simple bool) If `true`, estimates the cumulative value on unclosed bars based on the
// data since the last `anchor` condition. Optional. The default is `false`.
// @returns ([float, float, float]) A tuple of three float values. The first element is the current
// volume. The second is the average of volumes at equivalent time offsets from past
// anchors over the specified number of periods. The third is the ratio of the current volume
// to the historical average volume.
export relativeVolume(
simple int length, simple string anchorTimeframe = "D",
simple bool isCumulative = true, simple bool adjustRealtime = true
) =>
bool anchor = timeframe.change(anchorTimeframe)
float currVol = isCumulative ? TVrv.calcCumulativeSeries(volume, anchor, adjustRealtime) : volume
float pastVol = TVrv.averageAtTime(volume, length, anchorTimeframe, isCumulative)
float volRatio = currVol / pastVol
[currVol, pastVol, volRatio]
// @function An alternate RMA function to the `ta.rma()` built-in, which allows a "series float"
// `length` argument.
// @param source (series int/float) Series of values to process.
// @param length (series int/float) Length for the smoothing parameter calculation.
// @returns (float) The rolling moving average of the `source`.
export rma2(series float source, series float length) =>
float alpha = 1.0 / math.max(1.0, length)
float result = ewma(source, alpha)
// @function Calculates the Root Mean Square of the `source` over the `length`.
// @param source (series int/float) Series of values to process.
// @param length (series int) Number of bars (length).
// @returns (float) The RMS value.
export rms(series float source, series int length) =>
float result = math.sqrt(math.sum(math.pow(source, 2), length) / length)
// @function Calculates the values of the Random Walk Index.
// @param length (simple int) Lookback and ATR smoothing parameter length.
// @returns ([float, float]) A tuple of the `rwiHigh` and `rwiLow` values.
export rwi(simple int length) =>
float divisor = ta.atr(length) * math.sqrt(length)
float rwiHigh = (high - nz(low[length])) / divisor
float rwiLow = (nz(high[length]) - low) / divisor
[rwiHigh, rwiLow]
// @function Calculates the value of the Schaff Trend Cycle indicator.
// @param source (series int/float) Series of values to process.
// @param fast (simple int) Length for the MACD fast smoothing parameter calculation.
// @param slow (simple int) Length for the MACD slow smoothing parameter calculation.
// @param cycle (simple int) Number of bars for the Stochastic values (length).
// @param d1 (simple int) Length for the initial %D smoothing parameter calculation.
// @param d2 (simple int) Length for the final %D smoothing parameter calculation.
// @returns (float) The oscillator value.
export stc(series float source, simple int fast, simple int slow, simple int cycle, simple int d1, simple int d2) =>
float macd = ta.ema(source, fast) - ta.ema(source, slow)
float k = nz(fixnan(ta.stoch(macd, macd, macd, cycle)))
float d = ta.ema(k, d1)
float kd = nz(fixnan(ta.stoch(d, d, d, cycle)))
float stc = ta.ema(kd, d2)
float result = math.max(math.min(stc, 100), 0)
// @function Calculates the %K and %D values of the Full Stochastic indicator.
// @param periodK (simple int) Number of bars for Stochastic calculation. (length).
// @param smoothK (simple int) Number of bars for smoothing of the %K value (length).
// @param periodD (simple int) Number of bars for smoothing of the %D value (length).
// @returns ([float, float]) A tuple of the slow %K and the %D moving average values.
export stochFull(simple int periodK, simple int smoothK, simple int periodD) =>
float k = ta.sma(ta.stoch(close, high, low, periodK), smoothK)
float d = ta.sma(k, periodD)
[k, d]
// @function Calculates the %K and %D values of the Stochastic RSI indicator.
// @param lengthRsi (simple int) Length for the RSI smoothing parameter calculation.
// @param periodK (simple int) Number of bars for Stochastic calculation. (length).
// @param smoothK (simple int) Number of bars for smoothing of the %K value (length).
// @param periodD (simple int) Number of bars for smoothing of the %D value (length).
// @param source (series int/float) Series of values to process. Optional. The default is `close`.
// @returns ([float, float]) A tuple of the slow %K and the %D moving average values.
export stochRsi(
simple int lengthRsi, simple int periodK, simple int smoothK, simple int periodD, series float source = close
) =>
float rsi = ta.rsi(source, lengthRsi)
float k = ta.sma(ta.stoch(rsi, rsi, rsi, periodK), smoothK)
float d = ta.sma(k, periodD)
[k, d]
// @function Calculates the values of the SuperTrend indicator with the ability to take candle wicks
// into account, rather than only the closing price.
// @param factor (series int/float) Multiplier for the ATR value.
// @param atrLength (simple int) Length for the ATR smoothing parameter calculation.
// @param wicks (simple bool) Condition to determine whether to take candle wicks into account when
// reversing trend, or to use the close price. Optional. Default is false.
// @returns ([float, int]) A tuple of the superTrend value and trend direction.
export supertrend(series float factor, simple int atrLength, simple bool wicks = false) =>
float source = hl2
int direction = na
float superTrend = na
float atr = ta.atr(atrLength) * factor
float upperBand = source + atr
float lowerBand = source - atr
float highPrice = wicks ? high : close
float lowPrice = wicks ? low : close
float prevLowerBand = nz(lowerBand[1])
float prevUpperBand = nz(upperBand[1])
lowerBand := lowerBand > prevLowerBand or lowPrice[1] < prevLowerBand ? lowerBand : prevLowerBand
upperBand := upperBand < prevUpperBand or highPrice[1] > prevUpperBand ? upperBand : prevUpperBand
float prevSuperTrend = superTrend[1]
if na(atr[1])
direction := 1
else if prevSuperTrend == prevUpperBand
direction := highPrice > upperBand ? -1 : 1
else
direction := lowPrice < lowerBand ? 1 : -1
superTrend := direction == -1 ? lowerBand : upperBand
[superTrend, direction]
// @function An alternate SuperTrend function to `supertrend()`, which allows a "series float"
// `atrLength` argument.
// @param factor (series int/float) Multiplier for the ATR value.
// @param atrLength (series int/float) Length for the ATR smoothing parameter calculation.
// @param wicks (simple bool) Condition to determine whether to take candle wicks into account when
// reversing trend, or to use the close price. Optional. Default is false.
// @returns ([float, int]) A tuple of the superTrend value and trend direction.
export supertrend2(series float factor, series float atrLength, simple bool wicks = false) =>
float source = hl2
int direction = na
float superTrend = na
float atr = atr2(atrLength) * factor
float upperBand = source + atr
float lowerBand = source - atr
float highPrice = wicks ? high : close
float lowPrice = wicks ? low : close
float prevLowerBand = nz(lowerBand[1])
float prevUpperBand = nz(upperBand[1])
lowerBand := lowerBand > prevLowerBand or lowPrice[1] < prevLowerBand ? lowerBand : prevLowerBand
upperBand := upperBand < prevUpperBand or highPrice[1] > prevUpperBand ? upperBand : prevUpperBand
float prevSuperTrend = superTrend[1]
if na(atr[1])
direction := 1
else if prevSuperTrend == prevUpperBand
direction := highPrice > upperBand ? -1 : 1
else
direction := lowPrice < lowerBand ? 1 : -1
superTrend := direction == -1 ? lowerBand : upperBand
[superTrend, direction]
// @function Calculates the Generalized DEMA (GD) used in the `t3()` function.
// @param source (series int/float) Series of values to process.
// @param length (simple int) Length for the smoothing parameter calculation.
// @param vf (simple float) Volume factor. Affects the responsiveness.
// @returns (float) The GD value of the `source`.
gd(series float source, simple int length, simple float vf) =>
float result = ta.ema(source, length) * (1 + vf) - ta.ema(ta.ema(source, length), length) * vf
// @function Calculates the value of the Tilson Moving Average (T3).
// @param source (series int/float) Series of values to process.
// @param length (simple int) Length for the smoothing parameter calculation.
// @param vf (simple float) Volume factor. Affects the responsiveness.
// @returns (float) The Tilson moving average of the `source`.
export t3(series float source, simple int length, simple float vf = 0.7) =>
float result = gd(gd(gd(source, length, vf), length, vf), length, vf)
// @function An alternate Generalized DEMA (GD) function to `gd()`, which allows a "series float"
// `length` argument.
// @param source (series int/float) Series of values to process.
// @param length (series int/float) Length for the smoothing parameter calculation.
// @param vf (simple float) Volume factor. Affects the responsiveness.
// @returns (float) The GD value of the `source`.
gd2(series float source, series float length, simple float vf) =>
float result = ema2(source, length) * (1 + vf) - ema2(ema2(source, length), length) * vf
// @function An alternate Tilson Moving Average (T3) function to `t3()`, which allows a "series float"
// `length` argument.
// @param source (series int/float) Series of values to process.
// @param length (series int/float) Length for the smoothing parameter calculation.
// @param vf (simple float) Volume factor. Affects the responsiveness.
// @returns (float) The Tilson moving average of the `source`.
export t3Alt(series float source, series float length, simple float vf = 0.7) =>
float result = gd2(gd2(gd2(source, length, vf), length, vf), length, vf)
// @function Calculates the value of the Triple Exponential Moving Average (TEMA).
// @param source (series int/float) Series of values to process.
// @param length (simple int) Length for the smoothing parameter calculation.
// @returns (float) The triple exponentially weighted moving average of the `source`.
export tema(series float source, simple int length) =>
float ema1 = ta.ema(source, length)
float ema2 = ta.ema(ema1, length)
float ema3 = ta.ema(ema2, length)
float result = 3 * (ema1 - ema2) + ema3
// @function An alternate Triple Exponential Moving Average (TEMA) function to `tema()`, which allows a
// "series float" `length` argument.
// @param source (series int/float) Series of values to process.
// @param length (series int/float) Length for the smoothing parameter calculation.
// @returns (float) The triple exponentially weighted moving average of the `source`.
export tema2(series float source, series float length) =>
float ema1 = ema2(source, length)
float ema2 = ema2(ema1, length)
float ema3 = ema2(ema2, length)
float result = 3 * (ema1 - ema2) + ema3
// @function Calculates the value of the Triangular Moving Average (TRIMA).
// @param source (series int/float) Series of values to process.
// @param length (series int) Number of bars (length).
// @returns (float) The triangular moving average of the `source`.
export trima(series float source, series int length) =>
float result = ta.sma(ta.sma(source, math.ceil(length / 2)), math.floor(length / 2) + 1)
// @function Calculates the values of the TRIX indicator.
// @param source (series int/float) Series of values to process.
// @param length (simple int) Length for the smoothing parameter calculation.
// @param signalLength (simple int) Length for smoothing the signal line.
// @param exponential (simple bool) Condition to determine whether exponential or simple smoothing is used.
// Optional. The default is `true` (exponential smoothing).
// @returns ([float, float, float]) A tuple of the TRIX value, the signal value, and the histogram.
export trix(series float source, simple int length, simple int signalLength, simple bool exponential = true) =>
float triple = ta.ema(ta.ema(ta.ema(source, length), length), length)
float trix = ta.roc(triple, 1)
float signal = exponential ? ta.ema(trix, signalLength) : ta.sma(trix, signalLength)
float hist = trix - signal
[trix, signal, hist]
// @function Calculates the value of the Sentiment Zone Oscillator.
// @param source (series int/float) Series of values to process.
// @param length (simple int) Length for the smoothing parameter calculation.
// @returns (float) The oscillator value.
export szo(series float source, simple int length) =>
float trend = math.sign(ta.change(source))
float sentPos = tema(trend, length)
float result = 100 * sentPos / length
// @function Calculates the weighted average used in the `uo()` function.
// @param bp (series float) A source series representing the "Buying Pressure" value.
// @param trange (series float) A source series representing the True Range value.
// @param length (simple int) Number of bars (length).
// @returns (float) The weighted average value.
uoAverage(series float bp, series float trange, simple int length) =>
float result = math.sum(bp, length) / math.sum(trange, length)
// @function Calculates the value of the Ultimate Oscillator.
// @param fastLen (series int) Number of bars for the fast smoothing average (length).
// @param midLen (series int) Number of bars for the middle smoothing average (length).
// @param slowLen (series int) Number of bars for the slow smoothing average (length).
// @returns (float) The oscillator value.
export uo(simple int fastLen, simple int midLen, simple int slowLen) =>
float tMax = math.max(high, close[1])
float tMin = math.min(low, close[1])
float tr = tMax - tMin
float bp = close - tMin
float avg1 = uoAverage(bp, tr, fastLen)
float avg2 = uoAverage(bp, tr, midLen)
float avg3 = uoAverage(bp, tr, slowLen)
float result = 100 * (4 * avg1 + 2 * avg2 + avg3) / 7
// @function Calculates the value of the Vertical Horizontal Filter.
// @param source (series int/float) Series of values to process.
// @param length (simple int) Number of bars (length).
// @returns (float) The oscillator value.
export vhf(series float source, simple int length) =>
float sumChanges = math.sum(math.abs(ta.change(source)), length)
float result = math.abs(ta.highest(source, length) - ta.lowest(source, length)) / sumChanges
// @function Calculates the values of the Vortex Indicator.
// @param length (simple int) Number of bars (length).
// @returns ([float, float]) A tuple of the viPlus and viMinus values.
export vi(simple int length) =>
divisor = math.sum(ta.atr(1), length)
viPlus = math.sum(math.abs(high - nz(low[1])), length) / divisor
viMinus = math.sum(math.abs(low - nz(high[1])), length) / divisor
[viPlus, viMinus]
// @function Calculates an ATR-based stop value that trails behind the `source`. Can serve as a
// possible stop-loss guide and trend identifier.
// @param source (series int/float) Series of values that the stop trails behind.
// @param atrLength (simple int) Length for the ATR smoothing parameter calculation.
// @param atrFactor (series int/float) The multiplier of the ATR value. Affects the maximum distance between
// the stop and the `source` value. A value of 1 means the maximum distance is 100% of the
// ATR value. Optional. The default is 1.
// @returns ([float, bool]) A tuple of the volatility stop value and the trend direction as a "bool".
export vStop(series float source, simple int atrLength, series float atrFactor = 1) =>
float src = nz(source, close)
float atrM = nz(ta.atr(atrLength) * atrFactor, ta.tr(true))
var bool trendUp = true
var float max = src
var float min = src
var float stop = 0.0
max := math.max(max, src)
min := math.min(min, src)
stop := nz(trendUp ? math.max(stop, max - atrM) : math.min(stop, min + atrM), src)
trendUp := src - stop >= 0.0
if trendUp != nz(trendUp[1], true)
max := src
min := src
stop := trendUp ? max - atrM : min + atrM
[stop, trendUp]
// @function An alternate Volatility Stop function to `vStop()`, which allows a "series float"
// `atrLength` argument.
// @param source (series int/float) Series of values that the stop trails behind.
// @param atrLength (series int/float) Length for the ATR smoothing parameter calculation.
// @param atrFactor (series int/float) The multiplier of the ATR value. Affects the maximum distance between
// the stop and the `source` value. A value of 1 means the maximum distance is 100% of the
// ATR value. Optional. The default is 1.
// @returns ([float, bool]) A tuple of the volatility stop value and the trend direction as a "bool".
export vStop2(series float source, series float atrLength, series float atrFactor = 1) =>
float src = nz(source, close)
float atrM = nz(atr2(atrLength) * atrFactor, ta.tr(true))
var bool trendUp = true
var float max = src
var float min = src
var float stop = 0.0
max := math.max(max, src)
min := math.min(min, src)
stop := nz(trendUp ? math.max(stop, max - atrM) : math.min(stop, min + atrM), src)
trendUp := src - stop >= 0.0
if trendUp != nz(trendUp[1], true)
max := src
min := src
stop := trendUp ? max - atrM : min + atrM
[stop, trendUp]
// @function Calculates the value of the Volume Zone Oscillator.
// @param length (simple int) Length for the smoothing parameter calculation.
// @returns (float) The oscillator value.
export vzo(simple int length) =>
float result = zone(volume, length)
// @function Detects Williams fractals (used by `williamsFractal()`).
// @param source (series int/float) Series of values to process.
// @param n (series int) Lookback in bars.
// @param direction (simple int) Direction of the fractal to detect (+1 for up, -1 for down).
// @returns (series bool) `true` when a fractal was detected, `false` otherwise.
flag(series float source, series int n, simple int direction) =>
float src = source * direction
bool flag = true
bool flag0 = true
bool flag1 = true
bool flag2 = true
bool flag3 = true
bool flag4 = true
for i = 1 to n
flag := flag and (src[n - i] < src[n])
flag0 := flag0 and (src[n + i] < src[n])
flag1 := flag1 and (src[n + 1] <= src[n] and src[n + i + 1] < src[n])
flag2 := flag2 and (src[n + 1] <= src[n] and src[n + 2] <= src[n] and src[n + i + 2] < src[n])
flag3 := flag3 and (src[n + 1] <= src[n] and src[n + 2] <= src[n] and src[n + 3] <= src[n] and src[n + i + 3] < src[n])
flag4 := flag4 and (src[n + 1] <= src[n] and src[n + 2] <= src[n] and src[n + 3] <= src[n] and src[n + 4] <= src[n] and src[n + i + 4] < src[n])
bool flags = flag0 or flag1 or flag2 or flag3 or flag4
bool result = (flag and flags)
// @function Detects Williams Fractals.
// @param period (series int) Number of bars (length).
// @returns ([bool, bool]) A tuple of an up fractal and down fractal. Variables are true when detected.
export williamsFractal(series int period) =>
bool upFractal = flag(high, period, 1)
bool downFractal = flag(low, period, -1)
[upFractal, downFractal]
// @function Calculates the value of the Wave Period Oscillator.
// @param length (simple int) Length for the smoothing parameter calculation.
// @returns (float) The oscillator value.
export wpo(simple int length) =>
float tt = 2 * math.pi / math.asin(close[1] / high)
float ti = math.sign(ta.change(close)) * tt
float result = ta.ema(ti, length)
plot(cagr(time[1], close[1], time, close))
Show all 729 lines