mirror of
https://github.com/mihakralj/QuanTAlib.git
synced 2026-07-30 02:27:43 +00:00
feat: add TBF (Ehlers Truncated BandPass Filter) + fix all 64 warnings
TBF indicator: - Sealed class with RingBuffer, stackalloc scratch, O(Length) per bar - 7 core files: Tbf.cs, Tbf.Quantower.cs, Tbf.md, tbf.pine, 3 test files - 67 tests (48 lib + 19 Quantower) all passing - Full integration: sidebar, indexes, docs, Python bridge, exports AMFM fix: - Added envBuf.Clear()/smaBuf.Clear() after stackalloc in Batch (SkipLocalsInit garbage values caused 8.97e+65 blowup) Warning fixes (64 → 0): - Amfm.cs: S125 commented code removed, 11× IDE0011 braces - Pta.cs: 11× IDE0011 braces on if/else/for/foreach - Pta.Tests.cs: 14× IDE0011, S1481 unused var, S2699 assertion, 2× MA0074 - Lpf.Quantower.Tests.cs: 2× MA0074 StringComparison Build: 0 warnings, 0 errors, 20,048 tests passing
This commit is contained in:
@@ -331,6 +331,7 @@ HAS_RMED = _bind("qtl_rmed", [_dp, _dp, _ci, _ci])
|
||||
HAS_ROOFING = _bind("qtl_roofing", [_dp, _dp, _ci, _ci, _ci])
|
||||
HAS_SGF = _bind("qtl_sgf", [_dp, _dp, _ci, _ci, _ci])
|
||||
HAS_SPBF = _bind("qtl_spbf", [_dp, _dp, _ci, _ci, _ci, _ci])
|
||||
HAS_TBF = _bind("qtl_tbf", [_dp, _dp, _ci, _ci, _cd, _ci])
|
||||
HAS_SSF2 = _bind("qtl_ssf2", [_dp, _dp, _ci, _ci])
|
||||
HAS_SSF3 = _bind("qtl_ssf3", [_dp, _dp, _ci, _ci, _cd])
|
||||
HAS_USF = _bind("qtl_usf", [_dp, _dp, _ci, _ci])
|
||||
|
||||
@@ -257,8 +257,8 @@ def ttm_lrc(close: object, period: int = 14, offset: int = 0, **kwargs) -> objec
|
||||
return _wrap_multi({"midline": midline, "upper1": upper1, "lower1": lower1, "upper2": upper2, "lower2": lower2}, idx, "channels", offset)
|
||||
|
||||
|
||||
def ubands(close: object, period: int = 14, multiplier: float = 2.0, offset: int = 0, **kwargs) -> object:
|
||||
"""Upper/Lower Bands."""
|
||||
def ubands(close: object, period: int = 20, multiplier: float = 1.0, offset: int = 0, **kwargs) -> object:
|
||||
"""Ehlers Ultimate Bands."""
|
||||
period = int(kwargs.get("length", period))
|
||||
multiplier = float(multiplier)
|
||||
offset = int(offset)
|
||||
@@ -271,8 +271,8 @@ def ubands(close: object, period: int = 14, multiplier: float = 2.0, offset: int
|
||||
return _wrap_multi({"upper": upper, "middle": middle, "lower": lower}, idx, "channels", offset)
|
||||
|
||||
|
||||
def uchannel(high: object, low: object, close: object, strPeriod: int = 14, centerPeriod: int = 20, multiplier: float = 2.0, offset: int = 0, **kwargs) -> object:
|
||||
"""Ulcer Channel."""
|
||||
def uchannel(high: object, low: object, close: object, strPeriod: int = 20, centerPeriod: int = 20, multiplier: float = 1.0, offset: int = 0, **kwargs) -> object:
|
||||
"""Ehlers Ultimate Channel."""
|
||||
strPeriod = int(strPeriod)
|
||||
centerPeriod = int(centerPeriod)
|
||||
multiplier = float(multiplier)
|
||||
|
||||
@@ -25,6 +25,7 @@ __all__ = [
|
||||
"roofing",
|
||||
"sgf",
|
||||
"spbf",
|
||||
"tbf",
|
||||
"ssf2",
|
||||
"ssf3",
|
||||
"usf",
|
||||
@@ -248,6 +249,19 @@ def spbf(close: object, shortPeriod: int = 40, longPeriod: int = 60, rmsPeriod:
|
||||
return _wrap(output, idx, f"SPBF_{shortPeriod}", "filters", offset)
|
||||
|
||||
|
||||
def tbf(close: object, period: int = 20, bandwidth: float = 0.1, length: int = 10, offset: int = 0, **kwargs) -> object:
|
||||
"""Ehlers Truncated Bandpass Filter."""
|
||||
period = int(period)
|
||||
bandwidth = float(bandwidth)
|
||||
length = int(length)
|
||||
offset = int(offset)
|
||||
src, idx = _arr(close)
|
||||
n = len(src)
|
||||
output = _out(n)
|
||||
_check(_lib.qtl_tbf(_ptr(src), _ptr(output), n, period, bandwidth, length))
|
||||
return _wrap(output, idx, f"TBF_{period}", "filters", offset)
|
||||
|
||||
|
||||
def ssf2(close: object, period: int = 14, offset: int = 0, **kwargs) -> object:
|
||||
"""Super Smoother (2-pole)."""
|
||||
period = int(kwargs.get("length", period))
|
||||
|
||||
@@ -2887,6 +2887,22 @@ public static unsafe partial class Exports
|
||||
catch { return StatusCodes.QTL_ERR_INTERNAL; }
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly(EntryPoint = "qtl_tbf")]
|
||||
public static int QtlTbf(double* source, double* output, int n, int period, double bandwidth, int length)
|
||||
{
|
||||
if (source == null || output == null) return StatusCodes.QTL_ERR_NULL_PTR;
|
||||
if (n <= 0) return StatusCodes.QTL_ERR_INVALID_LENGTH;
|
||||
try
|
||||
{
|
||||
var src = Src(source, n);
|
||||
var dst = Dst(output, n);
|
||||
Span<double> bpScratch = n <= 4096 ? stackalloc double[n] : new double[n];
|
||||
Tbf.Batch(src, dst, bpScratch, period, bandwidth, length);
|
||||
return StatusCodes.QTL_OK;
|
||||
}
|
||||
catch { return StatusCodes.QTL_ERR_INTERNAL; }
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly(EntryPoint = "qtl_spearman")]
|
||||
public static int QtlSpearman(double* seriesX, double* seriesY, double* output, int n, int period)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user