feat: add new indicators (Decay, Edecay, MinusDi, MinusDm, PlusDi, PlusDm, Maxindex, Minindex, Sarext) and update pine scripts, core libs, validation tests, and python bindings

This commit is contained in:
Miha Kralj
2026-03-09 13:45:46 -07:00
parent 8e43d62cbb
commit 031f1b5fe6
491 changed files with 6156 additions and 5590 deletions
+48
View File
@@ -17,11 +17,15 @@ __all__ = [
"chop",
"dmx",
"dx",
"minus_di",
"minus_dm",
"ghla",
"ht_trendmode",
"ichimoku",
"impulse",
"pfe",
"plus_di",
"plus_dm",
"qstick",
"ravi",
"supertrend",
@@ -140,6 +144,28 @@ def dx(high: object, low: object, close: object, period: int = 14, offset: int =
return _wrap(destination, idx, f"DX_{period}", "dynamics", offset)
def minus_di(high: object, low: object, close: object, period: int = 14, offset: int = 0, **kwargs) -> object:
"""Minus Directional Indicator."""
period = int(kwargs.get("length", period))
offset = int(offset)
h, idx = _arr(high); l, _ = _arr(low); c, _ = _arr(close)
n = len(h)
destination = _out(n)
_check(_lib.qtl_minusdi(_ptr(h), _ptr(h), _ptr(l), _ptr(c), _ptr(destination), period, n, _ptr(destination)))
return _wrap(destination, idx, f"MINUS_DI_{period}", "dynamics", offset)
def minus_dm(high: object, low: object, close: object, period: int = 14, offset: int = 0, **kwargs) -> object:
"""Minus Directional Movement."""
period = int(kwargs.get("length", period))
offset = int(offset)
h, idx = _arr(high); l, _ = _arr(low); c, _ = _arr(close)
n = len(h)
destination = _out(n)
_check(_lib.qtl_minusdm(_ptr(h), _ptr(h), _ptr(l), _ptr(c), _ptr(destination), period, n, _ptr(destination)))
return _wrap(destination, idx, f"MINUS_DM_{period}", "dynamics", offset)
def ghla(high: object, low: object, close: object, period: int = 14, offset: int = 0, **kwargs) -> object:
"""Gann Hi-Lo Activator."""
period = int(kwargs.get("length", period))
@@ -206,6 +232,28 @@ def pfe(close: object, period: int = 14, smoothPeriod: int = 5, offset: int = 0,
return _wrap(output, idx, f"PFE_{period}", "dynamics", offset)
def plus_di(high: object, low: object, close: object, period: int = 14, offset: int = 0, **kwargs) -> object:
"""Plus Directional Indicator."""
period = int(kwargs.get("length", period))
offset = int(offset)
h, idx = _arr(high); l, _ = _arr(low); c, _ = _arr(close)
n = len(h)
destination = _out(n)
_check(_lib.qtl_plusdi(_ptr(h), _ptr(h), _ptr(l), _ptr(c), _ptr(destination), period, n, _ptr(destination)))
return _wrap(destination, idx, f"PLUS_DI_{period}", "dynamics", offset)
def plus_dm(high: object, low: object, close: object, period: int = 14, offset: int = 0, **kwargs) -> object:
"""Plus Directional Movement."""
period = int(kwargs.get("length", period))
offset = int(offset)
h, idx = _arr(high); l, _ = _arr(low); c, _ = _arr(close)
n = len(h)
destination = _out(n)
_check(_lib.qtl_plusdm(_ptr(h), _ptr(h), _ptr(l), _ptr(c), _ptr(destination), period, n, _ptr(destination)))
return _wrap(destination, idx, f"PLUS_DM_{period}", "dynamics", offset)
def qstick(open: object, high: object, low: object, close: object, volume: object, period: int = 14, useEma: int = 0, offset: int = 0, **kwargs) -> object:
"""QStick."""
period = int(kwargs.get("length", period))
+24
View File
@@ -13,12 +13,14 @@ __all__ = [
"fft",
"gammadist",
"highest",
"maxindex",
"ifft",
"jerk",
"lineartrans",
"lognormdist",
"logtrans",
"lowest",
"minindex",
"normalize",
"normdist",
"poissondist",
@@ -98,6 +100,17 @@ def highest(close: object, period: int = 14, offset: int = 0, **kwargs) -> objec
return _wrap(output, idx, f"HIGHEST_{period}", "numerics", offset)
def maxindex(close: object, period: int = 14, offset: int = 0, **kwargs) -> object:
"""Index of Highest Value."""
period = int(kwargs.get("length", period))
offset = int(offset)
src, idx = _arr(close)
n = len(src)
output = _out(n)
_check(_lib.qtl_maxindex(_ptr(src), _ptr(output), n, period))
return _wrap(output, idx, f"MAXINDEX_{period}", "numerics", offset)
def ifft(close: object, windowSize: int = 256, numHarmonics: int = 10, offset: int = 0, **kwargs) -> object:
"""Inverse FFT."""
windowSize = int(windowSize)
@@ -166,6 +179,17 @@ def lowest(close: object, period: int = 14, offset: int = 0, **kwargs) -> object
return _wrap(output, idx, f"LOWEST_{period}", "numerics", offset)
def minindex(close: object, period: int = 14, offset: int = 0, **kwargs) -> object:
"""Index of Lowest Value."""
period = int(kwargs.get("length", period))
offset = int(offset)
src, idx = _arr(close)
n = len(src)
output = _out(n)
_check(_lib.qtl_minindex(_ptr(src), _ptr(output), n, period))
return _wrap(output, idx, f"MININDEX_{period}", "numerics", offset)
def normalize(close: object, period: int = 14, offset: int = 0, **kwargs) -> object:
"""Normalization."""
period = int(kwargs.get("length", period))
+19
View File
@@ -18,6 +18,7 @@ __all__ = [
"pivotfib",
"pivotwood",
"psar",
"sarext",
"swings",
"ttm_scalper",
]
@@ -132,6 +133,24 @@ def psar(open: object, high: object, low: object, close: object, afStart: float
return _wrap(output, idx, "PSAR", "reversals", offset)
def sarext(open: object, high: object, low: object, close: object, startValue: float = 0.0, offsetOnReverse: float = 0.0, afInitLong: float = 0.02, afLong: float = 0.02, afMaxLong: float = 0.2, afInitShort: float = 0.02, afShort: float = 0.02, afMaxShort: float = 0.2, offset: int = 0, **kwargs) -> object:
"""Parabolic SAR Extended."""
startValue = float(startValue)
offsetOnReverse = float(offsetOnReverse)
afInitLong = float(afInitLong)
afLong = float(afLong)
afMaxLong = float(afMaxLong)
afInitShort = float(afInitShort)
afShort = float(afShort)
afMaxShort = float(afMaxShort)
offset = int(offset)
o, idx = _arr(open); h, _ = _arr(high); l, _ = _arr(low); c, _ = _arr(close)
n = len(o)
output = _out(n)
_check(_lib.qtl_sarext(_ptr(o), _ptr(h), _ptr(l), _ptr(c), _ptr(output), n, startValue, offsetOnReverse, afInitLong, afLong, afMaxLong, afInitShort, afShort, afMaxShort))
return _wrap(output, idx, "SAREXT", "reversals", offset)
def swings(high: object, low: object, lookback: int = 5, offset: int = 0, **kwargs) -> object:
"""Swing High/Low."""
lookback = int(lookback)