Files
QuanTAlib/lib/cycles/dsp/dsp.pine
T

51 lines
1.9 KiB
Plaintext

// Licensed under the Apache License, Version 2.0
// © mihakralj
//@version=6
indicator("Ehlers Detrended Synthetic Price (DSP)", "DSP", overlay=false)
//@function Calculates Detrended Synthetic Price using Ehlers dual-EMA algorithm
//@param source Series to detrend
//@param period Dominant cycle period for quarter/half-cycle EMA calculation
//@returns Detrended synthetic price (difference between quarter-cycle and half-cycle EMAs)
dsp(series float source, simple int period) =>
if period <= 0
runtime.error("Period must be greater than 0")
int fast_period = math.max(2, int(math.round(period / 4.0)))
int slow_period = math.max(3, int(math.round(period / 2.0)))
float alpha_fast = 2.0 / (fast_period + 1)
float alpha_slow = 2.0 / (slow_period + 1)
var float ema_fast_raw = 0.0
var float ema_slow_raw = 0.0
float current = nz(source)
ema_fast_raw += alpha_fast * (current - ema_fast_raw)
ema_slow_raw += alpha_slow * (current - ema_slow_raw)
var bool warmup = true
var float e_fast = 1.0
var float e_slow = 1.0
float ema_fast = ema_fast_raw
float ema_slow = ema_slow_raw
if warmup
e_fast *= (1.0 - alpha_fast)
e_slow *= (1.0 - alpha_slow)
float c_fast = 1.0 / (1.0 - e_fast)
float c_slow = 1.0 / (1.0 - e_slow)
ema_fast := c_fast * ema_fast_raw
ema_slow := c_slow * ema_slow_raw
warmup := e_fast > 1e-10 or e_slow > 1e-10
// Return difference (detrended synthetic price)
ema_fast - ema_slow
// ---------- Main loop ----------
// Inputs
i_source = input.source(hlc3, "Source")
i_period = input.int(40, "Dominant Cycle Period", minval=4, maxval=200, tooltip="Dominant cycle period. Quarter-cycle and half-cycle EMAs calculated from this value.")
// Calculation
dsp_val = dsp(i_source, i_period)
// Plot
plot(dsp_val, "DSP", color=color.yellow, linewidth=2)
hline(0, "Zero Line", color=color.gray, linestyle=hline.style_solid)