TradingView indicator comparisons

EMA vs SMMA: smoothing constants and initialization

EMA and SMMA use the same recursive form with different smoothing constants: EMA(N) uses alpha = 2 / (N + 1), while SMMA(N) uses alpha = 1 / N. At the same length above 1, EMA gives a new observation more weight. SMMA(N) has the same coefficient as EMA(2N − 1), but the two produce identical values only when their starting state, subsequent inputs and missing-value rules also match. TradingView calls this SMMA calculation RMA in Pine Script.

See the decision guide

The coefficient controls each update; the seed controls the start

Write either filter as y[t] = alpha × x[t] + (1 − alpha) × y[t−1]. The input coefficient is fixed for a fixed positive integer length. Older observations retain geometrically decreasing influence through the previous state. SMMA does not give all historical prices equal weight, and its length is not a hard cutoff after which old prices disappear.

  • For N > 1, 2/(N+1) > 1/N. Starting from the same state, EMA(N) moves farther toward the next input. This one-update statement does not say that EMA is closer to price at every later point.
  • At N = 1, both coefficients equal 1 and both outputs equal each valid source observation. Lengths zero and below are invalid. Larger lengths retain initialization differences for more updates.
CalculationInput coefficientInitialization to check
EMA(N)2 / (N + 1)The Pine reference example starts from the first source value. Other implementations can seed with an SMA.
SMMA(N) / RMA(N)1 / NThe Pine RMA example and MetaTrader SMMA formula seed with an N-observation SMA.
EMA(2N − 1)2 / ((2N − 1) + 1) = 1 / NUse the same state at the same starting observation as SMMA to prove equality.

SMMA, RMA and Wilder refer to a calculation family

Check the function and its initialization when moving a rule between platforms. The labels below identify the 1/N recurrence in these documented implementations. A custom indicator can use a familiar label with a different seed, extra smoothing, source or offset.

  • RMA and Wilder smoothing use the same 1/N recurrence in these implementations. Compare their startup policies and inputs before treating the outputs as interchangeable.
  • A smoothing option applied to an existing indicator smooths that indicator output. It is not necessarily SMMA applied directly to price. Match the actual input series before comparing lines.
PlatformDocumented nameWhat to verify
TradingViewSMMA (RMA) in the official MA selector example; ta.rma(source, length) in PineRMA uses alpha = 1/length and an SMA seed. Pine documents that missing source values are ignored.
MetaTrader 5Smoothed Moving Average (SMMA)The help formula starts with an SMA, then uses (previous × (N − 1) + close) / N. Match applied price and shift.
thinkorswimWildersAverage(data, length)The documented coefficient is 1/length with an SMA first value. Prefetch and initialization can change the visible starting state.

Why EMA length 2N − 1 is equivalent only with a common state

Set the EMA length to M and solve 2/(M+1) = 1/N. Multiplying gives M+1 = 2N, hence M = 2N−1. If E[0] = S[0] and both process the same next input, subtracting their updates gives E[t] − S[t] = (1 − 1/N) × (E[t−1] − S[t−1]). By induction the difference stays zero. This proves mathematical equality; floating-point implementations can still differ by tiny rounding amounts.

  • When the starting difference is d0 rather than zero, the same subtraction gives d[k] = d0 × (1 − 1/N)^k after k valid updates. For N = 3 and d0 = 3, the differences are 3, 2, 1.333333, 0.888889 and 0.592593 at k = 0 through 4.
  • For that example, 15 valid updates reduce the difference to about 0.006851, below a 0.01-unit tolerance. There is no universal warm-up bar count: choose a tolerance relative to your source units and use k ≥ ln(tolerance/|d0|) / ln(1−1/N) when N > 1 and 0 < tolerance < |d0|.
  • Matching EMA(14) to SMMA(14) compares two different decay rates. Matching EMA(27) to SMMA(14) isolates initialization and implementation differences. These are different experiments.
SMMA length NMatched EMA lengthShared alpha
111
351/3
14271/14
50991/50

Recalculate a seven-observation example

Use synthetic observations 100, 110, 90, 120, 80, 100, 110. After the first three valid observations, seed all controlled versions at their mean: (100 + 110 + 90)/3 = 100. Then update EMA(3) with alpha = 1/2, and both SMMA(3) and the matched EMA(5) with alpha = 1/3. The table rounds display values to six decimals; keep full precision during calculation.

  • At observation 5, SMMA = (1/3) × 80 + (2/3) × 106.666666… = 97.777777…. The matched EMA uses the same update. The equal-length EMA instead gives 0.5 × 80 + 0.5 × 110 = 95.
  • A separate first-value-seeded EMA(5) starts at 100 on observation 1 and reaches 98.888889 on observation 3. Its difference from the SMA-seeded SMMA(3) is then −1.111111 despite equal coefficients. This is an initialization counterexample, not a discrepancy in the equivalence proof.
ObservationInputEMA(3), common seedSMMA(3)EMA(5), common seed
1100Not seededNot seededNot seeded
2110Not seededNot seededNot seeded
3: seed90100.000000100.000000100.000000
4120110.000000106.666667106.666667
58095.00000097.77777897.777778
610097.50000098.51851998.518519
7110103.750000102.345679102.345679

Run the same-data seed audit in Pine Script v6

Paste this indicator into Pine Editor and add it to a chart. Synthetic mode fixes N at 3, uses the table inputs from the first loaded chart bar, and repeats 110 after observation 7. Locate those first seven observations with the Data Window. The green matched EMA markers should sit on the orange SMMA line; the blue equal-length EMA differs. The Data Window exposes their difference, a deliberately shifted seed, and the built-in EMA/RMA difference.

  • Disable synthetic mode to use the selected chart source and length. Keep the same symbol, exchange feed, session, timeframe, price adjustments and loaded history. Do not compare an offset plot against an unshifted one.
  • The shared-seed difference should be zero within floating-point tolerance after initialization. Seed +3 difference should follow 3 × (1−1/N)^k. Do not require the built-in EMA minus RMA field to be zero at startup.
  • All calculations run on every bar; plots require barstate.isconfirmed. Chart-close confirmation does not confirm an external source from another indicator or an unfinished higher timeframe. Use chart close for the basic comparison.
Controlled recurrences share an SMA seed. Built-in functions retain their own startup behavior. This indicator plots only completed chart bars and places no orders.pine
//@version=6
indicator("EMA vs SMMA: seed audit", overlay = false, precision = 6)
bool fixture = input.bool(true, "Use synthetic example (N = 3)")
int chartLength = input.int(14, "Chart source length", minval = 1, maxval = 500)
float chartSource = input.source(close, "Chart source")
bool insertGap = input.bool(false, "Synthetic example: omit observation 5")
int n = fixture ? 3 : chartLength
int emaLength = 2 * n - 1
float sample = switch bar_index
    0 => 100.0
    1 => 110.0
    2 => 90.0
    3 => 120.0
    4 => 80.0
    5 => 100.0
    => 110.0
float src = fixture ? (insertGap and bar_index == 4 ? na : sample) : chartSource
float aSame = 2.0 / (n + 1)
float aMatched = 2.0 / (emaLength + 1)
float aSmma = 1.0 / n
var int count = 0
var float seedSum = 0.0
var float sameEma = na
var float matchedEma = na
var float smma = na
var float shiftedSeed = na
// Skip missing inputs; count only valid observations for the shared seed.
if not na(src)
    if count < n
        seedSum += src
        count += 1
        if count == n
            float seed = seedSum / n
            sameEma := seed
            matchedEma := seed
            smma := seed
            shiftedSeed := seed + 3.0
    else
        sameEma := aSame * src + (1.0 - aSame) * sameEma
        matchedEma := aMatched * src + (1.0 - aMatched) * matchedEma
        smma := aSmma * src + (1.0 - aSmma) * smma
        shiftedSeed := aSmma * src + (1.0 - aSmma) * shiftedSeed
// Built-ins keep their own initialization. Always calculate on every bar.
float nativeEma = ta.ema(src, emaLength)
float nativeRma = ta.rma(src, n)
bool show = barstate.isconfirmed and not na(src)
plot(show ? src : na, "Source", color.gray, style = plot.style_circles)
plot(show ? sameEma : na, "EMA(N), shared seed", color.blue, style = plot.style_linebr)
plot(show ? smma : na, "SMMA(N), shared seed", color.orange, 2, plot.style_linebr)
plot(show ? matchedEma : na, "EMA(2N-1), shared seed", color.green, style = plot.style_circles)
plot(show ? matchedEma - smma : na, "Shared-seed difference", display = display.data_window)
plot(show ? shiftedSeed - smma : na, "Seed +3 difference", display = display.data_window)
plot(show ? nativeEma - nativeRma : na, "Built-in EMA minus RMA", display = display.data_window)
plot(bar_index + 1, "Observation number", display = display.data_window)

Missing data changes what an update means

The example skips na inputs, counts only valid inputs toward its SMA seed, and holds its internal state across a missing observation. It displays a gap on that bar. The next valid observation advances the recurrence once. Pine documents ignored na source values for ta.ema and ta.rma; do not assume that another library uses the same missing-data or output-display policy.

  • Enable the synthetic gap switch to omit observation 5 (the value 80). SMMA remains internally 106.666667 on that missing bar, then becomes 104.444444 at observation 6 and 106.296296 at observation 7. The seed discrepancy also pauses its decay during the gap.
  • Filling the missing observation with zero would instead push SMMA to 71.111111 on observation 5. That is a new price input, not missing-data handling. Forward-filling with the previous price also creates an additional update.
  • Before N valid inputs, the controlled outputs remain unavailable. An all-missing series never seeds. Calendar gaps with no chart bar create no update; a bar whose source is na follows the explicit skip policy. Count valid updates, not elapsed days, in the decay formula.

Turn the chosen calculation into a reviewable rule

Use EMA(N) when your specification needs its larger new-input coefficient at that length, or SMMA(N) when it requires the 1/N recurrence. A smoother line does not prove fewer losing trades. If you compare strategy outcomes, hold crossing rules, confirmation time, fills, costs and evaluation dates fixed before comparing results.

  • Ask the Pine Script AI Coding Agent to draft your selected recurrence with an explicit source, length, seed, missing-value policy and closed-bar rule. Request a syntax check, then compare the generated values with the fixture above.
  • Syntax validation checks supported compilation errors. Inspect numerical outputs and signal timestamps separately before using a generated strategy; this page reports filter calculations, not profitability.
Where Pineify fits

Pine Script AI Coding Agent

Draft a comparison from your source, smoothing and initialization rules. Request a syntax check and verify the output against known values in TradingView.

Draft my EMA/SMMA comparison

Frequently asked questions

Educational comparison, not investment advice. The sample uses synthetic observations and calculated filter values, not market returns or a backtest. Neither average guarantees profitable signals. Review generated code and execution assumptions independently.

Sources and verification

Published by Pineify. Pineify is an independent product and is not affiliated with TradingView. Sources support the technical explanations; examples do not establish trading performance.