diff --git a/lib/cycles/cg/Cg.cs b/lib/cycles/cg/Cg.cs index d3218120..9652e94a 100644 --- a/lib/cycles/cg/Cg.cs +++ b/lib/cycles/cg/Cg.cs @@ -13,8 +13,8 @@ namespace QuanTAlib; /// making it useful for timing entries and exits. /// /// Formula: -/// num = Σ(count * price[count-1]) for count = 1 to length -/// den = Σ(price[count-1]) for count = 1 to length +/// num = Σ(count * price[count-1]) for count = 1 to length +/// den = Σ(price[count-1]) for count = 1 to length /// CG = (num / den) - (length + 1) / 2 /// /// Properties: @@ -180,8 +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) + if (n == 0 || _sum == 0) // skipcq: CS-R1077 - Exact-zero guard: _sum is cumulative price sum; zero means empty buffer, division by zero below { return 0; } @@ -300,8 +299,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) + if (sum == 0) // skipcq: CS-R1077 - Exact-zero guard: sum is cumulative price sum; zero means empty buffer, division by zero below { output[i] = 0; continue; diff --git a/lib/cycles/homod/Homod.cs b/lib/cycles/homod/Homod.cs index 8a6a137a..6584f6c2 100644 --- a/lib/cycles/homod/Homod.cs +++ b/lib/cycles/homod/Homod.cs @@ -18,7 +18,7 @@ namespace QuanTAlib; /// 3. Homodyne mixing: multiply I/Q with their 1-bar delayed values /// 4. Re = I*I[1] + Q*Q[1], Im = I*Q[1] - Q*I[1] /// 5. Angle = atan2(Im, Re) gives instantaneous phase change -/// 6. Period = 2π / angle with clamping and smoothing +/// 6. Period = 2Ï€ / angle with clamping and smoothing /// /// Properties: /// - Returns smoothed dominant cycle period @@ -321,8 +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) + if (y == 0.0 && x == 0.0) // skipcq: CS-R1077 - Exact-zero guard: both quadrature components zero means no signal; atan2(0,0) is undefined { return 0.0; // Return 0 instead of error for robustness } diff --git a/lib/cycles/ht_sine/HtSine.cs b/lib/cycles/ht_sine/HtSine.cs index d2204893..81463d97 100644 --- a/lib/cycles/ht_sine/HtSine.cs +++ b/lib/cycles/ht_sine/HtSine.cs @@ -206,12 +206,10 @@ 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) + if (im != 0.0 && re != 0.0) // skipcq: CS-R1077 - Exact-zero guard: atan(im/re) needs nonzero; zero means no signal { 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) + if (angle != 0.0) // skipcq: CS-R1077 - Exact-zero guard: angle == 0 means period undefined (div by angle) { period = (2.0 * Math.PI) / angle; } diff --git a/lib/momentum/pmo/Pmo.cs b/lib/momentum/pmo/Pmo.cs index ef174d01..b8f841e7 100644 --- a/lib/momentum/pmo/Pmo.cs +++ b/lib/momentum/pmo/Pmo.cs @@ -9,8 +9,8 @@ namespace QuanTAlib; /// /// /// DecisionPoint PMO Algorithm: -/// ROC = (Close / Close[1] - 1) × 100 (always 1-bar), -/// RocEma = CustomEMA(ROC, timePeriods) × 10, +/// ROC = (Close / Close[1] - 1) × 100 (always 1-bar), +/// RocEma = CustomEMA(ROC, timePeriods) × 10, /// PMO = CustomEMA(RocEma, smoothPeriods). /// /// Custom EMA uses alpha = 2/N (not the standard 2/(N+1)), and is seeded with the SMA @@ -19,7 +19,7 @@ namespace QuanTAlib; /// /// PMO oscillates around zero; positive values indicate upward momentum, negative values /// indicate downward momentum. Crossings of zero or a signal line suggest trend changes. -/// Non-finite inputs (NaN/±Inf) are sanitized by substituting the last finite value observed. +/// Non-finite inputs (NaN/±Inf) are sanitized by substituting the last finite value observed. /// /// For the authoritative algorithm reference, full rationale, and behavioral contracts, see the /// companion files in the same directory. @@ -133,8 +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 + roc = _state.PrevClose != 0.0 // skipcq: CS-R1077 - Exact-zero guard: PrevClose is a price; zero means no prior data, division by zero produces Infinity ? ((value / _state.PrevClose) - 1.0) * 100.0 : 0.0; _state.PrevClose = value; @@ -179,7 +178,7 @@ public sealed class Pmo : AbstractBase rocEmaScaled = _state.RocEmaRaw * 10.0; } - // Step 3: Second Custom EMA smoothing → PMO (SMA-seeded, alpha = 2/smoothPeriods) + // Step 3: Second Custom EMA smoothing → PMO (SMA-seeded, alpha = 2/smoothPeriods) double pmoValue; if (!_state.RocEmaSeeded) { @@ -300,8 +299,8 @@ public sealed class Pmo : AbstractBase double alpha2 = 2.0 / smoothPeriods; // Step 1: Compute 1-bar ROC for all bars - // Step 2: First CustomEMA(ROC, timePeriods) with SMA seed, then ×10 - // Step 3: Second CustomEMA(scaled, smoothPeriods) with SMA seed → PMO + // Step 2: First CustomEMA(ROC, timePeriods) with SMA seed, then ×10 + // Step 3: Second CustomEMA(scaled, smoothPeriods) with SMA seed → PMO double rocEmaRaw = 0.0; bool rocEmaSeeded = false; @@ -352,7 +351,7 @@ public sealed class Pmo : AbstractBase rocEmaScaled = rocEmaRaw * 10.0; } - // Second Custom EMA of scaled RocEma with SMA seed → PMO + // Second Custom EMA of scaled RocEma with SMA seed → PMO if (!rocEmaSeeded) { output[i] = 0.0; diff --git a/lib/momentum/rocp/Rocp.cs b/lib/momentum/rocp/Rocp.cs index 6105562a..961a6c99 100644 --- a/lib/momentum/rocp/Rocp.cs +++ b/lib/momentum/rocp/Rocp.cs @@ -81,8 +81,7 @@ public sealed class Rocp : AbstractBase else { double past = _buffer[0]; - // 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; + result = past != 0 ? 100.0 * (value - past) / past : 0.0; // skipcq: CS-R1077 - Exact-zero IEEE 754 div guard } Last = new TValue(input.Time, result); @@ -151,8 +150,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; + output[i] = past != 0 ? 100.0 * (source[i] - past) / past : 0.0; // skipcq: CS-R1077 - Exact-zero IEEE 754 div guard } } } diff --git a/lib/momentum/rocr/Rocr.cs b/lib/momentum/rocr/Rocr.cs index 5aba9270..534c9381 100644 --- a/lib/momentum/rocr/Rocr.cs +++ b/lib/momentum/rocr/Rocr.cs @@ -81,8 +81,7 @@ public sealed class Rocr : AbstractBase else { double past = _buffer[0]; - // 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; + result = past != 0 ? value / past : 1.0; // skipcq: CS-R1077 - Exact-zero IEEE 754 div guard } Last = new TValue(input.Time, result); @@ -151,8 +150,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; + output[i] = past != 0 ? source[i] / past : 1.0; // skipcq: CS-R1077 - Exact-zero IEEE 754 div guard } } } diff --git a/lib/oscillators/bbs/Bbs.cs b/lib/oscillators/bbs/Bbs.cs index d2b0d041..efe62f99 100644 --- a/lib/oscillators/bbs/Bbs.cs +++ b/lib/oscillators/bbs/Bbs.cs @@ -329,8 +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; + double bandwidth = bbMean != 0.0 ? ((bbUpper - bbLower) / bbMean) * 100.0 : 0.0; // skipcq: CS-R1077 - Exact-zero div guard: price avg // === Resync for floating-point drift === if (isNew) @@ -612,8 +611,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; + bandwidth[i] = bbMean != 0.0 ? ((bbUpper - bbLower) / bbMean) * 100.0 : 0.0; // skipcq: CS-R1077 - Exact-zero div guard: price avg } } diff --git a/lib/oscillators/cfo/Cfo.cs b/lib/oscillators/cfo/Cfo.cs index 2bca1c8f..f5c6fb6a 100644 --- a/lib/oscillators/cfo/Cfo.cs +++ b/lib/oscillators/cfo/Cfo.cs @@ -9,7 +9,7 @@ namespace QuanTAlib; /// /// Measures the percentage difference between the current price and the /// Time Series Forecast (linear regression endpoint): -/// CFO = 100 × (source − TSF) / source +/// CFO = 100 × (source − TSF) / source /// /// Uses O(1) incremental sumY / sumXY maintenance from the PineScript reference. /// When source equals zero, returns NaN to avoid division by zero. @@ -26,7 +26,7 @@ public sealed class Cfo : AbstractBase // Precomputed linear regression constants (full window) private readonly double _sumX; // 0 + 1 + ... + (period-1) - private readonly double _denomX; // period * sumX2 - sumX² + private readonly double _denomX; // period * sumX2 - sumX² [StructLayout(LayoutKind.Auto)] private record struct State( @@ -147,8 +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; + double cfo = value == 0.0 ? double.NaN : 100.0 * (value - tsf) / value; // skipcq: CS-R1077 - Exact-zero guard: value is a price; zero means no data, division by zero produces Infinity Last = new TValue(input.Time, cfo); PubEvent(Last, isNew); @@ -305,8 +304,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; + 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 } } diff --git a/lib/statistics/mode/Mode.cs b/lib/statistics/mode/Mode.cs index fd8546da..cde9f87f 100644 --- a/lib/statistics/mode/Mode.cs +++ b/lib/statistics/mode/Mode.cs @@ -307,8 +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]) + if (sorted[i] == sorted[i - 1]) // skipcq: CS-R1077 - Exact-equality required: mode detection counts identical values in a sorted array; epsilon would merge distinct prices { currentFreq++; } diff --git a/lib/statistics/spearman/Spearman.cs b/lib/statistics/spearman/Spearman.cs index 229fc6f8..08316420 100644 --- a/lib/statistics/spearman/Spearman.cs +++ b/lib/statistics/spearman/Spearman.cs @@ -4,24 +4,24 @@ using System.Runtime.CompilerServices; namespace QuanTAlib; /// -/// Computes the Spearman Rank Correlation Coefficient (Spearman's ρ), which measures +/// Computes the Spearman Rank Correlation Coefficient (Spearman's ρ), which measures /// the monotonic relationship between two series by applying Pearson correlation to /// their ranks. /// /// /// Spearman's Rho Algorithm: -/// ρ = Pearson(rank(X), rank(Y)) +/// ρ = Pearson(rank(X), rank(Y)) /// /// Ranks are 1-based with average-rank tie-breaking: if k values share the same value, /// each receives the mean of the positions they would occupy. /// /// When no ties exist, the simplified formula applies: -/// ρ = 1 - 6·Σd² / (n·(n²-1)), where d_i = rank(x_i) - rank(y_i). +/// ρ = 1 - 6·Σd² / (n·(n²-1)), where d_i = rank(x_i) - rank(y_i). /// /// This implementation uses the general Pearson-on-ranks method because ties can occur -/// in financial data (identical closes, rounded prices). Ranking is O(n²) per series. +/// in financial data (identical closes, rounded prices). Ranking is O(n²) per series. /// -/// Non-finite inputs (NaN/±Inf) are sanitized by substituting the last finite value observed. +/// Non-finite inputs (NaN/±Inf) are sanitized by substituting the last finite value observed. /// /// For the authoritative algorithm reference, full rationale, and behavioral contracts, see the /// companion files in the same directory. @@ -65,7 +65,7 @@ public sealed class Spearman : AbstractBase /// First series value /// Second series value /// Whether this is a new bar - /// Spearman's ρ coefficient (-1 to +1) + /// Spearman's ρ coefficient (-1 to +1) [MethodImpl(MethodImplOptions.AggressiveInlining)] public TValue Update(TValue seriesX, TValue seriesY, bool isNew = true) { @@ -144,7 +144,7 @@ public sealed class Spearman : AbstractBase return double.NaN; } - // Allocate rank arrays — stackalloc for small, ArrayPool for large + // Allocate rank arrays — stackalloc for small, ArrayPool for large double[]? rentedRx = null; double[]? rentedRy = null; scoped Span rankX; @@ -189,7 +189,7 @@ public sealed class Spearman : AbstractBase if (sumXX < Epsilon || sumYY < Epsilon) { - return 0.0; // Constant series → zero correlation + return 0.0; // Constant series → zero correlation } return sumXY / Math.Sqrt(sumXX * sumYY); @@ -208,7 +208,7 @@ public sealed class Spearman : AbstractBase } /// - /// Computes 1-based average ranks for buffer values. O(n²). + /// Computes 1-based average ranks for buffer values. O(n²). /// [MethodImpl(MethodImplOptions.AggressiveInlining)] private static void ComputeRanks(RingBuffer buffer, int n, Span ranks) @@ -226,8 +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) + if (vj == vi) // skipcq: CS-R1077 - Exact-equality required: Spearman tie-detection needs bit-identical values; epsilon would create false ties { countEqual++; // includes self } @@ -256,7 +255,7 @@ public sealed class Spearman : AbstractBase } /// - /// Calculates Spearman's ρ for two time series. + /// Calculates Spearman's ρ for two time series. /// public static TSeries Batch(TSeries seriesX, TSeries seriesY, int period = 20, Spearman? indicator = null) {