feat: add FSI (Ehlers Fourier Series Indicator, TASC June 2019)

This commit is contained in:
Miha Kralj
2026-03-18 19:58:53 -07:00
parent b79b56dc65
commit b1302a4761
15 changed files with 1344 additions and 1 deletions
+1
View File
@@ -576,6 +576,7 @@ HAS_EBSW = _bind("qtl_ebsw", [_dp, _ci, _dp, _ci, _ci])
HAS_ACP = _bind("qtl_acp", [_dp, _ci, _dp, _ci, _ci, _ci, _ci])
HAS_LPF = _bind("qtl_lpf", [_dp, _ci, _dp, _ci, _ci, _ci])
HAS_AMFM = _bind("qtl_amfm", [_dp, _dp, _ci, _dp, _dp, _ci])
HAS_FSI = _bind("qtl_fsi", [_dp, _ci, _dp, _ci, _cd])
# ── Numerics (Exports.cs — manual) ──
HAS_CHANGE = _bind("qtl_change", [_dp, _ci, _dp, _ci])
+10
View File
@@ -23,6 +23,7 @@ __all__ = [
"ebsw",
"acp",
"amfm",
"fsi",
]
@@ -172,3 +173,12 @@ def amfm(open: object, close: object, period: int = 30,
n = len(o); fm = _out(n); am = _out(n)
_check(_lib.qtl_amfm(_ptr(o), _ptr(c), n, _ptr(fm), _ptr(am), period))
return _wrap_multi({f"FM_{period}": fm, f"AM_{period}": am}, idx, "cycles", offset)
def fsi(close: object, period: int = 20, bandwidth: float = 0.1,
offset: int = 0, **kwargs) -> object:
"""Ehlers Fourier Series Indicator."""
period = int(kwargs.get("length", period)); offset = int(offset)
src, idx = _arr(close); n = len(src); dst = _out(n)
_check(_lib.qtl_fsi(_ptr(src), n, _ptr(dst), period, float(bandwidth)))
return _wrap(dst, idx, f"FSI_{period}", "cycles", offset)
+10
View File
@@ -1556,6 +1556,16 @@ public static unsafe partial class Exports
catch { return StatusCodes.QTL_ERR_INTERNAL; }
}
// Fsi: Pattern A (src → dst, int period, double bandwidth)
[UnmanagedCallersOnly(EntryPoint = "qtl_fsi")]
public static int QtlFsi(double* src, int n, double* dst, int period, double bandwidth)
{
int v = Chk1(src, dst, n); if (v != 0) return v;
v = ChkPeriod(period); if (v != 0) return v;
try { Fsi.Batch(Src(src, n), Dst(dst, n), period, bandwidth); return StatusCodes.QTL_OK; }
catch { return StatusCodes.QTL_ERR_INTERNAL; }
}
// ═══════════════════════════════════════════════════════════════════════
// §8.14 Numerics / transforms
// ═══════════════════════════════════════════════════════════════════════