TradingView indicator guides

Moving Average Router in Pine Script: 11 Calculation Contracts

This custom p_ta_ma helper selects one of eleven calculations and plots one result. The displayed call uses EMA of close with length 20. The branches differ in weighting, initialization, volume requirements and extrapolation, so the same length does not give them an identical meaning.

Inspect the Pine Script

The router is custom; the underlying functions differ

p_ta_ma is defined in this script, not a built-in Pine function. The switch accepts exact strings SMA, EMA, RMA, HMA, WMA, TMA, VAR, WWMA, ZLEMA, TSF and VWMA. It has no fallback branch: an unmatched name returns an unavailable value. The current call chooses only EMA and draws one blue overlay line.

SMA averages a finite window equally. EMA recursively mixes the current source with its previous result using alpha = 2/(N+1). RMA uses alpha = 1/N with its own built-in initialization. WMA applies positive linear weights; VWMA weights price by chart volume. HMA combines weighted averages and can overshoot the input range.

These differences matter before any trading rule is added. Missing or zero volume affects VWMA; recursive filters retain earlier history; HMA and TSF are not simply convex averages of the latest N prices. Read the separate EMA, HMA and VWMA references for their calculation boundaries.

The five custom branches need their own specification

  • TMA applies SMA twice: first ceil(N/2), then floor(N/2)+1. For N20 the lengths are10 and11; for N21 they are11 and11. On contiguous valid data, the combined finite support is N bars. It is not two successive N-bar SMAs.
  • VAR uses an absolute CMO-like ratio from a fixed nine-bar sum of positive and negative source changes. Its effective alpha is 2/(N+1) × absolute ratio. The nine-bar momentum lookback does not change with N.
  • WWMA uses alpha1/N but initializes the previous result with zero via nz. This does not reproduce the built-in RMA’s SMA seed.
  • ZLEMA feeds 2×source − source[floor(N/2)] to EMA. This implementation’s even N20 uses lag10; variants using floor((N−1)/2) use9. Record that distinction rather than assuming all ZLEMA scripts match.
  • TSF adds the current fitted regression slope to the current endpoint. It extrapolates that line by one position; it does not read or know the next price.

The pasted code preserves these formulas and makes the ZLEMA history index explicitly integer. It does not replace the custom seeds or claim they are interchangeable with other implementations.

A length is not always a finite history window

With EMA length20, alpha is2/21 and the previous EMA receives weight19/21. Expanding the recursion reveals contributions from earlier history; the calculation does not discard everything before the twentieth bar. The starting value’s influence decays rather than disappearing at a fixed age.

For a sustained linear input after initialization effects have faded, both SMA(N) and EMA with alpha2/(N+1) have a mean weight age of (N−1)/2 bars. At N20 this is9.5. That property does not mean their response to a jump or reversal is identical. It also disproves a blanket claim that EMA20 has half SMA20’s lag.

Assume a long constant history at100, followed by a permanent step to110. At the first changed bar SMA20 is100.5 and EMA20 is100.952381. At the twentieth changed bar SMA20 is110, while EMA20 is100+10×(1−(19/21)^20), approximately108.648904. EMA moves further initially; SMA reaches the new constant level exactly once its window replaces the old prices.

These are deterministic arithmetic fixtures, not evidence of more profitable entries. Define which response property matters before choosing a length or comparing a crossover.

Initialization can dominate a comparison

For constant source100 and N20, the zero-seeded WWMA starts at5, then9.75. After20 updates it is100×(1−0.95^20) =64.151408. The built-in RMA, once its20-price SMA seed is available on that constant series, is100. Equal alpha does not remove the startup difference.

VAR has a stronger flat-start edge case. If the entire loaded source stays at100, its nine-bar up and down sums are both zero. The ratio is replaced by zero, giving effective alpha0. With the helper’s previous-state seed also zero, VAR stays at0. A flat input therefore does not produce a flat100 result in this branch. If adaptation is zero after an earlier nonzero state, that previous state is held.

For TSF, the five prices100,102,101,105,107 have fitted slope1.7 and endpoint106.4. TSF returns108.1 by extending that fit. The next observed price can differ. See the LSMA endpoint and offset example.

Use constant, step and reversal fixtures before comparing live charts. Specify how unavailable data and initialization are handled. The custom router itself does not enforce one uniform readiness policy across all eleven branches.

Separate displayed values from trading events

Price above a moving average is a state. A crossover requires a previous at-or-below relationship followed by a current above relationship. A rising average is not by itself an accelerating price trend; acceleration would require a separate change-of-slope definition. A large price-to-average distance does not establish when price will return.

The reference has no alerts, crossover markers, entry rules or strategy orders. It also has no input declarations: changing the fixed EMA/20/close selection requires editing the call. Pineify’s Visual Pine Script Editor MA block separately exposes source, length and type; request explicit input controls if the generated script needs editable TradingView Settings.

Live source values can change before close. A separate close-confirmed event arrives later and still needs an exit, sizing, fees, slippage and fill assumptions before it becomes a testable strategy. Neither ATR above its average nor an aligned MA ribbon proves liquidity, a profitable edge or agreement across separately requested timeframes.

Check TradingView’s EMA formula and repainting documentation. No universal best parameter or measured win rate is established on this page.

Pine Script v6: implementation and limits

Paste the complete source into Pine Editor. The default call plots EMA20. Review branch-specific seed and history behavior before selecting another type. This reference has no settings inputs, alerts or trading orders.

Pine Script v6
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © Pineify

//@version=6
indicator(title="ma", overlay=true, max_labels_count=500)

// Internal helper functions for custom MA types
p_ta_Var_Func(src, length) =>
    valpha = 2 / (length + 1)
    vud1 = src > src[1] ? src - src[1] : 0
    vdd1 = src < src[1] ? src[1] - src : 0
    vUD = math.sum(vud1, 9)
    vDD = math.sum(vdd1, 9)
    vCMO = nz((vUD - vDD) / (vUD + vDD))
    VAR = 0.0
    VAR := nz(valpha * math.abs(vCMO) * src) + (1 - valpha * math.abs(vCMO)) * nz(VAR[1])
    VAR

p_ta_Wwma_Func(src, length) =>
    wwalpha = 1 / length
    WWMA = 0.0
    WWMA := wwalpha * src + (1 - wwalpha) * nz(WWMA[1])
    WWMA

p_ta_Zlema_Func(src, length) =>
    zxLag = int(math.floor(length / 2))
    zxEMAData = src + src - src[zxLag]
    ZLEMA = ta.ema(zxEMAData, length)
    ZLEMA

p_ta_Tsf_Func(src, length) =>
    lrc = ta.linreg(src, length, 0)
    lrc1 = ta.linreg(src, length, 1)
    lrs = lrc - lrc1
    TSF = ta.linreg(src, length, 0) + lrs
    TSF

// Main MA function — supports 11 moving average types
p_ta_ma(series float source, simple int length, simple string ma_type) =>
    switch ma_type
        "SMA" => ta.sma(source, length)
        "EMA" => ta.ema(source, length)
        "RMA" => ta.rma(source, length)
        "HMA" => ta.hma(source, length)
        "WMA" => ta.wma(source, length)
        "TMA" => ta.sma(ta.sma(source, math.ceil(length / 2)), math.floor(length / 2) + 1)
        "VAR" => p_ta_Var_Func(source, length)
        "WWMA" => p_ta_Wwma_Func(source, length)
        "ZLEMA" => p_ta_Zlema_Func(source, length)
        "TSF" => p_ta_Tsf_Func(source, length)
        "VWMA" => ta.vwma(source, length)

p_ind_1 = p_ta_ma(close, 20, "EMA") // MA

plot(p_ind_1, "MA", color.rgb(41, 98, 255, 0), 1)
Existing indicator chart preview
Existing visual preview. Verify exact values against the source; the image is not a performance result.

Specify a checkable adaptation in Pineify

Name the exact calculation, source, length, seed and missing-data policy. If you need a comparison, ask for separate plotted branches and numerical diagnostics rather than simply “a faster MA.” Validate the final source, compare synthetic fixtures and closed-bar values, then define any strategy independently.

Open Pine Script AI Coding Agent

Educational indicator analysis. No measured trading performance is established here. Syntax validation does not prove formula equivalence, execution assumptions or profitability.

Implementation questions

No. It is the custom switch wrapper included here. It calls built-ins and four custom helper functions; TMA is composed directly in the switch.

No. The fixed call selects EMA at length20 using close. It plots one result. Comparing several types requires separate calculations and plots.

Not here. They share alpha1/N but use different seeds. The custom WWMA starts from zero; built-in RMA initializes from an SMA.

The fixed nine-bar change ratio is replaced by zero when its denominator is zero. Effective alpha then vanishes, and the zero-seeded previous state is retained.

No. It evaluates the current regression line one step beyond its endpoint. It is a conditional extrapolation, not a future observation or measured forecast accuracy.

There is no single ordering for every input and lag definition. With the usual EMA alpha, their steady linear-trend mean weight age matches, while their step responses differ.