mirror of
https://github.com/mihakralj/QuanTAlib.git
synced 2026-08-04 20:17:43 +00:00
feat: add 8 new indicators with full integration
New indicators: - HWC (Holt-Winters Channel) — channels, 27 tests - VWMACD (Volume-Weighted MACD) — momentum, 38 tests - Squeeze Pro — oscillators, 69 tests - BW_MFI (Bill Williams MFI) — oscillators - DSTOCH (Double Stochastic) — oscillators - ATRSTOP (ATR Trailing Stop) — reversals - VSTOP (Volatility Stop) — reversals - Convexity (Beta Convexity) — statistics, 23 tests Integration: - Python bridge: Exports.cs, _bridge.py, wrapper modules - Documentation: _sidebar.md, _index.md pages, SPEC.md - All analyzer warnings fixed (MA0074, xUnit2013, S2699) Build: 0 warnings, 0 errors | Tests: 15,933 passed, 0 failed
This commit is contained in:
@@ -308,6 +308,20 @@ public static unsafe partial class Exports
|
||||
catch { return StatusCodes.QTL_ERR_INTERNAL; }
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly(EntryPoint = "qtl_atrstop")]
|
||||
public static int QtlAtrstop(double* high, double* low, double* close, double* output, int n, int period, double multiplier)
|
||||
{
|
||||
if (high == null || low == null || close == null || output == null) return StatusCodes.QTL_ERR_NULL_PTR;
|
||||
if (n <= 0) return StatusCodes.QTL_ERR_INVALID_LENGTH;
|
||||
if (period <= 0) return StatusCodes.QTL_ERR_INVALID_PARAM;
|
||||
try
|
||||
{
|
||||
Atrstop.Batch(Src(high, n), Src(low, n), Src(close, n), Dst(output, n), period, multiplier);
|
||||
return StatusCodes.QTL_OK;
|
||||
}
|
||||
catch { return StatusCodes.QTL_ERR_INTERNAL; }
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly(EntryPoint = "qtl_atr")]
|
||||
public static int QtlAtr(double* sourceOpen, double* sourceHigh, double* sourceLow, double* sourceClose, double* sourceVolume, int period, int n, double* dst)
|
||||
{
|
||||
@@ -372,6 +386,44 @@ public static unsafe partial class Exports
|
||||
catch { return StatusCodes.QTL_ERR_INTERNAL; }
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly(EntryPoint = "qtl_bwmfi")]
|
||||
public static int QtlBwMfi(double* high, double* low, double* volume, double* mfiOutput, double* zoneOutput, int n)
|
||||
{
|
||||
if (high == null || low == null || volume == null || mfiOutput == null || zoneOutput == null) return StatusCodes.QTL_ERR_NULL_PTR;
|
||||
if (n <= 0) return StatusCodes.QTL_ERR_INVALID_LENGTH;
|
||||
try
|
||||
{
|
||||
var hi = Src(high, n);
|
||||
var lo = Src(low, n);
|
||||
var vol = Src(volume, n);
|
||||
var mfiTmp = new double[n];
|
||||
var zoneTmp = new int[n];
|
||||
BwMfi.Batch(hi, lo, vol, mfiTmp.AsSpan(), zoneTmp.AsSpan());
|
||||
mfiTmp.AsSpan().CopyTo(Dst(mfiOutput, n));
|
||||
var zoneDst = Dst(zoneOutput, n);
|
||||
for (int i = 0; i < n; i++)
|
||||
{
|
||||
zoneDst[i] = zoneTmp[i];
|
||||
}
|
||||
return StatusCodes.QTL_OK;
|
||||
}
|
||||
catch { return StatusCodes.QTL_ERR_INTERNAL; }
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly(EntryPoint = "qtl_dstoch")]
|
||||
public static int QtlDstoch(double* high, double* low, double* close, double* output, int n, int period)
|
||||
{
|
||||
if (high == null || low == null || close == null || output == null) return StatusCodes.QTL_ERR_NULL_PTR;
|
||||
if (n <= 0) return StatusCodes.QTL_ERR_INVALID_LENGTH;
|
||||
if (period <= 0) return StatusCodes.QTL_ERR_INVALID_PARAM;
|
||||
try
|
||||
{
|
||||
Dstoch.Batch(Src(high, n), Src(low, n), Src(close, n), Dst(output, n), period);
|
||||
return StatusCodes.QTL_OK;
|
||||
}
|
||||
catch { return StatusCodes.QTL_ERR_INTERNAL; }
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly(EntryPoint = "qtl_cci")]
|
||||
public static int QtlCci(double* sourceOpen, double* sourceHigh, double* sourceLow, double* sourceClose, double* sourceVolume, int period, int n, double* dst)
|
||||
{
|
||||
@@ -2848,6 +2900,19 @@ public static unsafe partial class Exports
|
||||
catch { return StatusCodes.QTL_ERR_INTERNAL; }
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly(EntryPoint = "qtl_squeeze_pro")]
|
||||
public static int QtlSqueezePro(double* high, double* low, double* close, double* momOut, double* sqOut, int n, int period, double bbMult, double kcMultWide, double kcMultNormal, double kcMultNarrow, int momLength, int momSmooth, int useSma)
|
||||
{
|
||||
if (high == null || low == null || close == null || momOut == null || sqOut == null) return StatusCodes.QTL_ERR_NULL_PTR;
|
||||
if (n <= 0) return StatusCodes.QTL_ERR_INVALID_LENGTH;
|
||||
try
|
||||
{
|
||||
SqueezePro.Batch(Src(high, n), Src(low, n), Src(close, n), Dst(momOut, n), Dst(sqOut, n), period, bbMult, kcMultWide, kcMultNormal, kcMultNarrow, momLength, momSmooth, useSma != 0);
|
||||
return StatusCodes.QTL_OK;
|
||||
}
|
||||
catch { return StatusCodes.QTL_ERR_INTERNAL; }
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly(EntryPoint = "qtl_ssf2")]
|
||||
public static int QtlSsf2(double* source, double* output, int n, int period)
|
||||
{
|
||||
@@ -3385,6 +3450,20 @@ public static unsafe partial class Exports
|
||||
catch { return StatusCodes.QTL_ERR_INTERNAL; }
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly(EntryPoint = "qtl_vstop")]
|
||||
public static int QtlVstop(double* high, double* low, double* close, double* output, int n, int period, double multiplier)
|
||||
{
|
||||
if (high == null || low == null || close == null || output == null) return StatusCodes.QTL_ERR_NULL_PTR;
|
||||
if (n <= 0) return StatusCodes.QTL_ERR_INVALID_LENGTH;
|
||||
if (period <= 0) return StatusCodes.QTL_ERR_INVALID_PARAM;
|
||||
try
|
||||
{
|
||||
Vstop.Batch(Src(high, n), Src(low, n), Src(close, n), Dst(output, n), period, multiplier);
|
||||
return StatusCodes.QTL_OK;
|
||||
}
|
||||
catch { return StatusCodes.QTL_ERR_INTERNAL; }
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly(EntryPoint = "qtl_vov")]
|
||||
public static int QtlVov(double* source, double* output, int n, int volatilityPeriod, int vovPeriod)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user