// Licensed under the Apache License, Version 2.0 // © mihakralj //@version=6 indicator("Elder's Thermometer", "ETHERM", overlay=false) //@function Calculates Elder's Market Thermometer with EMA signal line //@param period The EMA smoothing period for the signal line //@returns [thermometer, signal] The raw thermometer value and EMA signal line //@optimized Beta precomputation for EMA warmup compensation etherm(simple int period) => // Step 1: Calculate raw thermometer value // Temperature = max of upward high protrusion and downward low protrusion // Only outward extensions count; contractions clamp to zero float prevHigh = nz(high[1], high) float prevLow = nz(low[1], low) float highDiff = math.max(high - prevHigh, 0.0) float lowDiff = math.max(prevLow - low, 0.0) float temp = math.max(highDiff, lowDiff) // Step 2: EMA of thermometer with warmup compensation float alpha = 2.0 / float(period + 1) float beta = 1.0 - alpha var float EPSILON = 1e-10 var float raw_ema = 0.0 var float e = 1.0 float signal = na if not na(temp) raw_ema := raw_ema * beta + temp * alpha e *= beta signal := e > EPSILON ? raw_ema / (1.0 - e) : raw_ema [temp, signal] // ---------- Main loop ---------- // Inputs i_period = input.int(22, "EMA Period", minval=1, tooltip="Number of bars for the EMA signal line") i_multiplier = input.float(3.0, "Explosive Threshold", minval=0.1, step=0.5, tooltip="Multiplier for explosive move detection") // Calculation [thermValue, signalValue] = etherm(i_period) // Colors bool isExplosive = thermValue >= signalValue * i_multiplier bool isHot = thermValue >= signalValue color thermColor = isExplosive ? color.red : isHot ? color.orange : color.new(color.blue, 30) // Plot plot(thermValue, "Thermometer", color=thermColor, style=plot.style_histogram, linewidth=2) plot(signalValue, "Signal", color=color.yellow, linewidth=2)