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:
Miha Kralj
2025-12-31 23:39:47 -08:00
parent 11f4ec2497
commit d493bfd42f
175 changed files with 11977 additions and 897 deletions
+125
View File
@@ -0,0 +1,125 @@
# HT_PHASOR: Hilbert Transform - Phasor Components
[Pine Script Implementation of HT_PHASOR](https://github.com/mihakralj/pinescript/blob/main/indicators/cycles/ht_phasor.pine)
## Overview and Purpose
The Hilbert Transform Phasor Components (HT_PHASOR) is an advanced cycle analysis indicator developed by John Ehlers that provides direct access to the In-phase (I) and Quadrature (Q) components of the dominant market cycle. Unlike HT_DCPHASE which derives the phase angle from these components, HT_PHASOR exposes the raw I and Q values themselves, allowing traders and analysts to construct custom cycle indicators or perform advanced signal processing techniques.
The phasor components represent the cycle in two-dimensional phase space, where the I component is the detrended price delayed by a quarter cycle, and the Q component is a 90-degree phase-shifted version of the detrended price. Together, these components form a complex phasor that rotates through phase space as the market cycles, with the magnitude representing cycle amplitude and the angle representing phase position. This dual representation is invaluable for understanding both the strength and position of market cycles.
## Core Concepts
* **In-Phase Component (I)**: The detrended price delayed by quarter cycle; represents the "real" part of the cycle phasor
* **Quadrature Component (Q)**: 90-degree phase-shifted detrended price; represents the "imaginary" part of the cycle phasor
* **Phasor Representation**: I and Q together form a rotating vector in 2D phase space tracking cycle evolution
* **Complex Analysis**: Enables computation of amplitude (√(I²+Q²)), phase (atan2(Q,I)), and frequency
* **Adaptive Processing**: Uses dominant cycle period to adjust bandwidth for optimal component extraction
## Common Settings and Parameters
| Parameter | Default | Function | When to Adjust |
| ------ | ------ | ------ | ------ |
| Source | hlc3 | Price data for analysis | Use close for simpler signals; hlc3 for smoother, more comprehensive cycle detection |
**Pro Tip:** HT_PHASOR is primarily useful for custom indicator development and advanced cycle analysis. The I and Q components can be used to calculate amplitude (cycle strength), phase (cycle position), and instantaneous frequency. When I and Q oscillate with constant magnitude, the market is in a strong cyclical mode. When their magnitudes vary significantly, the market may be transitioning between cycle and trend modes.
## Calculation and Mathematical Foundation
**Simplified explanation:**
HT_PHASOR applies Hilbert Transform mathematics to extract the In-phase and Quadrature components, which represent the dominant cycle as a rotating vector in 2D phase space.
**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 component (90° phase shift):
```
Q1 = Hilbert_FIR(Detrender) × Bandwidth
```
4. Calculate In-phase component (delayed detrend):
```
I1 = Detrender[3]
```
5. Apply Hilbert Transform to get jI and jQ:
```
jI = Hilbert_FIR(I1) × Bandwidth
jQ = Hilbert_FIR(Q1) × Bandwidth
```
6. Compute smoothed I2 and Q2:
```
I2 = I1 - jQ
Q2 = Q1 + jI
I2 = 0.2×I2 + 0.8×I2[1] (smooth)
Q2 = 0.2×Q2 + 0.8×Q2[1] (smooth)
```
7. Return both components:
```
return [I2, Q2]
```
Where `Hilbert_FIR` is a finite impulse response filter with coefficients [0.0962, 0.5769, 0, -0.5769, -0.0962].
> 🔍 **Technical Note:** The I and Q components form a complex number representation of the cycle. The dominant cycle period is calculated internally and used to adapt the bandwidth, but the phasor components themselves are the primary output. These can be used to derive amplitude (magnitude = √(I²+Q²)), phase (angle = atan2(Q,I)), and rate of change of phase (instantaneous frequency).
## Interpretation Details
HT_PHASOR provides direct access to cycle components for advanced analysis:
* **Component Oscillation:**
* Both I and Q oscillate around zero
* Amplitude of oscillation indicates cycle strength
* Regular sinusoidal patterns indicate clean cycles
* Irregular patterns suggest trending or transitional periods
* **Phasor Magnitude (√(I²+Q²)):**
* Large magnitude: Strong cyclical behavior
* Small magnitude: Weak cycle or trending phase
* Constant magnitude: Pure cycle mode
* Varying magnitude: Mixed cycle/trend mode
* **Phase Angle (atan2(Q,I)):**
* Derived phase ranges from -π to π
* Constant rotation rate indicates steady cycle
* Accelerating rotation suggests cycle compression
* Decelerating rotation suggests cycle expansion
* **Component Relationships:**
* I and Q approximately 90° out of phase in clean cycles
* Loss of quadrature relationship indicates trend dominance
* Relative magnitudes reveal cycle shape distortions
* Sign changes indicate cycle progression through quadrants
* **Custom Indicator Construction:**
* Amplitude: `sqrt(I² + Q²)` for cycle strength
* Phase: `atan2(Q, I)` for cycle position
* Frequency: Rate of change of phase angle
* Power: `I² + Q²` for energy without sqrt overhead
## Limitations and Considerations
* **Raw Components:** Less intuitive than derived metrics (phase, amplitude); requires understanding of complex analysis
* **Trend Dependence:** Component values less meaningful in strong trending markets
* **Computation Required:** User must compute derived metrics (amplitude, phase) from I and Q components
* **Noise Sensitivity:** Can show erratic behavior in choppy markets without clear cycles
* **Cycle Assumption:** Assumes dominant cycle exists; questionable in random walk conditions
* **Advanced Tool:** Primarily for custom indicator development and algorithmic trading applications
## 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.
+78
View File
@@ -0,0 +1,78 @@
// The MIT License (MIT)
// © mihakralj
//@version=6
indicator("HT_PHASOR: Hilbert Transform Phasor Components", "HT_PHASOR", 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 Phasor Components (InPhase and Quadrature)
//@doc https://github.com/mihakralj/pinescript/blob/main/indicators/cycles/ht_phasor.md
//@param source Series to analyze for phasor components
//@returns Tuple [inphase, quadrature] components
ht_phasor(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
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
[i2, q2]
// ---------- Main loop ----------
// Inputs
i_source = input.source(hlc3, "Source")
// Calculation
[inphase, quadrature] = ht_phasor(i_source)
// Plot
plot(inphase, "InPhase", color=color.yellow, linewidth=2)
plot(quadrature, "Quadrature", color=color.blue, linewidth=2)
hline(0, "Zero", color=color.gray, linestyle=hline.style_solid)