mirror of
https://github.com/mihakralj/QuanTAlib.git
synced 2026-07-27 17:27:43 +00:00
Add exact-zero guards in various classes to prevent division by zero errors
This commit is contained in:
@@ -180,6 +180,7 @@ public sealed class Cg : AbstractBase
|
||||
private double CalculateCg()
|
||||
{
|
||||
int n = _buffer.Count;
|
||||
// skipcq: CS-R1077 - Exact-zero guard: _sum is cumulative price sum; zero means empty buffer, division by zero below
|
||||
if (n == 0 || _sum == 0)
|
||||
{
|
||||
return 0;
|
||||
@@ -299,6 +300,7 @@ public sealed class Cg : AbstractBase
|
||||
sum += price;
|
||||
}
|
||||
|
||||
// skipcq: CS-R1077 - Exact-zero guard: sum is cumulative price sum; zero means empty buffer, division by zero below
|
||||
if (sum == 0)
|
||||
{
|
||||
output[i] = 0;
|
||||
|
||||
@@ -321,6 +321,7 @@ public sealed class Homod : AbstractBase
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static double Atan2(double y, double x)
|
||||
{
|
||||
// skipcq: CS-R1077 - Exact-zero guard: both quadrature components zero means no signal; atan2(0,0) is undefined
|
||||
if (y == 0.0 && x == 0.0)
|
||||
{
|
||||
return 0.0; // Return 0 instead of error for robustness
|
||||
|
||||
@@ -206,9 +206,11 @@ public sealed class HtSine : AbstractBase
|
||||
prevI2 = i2;
|
||||
|
||||
double tempReal1 = period;
|
||||
// skipcq: CS-R1077 - Exact-zero guard: atan(im/re) requires nonzero denominator; zero im/re means no signal energy
|
||||
if (im != 0.0 && re != 0.0)
|
||||
{
|
||||
double angle = Math.Atan(im / re);
|
||||
// skipcq: CS-R1077 - Exact-zero guard: angle == 0 means period is undefined (division by angle below)
|
||||
if (angle != 0.0)
|
||||
{
|
||||
period = (2.0 * Math.PI) / angle;
|
||||
|
||||
@@ -133,6 +133,7 @@ public sealed class Pmo : AbstractBase
|
||||
}
|
||||
else
|
||||
{
|
||||
// skipcq: CS-R1077 - Exact-zero guard: PrevClose is a price; zero means no prior data, division by zero produces Infinity
|
||||
roc = _state.PrevClose != 0.0
|
||||
? ((value / _state.PrevClose) - 1.0) * 100.0
|
||||
: 0.0;
|
||||
|
||||
@@ -81,7 +81,8 @@ public sealed class Rocp : AbstractBase
|
||||
else
|
||||
{
|
||||
double past = _buffer[0];
|
||||
result = past != 0 ? 100.0 * (value - past) / past : 0.0; // Avoid division by zero
|
||||
// skipcq: CS-R1077 - Exact-zero guard: IEEE 754 div-by-zero produces Infinity; any nonzero denominator is valid
|
||||
result = past != 0 ? 100.0 * (value - past) / past : 0.0;
|
||||
}
|
||||
|
||||
Last = new TValue(input.Time, result);
|
||||
@@ -150,6 +151,7 @@ public sealed class Rocp : AbstractBase
|
||||
else
|
||||
{
|
||||
double past = source[i - period];
|
||||
// skipcq: CS-R1077 - Exact-zero guard: IEEE 754 div-by-zero produces Infinity; any nonzero denominator is valid
|
||||
output[i] = past != 0 ? 100.0 * (source[i] - past) / past : 0.0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -81,7 +81,8 @@ public sealed class Rocr : AbstractBase
|
||||
else
|
||||
{
|
||||
double past = _buffer[0];
|
||||
result = past != 0 ? value / past : 1.0; // Avoid division by zero
|
||||
// skipcq: CS-R1077 - Exact-zero guard: IEEE 754 div-by-zero produces Infinity; any nonzero denominator is valid
|
||||
result = past != 0 ? value / past : 1.0;
|
||||
}
|
||||
|
||||
Last = new TValue(input.Time, result);
|
||||
@@ -150,6 +151,7 @@ public sealed class Rocr : AbstractBase
|
||||
else
|
||||
{
|
||||
double past = source[i - period];
|
||||
// skipcq: CS-R1077 - Exact-zero guard: IEEE 754 div-by-zero produces Infinity; any nonzero denominator is valid
|
||||
output[i] = past != 0 ? source[i] / past : 1.0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -329,6 +329,7 @@ public sealed class Bbs : ITValuePublisher
|
||||
_prevSqueezeOn = squeezeOn;
|
||||
|
||||
// === Bandwidth ===
|
||||
// skipcq: CS-R1077 - Exact-zero guard: bbMean is a price average; zero means no data, not rounding artifact
|
||||
double bandwidth = bbMean != 0.0 ? ((bbUpper - bbLower) / bbMean) * 100.0 : 0.0;
|
||||
|
||||
// === Resync for floating-point drift ===
|
||||
@@ -611,6 +612,7 @@ public sealed class Bbs : ITValuePublisher
|
||||
squeezeOn[i] = bbUpper < kcUpper && bbLower > kcLower;
|
||||
|
||||
// Bandwidth
|
||||
// skipcq: CS-R1077 - Exact-zero guard: bbMean is a price average; zero means no data, not rounding artifact
|
||||
bandwidth[i] = bbMean != 0.0 ? ((bbUpper - bbLower) / bbMean) * 100.0 : 0.0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -147,6 +147,7 @@ public sealed class Cfo : AbstractBase
|
||||
double tsf = Math.FusedMultiplyAdd(slope, _period - 1, intercept);
|
||||
|
||||
// CFO = 100 * (source - tsf) / source
|
||||
// skipcq: CS-R1077 - Exact-zero guard: value is a price; zero means no data, division by zero produces Infinity
|
||||
double cfo = value == 0.0 ? double.NaN : 100.0 * (value - tsf) / value;
|
||||
|
||||
Last = new TValue(input.Time, cfo);
|
||||
@@ -304,6 +305,7 @@ public sealed class Cfo : AbstractBase
|
||||
double intercept = (sumY - slope * sumX) / period;
|
||||
double tsf = Math.FusedMultiplyAdd(slope, period - 1, intercept);
|
||||
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -307,6 +307,7 @@ public sealed class Mode : AbstractBase
|
||||
|
||||
for (int i = 1; i < count; i++)
|
||||
{
|
||||
// skipcq: CS-R1077 - Exact-equality required: mode detection counts identical values in a sorted array; epsilon would merge distinct prices
|
||||
if (sorted[i] == sorted[i - 1])
|
||||
{
|
||||
currentFreq++;
|
||||
|
||||
@@ -226,6 +226,7 @@ public sealed class Spearman : AbstractBase
|
||||
{
|
||||
countSmaller++;
|
||||
}
|
||||
// skipcq: CS-R1077 - Exact-equality required: Spearman tie-detection needs bit-identical values; epsilon would create false ties
|
||||
if (vj == vi)
|
||||
{
|
||||
countEqual++; // includes self
|
||||
|
||||
Reference in New Issue
Block a user