mirror of
https://github.com/mihakralj/QuanTAlib.git
synced 2026-08-22 20:48:04 +00:00
Add new moving average implementations: LTMA, MCNMA, NLMA, NMA, NYQMA, RAIN, and TRAMA
- LTMA (Linear Trend Moving Average): Introduces a predictive moving average using dual cascaded EMAs for trend estimation. - MCNMA (McNicholl EMA): Implements a zero-lag TEMA using a cascaded EMA structure for enhanced responsiveness. - NLMA (Non-Lag Moving Average): Utilizes a damped cosine kernel to achieve reduced lag in moving averages. - NMA (Natural Moving Average): Adapts smoothing based on volatility profiles using a square-root kernel. - NYQMA (Nyquist Moving Average): Applies the Nyquist-Shannon theorem to prevent aliasing in cascaded moving averages. - RAIN (Rainbow Moving Average): Combines multiple SMA layers with weighted averages for multi-scale smoothing. - TRAMA (Trend Regularity Adaptive Moving Average): Adapts smoothing based on the frequency of new highs and lows in price data.
This commit is contained in:
@@ -0,0 +1,82 @@
|
||||
// The MIT License (MIT)
|
||||
// © mihakralj
|
||||
//@version=6
|
||||
indicator("Derivative Oscillator (DOSC)", "DOSC", overlay=false, precision=4)
|
||||
|
||||
//@function Calculates the Derivative Oscillator: double-smoothed RSI minus its SMA signal line
|
||||
//@param source Series to calculate from
|
||||
//@param rsiPeriod RSI lookback period
|
||||
//@param ema1Period First EMA smoothing period applied to RSI
|
||||
//@param ema2Period Second EMA smoothing period (double smoothing)
|
||||
//@param sigPeriod SMA signal line period applied to double-smoothed RSI
|
||||
//@returns DOSC value (histogram: double-smoothed RSI minus signal)
|
||||
//@optimized O(1) per bar after warmup for all EMA/SMA stages
|
||||
dosc(series float source, simple int rsiPeriod, simple int ema1Period, simple int ema2Period, simple int sigPeriod) =>
|
||||
if rsiPeriod <= 0 or ema1Period <= 0 or ema2Period <= 0 or sigPeriod <= 0
|
||||
runtime.error("All periods must be greater than 0")
|
||||
|
||||
// --- Stage 1: RSI via Wilder's smoothing ---
|
||||
float change_up = math.max(source - nz(source[1]), 0.0)
|
||||
float change_down = math.max(nz(source[1]) - source, 0.0)
|
||||
|
||||
var float avgGain = 0.0
|
||||
var float avgLoss = 0.0
|
||||
|
||||
float rsiAlpha = 1.0 / rsiPeriod
|
||||
if bar_index < rsiPeriod
|
||||
avgGain := change_up
|
||||
avgLoss := change_down
|
||||
else
|
||||
avgGain := nz(avgGain[1]) * (1.0 - rsiAlpha) + change_up * rsiAlpha
|
||||
avgLoss := nz(avgLoss[1]) * (1.0 - rsiAlpha) + change_down * rsiAlpha
|
||||
|
||||
float rsiVal = avgLoss == 0.0 ? 100.0 : 100.0 - (100.0 / (1.0 + avgGain / avgLoss))
|
||||
|
||||
// --- Stage 2: EMA1 of RSI ---
|
||||
var float ema1 = na
|
||||
float alpha1 = 2.0 / (ema1Period + 1.0)
|
||||
ema1 := na(ema1[1]) ? rsiVal : nz(ema1[1]) * (1.0 - alpha1) + rsiVal * alpha1
|
||||
|
||||
// --- Stage 3: EMA2 of EMA1 (double smoothing) ---
|
||||
var float ema2 = na
|
||||
float alpha2 = 2.0 / (ema2Period + 1.0)
|
||||
ema2 := na(ema2[1]) ? ema1 : nz(ema2[1]) * (1.0 - alpha2) + ema1 * alpha2
|
||||
|
||||
// --- Stage 4: SMA signal line of EMA2 ---
|
||||
var array<float> sigBuf = array.new_float(sigPeriod, na)
|
||||
var int sigHead = 0
|
||||
var int sigCount = 0
|
||||
var float sigSum = 0.0
|
||||
|
||||
float oldest = array.get(sigBuf, sigHead)
|
||||
if not na(oldest)
|
||||
sigSum -= oldest
|
||||
sigSum += ema2
|
||||
else
|
||||
sigCount += 1
|
||||
sigSum += ema2
|
||||
|
||||
array.set(sigBuf, sigHead, ema2)
|
||||
sigHead := (sigHead + 1) % sigPeriod
|
||||
|
||||
float signal = sigCount > 0 ? sigSum / sigCount : 0.0
|
||||
|
||||
// DOSC = double-smoothed RSI minus signal
|
||||
float result = ema2 - signal
|
||||
result
|
||||
|
||||
// ---------- Main loop ----------
|
||||
|
||||
// Inputs
|
||||
i_source = input.source(close, "Source")
|
||||
i_rsiPeriod = input.int(14, "RSI Period", minval=1, maxval=500)
|
||||
i_ema1 = input.int(5, "EMA1 Period", minval=1, maxval=500, tooltip="First EMA smoothing of RSI")
|
||||
i_ema2 = input.int(3, "EMA2 Period", minval=1, maxval=500, tooltip="Second EMA smoothing (double smooth)")
|
||||
i_sigPeriod = input.int(9, "Signal Period", minval=1, maxval=500, tooltip="SMA signal line period")
|
||||
|
||||
// Calculation
|
||||
dosc_value = dosc(i_source, i_rsiPeriod, i_ema1, i_ema2, i_sigPeriod)
|
||||
|
||||
// Plot
|
||||
plot(dosc_value, "DOSC", color=color.yellow, linewidth=2)
|
||||
hline(0, "Zero", color=color.gray, linestyle=hline.style_dotted)
|
||||
Reference in New Issue
Block a user