// Licensed under the Apache License, Version 2.0 // © mihakralj //@version=6 indicator("Exponential Moving Average (EMA)", "EMA", overlay=true) //@function Calculates EMA using exponential smoothing with compensator //@param source Series to calculate EMA from //@param period Lookback period for EMA calculation //@param alpha Optional smoothing factor (overrides period if provided) //@returns EMA value from first bar with proper compensation //@optimized Uses exponential warmup compensator for O(1) complexity and valid output from bar 1 ema(series float source, simple int period=0, simple float alpha=0) => float a = alpha > 0 ? alpha : 2.0 / (period + 1) float beta = 1.0 - a var bool warmup = true var float e = 1.0 var float ema = 0.0 var float result = source ema := a * (source - ema) + ema if warmup e *= beta float c = 1.0 / (1.0 - e) result := c * ema warmup := e > 1e-10 else result := ema result // ---------- Main loop ---------- // Inputs i_period = input.int(10, "Period", minval=1) i_source = input.source(close, "Source") // Calculation ema_value = ema(i_source, period=i_period) // Plot plot(ema_value, "EMA", color=color.yellow, linewidth=2)