mirror of
https://github.com/mihakralj/QuanTAlib.git
synced 2026-08-20 03:28:05 +00:00
Remove multiple Pine Script indicators: SSFDSP, STARCHANNEL, STBANDS, STC, UBANDS, UCHANNEL, VWAPBANDS, and VWAPSD. These indicators were deleted to streamline the library and remove unused or redundant code.
This commit is contained in:
@@ -3,31 +3,10 @@
|
||||
//@version=6
|
||||
indicator("Ehlers Hilbert Transform Dominant Cycle Phase (HT_DCPHASE)", "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
|
||||
//@function Calculates Hilbert Transform Dominant Cycle Phase using TA-Lib algorithm
|
||||
//@param source Series to analyze for dominant cycle phase
|
||||
//@returns Phase angle in radians (-π to π)
|
||||
//@returns Phase angle in degrees
|
||||
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
|
||||
@@ -37,34 +16,91 @@ ht_dcphase(series float source) =>
|
||||
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
|
||||
var float period = 0.0
|
||||
var float smooth_period = 0.0
|
||||
var float dc_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
|
||||
|
||||
// Step 1: WMA smoothing (4-tap: [4,3,2,1]/10)
|
||||
float smooth_price = (4.0 * price + 3.0 * nz(price[1]) + 2.0 * nz(price[2]) + nz(price[3])) / 10.0
|
||||
|
||||
// Bandwidth uses period (not smooth_period) per TA-Lib
|
||||
float bandwidth = 0.075 * period + 0.54
|
||||
|
||||
// Step 2: Hilbert FIR detrender
|
||||
detrender := (0.0962 * smooth_price + 0.5769 * nz(smooth_price[2]) - 0.5769 * nz(smooth_price[4]) - 0.0962 * nz(smooth_price[6])) * bandwidth
|
||||
|
||||
// Step 3: Q1 computation (Hilbert FIR on detrender)
|
||||
q1 := (0.0962 * detrender + 0.5769 * nz(detrender[2]) - 0.5769 * nz(detrender[4]) - 0.0962 * nz(detrender[6])) * bandwidth
|
||||
|
||||
// Step 4: I1 = detrender delayed 3 bars
|
||||
i1 := nz(detrender[3])
|
||||
|
||||
// Step 5: Advance phase via JI/JQ
|
||||
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
|
||||
|
||||
// Step 6: Smooth I2/Q2 with 2-bar EMA
|
||||
i2 := 0.2 * (i1 - jq) + 0.8 * nz(i2[1])
|
||||
q2 := 0.2 * (q1 + ji) + 0.8 * nz(q2[1])
|
||||
|
||||
// Step 7: Homodyne discriminator
|
||||
re := 0.2 * (i2 * nz(i2[1]) + q2 * nz(q2[1])) + 0.8 * nz(re[1])
|
||||
im := 0.2 * (i2 * nz(q2[1]) - q2 * nz(i2[1])) + 0.8 * nz(im[1])
|
||||
|
||||
// Step 8: Period from atan (NOT atan2) + rate limiting + clamping
|
||||
float prev_period = period
|
||||
if math.abs(im) > 1e-12 and math.abs(re) > 1e-12
|
||||
float angle = math.atan(im / re)
|
||||
if math.abs(angle) > 1e-12
|
||||
period := 360.0 / (angle * (180.0 / math.pi))
|
||||
|
||||
// Rate limit: ±50% bar-to-bar
|
||||
if prev_period > 0
|
||||
period := math.min(period, 1.5 * prev_period)
|
||||
period := math.max(period, 0.67 * prev_period)
|
||||
|
||||
// Clamp to valid range
|
||||
period := math.max(6.0, math.min(50.0, period))
|
||||
|
||||
// Step 9: Smooth period with 0.2/0.8 EMA
|
||||
period := 0.2 * period + 0.8 * prev_period
|
||||
|
||||
// Step 10: Smooth smoothPeriod with 0.33/0.67 EMA
|
||||
smooth_period := 0.33 * period + 0.67 * smooth_period
|
||||
if i2 != 0.0 or q2 != 0.0
|
||||
phase := atan2(q2, i2)
|
||||
phase
|
||||
|
||||
// Step 11: DFT-based DC Phase extraction
|
||||
int dc_period_int = int(smooth_period + 0.5)
|
||||
float real_part = 0.0
|
||||
float imag_part = 0.0
|
||||
for i = 0 to dc_period_int - 1
|
||||
float temp_angle = i * 2.0 * math.pi / dc_period_int
|
||||
float sp_val = nz(smooth_price[i])
|
||||
real_part += math.sin(temp_angle) * sp_val
|
||||
imag_part += math.cos(temp_angle) * sp_val
|
||||
|
||||
// Phase from DFT components
|
||||
float abs_imag = math.abs(imag_part)
|
||||
if abs_imag > 0.0
|
||||
dc_phase := math.atan(real_part / imag_part) * (180.0 / math.pi)
|
||||
else if abs_imag <= 0.01
|
||||
if real_part < 0.0
|
||||
dc_phase -= 90.0
|
||||
else if real_part > 0.0
|
||||
dc_phase += 90.0
|
||||
|
||||
// Phase adjustments per TA-Lib
|
||||
dc_phase += 90.0
|
||||
dc_phase += 360.0 / smooth_period
|
||||
|
||||
if imag_part < 0.0
|
||||
dc_phase += 180.0
|
||||
|
||||
if dc_phase > 315.0
|
||||
dc_phase -= 360.0
|
||||
|
||||
dc_phase
|
||||
|
||||
// ---------- Main loop ----------
|
||||
|
||||
@@ -77,5 +113,5 @@ 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)
|
||||
hline(180, "180°", color=color.new(color.gray, 70), linestyle=hline.style_dashed)
|
||||
hline(-180, "-180°", color=color.new(color.gray, 70), linestyle=hline.style_dashed)
|
||||
|
||||
Reference in New Issue
Block a user