mirror of
https://github.com/mihakralj/QuanTAlib.git
synced 2026-08-21 03:58:04 +00:00
[CodeFactor] Apply fixes to commit 9697fac
This commit is contained in:
@@ -223,7 +223,7 @@ public sealed class Bbands : AbstractBase
|
|||||||
|
|
||||||
for (int i = 0; i < source.Length; i++)
|
for (int i = 0; i < source.Length; i++)
|
||||||
{
|
{
|
||||||
Update(new TValue(startTime + i * step.Value, source[i]), isNew: true);
|
Update(new TValue(startTime + (i * step.Value), source[i]), isNew: true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -367,5 +367,4 @@ public sealed class Bbands : AbstractBase
|
|||||||
TSeries results = indicator.Update(source);
|
TSeries results = indicator.Update(source);
|
||||||
return (results, indicator);
|
return (results, indicator);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ public sealed class JbandsIndicator : Indicator, IWatchlistIndicator
|
|||||||
|
|
||||||
private Jbands? _indicator;
|
private Jbands? _indicator;
|
||||||
|
|
||||||
public int MinHistoryDepths => (int)Math.Ceiling(20.0 + 80.0 * Math.Pow(Period, 0.36));
|
public int MinHistoryDepths => (int)Math.Ceiling(20.0 + (80.0 * Math.Pow(Period, 0.36)));
|
||||||
public override string ShortName => $"Jbands({Period},{Phase})";
|
public override string ShortName => $"Jbands({Period},{Phase})";
|
||||||
|
|
||||||
public JbandsIndicator()
|
public JbandsIndicator()
|
||||||
|
|||||||
@@ -99,7 +99,7 @@ public sealed class Jbands : ITValuePublisher, IDisposable
|
|||||||
_logLengthDivider = Math.Log(Math.Max(_lengthDivider, 1e-12));
|
_logLengthDivider = Math.Log(Math.Max(_lengthDivider, 1e-12));
|
||||||
_logSqrtDivider = Math.Log(Math.Max(sqrtDivider, 1e-12));
|
_logSqrtDivider = Math.Log(Math.Max(sqrtDivider, 1e-12));
|
||||||
|
|
||||||
WarmupPeriod = (int)Math.Ceiling(20.0 + 80.0 * Math.Pow(period, 0.36));
|
WarmupPeriod = (int)Math.Ceiling(20.0 + (80.0 * Math.Pow(period, 0.36)));
|
||||||
|
|
||||||
_handler = Handle;
|
_handler = Handle;
|
||||||
Name = $"Jbands({period},{phase})";
|
Name = $"Jbands({period},{phase})";
|
||||||
|
|||||||
@@ -197,7 +197,7 @@ public sealed class Kchannel : ITValuePublisher
|
|||||||
double trueRange = Math.Max(tr1, Math.Max(tr2, tr3));
|
double trueRange = Math.Max(tr1, Math.Max(tr2, tr3));
|
||||||
|
|
||||||
// ATR using RMA with warmup compensation
|
// ATR using RMA with warmup compensation
|
||||||
double newRawRma = (_state.RawRma * (_period - 1) + trueRange) / _period;
|
double newRawRma = ((_state.RawRma * (_period - 1)) + trueRange) / _period;
|
||||||
double newE = (1.0 - _atrAlpha) * _state.E;
|
double newE = (1.0 - _atrAlpha) * _state.E;
|
||||||
double atrValue = newE > Epsilon ? newRawRma / (1.0 - newE) : newRawRma;
|
double atrValue = newE > Epsilon ? newRawRma / (1.0 - newE) : newRawRma;
|
||||||
|
|
||||||
@@ -360,7 +360,7 @@ public sealed class Kchannel : ITValuePublisher
|
|||||||
double tr = Math.Max(tr1, Math.Max(tr2, tr3));
|
double tr = Math.Max(tr1, Math.Max(tr2, tr3));
|
||||||
|
|
||||||
// ATR (RMA with warmup)
|
// ATR (RMA with warmup)
|
||||||
rawRma = (rawRma * (period - 1) + tr) / period;
|
rawRma = ((rawRma * (period - 1)) + tr) / period;
|
||||||
e = (1.0 - atrAlpha) * e;
|
e = (1.0 - atrAlpha) * e;
|
||||||
double atr = e > Epsilon ? rawRma / (1.0 - e) : rawRma;
|
double atr = e > Epsilon ? rawRma / (1.0 - e) : rawRma;
|
||||||
|
|
||||||
|
|||||||
@@ -192,7 +192,7 @@ public sealed class Starchannel : ITValuePublisher
|
|||||||
double trueRange = Math.Max(tr1, Math.Max(tr2, tr3));
|
double trueRange = Math.Max(tr1, Math.Max(tr2, tr3));
|
||||||
|
|
||||||
// ATR using RMA with warmup compensation (uses _atrPeriod for separate ATR smoothing)
|
// ATR using RMA with warmup compensation (uses _atrPeriod for separate ATR smoothing)
|
||||||
double newRawRma = (_state.RawRma * (_atrPeriod - 1) + trueRange) / _atrPeriod;
|
double newRawRma = ((_state.RawRma * (_atrPeriod - 1)) + trueRange) / _atrPeriod;
|
||||||
double newE = (1.0 - _atrAlpha) * _state.E;
|
double newE = (1.0 - _atrAlpha) * _state.E;
|
||||||
double atrValue = newE > Epsilon ? newRawRma / (1.0 - newE) : newRawRma;
|
double atrValue = newE > Epsilon ? newRawRma / (1.0 - newE) : newRawRma;
|
||||||
|
|
||||||
@@ -406,7 +406,7 @@ public sealed class Starchannel : ITValuePublisher
|
|||||||
double tr = Math.Max(tr1, Math.Max(tr2, tr3));
|
double tr = Math.Max(tr1, Math.Max(tr2, tr3));
|
||||||
|
|
||||||
// ATR (RMA with warmup compensation, uses effectiveAtrPeriod)
|
// ATR (RMA with warmup compensation, uses effectiveAtrPeriod)
|
||||||
rawRma = (rawRma * (effectiveAtrPeriod - 1) + tr) / effectiveAtrPeriod;
|
rawRma = ((rawRma * (effectiveAtrPeriod - 1)) + tr) / effectiveAtrPeriod;
|
||||||
e = (1.0 - atrAlpha) * e;
|
e = (1.0 - atrAlpha) * e;
|
||||||
double atr = e > Epsilon ? rawRma / (1.0 - e) : rawRma;
|
double atr = e > Epsilon ? rawRma / (1.0 - e) : rawRma;
|
||||||
|
|
||||||
|
|||||||
@@ -279,7 +279,7 @@ public sealed class Stbands : AbstractBase
|
|||||||
for (int i = 0; i < source.Length; i++)
|
for (int i = 0; i < source.Length; i++)
|
||||||
{
|
{
|
||||||
// Treat as close price only
|
// Treat as close price only
|
||||||
Update(new TValue(startTime + i * step.Value, source[i]), isNew: true);
|
Update(new TValue(startTime + (i * step.Value), source[i]), isNew: true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -406,5 +406,4 @@ public sealed class Stbands : AbstractBase
|
|||||||
TSeries results = indicator.Update(source);
|
TSeries results = indicator.Update(source);
|
||||||
return (results, indicator);
|
return (results, indicator);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -136,9 +136,9 @@ public sealed class TtmLrc : ITValuePublisher
|
|||||||
// sumX = 0 + 1 + ... + (n-1) = n(n-1)/2
|
// sumX = 0 + 1 + ... + (n-1) = n(n-1)/2
|
||||||
_sumX = 0.5 * period * (period - 1);
|
_sumX = 0.5 * period * (period - 1);
|
||||||
// sumX² = 0² + 1² + ... + (n-1)² = (n-1)n(2n-1)/6
|
// sumX² = 0² + 1² + ... + (n-1)² = (n-1)n(2n-1)/6
|
||||||
double sumX2 = (period - 1.0) * period * (2.0 * period - 1.0) / 6.0;
|
double sumX2 = (period - 1.0) * period * ((2.0 * period) - 1.0) / 6.0;
|
||||||
// denominator = n * sumX² - sumX²
|
// denominator = n * sumX² - sumX²
|
||||||
_denominator = period * sumX2 - _sumX * _sumX;
|
_denominator = (period * sumX2) - (_sumX * _sumX);
|
||||||
|
|
||||||
Reset();
|
Reset();
|
||||||
}
|
}
|
||||||
@@ -253,8 +253,8 @@ public sealed class TtmLrc : ITValuePublisher
|
|||||||
if (count < _period)
|
if (count < _period)
|
||||||
{
|
{
|
||||||
sx = 0.5 * n * (n - 1);
|
sx = 0.5 * n * (n - 1);
|
||||||
double sx2 = (n - 1.0) * n * (2.0 * n - 1.0) / 6.0;
|
double sx2 = (n - 1.0) * n * ((2.0 * n) - 1.0) / 6.0;
|
||||||
denom = n * sx2 - sx * sx;
|
denom = (n * sx2) - (sx * sx);
|
||||||
}
|
}
|
||||||
|
|
||||||
double slope, intercept, regression;
|
double slope, intercept, regression;
|
||||||
@@ -267,8 +267,8 @@ public sealed class TtmLrc : ITValuePublisher
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
slope = (n * sumXY - sx * sumY) / denom;
|
slope = ((n * sumXY) - (sx * sumY)) / denom;
|
||||||
intercept = (sumY - slope * sx) / n;
|
intercept = (sumY - (slope * sx)) / n;
|
||||||
// Regression value at current point (x = count - 1)
|
// Regression value at current point (x = count - 1)
|
||||||
regression = Math.FusedMultiplyAdd(slope, count - 1, intercept);
|
regression = Math.FusedMultiplyAdd(slope, count - 1, intercept);
|
||||||
}
|
}
|
||||||
@@ -304,8 +304,8 @@ public sealed class TtmLrc : ITValuePublisher
|
|||||||
Midline = new TValue(input.Time, regression);
|
Midline = new TValue(input.Time, regression);
|
||||||
Upper1 = new TValue(input.Time, regression + stdDev);
|
Upper1 = new TValue(input.Time, regression + stdDev);
|
||||||
Lower1 = new TValue(input.Time, regression - stdDev);
|
Lower1 = new TValue(input.Time, regression - stdDev);
|
||||||
Upper2 = new TValue(input.Time, regression + 2.0 * stdDev);
|
Upper2 = new TValue(input.Time, regression + (2.0 * stdDev));
|
||||||
Lower2 = new TValue(input.Time, regression - 2.0 * stdDev);
|
Lower2 = new TValue(input.Time, regression - (2.0 * stdDev));
|
||||||
|
|
||||||
PubEvent(Midline, isNew);
|
PubEvent(Midline, isNew);
|
||||||
return Midline;
|
return Midline;
|
||||||
@@ -412,8 +412,8 @@ public sealed class TtmLrc : ITValuePublisher
|
|||||||
|
|
||||||
// Precompute constants for full period
|
// Precompute constants for full period
|
||||||
double sumXFull = 0.5 * period * (period - 1);
|
double sumXFull = 0.5 * period * (period - 1);
|
||||||
double sumX2Full = (period - 1.0) * period * (2.0 * period - 1.0) / 6.0;
|
double sumX2Full = (period - 1.0) * period * ((2.0 * period) - 1.0) / 6.0;
|
||||||
double denomFull = period * sumX2Full - sumXFull * sumXFull;
|
double denomFull = (period * sumX2Full) - (sumXFull * sumXFull);
|
||||||
|
|
||||||
// Track last valid value for NaN substitution
|
// Track last valid value for NaN substitution
|
||||||
double lastValid = double.NaN;
|
double lastValid = double.NaN;
|
||||||
@@ -483,8 +483,8 @@ public sealed class TtmLrc : ITValuePublisher
|
|||||||
if (count < period)
|
if (count < period)
|
||||||
{
|
{
|
||||||
sx = 0.5 * n * (n - 1);
|
sx = 0.5 * n * (n - 1);
|
||||||
double sx2 = (n - 1.0) * n * (2.0 * n - 1.0) / 6.0;
|
double sx2 = (n - 1.0) * n * ((2.0 * n) - 1.0) / 6.0;
|
||||||
denom = n * sx2 - sx * sx;
|
denom = (n * sx2) - (sx * sx);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -502,8 +502,8 @@ public sealed class TtmLrc : ITValuePublisher
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
slope = (n * sumXY - sx * sumY) / denom;
|
slope = ((n * sumXY) - (sx * sumY)) / denom;
|
||||||
intercept = (sumY - slope * sx) / n;
|
intercept = (sumY - (slope * sx)) / n;
|
||||||
regression = Math.FusedMultiplyAdd(slope, count - 1, intercept);
|
regression = Math.FusedMultiplyAdd(slope, count - 1, intercept);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -533,8 +533,8 @@ public sealed class TtmLrc : ITValuePublisher
|
|||||||
midline[i] = regression;
|
midline[i] = regression;
|
||||||
upper1[i] = regression + stdDev;
|
upper1[i] = regression + stdDev;
|
||||||
lower1[i] = regression - stdDev;
|
lower1[i] = regression - stdDev;
|
||||||
upper2[i] = regression + 2.0 * stdDev;
|
upper2[i] = regression + (2.0 * stdDev);
|
||||||
lower2[i] = regression - 2.0 * stdDev;
|
lower2[i] = regression - (2.0 * stdDev);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -100,7 +100,7 @@ public sealed class Ubands : AbstractBase
|
|||||||
|
|
||||||
// Precompute coefficients for FMA optimization
|
// Precompute coefficients for FMA optimization
|
||||||
_k0 = 1.0 - c1; // coefficient for val
|
_k0 = 1.0 - c1; // coefficient for val
|
||||||
_k1 = 2.0 * c1 - _c2; // coefficient for PrevInput1
|
_k1 = (2.0 * c1) - _c2; // coefficient for PrevInput1
|
||||||
_k2 = -(c1 + _c3); // coefficient for PrevInput2
|
_k2 = -(c1 + _c3); // coefficient for PrevInput2
|
||||||
|
|
||||||
WarmupPeriod = period;
|
WarmupPeriod = period;
|
||||||
@@ -261,7 +261,7 @@ public sealed class Ubands : AbstractBase
|
|||||||
|
|
||||||
for (int i = 0; i < source.Length; i++)
|
for (int i = 0; i < source.Length; i++)
|
||||||
{
|
{
|
||||||
Update(new TValue(startTime + i * step.Value, source[i]), isNew: true);
|
Update(new TValue(startTime + (i * step.Value), source[i]), isNew: true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -316,7 +316,7 @@ public sealed class Ubands : AbstractBase
|
|||||||
double c1 = (1.0 + c2 - c3) / 4.0;
|
double c1 = (1.0 + c2 - c3) / 4.0;
|
||||||
|
|
||||||
double k0 = 1.0 - c1;
|
double k0 = 1.0 - c1;
|
||||||
double k1 = 2.0 * c1 - c2;
|
double k1 = (2.0 * c1) - c2;
|
||||||
double k2 = -(c1 + c3);
|
double k2 = -(c1 + c3);
|
||||||
|
|
||||||
// Use stackalloc for residual buffer if small enough
|
// Use stackalloc for residual buffer if small enough
|
||||||
@@ -404,5 +404,4 @@ public sealed class Ubands : AbstractBase
|
|||||||
TSeries results = indicator.Update(source);
|
TSeries results = indicator.Update(source);
|
||||||
return (results, indicator);
|
return (results, indicator);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -217,7 +217,7 @@ public sealed class Uchannel : AbstractBase
|
|||||||
{
|
{
|
||||||
// USF: (1-c1)*s0 + (2*c1-c2)*s1 - (c1+c3)*s2 + c2*usf1 + c3*usf2
|
// USF: (1-c1)*s0 + (2*c1-c2)*s1 - (c1+c3)*s2 + c2*usf1 + c3*usf2
|
||||||
strValue = Math.FusedMultiplyAdd(1 - _c1_str, str_s0,
|
strValue = Math.FusedMultiplyAdd(1 - _c1_str, str_s0,
|
||||||
Math.FusedMultiplyAdd(2 * _c1_str - _c2_str, str_s1,
|
Math.FusedMultiplyAdd((2 * _c1_str) - _c2_str, str_s1,
|
||||||
Math.FusedMultiplyAdd(-(_c1_str + _c3_str), str_s2,
|
Math.FusedMultiplyAdd(-(_c1_str + _c3_str), str_s2,
|
||||||
Math.FusedMultiplyAdd(_c2_str, usStr1, _c3_str * usStr2))));
|
Math.FusedMultiplyAdd(_c2_str, usStr1, _c3_str * usStr2))));
|
||||||
}
|
}
|
||||||
@@ -237,7 +237,7 @@ public sealed class Uchannel : AbstractBase
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
cenValue = Math.FusedMultiplyAdd(1 - _c1_cen, cen_s0,
|
cenValue = Math.FusedMultiplyAdd(1 - _c1_cen, cen_s0,
|
||||||
Math.FusedMultiplyAdd(2 * _c1_cen - _c2_cen, cen_s1,
|
Math.FusedMultiplyAdd((2 * _c1_cen) - _c2_cen, cen_s1,
|
||||||
Math.FusedMultiplyAdd(-(_c1_cen + _c3_cen), cen_s2,
|
Math.FusedMultiplyAdd(-(_c1_cen + _c3_cen), cen_s2,
|
||||||
Math.FusedMultiplyAdd(_c2_cen, usCen1, _c3_cen * usCen2))));
|
Math.FusedMultiplyAdd(_c2_cen, usCen1, _c3_cen * usCen2))));
|
||||||
}
|
}
|
||||||
@@ -337,7 +337,7 @@ public sealed class Uchannel : AbstractBase
|
|||||||
for (int i = 0; i < source.Length; i++)
|
for (int i = 0; i < source.Length; i++)
|
||||||
{
|
{
|
||||||
// Treat as close price only
|
// Treat as close price only
|
||||||
Update(new TValue(startTime + i * step.Value, source[i]), isNew: true);
|
Update(new TValue(startTime + (i * step.Value), source[i]), isNew: true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -471,7 +471,7 @@ public sealed class Uchannel : AbstractBase
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
strValue = Math.FusedMultiplyAdd(1 - c1_str, str_s0,
|
strValue = Math.FusedMultiplyAdd(1 - c1_str, str_s0,
|
||||||
Math.FusedMultiplyAdd(2 * c1_str - c2_str, str_s1,
|
Math.FusedMultiplyAdd((2 * c1_str) - c2_str, str_s1,
|
||||||
Math.FusedMultiplyAdd(-(c1_str + c3_str), str_s2,
|
Math.FusedMultiplyAdd(-(c1_str + c3_str), str_s2,
|
||||||
Math.FusedMultiplyAdd(c2_str, usStr1, c3_str * usStr2))));
|
Math.FusedMultiplyAdd(c2_str, usStr1, c3_str * usStr2))));
|
||||||
}
|
}
|
||||||
@@ -489,7 +489,7 @@ public sealed class Uchannel : AbstractBase
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
cenValue = Math.FusedMultiplyAdd(1 - c1_cen, cen_s0,
|
cenValue = Math.FusedMultiplyAdd(1 - c1_cen, cen_s0,
|
||||||
Math.FusedMultiplyAdd(2 * c1_cen - c2_cen, cen_s1,
|
Math.FusedMultiplyAdd((2 * c1_cen) - c2_cen, cen_s1,
|
||||||
Math.FusedMultiplyAdd(-(c1_cen + c3_cen), cen_s2,
|
Math.FusedMultiplyAdd(-(c1_cen + c3_cen), cen_s2,
|
||||||
Math.FusedMultiplyAdd(c2_cen, usCen1, c3_cen * usCen2))));
|
Math.FusedMultiplyAdd(c2_cen, usCen1, c3_cen * usCen2))));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -206,9 +206,9 @@ public sealed class Vwapbands : AbstractBase
|
|||||||
{
|
{
|
||||||
_state = _state with
|
_state = _state with
|
||||||
{
|
{
|
||||||
SumPV = _state.SumPV + price * vol,
|
SumPV = _state.SumPV + (price * vol),
|
||||||
SumVol = _state.SumVol + vol,
|
SumVol = _state.SumVol + vol,
|
||||||
SumPV2 = _state.SumPV2 + price * price * vol,
|
SumPV2 = _state.SumPV2 + (price * price * vol),
|
||||||
Count = _state.Count + 1
|
Count = _state.Count + 1
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -228,10 +228,10 @@ public sealed class Vwapbands : AbstractBase
|
|||||||
double stdev = Math.Sqrt(variance);
|
double stdev = Math.Sqrt(variance);
|
||||||
|
|
||||||
// Calculate bands
|
// Calculate bands
|
||||||
double upper1 = vwap + _multiplier * stdev;
|
double upper1 = vwap + (_multiplier * stdev);
|
||||||
double lower1 = vwap - _multiplier * stdev;
|
double lower1 = vwap - (_multiplier * stdev);
|
||||||
double upper2 = vwap + 2.0 * _multiplier * stdev;
|
double upper2 = vwap + (2.0 * _multiplier * stdev);
|
||||||
double lower2 = vwap - 2.0 * _multiplier * stdev;
|
double lower2 = vwap - (2.0 * _multiplier * stdev);
|
||||||
|
|
||||||
// Update output values
|
// Update output values
|
||||||
Vwap = new TValue(input.Time, vwap);
|
Vwap = new TValue(input.Time, vwap);
|
||||||
@@ -316,7 +316,7 @@ public sealed class Vwapbands : AbstractBase
|
|||||||
|
|
||||||
for (int i = 0; i < source.Length; i++)
|
for (int i = 0; i < source.Length; i++)
|
||||||
{
|
{
|
||||||
Update(new TValue(startTime + i * step.Value, source[i]), 1.0, isNew: true, reset: false);
|
Update(new TValue(startTime + (i * step.Value), source[i]), 1.0, isNew: true, reset: false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -423,10 +423,10 @@ public sealed class Vwapbands : AbstractBase
|
|||||||
|
|
||||||
vwap[i] = vwapVal;
|
vwap[i] = vwapVal;
|
||||||
stdDev[i] = stdev;
|
stdDev[i] = stdev;
|
||||||
upper1[i] = vwapVal + multiplier * stdev;
|
upper1[i] = vwapVal + (multiplier * stdev);
|
||||||
lower1[i] = vwapVal - multiplier * stdev;
|
lower1[i] = vwapVal - (multiplier * stdev);
|
||||||
upper2[i] = vwapVal + 2.0 * multiplier * stdev;
|
upper2[i] = vwapVal + (2.0 * multiplier * stdev);
|
||||||
lower2[i] = vwapVal - 2.0 * multiplier * stdev;
|
lower2[i] = vwapVal - (2.0 * multiplier * stdev);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -200,9 +200,9 @@ public sealed class Vwapsd : AbstractBase
|
|||||||
{
|
{
|
||||||
_state = _state with
|
_state = _state with
|
||||||
{
|
{
|
||||||
SumPV = _state.SumPV + price * vol,
|
SumPV = _state.SumPV + (price * vol),
|
||||||
SumVol = _state.SumVol + vol,
|
SumVol = _state.SumVol + vol,
|
||||||
SumPV2 = _state.SumPV2 + price * price * vol,
|
SumPV2 = _state.SumPV2 + (price * price * vol),
|
||||||
Count = _state.Count + 1
|
Count = _state.Count + 1
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -222,8 +222,8 @@ public sealed class Vwapsd : AbstractBase
|
|||||||
double stdev = Math.Sqrt(variance);
|
double stdev = Math.Sqrt(variance);
|
||||||
|
|
||||||
// Calculate bands
|
// Calculate bands
|
||||||
double upper = vwap + _numDevs * stdev;
|
double upper = vwap + (_numDevs * stdev);
|
||||||
double lower = vwap - _numDevs * stdev;
|
double lower = vwap - (_numDevs * stdev);
|
||||||
|
|
||||||
// Update output values
|
// Update output values
|
||||||
Vwap = new TValue(input.Time, vwap);
|
Vwap = new TValue(input.Time, vwap);
|
||||||
@@ -302,7 +302,7 @@ public sealed class Vwapsd : AbstractBase
|
|||||||
|
|
||||||
for (int i = 0; i < source.Length; i++)
|
for (int i = 0; i < source.Length; i++)
|
||||||
{
|
{
|
||||||
Update(new TValue(startTime + i * step.Value, source[i]), 1.0, isNew: true, reset: false);
|
Update(new TValue(startTime + (i * step.Value), source[i]), 1.0, isNew: true, reset: false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -405,8 +405,8 @@ public sealed class Vwapsd : AbstractBase
|
|||||||
|
|
||||||
vwap[i] = vwapVal;
|
vwap[i] = vwapVal;
|
||||||
stdDev[i] = stdev;
|
stdDev[i] = stdev;
|
||||||
upper[i] = vwapVal + numDevs * stdev;
|
upper[i] = vwapVal + (numDevs * stdev);
|
||||||
lower[i] = vwapVal - numDevs * stdev;
|
lower[i] = vwapVal - (numDevs * stdev);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ using System.Buffers;
|
|||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
|
||||||
namespace QuanTAlib;
|
namespace QuanTAlib;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -433,7 +433,7 @@ public static class ErrorHelpers
|
|||||||
double diff = act - pred;
|
double diff = act - pred;
|
||||||
double ratio = diff / delta;
|
double ratio = diff / delta;
|
||||||
// δ² * (√(1 + (error/δ)²) - 1)
|
// δ² * (√(1 + (error/δ)²) - 1)
|
||||||
output[i] = deltaSquared * (Math.Sqrt(1.0 + ratio * ratio) - 1.0);
|
output[i] = deltaSquared * (Math.Sqrt(1.0 + (ratio * ratio)) - 1.0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ public sealed class Ccyc : AbstractBase
|
|||||||
throw new ArgumentException("Alpha must be between 0 and 1 (exclusive).", nameof(alpha));
|
throw new ArgumentException("Alpha must be between 0 and 1 (exclusive).", nameof(alpha));
|
||||||
}
|
}
|
||||||
|
|
||||||
double halfAlpha = 1.0 - 0.5 * alpha;
|
double halfAlpha = 1.0 - (0.5 * alpha);
|
||||||
_chp = halfAlpha * halfAlpha;
|
_chp = halfAlpha * halfAlpha;
|
||||||
double oneMinusAlpha = 1.0 - alpha;
|
double oneMinusAlpha = 1.0 - alpha;
|
||||||
_cfb1 = 2.0 * oneMinusAlpha;
|
_cfb1 = 2.0 * oneMinusAlpha;
|
||||||
@@ -125,7 +125,7 @@ public sealed class Ccyc : AbstractBase
|
|||||||
double price0 = price;
|
double price0 = price;
|
||||||
|
|
||||||
// 4-tap FIR smoother: smooth = (x + 2*x1 + 2*x2 + x3) / 6
|
// 4-tap FIR smoother: smooth = (x + 2*x1 + 2*x2 + x3) / 6
|
||||||
double smooth = (price0 + 2.0 * price1 + 2.0 * price2 + price3) / 6.0;
|
double smooth = (price0 + (2.0 * price1) + (2.0 * price2) + price3) / 6.0;
|
||||||
|
|
||||||
// Shift smooth history
|
// Shift smooth history
|
||||||
double smooth2 = s.Smooth1;
|
double smooth2 = s.Smooth1;
|
||||||
@@ -136,13 +136,13 @@ public sealed class Ccyc : AbstractBase
|
|||||||
if (count < 7)
|
if (count < 7)
|
||||||
{
|
{
|
||||||
// Bootstrap: second-difference of raw price
|
// Bootstrap: second-difference of raw price
|
||||||
cycle = (price0 - 2.0 * price1 + price2) * 0.25;
|
cycle = (price0 - (2.0 * price1) + price2) * 0.25;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Steady-state: 2-pole high-pass IIR on smoothed input
|
// Steady-state: 2-pole high-pass IIR on smoothed input
|
||||||
// cycle = c_hp * (smooth - 2*smooth1 + smooth2) + c_fb1*cycle1 + c_fb2*cycle2
|
// cycle = c_hp * (smooth - 2*smooth1 + smooth2) + c_fb1*cycle1 + c_fb2*cycle2
|
||||||
double diff = smooth0 - 2.0 * smooth1 + smooth2;
|
double diff = smooth0 - (2.0 * smooth1) + smooth2;
|
||||||
cycle = Math.FusedMultiplyAdd(_chp, diff,
|
cycle = Math.FusedMultiplyAdd(_chp, diff,
|
||||||
Math.FusedMultiplyAdd(_cfb1, s.Cycle1, _cfb2 * s.Cycle2));
|
Math.FusedMultiplyAdd(_cfb1, s.Cycle1, _cfb2 * s.Cycle2));
|
||||||
}
|
}
|
||||||
@@ -240,7 +240,7 @@ public sealed class Ccyc : AbstractBase
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
double halfAlpha = 1.0 - 0.5 * alpha;
|
double halfAlpha = 1.0 - (0.5 * alpha);
|
||||||
double chp = halfAlpha * halfAlpha;
|
double chp = halfAlpha * halfAlpha;
|
||||||
double oneMinusAlpha = 1.0 - alpha;
|
double oneMinusAlpha = 1.0 - alpha;
|
||||||
double cfb1 = 2.0 * oneMinusAlpha;
|
double cfb1 = 2.0 * oneMinusAlpha;
|
||||||
@@ -263,7 +263,7 @@ public sealed class Ccyc : AbstractBase
|
|||||||
price1 = price0;
|
price1 = price0;
|
||||||
price0 = val;
|
price0 = val;
|
||||||
|
|
||||||
double smooth = (price0 + 2.0 * price1 + 2.0 * price2 + price3) / 6.0;
|
double smooth = (price0 + (2.0 * price1) + (2.0 * price2) + price3) / 6.0;
|
||||||
smooth2 = smooth1;
|
smooth2 = smooth1;
|
||||||
smooth1 = smooth0;
|
smooth1 = smooth0;
|
||||||
smooth0 = smooth;
|
smooth0 = smooth;
|
||||||
@@ -272,11 +272,11 @@ public sealed class Ccyc : AbstractBase
|
|||||||
int barNum = i + 1;
|
int barNum = i + 1;
|
||||||
if (barNum < 7)
|
if (barNum < 7)
|
||||||
{
|
{
|
||||||
cycle = (price0 - 2.0 * price1 + price2) * 0.25;
|
cycle = (price0 - (2.0 * price1) + price2) * 0.25;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
double diff = smooth0 - 2.0 * smooth1 + smooth2;
|
double diff = smooth0 - (2.0 * smooth1) + smooth2;
|
||||||
cycle = Math.FusedMultiplyAdd(chp, diff,
|
cycle = Math.FusedMultiplyAdd(chp, diff,
|
||||||
Math.FusedMultiplyAdd(cfb1, cycle1, cfb2 * cycle2));
|
Math.FusedMultiplyAdd(cfb1, cycle1, cfb2 * cycle2));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -43,7 +43,6 @@ public sealed class Cg : AbstractBase
|
|||||||
private double _p_weightedSum;
|
private double _p_weightedSum;
|
||||||
private double _p_sum;
|
private double _p_sum;
|
||||||
|
|
||||||
|
|
||||||
public override bool IsHot => _buffer.IsFull;
|
public override bool IsHot => _buffer.IsFull;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -112,7 +111,6 @@ public sealed class Cg : AbstractBase
|
|||||||
// after each update (or track differential updates which is complex)
|
// after each update (or track differential updates which is complex)
|
||||||
RecalculateSums();
|
RecalculateSums();
|
||||||
|
|
||||||
|
|
||||||
// Calculate CG
|
// Calculate CG
|
||||||
double cg = CalculateCg();
|
double cg = CalculateCg();
|
||||||
|
|
||||||
|
|||||||
@@ -185,7 +185,7 @@ public sealed class Ebsw : AbstractBase
|
|||||||
double wave = (filt0 + filt1 + filt2) / 3.0;
|
double wave = (filt0 + filt1 + filt2) / 3.0;
|
||||||
|
|
||||||
// Power: 3-bar average of squared filtered values
|
// Power: 3-bar average of squared filtered values
|
||||||
double pwr = (filt0 * filt0 + filt1 * filt1 + filt2 * filt2) / 3.0;
|
double pwr = ((filt0 * filt0) + (filt1 * filt1) + (filt2 * filt2)) / 3.0;
|
||||||
|
|
||||||
// Automatic gain control: normalize by RMS, clamp to [-1, +1]
|
// Automatic gain control: normalize by RMS, clamp to [-1, +1]
|
||||||
double sineWave = pwr > 0 ? wave / Math.Sqrt(pwr) : 0;
|
double sineWave = pwr > 0 ? wave / Math.Sqrt(pwr) : 0;
|
||||||
@@ -326,7 +326,7 @@ public sealed class Ebsw : AbstractBase
|
|||||||
double wave = (filt0 + filt1 + filt2) / 3.0;
|
double wave = (filt0 + filt1 + filt2) / 3.0;
|
||||||
|
|
||||||
// Power
|
// Power
|
||||||
double pwr = (filt0 * filt0 + filt1 * filt1 + filt2 * filt2) / 3.0;
|
double pwr = ((filt0 * filt0) + (filt1 * filt1) + (filt2 * filt2)) / 3.0;
|
||||||
|
|
||||||
// AGC normalization
|
// AGC normalization
|
||||||
double sineWave = pwr > 0 ? wave / Math.Sqrt(pwr) : 0;
|
double sineWave = pwr > 0 ? wave / Math.Sqrt(pwr) : 0;
|
||||||
|
|||||||
@@ -162,10 +162,10 @@ public sealed class Homod : AbstractBase
|
|||||||
double price0 = price;
|
double price0 = price;
|
||||||
|
|
||||||
// Calculate bandwidth based on smooth period
|
// Calculate bandwidth based on smooth period
|
||||||
double bandwidth = 0.075 * s.SmoothPeriod + 0.54;
|
double bandwidth = (0.075 * s.SmoothPeriod) + 0.54;
|
||||||
|
|
||||||
// 4-bar weighted moving average: (4*p0 + 3*p1 + 2*p2 + p3) / 10
|
// 4-bar weighted moving average: (4*p0 + 3*p1 + 2*p2 + p3) / 10
|
||||||
double smoothPrice = (4.0 * price0 + 3.0 * price1 + 2.0 * price2 + price3) / 10.0;
|
double smoothPrice = ((4.0 * price0) + (3.0 * price1) + (2.0 * price2) + price3) / 10.0;
|
||||||
|
|
||||||
// Shift smooth price history
|
// Shift smooth price history
|
||||||
double sp6 = s.Sp5;
|
double sp6 = s.Sp5;
|
||||||
@@ -177,7 +177,7 @@ public sealed class Homod : AbstractBase
|
|||||||
double sp0 = smoothPrice;
|
double sp0 = smoothPrice;
|
||||||
|
|
||||||
// Hilbert Transform detrender: coefficients [0.0962, 0, 0.5769, 0, -0.5769, 0, -0.0962] * bandwidth
|
// Hilbert Transform detrender: coefficients [0.0962, 0, 0.5769, 0, -0.5769, 0, -0.0962] * bandwidth
|
||||||
double detrender = (0.0962 * sp0 + 0.5769 * sp2 - 0.5769 * sp4 - 0.0962 * sp6) * bandwidth;
|
double detrender = ((0.0962 * sp0) + (0.5769 * sp2) - (0.5769 * sp4) - (0.0962 * sp6)) * bandwidth;
|
||||||
|
|
||||||
// Shift detrender history
|
// Shift detrender history
|
||||||
double det6 = s.Det5;
|
double det6 = s.Det5;
|
||||||
@@ -189,7 +189,7 @@ public sealed class Homod : AbstractBase
|
|||||||
double det0 = detrender;
|
double det0 = detrender;
|
||||||
|
|
||||||
// Q1 via Hilbert Transform of detrender
|
// Q1 via Hilbert Transform of detrender
|
||||||
double q1 = (0.0962 * det0 + 0.5769 * det2 - 0.5769 * det4 - 0.0962 * det6) * bandwidth;
|
double q1 = ((0.0962 * det0) + (0.5769 * det2) - (0.5769 * det4) - (0.0962 * det6)) * bandwidth;
|
||||||
|
|
||||||
// I1 is detrender delayed by 3 bars
|
// I1 is detrender delayed by 3 bars
|
||||||
double i1 = det3;
|
double i1 = det3;
|
||||||
@@ -213,10 +213,10 @@ public sealed class Homod : AbstractBase
|
|||||||
double q1_0 = q1;
|
double q1_0 = q1;
|
||||||
|
|
||||||
// JI = Hilbert Transform of I1
|
// JI = Hilbert Transform of I1
|
||||||
double ji = (0.0962 * i1_0 + 0.5769 * i1_2 - 0.5769 * i1_4 - 0.0962 * i1_6) * bandwidth;
|
double ji = ((0.0962 * i1_0) + (0.5769 * i1_2) - (0.5769 * i1_4) - (0.0962 * i1_6)) * bandwidth;
|
||||||
|
|
||||||
// JQ = Hilbert Transform of Q1
|
// JQ = Hilbert Transform of Q1
|
||||||
double jq = (0.0962 * q1_0 + 0.5769 * q1_2 - 0.5769 * q1_4 - 0.0962 * q1_6) * bandwidth;
|
double jq = ((0.0962 * q1_0) + (0.5769 * q1_2) - (0.5769 * q1_4) - (0.0962 * q1_6)) * bandwidth;
|
||||||
|
|
||||||
// Calculate I2 and Q2 (phasor rotation)
|
// Calculate I2 and Q2 (phasor rotation)
|
||||||
double i2Raw = i1 - jq;
|
double i2Raw = i1 - jq;
|
||||||
|
|||||||
@@ -139,8 +139,8 @@ public sealed class HtDcperiod : AbstractBase
|
|||||||
double input1 = buffer[KEY_Q1];
|
double input1 = buffer[KEY_Q1];
|
||||||
DoHilbertTransform(buffer, KEY_JQ, input1, true, hilbertIdx, adjustedPrevPeriod);
|
DoHilbertTransform(buffer, KEY_JQ, input1, true, hilbertIdx, adjustedPrevPeriod);
|
||||||
|
|
||||||
q2 = 0.2 * (buffer[KEY_Q1] + buffer[KEY_JI]) + 0.8 * prevQ2;
|
q2 = (0.2 * (buffer[KEY_Q1] + buffer[KEY_JI])) + (0.8 * prevQ2);
|
||||||
i2 = 0.2 * (i1ForOddPrev3 - buffer[KEY_JQ]) + 0.8 * prevI2;
|
i2 = (0.2 * (i1ForOddPrev3 - buffer[KEY_JQ])) + (0.8 * prevI2);
|
||||||
|
|
||||||
i1ForEvenPrev3 = i1ForEvenPrev2;
|
i1ForEvenPrev3 = i1ForEvenPrev2;
|
||||||
i1ForEvenPrev2 = buffer[KEY_DETRENDER];
|
i1ForEvenPrev2 = buffer[KEY_DETRENDER];
|
||||||
@@ -164,8 +164,8 @@ public sealed class HtDcperiod : AbstractBase
|
|||||||
hilbertIdx = 0;
|
hilbertIdx = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
q2 = 0.2 * (buffer[KEY_Q1] + buffer[KEY_JI]) + 0.8 * prevQ2;
|
q2 = (0.2 * (buffer[KEY_Q1] + buffer[KEY_JI])) + (0.8 * prevQ2);
|
||||||
i2 = 0.2 * (i1ForEvenPrev3 - buffer[KEY_JQ]) + 0.8 * prevI2;
|
i2 = (0.2 * (i1ForEvenPrev3 - buffer[KEY_JQ])) + (0.8 * prevI2);
|
||||||
|
|
||||||
i1ForOddPrev3 = i1ForOddPrev2;
|
i1ForOddPrev3 = i1ForOddPrev2;
|
||||||
i1ForOddPrev2 = buffer[KEY_DETRENDER];
|
i1ForOddPrev2 = buffer[KEY_DETRENDER];
|
||||||
@@ -289,7 +289,7 @@ public sealed class HtDcperiod : AbstractBase
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Calculate smoothed price using WMA
|
// Calculate smoothed price using WMA
|
||||||
double adjustedPrevPeriod = 0.075 * s.Period + 0.54;
|
double adjustedPrevPeriod = (0.075 * s.Period) + 0.54;
|
||||||
|
|
||||||
s.PeriodWMASub += price;
|
s.PeriodWMASub += price;
|
||||||
s.PeriodWMASub -= s.TrailingWMAValue;
|
s.PeriodWMASub -= s.TrailingWMAValue;
|
||||||
|
|||||||
@@ -142,8 +142,8 @@ public sealed class HtPhasor : AbstractBase
|
|||||||
double input1 = buffer[KEY_Q1];
|
double input1 = buffer[KEY_Q1];
|
||||||
DoHilbertTransform(buffer, KEY_JQ, input1, true, hilbertIdx, adjustedPrevPeriod);
|
DoHilbertTransform(buffer, KEY_JQ, input1, true, hilbertIdx, adjustedPrevPeriod);
|
||||||
|
|
||||||
q2 = 0.2 * (buffer[KEY_Q1] + buffer[KEY_JI]) + 0.8 * prevQ2;
|
q2 = (0.2 * (buffer[KEY_Q1] + buffer[KEY_JI])) + (0.8 * prevQ2);
|
||||||
i2 = 0.2 * (i1ForOddPrev3 - buffer[KEY_JQ]) + 0.8 * prevI2;
|
i2 = (0.2 * (i1ForOddPrev3 - buffer[KEY_JQ])) + (0.8 * prevI2);
|
||||||
|
|
||||||
i1ForEvenPrev3 = i1ForEvenPrev2;
|
i1ForEvenPrev3 = i1ForEvenPrev2;
|
||||||
i1ForEvenPrev2 = buffer[KEY_DETRENDER];
|
i1ForEvenPrev2 = buffer[KEY_DETRENDER];
|
||||||
@@ -167,8 +167,8 @@ public sealed class HtPhasor : AbstractBase
|
|||||||
hilbertIdx = 0;
|
hilbertIdx = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
q2 = 0.2 * (buffer[KEY_Q1] + buffer[KEY_JI]) + 0.8 * prevQ2;
|
q2 = (0.2 * (buffer[KEY_Q1] + buffer[KEY_JI])) + (0.8 * prevQ2);
|
||||||
i2 = 0.2 * (i1ForEvenPrev3 - buffer[KEY_JQ]) + 0.8 * prevI2;
|
i2 = (0.2 * (i1ForEvenPrev3 - buffer[KEY_JQ])) + (0.8 * prevI2);
|
||||||
|
|
||||||
i1ForOddPrev3 = i1ForOddPrev2;
|
i1ForOddPrev3 = i1ForOddPrev2;
|
||||||
i1ForOddPrev2 = buffer[KEY_DETRENDER];
|
i1ForOddPrev2 = buffer[KEY_DETRENDER];
|
||||||
@@ -178,8 +178,8 @@ public sealed class HtPhasor : AbstractBase
|
|||||||
private static void CalcSmoothedPeriod(
|
private static void CalcSmoothedPeriod(
|
||||||
ref double re, double i2, double q2, ref double prevI2, ref double prevQ2, ref double im, ref double period)
|
ref double re, double i2, double q2, ref double prevI2, ref double prevQ2, ref double im, ref double period)
|
||||||
{
|
{
|
||||||
re = Math.FusedMultiplyAdd(0.2, i2 * prevI2 + q2 * prevQ2, 0.8 * re);
|
re = Math.FusedMultiplyAdd(0.2, (i2 * prevI2) + (q2 * prevQ2), 0.8 * re);
|
||||||
im = Math.FusedMultiplyAdd(0.2, i2 * prevQ2 - q2 * prevI2, 0.8 * im);
|
im = Math.FusedMultiplyAdd(0.2, (i2 * prevQ2) - (q2 * prevI2), 0.8 * im);
|
||||||
|
|
||||||
prevQ2 = q2;
|
prevQ2 = q2;
|
||||||
prevI2 = i2;
|
prevI2 = i2;
|
||||||
@@ -228,7 +228,7 @@ public sealed class HtPhasor : AbstractBase
|
|||||||
double p2 = Get(priceHistory, historyIdx, 2);
|
double p2 = Get(priceHistory, historyIdx, 2);
|
||||||
double p3 = Get(priceHistory, historyIdx, 3);
|
double p3 = Get(priceHistory, historyIdx, 3);
|
||||||
|
|
||||||
double smoothedValue = (4.0 * p0 + 3.0 * p1 + 2.0 * p2 + p3) * 0.1;
|
double smoothedValue = ((4.0 * p0) + (3.0 * p1) + (2.0 * p2) + p3) * 0.1;
|
||||||
|
|
||||||
s.PeriodWMASub = p0 + p1 + p2 + p3;
|
s.PeriodWMASub = p0 + p1 + p2 + p3;
|
||||||
s.PeriodWMASum = smoothedValue * 10.0;
|
s.PeriodWMASum = smoothedValue * 10.0;
|
||||||
@@ -306,7 +306,7 @@ public sealed class HtPhasor : AbstractBase
|
|||||||
double prevQ2 = s.PrevQ2;
|
double prevQ2 = s.PrevQ2;
|
||||||
double period = s.Period;
|
double period = s.Period;
|
||||||
|
|
||||||
double adjustedPrevPeriod = 0.075 * period + 0.54;
|
double adjustedPrevPeriod = (0.075 * period) + 0.54;
|
||||||
_smoothPrice[s.SmoothPriceIdx] = smoothedValue;
|
_smoothPrice[s.SmoothPriceIdx] = smoothedValue;
|
||||||
|
|
||||||
double q2, i2;
|
double q2, i2;
|
||||||
|
|||||||
@@ -293,7 +293,6 @@ public sealed class Alligator : ITValuePublisher
|
|||||||
return new TSeries(tList, vList);
|
return new TSeries(tList, vList);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initializes the indicator state using the provided bar series history.
|
/// Initializes the indicator state using the provided bar series history.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -337,7 +336,6 @@ public sealed class Alligator : ITValuePublisher
|
|||||||
return (results, indicator);
|
return (results, indicator);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the Jaw period value.
|
/// Gets the Jaw period value.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -642,5 +642,4 @@ public sealed class Amat : ITValuePublisher, IDisposable
|
|||||||
TSeries results = amat.Update(source);
|
TSeries results = amat.Update(source);
|
||||||
return (results, amat);
|
return (results, amat);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -240,7 +240,6 @@ public sealed class Chop : ITValuePublisher
|
|||||||
return Math.Clamp(chop, 0.0, 100.0);
|
return Math.Clamp(chop, 0.0, 100.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initializes the indicator state using the provided bar series history.
|
/// Initializes the indicator state using the provided bar series history.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -282,5 +281,4 @@ public sealed class Chop : ITValuePublisher
|
|||||||
TSeries results = indicator.Update(source);
|
TSeries results = indicator.Update(source);
|
||||||
return (results, indicator);
|
return (results, indicator);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -52,7 +52,7 @@ public sealed class HtTrendmodeIndicator : Indicator, IWatchlistIndicator
|
|||||||
SourceType.HL2 => (GetPrice(PriceType.High) + GetPrice(PriceType.Low)) / 2,
|
SourceType.HL2 => (GetPrice(PriceType.High) + GetPrice(PriceType.Low)) / 2,
|
||||||
SourceType.HLC3 => (GetPrice(PriceType.High) + GetPrice(PriceType.Low) + GetPrice(PriceType.Close)) / 3,
|
SourceType.HLC3 => (GetPrice(PriceType.High) + GetPrice(PriceType.Low) + GetPrice(PriceType.Close)) / 3,
|
||||||
SourceType.OHLC4 => (GetPrice(PriceType.Open) + GetPrice(PriceType.High) + GetPrice(PriceType.Low) + GetPrice(PriceType.Close)) / 4,
|
SourceType.OHLC4 => (GetPrice(PriceType.Open) + GetPrice(PriceType.High) + GetPrice(PriceType.Low) + GetPrice(PriceType.Close)) / 4,
|
||||||
SourceType.HLCC4 => (GetPrice(PriceType.High) + GetPrice(PriceType.Low) + 2 * GetPrice(PriceType.Close)) / 4,
|
SourceType.HLCC4 => (GetPrice(PriceType.High) + GetPrice(PriceType.Low) + (2 * GetPrice(PriceType.Close))) / 4,
|
||||||
_ => GetPrice(PriceType.Close)
|
_ => GetPrice(PriceType.Close)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -186,8 +186,8 @@ public sealed class HtTrendmode : AbstractBase
|
|||||||
double input1 = buffer[KEY_Q1];
|
double input1 = buffer[KEY_Q1];
|
||||||
DoHilbertTransform(buffer, KEY_JQ, input1, true, hilbertIdx, adjustedPrevPeriod);
|
DoHilbertTransform(buffer, KEY_JQ, input1, true, hilbertIdx, adjustedPrevPeriod);
|
||||||
|
|
||||||
q2 = 0.2 * (buffer[KEY_Q1] + buffer[KEY_JI]) + 0.8 * prevQ2;
|
q2 = (0.2 * (buffer[KEY_Q1] + buffer[KEY_JI])) + (0.8 * prevQ2);
|
||||||
i2 = 0.2 * (i1ForOddPrev3 - buffer[KEY_JQ]) + 0.8 * prevI2;
|
i2 = (0.2 * (i1ForOddPrev3 - buffer[KEY_JQ])) + (0.8 * prevI2);
|
||||||
|
|
||||||
i1ForEvenPrev3 = i1ForEvenPrev2;
|
i1ForEvenPrev3 = i1ForEvenPrev2;
|
||||||
i1ForEvenPrev2 = buffer[KEY_DETRENDER];
|
i1ForEvenPrev2 = buffer[KEY_DETRENDER];
|
||||||
@@ -211,8 +211,8 @@ public sealed class HtTrendmode : AbstractBase
|
|||||||
hilbertIdx = 0;
|
hilbertIdx = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
q2 = 0.2 * (buffer[KEY_Q1] + buffer[KEY_JI]) + 0.8 * prevQ2;
|
q2 = (0.2 * (buffer[KEY_Q1] + buffer[KEY_JI])) + (0.8 * prevQ2);
|
||||||
i2 = 0.2 * (i1ForEvenPrev3 - buffer[KEY_JQ]) + 0.8 * prevI2;
|
i2 = (0.2 * (i1ForEvenPrev3 - buffer[KEY_JQ])) + (0.8 * prevI2);
|
||||||
|
|
||||||
i1ForOddPrev3 = i1ForOddPrev2;
|
i1ForOddPrev3 = i1ForOddPrev2;
|
||||||
i1ForOddPrev2 = buffer[KEY_DETRENDER];
|
i1ForOddPrev2 = buffer[KEY_DETRENDER];
|
||||||
@@ -304,7 +304,7 @@ public sealed class HtTrendmode : AbstractBase
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Calculate smoothed price using WMA
|
// Calculate smoothed price using WMA
|
||||||
double adjustedPrevPeriod = 0.075 * s.Period + 0.54;
|
double adjustedPrevPeriod = (0.075 * s.Period) + 0.54;
|
||||||
|
|
||||||
s.PeriodWMASub += price;
|
s.PeriodWMASub += price;
|
||||||
s.PeriodWMASub -= s.TrailingWMAValue;
|
s.PeriodWMASub -= s.TrailingWMAValue;
|
||||||
@@ -488,7 +488,7 @@ public sealed class HtTrendmode : AbstractBase
|
|||||||
double smaValue = (dcPeriodInt > 0) ? sumPrice / (double)dcPeriodInt : price;
|
double smaValue = (dcPeriodInt > 0) ? sumPrice / (double)dcPeriodInt : price;
|
||||||
|
|
||||||
// WMA smoothing of SMA: (4*current + 3*prev1 + 2*prev2 + prev3) / 10
|
// WMA smoothing of SMA: (4*current + 3*prev1 + 2*prev2 + prev3) / 10
|
||||||
double trendline = (4.0 * smaValue + 3.0 * s.ITrend1 + 2.0 * s.ITrend2 + s.ITrend3) / 10.0;
|
double trendline = ((4.0 * smaValue) + (3.0 * s.ITrend1) + (2.0 * s.ITrend2) + s.ITrend3) / 10.0;
|
||||||
s.ITrend3 = s.ITrend2;
|
s.ITrend3 = s.ITrend2;
|
||||||
s.ITrend2 = s.ITrend1;
|
s.ITrend2 = s.ITrend1;
|
||||||
s.ITrend1 = smaValue;
|
s.ITrend1 = smaValue;
|
||||||
|
|||||||
@@ -234,7 +234,7 @@ public sealed class Pfe : AbstractBase
|
|||||||
_s = default;
|
_s = default;
|
||||||
_ps = default;
|
_ps = default;
|
||||||
|
|
||||||
int warmupLength = Math.Min(source.Length, WarmupPeriod + _smoothPeriod * 3);
|
int warmupLength = Math.Min(source.Length, WarmupPeriod + (_smoothPeriod * 3));
|
||||||
int startIndex = source.Length - warmupLength;
|
int startIndex = source.Length - warmupLength;
|
||||||
|
|
||||||
// Seed LastValidValue
|
// Seed LastValidValue
|
||||||
|
|||||||
@@ -265,7 +265,6 @@ public sealed class Super : ITValuePublisher
|
|||||||
return new TSeries(t, v);
|
return new TSeries(t, v);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initializes the indicator state using the provided bar series history.
|
/// Initializes the indicator state using the provided bar series history.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -392,7 +392,6 @@ public sealed class Vhf : AbstractBase
|
|||||||
prevClose = val;
|
prevClose = val;
|
||||||
hasPrevClose = true;
|
hasPrevClose = true;
|
||||||
|
|
||||||
|
|
||||||
// Calculate VHF
|
// Calculate VHF
|
||||||
if (closeFilled >= closeBufSize && diffFilled >= period)
|
if (closeFilled >= closeBufSize && diffFilled >= period)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -339,5 +339,4 @@ public sealed class Vortex : ITValuePublisher
|
|||||||
TSeries results = indicator.Update(source);
|
TSeries results = indicator.Update(source);
|
||||||
return (results, indicator);
|
return (results, indicator);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ public sealed class PseudoHuber : BiInputIndicatorBase
|
|||||||
{
|
{
|
||||||
double diff = actual - predicted;
|
double diff = actual - predicted;
|
||||||
double ratio = diff / Delta;
|
double ratio = diff / Delta;
|
||||||
double sqrtTerm = Math.Sqrt(1.0 + ratio * ratio);
|
double sqrtTerm = Math.Sqrt(1.0 + (ratio * ratio));
|
||||||
return Math.FusedMultiplyAdd(_deltaSquared, sqrtTerm, -_deltaSquared);
|
return Math.FusedMultiplyAdd(_deltaSquared, sqrtTerm, -_deltaSquared);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -393,7 +393,7 @@ public sealed class CsvFeed : IFeed
|
|||||||
|
|
||||||
while (left < right)
|
while (left < right)
|
||||||
{
|
{
|
||||||
int mid = left + (right - left) / 2;
|
int mid = left + ((right - left) / 2);
|
||||||
|
|
||||||
if (Data[mid].Time < startTime)
|
if (Data[mid].Time < startTime)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -400,7 +400,7 @@ public sealed class ALaguerre : AbstractBase
|
|||||||
s.LastValid = input;
|
s.LastValid = input;
|
||||||
|
|
||||||
// Filt = (L0 + 2*L1 + 2*L2 + L3) / 6
|
// Filt = (L0 + 2*L1 + 2*L2 + L3) / 6
|
||||||
double result = (s.L0 + 2.0 * s.L1 + 2.0 * s.L2 + s.L3) / 6.0;
|
double result = (s.L0 + (2.0 * s.L1) + (2.0 * s.L2) + s.L3) / 6.0;
|
||||||
s.LastResult = result;
|
s.LastResult = result;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -159,7 +159,7 @@ public sealed class Bpf : AbstractBase
|
|||||||
|
|
||||||
// Highpass Filter Step
|
// Highpass Filter Step
|
||||||
// hp = hp_c1 * (val - 2*src1 + src2) + hp_c2 * hp1 + hp_c3 * hp2
|
// hp = hp_c1 * (val - 2*src1 + src2) + hp_c2 * hp1 + hp_c3 * hp2
|
||||||
double term1 = _hpC1 * (val - 2.0 * _state.Src1 + _state.Src2);
|
double term1 = _hpC1 * (val - (2.0 * _state.Src1) + _state.Src2);
|
||||||
double hp = Math.FusedMultiplyAdd(_hpC2, _state.Hp1, Math.FusedMultiplyAdd(_hpC3, _state.Hp2, term1));
|
double hp = Math.FusedMultiplyAdd(_hpC2, _state.Hp1, Math.FusedMultiplyAdd(_hpC3, _state.Hp2, term1));
|
||||||
|
|
||||||
// Lowpass Filter Step (Bandpass output)
|
// Lowpass Filter Step (Bandpass output)
|
||||||
@@ -187,7 +187,6 @@ public sealed class Bpf : AbstractBase
|
|||||||
return indicator.Update(source);
|
return indicator.Update(source);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static void Batch(ReadOnlySpan<double> source, Span<double> output, int lowerPeriod, int upperPeriod)
|
public static void Batch(ReadOnlySpan<double> source, Span<double> output, int lowerPeriod, int upperPeriod)
|
||||||
{
|
{
|
||||||
@@ -240,7 +239,7 @@ public sealed class Bpf : AbstractBase
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Highpass
|
// Highpass
|
||||||
double term1 = hpC1 * (val - 2.0 * src1 + src2);
|
double term1 = hpC1 * (val - (2.0 * src1) + src2);
|
||||||
double hp = Math.FusedMultiplyAdd(hpC2, hp1, Math.FusedMultiplyAdd(hpC3, hp2, term1));
|
double hp = Math.FusedMultiplyAdd(hpC2, hp1, Math.FusedMultiplyAdd(hpC3, hp2, term1));
|
||||||
|
|
||||||
// Lowpass
|
// Lowpass
|
||||||
|
|||||||
@@ -93,7 +93,7 @@ public sealed class Butter2 : AbstractBase
|
|||||||
DateTime baseTime = DateTime.UtcNow;
|
DateTime baseTime = DateTime.UtcNow;
|
||||||
for (int i = 0; i < source.Length; i++)
|
for (int i = 0; i < source.Length; i++)
|
||||||
{
|
{
|
||||||
Update(new TValue(baseTime + interval * i, source[i]));
|
Update(new TValue(baseTime + (interval * i), source[i]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ public sealed class Butter3 : AbstractBase
|
|||||||
double c1 = a1 * a1;
|
double c1 = a1 * a1;
|
||||||
|
|
||||||
coef2 = b1 + c1;
|
coef2 = b1 + c1;
|
||||||
coef3 = -(c1 + b1 * c1);
|
coef3 = -(c1 + (b1 * c1));
|
||||||
coef4 = c1 * c1;
|
coef4 = c1 * c1;
|
||||||
coef1 = (1.0 - b1 + c1) * (1.0 - c1) / 8.0;
|
coef1 = (1.0 - b1 + c1) * (1.0 - c1) / 8.0;
|
||||||
}
|
}
|
||||||
@@ -87,7 +87,7 @@ public sealed class Butter3 : AbstractBase
|
|||||||
DateTime baseTime = DateTime.UtcNow;
|
DateTime baseTime = DateTime.UtcNow;
|
||||||
for (int i = 0; i < source.Length; i++)
|
for (int i = 0; i < source.Length; i++)
|
||||||
{
|
{
|
||||||
Update(new TValue(baseTime + interval * i, source[i]));
|
Update(new TValue(baseTime + (interval * i), source[i]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -117,7 +117,7 @@ public sealed class Butter3 : AbstractBase
|
|||||||
: Math.FusedMultiplyAdd(_coef4, _state.Y3,
|
: Math.FusedMultiplyAdd(_coef4, _state.Y3,
|
||||||
Math.FusedMultiplyAdd(_coef3, _state.Y2,
|
Math.FusedMultiplyAdd(_coef3, _state.Y2,
|
||||||
Math.FusedMultiplyAdd(_coef2, _state.Y1,
|
Math.FusedMultiplyAdd(_coef2, _state.Y1,
|
||||||
_coef1 * (x + 3.0 * _state.X1 + 3.0 * _state.X2 + _state.X3))));
|
_coef1 * (x + (3.0 * _state.X1) + (3.0 * _state.X2) + _state.X3))));
|
||||||
|
|
||||||
// Update state: shift history
|
// Update state: shift history
|
||||||
_state.X3 = _state.X2;
|
_state.X3 = _state.X2;
|
||||||
@@ -203,7 +203,7 @@ public sealed class Butter3 : AbstractBase
|
|||||||
: Math.FusedMultiplyAdd(coef4, y3,
|
: Math.FusedMultiplyAdd(coef4, y3,
|
||||||
Math.FusedMultiplyAdd(coef3, y2,
|
Math.FusedMultiplyAdd(coef3, y2,
|
||||||
Math.FusedMultiplyAdd(coef2, y1,
|
Math.FusedMultiplyAdd(coef2, y1,
|
||||||
coef1 * (x + 3.0 * x1 + 3.0 * x2 + x3))));
|
coef1 * (x + (3.0 * x1) + (3.0 * x2) + x3))));
|
||||||
|
|
||||||
x3 = x2;
|
x3 = x2;
|
||||||
x2 = x1;
|
x2 = x1;
|
||||||
|
|||||||
@@ -226,7 +226,7 @@ public sealed class Cfitz : AbstractBase
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Endpoint correction: b̃ = -0.5*B_0 - Σ B_j
|
// Endpoint correction: b̃ = -0.5*B_0 - Σ B_j
|
||||||
double btilde = -0.5 * _b0 - sumBj;
|
double btilde = (-0.5 * _b0) - sumBj;
|
||||||
weightedSum += btilde * _history[0];
|
weightedSum += btilde * _history[0];
|
||||||
|
|
||||||
return weightedSum;
|
return weightedSum;
|
||||||
@@ -303,7 +303,7 @@ public sealed class Cfitz : AbstractBase
|
|||||||
ws += bWeights[j] * source[j]; // y_{j+1} in 0-index is source[j]
|
ws += bWeights[j] * source[j]; // y_{j+1} in 0-index is source[j]
|
||||||
sBj += bWeights[j];
|
sBj += bWeights[j];
|
||||||
}
|
}
|
||||||
double bt = -0.5 * b0 - sBj;
|
double bt = (-0.5 * b0) - sBj;
|
||||||
ws += bt * source[T - 1];
|
ws += bt * source[T - 1];
|
||||||
output[t] = ws;
|
output[t] = ws;
|
||||||
}
|
}
|
||||||
@@ -317,7 +317,7 @@ public sealed class Cfitz : AbstractBase
|
|||||||
ws += bWeights[j] * source[T - 1 - j];
|
ws += bWeights[j] * source[T - 1 - j];
|
||||||
sBj += bWeights[j];
|
sBj += bWeights[j];
|
||||||
}
|
}
|
||||||
double bt = -0.5 * b0 - sBj;
|
double bt = (-0.5 * b0) - sBj;
|
||||||
ws += bt * source[0];
|
ws += bt * source[0];
|
||||||
output[t] = ws;
|
output[t] = ws;
|
||||||
}
|
}
|
||||||
@@ -339,7 +339,7 @@ public sealed class Cfitz : AbstractBase
|
|||||||
sumFwd += bWeights[j];
|
sumFwd += bWeights[j];
|
||||||
}
|
}
|
||||||
// Far endpoint correction
|
// Far endpoint correction
|
||||||
double btFwd = -0.5 * b0 - sumFwd;
|
double btFwd = (-0.5 * b0) - sumFwd;
|
||||||
ws += btFwd * source[T - 1];
|
ws += btFwd * source[T - 1];
|
||||||
|
|
||||||
// Backward terms: j=1..tp-2 = t-1 in 0-indexed
|
// Backward terms: j=1..tp-2 = t-1 in 0-indexed
|
||||||
@@ -351,7 +351,7 @@ public sealed class Cfitz : AbstractBase
|
|||||||
sumBwd += bWeights[j];
|
sumBwd += bWeights[j];
|
||||||
}
|
}
|
||||||
// Near endpoint correction
|
// Near endpoint correction
|
||||||
double btBwd = -0.5 * b0 - sumBwd;
|
double btBwd = (-0.5 * b0) - sumBwd;
|
||||||
ws += btBwd * source[0];
|
ws += btBwd * source[0];
|
||||||
|
|
||||||
output[t] = ws;
|
output[t] = ws;
|
||||||
|
|||||||
@@ -72,9 +72,9 @@ public sealed class Cheby1 : AbstractBase
|
|||||||
double omegaD = coshMu * Wc;
|
double omegaD = coshMu * Wc;
|
||||||
double K = Math.FusedMultiplyAdd(sigma, sigma, omegaD * omegaD);
|
double K = Math.FusedMultiplyAdd(sigma, sigma, omegaD * omegaD);
|
||||||
|
|
||||||
double a0z = 1.0 - 2.0 * sigma + K;
|
double a0z = 1.0 - (2.0 * sigma) + K;
|
||||||
double a1z = 2.0 * K - 2.0;
|
double a1z = (2.0 * K) - 2.0;
|
||||||
double a2z = 1.0 + 2.0 * sigma + K;
|
double a2z = 1.0 + (2.0 * sigma) + K;
|
||||||
double b0z = K;
|
double b0z = K;
|
||||||
double b1z = 2.0 * K;
|
double b1z = 2.0 * K;
|
||||||
double b2z = K;
|
double b2z = K;
|
||||||
@@ -202,7 +202,6 @@ public sealed class Cheby1 : AbstractBase
|
|||||||
return indicator.Update(source);
|
return indicator.Update(source);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static void Batch(ReadOnlySpan<double> source, Span<double> output, int period, double ripple = 1.0)
|
public static void Batch(ReadOnlySpan<double> source, Span<double> output, int period, double ripple = 1.0)
|
||||||
{
|
{
|
||||||
@@ -231,11 +230,11 @@ public sealed class Cheby1 : AbstractBase
|
|||||||
double coshMu = Math.Cosh(mu);
|
double coshMu = Math.Cosh(mu);
|
||||||
double sigma = -sinhMu * Wc;
|
double sigma = -sinhMu * Wc;
|
||||||
double omegaD = coshMu * Wc;
|
double omegaD = coshMu * Wc;
|
||||||
double K = sigma * sigma + omegaD * omegaD;
|
double K = (sigma * sigma) + (omegaD * omegaD);
|
||||||
|
|
||||||
double a0z = 1.0 - 2.0 * sigma + K;
|
double a0z = 1.0 - (2.0 * sigma) + K;
|
||||||
double a1z = 2.0 * K - 2.0;
|
double a1z = (2.0 * K) - 2.0;
|
||||||
double a2z = 1.0 + 2.0 * sigma + K;
|
double a2z = 1.0 + (2.0 * sigma) + K;
|
||||||
double b0z = K;
|
double b0z = K;
|
||||||
double b1z = 2.0 * K;
|
double b1z = 2.0 * K;
|
||||||
double b2z = K;
|
double b2z = K;
|
||||||
|
|||||||
@@ -77,12 +77,12 @@ public sealed class Cheby2 : AbstractBase
|
|||||||
double Kz = omegaZ * omegaZ;
|
double Kz = omegaZ * omegaZ;
|
||||||
double dcGain = Kz / Kp;
|
double dcGain = Kz / Kp;
|
||||||
|
|
||||||
double a0z = 1.0 - 2.0 * sigmaP + Kp;
|
double a0z = 1.0 - (2.0 * sigmaP) + Kp;
|
||||||
double a1z = 2.0 * Kp - 2.0;
|
double a1z = (2.0 * Kp) - 2.0;
|
||||||
double a2z = 1.0 + 2.0 * sigmaP + Kp;
|
double a2z = 1.0 + (2.0 * sigmaP) + Kp;
|
||||||
|
|
||||||
double b0z = dcGain * (1.0 + Kz);
|
double b0z = dcGain * (1.0 + Kz);
|
||||||
double b1z = dcGain * (2.0 * Kz - 2.0);
|
double b1z = dcGain * ((2.0 * Kz) - 2.0);
|
||||||
double b2z = dcGain * (1.0 + Kz);
|
double b2z = dcGain * (1.0 + Kz);
|
||||||
|
|
||||||
// Normalize
|
// Normalize
|
||||||
@@ -258,12 +258,12 @@ public sealed class Cheby2 : AbstractBase
|
|||||||
double Kz = omegaZ * omegaZ;
|
double Kz = omegaZ * omegaZ;
|
||||||
double dcGain = Kz / Kp;
|
double dcGain = Kz / Kp;
|
||||||
|
|
||||||
double a0z = 1.0 - 2.0 * sigmaP + Kp;
|
double a0z = 1.0 - (2.0 * sigmaP) + Kp;
|
||||||
double a1z = 2.0 * Kp - 2.0;
|
double a1z = (2.0 * Kp) - 2.0;
|
||||||
double a2z = 1.0 + 2.0 * sigmaP + Kp;
|
double a2z = 1.0 + (2.0 * sigmaP) + Kp;
|
||||||
|
|
||||||
double b0z = dcGain * (1.0 + Kz);
|
double b0z = dcGain * (1.0 + Kz);
|
||||||
double b1z = dcGain * (2.0 * Kz - 2.0);
|
double b1z = dcGain * ((2.0 * Kz) - 2.0);
|
||||||
double b2z = dcGain * (1.0 + Kz);
|
double b2z = dcGain * (1.0 + Kz);
|
||||||
|
|
||||||
double b0 = b0z / a0z;
|
double b0 = b0z / a0z;
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ public sealed class Edcf : AbstractBase
|
|||||||
// But the inner loop looks back within the same window, so we only need 'length' samples
|
// But the inner loop looks back within the same window, so we only need 'length' samples
|
||||||
// However, the EasyLanguage code accesses Price[count + LookBack] where count goes to Length-1
|
// However, the EasyLanguage code accesses Price[count + LookBack] where count goes to Length-1
|
||||||
// and LookBack goes to Length-1, so max index = 2*(Length-1). We need 2*Length - 1 in the buffer.
|
// and LookBack goes to Length-1, so max index = 2*(Length-1). We need 2*Length - 1 in the buffer.
|
||||||
_buffer = new RingBuffer(2 * length - 1);
|
_buffer = new RingBuffer((2 * length) - 1);
|
||||||
WarmupPeriod = length;
|
WarmupPeriod = length;
|
||||||
Name = $"Edcf({_length})";
|
Name = $"Edcf({_length})";
|
||||||
}
|
}
|
||||||
@@ -215,12 +215,12 @@ public sealed class Edcf : AbstractBase
|
|||||||
|
|
||||||
public override void Prime(ReadOnlySpan<double> source, TimeSpan? step = null)
|
public override void Prime(ReadOnlySpan<double> source, TimeSpan? step = null)
|
||||||
{
|
{
|
||||||
long initialTicks = DateTime.UtcNow.Ticks - source.Length * (step?.Ticks ?? TimeSpan.FromSeconds(1).Ticks);
|
long initialTicks = DateTime.UtcNow.Ticks - (source.Length * (step?.Ticks ?? TimeSpan.FromSeconds(1).Ticks));
|
||||||
TimeSpan increment = step ?? TimeSpan.FromSeconds(1);
|
TimeSpan increment = step ?? TimeSpan.FromSeconds(1);
|
||||||
|
|
||||||
for (int i = 0; i < source.Length; i++)
|
for (int i = 0; i < source.Length; i++)
|
||||||
{
|
{
|
||||||
Update(new TValue(initialTicks + i * increment.Ticks, source[i]));
|
Update(new TValue(initialTicks + (i * increment.Ticks), source[i]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -65,7 +65,7 @@ public sealed class Elliptic : AbstractBase
|
|||||||
double sigma_scaled = C_sigma * Wc;
|
double sigma_scaled = C_sigma * Wc;
|
||||||
double Kp_scaled = C_Kp_norm * Wc * Wc;
|
double Kp_scaled = C_Kp_norm * Wc * Wc;
|
||||||
|
|
||||||
double a0_denom = 1.0 - 2.0 * sigma_scaled + Kp_scaled;
|
double a0_denom = 1.0 - (2.0 * sigma_scaled) + Kp_scaled;
|
||||||
if (Math.Abs(a0_denom) < 1e-9)
|
if (Math.Abs(a0_denom) < 1e-9)
|
||||||
{
|
{
|
||||||
a0_denom = 1e-9;
|
a0_denom = 1e-9;
|
||||||
@@ -73,12 +73,12 @@ public sealed class Elliptic : AbstractBase
|
|||||||
|
|
||||||
const double norm_factor = C_Kp_norm / (C_k * C_wz * C_wz);
|
const double norm_factor = C_Kp_norm / (C_k * C_wz * C_wz);
|
||||||
|
|
||||||
double b0_val = norm_factor * C_k * (1.0 + omega_z_scaled * omega_z_scaled) / a0_denom;
|
double b0_val = norm_factor * C_k * (1.0 + (omega_z_scaled * omega_z_scaled)) / a0_denom;
|
||||||
double b1_val = norm_factor * C_k * (2.0 * omega_z_scaled * omega_z_scaled - 2.0) / a0_denom;
|
double b1_val = norm_factor * C_k * ((2.0 * omega_z_scaled * omega_z_scaled) - 2.0) / a0_denom;
|
||||||
double b2_val = b0_val;
|
double b2_val = b0_val;
|
||||||
|
|
||||||
double a1_val = (2.0 * Kp_scaled - 2.0) / a0_denom;
|
double a1_val = ((2.0 * Kp_scaled) - 2.0) / a0_denom;
|
||||||
double a2_val = (1.0 + 2.0 * sigma_scaled + Kp_scaled) / a0_denom;
|
double a2_val = (1.0 + (2.0 * sigma_scaled) + Kp_scaled) / a0_denom;
|
||||||
|
|
||||||
// Validate and Normalize for Unity Gain at DC
|
// Validate and Normalize for Unity Gain at DC
|
||||||
// DC Gain = (b0 + b1 + b2) / (1 + a1 + a2)
|
// DC Gain = (b0 + b1 + b2) / (1 + a1 + a2)
|
||||||
@@ -207,7 +207,6 @@ public sealed class Elliptic : AbstractBase
|
|||||||
return indicator.Update(source);
|
return indicator.Update(source);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static void Batch(ReadOnlySpan<double> source, Span<double> output, int period)
|
public static void Batch(ReadOnlySpan<double> source, Span<double> output, int period)
|
||||||
{
|
{
|
||||||
@@ -255,7 +254,7 @@ public sealed class Elliptic : AbstractBase
|
|||||||
double sigma_scaled = C_sigma * Wc;
|
double sigma_scaled = C_sigma * Wc;
|
||||||
double Kp_scaled = C_Kp_norm * Wc * Wc;
|
double Kp_scaled = C_Kp_norm * Wc * Wc;
|
||||||
|
|
||||||
double a0_denom = 1.0 - 2.0 * sigma_scaled + Kp_scaled;
|
double a0_denom = 1.0 - (2.0 * sigma_scaled) + Kp_scaled;
|
||||||
if (Math.Abs(a0_denom) < 1e-9)
|
if (Math.Abs(a0_denom) < 1e-9)
|
||||||
{
|
{
|
||||||
a0_denom = 1e-9;
|
a0_denom = 1e-9;
|
||||||
@@ -263,12 +262,12 @@ public sealed class Elliptic : AbstractBase
|
|||||||
|
|
||||||
const double norm_factor = C_Kp_norm / (C_k * C_wz * C_wz);
|
const double norm_factor = C_Kp_norm / (C_k * C_wz * C_wz);
|
||||||
|
|
||||||
double b0 = norm_factor * C_k * (1.0 + omega_z_scaled * omega_z_scaled) / a0_denom;
|
double b0 = norm_factor * C_k * (1.0 + (omega_z_scaled * omega_z_scaled)) / a0_denom;
|
||||||
double b1 = norm_factor * C_k * (2.0 * omega_z_scaled * omega_z_scaled - 2.0) / a0_denom;
|
double b1 = norm_factor * C_k * ((2.0 * omega_z_scaled * omega_z_scaled) - 2.0) / a0_denom;
|
||||||
double b2 = b0;
|
double b2 = b0;
|
||||||
|
|
||||||
double a1 = (2.0 * Kp_scaled - 2.0) / a0_denom;
|
double a1 = ((2.0 * Kp_scaled) - 2.0) / a0_denom;
|
||||||
double a2 = (1.0 + 2.0 * sigma_scaled + Kp_scaled) / a0_denom;
|
double a2 = (1.0 + (2.0 * sigma_scaled) + Kp_scaled) / a0_denom;
|
||||||
|
|
||||||
// Normalize constants for Unity Gain
|
// Normalize constants for Unity Gain
|
||||||
double sum_b = b0 + b1 + b2;
|
double sum_b = b0 + b1 + b2;
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ public sealed class Gauss : AbstractBase
|
|||||||
}
|
}
|
||||||
|
|
||||||
_sigma = sigma;
|
_sigma = sigma;
|
||||||
KernelSize = (int)(2 * Math.Ceiling(3.0 * sigma) + 1);
|
KernelSize = (int)((2 * Math.Ceiling(3.0 * sigma)) + 1);
|
||||||
WarmupPeriod = KernelSize;
|
WarmupPeriod = KernelSize;
|
||||||
Name = $"Gauss({sigma:F2})";
|
Name = $"Gauss({sigma:F2})";
|
||||||
_buffer = new RingBuffer(KernelSize);
|
_buffer = new RingBuffer(KernelSize);
|
||||||
@@ -241,7 +241,7 @@ public sealed class Gauss : AbstractBase
|
|||||||
throw new ArgumentException("Source and output spans must be of equal length.", nameof(output));
|
throw new ArgumentException("Source and output spans must be of equal length.", nameof(output));
|
||||||
}
|
}
|
||||||
|
|
||||||
int kernelSize = (int)(2 * Math.Ceiling(3.0 * sigma) + 1);
|
int kernelSize = (int)((2 * Math.Ceiling(3.0 * sigma)) + 1);
|
||||||
|
|
||||||
// Use stackalloc for small kernels, ArrayPool for large ones to avoid stack overflow
|
// Use stackalloc for small kernels, ArrayPool for large ones to avoid stack overflow
|
||||||
double[]? rented = null;
|
double[]? rented = null;
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ public sealed class Hp : AbstractBase
|
|||||||
Lambda = lambda;
|
Lambda = lambda;
|
||||||
|
|
||||||
double s = Math.Sqrt(lambda);
|
double s = Math.Sqrt(lambda);
|
||||||
_alpha = (s * 0.5 - 1.0) / (s * 0.5 + 1.0);
|
_alpha = ((s * 0.5) - 1.0) / ((s * 0.5) + 1.0);
|
||||||
_alpha = Math.Clamp(_alpha, 0.0001, 0.9999);
|
_alpha = Math.Clamp(_alpha, 0.0001, 0.9999);
|
||||||
_oneMinusAlpha = 1.0 - _alpha;
|
_oneMinusAlpha = 1.0 - _alpha;
|
||||||
_halfAlpha = 0.5 * _alpha;
|
_halfAlpha = 0.5 * _alpha;
|
||||||
@@ -218,7 +218,7 @@ public sealed class Hp : AbstractBase
|
|||||||
}
|
}
|
||||||
|
|
||||||
double s = Math.Sqrt(lambda);
|
double s = Math.Sqrt(lambda);
|
||||||
double alpha = (s * 0.5 - 1.0) / (s * 0.5 + 1.0);
|
double alpha = ((s * 0.5) - 1.0) / ((s * 0.5) + 1.0);
|
||||||
alpha = Math.Clamp(alpha, 0.0001, 0.9999);
|
alpha = Math.Clamp(alpha, 0.0001, 0.9999);
|
||||||
|
|
||||||
double oneMinusAlpha = 1.0 - alpha;
|
double oneMinusAlpha = 1.0 - alpha;
|
||||||
|
|||||||
@@ -251,7 +251,7 @@ public sealed class Hpf : AbstractBase
|
|||||||
double a = (cosW + sinW - 1.0) / cosW;
|
double a = (cosW + sinW - 1.0) / cosW;
|
||||||
double oneMinusA = 1.0 - a;
|
double oneMinusA = 1.0 - a;
|
||||||
|
|
||||||
double t = 1.0 - 0.5 * a;
|
double t = 1.0 - (0.5 * a);
|
||||||
double c1 = t * t;
|
double c1 = t * t;
|
||||||
double c2 = 2.0 * oneMinusA;
|
double c2 = 2.0 * oneMinusA;
|
||||||
double c3 = oneMinusA * oneMinusA;
|
double c3 = oneMinusA * oneMinusA;
|
||||||
@@ -316,7 +316,6 @@ public sealed class Hpf : AbstractBase
|
|||||||
return (results, indicator);
|
return (results, indicator);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Unsubscribes from the source publisher if one was provided during construction.
|
/// Unsubscribes from the source publisher if one was provided during construction.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -263,7 +263,7 @@ public sealed class Laguerre : AbstractBase
|
|||||||
s.LastValid = input;
|
s.LastValid = input;
|
||||||
|
|
||||||
// Filt = (L0 + 2*L1 + 2*L2 + L3) / 6
|
// Filt = (L0 + 2*L1 + 2*L2 + L3) / 6
|
||||||
return (s.L0 + 2.0 * s.L1 + 2.0 * s.L2 + s.L3) / 6.0;
|
return (s.L0 + (2.0 * s.L1) + (2.0 * s.L2) + s.L3) / 6.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -131,7 +131,7 @@ public sealed class OneEuro : AbstractBase
|
|||||||
s.DxHat = Math.FusedMultiplyAdd(_alphaD, dx - s.DxHat, s.DxHat);
|
s.DxHat = Math.FusedMultiplyAdd(_alphaD, dx - s.DxHat, s.DxHat);
|
||||||
|
|
||||||
// Step 3: Adaptive cutoff
|
// Step 3: Adaptive cutoff
|
||||||
double fc = MinCutoff + Beta * Math.Abs(s.DxHat);
|
double fc = MinCutoff + (Beta * Math.Abs(s.DxHat));
|
||||||
|
|
||||||
// Step 4: Smoothing factor α = r / (r + 1), r = 2π·fc
|
// Step 4: Smoothing factor α = r / (r + 1), r = 2π·fc
|
||||||
double r = 2.0 * Math.PI * fc;
|
double r = 2.0 * Math.PI * fc;
|
||||||
@@ -223,7 +223,7 @@ public sealed class OneEuro : AbstractBase
|
|||||||
dxHat = Math.FusedMultiplyAdd(alphaD, dx - dxHat, dxHat);
|
dxHat = Math.FusedMultiplyAdd(alphaD, dx - dxHat, dxHat);
|
||||||
|
|
||||||
// Adaptive cutoff
|
// Adaptive cutoff
|
||||||
double fc = minCutoff + beta * Math.Abs(dxHat);
|
double fc = minCutoff + (beta * Math.Abs(dxHat));
|
||||||
|
|
||||||
// Smoothing factor
|
// Smoothing factor
|
||||||
double r = 2.0 * Math.PI * fc;
|
double r = 2.0 * Math.PI * fc;
|
||||||
|
|||||||
@@ -88,7 +88,7 @@ public sealed class Rls : AbstractBase
|
|||||||
_p_P = new double[matSize];
|
_p_P = new double[matSize];
|
||||||
for (int i = 0; i < order; i++)
|
for (int i = 0; i < order; i++)
|
||||||
{
|
{
|
||||||
_P[i * order + i] = delta;
|
_P[(i * order) + i] = delta;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ring buffer holds order+1 values: current + order past values
|
// Ring buffer holds order+1 values: current + order past values
|
||||||
@@ -247,7 +247,7 @@ public sealed class Rls : AbstractBase
|
|||||||
int rowBase = i * _order;
|
int rowBase = i * _order;
|
||||||
for (int j = 0; j < _order; j++)
|
for (int j = 0; j < _order; j++)
|
||||||
{
|
{
|
||||||
_P[rowBase + j] = _invLambda * (_P[rowBase + j] - ki * px[j]);
|
_P[rowBase + j] = _invLambda * (_P[rowBase + j] - (ki * px[j]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -304,7 +304,7 @@ public sealed class Rls : AbstractBase
|
|||||||
double[] P = new double[matSize];
|
double[] P = new double[matSize];
|
||||||
for (int i = 0; i < order; i++)
|
for (int i = 0; i < order; i++)
|
||||||
{
|
{
|
||||||
P[i * order + i] = delta;
|
P[(i * order) + i] = delta;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Temporary buffers for Px and k
|
// Temporary buffers for Px and k
|
||||||
@@ -391,7 +391,7 @@ public sealed class Rls : AbstractBase
|
|||||||
int rowBase = i * order;
|
int rowBase = i * order;
|
||||||
for (int j = 0; j < order; j++)
|
for (int j = 0; j < order; j++)
|
||||||
{
|
{
|
||||||
P[rowBase + j] = invLambda * (P[rowBase + j] - ki * px[j]);
|
P[rowBase + j] = invLambda * (P[rowBase + j] - (ki * px[j]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -414,7 +414,7 @@ public sealed class Rls : AbstractBase
|
|||||||
Array.Clear(_p_P);
|
Array.Clear(_p_P);
|
||||||
for (int i = 0; i < _order; i++)
|
for (int i = 0; i < _order; i++)
|
||||||
{
|
{
|
||||||
_P[i * _order + i] = delta;
|
_P[(i * _order) + i] = delta;
|
||||||
}
|
}
|
||||||
|
|
||||||
Last = default;
|
Last = default;
|
||||||
|
|||||||
@@ -159,7 +159,7 @@ public sealed class Roofing : AbstractBase
|
|||||||
|
|
||||||
// Stage 1: Highpass Filter (removes trend)
|
// Stage 1: Highpass Filter (removes trend)
|
||||||
// hp = hpC1 * (val - 2*src1 + src2) + hpC2 * hp1 + hpC3 * hp2
|
// hp = hpC1 * (val - 2*src1 + src2) + hpC2 * hp1 + hpC3 * hp2
|
||||||
double hpInput = _hpC1 * (val - 2.0 * _state.Src1 + _state.Src2);
|
double hpInput = _hpC1 * (val - (2.0 * _state.Src1) + _state.Src2);
|
||||||
double hp = Math.FusedMultiplyAdd(_hpC2, _state.Hp1, Math.FusedMultiplyAdd(_hpC3, _state.Hp2, hpInput));
|
double hp = Math.FusedMultiplyAdd(_hpC2, _state.Hp1, Math.FusedMultiplyAdd(_hpC3, _state.Hp2, hpInput));
|
||||||
|
|
||||||
// Stage 2: Super Smoother (removes noise from HP output)
|
// Stage 2: Super Smoother (removes noise from HP output)
|
||||||
@@ -238,7 +238,7 @@ public sealed class Roofing : AbstractBase
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Highpass
|
// Highpass
|
||||||
double hpInput = hpC1 * (val - 2.0 * src1 + src2);
|
double hpInput = hpC1 * (val - (2.0 * src1) + src2);
|
||||||
double hp = Math.FusedMultiplyAdd(hpC2, hp1, Math.FusedMultiplyAdd(hpC3, hp2, hpInput));
|
double hp = Math.FusedMultiplyAdd(hpC2, hp1, Math.FusedMultiplyAdd(hpC3, hp2, hpInput));
|
||||||
|
|
||||||
// Super Smoother
|
// Super Smoother
|
||||||
|
|||||||
@@ -156,7 +156,7 @@ public sealed class Sak : AbstractBase
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case "HP":
|
case "HP":
|
||||||
_c0 = 1.0 - alpha / 2.0; _b0 = 1; _b1 = -1; _b2 = 0;
|
_c0 = 1.0 - (alpha / 2.0); _b0 = 1; _b1 = -1; _b2 = 0;
|
||||||
_a1 = decay; _a2 = 0;
|
_a1 = decay; _a2 = 0;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -245,7 +245,7 @@ public sealed class Sak : AbstractBase
|
|||||||
double oldest = _smaBuf!.IsFull ? _smaBuf.Oldest : 0.0;
|
double oldest = _smaBuf!.IsFull ? _smaBuf.Oldest : 0.0;
|
||||||
_smaBuf.Add(val, isNew);
|
_smaBuf.Add(val, isNew);
|
||||||
// _state.Y1 holds the running sum
|
// _state.Y1 holds the running sum
|
||||||
y = Math.FusedMultiplyAdd(_oneDivN, val, _state.Y1 - _oneDivN * oldest);
|
y = Math.FusedMultiplyAdd(_oneDivN, val, _state.Y1 - (_oneDivN * oldest));
|
||||||
_state.Y1 = y;
|
_state.Y1 = y;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -388,7 +388,7 @@ public sealed class Sak : AbstractBase
|
|||||||
{
|
{
|
||||||
double oldest = (smaBuf != null && smaBuf.IsFull) ? smaBuf.Oldest : 0.0;
|
double oldest = (smaBuf != null && smaBuf.IsFull) ? smaBuf.Oldest : 0.0;
|
||||||
smaBuf?.Add(val);
|
smaBuf?.Add(val);
|
||||||
y = Math.FusedMultiplyAdd(oneDivN, val, state.Y1 - oneDivN * oldest);
|
y = Math.FusedMultiplyAdd(oneDivN, val, state.Y1 - (oneDivN * oldest));
|
||||||
state.Y1 = y;
|
state.Y1 = y;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -69,17 +69,17 @@ public sealed class Sgf : AbstractBase
|
|||||||
double weight = 0;
|
double weight = 0;
|
||||||
if (_polyOrder == 2)
|
if (_polyOrder == 2)
|
||||||
{
|
{
|
||||||
weight = 3.0 * (3.0 * _period * _period - 7.0 - 20.0 * k * k);
|
weight = 3.0 * ((3.0 * _period * _period) - 7.0 - (20.0 * k * k));
|
||||||
}
|
}
|
||||||
else if (_polyOrder == 4)
|
else if (_polyOrder == 4)
|
||||||
{
|
{
|
||||||
double k2 = k * k;
|
double k2 = k * k;
|
||||||
weight = 15.0 + k2 * (-20.0 + k2 * 6.0);
|
weight = 15.0 + (k2 * (-20.0 + (k2 * 6.0)));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Guard against division by zero when halfWindow == 0 (period == 1)
|
// Guard against division by zero when halfWindow == 0 (period == 1)
|
||||||
weight = (halfWindow == 0) ? 1.0 : 1.0 - Math.Abs((double)k) / (double)halfWindow;
|
weight = (halfWindow == 0) ? 1.0 : 1.0 - (Math.Abs((double)k) / (double)halfWindow);
|
||||||
}
|
}
|
||||||
|
|
||||||
_weights[i] = weight;
|
_weights[i] = weight;
|
||||||
@@ -287,17 +287,17 @@ public sealed class Sgf : AbstractBase
|
|||||||
double weight = 0;
|
double weight = 0;
|
||||||
if (polyOrder == 2)
|
if (polyOrder == 2)
|
||||||
{
|
{
|
||||||
weight = 3.0 * (3.0 * period * period - 7.0 - 20.0 * k * k);
|
weight = 3.0 * ((3.0 * period * period) - 7.0 - (20.0 * k * k));
|
||||||
}
|
}
|
||||||
else if (polyOrder == 4)
|
else if (polyOrder == 4)
|
||||||
{
|
{
|
||||||
double k2 = k * k;
|
double k2 = k * k;
|
||||||
weight = 15.0 + k2 * (-20.0 + k2 * 6.0);
|
weight = 15.0 + (k2 * (-20.0 + (k2 * 6.0)));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Guard against division by zero when halfWindow == 0 (period == 1)
|
// Guard against division by zero when halfWindow == 0 (period == 1)
|
||||||
weight = (halfWindow == 0) ? 1.0 : 1.0 - Math.Abs((double)k) / (double)halfWindow;
|
weight = (halfWindow == 0) ? 1.0 : 1.0 - (Math.Abs((double)k) / (double)halfWindow);
|
||||||
}
|
}
|
||||||
|
|
||||||
weights[i] = weight;
|
weights[i] = weight;
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ public sealed class Ssf3 : AbstractBase
|
|||||||
double c1 = a1 * a1;
|
double c1 = a1 * a1;
|
||||||
|
|
||||||
coef2 = b1 + c1;
|
coef2 = b1 + c1;
|
||||||
coef3 = -(c1 + b1 * c1);
|
coef3 = -(c1 + (b1 * c1));
|
||||||
coef4 = c1 * c1;
|
coef4 = c1 * c1;
|
||||||
coef1 = 1.0 - coef2 - coef3 - coef4;
|
coef1 = 1.0 - coef2 - coef3 - coef4;
|
||||||
}
|
}
|
||||||
@@ -88,7 +88,7 @@ public sealed class Ssf3 : AbstractBase
|
|||||||
DateTime baseTime = DateTime.UtcNow;
|
DateTime baseTime = DateTime.UtcNow;
|
||||||
for (int i = 0; i < source.Length; i++)
|
for (int i = 0; i < source.Length; i++)
|
||||||
{
|
{
|
||||||
Update(new TValue(baseTime + interval * i, source[i]));
|
Update(new TValue(baseTime + (interval * i), source[i]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ public sealed class Usf : AbstractBase
|
|||||||
|
|
||||||
// Precompute coefficients for FMA optimization
|
// Precompute coefficients for FMA optimization
|
||||||
_k0 = 1.0 - _c1; // coefficient for val
|
_k0 = 1.0 - _c1; // coefficient for val
|
||||||
_k1 = 2.0 * _c1 - _c2; // coefficient for PrevInput1
|
_k1 = (2.0 * _c1) - _c2; // coefficient for PrevInput1
|
||||||
_k2 = -(_c1 + _c3); // coefficient for PrevInput2
|
_k2 = -(_c1 + _c3); // coefficient for PrevInput2
|
||||||
|
|
||||||
Name = $"Usf({period})";
|
Name = $"Usf({period})";
|
||||||
@@ -281,7 +281,7 @@ public sealed class Usf : AbstractBase
|
|||||||
|
|
||||||
// Precompute coefficients for FMA (outside loop)
|
// Precompute coefficients for FMA (outside loop)
|
||||||
double k0 = 1.0 - c1;
|
double k0 = 1.0 - c1;
|
||||||
double k1 = 2.0 * c1 - c2;
|
double k1 = (2.0 * c1) - c2;
|
||||||
double k2 = -(c1 + c3);
|
double k2 = -(c1 + c3);
|
||||||
|
|
||||||
for (; i < len; i++)
|
for (; i < len; i++)
|
||||||
|
|||||||
@@ -102,7 +102,7 @@ public sealed class Voss : AbstractBase
|
|||||||
double twoPiOverPeriod = 2.0 * Math.PI / period;
|
double twoPiOverPeriod = 2.0 * Math.PI / period;
|
||||||
_f1 = Math.Cos(twoPiOverPeriod);
|
_f1 = Math.Cos(twoPiOverPeriod);
|
||||||
double g1 = Math.Cos(bandwidth * twoPiOverPeriod);
|
double g1 = Math.Cos(bandwidth * twoPiOverPeriod);
|
||||||
_s1 = 1.0 / g1 - Math.Sqrt(1.0 / (g1 * g1) - 1.0);
|
_s1 = (1.0 / g1) - Math.Sqrt((1.0 / (g1 * g1)) - 1.0);
|
||||||
|
|
||||||
_vossRing = new double[_order + 1];
|
_vossRing = new double[_order + 1];
|
||||||
_s.LastValid = double.NaN;
|
_s.LastValid = double.NaN;
|
||||||
@@ -203,11 +203,11 @@ public sealed class Voss : AbstractBase
|
|||||||
for (int count = 0; count < _order; count++)
|
for (int count = 0; count < _order; count++)
|
||||||
{
|
{
|
||||||
int idx = _order - count; // lookback distance
|
int idx = _order - count; // lookback distance
|
||||||
int ringPos = (_vossIdx - idx + ringLen * 2) % ringLen;
|
int ringPos = (_vossIdx - idx + (ringLen * 2)) % ringLen;
|
||||||
sumC += (double)(count + 1) / _order * _vossRing[ringPos];
|
sumC += (double)(count + 1) / _order * _vossRing[ringPos];
|
||||||
}
|
}
|
||||||
|
|
||||||
double vossVal = (double)(3 + _order) / 2.0 * filt - sumC;
|
double vossVal = ((double)(3 + _order) / 2.0 * filt) - sumC;
|
||||||
|
|
||||||
// State shifts for next bar
|
// State shifts for next bar
|
||||||
if (isNew)
|
if (isNew)
|
||||||
@@ -261,7 +261,7 @@ public sealed class Voss : AbstractBase
|
|||||||
double twoPiOverPeriod = 2.0 * Math.PI / period;
|
double twoPiOverPeriod = 2.0 * Math.PI / period;
|
||||||
double f1 = Math.Cos(twoPiOverPeriod);
|
double f1 = Math.Cos(twoPiOverPeriod);
|
||||||
double g1 = Math.Cos(bandwidth * twoPiOverPeriod);
|
double g1 = Math.Cos(bandwidth * twoPiOverPeriod);
|
||||||
double s1 = 1.0 / g1 - Math.Sqrt(1.0 / (g1 * g1) - 1.0);
|
double s1 = (1.0 / g1) - Math.Sqrt((1.0 / (g1 * g1)) - 1.0);
|
||||||
|
|
||||||
int order = 3 * predict;
|
int order = 3 * predict;
|
||||||
double[] vossHistory = new double[source.Length];
|
double[] vossHistory = new double[source.Length];
|
||||||
@@ -319,7 +319,7 @@ public sealed class Voss : AbstractBase
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
double vossVal = (double)(3 + order) / 2.0 * filt - sumC;
|
double vossVal = ((double)(3 + order) / 2.0 * filt) - sumC;
|
||||||
vossHistory[i] = vossVal;
|
vossHistory[i] = vossVal;
|
||||||
output[i] = vossVal;
|
output[i] = vossVal;
|
||||||
|
|
||||||
|
|||||||
@@ -160,17 +160,17 @@ public sealed class Wiener : AbstractBase
|
|||||||
|
|
||||||
// result = mean + k * (src - mean)
|
// result = mean + k * (src - mean)
|
||||||
double src0 = _buffer[^1];
|
double src0 = _buffer[^1];
|
||||||
return mean + kp * (src0 - mean);
|
return mean + (kp * (src0 - mean));
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Prime(ReadOnlySpan<double> source, TimeSpan? step = null)
|
public override void Prime(ReadOnlySpan<double> source, TimeSpan? step = null)
|
||||||
{
|
{
|
||||||
long initialTicks = DateTime.UtcNow.Ticks - source.Length * (step?.Ticks ?? TimeSpan.FromSeconds(1).Ticks);
|
long initialTicks = DateTime.UtcNow.Ticks - (source.Length * (step?.Ticks ?? TimeSpan.FromSeconds(1).Ticks));
|
||||||
TimeSpan increment = step ?? TimeSpan.FromSeconds(1);
|
TimeSpan increment = step ?? TimeSpan.FromSeconds(1);
|
||||||
|
|
||||||
for (int i = 0; i < source.Length; i++)
|
for (int i = 0; i < source.Length; i++)
|
||||||
{
|
{
|
||||||
Update(new TValue(initialTicks + i * increment.Ticks, source[i]));
|
Update(new TValue(initialTicks + (i * increment.Ticks), source[i]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -178,21 +178,21 @@ public sealed class Asi : ITValuePublisher
|
|||||||
double R;
|
double R;
|
||||||
if (absHC >= absLC && absHC >= absHL)
|
if (absHC >= absLC && absHC >= absHL)
|
||||||
{
|
{
|
||||||
R = Math.FusedMultiplyAdd(-0.5, absLC, absHC) + 0.25 * absC1O1;
|
R = Math.FusedMultiplyAdd(-0.5, absLC, absHC) + (0.25 * absC1O1);
|
||||||
}
|
}
|
||||||
else if (absLC >= absHC && absLC >= absHL)
|
else if (absLC >= absHC && absLC >= absHL)
|
||||||
{
|
{
|
||||||
R = Math.FusedMultiplyAdd(-0.5, absHC, absLC) + 0.25 * absC1O1;
|
R = Math.FusedMultiplyAdd(-0.5, absHC, absLC) + (0.25 * absC1O1);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
R = absHL + 0.25 * absC1O1;
|
R = absHL + (0.25 * absC1O1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (R > 0.0)
|
if (R > 0.0)
|
||||||
{
|
{
|
||||||
// SI = 50 * [(C-C1) + 0.5*(C-O) + 0.25*(C1-O1)] / R * (K/T)
|
// SI = 50 * [(C-C1) + 0.5*(C-O) + 0.25*(C1-O1)] / R * (K/T)
|
||||||
double numerator = Math.FusedMultiplyAdd(0.5, close - open, close - prevClose) + 0.25 * (prevClose - prevOpen);
|
double numerator = Math.FusedMultiplyAdd(0.5, close - open, close - prevClose) + (0.25 * (prevClose - prevOpen));
|
||||||
si = 50.0 * numerator / R * (K / _limitMove);
|
si = 50.0 * numerator / R * (K / _limitMove);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -348,20 +348,20 @@ public sealed class Asi : ITValuePublisher
|
|||||||
double R;
|
double R;
|
||||||
if (absHC >= absLC && absHC >= absHL)
|
if (absHC >= absLC && absHC >= absHL)
|
||||||
{
|
{
|
||||||
R = Math.FusedMultiplyAdd(-0.5, absLC, absHC) + 0.25 * absC1O1;
|
R = Math.FusedMultiplyAdd(-0.5, absLC, absHC) + (0.25 * absC1O1);
|
||||||
}
|
}
|
||||||
else if (absLC >= absHC && absLC >= absHL)
|
else if (absLC >= absHC && absLC >= absHL)
|
||||||
{
|
{
|
||||||
R = Math.FusedMultiplyAdd(-0.5, absHC, absLC) + 0.25 * absC1O1;
|
R = Math.FusedMultiplyAdd(-0.5, absHC, absLC) + (0.25 * absC1O1);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
R = absHL + 0.25 * absC1O1;
|
R = absHL + (0.25 * absC1O1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (R > 0.0)
|
if (R > 0.0)
|
||||||
{
|
{
|
||||||
double numerator = Math.FusedMultiplyAdd(0.5, c - o, c - pc) + 0.25 * (pc - po);
|
double numerator = Math.FusedMultiplyAdd(0.5, c - o, c - pc) + (0.25 * (pc - po));
|
||||||
si = 50.0 * numerator / R * (K / limitMove);
|
si = 50.0 * numerator / R * (K / limitMove);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -48,11 +48,11 @@ public sealed class CfbIndicator : Indicator, IWatchlistIndicator
|
|||||||
protected override void OnInit()
|
protected override void OnInit()
|
||||||
{
|
{
|
||||||
// Generate lengths array
|
// Generate lengths array
|
||||||
int count = (MaxLength - MinLength) / Step + 1;
|
int count = ((MaxLength - MinLength) / Step) + 1;
|
||||||
int[] lengths = new int[count];
|
int[] lengths = new int[count];
|
||||||
for (int i = 0; i < count; i++)
|
for (int i = 0; i < count; i++)
|
||||||
{
|
{
|
||||||
lengths[i] = MinLength + i * Step;
|
lengths[i] = MinLength + (i * Step);
|
||||||
}
|
}
|
||||||
|
|
||||||
_cfb = new Cfb(lengths);
|
_cfb = new Cfb(lengths);
|
||||||
|
|||||||
@@ -299,7 +299,6 @@ public sealed class Cfb : ITValuePublisher, IDisposable
|
|||||||
return new TSeries(t, v);
|
return new TSeries(t, v);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initializes the indicator state using the provided value series history.
|
/// Initializes the indicator state using the provided value series history.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -170,7 +170,7 @@ public sealed class Rsx : ITValuePublisher
|
|||||||
double rsx;
|
double rsx;
|
||||||
if (smoothedAbsMomentum > 1e-10)
|
if (smoothedAbsMomentum > 1e-10)
|
||||||
{
|
{
|
||||||
double v4 = (smoothedMomentum / smoothedAbsMomentum + 1.0) * 50.0;
|
double v4 = ((smoothedMomentum / smoothedAbsMomentum) + 1.0) * 50.0;
|
||||||
rsx = Math.Clamp(v4, 0.0, 100.0);
|
rsx = Math.Clamp(v4, 0.0, 100.0);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -214,7 +214,6 @@ public sealed class Rsx : ITValuePublisher
|
|||||||
return new TSeries(t, v);
|
return new TSeries(t, v);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initializes the indicator state using the provided series history.
|
/// Initializes the indicator state using the provided series history.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -328,7 +327,7 @@ public sealed class Rsx : ITValuePublisher
|
|||||||
double rsx;
|
double rsx;
|
||||||
if (smoothedAbsMomentum > 1e-10)
|
if (smoothedAbsMomentum > 1e-10)
|
||||||
{
|
{
|
||||||
double v4 = (smoothedMomentum / smoothedAbsMomentum + 1.0) * 50.0;
|
double v4 = ((smoothedMomentum / smoothedAbsMomentum) + 1.0) * 50.0;
|
||||||
rsx = Math.Clamp(v4, 0.0, 100.0);
|
rsx = Math.Clamp(v4, 0.0, 100.0);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -176,11 +176,11 @@ public sealed class Sam : AbstractBase
|
|||||||
double price1 = s.Price0;
|
double price1 = s.Price0;
|
||||||
double price0 = price;
|
double price0 = price;
|
||||||
|
|
||||||
double smoothPrice = (price0 + 2.0 * price1 + 2.0 * price2 + price3) / 6.0;
|
double smoothPrice = (price0 + (2.0 * price1) + (2.0 * price2) + price3) / 6.0;
|
||||||
|
|
||||||
// ── Stage 2: Hilbert Transform ──
|
// ── Stage 2: Hilbert Transform ──
|
||||||
// Adaptive bandwidth based on previous smooth period
|
// Adaptive bandwidth based on previous smooth period
|
||||||
double bandwidth = 0.075 * s.DcPeriod + 0.54;
|
double bandwidth = (0.075 * s.DcPeriod) + 0.54;
|
||||||
|
|
||||||
// Shift smooth price history
|
// Shift smooth price history
|
||||||
double sp6 = s.Sp5;
|
double sp6 = s.Sp5;
|
||||||
@@ -192,7 +192,7 @@ public sealed class Sam : AbstractBase
|
|||||||
double sp0 = smoothPrice;
|
double sp0 = smoothPrice;
|
||||||
|
|
||||||
// Detrender: Hilbert Transform of smooth price
|
// Detrender: Hilbert Transform of smooth price
|
||||||
double detrender = (0.0962 * sp0 + 0.5769 * sp2 - 0.5769 * sp4 - 0.0962 * sp6) * bandwidth;
|
double detrender = ((0.0962 * sp0) + (0.5769 * sp2) - (0.5769 * sp4) - (0.0962 * sp6)) * bandwidth;
|
||||||
|
|
||||||
// Shift detrender history
|
// Shift detrender history
|
||||||
double det6 = s.Det5;
|
double det6 = s.Det5;
|
||||||
@@ -204,7 +204,7 @@ public sealed class Sam : AbstractBase
|
|||||||
double det0 = detrender;
|
double det0 = detrender;
|
||||||
|
|
||||||
// Q1 via Hilbert Transform of detrender
|
// Q1 via Hilbert Transform of detrender
|
||||||
double q1 = (0.0962 * det0 + 0.5769 * det2 - 0.5769 * det4 - 0.0962 * det6) * bandwidth;
|
double q1 = ((0.0962 * det0) + (0.5769 * det2) - (0.5769 * det4) - (0.0962 * det6)) * bandwidth;
|
||||||
|
|
||||||
// I1 is detrender delayed by 3 bars
|
// I1 is detrender delayed by 3 bars
|
||||||
double i1 = det3;
|
double i1 = det3;
|
||||||
@@ -229,10 +229,10 @@ public sealed class Sam : AbstractBase
|
|||||||
|
|
||||||
// ── Stage 3: Phase advance ──
|
// ── Stage 3: Phase advance ──
|
||||||
// JI = Hilbert Transform of I1
|
// JI = Hilbert Transform of I1
|
||||||
double ji = (0.0962 * i1_0 + 0.5769 * i1_2 - 0.5769 * i1_4 - 0.0962 * i1_6) * bandwidth;
|
double ji = ((0.0962 * i1_0) + (0.5769 * i1_2) - (0.5769 * i1_4) - (0.0962 * i1_6)) * bandwidth;
|
||||||
|
|
||||||
// JQ = Hilbert Transform of Q1
|
// JQ = Hilbert Transform of Q1
|
||||||
double jq = (0.0962 * q1_0 + 0.5769 * q1_2 - 0.5769 * q1_4 - 0.0962 * q1_6) * bandwidth;
|
double jq = ((0.0962 * q1_0) + (0.5769 * q1_2) - (0.5769 * q1_4) - (0.0962 * q1_6)) * bandwidth;
|
||||||
|
|
||||||
// Phasor addition: I2 = I1 - JQ, Q2 = Q1 + JI
|
// Phasor addition: I2 = I1 - JQ, Q2 = Q1 + JI
|
||||||
double i2Raw = i1 - jq;
|
double i2Raw = i1 - jq;
|
||||||
|
|||||||
@@ -119,7 +119,6 @@ public sealed class Vel : ITValuePublisher, IDisposable
|
|||||||
return new TSeries(t, v);
|
return new TSeries(t, v);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initializes the indicator state using the provided series history.
|
/// Initializes the indicator state using the provided series history.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -116,8 +116,8 @@ public sealed class Betadist : AbstractBase
|
|||||||
ser += LanczosCoeff[k] / (x + k);
|
ser += LanczosCoeff[k] / (x + k);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0.5 * Math.Log(2.0 * Math.PI)
|
return (0.5 * Math.Log(2.0 * Math.PI))
|
||||||
+ (x + 0.5) * Math.Log(t)
|
+ ((x + 0.5) * Math.Log(t))
|
||||||
- t
|
- t
|
||||||
+ Math.Log(ser);
|
+ Math.Log(ser);
|
||||||
}
|
}
|
||||||
@@ -161,7 +161,7 @@ public sealed class Betadist : AbstractBase
|
|||||||
|
|
||||||
// ln-prefactor: cfX^cfA * (1-cfX)^cfB / (cfA * B(cfA,cfB))
|
// ln-prefactor: cfX^cfA * (1-cfX)^cfB / (cfA * B(cfA,cfB))
|
||||||
// B(a,b) = B(b,a) so the log-beta term is symmetric.
|
// B(a,b) = B(b,a) so the log-beta term is symmetric.
|
||||||
double lnPrefactor = cfA * Math.Log(cfX) + cfB * Math.Log(1.0 - cfX)
|
double lnPrefactor = (cfA * Math.Log(cfX)) + (cfB * Math.Log(1.0 - cfX))
|
||||||
- Math.Log(cfA)
|
- Math.Log(cfA)
|
||||||
- (LnGamma(cfA) + LnGamma(cfB) - LnGamma(cfA + cfB));
|
- (LnGamma(cfA) + LnGamma(cfB) - LnGamma(cfA + cfB));
|
||||||
|
|
||||||
@@ -186,7 +186,7 @@ public sealed class Betadist : AbstractBase
|
|||||||
double qam = p - 1.0;
|
double qam = p - 1.0;
|
||||||
|
|
||||||
double c = 1.0;
|
double c = 1.0;
|
||||||
double d = 1.0 - qab * x / qap;
|
double d = 1.0 - (qab * x / qap);
|
||||||
if (Math.Abs(d) < FpMin)
|
if (Math.Abs(d) < FpMin)
|
||||||
{
|
{
|
||||||
d = FpMin;
|
d = FpMin;
|
||||||
@@ -201,13 +201,13 @@ public sealed class Betadist : AbstractBase
|
|||||||
|
|
||||||
// Even step: d_{2m}
|
// Even step: d_{2m}
|
||||||
double aa = m * (q - m) * x / ((qam + m2) * (p + m2));
|
double aa = m * (q - m) * x / ((qam + m2) * (p + m2));
|
||||||
d = 1.0 + aa * d;
|
d = 1.0 + (aa * d);
|
||||||
if (Math.Abs(d) < FpMin)
|
if (Math.Abs(d) < FpMin)
|
||||||
{
|
{
|
||||||
d = FpMin;
|
d = FpMin;
|
||||||
}
|
}
|
||||||
|
|
||||||
c = 1.0 + aa / c;
|
c = 1.0 + (aa / c);
|
||||||
if (Math.Abs(c) < FpMin)
|
if (Math.Abs(c) < FpMin)
|
||||||
{
|
{
|
||||||
c = FpMin;
|
c = FpMin;
|
||||||
@@ -218,13 +218,13 @@ public sealed class Betadist : AbstractBase
|
|||||||
|
|
||||||
// Odd step: d_{2m+1}
|
// Odd step: d_{2m+1}
|
||||||
aa = -(p + m) * (qab + m) * x / ((p + m2) * (qap + m2));
|
aa = -(p + m) * (qab + m) * x / ((p + m2) * (qap + m2));
|
||||||
d = 1.0 + aa * d;
|
d = 1.0 + (aa * d);
|
||||||
if (Math.Abs(d) < FpMin)
|
if (Math.Abs(d) < FpMin)
|
||||||
{
|
{
|
||||||
d = FpMin;
|
d = FpMin;
|
||||||
}
|
}
|
||||||
|
|
||||||
c = 1.0 + aa / c;
|
c = 1.0 + (aa / c);
|
||||||
if (Math.Abs(c) < FpMin)
|
if (Math.Abs(c) < FpMin)
|
||||||
{
|
{
|
||||||
c = FpMin;
|
c = FpMin;
|
||||||
|
|||||||
@@ -108,8 +108,8 @@ public sealed class Binomdist : AbstractBase
|
|||||||
ser += LanczosCoeff[k] / (x + k);
|
ser += LanczosCoeff[k] / (x + k);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0.5 * Math.Log(2.0 * Math.PI)
|
return (0.5 * Math.Log(2.0 * Math.PI))
|
||||||
+ (x + 0.5) * Math.Log(t)
|
+ ((x + 0.5) * Math.Log(t))
|
||||||
- t
|
- t
|
||||||
+ Math.Log(ser);
|
+ Math.Log(ser);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ public sealed class Cwt : AbstractBase
|
|||||||
}
|
}
|
||||||
|
|
||||||
int halfWindow = (int)Math.Round(3.0 * scale);
|
int halfWindow = (int)Math.Round(3.0 * scale);
|
||||||
_windowSize = 2 * halfWindow + 1;
|
_windowSize = (2 * halfWindow) + 1;
|
||||||
_normFactor = 1.0 / Math.Sqrt(scale);
|
_normFactor = 1.0 / Math.Sqrt(scale);
|
||||||
|
|
||||||
// Precompute kernel: ψ(k/s) = exp(-k²/(2s²)) * (cos(ω₀k/s) - i·sin(ω₀k/s))
|
// Precompute kernel: ψ(k/s) = exp(-k²/(2s²)) * (cos(ω₀k/s) - i·sin(ω₀k/s))
|
||||||
@@ -104,7 +104,7 @@ public sealed class Cwt : AbstractBase
|
|||||||
double[] kernelReal, double[] kernelImag,
|
double[] kernelReal, double[] kernelImag,
|
||||||
int halfWindow, double scale, double omega0)
|
int halfWindow, double scale, double omega0)
|
||||||
{
|
{
|
||||||
int windowSize = 2 * halfWindow + 1;
|
int windowSize = (2 * halfWindow) + 1;
|
||||||
double invScale = 1.0 / scale;
|
double invScale = 1.0 / scale;
|
||||||
for (int j = 0; j < windowSize; j++)
|
for (int j = 0; j < windowSize; j++)
|
||||||
{
|
{
|
||||||
@@ -245,7 +245,7 @@ public sealed class Cwt : AbstractBase
|
|||||||
}
|
}
|
||||||
|
|
||||||
int halfWindow = (int)Math.Round(3.0 * scale);
|
int halfWindow = (int)Math.Round(3.0 * scale);
|
||||||
int windowSize = 2 * halfWindow + 1;
|
int windowSize = (2 * halfWindow) + 1;
|
||||||
double normFactor = 1.0 / Math.Sqrt(scale);
|
double normFactor = 1.0 / Math.Sqrt(scale);
|
||||||
double lastValid = 0.0;
|
double lastValid = 0.0;
|
||||||
|
|
||||||
|
|||||||
@@ -123,7 +123,7 @@ public sealed class Gammadist : AbstractBase
|
|||||||
}
|
}
|
||||||
|
|
||||||
double t = z + 7.5;
|
double t = z + 7.5;
|
||||||
return Math.FusedMultiplyAdd(z + 0.5, Math.Log(t), 0.5 * Math.Log(2.0 * Math.PI) - t + Math.Log(x));
|
return Math.FusedMultiplyAdd(z + 0.5, Math.Log(t), (0.5 * Math.Log(2.0 * Math.PI)) - t + Math.Log(x));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -151,7 +151,7 @@ public sealed class Gammadist : AbstractBase
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return sum * Math.Exp(-x + a * Math.Log(x) - lnGammaA);
|
return sum * Math.Exp(-x + (a * Math.Log(x)) - lnGammaA);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -180,7 +180,7 @@ public sealed class Gammadist : AbstractBase
|
|||||||
d = FpMin;
|
d = FpMin;
|
||||||
}
|
}
|
||||||
|
|
||||||
c = b + an / c;
|
c = b + (an / c);
|
||||||
if (Math.Abs(c) < FpMin)
|
if (Math.Abs(c) < FpMin)
|
||||||
{
|
{
|
||||||
c = FpMin;
|
c = FpMin;
|
||||||
@@ -195,7 +195,7 @@ public sealed class Gammadist : AbstractBase
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return Math.Exp(-x + a * Math.Log(x) - lnGammaA) * h;
|
return Math.Exp(-x + (a * Math.Log(x)) - lnGammaA) * h;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -98,8 +98,8 @@ public sealed class Lognormdist : AbstractBase
|
|||||||
double az = Math.Abs(z);
|
double az = Math.Abs(z);
|
||||||
double t = 1.0 / Math.FusedMultiplyAdd(P, az, 1.0);
|
double t = 1.0 / Math.FusedMultiplyAdd(P, az, 1.0);
|
||||||
double phi = Math.Exp(-0.5 * az * az) * (1.0 / Math.Sqrt(2.0 * Math.PI));
|
double phi = Math.Exp(-0.5 * az * az) * (1.0 / Math.Sqrt(2.0 * Math.PI));
|
||||||
double poly = ((((Math.FusedMultiplyAdd(B5, t, B4) * t) + B3) * t + B2) * t + B1) * t;
|
double poly = ((((((Math.FusedMultiplyAdd(B5, t, B4) * t) + B3) * t) + B2) * t) + B1) * t;
|
||||||
double cdf = 1.0 - phi * poly;
|
double cdf = 1.0 - (phi * poly);
|
||||||
return z >= 0.0 ? cdf : 1.0 - cdf;
|
return z >= 0.0 ? cdf : 1.0 - cdf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -98,7 +98,7 @@ public sealed class Normdist : AbstractBase
|
|||||||
double poly = Math.FusedMultiplyAdd(a3, t, a2);
|
double poly = Math.FusedMultiplyAdd(a3, t, a2);
|
||||||
poly = Math.FusedMultiplyAdd(poly, t, a1);
|
poly = Math.FusedMultiplyAdd(poly, t, a1);
|
||||||
poly *= t;
|
poly *= t;
|
||||||
double val = 1.0 - poly * Math.Exp(-(ax * ax));
|
double val = 1.0 - (poly * Math.Exp(-(ax * ax)));
|
||||||
return x >= 0.0 ? val : -val;
|
return x >= 0.0 ? val : -val;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -153,7 +153,7 @@ public sealed class Normdist : AbstractBase
|
|||||||
}
|
}
|
||||||
|
|
||||||
double mean = sum / count;
|
double mean = sum / count;
|
||||||
double variance = sumSq / count - mean * mean;
|
double variance = (sumSq / count) - (mean * mean);
|
||||||
double stddev = variance > 0.0 ? Math.Sqrt(variance) : 0.0;
|
double stddev = variance > 0.0 ? Math.Sqrt(variance) : 0.0;
|
||||||
return (mean, stddev, count);
|
return (mean, stddev, count);
|
||||||
}
|
}
|
||||||
@@ -305,7 +305,7 @@ public sealed class Normdist : AbstractBase
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
double mean = sum / count;
|
double mean = sum / count;
|
||||||
double variance = sumSq / count - mean * mean;
|
double variance = (sumSq / count) - (mean * mean);
|
||||||
double stddev = variance > 0.0 ? Math.Sqrt(variance) : 0.0;
|
double stddev = variance > 0.0 ? Math.Sqrt(variance) : 0.0;
|
||||||
double z = stddev > 0.0 ? (val - mean) / stddev : 0.0;
|
double z = stddev > 0.0 ? (val - mean) / stddev : 0.0;
|
||||||
double zFinal = (z - mu) * invSigmaSqrt2;
|
double zFinal = (z - mu) * invSigmaSqrt2;
|
||||||
|
|||||||
@@ -121,7 +121,7 @@ public sealed class Poissondist : AbstractBase
|
|||||||
}
|
}
|
||||||
|
|
||||||
double t = z + 7.5;
|
double t = z + 7.5;
|
||||||
return Math.FusedMultiplyAdd(z + 0.5, Math.Log(t), 0.5 * Math.Log(2.0 * Math.PI) - t + Math.Log(x));
|
return Math.FusedMultiplyAdd(z + 0.5, Math.Log(t), (0.5 * Math.Log(2.0 * Math.PI)) - t + Math.Log(x));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -149,7 +149,7 @@ public sealed class Poissondist : AbstractBase
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return sum * Math.Exp(-x + a * Math.Log(x) - lnGammaA);
|
return sum * Math.Exp(-x + (a * Math.Log(x)) - lnGammaA);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -178,7 +178,7 @@ public sealed class Poissondist : AbstractBase
|
|||||||
d = FpMin;
|
d = FpMin;
|
||||||
}
|
}
|
||||||
|
|
||||||
c = b + an / c;
|
c = b + (an / c);
|
||||||
if (Math.Abs(c) < FpMin)
|
if (Math.Abs(c) < FpMin)
|
||||||
{
|
{
|
||||||
c = FpMin;
|
c = FpMin;
|
||||||
@@ -193,7 +193,7 @@ public sealed class Poissondist : AbstractBase
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return Math.Exp(-x + a * Math.Log(x) - lnGammaA) * h;
|
return Math.Exp(-x + (a * Math.Log(x)) - lnGammaA) * h;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -89,7 +89,7 @@ public sealed class Tdist : AbstractBase
|
|||||||
double t2 = t * t;
|
double t2 = t * t;
|
||||||
double bx = nuD / Math.FusedMultiplyAdd(1.0, t2, nuD); // ν / (ν + t²)
|
double bx = nuD / Math.FusedMultiplyAdd(1.0, t2, nuD); // ν / (ν + t²)
|
||||||
double ibeta = Betadist.IncompleteBeta(bx, nuD * 0.5, 0.5);
|
double ibeta = Betadist.IncompleteBeta(bx, nuD * 0.5, 0.5);
|
||||||
return t >= 0.0 ? 1.0 - 0.5 * ibeta : 0.5 * ibeta;
|
return t >= 0.0 ? 1.0 - (0.5 * ibeta) : 0.5 * ibeta;
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
|||||||
@@ -161,7 +161,6 @@ public sealed class Apo : ITValuePublisher, IDisposable
|
|||||||
Update(args.Value, args.IsNew);
|
Update(args.Value, args.IsNew);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initializes the indicator state using the provided series history.
|
/// Initializes the indicator state using the provided series history.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -339,8 +339,8 @@ public sealed class Bbi : AbstractBase
|
|||||||
double old4 = b4[h4]; sum4 = c4 < p4 ? sum4 + val - old4 : sum4 - old4 + val; if (c4 < p4) { c4++; }
|
double old4 = b4[h4]; sum4 = c4 < p4 ? sum4 + val - old4 : sum4 - old4 + val; if (c4 < p4) { c4++; }
|
||||||
b4[h4] = val; h4 = (h4 + 1) % p4;
|
b4[h4] = val; h4 = (h4 + 1) % p4;
|
||||||
|
|
||||||
output[i] = (sum1 / Math.Max(1, c1) + sum2 / Math.Max(1, c2)
|
output[i] = ((sum1 / Math.Max(1, c1)) + (sum2 / Math.Max(1, c2))
|
||||||
+ sum3 / Math.Max(1, c3) + sum4 / Math.Max(1, c4)) * 0.25;
|
+ (sum3 / Math.Max(1, c3)) + (sum4 / Math.Max(1, c4))) * 0.25;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
|
|||||||
@@ -360,7 +360,6 @@ public sealed class Bbs : ITValuePublisher
|
|||||||
// === Bandwidth ===
|
// === Bandwidth ===
|
||||||
double bandwidth = bbMean != 0.0 ? ((bbUpper - bbLower) / bbMean) * 100.0 : 0.0; // skipcq: CS-R1077 - Exact-zero div guard: price avg
|
double bandwidth = bbMean != 0.0 ? ((bbUpper - bbLower) / bbMean) * 100.0 : 0.0; // skipcq: CS-R1077 - Exact-zero div guard: price avg
|
||||||
|
|
||||||
|
|
||||||
// === IsHot ===
|
// === IsHot ===
|
||||||
if (!_state.IsHot && _state.Bars >= WarmupPeriod)
|
if (!_state.IsHot && _state.Bars >= WarmupPeriod)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -56,8 +56,8 @@ public sealed class Cfo : AbstractBase
|
|||||||
WarmupPeriod = period;
|
WarmupPeriod = period;
|
||||||
|
|
||||||
_sumX = period * (period - 1) / 2.0;
|
_sumX = period * (period - 1) / 2.0;
|
||||||
double sumX2 = period * (period - 1.0) * (2.0 * period - 1.0) / 6.0;
|
double sumX2 = period * (period - 1.0) * ((2.0 * period) - 1.0) / 6.0;
|
||||||
_denomX = period * sumX2 - _sumX * _sumX;
|
_denomX = (period * sumX2) - (_sumX * _sumX);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -160,8 +160,8 @@ public sealed class Cfo : AbstractBase
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Linear regression: slope, intercept, TSF
|
// Linear regression: slope, intercept, TSF
|
||||||
double slope = (_period * _state.SumXY - _sumX * _state.SumY) / _denomX;
|
double slope = ((_period * _state.SumXY) - (_sumX * _state.SumY)) / _denomX;
|
||||||
double intercept = (_state.SumY - slope * _sumX) / _period;
|
double intercept = (_state.SumY - (slope * _sumX)) / _period;
|
||||||
double tsf = Math.FusedMultiplyAdd(slope, _period - 1, intercept);
|
double tsf = Math.FusedMultiplyAdd(slope, _period - 1, intercept);
|
||||||
|
|
||||||
// CFO = 100 * (source - tsf) / source
|
// CFO = 100 * (source - tsf) / source
|
||||||
@@ -265,8 +265,8 @@ public sealed class Cfo : AbstractBase
|
|||||||
}
|
}
|
||||||
|
|
||||||
double sumX = period * (period - 1) / 2.0;
|
double sumX = period * (period - 1) / 2.0;
|
||||||
double sumX2 = period * (period - 1.0) * (2.0 * period - 1.0) / 6.0;
|
double sumX2 = period * (period - 1.0) * ((2.0 * period) - 1.0) / 6.0;
|
||||||
double denomX = period * sumX2 - sumX * sumX;
|
double denomX = (period * sumX2) - (sumX * sumX);
|
||||||
|
|
||||||
double sumY = 0.0;
|
double sumY = 0.0;
|
||||||
double sumXY = 0.0;
|
double sumXY = 0.0;
|
||||||
@@ -311,8 +311,8 @@ public sealed class Cfo : AbstractBase
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
double slope = (period * sumXY - sumX * sumY) / denomX;
|
double slope = ((period * sumXY) - (sumX * sumY)) / denomX;
|
||||||
double intercept = (sumY - slope * sumX) / period;
|
double intercept = (sumY - (slope * sumX)) / period;
|
||||||
double tsf = Math.FusedMultiplyAdd(slope, period - 1, intercept);
|
double tsf = Math.FusedMultiplyAdd(slope, period - 1, intercept);
|
||||||
|
|
||||||
output[i] = val == 0.0 ? double.NaN : 100.0 * (val - tsf) / val; // skipcq: CS-R1077 - Exact-zero guard: val is a price; zero means no data, division by zero produces Infinity
|
output[i] = val == 0.0 ? double.NaN : 100.0 * (val - tsf) / val; // skipcq: CS-R1077 - Exact-zero guard: val is a price; zero means no data, division by zero produces Infinity
|
||||||
|
|||||||
@@ -203,7 +203,7 @@ public sealed class Coppock : ITValuePublisher
|
|||||||
{
|
{
|
||||||
double oldPlain = plainSum;
|
double oldPlain = plainSum;
|
||||||
plainSum = plainSum - prevWma + combined;
|
plainSum = plainSum - prevWma + combined;
|
||||||
weightedSum = weightedSum - oldPlain + _wmaPeriod * combined;
|
weightedSum = weightedSum - oldPlain + (_wmaPeriod * combined);
|
||||||
coppockVal = weightedSum / _wmaNorm;
|
coppockVal = weightedSum / _wmaNorm;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -357,7 +357,7 @@ public sealed class Coppock : ITValuePublisher
|
|||||||
{
|
{
|
||||||
double oldPlain = plainSum;
|
double oldPlain = plainSum;
|
||||||
plainSum = plainSum - oldest + combined;
|
plainSum = plainSum - oldest + combined;
|
||||||
weightedSum = weightedSum - oldPlain + wmaPeriod * combined;
|
weightedSum = weightedSum - oldPlain + (wmaPeriod * combined);
|
||||||
coppockVal = weightedSum / wmaNorm;
|
coppockVal = weightedSum / wmaNorm;
|
||||||
}
|
}
|
||||||
wmaBuf[wmaH] = combined;
|
wmaBuf[wmaH] = combined;
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ public sealed class Cti : AbstractBase
|
|||||||
WarmupPeriod = period;
|
WarmupPeriod = period;
|
||||||
|
|
||||||
_sx = period * (period - 1) / 2.0;
|
_sx = period * (period - 1) / 2.0;
|
||||||
_sxx = period * (period - 1.0) * (2 * period - 1) / 6.0;
|
_sxx = period * (period - 1.0) * ((2 * period) - 1) / 6.0;
|
||||||
_denomX = Math.FusedMultiplyAdd(period, _sxx, -_sx * _sx);
|
_denomX = Math.FusedMultiplyAdd(period, _sxx, -_sx * _sx);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -287,7 +287,7 @@ public sealed class Cti : AbstractBase
|
|||||||
}
|
}
|
||||||
|
|
||||||
double sx = period * (period - 1) / 2.0;
|
double sx = period * (period - 1) / 2.0;
|
||||||
double sxx = period * (period - 1.0) * (2 * period - 1) / 6.0;
|
double sxx = period * (period - 1.0) * ((2 * period) - 1) / 6.0;
|
||||||
double denomX = Math.FusedMultiplyAdd(period, sxx, -sx * sx);
|
double denomX = Math.FusedMultiplyAdd(period, sxx, -sx * sx);
|
||||||
|
|
||||||
double sumY = 0.0;
|
double sumY = 0.0;
|
||||||
|
|||||||
@@ -87,7 +87,7 @@ public sealed class Deco : AbstractBase
|
|||||||
|
|
||||||
double argShort = rad / shortPeriod;
|
double argShort = rad / shortPeriod;
|
||||||
double alphaShort = (Math.Cos(argShort) + Math.Sin(argShort) - 1.0) / Math.Cos(argShort);
|
double alphaShort = (Math.Cos(argShort) + Math.Sin(argShort) - 1.0) / Math.Cos(argShort);
|
||||||
double oneMinusAlphaHalfShort = 1.0 - alphaShort * 0.5;
|
double oneMinusAlphaHalfShort = 1.0 - (alphaShort * 0.5);
|
||||||
double oneMinusAlphaShort = 1.0 - alphaShort;
|
double oneMinusAlphaShort = 1.0 - alphaShort;
|
||||||
_a1Short = oneMinusAlphaHalfShort * oneMinusAlphaHalfShort;
|
_a1Short = oneMinusAlphaHalfShort * oneMinusAlphaHalfShort;
|
||||||
_b1Short = 2.0 * oneMinusAlphaShort;
|
_b1Short = 2.0 * oneMinusAlphaShort;
|
||||||
@@ -95,7 +95,7 @@ public sealed class Deco : AbstractBase
|
|||||||
|
|
||||||
double argLong = rad / longPeriod;
|
double argLong = rad / longPeriod;
|
||||||
double alphaLong = (Math.Cos(argLong) + Math.Sin(argLong) - 1.0) / Math.Cos(argLong);
|
double alphaLong = (Math.Cos(argLong) + Math.Sin(argLong) - 1.0) / Math.Cos(argLong);
|
||||||
double oneMinusAlphaHalfLong = 1.0 - alphaLong * 0.5;
|
double oneMinusAlphaHalfLong = 1.0 - (alphaLong * 0.5);
|
||||||
double oneMinusAlphaLong = 1.0 - alphaLong;
|
double oneMinusAlphaLong = 1.0 - alphaLong;
|
||||||
_a1Long = oneMinusAlphaHalfLong * oneMinusAlphaHalfLong;
|
_a1Long = oneMinusAlphaHalfLong * oneMinusAlphaHalfLong;
|
||||||
_b1Long = 2.0 * oneMinusAlphaLong;
|
_b1Long = 2.0 * oneMinusAlphaLong;
|
||||||
@@ -153,7 +153,7 @@ public sealed class Deco : AbstractBase
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
// HP[n] = a1*(x[n] - 2*x[n-1] + x[n-2]) + b1*HP[n-1] + c1*HP[n-2]
|
// HP[n] = a1*(x[n] - 2*x[n-1] + x[n-2]) + b1*HP[n-1] + c1*HP[n-2]
|
||||||
double diff = value - 2.0 * s.Price1 + s.Price2;
|
double diff = value - (2.0 * s.Price1) + s.Price2;
|
||||||
hpShort = Math.FusedMultiplyAdd(_a1Short, diff, Math.FusedMultiplyAdd(_b1Short, s.HpShort1, _c1Short * s.HpShort2));
|
hpShort = Math.FusedMultiplyAdd(_a1Short, diff, Math.FusedMultiplyAdd(_b1Short, s.HpShort1, _c1Short * s.HpShort2));
|
||||||
hpLong = Math.FusedMultiplyAdd(_a1Long, diff, Math.FusedMultiplyAdd(_b1Long, s.HpLong1, _c1Long * s.HpLong2));
|
hpLong = Math.FusedMultiplyAdd(_a1Long, diff, Math.FusedMultiplyAdd(_b1Long, s.HpLong1, _c1Long * s.HpLong2));
|
||||||
|
|
||||||
@@ -262,7 +262,7 @@ public sealed class Deco : AbstractBase
|
|||||||
|
|
||||||
double argShort = rad / shortPeriod;
|
double argShort = rad / shortPeriod;
|
||||||
double alphaShort = (Math.Cos(argShort) + Math.Sin(argShort) - 1.0) / Math.Cos(argShort);
|
double alphaShort = (Math.Cos(argShort) + Math.Sin(argShort) - 1.0) / Math.Cos(argShort);
|
||||||
double omahShort = 1.0 - alphaShort * 0.5;
|
double omahShort = 1.0 - (alphaShort * 0.5);
|
||||||
double omaShort = 1.0 - alphaShort;
|
double omaShort = 1.0 - alphaShort;
|
||||||
double a1S = omahShort * omahShort;
|
double a1S = omahShort * omahShort;
|
||||||
double b1S = 2.0 * omaShort;
|
double b1S = 2.0 * omaShort;
|
||||||
@@ -270,7 +270,7 @@ public sealed class Deco : AbstractBase
|
|||||||
|
|
||||||
double argLong = rad / longPeriod;
|
double argLong = rad / longPeriod;
|
||||||
double alphaLong = (Math.Cos(argLong) + Math.Sin(argLong) - 1.0) / Math.Cos(argLong);
|
double alphaLong = (Math.Cos(argLong) + Math.Sin(argLong) - 1.0) / Math.Cos(argLong);
|
||||||
double omahLong = 1.0 - alphaLong * 0.5;
|
double omahLong = 1.0 - (alphaLong * 0.5);
|
||||||
double omaLong = 1.0 - alphaLong;
|
double omaLong = 1.0 - alphaLong;
|
||||||
double a1L = omahLong * omahLong;
|
double a1L = omahLong * omahLong;
|
||||||
double b1L = 2.0 * omaLong;
|
double b1L = 2.0 * omaLong;
|
||||||
@@ -291,7 +291,7 @@ public sealed class Deco : AbstractBase
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
double diff = val - 2.0 * price1 + price2;
|
double diff = val - (2.0 * price1) + price2;
|
||||||
double hpS = Math.FusedMultiplyAdd(a1S, diff, Math.FusedMultiplyAdd(b1S, hpS1, c1S * hpS2));
|
double hpS = Math.FusedMultiplyAdd(a1S, diff, Math.FusedMultiplyAdd(b1S, hpS1, c1S * hpS2));
|
||||||
double hpL = Math.FusedMultiplyAdd(a1L, diff, Math.FusedMultiplyAdd(b1L, hpL1, c1L * hpL2));
|
double hpL = Math.FusedMultiplyAdd(a1L, diff, Math.FusedMultiplyAdd(b1L, hpL1, c1L * hpL2));
|
||||||
output[i] = hpL - hpS;
|
output[i] = hpL - hpS;
|
||||||
@@ -314,5 +314,4 @@ public sealed class Deco : AbstractBase
|
|||||||
var results = ind.Update(source);
|
var results = ind.Update(source);
|
||||||
return (results, ind);
|
return (results, ind);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -277,7 +277,7 @@ public sealed class Dosc : AbstractBase
|
|||||||
s.AvgLoss = Math.FusedMultiplyAdd(rsiAlpha, changeDn, rsiDecay * s.AvgLoss);
|
s.AvgLoss = Math.FusedMultiplyAdd(rsiAlpha, changeDn, rsiDecay * s.AvgLoss);
|
||||||
}
|
}
|
||||||
|
|
||||||
double rsiVal = s.AvgLoss == 0.0 ? 100.0 : 100.0 - 100.0 / (1.0 + s.AvgGain / s.AvgLoss);
|
double rsiVal = s.AvgLoss == 0.0 ? 100.0 : 100.0 - (100.0 / (1.0 + (s.AvgGain / s.AvgLoss)));
|
||||||
|
|
||||||
// --- Stage 2: EMA1 of RSI ---
|
// --- Stage 2: EMA1 of RSI ---
|
||||||
double ema1;
|
double ema1;
|
||||||
|
|||||||
@@ -194,7 +194,7 @@ public sealed class Dymoi : AbstractBase
|
|||||||
|
|
||||||
int nShort = s.CountShort;
|
int nShort = s.CountShort;
|
||||||
double meanShort = s.SumShort / nShort;
|
double meanShort = s.SumShort / nShort;
|
||||||
double varShort = s.SumSqShort / nShort - meanShort * meanShort;
|
double varShort = (s.SumSqShort / nShort) - (meanShort * meanShort);
|
||||||
double sdShort = varShort > 0.0 ? Math.Sqrt(varShort) : 0.0;
|
double sdShort = varShort > 0.0 ? Math.Sqrt(varShort) : 0.0;
|
||||||
|
|
||||||
// ── Stage 1: StdDev long window (O(1) update) ──
|
// ── Stage 1: StdDev long window (O(1) update) ──
|
||||||
@@ -216,7 +216,7 @@ public sealed class Dymoi : AbstractBase
|
|||||||
|
|
||||||
int nLong = s.CountLong;
|
int nLong = s.CountLong;
|
||||||
double meanLong = s.SumLong / nLong;
|
double meanLong = s.SumLong / nLong;
|
||||||
double varLong = s.SumSqLong / nLong - meanLong * meanLong;
|
double varLong = (s.SumSqLong / nLong) - (meanLong * meanLong);
|
||||||
double sdLong = varLong > 0.0 ? Math.Sqrt(varLong) : 0.0;
|
double sdLong = varLong > 0.0 ? Math.Sqrt(varLong) : 0.0;
|
||||||
|
|
||||||
// ── Stage 2: dynamic period ──
|
// ── Stage 2: dynamic period ──
|
||||||
@@ -442,7 +442,7 @@ public sealed class Dymoi : AbstractBase
|
|||||||
}
|
}
|
||||||
|
|
||||||
double meanS = sumShort / countShort;
|
double meanS = sumShort / countShort;
|
||||||
double varS = sumSqShort / countShort - meanS * meanS;
|
double varS = (sumSqShort / countShort) - (meanS * meanS);
|
||||||
double sdShort = varS > 0.0 ? Math.Sqrt(varS) : 0.0;
|
double sdShort = varS > 0.0 ? Math.Sqrt(varS) : 0.0;
|
||||||
|
|
||||||
// Long StdDev update
|
// Long StdDev update
|
||||||
@@ -463,7 +463,7 @@ public sealed class Dymoi : AbstractBase
|
|||||||
}
|
}
|
||||||
|
|
||||||
double meanL = sumLong / countLong;
|
double meanL = sumLong / countLong;
|
||||||
double varL = sumSqLong / countLong - meanL * meanL;
|
double varL = (sumSqLong / countLong) - (meanL * meanL);
|
||||||
double sdLong = varL > 0.0 ? Math.Sqrt(varL) : 0.0;
|
double sdLong = varL > 0.0 ? Math.Sqrt(varL) : 0.0;
|
||||||
|
|
||||||
// Dynamic period
|
// Dynamic period
|
||||||
|
|||||||
@@ -58,8 +58,8 @@ public sealed class Inertia : AbstractBase
|
|||||||
WarmupPeriod = period;
|
WarmupPeriod = period;
|
||||||
|
|
||||||
_sumX = period * (period - 1) / 2.0;
|
_sumX = period * (period - 1) / 2.0;
|
||||||
double sumX2 = period * (period - 1.0) * (2.0 * period - 1.0) / 6.0;
|
double sumX2 = period * (period - 1.0) * ((2.0 * period) - 1.0) / 6.0;
|
||||||
_denomX = period * sumX2 - _sumX * _sumX;
|
_denomX = (period * sumX2) - (_sumX * _sumX);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -160,8 +160,8 @@ public sealed class Inertia : AbstractBase
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Linear regression: slope, intercept, TSF
|
// Linear regression: slope, intercept, TSF
|
||||||
double slope = (_period * _state.SumXY - _sumX * _state.SumY) / _denomX;
|
double slope = ((_period * _state.SumXY) - (_sumX * _state.SumY)) / _denomX;
|
||||||
double intercept = (_state.SumY - slope * _sumX) / _period;
|
double intercept = (_state.SumY - (slope * _sumX)) / _period;
|
||||||
double tsf = Math.FusedMultiplyAdd(slope, _period - 1, intercept);
|
double tsf = Math.FusedMultiplyAdd(slope, _period - 1, intercept);
|
||||||
|
|
||||||
// Inertia = source - TSF (raw residual, no normalization)
|
// Inertia = source - TSF (raw residual, no normalization)
|
||||||
@@ -265,8 +265,8 @@ public sealed class Inertia : AbstractBase
|
|||||||
}
|
}
|
||||||
|
|
||||||
double sumX = period * (period - 1) / 2.0;
|
double sumX = period * (period - 1) / 2.0;
|
||||||
double sumX2 = period * (period - 1.0) * (2.0 * period - 1.0) / 6.0;
|
double sumX2 = period * (period - 1.0) * ((2.0 * period) - 1.0) / 6.0;
|
||||||
double denomX = period * sumX2 - sumX * sumX;
|
double denomX = (period * sumX2) - (sumX * sumX);
|
||||||
|
|
||||||
double sumY = 0.0;
|
double sumY = 0.0;
|
||||||
double sumXY = 0.0;
|
double sumXY = 0.0;
|
||||||
@@ -311,8 +311,8 @@ public sealed class Inertia : AbstractBase
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
double slope = (period * sumXY - sumX * sumY) / denomX;
|
double slope = ((period * sumXY) - (sumX * sumY)) / denomX;
|
||||||
double intercept = (sumY - slope * sumX) / period;
|
double intercept = (sumY - (slope * sumX)) / period;
|
||||||
double tsf = Math.FusedMultiplyAdd(slope, period - 1, intercept);
|
double tsf = Math.FusedMultiplyAdd(slope, period - 1, intercept);
|
||||||
|
|
||||||
output[i] = val - tsf;
|
output[i] = val - tsf;
|
||||||
|
|||||||
@@ -255,7 +255,7 @@ public sealed class Kst : ITValuePublisher
|
|||||||
|
|
||||||
// ── KST composite (weighted sum, FMA for w1..w3) ─────────────────────
|
// ── KST composite (weighted sum, FMA for w1..w3) ─────────────────────
|
||||||
double kstVal = Math.FusedMultiplyAdd(3.0, sm3, Math.FusedMultiplyAdd(2.0, sm2, sm1))
|
double kstVal = Math.FusedMultiplyAdd(3.0, sm3, Math.FusedMultiplyAdd(2.0, sm2, sm1))
|
||||||
+ 4.0 * sm4;
|
+ (4.0 * sm4);
|
||||||
|
|
||||||
// ── Signal line (SMA of KST) ──────────────────────────────────────────
|
// ── Signal line (SMA of KST) ──────────────────────────────────────────
|
||||||
double sigVal = StepSma(_sigBuf, ref sigSum, ref sigH, ref sigC, kstVal, _sigPeriod, isNew, out double prevSig);
|
double sigVal = StepSma(_sigBuf, ref sigSum, ref sigH, ref sigC, kstVal, _sigPeriod, isNew, out double prevSig);
|
||||||
@@ -458,7 +458,7 @@ public sealed class Kst : ITValuePublisher
|
|||||||
double sm4 = BatchStepSma(sm4b, s4, ref sum4, ref sh4, ref sc4, roc4);
|
double sm4 = BatchStepSma(sm4b, s4, ref sum4, ref sh4, ref sc4, roc4);
|
||||||
|
|
||||||
double kstVal = Math.FusedMultiplyAdd(3.0, sm3, Math.FusedMultiplyAdd(2.0, sm2, sm1))
|
double kstVal = Math.FusedMultiplyAdd(3.0, sm3, Math.FusedMultiplyAdd(2.0, sm2, sm1))
|
||||||
+ 4.0 * sm4;
|
+ (4.0 * sm4);
|
||||||
|
|
||||||
sigOut[i] = BatchStepSma(sigb, sigPeriod, ref sumSig, ref shSig, ref scSig, kstVal);
|
sigOut[i] = BatchStepSma(sigb, sigPeriod, ref sumSig, ref shSig, ref scSig, kstVal);
|
||||||
kstOut[i] = kstVal;
|
kstOut[i] = kstVal;
|
||||||
|
|||||||
@@ -135,7 +135,7 @@ public sealed class Mstoch : ITValuePublisher
|
|||||||
// === Stage 1: Highpass (2-pole Butterworth, removes trend) ===
|
// === Stage 1: Highpass (2-pole Butterworth, removes trend) ===
|
||||||
// HP = c1*(src - 2*src1 + src2) + c2*hp1 + c3*hp2
|
// HP = c1*(src - 2*src1 + src2) + c2*hp1 + c3*hp2
|
||||||
double hp = Math.FusedMultiplyAdd(
|
double hp = Math.FusedMultiplyAdd(
|
||||||
_hpC1, src - 2.0 * s.Src1 + s.Src2,
|
_hpC1, src - (2.0 * s.Src1) + s.Src2,
|
||||||
Math.FusedMultiplyAdd(_hpC2, s.Hp1, _hpC3 * s.Hp2));
|
Math.FusedMultiplyAdd(_hpC2, s.Hp1, _hpC3 * s.Hp2));
|
||||||
|
|
||||||
// === Stage 1: Super Smoother of HP => Filt ===
|
// === Stage 1: Super Smoother of HP => Filt ===
|
||||||
@@ -332,7 +332,7 @@ public sealed class Mstoch : ITValuePublisher
|
|||||||
}
|
}
|
||||||
|
|
||||||
double hp = Math.FusedMultiplyAdd(
|
double hp = Math.FusedMultiplyAdd(
|
||||||
hpC1, s - 2.0 * prevSrc1 + prevSrc2,
|
hpC1, s - (2.0 * prevSrc1) + prevSrc2,
|
||||||
Math.FusedMultiplyAdd(hpC2, prevHp1, hpC3 * prevHp2));
|
Math.FusedMultiplyAdd(hpC2, prevHp1, hpC3 * prevHp2));
|
||||||
|
|
||||||
double filtIn = (hp + prevHp1) * 0.5;
|
double filtIn = (hp + prevHp1) * 0.5;
|
||||||
|
|||||||
@@ -222,7 +222,7 @@ public sealed class Trendflex : AbstractBase
|
|||||||
// Always use Add (not UpdateNewest) because Snapshot/Restore already handles rollback
|
// Always use Add (not UpdateNewest) because Snapshot/Restore already handles rollback
|
||||||
buf.Add(filt);
|
buf.Add(filt);
|
||||||
int n = Math.Min(s.Count, period);
|
int n = Math.Min(s.Count, period);
|
||||||
double slopeSum = n > 0 ? (n * filt - buf.Sum) / period : 0.0;
|
double slopeSum = n > 0 ? ((n * filt) - buf.Sum) / period : 0.0;
|
||||||
|
|
||||||
// --- RMS normalization ---
|
// --- RMS normalization ---
|
||||||
s.Ms = Math.FusedMultiplyAdd(RMS_ALPHA, slopeSum * slopeSum, RMS_DECAY * s.Ms);
|
s.Ms = Math.FusedMultiplyAdd(RMS_ALPHA, slopeSum * slopeSum, RMS_DECAY * s.Ms);
|
||||||
@@ -272,7 +272,7 @@ public sealed class Trendflex : AbstractBase
|
|||||||
// Slope
|
// Slope
|
||||||
buf.Add(filt);
|
buf.Add(filt);
|
||||||
int n = Math.Min(s.Count, period);
|
int n = Math.Min(s.Count, period);
|
||||||
double slopeSum = n > 0 ? (n * filt - buf.Sum) / period : 0.0;
|
double slopeSum = n > 0 ? ((n * filt) - buf.Sum) / period : 0.0;
|
||||||
|
|
||||||
// RMS
|
// RMS
|
||||||
s.Ms = Math.FusedMultiplyAdd(RMS_ALPHA, slopeSum * slopeSum, RMS_DECAY * s.Ms);
|
s.Ms = Math.FusedMultiplyAdd(RMS_ALPHA, slopeSum * slopeSum, RMS_DECAY * s.Ms);
|
||||||
|
|||||||
@@ -424,7 +424,6 @@ public sealed class Ultosc : AbstractBase
|
|||||||
return (results, indicator);
|
return (results, indicator);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public override void Reset()
|
public override void Reset()
|
||||||
{
|
{
|
||||||
_bp1.Clear();
|
_bp1.Clear();
|
||||||
|
|||||||
@@ -240,8 +240,8 @@ public sealed class Chandelier : ITValuePublisher
|
|||||||
double lowestLow = _minDequeLow.GetExtremum(_lBuf);
|
double lowestLow = _minDequeLow.GetExtremum(_lBuf);
|
||||||
|
|
||||||
// Step 3: Chandelier exits — no second-stage smoothing
|
// Step 3: Chandelier exits — no second-stage smoothing
|
||||||
ExitLong = highestHigh - _multiplier * atr;
|
ExitLong = highestHigh - (_multiplier * atr);
|
||||||
ExitShort = lowestLow + _multiplier * atr;
|
ExitShort = lowestLow + (_multiplier * atr);
|
||||||
|
|
||||||
_s = s;
|
_s = s;
|
||||||
|
|
||||||
|
|||||||
@@ -241,8 +241,8 @@ public sealed class Ckstop : ITValuePublisher
|
|||||||
double lowestLow = _minDequeLow.GetExtremum(_lBuf);
|
double lowestLow = _minDequeLow.GetExtremum(_lBuf);
|
||||||
|
|
||||||
// Step 2b: First (initial) stops
|
// Step 2b: First (initial) stops
|
||||||
double initStopShort = highestHigh - _multiplier * atr;
|
double initStopShort = highestHigh - (_multiplier * atr);
|
||||||
double initStopLong = lowestLow + _multiplier * atr;
|
double initStopLong = lowestLow + (_multiplier * atr);
|
||||||
|
|
||||||
// Step 3: Track highest/lowest of initial stops over stopPeriod
|
// Step 3: Track highest/lowest of initial stops over stopPeriod
|
||||||
int sBufIdx = (int)(_index % _stopPeriod);
|
int sBufIdx = (int)(_index % _stopPeriod);
|
||||||
|
|||||||
@@ -179,15 +179,15 @@ public sealed class Pivotdem : ITValuePublisher
|
|||||||
double x;
|
double x;
|
||||||
if (pC < pO)
|
if (pC < pO)
|
||||||
{
|
{
|
||||||
x = pH + 2.0 * pL + pC; // Bearish: weight Low
|
x = pH + (2.0 * pL) + pC; // Bearish: weight Low
|
||||||
}
|
}
|
||||||
else if (pC > pO)
|
else if (pC > pO)
|
||||||
{
|
{
|
||||||
x = 2.0 * pH + pL + pC; // Bullish: weight High
|
x = (2.0 * pH) + pL + pC; // Bullish: weight High
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
x = pH + pL + 2.0 * pC; // Doji: weight Close
|
x = pH + pL + (2.0 * pC); // Doji: weight Close
|
||||||
}
|
}
|
||||||
|
|
||||||
double halfX = x * 0.5;
|
double halfX = x * 0.5;
|
||||||
@@ -331,9 +331,9 @@ public sealed class Pivotdem : ITValuePublisher
|
|||||||
double pC = close[i - 1];
|
double pC = close[i - 1];
|
||||||
|
|
||||||
double x;
|
double x;
|
||||||
if (pC < pO) { x = pH + 2.0 * pL + pC; }
|
if (pC < pO) { x = pH + (2.0 * pL) + pC; }
|
||||||
else if (pC > pO) { x = 2.0 * pH + pL + pC; }
|
else if (pC > pO) { x = (2.0 * pH) + pL + pC; }
|
||||||
else { x = pH + pL + 2.0 * pC; }
|
else { x = pH + pL + (2.0 * pC); }
|
||||||
|
|
||||||
ppOutput[i] = x * 0.25;
|
ppOutput[i] = x * 0.25;
|
||||||
}
|
}
|
||||||
@@ -403,9 +403,9 @@ public sealed class Pivotdem : ITValuePublisher
|
|||||||
double pC = close[i - 1];
|
double pC = close[i - 1];
|
||||||
|
|
||||||
double x;
|
double x;
|
||||||
if (pC < pO) { x = pH + 2.0 * pL + pC; }
|
if (pC < pO) { x = pH + (2.0 * pL) + pC; }
|
||||||
else if (pC > pO) { x = 2.0 * pH + pL + pC; }
|
else if (pC > pO) { x = (2.0 * pH) + pL + pC; }
|
||||||
else { x = pH + pL + 2.0 * pC; }
|
else { x = pH + pL + (2.0 * pC); }
|
||||||
|
|
||||||
double halfX = x * 0.5;
|
double halfX = x * 0.5;
|
||||||
ppOut[i] = x * 0.25;
|
ppOut[i] = x * 0.25;
|
||||||
|
|||||||
@@ -101,7 +101,7 @@ public sealed class Swings : ITValuePublisher
|
|||||||
}
|
}
|
||||||
|
|
||||||
_lookback = lookback;
|
_lookback = lookback;
|
||||||
_windowSize = 2 * lookback + 1;
|
_windowSize = (2 * lookback) + 1;
|
||||||
|
|
||||||
_hBuf = new double[_windowSize];
|
_hBuf = new double[_windowSize];
|
||||||
_lBuf = new double[_windowSize];
|
_lBuf = new double[_windowSize];
|
||||||
@@ -361,7 +361,7 @@ public sealed class Swings : ITValuePublisher
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int windowSize = 2 * lookback + 1;
|
int windowSize = (2 * lookback) + 1;
|
||||||
|
|
||||||
// Fill warmup bars with NaN
|
// Fill warmup bars with NaN
|
||||||
int warmup = Math.Min(windowSize - 1, len);
|
int warmup = Math.Min(windowSize - 1, len);
|
||||||
|
|||||||
@@ -189,7 +189,6 @@ public sealed class Granger : AbstractBase
|
|||||||
double oldY = _windowY.Oldest;
|
double oldY = _windowY.Oldest;
|
||||||
double oldYLag = _windowYLag.Oldest;
|
double oldYLag = _windowYLag.Oldest;
|
||||||
double oldXLag = _windowXLag.Oldest;
|
double oldXLag = _windowXLag.Oldest;
|
||||||
|
|
||||||
{ double yk = -oldY - _sumYComp; double t = _sumY + yk; _sumYComp = (t - _sumY) - yk; _sumY = t; }
|
{ double yk = -oldY - _sumYComp; double t = _sumY + yk; _sumYComp = (t - _sumY) - yk; _sumY = t; }
|
||||||
{ double yk = -oldYLag - _sumYLagComp; double t = _sumYLag + yk; _sumYLagComp = (t - _sumYLag) - yk; _sumYLag = t; }
|
{ double yk = -oldYLag - _sumYLagComp; double t = _sumYLag + yk; _sumYLagComp = (t - _sumYLag) - yk; _sumYLag = t; }
|
||||||
{ double yk = -oldXLag - _sumXLagComp; double t = _sumXLag + yk; _sumXLagComp = (t - _sumXLag) - yk; _sumXLag = t; }
|
{ double yk = -oldXLag - _sumXLagComp; double t = _sumXLag + yk; _sumXLagComp = (t - _sumXLag) - yk; _sumXLag = t; }
|
||||||
@@ -205,7 +204,6 @@ public sealed class Granger : AbstractBase
|
|||||||
_windowY.Add(y);
|
_windowY.Add(y);
|
||||||
_windowYLag.Add(yLag);
|
_windowYLag.Add(yLag);
|
||||||
_windowXLag.Add(xLag);
|
_windowXLag.Add(xLag);
|
||||||
|
|
||||||
{ double yk = y - _sumYComp; double t = _sumY + yk; _sumYComp = (t - _sumY) - yk; _sumY = t; }
|
{ double yk = y - _sumYComp; double t = _sumY + yk; _sumYComp = (t - _sumY) - yk; _sumY = t; }
|
||||||
{ double yk = yLag - _sumYLagComp; double t = _sumYLag + yk; _sumYLagComp = (t - _sumYLag) - yk; _sumYLag = t; }
|
{ double yk = yLag - _sumYLagComp; double t = _sumYLag + yk; _sumYLagComp = (t - _sumYLag) - yk; _sumYLag = t; }
|
||||||
{ double yk = xLag - _sumXLagComp; double t = _sumXLag + yk; _sumXLagComp = (t - _sumXLag) - yk; _sumXLag = t; }
|
{ double yk = xLag - _sumXLagComp; double t = _sumXLag + yk; _sumXLagComp = (t - _sumXLag) - yk; _sumXLag = t; }
|
||||||
|
|||||||
@@ -357,7 +357,7 @@ public sealed class Jb : AbstractBase
|
|||||||
double meanSq = mean * mean;
|
double meanSq = mean * mean;
|
||||||
|
|
||||||
// m₂ = (Σx² - Σx²/n) / n
|
// m₂ = (Σx² - Σx²/n) / n
|
||||||
double m2Numerator = sumSq - (sum * sum) / n;
|
double m2Numerator = sumSq - ((sum * sum) / n);
|
||||||
if (m2Numerator < Epsilon)
|
if (m2Numerator < Epsilon)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
@@ -479,8 +479,8 @@ public sealed class Jb : AbstractBase
|
|||||||
// Kahan subtract old, add new
|
// Kahan subtract old, add new
|
||||||
{ double y = (val - oldVal) - sumComp; double t = sum + y; sumComp = (t - sum) - y; sum = t; }
|
{ double y = (val - oldVal) - sumComp; double t = sum + y; sumComp = (t - sum) - y; sum = t; }
|
||||||
{ double y = (vSq - oSq) - sumSqComp; double t = sumSq + y; sumSqComp = (t - sumSq) - y; sumSq = t; }
|
{ double y = (vSq - oSq) - sumSqComp; double t = sumSq + y; sumSqComp = (t - sumSq) - y; sumSq = t; }
|
||||||
{ double y = (vSq * val - oSq * oldVal) - sumCuComp; double t = sumCu + y; sumCuComp = (t - sumCu) - y; sumCu = t; }
|
{ double y = ((vSq * val) - (oSq * oldVal)) - sumCuComp; double t = sumCu + y; sumCuComp = (t - sumCu) - y; sumCu = t; }
|
||||||
{ double y = (vSq * vSq - oSq * oSq) - sumQuComp; double t = sumQu + y; sumQuComp = (t - sumQu) - y; sumQu = t; }
|
{ double y = ((vSq * vSq) - (oSq * oSq)) - sumQuComp; double t = sumQu + y; sumQuComp = (t - sumQu) - y; sumQu = t; }
|
||||||
|
|
||||||
output[i] = CalculateJbFromSums(sum, sumSq, sumCu, sumQu, period);
|
output[i] = CalculateJbFromSums(sum, sumSq, sumCu, sumQu, period);
|
||||||
}
|
}
|
||||||
@@ -540,7 +540,7 @@ public sealed class Jb : AbstractBase
|
|||||||
var vEpsilon = Vector256.Create(Epsilon);
|
var vEpsilon = Vector256.Create(Epsilon);
|
||||||
var vZero = Vector256<double>.Zero;
|
var vZero = Vector256<double>.Zero;
|
||||||
|
|
||||||
int simdEnd = period + ((len - period) / VectorWidth) * VectorWidth;
|
int simdEnd = period + (((len - period) / VectorWidth) * VectorWidth);
|
||||||
|
|
||||||
for (int i = period; i < simdEnd; i += VectorWidth)
|
for (int i = period; i < simdEnd; i += VectorWidth)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -94,10 +94,10 @@ public sealed class LinReg : AbstractBase
|
|||||||
_sum_x = 0.5 * period * (period - 1);
|
_sum_x = 0.5 * period * (period - 1);
|
||||||
|
|
||||||
// sum_x2 = 0^2 + ... + (n-1)^2 = (n-1)n(2n-1)/6
|
// sum_x2 = 0^2 + ... + (n-1)^2 = (n-1)n(2n-1)/6
|
||||||
double sum_x2 = (period - 1.0) * period * (2.0 * period - 1.0) / 6.0;
|
double sum_x2 = (period - 1.0) * period * ((2.0 * period) - 1.0) / 6.0;
|
||||||
|
|
||||||
// denominator = n * sum_x2 - sum_x^2
|
// denominator = n * sum_x2 - sum_x^2
|
||||||
_denominator = period * sum_x2 - _sum_x * _sum_x;
|
_denominator = (period * sum_x2) - (_sum_x * _sum_x);
|
||||||
}
|
}
|
||||||
|
|
||||||
public LinReg(ITValuePublisher source, int period, int offset = 0) : this(period, offset)
|
public LinReg(ITValuePublisher source, int period, int offset = 0) : this(period, offset)
|
||||||
@@ -130,7 +130,7 @@ public sealed class LinReg : AbstractBase
|
|||||||
// O(1) update for sum_xy with Kahan compensation
|
// O(1) update for sum_xy with Kahan compensation
|
||||||
// sum_xy_new = sum_xy_old + sum_y_prev - n * oldest
|
// sum_xy_new = sum_xy_old + sum_y_prev - n * oldest
|
||||||
{
|
{
|
||||||
double delta = prev_sum_y - _period * oldest;
|
double delta = prev_sum_y - (_period * oldest);
|
||||||
double y = delta - _state.SumXYComp;
|
double y = delta - _state.SumXYComp;
|
||||||
double t = _state.SumXY + y;
|
double t = _state.SumXY + y;
|
||||||
_state.SumXYComp = (t - _state.SumXY) - y;
|
_state.SumXYComp = (t - _state.SumXY) - y;
|
||||||
@@ -148,7 +148,7 @@ public sealed class LinReg : AbstractBase
|
|||||||
|
|
||||||
// O(1) update for sum_y2 with Kahan: subtract oldest², add val²
|
// O(1) update for sum_y2 with Kahan: subtract oldest², add val²
|
||||||
{
|
{
|
||||||
double delta = val * val - oldest * oldest;
|
double delta = (val * val) - (oldest * oldest);
|
||||||
double y = delta - _state.SumY2Comp;
|
double y = delta - _state.SumY2Comp;
|
||||||
double t = _state.SumY2 + y;
|
double t = _state.SumY2 + y;
|
||||||
_state.SumY2Comp = (t - _state.SumY2) - y;
|
_state.SumY2Comp = (t - _state.SumY2) - y;
|
||||||
@@ -235,8 +235,8 @@ public sealed class LinReg : AbstractBase
|
|||||||
if (!_buffer.IsFull)
|
if (!_buffer.IsFull)
|
||||||
{
|
{
|
||||||
sx = 0.5 * n * (n - 1);
|
sx = 0.5 * n * (n - 1);
|
||||||
double sx2 = (n - 1.0) * n * (2.0 * n - 1.0) / 6.0;
|
double sx2 = (n - 1.0) * n * ((2.0 * n) - 1.0) / 6.0;
|
||||||
denom = n * sx2 - sx * sx;
|
denom = (n * sx2) - (sx * sx);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Math.Abs(denom) < MinDenominator)
|
if (Math.Abs(denom) < MinDenominator)
|
||||||
@@ -379,7 +379,6 @@ public sealed class LinReg : AbstractBase
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
|
||||||
double sum_y = 0;
|
double sum_y = 0;
|
||||||
double sum_xy = 0;
|
double sum_xy = 0;
|
||||||
double sumYComp = 0; // Kahan compensation for sum_y
|
double sumYComp = 0; // Kahan compensation for sum_y
|
||||||
@@ -389,8 +388,8 @@ public sealed class LinReg : AbstractBase
|
|||||||
int count = 0;
|
int count = 0;
|
||||||
|
|
||||||
double full_sum_x = 0.5 * period * (period - 1);
|
double full_sum_x = 0.5 * period * (period - 1);
|
||||||
double full_sum_x2 = (period - 1.0) * period * (2.0 * period - 1.0) / 6.0;
|
double full_sum_x2 = (period - 1.0) * period * ((2.0 * period) - 1.0) / 6.0;
|
||||||
double full_denom = period * full_sum_x2 - full_sum_x * full_sum_x;
|
double full_denom = (period * full_sum_x2) - (full_sum_x * full_sum_x);
|
||||||
|
|
||||||
for (int i = 0; i < len; i++)
|
for (int i = 0; i < len; i++)
|
||||||
{
|
{
|
||||||
@@ -424,8 +423,8 @@ public sealed class LinReg : AbstractBase
|
|||||||
{
|
{
|
||||||
double n = count;
|
double n = count;
|
||||||
double sx = 0.5 * n * (n - 1);
|
double sx = 0.5 * n * (n - 1);
|
||||||
double sx2 = (n - 1.0) * n * (2.0 * n - 1.0) / 6.0;
|
double sx2 = (n - 1.0) * n * ((2.0 * n) - 1.0) / 6.0;
|
||||||
double denom = n * sx2 - sx * sx;
|
double denom = (n * sx2) - (sx * sx);
|
||||||
|
|
||||||
if (Math.Abs(denom) < MinDenominator)
|
if (Math.Abs(denom) < MinDenominator)
|
||||||
{
|
{
|
||||||
@@ -454,7 +453,7 @@ public sealed class LinReg : AbstractBase
|
|||||||
|
|
||||||
// Kahan compensated update for sum_xy
|
// Kahan compensated update for sum_xy
|
||||||
{
|
{
|
||||||
double delta = prev_sum_y - period * oldest;
|
double delta = prev_sum_y - (period * oldest);
|
||||||
double y = delta - sumXYComp;
|
double y = delta - sumXYComp;
|
||||||
double t = sum_xy + y;
|
double t = sum_xy + y;
|
||||||
sumXYComp = (t - sum_xy) - y;
|
sumXYComp = (t - sum_xy) - y;
|
||||||
|
|||||||
@@ -263,7 +263,7 @@ public sealed class Pacf : AbstractBase
|
|||||||
// Update coefficients: φ_kj = φ_{k-1,j} - φ_kk * φ_{k-1,k-j}
|
// Update coefficients: φ_kj = φ_{k-1,j} - φ_kk * φ_{k-1,k-j}
|
||||||
for (int j = 1; j < k; j++)
|
for (int j = 1; j < k; j++)
|
||||||
{
|
{
|
||||||
phi[j] = phiPrev[j] - phi[k] * phiPrev[k - j];
|
phi[j] = phiPrev[j] - (phi[k] * phiPrev[k - j]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -100,7 +100,7 @@ public sealed class Polyfit : AbstractBase
|
|||||||
|
|
||||||
// Power sums and cross products accumulate with normalized t ∈ [0, 1].
|
// Power sums and cross products accumulate with normalized t ∈ [0, 1].
|
||||||
// Max degree=6 → sz=7, matrix=7*8=56 doubles + powSums=13 + crossSums=7 — all stackalloc safe.
|
// Max degree=6 → sz=7, matrix=7*8=56 doubles + powSums=13 + crossSums=7 — all stackalloc safe.
|
||||||
Span<double> powSums = stackalloc double[2 * m + 1];
|
Span<double> powSums = stackalloc double[(2 * m) + 1];
|
||||||
Span<double> crossSums = stackalloc double[sz];
|
Span<double> crossSums = stackalloc double[sz];
|
||||||
Span<double> aug = stackalloc double[sz * (sz + 1)]; // augmented matrix row-major
|
Span<double> aug = stackalloc double[sz * (sz + 1)]; // augmented matrix row-major
|
||||||
|
|
||||||
@@ -133,19 +133,19 @@ public sealed class Polyfit : AbstractBase
|
|||||||
{
|
{
|
||||||
for (int col = 0; col < sz; col++)
|
for (int col = 0; col < sz; col++)
|
||||||
{
|
{
|
||||||
aug[row * stride + col] = powSums[row + col];
|
aug[(row * stride) + col] = powSums[row + col];
|
||||||
}
|
}
|
||||||
aug[row * stride + sz] = crossSums[row];
|
aug[(row * stride) + sz] = crossSums[row];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Gaussian elimination with partial pivoting
|
// Gaussian elimination with partial pivoting
|
||||||
for (int col = 0; col < sz; col++)
|
for (int col = 0; col < sz; col++)
|
||||||
{
|
{
|
||||||
int pivotRow = col;
|
int pivotRow = col;
|
||||||
double pivotMax = Math.Abs(aug[col * stride + col]);
|
double pivotMax = Math.Abs(aug[(col * stride) + col]);
|
||||||
for (int row = col + 1; row < sz; row++)
|
for (int row = col + 1; row < sz; row++)
|
||||||
{
|
{
|
||||||
double absVal = Math.Abs(aug[row * stride + col]);
|
double absVal = Math.Abs(aug[(row * stride) + col]);
|
||||||
if (absVal > pivotMax)
|
if (absVal > pivotMax)
|
||||||
{
|
{
|
||||||
pivotMax = absVal;
|
pivotMax = absVal;
|
||||||
@@ -168,13 +168,13 @@ public sealed class Polyfit : AbstractBase
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
double diag = aug[col * stride + col];
|
double diag = aug[(col * stride) + col];
|
||||||
for (int row = col + 1; row < sz; row++)
|
for (int row = col + 1; row < sz; row++)
|
||||||
{
|
{
|
||||||
double factor = aug[row * stride + col] / diag;
|
double factor = aug[(row * stride) + col] / diag;
|
||||||
for (int k = col; k <= sz; k++)
|
for (int k = col; k <= sz; k++)
|
||||||
{
|
{
|
||||||
aug[row * stride + k] = Math.FusedMultiplyAdd(-factor, aug[col * stride + k], aug[row * stride + k]);
|
aug[(row * stride) + k] = Math.FusedMultiplyAdd(-factor, aug[(col * stride) + k], aug[(row * stride) + k]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -183,12 +183,12 @@ public sealed class Polyfit : AbstractBase
|
|||||||
Span<double> a = stackalloc double[sz];
|
Span<double> a = stackalloc double[sz];
|
||||||
for (int row = sz - 1; row >= 0; row--)
|
for (int row = sz - 1; row >= 0; row--)
|
||||||
{
|
{
|
||||||
double val = aug[row * stride + sz];
|
double val = aug[(row * stride) + sz];
|
||||||
for (int k = row + 1; k < sz; k++)
|
for (int k = row + 1; k < sz; k++)
|
||||||
{
|
{
|
||||||
val = Math.FusedMultiplyAdd(-aug[row * stride + k], a[k], val);
|
val = Math.FusedMultiplyAdd(-aug[(row * stride) + k], a[k], val);
|
||||||
}
|
}
|
||||||
a[row] = val / aug[row * stride + row];
|
a[row] = val / aug[(row * stride) + row];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Evaluate polynomial at t=1: P(1) = a0 + a1 + a2 + ... + am
|
// Evaluate polynomial at t=1: P(1) = a0 + a1 + a2 + ... + am
|
||||||
|
|||||||
@@ -81,8 +81,8 @@ public sealed class Stderr : AbstractBase
|
|||||||
|
|
||||||
// Precompute fixed regression constants
|
// Precompute fixed regression constants
|
||||||
_sumX = 0.5 * period * (period - 1);
|
_sumX = 0.5 * period * (period - 1);
|
||||||
_sumX2 = (period - 1.0) * period * (2.0 * period - 1.0) / 6.0;
|
_sumX2 = (period - 1.0) * period * ((2.0 * period) - 1.0) / 6.0;
|
||||||
_denom = period * _sumX2 - _sumX * _sumX;
|
_denom = (period * _sumX2) - (_sumX * _sumX);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>Creates a chaining constructor that subscribes to an upstream publisher.</summary>
|
/// <summary>Creates a chaining constructor that subscribes to an upstream publisher.</summary>
|
||||||
@@ -133,7 +133,7 @@ public sealed class Stderr : AbstractBase
|
|||||||
|
|
||||||
// Correct running sums for newest bar change
|
// Correct running sums for newest bar change
|
||||||
_sumY = _p_sumY - _p_lastVal + val;
|
_sumY = _p_sumY - _p_lastVal + val;
|
||||||
_sumXY = _p_sumXY - (_period - 1) * (_p_lastVal - val);
|
_sumXY = _p_sumXY - ((_period - 1) * (_p_lastVal - val));
|
||||||
// Re-derive sumXY correctly via recalculation to avoid drift on bar corrections
|
// Re-derive sumXY correctly via recalculation to avoid drift on bar corrections
|
||||||
if (_buffer.Count > 0)
|
if (_buffer.Count > 0)
|
||||||
{
|
{
|
||||||
@@ -211,7 +211,7 @@ public sealed class Stderr : AbstractBase
|
|||||||
// O(1) update for sumXY with Kahan compensation
|
// O(1) update for sumXY with Kahan compensation
|
||||||
// ΣXY_new = ΣXY_old - ΣY_old + oldest + (N-1)*val
|
// ΣXY_new = ΣXY_old - ΣY_old + oldest + (N-1)*val
|
||||||
{
|
{
|
||||||
double delta = -prevSumY + oldest + (_period - 1) * val;
|
double delta = -prevSumY + oldest + ((_period - 1) * val);
|
||||||
double y = delta - _sumXYComp;
|
double y = delta - _sumXYComp;
|
||||||
double t = _sumXY + y;
|
double t = _sumXY + y;
|
||||||
_sumXYComp = (t - _sumXY) - y;
|
_sumXYComp = (t - _sumXY) - y;
|
||||||
@@ -266,16 +266,16 @@ public sealed class Stderr : AbstractBase
|
|||||||
double sumY = _sumY;
|
double sumY = _sumY;
|
||||||
double sumXY = _sumXY;
|
double sumXY = _sumXY;
|
||||||
double sumX = (n == _period) ? _sumX : 0.5 * n * (n - 1);
|
double sumX = (n == _period) ? _sumX : 0.5 * n * (n - 1);
|
||||||
double sumX2 = (n == _period) ? _sumX2 : (n - 1.0) * n * (2.0 * n - 1.0) / 6.0;
|
double sumX2 = (n == _period) ? _sumX2 : (n - 1.0) * n * ((2.0 * n) - 1.0) / 6.0;
|
||||||
double denom = (n == _period) ? _denom : n * sumX2 - sumX * sumX;
|
double denom = (n == _period) ? _denom : (n * sumX2) - (sumX * sumX);
|
||||||
|
|
||||||
if (denom == 0)
|
if (denom == 0)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
double slope = (n * sumXY - sumX * sumY) / denom;
|
double slope = ((n * sumXY) - (sumX * sumY)) / denom;
|
||||||
double intercept = (sumY - slope * sumX) / n;
|
double intercept = (sumY - (slope * sumX)) / n;
|
||||||
|
|
||||||
// O(N): accumulate residual sum of squares
|
// O(N): accumulate residual sum of squares
|
||||||
double ssr = 0;
|
double ssr = 0;
|
||||||
@@ -437,8 +437,8 @@ public sealed class Stderr : AbstractBase
|
|||||||
|
|
||||||
// Precompute constants for full period window
|
// Precompute constants for full period window
|
||||||
double sumXFull = 0.5 * period * (period - 1);
|
double sumXFull = 0.5 * period * (period - 1);
|
||||||
double sumX2Full = (period - 1.0) * period * (2.0 * period - 1.0) / 6.0;
|
double sumX2Full = (period - 1.0) * period * ((2.0 * period) - 1.0) / 6.0;
|
||||||
double denomFull = period * sumX2Full - sumXFull * sumXFull;
|
double denomFull = (period * sumX2Full) - (sumXFull * sumXFull);
|
||||||
|
|
||||||
double sumY = 0;
|
double sumY = 0;
|
||||||
double sumXY = 0;
|
double sumXY = 0;
|
||||||
@@ -480,7 +480,7 @@ public sealed class Stderr : AbstractBase
|
|||||||
|
|
||||||
// O(1) Kahan compensated update for sumXY
|
// O(1) Kahan compensated update for sumXY
|
||||||
{
|
{
|
||||||
double delta = -sumY + oldest + (period - 1) * newest;
|
double delta = -sumY + oldest + ((period - 1) * newest);
|
||||||
double y = delta - sumXYComp;
|
double y = delta - sumXYComp;
|
||||||
double t = sumXY + y;
|
double t = sumXY + y;
|
||||||
sumXYComp = (t - sumXY) - y;
|
sumXYComp = (t - sumXY) - y;
|
||||||
@@ -496,8 +496,8 @@ public sealed class Stderr : AbstractBase
|
|||||||
sumY = t;
|
sumY = t;
|
||||||
}
|
}
|
||||||
|
|
||||||
double slope = (period * sumXY - sumXFull * sumY) / denomFull;
|
double slope = ((period * sumXY) - (sumXFull * sumY)) / denomFull;
|
||||||
double intercept = (sumY - slope * sumXFull) / period;
|
double intercept = (sumY - (slope * sumXFull)) / period;
|
||||||
|
|
||||||
double ssr = 0;
|
double ssr = 0;
|
||||||
int start = i - period + 1;
|
int start = i - period + 1;
|
||||||
@@ -529,16 +529,16 @@ public sealed class Stderr : AbstractBase
|
|||||||
}
|
}
|
||||||
|
|
||||||
double sumX = 0.5 * n * (n - 1);
|
double sumX = 0.5 * n * (n - 1);
|
||||||
double sumX2 = (n - 1.0) * n * (2.0 * n - 1.0) / 6.0;
|
double sumX2 = (n - 1.0) * n * ((2.0 * n) - 1.0) / 6.0;
|
||||||
double denom = n * sumX2 - sumX * sumX;
|
double denom = (n * sumX2) - (sumX * sumX);
|
||||||
|
|
||||||
if (denom == 0)
|
if (denom == 0)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
double slope = (n * sumXY - sumX * sumY) / denom;
|
double slope = ((n * sumXY) - (sumX * sumY)) / denom;
|
||||||
double intercept = (sumY - slope * sumX) / n;
|
double intercept = (sumY - (slope * sumX)) / n;
|
||||||
|
|
||||||
double ssr = 0;
|
double ssr = 0;
|
||||||
for (int k = 0; k < n; k++)
|
for (int k = 0; k < n; k++)
|
||||||
|
|||||||
@@ -314,7 +314,7 @@ public sealed class Trim : AbstractBase
|
|||||||
}
|
}
|
||||||
|
|
||||||
int trimCount = (int)(count * trimPct / 100.0);
|
int trimCount = (int)(count * trimPct / 100.0);
|
||||||
int keepCount = count - 2 * trimCount;
|
int keepCount = count - (2 * trimCount);
|
||||||
|
|
||||||
if (keepCount < 1)
|
if (keepCount < 1)
|
||||||
{
|
{
|
||||||
@@ -341,7 +341,7 @@ public sealed class Trim : AbstractBase
|
|||||||
}
|
}
|
||||||
|
|
||||||
int trimCount = (int)(count * trimPct / 100.0);
|
int trimCount = (int)(count * trimPct / 100.0);
|
||||||
int keepCount = count - 2 * trimCount;
|
int keepCount = count - (2 * trimCount);
|
||||||
|
|
||||||
if (keepCount < 1)
|
if (keepCount < 1)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -306,7 +306,7 @@ public sealed class Variance : AbstractBase
|
|||||||
}
|
}
|
||||||
// Kahan sliding window for sumSq: sumSq += (val² - oldVal²)
|
// Kahan sliding window for sumSq: sumSq += (val² - oldVal²)
|
||||||
{
|
{
|
||||||
double delta = (val * val - oldVal * oldVal) - sumSqComp;
|
double delta = ((val * val) - (oldVal * oldVal)) - sumSqComp;
|
||||||
double t = sumSq + delta;
|
double t = sumSq + delta;
|
||||||
sumSqComp = (t - sumSq) - delta;
|
sumSqComp = (t - sumSq) - delta;
|
||||||
sumSq = t;
|
sumSq = t;
|
||||||
|
|||||||
@@ -127,7 +127,7 @@ public sealed class Zscore : AbstractBase
|
|||||||
double sum = _buffer.Sum;
|
double sum = _buffer.Sum;
|
||||||
double mean = sum / n;
|
double mean = sum / n;
|
||||||
|
|
||||||
double numerator = _sumSq - (sum * sum) / n;
|
double numerator = _sumSq - ((sum * sum) / n);
|
||||||
if (numerator < 0)
|
if (numerator < 0)
|
||||||
{
|
{
|
||||||
numerator = 0;
|
numerator = 0;
|
||||||
@@ -317,7 +317,7 @@ public sealed class Zscore : AbstractBase
|
|||||||
int n = count;
|
int n = count;
|
||||||
double mean = sum / n;
|
double mean = sum / n;
|
||||||
|
|
||||||
double numerator = sumSq - (sum * sum) / n;
|
double numerator = sumSq - ((sum * sum) / n);
|
||||||
if (numerator < 0)
|
if (numerator < 0)
|
||||||
{
|
{
|
||||||
numerator = 0;
|
numerator = 0;
|
||||||
|
|||||||
@@ -132,7 +132,7 @@ public sealed class Ztest : AbstractBase
|
|||||||
double sum = _buffer.Sum;
|
double sum = _buffer.Sum;
|
||||||
double mean = sum / n;
|
double mean = sum / n;
|
||||||
|
|
||||||
double numerator = _sumSq - (sum * sum) / n;
|
double numerator = _sumSq - ((sum * sum) / n);
|
||||||
if (numerator < 0)
|
if (numerator < 0)
|
||||||
{
|
{
|
||||||
numerator = 0;
|
numerator = 0;
|
||||||
@@ -325,7 +325,7 @@ public sealed class Ztest : AbstractBase
|
|||||||
int n = count;
|
int n = count;
|
||||||
double mean = sum / n;
|
double mean = sum / n;
|
||||||
|
|
||||||
double numerator = sumSq - (sum * sum) / n;
|
double numerator = sumSq - ((sum * sum) / n);
|
||||||
if (numerator < 0)
|
if (numerator < 0)
|
||||||
{
|
{
|
||||||
numerator = 0;
|
numerator = 0;
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ public sealed class Bwma : AbstractBase
|
|||||||
|
|
||||||
_period = period;
|
_period = period;
|
||||||
_order = order;
|
_order = order;
|
||||||
_power = order * 0.5 + 0.5;
|
_power = (order * 0.5) + 0.5;
|
||||||
_buffer = new RingBuffer(period);
|
_buffer = new RingBuffer(period);
|
||||||
_weights = new double[period];
|
_weights = new double[period];
|
||||||
Name = $"Bwma({period}, {order})";
|
Name = $"Bwma({period}, {order})";
|
||||||
@@ -101,12 +101,12 @@ public sealed class Bwma : AbstractBase
|
|||||||
{
|
{
|
||||||
double sum = 0;
|
double sum = 0;
|
||||||
double scale = period > 1 ? 2.0 / (period - 1) : 0.0;
|
double scale = period > 1 ? 2.0 / (period - 1) : 0.0;
|
||||||
double power = order * 0.5 + 0.5;
|
double power = (order * 0.5) + 0.5;
|
||||||
|
|
||||||
for (int i = 0; i < period; i++)
|
for (int i = 0; i < period; i++)
|
||||||
{
|
{
|
||||||
double x = period > 1 ? i * scale - 1.0 : 0.0;
|
double x = period > 1 ? (i * scale) - 1.0 : 0.0;
|
||||||
double arg = 1.0 - x * x;
|
double arg = 1.0 - (x * x);
|
||||||
|
|
||||||
double w;
|
double w;
|
||||||
if (arg > 0.0)
|
if (arg > 0.0)
|
||||||
@@ -366,7 +366,7 @@ public sealed class Bwma : AbstractBase
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
double power = order * 0.5 + 0.5;
|
double power = (order * 0.5) + 0.5;
|
||||||
|
|
||||||
if (period > len)
|
if (period > len)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -120,10 +120,10 @@ public sealed class Crma : AbstractBase
|
|||||||
{
|
{
|
||||||
// Find pivot row
|
// Find pivot row
|
||||||
int pivotRow = col;
|
int pivotRow = col;
|
||||||
double pivotMax = Math.Abs(m[col * 5 + col]);
|
double pivotMax = Math.Abs(m[(col * 5) + col]);
|
||||||
for (int row = col + 1; row < 4; row++)
|
for (int row = col + 1; row < 4; row++)
|
||||||
{
|
{
|
||||||
double absVal = Math.Abs(m[row * 5 + col]);
|
double absVal = Math.Abs(m[(row * 5) + col]);
|
||||||
if (absVal > pivotMax)
|
if (absVal > pivotMax)
|
||||||
{
|
{
|
||||||
pivotMax = absVal;
|
pivotMax = absVal;
|
||||||
@@ -148,13 +148,13 @@ public sealed class Crma : AbstractBase
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Eliminate below
|
// Eliminate below
|
||||||
double diag = m[col * 5 + col];
|
double diag = m[(col * 5) + col];
|
||||||
for (int row = col + 1; row < 4; row++)
|
for (int row = col + 1; row < 4; row++)
|
||||||
{
|
{
|
||||||
double factor = m[row * 5 + col] / diag;
|
double factor = m[(row * 5) + col] / diag;
|
||||||
for (int k = col; k < 5; k++)
|
for (int k = col; k < 5; k++)
|
||||||
{
|
{
|
||||||
m[row * 5 + k] = Math.FusedMultiplyAdd(-factor, m[col * 5 + k], m[row * 5 + k]);
|
m[(row * 5) + k] = Math.FusedMultiplyAdd(-factor, m[(col * 5) + k], m[(row * 5) + k]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -163,12 +163,12 @@ public sealed class Crma : AbstractBase
|
|||||||
Span<double> a = stackalloc double[4];
|
Span<double> a = stackalloc double[4];
|
||||||
for (int row = 3; row >= 0; row--)
|
for (int row = 3; row >= 0; row--)
|
||||||
{
|
{
|
||||||
double val = m[row * 5 + 4];
|
double val = m[(row * 5) + 4];
|
||||||
for (int k = row + 1; k < 4; k++)
|
for (int k = row + 1; k < 4; k++)
|
||||||
{
|
{
|
||||||
val = Math.FusedMultiplyAdd(-m[row * 5 + k], a[k], val);
|
val = Math.FusedMultiplyAdd(-m[(row * 5) + k], a[k], val);
|
||||||
}
|
}
|
||||||
a[row] = val / m[row * 5 + row];
|
a[row] = val / m[(row * 5) + row];
|
||||||
}
|
}
|
||||||
|
|
||||||
return a[0]; // Fitted value at x=0 (newest bar)
|
return a[0]; // Fitted value at x=0 (newest bar)
|
||||||
|
|||||||
@@ -109,7 +109,7 @@ public sealed class Hamma : AbstractBase
|
|||||||
double twoPiOverPm1 = 2.0 * Math.PI / (period - 1);
|
double twoPiOverPm1 = 2.0 * Math.PI / (period - 1);
|
||||||
for (int i = 0; i < period; i++)
|
for (int i = 0; i < period; i++)
|
||||||
{
|
{
|
||||||
double w = 0.54 - 0.46 * Math.Cos(twoPiOverPm1 * i);
|
double w = 0.54 - (0.46 * Math.Cos(twoPiOverPm1 * i));
|
||||||
weights[i] = w;
|
weights[i] = w;
|
||||||
sum += w;
|
sum += w;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -80,14 +80,14 @@ public sealed class Hend : AbstractBase
|
|||||||
double n2 = n * n;
|
double n2 = n * n;
|
||||||
double nm1_2 = (n - 1) * (n - 1);
|
double nm1_2 = (n - 1) * (n - 1);
|
||||||
double np1_2 = (n + 1) * (n + 1);
|
double np1_2 = (n + 1) * (n + 1);
|
||||||
double denom = 8.0 * n * (n2 - 1) * (4 * n2 - 1) * (4 * n2 - 9) * (4 * n2 - 25);
|
double denom = 8.0 * n * (n2 - 1) * ((4 * n2) - 1) * ((4 * n2) - 9) * ((4 * n2) - 25);
|
||||||
|
|
||||||
double wsum = 0.0;
|
double wsum = 0.0;
|
||||||
for (int i = 0; i < period; i++)
|
for (int i = 0; i < period; i++)
|
||||||
{
|
{
|
||||||
int k = i - half;
|
int k = i - half;
|
||||||
double k2 = (double)(k * k);
|
double k2 = (double)(k * k);
|
||||||
double w = 315.0 * (nm1_2 - k2) * (n2 - k2) * (np1_2 - k2) * (3 * n2 - 16 - 11 * k2) / denom;
|
double w = 315.0 * (nm1_2 - k2) * (n2 - k2) * (np1_2 - k2) * ((3 * n2) - 16 - (11 * k2)) / denom;
|
||||||
weights[i] = w;
|
weights[i] = w;
|
||||||
wsum += w;
|
wsum += w;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -63,8 +63,8 @@ public sealed class Ilrs : AbstractBase
|
|||||||
|
|
||||||
// Precompute constants (reversed-x convention: x=0=newest, x=n-1=oldest)
|
// Precompute constants (reversed-x convention: x=0=newest, x=n-1=oldest)
|
||||||
_sumX = 0.5 * period * (period - 1);
|
_sumX = 0.5 * period * (period - 1);
|
||||||
double sumX2 = (period - 1.0) * period * (2.0 * period - 1.0) / 6.0;
|
double sumX2 = (period - 1.0) * period * ((2.0 * period) - 1.0) / 6.0;
|
||||||
_denominator = period * sumX2 - _sumX * _sumX;
|
_denominator = (period * sumX2) - (_sumX * _sumX);
|
||||||
_s.LastValidValue = double.NaN;
|
_s.LastValidValue = double.NaN;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -239,8 +239,8 @@ public sealed class Ilrs : AbstractBase
|
|||||||
{
|
{
|
||||||
double nd = n;
|
double nd = n;
|
||||||
sx = 0.5 * nd * (nd - 1);
|
sx = 0.5 * nd * (nd - 1);
|
||||||
double sx2 = (nd - 1.0) * nd * (2.0 * nd - 1.0) / 6.0;
|
double sx2 = (nd - 1.0) * nd * ((2.0 * nd) - 1.0) / 6.0;
|
||||||
denom = nd * sx2 - sx * sx;
|
denom = (nd * sx2) - (sx * sx);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Math.Abs(denom) < 1e-10)
|
if (Math.Abs(denom) < 1e-10)
|
||||||
@@ -305,8 +305,8 @@ public sealed class Ilrs : AbstractBase
|
|||||||
|
|
||||||
// Precalculate constants for full period
|
// Precalculate constants for full period
|
||||||
double fullSumX = 0.5 * period * (period - 1);
|
double fullSumX = 0.5 * period * (period - 1);
|
||||||
double fullSumX2 = (period - 1.0) * period * (2.0 * period - 1.0) / 6.0;
|
double fullSumX2 = (period - 1.0) * period * ((2.0 * period) - 1.0) / 6.0;
|
||||||
double fullDenom = period * fullSumX2 - fullSumX * fullSumX;
|
double fullDenom = (period * fullSumX2) - (fullSumX * fullSumX);
|
||||||
|
|
||||||
for (int i = 0; i < len; i++)
|
for (int i = 0; i < len; i++)
|
||||||
{
|
{
|
||||||
@@ -345,8 +345,8 @@ public sealed class Ilrs : AbstractBase
|
|||||||
{
|
{
|
||||||
double n = count;
|
double n = count;
|
||||||
double sx = 0.5 * n * (n - 1);
|
double sx = 0.5 * n * (n - 1);
|
||||||
double sx2 = (n - 1.0) * n * (2.0 * n - 1.0) / 6.0;
|
double sx2 = (n - 1.0) * n * ((2.0 * n) - 1.0) / 6.0;
|
||||||
double denom = n * sx2 - sx * sx;
|
double denom = (n * sx2) - (sx * sx);
|
||||||
|
|
||||||
if (Math.Abs(denom) < 1e-10)
|
if (Math.Abs(denom) < 1e-10)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -105,7 +105,7 @@ public sealed class Kaiser : AbstractBase
|
|||||||
for (int k = 0; k < period; k++)
|
for (int k = 0; k < period; k++)
|
||||||
{
|
{
|
||||||
double t = nm1 > 0 ? (2.0 * k / nm1) - 1.0 : 0.0;
|
double t = nm1 > 0 ? (2.0 * k / nm1) - 1.0 : 0.0;
|
||||||
double argSq = 1.0 - t * t;
|
double argSq = 1.0 - (t * t);
|
||||||
double arg = argSq > 0 ? Math.Sqrt(argSq) : 0.0;
|
double arg = argSq > 0 ? Math.Sqrt(argSq) : 0.0;
|
||||||
double w = i0Beta > 0 ? BesselI0(beta * arg) / i0Beta : 1.0;
|
double w = i0Beta > 0 ? BesselI0(beta * arg) / i0Beta : 1.0;
|
||||||
weights[k] = w;
|
weights[k] = w;
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user