mirror of
https://github.com/mihakralj/QuanTAlib.git
synced 2026-08-25 05:48:06 +00:00
Refactor documentation for various filters and indicators to enhance clarity and consistency
- Updated Bessel, Bilateral, Blma, Butter, Conv, Ema, Kama, LSMA, MAMA, MGDI, SSF, USF, ATR, ADL, and ADOSC documentation to use bullet points for key concepts and features. - Added a new Qodana configuration file for code analysis. - Removed coverage configuration from Quantower.Tests.csproj to streamline testing setup.
This commit is contained in:
@@ -0,0 +1,138 @@
|
||||
# HT_SINE: Hilbert Transform - SineWave
|
||||
|
||||
[Pine Script Implementation of HT_SINE](https://github.com/mihakralj/pinescript/blob/main/indicators/cycles/ht_sine.pine)
|
||||
|
||||
## Overview and Purpose
|
||||
|
||||
The Hilbert Transform SineWave (HT_SINE) is a cycle visualization indicator developed by John Ehlers that generates sine and lead-sine wave plots based on the dominant market cycle identified through Hilbert Transform analysis. Unlike simple sine wave indicators that assume a fixed cycle period, HT_SINE adapts to the actual dominant cycle present in the market, providing a dynamic representation of cyclical behavior. The lead-sine component leads the sine wave, offering early signals of potential cycle turning points.
|
||||
|
||||
This indicator transforms the complex phase information from Hilbert Transform analysis into intuitive sine wave visualizations that oscillate between -1 and +1. By plotting both the sine wave (current cycle position) and lead-sine wave (advanced cycle position), traders can identify cycle peaks, troughs, and transitions. Crossovers between the sine and lead-sine waves often coincide with significant price turning points, making this a valuable tool for timing entries and exits in cyclical markets.
|
||||
|
||||
## Core Concepts
|
||||
|
||||
* **Sine Wave**: Visual representation of the dominant cycle position; oscillates smoothly between -1 and +1
|
||||
* **Lead Sine Wave**: Phase-advanced version of sine wave; leads by delta_phase/period for early signals
|
||||
* **Dynamic Phase**: Uses instantaneous phase from Hilbert Transform rather than fixed cycle assumption
|
||||
* **Adaptive Cycle**: Automatically adjusts to dominant cycle period detected in price data
|
||||
* **Crossover Signals**: Sine/LeadSine crossovers indicate potential cycle turning points
|
||||
|
||||
## Common Settings and Parameters
|
||||
|
||||
| Parameter | Default | Function | When to Adjust |
|
||||
| ------ | ------ | ------ | ------ |
|
||||
| Source | hlc3 | Price data for cycle analysis | Use close for simpler signals; hlc3 for smoother, more comprehensive cycle detection |
|
||||
|
||||
**Pro Tip:** Watch for crossovers between the sine and lead-sine waves as potential cycle reversal signals. When lead-sine crosses above sine near the trough (-1), it suggests an upcoming cycle bottom. When lead-sine crosses below sine near the peak (+1), it suggests an upcoming cycle top. The indicator works best in ranging or cyclical markets; strong trends can produce less reliable signals as the cycle assumption breaks down.
|
||||
|
||||
## Calculation and Mathematical Foundation
|
||||
|
||||
**Simplified explanation:**
|
||||
HT_SINE uses Hilbert Transform to determine the dominant cycle's phase, then generates sine and lead-sine waves based on that phase for visual cycle representation.
|
||||
|
||||
**Technical formula:**
|
||||
|
||||
1. Smooth the price data:
|
||||
```
|
||||
SmoothPrice = (4×Price + 3×Price[1] + 2×Price[2] + Price[3]) / 10
|
||||
```
|
||||
|
||||
2. Detrend with adaptive bandwidth:
|
||||
```
|
||||
Bandwidth = 0.075 × Period[1] + 0.54
|
||||
Detrender = Hilbert_FIR(SmoothPrice) × Bandwidth
|
||||
```
|
||||
|
||||
3. Calculate Quadrature and In-phase components:
|
||||
```
|
||||
Q1 = Hilbert_FIR(Detrender) × Bandwidth
|
||||
I1 = Detrender[3]
|
||||
```
|
||||
|
||||
4. Apply Hilbert Transform:
|
||||
```
|
||||
jI = Hilbert_FIR(I1) × Bandwidth
|
||||
jQ = Hilbert_FIR(Q1) × Bandwidth
|
||||
```
|
||||
|
||||
5. Compute smoothed I2 and Q2:
|
||||
```
|
||||
I2 = I1 - jQ
|
||||
Q2 = Q1 + jI
|
||||
I2 = 0.2×I2 + 0.8×I2[1]
|
||||
Q2 = 0.2×Q2 + 0.8×Q2[1]
|
||||
```
|
||||
|
||||
6. Calculate phase using four-quadrant arctangent:
|
||||
```
|
||||
if I2 > 0:
|
||||
Phase = atan(Q2 / I2)
|
||||
else if I2 < 0:
|
||||
Phase = atan(Q2 / I2) ± π
|
||||
else:
|
||||
Phase = ±π/2
|
||||
```
|
||||
|
||||
7. Compute phase change and alpha:
|
||||
```
|
||||
DeltaPhase = max(Phase[1] - Phase, 1.0)
|
||||
Alpha = DeltaPhase / Period
|
||||
```
|
||||
|
||||
8. Generate sine waves:
|
||||
```
|
||||
Sine = sin(Phase)
|
||||
LeadSine = sin(Phase + Alpha)
|
||||
```
|
||||
|
||||
Where `Hilbert_FIR` is a finite impulse response filter with coefficients [0.0962, 0.5769, 0, -0.5769, -0.0962].
|
||||
|
||||
> 🔍 **Technical Note:** The lead-sine component is phase-advanced by alpha (DeltaPhase/Period), causing it to lead the sine wave. The minimum DeltaPhase constraint of 1.0 prevents division issues when phase changes slowly. The sine waves are bounded between -1 and +1, providing normalized cycle visualization regardless of price magnitude.
|
||||
|
||||
## Interpretation Details
|
||||
|
||||
HT_SINE provides cycle visualization and timing signals through multiple perspectives:
|
||||
|
||||
* **Wave Position:**
|
||||
* Sine ≈ +1: Cycle peak (potential sell zone)
|
||||
* Sine ≈ 0: Mid-cycle (transition zone)
|
||||
* Sine ≈ -1: Cycle trough (potential buy zone)
|
||||
* Regular oscillation indicates clean cyclical behavior
|
||||
|
||||
* **Crossover Signals:**
|
||||
* LeadSine crosses above Sine: Potential bullish reversal signal
|
||||
* LeadSine crosses below Sine: Potential bearish reversal signal
|
||||
* Crossovers near extremes (+1 or -1) are most reliable
|
||||
* Multiple rapid crossovers suggest choppy, non-cyclical conditions
|
||||
|
||||
* **Wave Separation:**
|
||||
* Wide separation: Strong, clear cycle in progress
|
||||
* Narrow separation: Weak or transitioning cycle
|
||||
* Consistent spacing: Steady cycle frequency
|
||||
* Erratic spacing: Cycle instability or trend dominance
|
||||
|
||||
* **Extreme Levels:**
|
||||
* Both waves at +1: Confirmed cycle peak
|
||||
* Both waves at -1: Confirmed cycle trough
|
||||
* Failure to reach extremes: Weakening cycle or trend emergence
|
||||
* Extended time at extremes: Possible trend rather than cycle
|
||||
|
||||
* **Lead-Lag Relationship:**
|
||||
* Lead-sine consistently ahead: Normal cycle mode
|
||||
* Lead-sine loses leadership: Cycle breaking down
|
||||
* Waves synchronizing: Transitioning to trend mode
|
||||
* Lead reversing direction first: Early warning signal
|
||||
|
||||
## Limitations and Considerations
|
||||
|
||||
* **Cycle Assumption:** Assumes market is in cyclical mode; less reliable during strong trends
|
||||
* **Lag Component:** Despite "lead-sine," overall indicator lags actual price action due to Hilbert Transform smoothing
|
||||
* **False Signals:** Can generate whipsaws in choppy, non-cyclical markets
|
||||
* **Trend Weakness:** Strong directional moves violate cycle assumptions, producing unreliable waves
|
||||
* **Period Dependency:** Relies on accurate dominant cycle detection; errors in period affect wave quality
|
||||
* **Visual Tool:** Best used as confirmation with other indicators rather than standalone timing tool
|
||||
|
||||
## References
|
||||
|
||||
* Ehlers, J. F. (2004). "Cybernetic Analysis for Stocks and Futures." John Wiley & Sons.
|
||||
* Ehlers, J. F. (2001). "Rocket Science for Traders: Digital Signal Processing Applications." John Wiley & Sons.
|
||||
* Ehlers, J. F. (2013). "Cycle Analytics for Traders: Advanced Technical Trading Concepts." John Wiley & Sons.
|
||||
@@ -0,0 +1,85 @@
|
||||
// The MIT License (MIT)
|
||||
// © mihakralj
|
||||
//@version=6
|
||||
indicator("HT_SINE: Hilbert Transform - SineWave", "HT_SINE", 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 SineWave and LeadSine
|
||||
//@doc https://github.com/mihakralj/pinescript/blob/main/indicators/cycles/ht_sine.md
|
||||
//@param source Series to analyze for dominant cycle
|
||||
//@returns Tuple [sine, leadsine] - sine wave and lead sine wave
|
||||
ht_sine(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
|
||||
var float sine = 0.0
|
||||
var float leadsine = 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)
|
||||
sine := math.sin(phase)
|
||||
leadsine := math.sin(phase + math.pi / 4.0)
|
||||
[sine, leadsine]
|
||||
|
||||
// ---------- Main loop ----------
|
||||
|
||||
// Inputs
|
||||
i_source = input.source(hlc3, "Source")
|
||||
|
||||
// Calculation
|
||||
[sine, leadsine] = ht_sine(i_source)
|
||||
|
||||
// Plot
|
||||
plot(sine, "Sine", color=color.yellow, linewidth=2)
|
||||
plot(leadsine, "LeadSine", color=color.blue, linewidth=2)
|
||||
hline(0, "Zero", color=color.gray, linestyle=hline.style_solid)
|
||||
Reference in New Issue
Block a user