mirror of
https://github.com/mihakralj/QuanTAlib.git
synced 2026-08-02 11:37:42 +00:00
24e86d762a
- Updated BBWN, BBWP, CCV, CV, CVI, EWMA, GKV, HLV, HV, Jvolty, JVOLTYN, MASSI, NATR, RSV, RV, RVI, TR, UI, VOV, VR, YZV indicators with documentation links. - Added documentation links for Aberration, Acceleration Bands, Andrews' Pitchfork, Adaptive Price Zone, ATR Bands, Bollinger Bands, Center of Gravity, Donchian Channels, Decay Min-Max Channel, Detrended Synthetic Price, EACP, EBSW, HOMOD, Jurik Volatility Bands, Keltner Channel, MA Envelope, Min-Max Channel, Price Channel, Regression Channels, Standard Deviation Channel, Stoller Average Range Channel, Super Trend Bands, Ultimate Bands, Ultimate Channel, VWAP Bands, and VWAP with Standard Deviation Bands.
82 lines
3.0 KiB
Plaintext
82 lines
3.0 KiB
Plaintext
// The MIT License (MIT)
|
|
// © mihakralj
|
|
//@version=6
|
|
indicator("HT_DCPHASE: Hilbert Transform Dominant Cycle Phase", "HT_DCPHASE", overlay=false)
|
|
|
|
//@function Numerically stable atan2 implementation for quadrant-aware angle calculation
|
|
//@param y Y-coordinate (imaginary/quadrature component)
|
|
//@param x X-coordinate (real/in-phase component)
|
|
//@returns Angle in radians from -π to π
|
|
atan2(series float y, series float x) =>
|
|
if y == 0.0 and x == 0.0
|
|
runtime.error("atan2: Both y and x cannot be zero")
|
|
ay = math.abs(y)
|
|
ax = math.abs(x)
|
|
angle = 0.0
|
|
if ax > ay
|
|
angle := math.atan(ay / ax)
|
|
else
|
|
angle := (math.pi / 2.0) - math.atan(ax / ay)
|
|
if x < 0.0
|
|
angle := math.pi - angle
|
|
if y < 0.0
|
|
angle := -angle
|
|
angle
|
|
|
|
//@function Calculates Hilbert Transform Dominant Cycle Phase using Ehlers algorithm
|
|
//@param source Series to analyze for dominant cycle phase
|
|
//@returns Phase angle in radians (-π to π)
|
|
ht_dcphase(series float source) =>
|
|
var float smooth_price = 0.0
|
|
var float detrender = 0.0
|
|
var float i1 = 0.0
|
|
var float q1 = 0.0
|
|
var float ji = 0.0
|
|
var float jq = 0.0
|
|
var float i2 = 0.0
|
|
var float q2 = 0.0
|
|
var float re = 0.0
|
|
var float im = 0.0
|
|
var float period = 15.0
|
|
var float smooth_period = 15.0
|
|
var float phase = 0.0
|
|
float price = nz(source)
|
|
float bandwidth = 0.075 * smooth_period + 0.54
|
|
smooth_price := (4.0 * price + 3.0 * nz(price[1]) + 2.0 * nz(price[2]) + nz(price[3])) / 10.0
|
|
detrender := (0.0962 * smooth_price + 0.5769 * nz(smooth_price[2]) - 0.5769 * nz(smooth_price[4]) - 0.0962 * nz(smooth_price[6])) * bandwidth
|
|
q1 := (0.0962 * detrender + 0.5769 * nz(detrender[2]) - 0.5769 * nz(detrender[4]) - 0.0962 * nz(detrender[6])) * bandwidth
|
|
i1 := nz(detrender[3])
|
|
ji := (0.0962 * i1 + 0.5769 * nz(i1[2]) - 0.5769 * nz(i1[4]) - 0.0962 * nz(i1[6])) * bandwidth
|
|
jq := (0.0962 * q1 + 0.5769 * nz(q1[2]) - 0.5769 * nz(q1[4]) - 0.0962 * nz(q1[6])) * bandwidth
|
|
i2 := i1 - jq
|
|
q2 := q1 + ji
|
|
i2 := 0.2 * i2 + 0.8 * nz(i2[1])
|
|
q2 := 0.2 * q2 + 0.8 * nz(q2[1])
|
|
re := i2 * nz(i2[1]) + q2 * nz(q2[1])
|
|
im := i2 * nz(q2[1]) - q2 * nz(i2[1])
|
|
re := 0.2 * re + 0.8 * nz(re[1])
|
|
im := 0.2 * im + 0.8 * nz(im[1])
|
|
if im != 0.0 or re != 0.0
|
|
float angle = atan2(im, re)
|
|
if angle != 0.0
|
|
period := 2.0 * math.pi / angle
|
|
period := math.max(6.0, math.min(50.0, period))
|
|
smooth_period := 0.33 * period + 0.67 * smooth_period
|
|
if i2 != 0.0 or q2 != 0.0
|
|
phase := atan2(q2, i2)
|
|
phase
|
|
|
|
// ---------- Main loop ----------
|
|
|
|
// Inputs
|
|
i_source = input.source(hlc3, "Source")
|
|
|
|
// Calculation
|
|
dcphase = ht_dcphase(i_source)
|
|
|
|
// Plot
|
|
plot(dcphase, "Dominant Cycle Phase", color=color.yellow, linewidth=2)
|
|
hline(0, "Zero Phase", color=color.gray, linestyle=hline.style_solid)
|
|
hline(1.5708, "π/2", color=color.new(color.gray, 70), linestyle=hline.style_dashed)
|
|
hline(-1.5708, "-π/2", color=color.new(color.gray, 70), linestyle=hline.style_dashed)
|