Files

50 lines
1.9 KiB
Plaintext
Raw Permalink Normal View History

// Licensed under the Apache License, Version 2.0
2026-02-26 09:59:44 -08:00
// © 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
2026-02-26 09:59:44 -08:00
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)
2026-02-26 09:59:44 -08:00
// 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)