mirror of
https://github.com/mihakralj/QuanTAlib.git
synced 2026-08-14 00:28:05 +00:00
feat(dynamics): add PlusDI, MinusDI, PlusDM, MinusDM indicators
Complete thin Dx-composition wrapper indicators with full test coverage: - PlusDi/MinusDi: Directional Indicator wrappers (DiPlus/DiMinus from Dx) - PlusDm/MinusDm: Directional Movement wrappers (DmPlus/DmMinus from Dx) - Individual validation tests per indicator directory (TALib, Skender, bounds) - Combined unit tests (DiDm.Tests.cs) and validation tests (DiDm.Validation.Tests.cs) - Quantower wrappers + tests for all 4 indicators - PineScript v6 implementations with compensated RMA - Normalized .md documentation for all indicators and categories - 182 tests passing, 0 failures
This commit is contained in:
@@ -1,7 +1,5 @@
|
||||
# Cycles
|
||||
|
||||
> "The market is a discounting mechanism that anticipates cycles before they complete." Unknown
|
||||
|
||||
Cycle analysis identifies repeating patterns in price data. John Ehlers pioneered digital signal processing techniques for financial cycles, using Hilbert transforms and autocorrelation to detect dominant periods. Cycles exist but are non-stationary: period and amplitude shift over time.
|
||||
|
||||
## Indicators
|
||||
|
||||
+2
-42
@@ -1,5 +1,7 @@
|
||||
# CCOR: Ehlers Correlation Cycle
|
||||
|
||||
> *Correlation cycles reveal hidden periodicities by measuring how well price correlates with a rotating reference wave.*
|
||||
|
||||
| Property | Value |
|
||||
| ---------------- | -------------------------------- |
|
||||
| **Category** | Cycle |
|
||||
@@ -94,48 +96,6 @@ Where:
|
||||
- Real: $y_k = \cos(2\pi k / N)$
|
||||
- Imaginary: $y_k = -\sin(2\pi k / N)$
|
||||
|
||||
### Pseudo-code
|
||||
|
||||
```
|
||||
function CCOR(source, period, threshold):
|
||||
// Real correlation
|
||||
Sx_r = Sy_r = Sxx_r = Sxy_r = Syy_r = 0
|
||||
for k = 0 to period-1:
|
||||
x = source[k]
|
||||
y = cos(2π * k / period)
|
||||
Sx_r += x; Sy_r += y
|
||||
Sxx_r += x*x; Sxy_r += x*y; Syy_r += y*y
|
||||
denom_r = (N*Sxx_r - Sx_r²) * (N*Syy_r - Sy_r²)
|
||||
real = denom_r > 0 ? (N*Sxy_r - Sx_r*Sy_r) / √denom_r : 0
|
||||
|
||||
// Imaginary correlation (same accumulators for x, different y)
|
||||
Sx_i = Sy_i = Sxx_i = Sxy_i = Syy_i = 0
|
||||
for k = 0 to period-1:
|
||||
x = source[k]
|
||||
y = -sin(2π * k / period)
|
||||
Sx_i += x; Sy_i += y
|
||||
Sxx_i += x*x; Sxy_i += x*y; Syy_i += y*y
|
||||
denom_i = (N*Sxx_i - Sx_i²) * (N*Syy_i - Sy_i²)
|
||||
imag = denom_i > 0 ? (N*Sxy_i - Sx_i*Sy_i) / √denom_i : 0
|
||||
|
||||
// Phasor angle
|
||||
angle = 0
|
||||
if imag ≠ 0: angle = 90 + atan(real/imag) * (180/π)
|
||||
if imag > 0: angle -= 180
|
||||
|
||||
// Monotonic constraint
|
||||
angle = max(angle, prev_angle)
|
||||
prev_angle = angle
|
||||
|
||||
// State detection
|
||||
Δθ = |angle - saved_prev_angle|
|
||||
state = 0
|
||||
if Δθ < threshold and angle ≥ 0: state = +1
|
||||
if Δθ < threshold and angle ≤ 0: state = -1
|
||||
|
||||
return [real, imag, angle, state]
|
||||
```
|
||||
|
||||
### Output Interpretation
|
||||
|
||||
| Output | Range | Meaning |
|
||||
|
||||
+2
-27
@@ -1,5 +1,7 @@
|
||||
# CCYC: Ehlers Cyber Cycle
|
||||
|
||||
> *The Cyber Cycle isolator extracts the dominant cycle component while suppressing trend — pure periodicity distilled.*
|
||||
|
||||
| Property | Value |
|
||||
| ---------------- | -------------------------------- |
|
||||
| **Category** | Cycle |
|
||||
@@ -109,33 +111,6 @@ $$z^2 - 2(1-\alpha)z + (1-\alpha)^2 = 0$$
|
||||
|
||||
has a double pole at $z = 1 - \alpha$. For $\alpha = 0.07$, the pole is at $z = 0.93$, well inside the unit circle (stable), with a $-3$ dB cutoff period of approximately $\frac{2\pi}{\alpha} \approx 90$ bars.
|
||||
|
||||
### Pseudo-code
|
||||
|
||||
```
|
||||
function CCYC(source, alpha):
|
||||
validate: 0 < alpha < 1
|
||||
|
||||
// FIR smoother
|
||||
smooth = (source[0] + 2*source[1] + 2*source[2] + source[3]) / 6
|
||||
|
||||
// IIR coefficients
|
||||
c_hp = (1 - 0.5*alpha)²
|
||||
c_fb1 = 2*(1 - alpha)
|
||||
c_fb2 = -(1 - alpha)²
|
||||
|
||||
if bar_count < 7:
|
||||
// Bootstrap: second-difference of raw price
|
||||
cycle = (source[0] - 2*source[1] + source[2]) / 4
|
||||
else:
|
||||
// Steady-state: 2-pole high-pass on smoothed input
|
||||
cycle = c_hp * (smooth - 2*smooth[1] + smooth[2])
|
||||
+ c_fb1 * cycle[1] + c_fb2 * cycle[2]
|
||||
|
||||
trigger = cycle[1]
|
||||
|
||||
return [cycle, trigger]
|
||||
```
|
||||
|
||||
### Output Interpretation
|
||||
|
||||
| Output | Description |
|
||||
|
||||
+2
-25
@@ -1,5 +1,7 @@
|
||||
# CG: Ehlers Center of Gravity
|
||||
|
||||
> *Center of Gravity locates the balance point of price over a window, anticipating turns before they arrive.*
|
||||
|
||||
| Property | Value |
|
||||
| ---------------- | -------------------------------- |
|
||||
| **Category** | Cycle |
|
||||
@@ -54,31 +56,6 @@ Streaming uses running sums for both numerator and denominator: $O(1)$ per bar w
|
||||
|-----------|-------------|---------|------------|
|
||||
| `period` | Lookback window length | 10 | $> 0$ |
|
||||
|
||||
### Pseudo-code
|
||||
|
||||
```
|
||||
function CG(source, period):
|
||||
buffer ← RingBuffer(period)
|
||||
runNum ← 0 // weighted sum
|
||||
runDen ← 0 // simple sum
|
||||
|
||||
for each price in source:
|
||||
buffer.Add(price)
|
||||
if buffer.Count < period: continue
|
||||
|
||||
// Compute from buffer (or maintain running sums)
|
||||
num = 0
|
||||
den = 0
|
||||
for i = 0 to period-1:
|
||||
w = i + 1
|
||||
num += w * buffer[i]
|
||||
den += buffer[i]
|
||||
|
||||
cg = (den ≠ 0) ? (num / den) - (period + 1) / 2.0 : 0
|
||||
|
||||
emit cg
|
||||
```
|
||||
|
||||
### Output Interpretation
|
||||
|
||||
| Condition | Meaning |
|
||||
|
||||
+2
-28
@@ -1,5 +1,7 @@
|
||||
# DSP: Ehlers Detrended Synthetic Price
|
||||
|
||||
> *Detrended synthetic price removes the trend to expose the oscillation underneath — the signal beneath the drift.*
|
||||
|
||||
| Property | Value |
|
||||
| ---------------- | -------------------------------- |
|
||||
| **Category** | Cycle |
|
||||
@@ -66,34 +68,6 @@ $O(1)$ per bar with $O(1)$ memory. Two EMA state variables plus two bias correct
|
||||
|-----------|-------------|---------|------------|
|
||||
| `period` | Dominant cycle period | 40 | $\geq 4$ |
|
||||
|
||||
### Pseudo-code
|
||||
|
||||
```
|
||||
function DSP(source, period):
|
||||
pFast ← max(2, round(period / 4))
|
||||
pSlow ← max(3, round(period / 2))
|
||||
αFast ← 2 / (pFast + 1)
|
||||
αSlow ← 2 / (pSlow + 1)
|
||||
|
||||
emaFastRaw ← 0
|
||||
emaSlowRaw ← 0
|
||||
decayFast ← 1.0 // (1 - αFast)^n
|
||||
decaySlow ← 1.0 // (1 - αSlow)^n
|
||||
|
||||
for each price in source:
|
||||
emaFastRaw ← FMA(αFast, price, (1 - αFast) * emaFastRaw)
|
||||
emaSlowRaw ← FMA(αSlow, price, (1 - αSlow) * emaSlowRaw)
|
||||
|
||||
decayFast *= (1 - αFast)
|
||||
decaySlow *= (1 - αSlow)
|
||||
|
||||
emaFast ← emaFastRaw / (1 - decayFast)
|
||||
emaSlow ← emaSlowRaw / (1 - decaySlow)
|
||||
|
||||
dsp ← emaFast - emaSlow
|
||||
emit dsp
|
||||
```
|
||||
|
||||
### Output Interpretation
|
||||
|
||||
| Condition | Meaning |
|
||||
|
||||
+2
-45
@@ -1,5 +1,7 @@
|
||||
# EACP: Ehlers Autocorrelation Periodogram
|
||||
|
||||
> *Autocorrelation periodogram scans every possible cycle length and ranks them by strength — a spectral fingerprint of the market.*
|
||||
|
||||
| Property | Value |
|
||||
| ---------------- | -------------------------------- |
|
||||
| **Category** | Cycle |
|
||||
@@ -72,51 +74,6 @@ $O(N \times M)$ per bar where $N$ is the period range and $M$ is the averaging l
|
||||
| `maxPeriod` | Maximum period to evaluate | 48 | $> minPeriod$ |
|
||||
| `enhance` | Apply cubic emphasis to spectral peaks | true | |
|
||||
|
||||
### Pseudo-code
|
||||
|
||||
```
|
||||
function EACP(source, minPeriod, maxPeriod, enhance):
|
||||
N ← maxPeriod - minPeriod + 1
|
||||
M ← maxPeriod // averaging window
|
||||
hpBuf ← HighPassFilter(source)
|
||||
ssfBuf ← SuperSmoother(hpBuf)
|
||||
|
||||
power[N] ← {0}
|
||||
smoothPower[N] ← {0}
|
||||
|
||||
for each bar:
|
||||
// Autocorrelation for each lag
|
||||
corr[0..maxPeriod] ← PearsonAutocorrelation(ssfBuf, M)
|
||||
|
||||
// DFT: convert autocorrelation to power spectrum
|
||||
for p = minPeriod to maxPeriod:
|
||||
cosPower ← 0
|
||||
for k = 0 to M-1:
|
||||
cosPower += corr[k] * cos(2π * k / p)
|
||||
power[p] ← cosPower²
|
||||
|
||||
// Exponential smoothing of spectrum
|
||||
for p = minPeriod to maxPeriod:
|
||||
smoothPower[p] ← 0.2 * power[p] + 0.8 * smoothPower[p]
|
||||
|
||||
// Optional cubic enhancement
|
||||
if enhance:
|
||||
for p: smoothPower[p] ← smoothPower[p]³
|
||||
|
||||
// AGC normalization
|
||||
maxPow ← max(smoothPower)
|
||||
for p: smoothPower[p] /= maxPow // normalize to [0, 1]
|
||||
|
||||
// Center-of-gravity dominant cycle
|
||||
num ← 0; den ← 0
|
||||
for p = minPeriod to maxPeriod:
|
||||
num += smoothPower[p] * p
|
||||
den += smoothPower[p]
|
||||
dominantCycle ← (den > 0) ? num / den : (minPeriod + maxPeriod) / 2
|
||||
|
||||
emit dominantCycle
|
||||
```
|
||||
|
||||
### Output Interpretation
|
||||
|
||||
| Output | Meaning |
|
||||
|
||||
+2
-39
@@ -1,5 +1,7 @@
|
||||
# EBSW: Ehlers Even Better Sinewave
|
||||
|
||||
> *Even Better Sinewave refines cycle detection by combining bandpass filtering with adaptive gain normalization.*
|
||||
|
||||
| Property | Value |
|
||||
| ---------------- | -------------------------------- |
|
||||
| **Category** | Cycle |
|
||||
@@ -78,45 +80,6 @@ b = 2·a·cos(√2·π / ssfLength)
|
||||
c₁ = (1 - b + a²) / 2
|
||||
```
|
||||
|
||||
### Pseudo-code
|
||||
|
||||
```
|
||||
function EBSW(source, hpLength, ssfLength):
|
||||
// Precompute HP coefficient
|
||||
α₁ ← (1 - sin(2π/hpLength)) / cos(2π/hpLength)
|
||||
|
||||
// Precompute SSF coefficients
|
||||
a ← exp(-√2·π / ssfLength)
|
||||
b ← 2·a·cos(√2·π / ssfLength)
|
||||
c₁ ← (1 - b + a²) / 2
|
||||
|
||||
hp_prev ← 0; p_prev ← 0
|
||||
filt_1 ← 0; filt_2 ← 0
|
||||
|
||||
for each price in source:
|
||||
// High-pass filter
|
||||
hp ← 0.5·(1 + α₁)·(price - p_prev) + α₁·hp_prev
|
||||
|
||||
// Super-smoother
|
||||
filt ← c₁·(hp + hp_prev) + b·filt_1 - a²·filt_2
|
||||
|
||||
// Wave (3-bar average of filtered signal)
|
||||
wave ← (filt + filt_1 + filt_2) / 3
|
||||
|
||||
// Power (3-bar RMS²)
|
||||
power ← (filt² + filt_1² + filt_2²) / 3
|
||||
|
||||
// AGC normalization
|
||||
ebsw ← (power > 0) ? wave / √power : 0
|
||||
ebsw ← clamp(ebsw, -1, +1)
|
||||
|
||||
// Shift state
|
||||
hp_prev ← hp; p_prev ← price
|
||||
filt_2 ← filt_1; filt_1 ← filt
|
||||
|
||||
emit ebsw
|
||||
```
|
||||
|
||||
### Output Interpretation
|
||||
|
||||
| Condition | Meaning |
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
# HOMOD: Ehlers Homodyne Discriminator
|
||||
|
||||
> *The homodyne discriminator locks onto a cycle's frequency by comparing successive analytic signal rotations.*
|
||||
|
||||
| Property | Value |
|
||||
| ---------------- | -------------------------------- |
|
||||
| **Category** | Cycle |
|
||||
@@ -71,60 +73,6 @@ $O(1)$ per bar with $O(1)$ memory. The pipeline consists entirely of fixed-depth
|
||||
| `minPeriod` | Minimum detectable period | 6.0 | $> 0$ |
|
||||
| `maxPeriod` | Maximum detectable period | 50.0 | $> minPeriod$ |
|
||||
|
||||
### Pseudo-code
|
||||
|
||||
```
|
||||
function HOMOD(source, minPeriod, maxPeriod):
|
||||
A ← 0.0962; B ← 0.5769
|
||||
smoothBuf ← CircularBuffer(7)
|
||||
detBuf ← CircularBuffer(7)
|
||||
|
||||
I2_prev ← 0; Q2_prev ← 0
|
||||
Re_prev ← 0; Im_prev ← 0
|
||||
period_prev ← (minPeriod + maxPeriod) / 2
|
||||
|
||||
for each price in source:
|
||||
// 4-bar WMA
|
||||
smooth ← (4·price + 3·p[1] + 2·p[2] + p[3]) / 10
|
||||
smoothBuf.Add(smooth)
|
||||
|
||||
// Detrender (Hilbert FIR)
|
||||
det ← A·smooth[0] + B·smooth[2] - B·smooth[4] - A·smooth[6]
|
||||
detBuf.Add(det)
|
||||
|
||||
// I1 = det[3], Q1 = Hilbert(det)
|
||||
I1 ← det[3]
|
||||
Q1 ← A·det[0] + B·det[2] - B·det[4] - A·det[6]
|
||||
|
||||
// Hilbert of I1 and Q1
|
||||
jI ← HilbertFIR(I1_history)
|
||||
jQ ← HilbertFIR(Q1_history)
|
||||
|
||||
// Phasor components (smoothed)
|
||||
I2 ← 0.2·(I1 - jQ) + 0.8·I2_prev
|
||||
Q2 ← 0.2·(Q1 + jI) + 0.8·Q2_prev
|
||||
|
||||
// Homodyne mixing
|
||||
re ← 0.2·(I2·I2_prev + Q2·Q2_prev) + 0.8·Re_prev
|
||||
im ← 0.2·(I2·Q2_prev - Q2·I2_prev) + 0.8·Im_prev
|
||||
|
||||
// Period extraction
|
||||
if im ≠ 0 and re ≠ 0:
|
||||
period ← 2π / atan2(im, re)
|
||||
else:
|
||||
period ← period_prev
|
||||
|
||||
period ← clamp(period, minPeriod, maxPeriod)
|
||||
period ← 0.33·period + 0.67·period_prev
|
||||
|
||||
// Update state
|
||||
I2_prev ← I2; Q2_prev ← Q2
|
||||
Re_prev ← re; Im_prev ← im
|
||||
period_prev ← period
|
||||
|
||||
emit period
|
||||
```
|
||||
|
||||
### Output Interpretation
|
||||
|
||||
| Output | Meaning |
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
# HT_DCPERIOD: Ehlers Hilbert Transform Dominant Cycle Period
|
||||
|
||||
> *The Hilbert Transform extracts the dominant cycle period by converting price into an analytic signal and measuring its phase rate.*
|
||||
|
||||
| Property | Value |
|
||||
| ---------------- | -------------------------------- |
|
||||
| **Category** | Cycle |
|
||||
@@ -68,47 +70,6 @@ $O(1)$ per bar. Fixed Hilbert cascade with circular buffers totaling approximate
|
||||
|
||||
The period range [6, 50] and all smoothing constants are fixed by the TA-Lib specification.
|
||||
|
||||
### Pseudo-code
|
||||
|
||||
```
|
||||
function HT_DCPERIOD(source):
|
||||
A ← 0.0962; B ← 0.5769
|
||||
smoothBuf ← CircularBuffer(7)
|
||||
detBuf, q1Buf, i1Buf ← CircularBuffers
|
||||
|
||||
I2 ← 0; Q2 ← 0
|
||||
Re ← 0; Im ← 0
|
||||
period ← 15 // initial estimate
|
||||
|
||||
for each price in source:
|
||||
// Step 1: WMA smooth
|
||||
smooth ← (4·price + 3·p[1] + 2·p[2] + p[3]) / 10
|
||||
|
||||
// Step 2: Hilbert FIR (adaptive to period)
|
||||
adj ← A + B // coefficient adjustment
|
||||
det ← adj·(smooth[0] - smooth[6]) + B·(smooth[2] - smooth[4])
|
||||
Q1 ← adj·(det[0] - det[6]) + B·(det[2] - det[4])
|
||||
I1 ← det[3]
|
||||
jI ← adj·(I1[0] - I1[6]) + B·(I1[2] - I1[4])
|
||||
jQ ← adj·(Q1[0] - Q1[6]) + B·(Q1[2] - Q1[4])
|
||||
|
||||
// Step 3: Phasor (EMA smoothed)
|
||||
I2 ← 0.2·(I1 - jQ) + 0.8·I2
|
||||
Q2 ← 0.2·(Q1 + jI) + 0.8·Q2
|
||||
|
||||
// Step 4: Homodyne discriminator
|
||||
Re ← 0.2·(I2·I2_prev + Q2·Q2_prev) + 0.8·Re
|
||||
Im ← 0.2·(I2·Q2_prev - Q2·I2_prev) + 0.8·Im
|
||||
|
||||
// Step 5: Period
|
||||
if Im ≠ 0 and Re ≠ 0:
|
||||
p ← 2π / atan(Im / Re)
|
||||
p ← clamp(p, 6, 50)
|
||||
period ← 0.33·p + 0.67·period
|
||||
|
||||
emit period
|
||||
```
|
||||
|
||||
### Output Interpretation
|
||||
|
||||
| Output | Meaning |
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
# HT_DCPHASE: Ehlers Hilbert Transform Dominant Cycle Phase
|
||||
|
||||
> *Dominant cycle phase tracks where price sits within its current cycle — the angular position of the market's heartbeat.*
|
||||
|
||||
| Property | Value |
|
||||
| ---------------- | -------------------------------- |
|
||||
| **Category** | Cycle |
|
||||
@@ -64,38 +66,6 @@ $O(P)$ per bar where $P$ is the smoothed period (typically 6-50), due to the DFT
|
||||
|
||||
All internal constants are fixed by the TA-Lib specification.
|
||||
|
||||
### Pseudo-code
|
||||
|
||||
```
|
||||
function HT_DCPHASE(source):
|
||||
// Same Hilbert cascade as HT_DCPERIOD
|
||||
// ... (WMA smooth, Hilbert FIR, phasor, homodyne)
|
||||
// Produces: smoothPeriod, smoothPriceBuf
|
||||
|
||||
for each bar (after warmup):
|
||||
P ← round(smoothPeriod)
|
||||
|
||||
// DFT accumulation over dominant period
|
||||
realPart ← 0; imagPart ← 0
|
||||
for i = 0 to P-1:
|
||||
realPart += sin(2π·i / P) · smoothPriceBuf[t - i]
|
||||
imagPart += cos(2π·i / P) · smoothPriceBuf[t - i]
|
||||
|
||||
// Phase extraction
|
||||
if |imagPart| > 0:
|
||||
dcPhase ← atan(realPart / imagPart) · (180/π)
|
||||
else:
|
||||
dcPhase ← 90 · sign(realPart)
|
||||
|
||||
if imagPart > 0: dcPhase -= 180
|
||||
dcPhase += 90
|
||||
|
||||
// Wrap to [-45, 315]
|
||||
if dcPhase < -45: dcPhase += 360
|
||||
|
||||
emit dcPhase
|
||||
```
|
||||
|
||||
### Phase Quadrant Interpretation
|
||||
|
||||
| Phase Range | Cycle Position |
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
# HT_PHASOR: Ehlers Hilbert Transform Phasor Components
|
||||
|
||||
> *Phasor components decompose price into in-phase and quadrature parts, mapping the cycle as a rotating vector.*
|
||||
|
||||
| Property | Value |
|
||||
| ---------------- | -------------------------------- |
|
||||
| **Category** | Cycle |
|
||||
@@ -58,37 +60,6 @@ $O(1)$ per bar. Fixed Hilbert cascade with circular buffers. Warmup: 32 bars (TA
|
||||
|-----------|-------------|---------|------------|
|
||||
| (none) | No user-configurable parameters | | |
|
||||
|
||||
### Pseudo-code
|
||||
|
||||
```
|
||||
function HT_PHASOR(source):
|
||||
A ← 0.0962; B ← 0.5769
|
||||
smoothBuf ← CircularBuffer(7)
|
||||
detBuf, q1Buf, i1Buf ← CircularBuffers
|
||||
|
||||
I2 ← 0; Q2 ← 0
|
||||
|
||||
for each price in source:
|
||||
// WMA smooth
|
||||
smooth ← (4·price + 3·p[1] + 2·p[2] + p[3]) / 10
|
||||
smoothBuf.Add(smooth)
|
||||
|
||||
// Hilbert FIR (adaptive)
|
||||
det ← A·smooth[0] + B·smooth[2] - B·smooth[4] - A·smooth[6]
|
||||
Q1 ← A·det[0] + B·det[2] - B·det[4] - A·det[6]
|
||||
I1 ← det[3]
|
||||
|
||||
// Hilbert of I1 and Q1
|
||||
jI ← A·I1[0] + B·I1[2] - B·I1[4] - A·I1[6]
|
||||
jQ ← A·Q1[0] + B·Q1[2] - B·Q1[4] - A·Q1[6]
|
||||
|
||||
// Phasor components (EMA smoothed)
|
||||
I2 ← 0.2·(I1 - jQ) + 0.8·I2
|
||||
Q2 ← 0.2·(Q1 + jI) + 0.8·Q2
|
||||
|
||||
emit InPhase = I2, Quadrature = Q2
|
||||
```
|
||||
|
||||
### Phasor Crossover Signals
|
||||
|
||||
| Condition | Signal |
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
# HT_SINE: Ehlers Hilbert Transform SineWave (also known as SINE)
|
||||
|
||||
> *The Hilbert sine wave renders cycle timing visible — crossovers of sine and lead-sine mark turning points.*
|
||||
|
||||
| Property | Value |
|
||||
| ---------------- | -------------------------------- |
|
||||
| **Category** | Cycle |
|
||||
@@ -70,27 +72,6 @@ $O(P)$ per bar where $P$ is the smoothed period (typically 6-50), due to the DFT
|
||||
|
||||
All constants are fixed by the TA-Lib specification.
|
||||
|
||||
### Pseudo-code
|
||||
|
||||
```
|
||||
function HT_SINE(source):
|
||||
// Full Hilbert cascade (same as HT_DCPHASE)
|
||||
// Produces: smoothPeriod, smoothPriceBuf, dcPhase
|
||||
|
||||
for each bar (after warmup):
|
||||
// Phase from DFT accumulation (see HT_DCPHASE)
|
||||
φ ← computeDCPhase(smoothPeriod, smoothPriceBuf)
|
||||
|
||||
// Convert phase to radians
|
||||
φ_rad ← φ · (π / 180)
|
||||
|
||||
// Dual sine output
|
||||
sine ← sin(φ_rad)
|
||||
leadSine ← sin(φ_rad + π/4) // 45° lead
|
||||
|
||||
emit sine, leadSine
|
||||
```
|
||||
|
||||
### Crossover Signals
|
||||
|
||||
| Pattern | Signal |
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
# LUNAR: Lunar Phase Indicator
|
||||
|
||||
> *The lunar cycle maps the Moon's phase onto price — an ancient rhythm tested against modern markets.*
|
||||
|
||||
| Property | Value |
|
||||
| ---------------- | -------------------------------- |
|
||||
| **Category** | Cycle |
|
||||
@@ -82,41 +84,6 @@ $O(1)$ per timestamp. No state required (deterministic from time). Zero warmup.
|
||||
|
||||
The calculation is entirely determined by the input timestamp.
|
||||
|
||||
### Pseudo-code
|
||||
|
||||
```
|
||||
function LUNAR(timestamp):
|
||||
// Julian date
|
||||
JD ← timestamp_to_unix_ms / 86400000 + 2440587.5
|
||||
T ← (JD - 2451545.0) / 36525.0
|
||||
|
||||
// Mean orbital elements (Horner evaluation)
|
||||
Lp ← FMA(T, FMA(T, FMA(T, 1/538841, -0.0015786), 481267.88123421), 218.3164477)
|
||||
D ← FMA(T, FMA(T, FMA(T, 1/545868, -0.0018819), 445267.1114034), 297.8501921)
|
||||
M ← FMA(T, FMA(T, -0.0001536, 35999.0502909), 357.5291092)
|
||||
Mp ← FMA(T, FMA(T, 0.0087414, 477198.8675055), 134.9633964)
|
||||
F ← FMA(T, FMA(T, -0.0036539, 483202.0175233), 93.2720950)
|
||||
|
||||
// Normalize to [0°, 360°)
|
||||
Lp, D, M, Mp, F ← mod(*, 360)
|
||||
|
||||
// Perturbation correction (6 major terms)
|
||||
Σ ← 6288016·sin(Mp) + 1274242·sin(2D - Mp) + 658314·sin(2D)
|
||||
+ 214818·sin(2Mp) + 186986·sin(M) + 109154·sin(2F)
|
||||
λ_moon ← Lp + Σ / 1e6
|
||||
|
||||
// Solar longitude (simplified)
|
||||
L0 ← 280.46646 + 36000.76983·T
|
||||
M_sun ← 357.52911 + 35999.05029·T
|
||||
λ_sun ← L0 + 1.9146·sin(M_sun) + 0.02·sin(2·M_sun)
|
||||
|
||||
// Phase angle and illumination
|
||||
ψ ← λ_moon - λ_sun
|
||||
k ← (1 - cos(ψ)) / 2
|
||||
|
||||
emit k // 0.0 = New Moon, 1.0 = Full Moon
|
||||
```
|
||||
|
||||
### Output Interpretation
|
||||
|
||||
| Value | Phase |
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
# SOLAR: Solar Cycle Indicator
|
||||
|
||||
> *Solar cycles encode the Sun's rhythmic activity into a tradeable signal, bridging astrophysics and price action.*
|
||||
|
||||
| Property | Value |
|
||||
| ---------------- | -------------------------------- |
|
||||
| **Category** | Cycle |
|
||||
@@ -74,36 +76,6 @@ $O(1)$ per timestamp. No state required. Zero warmup. The tropical year is appro
|
||||
|
||||
The calculation is entirely determined by the input timestamp.
|
||||
|
||||
### Pseudo-code
|
||||
|
||||
```
|
||||
function SOLAR(timestamp):
|
||||
// Julian date
|
||||
JD ← timestamp_to_unix_ms / 86400000 + 2440587.5
|
||||
T ← (JD - 2451545.0) / 36525.0
|
||||
|
||||
// Geometric mean longitude
|
||||
L0 ← FMA(T, FMA(T, 0.0003032, 36000.76983), 280.46646)
|
||||
L0 ← mod(L0, 360)
|
||||
|
||||
// Mean anomaly
|
||||
M ← FMA(T, FMA(T, -0.0001537, 35999.05029), 357.52911)
|
||||
M ← mod(M, 360)
|
||||
|
||||
// Equation of center
|
||||
C ← FMA(T, FMA(T, -0.000014, -0.004817), 1.914602) · sin(M)
|
||||
+ FMA(T, -0.000101, 0.019993) · sin(2M)
|
||||
+ 0.000289 · sin(3M)
|
||||
|
||||
// True ecliptic longitude
|
||||
λ ← L0 + C
|
||||
|
||||
// Seasonal index
|
||||
solar ← sin(λ · π / 180)
|
||||
|
||||
emit solar
|
||||
```
|
||||
|
||||
### Seasonal Correspondence (Northern Hemisphere)
|
||||
|
||||
| Date (approx.) | $\lambda_{Sun}$ | Solar Value | Season |
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
# SSFDSP: Ehlers SSF Detrended Synthetic Price
|
||||
|
||||
> *SSF-based detrended synthetic price applies a super smoother before extracting cycles, achieving cleaner periodicity isolation.*
|
||||
|
||||
| Property | Value |
|
||||
| ---------------- | -------------------------------- |
|
||||
| **Category** | Cycle |
|
||||
@@ -70,50 +72,6 @@ $O(1)$ per bar. Two independent 2-pole IIR filters with $O(1)$ memory. Warmup: a
|
||||
|
||||
The SSF has $-3$ dB attenuation at the cutoff period, $-12$ dB/octave rolloff (2-pole), and zero phase lag at the cutoff. This is equivalent to a critically-damped Butterworth filter.
|
||||
|
||||
### Pseudo-code
|
||||
|
||||
```
|
||||
function SSFDSP(source, period):
|
||||
pFast ← max(2, round(period / 4))
|
||||
pSlow ← max(3, round(period / 2))
|
||||
|
||||
// Fast SSF coefficients
|
||||
αf ← √2·π / pFast
|
||||
c2f ← 2·exp(-αf)·cos(αf)
|
||||
c3f ← -exp(-2·αf)
|
||||
c1f ← 1 - c2f - c3f
|
||||
|
||||
// Slow SSF coefficients
|
||||
αs ← √2·π / pSlow
|
||||
c2s ← 2·exp(-αs)·cos(αs)
|
||||
c3s ← -exp(-2·αs)
|
||||
c1s ← 1 - c2s - c3s
|
||||
|
||||
ssfFast_1 ← 0; ssfFast_2 ← 0
|
||||
ssfSlow_1 ← 0; ssfSlow_2 ← 0
|
||||
p_prev ← 0
|
||||
|
||||
for each price in source:
|
||||
// Input averaging
|
||||
avg ← (price + p_prev) / 2
|
||||
|
||||
// Fast SSF update
|
||||
ssfFast ← c1f·avg + c2f·ssfFast_1 + c3f·ssfFast_2
|
||||
|
||||
// Slow SSF update
|
||||
ssfSlow ← c1s·avg + c2s·ssfSlow_1 + c3s·ssfSlow_2
|
||||
|
||||
// SSFDSP
|
||||
ssfdsp ← ssfFast - ssfSlow
|
||||
|
||||
// Shift state
|
||||
ssfFast_2 ← ssfFast_1; ssfFast_1 ← ssfFast
|
||||
ssfSlow_2 ← ssfSlow_1; ssfSlow_1 ← ssfSlow
|
||||
p_prev ← price
|
||||
|
||||
emit ssfdsp
|
||||
```
|
||||
|
||||
### DSP vs SSFDSP
|
||||
|
||||
| Aspect | DSP (EMA-based) | SSFDSP (Super-Smoother) |
|
||||
|
||||
Reference in New Issue
Block a user