Library · Pine Script v6 · Library

MovingAverages

by Electrified-Trading

This library exports utilities for calculating moving averages rather than drawing them on a chart.

View on GitHub

GitHub stars2on the repository
Pine versionv6current
Lines of code320
Settings0inputs
LicenceMPL-2.0
Last update1 year ago7 Jul 2025

Add It to Your TradingView Chart

  1. 1Copy the scriptPress Copy script above, or the copy button on the code below.
  2. 2Open the Pine EditorOpen a TradingView chart and choose Pine Editor at the bottom of the screen.
  3. 3Paste over the templateCreate a new library, select all of the template text and paste. Press Save and give it a name.
  4. 4Publish or import itA library draws nothing. Publish it from the editor, then import its functions in your own scripts.

Source Code

320 lines of Pine Script v6 from MovingAverages.pine, published under MPL-2.0. Keep the author's credit and licence lines when you reuse it.

MovingAverages.pine
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © Electrified (electrifiedtrading)

// @version=6
// @description Contains utilities for generating moving average values including getting a moving average by name and a function for generating a Volume-Adjusted WMA.
library('MovingAverages', true)

isLenInvalid(simple int len, simple string name = 'len') =>
    if na(len)
        runtime.error("The '"+name+"' param cannot be NA.")
        true
    else if len < 0
        runtime.error("The '"+name+"' param cannot be negative.")
        true
    else if len == 0
        true
    else
        false

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// VAWMA = VWMA and WMA combined.
// Simply put, this attempts to determine the average price per share over time weighted heavier for recent values.
// Uses triangular algorithm to taper off values in the past (same as WMA does).
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////
// @function VAWMA = VWMA and WMA combined. Simply put, this attempts to determine the average price per share over time weighted heavier for recent values. Uses a triangular algorithm to taper off values in the past (same as WMA does).
// @param len The number of bars to measure with.
// @param src The series to measure from.  Default is 'hlc3'.
// @param volumeDefault The default value to use when a chart has no (N/A) volume.
// @returns The volume adjusted triangular weighted moving average of the series.
export vawma(
  simple int len,
  series float src = hlc3,
  simple float volumeDefault = na,
  simple int startingWeight = 1) =>
    var float notAvailable = na
    if isLenInvalid(len)
        notAvailable
    else
        sum = 0.0
        vol = 0.0
        last = len - 1
        for i = 0 to last
            s = src[i]
            v = volume[i]
            if na(v) and not na(volumeDefault)
                v := volumeDefault
            if not na(s) and not na(v)
                m = last - i + startingWeight
                v *= m
                vol += v
                sum += s * v
        vol == 0 ? na : sum/vol
///////////////////////////////////////////////////

///////////////////////////////////////////////////
// @function Coefficient Moving Avereage (CMA) is a variation of a moving average that can simulate SMA or WMA with the advantage of previous data.
// @param n The number of bars to measure with.
// @param D The series to measure from.  Default is 'close'.
// @param C The coefficient to use when averaging. 0 behaves like SMA, 1 behaves like WMA.
// @param compound When true (default is false) will use a compounding method for weighting the average.
export cma(
  simple int n,
  series float D = close,
  simple float C = 1,
  simple bool compound = false) =>
    var float notAvailable = na
    if isLenInvalid(n, 'n')
        notAvailable
    else
        var float result = na
        sum = 0.0
        weight = 1.0
        weightTotal = 0.0
        for m = 1 to n
            s = D[n - m]
            if not na(s)
                sum := sum + s * weight
                weightTotal += weight
                if compound
                    weight *= 1 + C
                else
                    weight += C

        prev = result[n]
        if na(prev)
            result := sum / weightTotal
        else
            result := (prev + sum) / (weightTotal + 1)
///////////////////////////////////////////////////


///////////////////////////////////////////////////
// @function Same as ta.ema(src,len) but properly ignores NA values.
// @param len The number of samples to derive the average from.
// @param src The series to measure from.  Default is 'close'.
export ema(
  simple int len,
  series float src = close) =>
    var float notAvailable = na
    if isLenInvalid(len)
        notAvailable
    else
        var float alpha = 2 / (len + 1)
        var float a1 = 1 - alpha
        var float s = na
        var float ema = na
        if not na(src)
            s := src
        ema := alpha * s + a1 * nz(ema)
///////////////////////////////////////////////////

///////////////////////////////////////////////////
// @function Same as ta.wma(src,len) but properly ignores NA values.
// @param len The number of samples to derive the average from.
// @param src The series to measure from.  Default is 'close'.
// @param startingWeight The weight to begin with when calculating the average.  Higher numbers will decrease the bias.
export wma(
  simple int len,
  series float src = close,
  simple int startingWeight = 1) =>
    var float notAvailable = na
    if isLenInvalid(len)
        notAvailable
    else
        sum = 0.0
        total = 0
        last = len - 1
        for i = 0 to last
            s = src[i]
            if not na(s)
                m = last - i + startingWeight // triangular multiple
                total += m
                sum += s * m
        total == 0 ? na : sum/total
///////////////////////////////////////////////////

///////////////////////////////////////////////////
// @function Same as ta.vwma(src,len) but properly ignores NA values.
// @param len The number of bars to measure with.
// @param src The series to measure from.  Default is 'hlc3'.
// @param volumeDefault The default value to use when a chart has no (N/A) volume.
export vwma(
  simple int len,
  series float src = hlc3,
  simple float volumeDefault = na) =>
    var float notAvailable = na
    if isLenInvalid(len)
        notAvailable
    else
        var sum = 0.0
        var vol = 0.0
        float datum = na

        v = volume
        if na(v) and not na(volumeDefault)
            v := volumeDefault

        if not na(src) and not na(v)
            vol += v
            datum := src * v
            sum += datum
        else
            v := na

        vStart = v[len]
        dStart = datum[len]
        if not na(vStart)
            vol -= vStart
        if not na(dStart)
            sum -= dStart

        vol == 0 ? na : sum/vol
///////////////////////////////////////////////////

type VWAP
    float sum
    float volume
    float value

vwap(float sum, float vol, float ratio = 1) =>
    VWAP.new(ratio * sum, ratio * vol, sum/vol)

sum(VWAP a, VWAP b, float ratio = 1) =>
    s = a.sum + b.sum
    v = a.volume + b.volume
    vwap(s, v, ratio)

import Electrified/Time/7
///////////////////////////////////////////////////
// @function This is experimental moving average doesn't use a period/length but instead buffers the price per share and transfers that price per share at a given ratio per bar while also releasing the previous values at a decay ratio.
// @param transferRatio The ratio at which buffered data is applied to the average.
// @param releaseRatio The ratio at which data is released from the average.
// @param useTime When true will tend to make the values consistent across timeframes.
// @param src The series to measure from.  Default is 'hlc3'.
// @param vol The series to represent volume.  The default is 'volume'.
export rsvwma(
  simple float transferRatio,
  simple float releaseRatio,
  simple bool useTime,
  series float src = hlc3,
  float vol = volume) =>
    var retainRatio = 1 - releaseRatio
    var minutesPerBar = Time.bar() / 1000 / 60
    var m = useTime ? minutesPerBar : 1
    var r = math.pow(1 - transferRatio, m)

    var active = VWAP.new(0, 0, 0)
    var surplus = VWAP.new(0, 0, 0)

    s = surplus.sum + nz(src * vol)
    v = surplus.volume + (na(src) ? 0 : nz(vol))
    transfer = vwap(s, v, 1 - r)
    surplus := vwap(s, v, r)
    active := sum(active, transfer, math.pow(retainRatio, m))

    active.value
///////////////////////////////////////////////////

const string SMA = 'SMA'
const string EMA = 'EMA'
const string WMA = 'WMA'
const string CMA = 'CMA'
const string VWMA = 'VWMA'
const string VAWMA = 'VAWMA'

///////////////////////////////////////////////////
// Moving Average Types
///////////////////////////////////////////////////
export enum Type
    SMA = 'SMA'
    EMA = 'EMA'
    WMA = 'WMA'
    CMA = 'CMA'
    VWMA = 'VWMA'
    VAWMA = 'VAWMA'

///////////////////////////////////////////////////
// @function Generates a moving average based upon a 'type'.
// @param type The type of moving average to generate.  Values allowed are: SMA, EMA, WMA, VWMA and VAWMA.
// @param len The number of bars to measure with.
// @param src The series to measure from.  Default is 'close'.
// @returns The moving average series requested.
export get(
  simple string type,
  simple int len,
  series float src = close) =>
    switch type
        WMA => wma(len, src)
        EMA => ema(len, src)
        VWMA => vwma(len, src)
        VAWMA => vawma(len, src)
        CMA => cma(len, src)
        SMA => ta.sma(src, len)
        =>
            runtime.error("No matching MA type found.")
            na
///////////////////////////////////////////////////

///////////////////////////////////////////////////
// @function Generates a moving average based upon a 'type' (enum overload).
// @param type The type of moving average to generate as a Type enum. Values allowed are: Type.SMA, Type.EMA, Type.WMA, Type.VWMA, Type.VAWMA, Type.CMA.
// @param len The number of bars to measure with.
// @param src The series to measure from.  Default is 'close'.
// @returns The moving average series requested.
export get(
  simple Type type,
  simple int len,
  series float src = close) =>
    get(str.tostring(type), len, src)
///////////////////////////////////////////////////

getLevels(float[] values) =>
    avg = math.abs(array.avg(values))
    stdev = array.stdev(values)
    [avg + stdev, stdev]

///////////////////////////////////////////////////
// @function The slope of the source (change over time) is measured over the mLen to determine what is considered 'normal'. A positive value less than 1 is considered within 1 standard deviation.  A value less than 2 is within 2 standard deviations and so-on. This allows for the slope of a value to be standardized regardless of the symbol.
// @param source The series (typically a moving average) to meaasue the slope.
// @param mlen The number of bars to measure the standard deviation of the slope.
// @param slopeLen The number of bars to measure the slope. A higher number will smooth out the curve.
// @returns The nromalized value of the slope.
export normalizeSlope(series float source, simple int mLen = 400, simple int slopeLen = 1) =>
    var pos = array.new_float()
    var neg = array.new_float()

    change = ta.change(source, slopeLen)
    if(change > 0)
        array.push(pos, change)
        if array.size(pos) > mLen
            array.shift(pos)
    if(change < 0)
        array.push(neg, change)
        if array.size(neg) > mLen
            array.shift(neg)

    [pos_level1, pos_stdev] = getLevels(pos)
    [neg_level1, neg_stdev] = getLevels(neg)

    if change > 0
        if(change < pos_level1)
            change / pos_level1
        else
            (change - pos_level1) / pos_stdev + 1
    else if change < 0
        if(change > -neg_level1)
            change / neg_level1
        else
            (change + neg_level1) / neg_stdev - 1
    else
        0
///////////////////////////////////////////////////

// Demo
plot(ema(20), 'ema(20)', color.red)
plot(wma(20), 'wma(20)', color.yellow)
plot(vwma(20), 'vwma(20)', color.blue)
plot(vawma(20), 'vawma(20)', color.purple)

Overview

MovingAverages provides a volume-adjusted weighted moving average that combines volume weighting with triangular recent-bar emphasis, and a coefficient moving average that interpolates between simple and weighted behavior. Callers choose length, source, a fallback volume value, starting weight, and a coefficient, with optional compounding. Invalid lengths return na after a runtime error.

Details

Published by

Electrified-Trading on GitHub

Type

Library, Pine Script v6

Draws

Library (no plots)

Category

Moving averages, Volume

Markets

Any symbol

Timeframes

Any timeframe

Risk Notes

No repainting, lookahead or stacked entries were found in its code or README. That says nothing about how well it works: test it first.

Third-party code. ForexR did not write, test or endorse this script, and the summary above was generated automatically from its code and README. Indicators describe the past, and a strategy's backtest can look better than live trading, especially when a script repaints. Check it in the Strategy Tester and on a demo account before you rely on it.

Similar Pine Scripts

FunctionArrayMovingAverage

by ricardosantos79
261 stars

This Pine Script v5 library provides an exported function to calculate moving averages directly over float arrays. Users can supply a sample array, set the smoothing length, choose whether to omit initial values prior to reaching the lookback window, and speci

Library v5 Moving averages
Updated 4 years ago · None stated GitHub repository of FunctionArrayMovingAverage
29 stars

This library exports one function, custom_ma, which returns a 14-period exponential moving average of a supplied source series. It declares no inputs, so the length stays fixed at 14 and the caller chooses the series. It plots nothing and does not generate ent

Library v5 Moving averages
Updated 11 months ago · Custom licence GitHub repository of Exponential Trend [AlgoAlpha]

Bands

by heyphat
26 stars

This library exports a Band type and functions that build a simple-moving-average basis with upper and lower envelopes from standard deviation. It classifies a source as above, below, or inside those envelopes, measures band width, and scales an imported z-sco

Library v6 Volatility & bandsMoving averages
Updated 2 months ago · AGPL-3.0 GitHub repository of Bands

Public

by wanjo-tech
6 stars

This Pine Script v5 library walks historical price, volume, time and amount series until a requested number of hours is covered, stopping at 4999 bars. TimeAligned returns the bar count, net and absolute price changes, net and absolute log-price changes, volum

Library v5 Volatility & bandsVolume
Updated 2 years ago · None stated GitHub repository of Public

MirPapa_Lib_trend

by alvinng214
2 stars

MirPapa_Lib_trend is a Pine Script utility library providing trend and momentum calculation functions for other scripts. It features implementations for several moving average types, including the Hull Moving Average (HMA), Exponential Hull Moving Average (EHM

Library v6 TrendMoving averages
Updated 2 months ago · None stated GitHub repository of MirPapa_Lib_trend

ta

by ivansoft
1 stars

Provides a collection of technical analysis calculation functions for use across Pine scripts. It exports implementations for various indicators and mathematical formulas, including oscillators like the Awesome Oscillator, Aroon, and Schaff Trend Cycle, moving

Library v5 TrendOscillators & momentum
Updated 1 year ago · None stated GitHub repository of ta

More libraries

Trade Your Charts With a Regulated Broker

Compare brokers that connect to TradingView, with spreads, minimum deposits and leverage side by side.

Compare brokers