[CodeFactor] Apply fixes to commit 4a01f03

This commit is contained in:
codefactor-io
2026-03-11 03:35:12 +00:00
parent 4a01f03cb4
commit 567fa89465
63 changed files with 293 additions and 302 deletions
+13 -13
View File
@@ -105,9 +105,9 @@ public sealed class Regchannel : 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);
// sumX2 = 0² + 1² + ... + (n-1)² = (n-1)n(2n-1)/6 // sumX2 = 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 * sumX2 - sumX² // denominator = n * sumX2 - sumX²
_denominator = period * sumX2 - _sumX * _sumX; _denominator = (period * sumX2) - (_sumX * _sumX);
Reset(); Reset();
} }
@@ -218,8 +218,8 @@ public sealed class Regchannel : 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;
@@ -232,8 +232,8 @@ public sealed class Regchannel : 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);
} }
@@ -362,8 +362,8 @@ public sealed class Regchannel : 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);
// Circular buffer of NaN-sanitised values for O(1) sliding-window recurrences. // Circular buffer of NaN-sanitised values for O(1) sliding-window recurrences.
const int StackAllocThreshold = 256; const int StackAllocThreshold = 256;
@@ -442,8 +442,8 @@ public sealed class Regchannel : 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
{ {
@@ -461,14 +461,14 @@ public sealed class Regchannel : 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);
} }
// Closed-form residual variance (normal-equation identity): // Closed-form residual variance (normal-equation identity):
// sumResiduals² = sumY² intercept·sumY slope·sumXY // sumResiduals² = sumY² intercept·sumY slope·sumXY
double sumResiduals2 = Math.Max(0.0, sumY2 - intercept * sumY - slope * sumXY); double sumResiduals2 = Math.Max(0.0, sumY2 - (intercept * sumY) - (slope * sumXY));
double stdDev = Math.Sqrt(sumResiduals2 / n); double stdDev = Math.Sqrt(sumResiduals2 / n);
double band = multiplier * stdDev; double band = multiplier * stdDev;
+12 -12
View File
@@ -105,9 +105,9 @@ public sealed class Sdchannel : 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);
// sumX2 = 0² + 1² + ... + (n-1)² = (n-1)n(2n-1)/6 // sumX2 = 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 * sumX2 - sumX² // denominator = n * sumX2 - sumX²
_denominator = period * sumX2 - _sumX * _sumX; _denominator = (period * sumX2) - (_sumX * _sumX);
Reset(); Reset();
} }
@@ -218,8 +218,8 @@ public sealed class Sdchannel : 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;
@@ -232,8 +232,8 @@ public sealed class Sdchannel : 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);
} }
@@ -362,8 +362,8 @@ public sealed class Sdchannel : 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);
// Circular buffer of NaN-sanitised values for O(1) sliding-window recurrences. // Circular buffer of NaN-sanitised values for O(1) sliding-window recurrences.
const int StackAllocThreshold = 256; const int StackAllocThreshold = 256;
@@ -441,8 +441,8 @@ public sealed class Sdchannel : 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
{ {
@@ -460,8 +460,8 @@ public sealed class Sdchannel : 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);
} }
+4 -4
View File
@@ -94,7 +94,7 @@ public class CcorValidationTests
for (int i = 0; i < 200; i++) for (int i = 0; i < 200; i++)
{ {
double val = 100.0 + 10.0 * Math.Sin(2.0 * Math.PI * i / period); double val = 100.0 + (10.0 * Math.Sin(2.0 * Math.PI * i / period));
ccor.Update(new TValue(DateTime.UtcNow.AddMinutes(i), val), true); ccor.Update(new TValue(DateTime.UtcNow.AddMinutes(i), val), true);
} }
@@ -103,7 +103,7 @@ public class CcorValidationTests
$"Sine wave should produce non-trivial phasor: Real={ccor.Real:F4}, Imag={ccor.Imag:F4}"); $"Sine wave should produce non-trivial phasor: Real={ccor.Real:F4}, Imag={ccor.Imag:F4}");
// R² + I² should be near 1 for a pure tone at the matched frequency // R² + I² should be near 1 for a pure tone at the matched frequency
double magnitude = Math.Sqrt(ccor.Real * ccor.Real + ccor.Imag * ccor.Imag); double magnitude = Math.Sqrt((ccor.Real * ccor.Real) + (ccor.Imag * ccor.Imag));
Assert.True(magnitude > 0.5, Assert.True(magnitude > 0.5,
$"Phasor magnitude should be significant for matched sine: {magnitude:F4}"); $"Phasor magnitude should be significant for matched sine: {magnitude:F4}");
} }
@@ -138,7 +138,7 @@ public class CcorValidationTests
for (int i = 0; i < 200; i++) for (int i = 0; i < 200; i++)
{ {
double val = 100.0 + 10.0 * Math.Sin(2.0 * Math.PI * i / period); double val = 100.0 + (10.0 * Math.Sin(2.0 * Math.PI * i / period));
ccor.Update(new TValue(DateTime.UtcNow.AddMinutes(i), val), true); ccor.Update(new TValue(DateTime.UtcNow.AddMinutes(i), val), true);
} }
@@ -374,7 +374,7 @@ public class CcorValidationTests
for (int i = 0; i < 100; i++) for (int i = 0; i < 100; i++)
{ {
ind.Update(new TValue(t0.AddMinutes(i), ind.Update(new TValue(t0.AddMinutes(i),
100.0 + 10.0 * Math.Sin(2.0 * Math.PI * i / 20.0)), isNew: true); 100.0 + (10.0 * Math.Sin(2.0 * Math.PI * i / 20.0))), isNew: true);
} }
// Anchor bar // Anchor bar
+6 -6
View File
@@ -158,7 +158,7 @@ public sealed class Ccor : AbstractBase
// Phasor angle (degrees) with quadrant resolution // Phasor angle (degrees) with quadrant resolution
if (imagVal != 0.0) if (imagVal != 0.0)
{ {
angleVal = 90.0 + Math.Atan(realVal / imagVal) * (180.0 / Math.PI); angleVal = 90.0 + (Math.Atan(realVal / imagVal) * (180.0 / Math.PI));
} }
if (imagVal > 0.0) if (imagVal > 0.0)
{ {
@@ -342,7 +342,7 @@ public sealed class Ccor : AbstractBase
for (int k = 0; k < n; k++) for (int k = 0; k < n; k++)
{ {
int idx = ((bufIdx - 1 - k) % period + period) % period; int idx = (((bufIdx - 1 - k) % period) + period) % period;
double x = priceBuf[idx]; double x = priceBuf[idx];
double y = cosTab[k]; double y = cosTab[k];
sx += x; sx += x;
@@ -353,8 +353,8 @@ public sealed class Ccor : AbstractBase
} }
double nd = n; double nd = n;
double dp = (nd * sxx - sx * sx) * (nd * syy - sy * sy); double dp = ((nd * sxx) - (sx * sx)) * ((nd * syy) - (sy * sy));
realVal = dp > 0.0 ? Math.Clamp((nd * sxy - sx * sy) / Math.Sqrt(dp), -1.0, 1.0) : 0.0; realVal = dp > 0.0 ? Math.Clamp(((nd * sxy) - (sx * sy)) / Math.Sqrt(dp), -1.0, 1.0) : 0.0;
} }
output[i] = realVal; output[i] = realVal;
@@ -423,13 +423,13 @@ public sealed class Ccor : AbstractBase
} }
double nd = n; double nd = n;
double denomProd = (nd * sxx - sx * sx) * (nd * syy - sy * sy); double denomProd = ((nd * sxx) - (sx * sx)) * ((nd * syy) - (sy * sy));
if (denomProd <= 0.0) if (denomProd <= 0.0)
{ {
return 0.0; return 0.0;
} }
double r = (nd * sxy - sx * sy) / Math.Sqrt(denomProd); double r = ((nd * sxy) - (sx * sy)) / Math.Sqrt(denomProd);
return Math.Clamp(r, -1.0, 1.0); return Math.Clamp(r, -1.0, 1.0);
} }
} }
+8 -8
View File
@@ -40,7 +40,7 @@ public class EacpValidationTests
// Generate sine wave with known period // Generate sine wave with known period
for (int i = 0; i < 500; i++) for (int i = 0; i < 500; i++)
{ {
double price = 100.0 + 10.0 * Math.Sin(2.0 * Math.PI * i / knownPeriod); double price = 100.0 + (10.0 * Math.Sin(2.0 * Math.PI * i / knownPeriod));
eacp.Update(new TValue(DateTime.UtcNow.AddSeconds(i), price)); eacp.Update(new TValue(DateTime.UtcNow.AddSeconds(i), price));
} }
@@ -155,7 +155,7 @@ public class EacpValidationTests
// Generate sine wave // Generate sine wave
for (int i = 0; i < 300; i++) for (int i = 0; i < 300; i++)
{ {
double price = 100.0 + 10.0 * Math.Sin(2.0 * Math.PI * i / 20.0); double price = 100.0 + (10.0 * Math.Sin(2.0 * Math.PI * i / 20.0));
eacpEnhanced.Update(new TValue(DateTime.UtcNow.AddSeconds(i), price)); eacpEnhanced.Update(new TValue(DateTime.UtcNow.AddSeconds(i), price));
eacpNormal.Update(new TValue(DateTime.UtcNow.AddSeconds(i), price)); eacpNormal.Update(new TValue(DateTime.UtcNow.AddSeconds(i), price));
} }
@@ -293,7 +293,7 @@ public class EacpValidationTests
for (int i = 0; i < 200; i++) for (int i = 0; i < 200; i++)
{ {
double price = 0.0001 + 0.00001 * Math.Sin(2.0 * Math.PI * i / 20.0); double price = 0.0001 + (0.00001 * Math.Sin(2.0 * Math.PI * i / 20.0));
eacp.Update(new TValue(DateTime.UtcNow.AddSeconds(i), price)); eacp.Update(new TValue(DateTime.UtcNow.AddSeconds(i), price));
} }
@@ -308,7 +308,7 @@ public class EacpValidationTests
for (int i = 0; i < 200; i++) for (int i = 0; i < 200; i++)
{ {
double price = 1e10 + 1e9 * Math.Sin(2.0 * Math.PI * i / 20.0); double price = 1e10 + (1e9 * Math.Sin(2.0 * Math.PI * i / 20.0));
eacp.Update(new TValue(DateTime.UtcNow.AddSeconds(i), price)); eacp.Update(new TValue(DateTime.UtcNow.AddSeconds(i), price));
} }
@@ -360,7 +360,7 @@ public class EacpValidationTests
// Generate pure sine wave // Generate pure sine wave
for (int i = 0; i < 300; i++) for (int i = 0; i < 300; i++)
{ {
double price = 100.0 + 10.0 * Math.Sin(2.0 * Math.PI * i / 20.0); double price = 100.0 + (10.0 * Math.Sin(2.0 * Math.PI * i / 20.0));
eacp.Update(new TValue(DateTime.UtcNow.AddSeconds(i), price)); eacp.Update(new TValue(DateTime.UtcNow.AddSeconds(i), price));
} }
@@ -406,8 +406,8 @@ public class EacpValidationTests
// Generate two different sine waves // Generate two different sine waves
for (int i = 0; i < 500; i++) for (int i = 0; i < 500; i++)
{ {
double price1 = 100.0 + 10.0 * Math.Sin(2.0 * Math.PI * i / period1); double price1 = 100.0 + (10.0 * Math.Sin(2.0 * Math.PI * i / period1));
double price2 = 100.0 + 10.0 * Math.Sin(2.0 * Math.PI * i / period2); double price2 = 100.0 + (10.0 * Math.Sin(2.0 * Math.PI * i / period2));
eacp1.Update(new TValue(DateTime.UtcNow.AddSeconds(i), price1)); eacp1.Update(new TValue(DateTime.UtcNow.AddSeconds(i), price1));
eacp2.Update(new TValue(DateTime.UtcNow.AddSeconds(i), price2)); eacp2.Update(new TValue(DateTime.UtcNow.AddSeconds(i), price2));
@@ -428,7 +428,7 @@ public class EacpValidationTests
for (int i = 0; i < 100; i++) for (int i = 0; i < 100; i++)
{ {
ind.Update(new TValue(t0.AddMinutes(i), ind.Update(new TValue(t0.AddMinutes(i),
100.0 + 10.0 * Math.Sin(2.0 * Math.PI * i / 20.0)), isNew: true); 100.0 + (10.0 * Math.Sin(2.0 * Math.PI * i / 20.0))), isNew: true);
} }
// Anchor bar // Anchor bar
+8 -8
View File
@@ -191,10 +191,10 @@ public sealed class Eacp : AbstractBase
// High-pass filter: removes DC and low-frequency trend // High-pass filter: removes DC and low-frequency trend
double hp2 = s.Hp1; double hp2 = s.Hp1;
double hp1 = s.Hp0; double hp1 = s.Hp0;
double coef = (1.0 - _alphaHP / 2.0); double coef = (1.0 - (_alphaHP / 2.0));
double hp0 = coef * coef * (price0 - 2.0 * price1 + price2) double hp0 = (coef * coef * (price0 - (2.0 * price1) + price2))
+ 2.0 * (1.0 - _alphaHP) * hp1 + (2.0 * (1.0 - _alphaHP) * hp1)
- (1.0 - _alphaHP) * (1.0 - _alphaHP) * hp2; - ((1.0 - _alphaHP) * (1.0 - _alphaHP) * hp2);
// Super-smoother filter: removes high-frequency noise // Super-smoother filter: removes high-frequency noise
double filt2 = s.Filt1; double filt2 = s.Filt1;
@@ -290,12 +290,12 @@ public sealed class Eacp : AbstractBase
double corrVal = 0; double corrVal = 0;
if (valid > 1) if (valid > 1)
{ {
double denomX = valid * sxx - sx * sx; double denomX = (valid * sxx) - (sx * sx);
double denomY = valid * syy - sy * sy; double denomY = (valid * syy) - (sy * sy);
double denom = denomX * denomY; double denom = denomX * denomY;
if (denom > 0) if (denom > 0)
{ {
corrVal = (valid * sxy - sx * sy) / Math.Sqrt(denom); corrVal = ((valid * sxy) - (sx * sy)) / Math.Sqrt(denom);
} }
} }
@@ -319,7 +319,7 @@ public sealed class Eacp : AbstractBase
} }
// Power = amplitude squared // Power = amplitude squared
double sq = cosAcc * cosAcc + sinAcc * sinAcc; double sq = (cosAcc * cosAcc) + (sinAcc * sinAcc);
// Smooth the power spectrum (EMA-like smoothing) // Smooth the power spectrum (EMA-like smoothing)
// Power squared per Ehlers: emphasizes spectral peaks, suppresses noise // Power squared per Ehlers: emphasizes spectral peaks, suppresses noise
@@ -103,7 +103,7 @@ public sealed class HtDcperiodValidationTests : IDisposable
for (int i = 0; i < 100; i++) for (int i = 0; i < 100; i++)
{ {
ind.Update(new TValue(t0.AddMinutes(i), ind.Update(new TValue(t0.AddMinutes(i),
100.0 + 10.0 * Math.Sin(2.0 * Math.PI * i / 20.0)), isNew: true); 100.0 + (10.0 * Math.Sin(2.0 * Math.PI * i / 20.0))), isNew: true);
} }
// Anchor bar // Anchor bar
+8 -8
View File
@@ -27,7 +27,7 @@ public class HtDcphaseTests
// Feed data through publisher // Feed data through publisher
for (int i = 0; i < 80; i++) for (int i = 0; i < 80; i++)
{ {
source.Add(new TValue(DateTime.UtcNow.AddMinutes(i), 100 + Math.Sin(i * 0.3) * 10)); source.Add(new TValue(DateTime.UtcNow.AddMinutes(i), 100 + (Math.Sin(i * 0.3) * 10)));
} }
Assert.True(ht.IsHot); Assert.True(ht.IsHot);
@@ -131,7 +131,7 @@ public class HtDcphaseTests
// Prime with data // Prime with data
for (int i = 0; i < 70; i++) for (int i = 0; i < 70; i++)
{ {
ht.Update(new TValue(now.AddMinutes(i), 100 + Math.Sin(i * 0.1) * 10)); ht.Update(new TValue(now.AddMinutes(i), 100 + (Math.Sin(i * 0.1) * 10)));
} }
Assert.True(ht.IsHot); Assert.True(ht.IsHot);
@@ -153,7 +153,7 @@ public class HtDcphaseTests
for (int i = 0; i < 70; i++) for (int i = 0; i < 70; i++)
{ {
ht.Update(new TValue(now.AddMinutes(i), 100 + i * 0.5)); ht.Update(new TValue(now.AddMinutes(i), 100 + (i * 0.5)));
} }
// New bar // New bar
@@ -187,7 +187,7 @@ public class HtDcphaseTests
for (int i = 0; i < 80; i++) for (int i = 0; i < 80; i++)
{ {
ht.Update(new TValue(now.AddMinutes(i), 100 + Math.Sin(i * 0.2) * 5)); ht.Update(new TValue(now.AddMinutes(i), 100 + (Math.Sin(i * 0.2) * 5)));
} }
Assert.True(ht.IsHot); Assert.True(ht.IsHot);
@@ -203,7 +203,7 @@ public class HtDcphaseTests
for (int i = 0; i < 80; i++) for (int i = 0; i < 80; i++)
{ {
ht.Update(new TValue(now.AddMinutes(i), 100 + i * 0.5)); ht.Update(new TValue(now.AddMinutes(i), 100 + (i * 0.5)));
} }
var result = ht.Update(new TValue(now.AddMinutes(80), double.PositiveInfinity)); var result = ht.Update(new TValue(now.AddMinutes(80), double.PositiveInfinity));
@@ -236,14 +236,14 @@ public class HtDcphaseTests
for (int i = 0; i < 80; i++) for (int i = 0; i < 80; i++)
{ {
ht.Update(new TValue(now.AddMinutes(i), 100 + Math.Sin(i * 0.2) * 5)); ht.Update(new TValue(now.AddMinutes(i), 100 + (Math.Sin(i * 0.2) * 5)));
} }
var firstResult = ht.Last.Value; var firstResult = ht.Last.Value;
ht.Reset(); ht.Reset();
for (int i = 0; i < 80; i++) for (int i = 0; i < 80; i++)
{ {
ht.Update(new TValue(now.AddMinutes(i), 100 + Math.Sin(i * 0.2) * 5)); ht.Update(new TValue(now.AddMinutes(i), 100 + (Math.Sin(i * 0.2) * 5)));
} }
Assert.Equal(firstResult, ht.Last.Value); Assert.Equal(firstResult, ht.Last.Value);
} }
@@ -352,7 +352,7 @@ public class HtDcphaseTests
var values = new double[80]; var values = new double[80];
for (int i = 0; i < 80; i++) for (int i = 0; i < 80; i++)
{ {
values[i] = 100 + Math.Sin(i * 0.2) * 5; values[i] = 100 + (Math.Sin(i * 0.2) * 5);
} }
ht.Prime(values, TimeSpan.FromMinutes(5)); ht.Prime(values, TimeSpan.FromMinutes(5));
@@ -103,7 +103,7 @@ public sealed class HtDcphaseValidationTests : IDisposable
for (int i = 0; i < 100; i++) for (int i = 0; i < 100; i++)
{ {
ind.Update(new TValue(t0.AddMinutes(i), ind.Update(new TValue(t0.AddMinutes(i),
100.0 + 10.0 * Math.Sin(2.0 * Math.PI * i / 20.0)), isNew: true); 100.0 + (10.0 * Math.Sin(2.0 * Math.PI * i / 20.0))), isNew: true);
} }
// Anchor bar // Anchor bar
+5 -5
View File
@@ -141,8 +141,8 @@ public sealed class HtDcphase : 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];
@@ -166,8 +166,8 @@ public sealed class HtDcphase : 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];
@@ -296,7 +296,7 @@ public sealed class HtDcphase : 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;
@@ -133,7 +133,7 @@ public sealed class HtSineValidationTests : IDisposable
for (int i = 0; i < 100; i++) for (int i = 0; i < 100; i++)
{ {
ind.Update(new TValue(t0.AddMinutes(i), ind.Update(new TValue(t0.AddMinutes(i),
100.0 + 10.0 * Math.Sin(2.0 * Math.PI * i / 20.0)), isNew: true); 100.0 + (10.0 * Math.Sin(2.0 * Math.PI * i / 20.0))), isNew: true);
} }
// Anchor bar // Anchor bar
+7 -7
View File
@@ -161,8 +161,8 @@ public sealed class HtSine : 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);
// The variable I1 is the detrender delayed for 3 price bars. // The variable I1 is the detrender delayed for 3 price bars.
i1ForEvenPrev3 = i1ForEvenPrev2; i1ForEvenPrev3 = i1ForEvenPrev2;
@@ -187,8 +187,8 @@ public sealed class HtSine : 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);
// The variable i1 is the detrender delayed for 3 price bars. // The variable i1 is the detrender delayed for 3 price bars.
i1ForOddPrev3 = i1ForOddPrev2; i1ForOddPrev3 = i1ForOddPrev2;
@@ -199,8 +199,8 @@ public sealed class HtSine : 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;
@@ -373,7 +373,7 @@ public sealed class HtSine : 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;
+1 -1
View File
@@ -476,7 +476,7 @@ public sealed class Adx : ITValuePublisher
double dx = CalcDx(trSmooth, dmPlusSmooth, dmMinusSmooth); double dx = CalcDx(trSmooth, dmPlusSmooth, dmMinusSmooth);
dxSum += dx; dxSum += dx;
int adxStart = period * 2 - 1; int adxStart = (period * 2) - 1;
for (int i = period + 1; i <= adxStart; i++) for (int i = period + 1; i <= adxStart; i++)
{ {
@@ -55,7 +55,7 @@ public sealed class HtTrendmodeValidationTests : IDisposable
// Act - Process with sinusoidal data // Act - Process with sinusoidal data
for (int i = 0; i < 200; i++) for (int i = 0; i < 200; i++)
{ {
double value = 100.0 + Math.Sin(i * 0.2) * 10.0 + Math.Sin(i * 0.05) * 5.0; double value = 100.0 + (Math.Sin(i * 0.2) * 10.0) + (Math.Sin(i * 0.05) * 5.0);
indicator.Update(new TValue(DateTime.UtcNow.AddMinutes(i), value)); indicator.Update(new TValue(DateTime.UtcNow.AddMinutes(i), value));
} }
@@ -74,7 +74,7 @@ public sealed class HtTrendmodeValidationTests : IDisposable
// Act // Act
for (int i = 0; i < 200; i++) for (int i = 0; i < 200; i++)
{ {
double value = 100.0 + Math.Sin(i * 0.15) * 8.0; double value = 100.0 + (Math.Sin(i * 0.15) * 8.0);
indicator.Update(new TValue(DateTime.UtcNow.AddMinutes(i), value)); indicator.Update(new TValue(DateTime.UtcNow.AddMinutes(i), value));
} }
@@ -208,7 +208,7 @@ public sealed class HtTrendmodeValidationTests : IDisposable
for (int i = 0; i < 100; i++) for (int i = 0; i < 100; i++)
{ {
ind.Update(new TValue(t0.AddMinutes(i), ind.Update(new TValue(t0.AddMinutes(i),
100.0 + 10.0 * Math.Sin(2.0 * Math.PI * i / 20.0)), isNew: true); 100.0 + (10.0 * Math.Sin(2.0 * Math.PI * i / 20.0))), isNew: true);
} }
// Anchor bar // Anchor bar
@@ -124,8 +124,8 @@ public sealed class IchimokuValidationTests : IDisposable
// Add 4 bars with increasing trend // Add 4 bars with increasing trend
for (int i = 0; i < 4; i++) for (int i = 0; i < 4; i++)
{ {
double basePrice = 100 + i * 5; double basePrice = 100 + (i * 5);
ichimoku.Update(new TBar(baseTime + i * 60000, basePrice, basePrice + 5, basePrice - 5, basePrice, 1000)); ichimoku.Update(new TBar(baseTime + (i * 60000), basePrice, basePrice + 5, basePrice - 5, basePrice, 1000));
} }
// Tenkan (2-period) uses last 2 bars: bars 3,4 // Tenkan (2-period) uses last 2 bars: bars 3,4
@@ -223,7 +223,7 @@ public sealed class IchimokuValidationTests : IDisposable
for (int i = 0; i < 5; i++) for (int i = 0; i < 5; i++)
{ {
ichimoku.Update(new TBar(baseTime + i * 60000, (highs[i] + lows[i]) / 2, highs[i], lows[i], (highs[i] + lows[i]) / 2, 1000)); ichimoku.Update(new TBar(baseTime + (i * 60000), (highs[i] + lows[i]) / 2, highs[i], lows[i], (highs[i] + lows[i]) / 2, 1000));
} }
// 5-period: max(100,110,120,115,105) = 120, min(90,85,80,88,92) = 80 // 5-period: max(100,110,120,115,105) = 120, min(90,85,80,88,92) = 80
@@ -244,7 +244,7 @@ public sealed class IchimokuValidationTests : IDisposable
for (int i = 1; i < 10; i++) for (int i = 1; i < 10; i++)
{ {
ichimoku.Update(new TBar(baseTime + i * 60000, 100, 110, 90, 100, 1000)); ichimoku.Update(new TBar(baseTime + (i * 60000), 100, 110, 90, 100, 1000));
} }
// 10-period includes the extreme bar // 10-period includes the extreme bar
@@ -254,7 +254,7 @@ public sealed class IchimokuValidationTests : IDisposable
Assert.Equal(125.0, ichimoku.SenkouB.Value, Precision); Assert.Equal(125.0, ichimoku.SenkouB.Value, Precision);
// Add another bar to drop the extreme // Add another bar to drop the extreme
ichimoku.Update(new TBar(baseTime + 10 * 60000, 100, 110, 90, 100, 1000)); ichimoku.Update(new TBar(baseTime + (10 * 60000), 100, 110, 90, 100, 1000));
// Now 10-period window doesn't include extreme bar // Now 10-period window doesn't include extreme bar
// max(110,110,...) = 110, min(90,90,...) = 90 // max(110,110,...) = 110, min(90,90,...) = 90
@@ -291,8 +291,8 @@ public sealed class IchimokuValidationTests : IDisposable
for (int i = 0; i < 15; i++) for (int i = 0; i < 15; i++)
{ {
double expectedClose = 100 + i * 1.5; double expectedClose = 100 + (i * 1.5);
ichimoku.Update(new TBar(baseTime + i * 60000, expectedClose, expectedClose + 5, expectedClose - 5, expectedClose, 1000)); ichimoku.Update(new TBar(baseTime + (i * 60000), expectedClose, expectedClose + 5, expectedClose - 5, expectedClose, 1000));
Assert.Equal(expectedClose, ichimoku.Chikou.Value, Precision); Assert.Equal(expectedClose, ichimoku.Chikou.Value, Precision);
} }
} }
@@ -315,14 +315,14 @@ public sealed class IchimokuValidationTests : IDisposable
for (int i = 0; i < 10; i++) for (int i = 0; i < 10; i++)
{ {
double price = 50 + i; // 50 to 59 double price = 50 + i; // 50 to 59
ichimoku.Update(new TBar(baseTime + i * 60000, price, price + 5, price - 5, price, 1000)); ichimoku.Update(new TBar(baseTime + (i * 60000), price, price + 5, price - 5, price, 1000));
} }
// Then jump to much higher prices - affects Tenkan and Kijun more than SenkouB // Then jump to much higher prices - affects Tenkan and Kijun more than SenkouB
for (int i = 10; i < 15; i++) for (int i = 10; i < 15; i++)
{ {
double price = 100 + (i - 10) * 2; double price = 100 + ((i - 10) * 2);
ichimoku.Update(new TBar(baseTime + i * 60000, price, price + 5, price - 5, price, 1000)); ichimoku.Update(new TBar(baseTime + (i * 60000), price, price + 5, price - 5, price, 1000));
} }
// In this scenario, SenkouA should be above SenkouB (bullish cloud) // In this scenario, SenkouA should be above SenkouB (bullish cloud)
@@ -344,14 +344,14 @@ public sealed class IchimokuValidationTests : IDisposable
for (int i = 0; i < 10; i++) for (int i = 0; i < 10; i++)
{ {
double price = 150 - i; // 150 down to 141 double price = 150 - i; // 150 down to 141
ichimoku.Update(new TBar(baseTime + i * 60000, price, price + 5, price - 5, price, 1000)); ichimoku.Update(new TBar(baseTime + (i * 60000), price, price + 5, price - 5, price, 1000));
} }
// Then drop to much lower prices // Then drop to much lower prices
for (int i = 10; i < 15; i++) for (int i = 10; i < 15; i++)
{ {
double price = 100 - (i - 10) * 3; double price = 100 - ((i - 10) * 3);
ichimoku.Update(new TBar(baseTime + i * 60000, price, price + 5, price - 5, price, 1000)); ichimoku.Update(new TBar(baseTime + (i * 60000), price, price + 5, price - 5, price, 1000));
} }
// In downtrend, SenkouB (longer term) should be above SenkouA (bearish cloud) // In downtrend, SenkouB (longer term) should be above SenkouA (bearish cloud)
@@ -374,9 +374,9 @@ public sealed class IchimokuValidationTests : IDisposable
for (int i = 0; i < 100; i++) for (int i = 0; i < 100; i++)
{ {
// Random walk-ish price movement // Random walk-ish price movement
double change = Math.Sin(i * 0.1) * 2 + Math.Cos(i * 0.05); double change = (Math.Sin(i * 0.1) * 2) + Math.Cos(i * 0.05);
price += change; price += change;
barSeries.Add(new TBar(baseTime + i * 60000, price, price + 2, price - 2, price, 1000)); barSeries.Add(new TBar(baseTime + (i * 60000), price, price + 2, price - 2, price, 1000));
} }
// Process all bars // Process all bars
@@ -406,8 +406,8 @@ public sealed class IchimokuValidationTests : IDisposable
// Process enough bars to warmup // Process enough bars to warmup
for (int i = 0; i < 70; i++) for (int i = 0; i < 70; i++)
{ {
double price = 40000 + Math.Sin(i * 0.05) * 1000; double price = 40000 + (Math.Sin(i * 0.05) * 1000);
ichimoku.Update(new TBar(baseTime + i * 60000, price, price + 50, price - 50, price, 10)); ichimoku.Update(new TBar(baseTime + (i * 60000), price, price + 50, price - 50, price, 10));
} }
Assert.True(ichimoku.IsHot); Assert.True(ichimoku.IsHot);
@@ -427,7 +427,7 @@ public sealed class IchimokuValidationTests : IDisposable
for (int i = 0; i < 60; i++) for (int i = 0; i < 60; i++)
{ {
double price = 100 + i; double price = 100 + i;
barSeries.Add(new TBar(baseTime + i * 60000, price, price + 5, price - 5, price, 1000)); barSeries.Add(new TBar(baseTime + (i * 60000), price, price + 5, price - 5, price, 1000));
} }
// Batch processing // Batch processing
@@ -472,7 +472,7 @@ public sealed class IchimokuValidationTests : IDisposable
for (int i = 0; i < 60; i++) for (int i = 0; i < 60; i++)
{ {
double price = 100 + i; double price = 100 + i;
barSeries.Add(new TBar(baseTime + i * 60000, price, price + 5, price - 5, price, 1000)); barSeries.Add(new TBar(baseTime + (i * 60000), price, price + 5, price - 5, price, 1000));
} }
var (results, indicator) = Ichimoku.Calculate(barSeries); var (results, indicator) = Ichimoku.Calculate(barSeries);
@@ -500,7 +500,7 @@ public sealed class IchimokuValidationTests : IDisposable
// Phase 1: Ranging market - Tenkan ≈ Kijun // Phase 1: Ranging market - Tenkan ≈ Kijun
for (int i = 0; i < 5; i++) for (int i = 0; i < 5; i++)
{ {
ichimoku.Update(new TBar(baseTime + i * 60000, 100, 105, 95, 100, 1000)); ichimoku.Update(new TBar(baseTime + (i * 60000), 100, 105, 95, 100, 1000));
} }
// Capture initial state (using discards since we're testing the response to change) // Capture initial state (using discards since we're testing the response to change)
@@ -510,8 +510,8 @@ public sealed class IchimokuValidationTests : IDisposable
// Phase 2: Sharp upward move - Tenkan should rise faster // Phase 2: Sharp upward move - Tenkan should rise faster
for (int i = 5; i < 10; i++) for (int i = 5; i < 10; i++)
{ {
double price = 100 + (i - 5) * 5; double price = 100 + ((i - 5) * 5);
ichimoku.Update(new TBar(baseTime + i * 60000, price, price + 3, price - 3, price, 1000)); ichimoku.Update(new TBar(baseTime + (i * 60000), price, price + 3, price - 3, price, 1000));
} }
// Tenkan (short-term) should react faster to the uptrend // Tenkan (short-term) should react faster to the uptrend
@@ -689,7 +689,7 @@ public sealed class IchimokuValidationTests : IDisposable
// Build state well past warmup // Build state well past warmup
for (int i = 0; i < 100; i++) for (int i = 0; i < 100; i++)
{ {
double p = 100.0 + 10.0 * Math.Sin(2.0 * Math.PI * i / 20.0); double p = 100.0 + (10.0 * Math.Sin(2.0 * Math.PI * i / 20.0));
ind.Update(new TBar(t0.AddMinutes(i), p, p + 2, p - 2, p, 1000), isNew: true); ind.Update(new TBar(t0.AddMinutes(i), p, p + 2, p - 2, p, 1000), isNew: true);
} }
@@ -22,7 +22,7 @@ public class TtmSqueezeValidationTests
// Very tight range bars - stddev will be near 0 // Very tight range bars - stddev will be near 0
for (int i = 0; i < 10; i++) for (int i = 0; i < 10; i++)
{ {
squeeze.Update(new TBar(baseTime + i * 60000, 100.0, 100.01, 99.99, 100.0, 1000)); squeeze.Update(new TBar(baseTime + (i * 60000), 100.0, 100.01, 99.99, 100.0, 1000));
} }
// With effectively zero stddev, BB bands collapse to the mean // With effectively zero stddev, BB bands collapse to the mean
@@ -45,7 +45,7 @@ public class TtmSqueezeValidationTests
double high = 105; double high = 105;
double low = 95; double low = 95;
double close = (high + low) / 2; // exactly at midline double close = (high + low) / 2; // exactly at midline
squeeze.Update(new TBar(baseTime + i * 60000, 100, high, low, close, 1000)); squeeze.Update(new TBar(baseTime + (i * 60000), 100, high, low, close, 1000));
} }
// Momentum should be near zero since price = midline // Momentum should be near zero since price = midline
@@ -113,7 +113,7 @@ public class TtmSqueezeValidationTests
double midline = 100; // (110 + 90) / 2 double midline = 100; // (110 + 90) / 2
double close = midline + (i * 2); // 100, 102, 104, ... double close = midline + (i * 2); // 100, 102, 104, ...
squeeze.Update(new TBar(baseTime + i * 60000, 100, high, low, close, 1000)); squeeze.Update(new TBar(baseTime + (i * 60000), 100, high, low, close, 1000));
} }
// Momentum should be strongly positive with rising trend // Momentum should be strongly positive with rising trend
@@ -135,28 +135,28 @@ public class TtmSqueezeValidationTests
// Uptrend (rising above zero - cyan = 0) // Uptrend (rising above zero - cyan = 0)
for (int i = 0; i < 5; i++) for (int i = 0; i < 5; i++)
{ {
squeeze.Update(new TBar(baseTime + i * 60000, 100 + i * 2, 105 + i * 2, 95 + i * 2, 103 + i * 2, 1000)); squeeze.Update(new TBar(baseTime + (i * 60000), 100 + (i * 2), 105 + (i * 2), 95 + (i * 2), 103 + (i * 2), 1000));
colorsSeen.Add(squeeze.ColorCode); colorsSeen.Add(squeeze.ColorCode);
} }
// Now weakening but still positive (falling above zero - blue = 1) // Now weakening but still positive (falling above zero - blue = 1)
for (int i = 5; i < 10; i++) for (int i = 5; i < 10; i++)
{ {
squeeze.Update(new TBar(baseTime + i * 60000, 115, 118, 112, 114, 1000)); squeeze.Update(new TBar(baseTime + (i * 60000), 115, 118, 112, 114, 1000));
colorsSeen.Add(squeeze.ColorCode); colorsSeen.Add(squeeze.ColorCode);
} }
// Downtrend (falling below zero - red = 2) // Downtrend (falling below zero - red = 2)
for (int i = 10; i < 15; i++) for (int i = 10; i < 15; i++)
{ {
squeeze.Update(new TBar(baseTime + i * 60000, 100 - (i - 10) * 3, 102 - (i - 10) * 3, 95 - (i - 10) * 3, 97 - (i - 10) * 3, 1000)); squeeze.Update(new TBar(baseTime + (i * 60000), 100 - ((i - 10) * 3), 102 - ((i - 10) * 3), 95 - ((i - 10) * 3), 97 - ((i - 10) * 3), 1000));
colorsSeen.Add(squeeze.ColorCode); colorsSeen.Add(squeeze.ColorCode);
} }
// Recovering but still negative (rising below zero - yellow = 3) // Recovering but still negative (rising below zero - yellow = 3)
for (int i = 15; i < 20; i++) for (int i = 15; i < 20; i++)
{ {
squeeze.Update(new TBar(baseTime + i * 60000, 80, 85, 78, 82, 1000)); squeeze.Update(new TBar(baseTime + (i * 60000), 80, 85, 78, 82, 1000));
colorsSeen.Add(squeeze.ColorCode); colorsSeen.Add(squeeze.ColorCode);
} }
@@ -173,7 +173,7 @@ public class TtmSqueezeValidationTests
// Strong uptrend to ensure positive and rising momentum // Strong uptrend to ensure positive and rising momentum
for (int i = 0; i < 10; i++) for (int i = 0; i < 10; i++)
{ {
squeeze.Update(new TBar(baseTime + i * 60000, 100 + i * 5, 105 + i * 5, 95 + i * 5, 103 + i * 5, 1000)); squeeze.Update(new TBar(baseTime + (i * 60000), 100 + (i * 5), 105 + (i * 5), 95 + (i * 5), 103 + (i * 5), 1000));
} }
if (squeeze.MomentumPositive && squeeze.MomentumRising) if (squeeze.MomentumPositive && squeeze.MomentumRising)
@@ -191,7 +191,7 @@ public class TtmSqueezeValidationTests
// Strong downtrend to ensure negative and falling momentum // Strong downtrend to ensure negative and falling momentum
for (int i = 0; i < 10; i++) for (int i = 0; i < 10; i++)
{ {
squeeze.Update(new TBar(baseTime + i * 60000, 100 - i * 5, 105 - i * 5, 95 - i * 5, 97 - i * 5, 1000)); squeeze.Update(new TBar(baseTime + (i * 60000), 100 - (i * 5), 105 - (i * 5), 95 - (i * 5), 97 - (i * 5), 1000));
} }
if (!squeeze.MomentumPositive && !squeeze.MomentumRising) if (!squeeze.MomentumPositive && !squeeze.MomentumRising)
@@ -215,7 +215,7 @@ public class TtmSqueezeValidationTests
// Start with tight range to build squeeze // Start with tight range to build squeeze
for (int i = 0; i < 5; i++) for (int i = 0; i < 5; i++)
{ {
squeeze.Update(new TBar(baseTime + i * 60000, 100, 100.1, 99.9, 100, 1000)); squeeze.Update(new TBar(baseTime + (i * 60000), 100, 100.1, 99.9, 100, 1000));
if (squeeze.SqueezeFired) if (squeeze.SqueezeFired)
{ {
squeezeFiredCount++; squeezeFiredCount++;
@@ -226,7 +226,7 @@ public class TtmSqueezeValidationTests
for (int i = 5; i < 10; i++) for (int i = 5; i < 10; i++)
{ {
double volatility = (i - 4) * 5; double volatility = (i - 4) * 5;
squeeze.Update(new TBar(baseTime + i * 60000, 100, 100 + volatility, 100 - volatility, 100 + volatility - 2, 1000)); squeeze.Update(new TBar(baseTime + (i * 60000), 100, 100 + volatility, 100 - volatility, 100 + volatility - 2, 1000));
if (squeeze.SqueezeFired) if (squeeze.SqueezeFired)
{ {
squeezeFiredCount++; squeezeFiredCount++;
@@ -250,10 +250,10 @@ public class TtmSqueezeValidationTests
for (int i = 0; i < 50; i++) for (int i = 0; i < 50; i++)
{ {
double price = 100 + Math.Sin(i * 0.2) * 10; double price = 100 + (Math.Sin(i * 0.2) * 10);
double high = price + 2; double high = price + 2;
double low = price - 2; double low = price - 2;
source.Add(new TBar(baseTime + i * 60000, price, high, low, price + 0.5, 1000)); source.Add(new TBar(baseTime + (i * 60000), price, high, low, price + 0.5, 1000));
} }
// Batch calculation // Batch calculation
@@ -301,7 +301,7 @@ public class TtmSqueezeValidationTests
// All bars identical // All bars identical
for (int i = 0; i < 10; i++) for (int i = 0; i < 10; i++)
{ {
squeeze.Update(new TBar(baseTime + i * 60000, 100, 100, 100, 100, 1000)); squeeze.Update(new TBar(baseTime + (i * 60000), 100, 100, 100, 100, 1000));
} }
Assert.True(double.IsFinite(squeeze.Momentum.Value)); Assert.True(double.IsFinite(squeeze.Momentum.Value));
@@ -318,7 +318,7 @@ public class TtmSqueezeValidationTests
for (int i = 0; i < 10; i++) for (int i = 0; i < 10; i++)
{ {
double range = (i + 1) * 100; // Increasing volatility double range = (i + 1) * 100; // Increasing volatility
squeeze.Update(new TBar(baseTime + i * 60000, 100, 100 + range, 100 - range, 100 + range / 2, 1000)); squeeze.Update(new TBar(baseTime + (i * 60000), 100, 100 + range, 100 - range, 100 + (range / 2), 1000));
} }
Assert.True(double.IsFinite(squeeze.Momentum.Value)); Assert.True(double.IsFinite(squeeze.Momentum.Value));
@@ -334,7 +334,7 @@ public class TtmSqueezeValidationTests
// Build state well past warmup // Build state well past warmup
for (int i = 0; i < 100; i++) for (int i = 0; i < 100; i++)
{ {
double p = 100.0 + 10.0 * Math.Sin(2.0 * Math.PI * i / 20.0); double p = 100.0 + (10.0 * Math.Sin(2.0 * Math.PI * i / 20.0));
ind.Update(new TBar(t0.AddMinutes(i), p, p + 2, p - 2, p, 1000), isNew: true); ind.Update(new TBar(t0.AddMinutes(i), p, p + 2, p - 2, p, 1000), isNew: true);
} }
+12 -13
View File
@@ -210,8 +210,8 @@ public sealed class TtmSqueeze : ITValuePublisher
// Precompute linear regression constants // Precompute linear regression constants
_sumX = 0.5 * momPeriod * (momPeriod - 1); _sumX = 0.5 * momPeriod * (momPeriod - 1);
double sumX2 = (momPeriod - 1.0) * momPeriod * (2.0 * momPeriod - 1.0) / 6.0; double sumX2 = (momPeriod - 1.0) * momPeriod * ((2.0 * momPeriod) - 1.0) / 6.0;
_denominator = momPeriod * sumX2 - _sumX * _sumX; _denominator = (momPeriod * sumX2) - (_sumX * _sumX);
Reset(); Reset();
} }
@@ -328,11 +328,11 @@ public sealed class TtmSqueeze : ITValuePublisher
double bbCount = Math.Min(_barCount, _bbPeriod); double bbCount = Math.Min(_barCount, _bbPeriod);
double bbMean = bbCount > 0 ? _priceSum / bbCount : close; double bbMean = bbCount > 0 ? _priceSum / bbCount : close;
double bbVariance = bbCount > 1 ? (_priceSumSquares - _priceSum * _priceSum / bbCount) / bbCount : 0; double bbVariance = bbCount > 1 ? (_priceSumSquares - (_priceSum * _priceSum / bbCount)) / bbCount : 0;
double bbStdDev = Math.Sqrt(Math.Max(0, bbVariance)); double bbStdDev = Math.Sqrt(Math.Max(0, bbVariance));
double bbUpper = bbMean + _bbMult * bbStdDev; double bbUpper = bbMean + (_bbMult * bbStdDev);
double bbLower = bbMean - _bbMult * bbStdDev; double bbLower = bbMean - (_bbMult * bbStdDev);
// === Keltner Channel Calculation === // === Keltner Channel Calculation ===
// EMA with warmup compensation // EMA with warmup compensation
@@ -354,8 +354,8 @@ public sealed class TtmSqueeze : ITValuePublisher
_atrE = Math.FusedMultiplyAdd(_atrE, 1 - atrAlpha, 0); _atrE = Math.FusedMultiplyAdd(_atrE, 1 - atrAlpha, 0);
double atr = _atrE < 1.0 ? _atrRma / (1.0 - _atrE) : _atrRma; double atr = _atrE < 1.0 ? _atrRma / (1.0 - _atrE) : _atrRma;
double kcUpper = kcMid + _kcMult * atr; double kcUpper = kcMid + (_kcMult * atr);
double kcLower = kcMid - _kcMult * atr; double kcLower = kcMid - (_kcMult * atr);
// === Squeeze Detection === // === Squeeze Detection ===
bool wasSqueezeOn = _prevSqueezeOn; bool wasSqueezeOn = _prevSqueezeOn;
@@ -380,7 +380,7 @@ public sealed class TtmSqueeze : ITValuePublisher
{ {
double oldest = _momentumBuffer[0]; double oldest = _momentumBuffer[0];
double prevSumY = _momentumSumY; double prevSumY = _momentumSumY;
_momentumSumXY = _momentumSumXY + prevSumY - _momPeriod * oldest; _momentumSumXY = _momentumSumXY + prevSumY - (_momPeriod * oldest);
_momentumSumY -= oldest; _momentumSumY -= oldest;
} }
_momentumBuffer.Add(deviation); _momentumBuffer.Add(deviation);
@@ -411,8 +411,8 @@ public sealed class TtmSqueeze : ITValuePublisher
if (momCount < _momPeriod) if (momCount < _momPeriod)
{ {
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
{ {
@@ -426,8 +426,8 @@ public sealed class TtmSqueeze : ITValuePublisher
} }
else else
{ {
double slope = (n * _momentumSumXY - sx * _momentumSumY) / denom; double slope = ((n * _momentumSumXY) - (sx * _momentumSumY)) / denom;
double intercept = (_momentumSumY - slope * sx) / n; double intercept = (_momentumSumY - (slope * sx)) / n;
// Regression value at current point (x = count - 1) // Regression value at current point (x = count - 1)
momentum = Math.FusedMultiplyAdd(slope, n - 1, intercept); momentum = Math.FusedMultiplyAdd(slope, n - 1, intercept);
} }
@@ -561,5 +561,4 @@ public sealed class TtmSqueeze : ITValuePublisher
_lowBuffer.Restore(); _lowBuffer.Restore();
_momentumBuffer.Restore(); _momentumBuffer.Restore();
} }
} }
+1 -1
View File
@@ -80,7 +80,7 @@ public sealed class MaeValidationTests : IDisposable
// Build state well past warmup // Build state well past warmup
for (int i = 0; i < 50; i++) for (int i = 0; i < 50; i++)
{ {
ind.Update(100.0 + i * 0.5, 98.0 + i * 0.5); ind.Update(100.0 + (i * 0.5), 98.0 + (i * 0.5));
} }
// Anchor bar // Anchor bar
+1 -1
View File
@@ -93,7 +93,7 @@ public sealed class MapeValidationTests : IDisposable
// Build state well past warmup (actual always > 0 so MAPE denominator is valid) // Build state well past warmup (actual always > 0 so MAPE denominator is valid)
for (int i = 0; i < 50; i++) for (int i = 0; i < 50; i++)
{ {
ind.Update(100.0 + i * 0.5, 98.0 + i * 0.5); ind.Update(100.0 + (i * 0.5), 98.0 + (i * 0.5));
} }
// Anchor bar // Anchor bar
+1 -1
View File
@@ -336,7 +336,7 @@ public sealed class Mdae : AbstractBase
} }
// Median-of-three pivot selection for better pivot choice // Median-of-three pivot selection for better pivot choice
int mid = left + (right - left) / 2; int mid = left + ((right - left) / 2);
if (span[mid] < span[left]) if (span[mid] < span[left])
{ {
(span[left], span[mid]) = (span[mid], span[left]); (span[left], span[mid]) = (span[mid], span[left]);
+1 -1
View File
@@ -80,7 +80,7 @@ public sealed class MseValidationTests : IDisposable
// Build state well past warmup // Build state well past warmup
for (int i = 0; i < 50; i++) for (int i = 0; i < 50; i++)
{ {
ind.Update(100.0 + i * 0.5, 98.0 + i * 0.5); ind.Update(100.0 + (i * 0.5), 98.0 + (i * 0.5));
} }
// Anchor bar // Anchor bar
+1 -1
View File
@@ -82,7 +82,7 @@ public sealed class RmseValidationTests : IDisposable
// Build state well past warmup // Build state well past warmup
for (int i = 0; i < 50; i++) for (int i = 0; i < 50; i++)
{ {
ind.Update(100.0 + i * 0.5, 98.0 + i * 0.5); ind.Update(100.0 + (i * 0.5), 98.0 + (i * 0.5));
} }
// Anchor bar // Anchor bar
@@ -203,7 +203,7 @@ public sealed class RsquaredValidationTests : IDisposable
// Build state well past warmup // Build state well past warmup
for (int i = 0; i < 50; i++) for (int i = 0; i < 50; i++)
{ {
ind.Update(100.0 + i * 0.5, 98.0 + i * 0.5); ind.Update(100.0 + (i * 0.5), 98.0 + (i * 0.5));
} }
// Anchor bar // Anchor bar
+3 -3
View File
@@ -817,8 +817,8 @@ public sealed class CsvFeedTests : IDisposable
Assert.Equal(startTime, series[0].Time); // Jan 1 Assert.Equal(startTime, series[0].Time); // Jan 1
Assert.Equal(startTime + interval.Ticks, series[1].Time); // Jan 2 Assert.Equal(startTime + interval.Ticks, series[1].Time); // Jan 2
// Gap here (Jan 3 missing) // Gap here (Jan 3 missing)
Assert.Equal(startTime + 3 * interval.Ticks, series[2].Time); // Jan 4 Assert.Equal(startTime + (3 * interval.Ticks), series[2].Time); // Jan 4
Assert.Equal(startTime + 4 * interval.Ticks, series[3].Time); // Jan 5 Assert.Equal(startTime + (4 * interval.Ticks), series[3].Time); // Jan 5
} }
[Fact] [Fact]
@@ -941,7 +941,7 @@ public sealed class CsvFeedTests : IDisposable
// Jan 1 and Jan 3 present; Jan 2 absent → Fetch includes both with gap // Jan 1 and Jan 3 present; Jan 2 absent → Fetch includes both with gap
Assert.Equal(2, series.Count); Assert.Equal(2, series.Count);
Assert.Equal(startTime, series[0].Time); Assert.Equal(startTime, series[0].Time);
Assert.Equal(startTime + 2 * TimeSpan.FromDays(1).Ticks, series[1].Time); Assert.Equal(startTime + (2 * TimeSpan.FromDays(1).Ticks), series[1].Time);
} }
#endregion #endregion
+1 -1
View File
@@ -276,7 +276,7 @@ public class GBMTests
Assert.Equal(startTime, series[0].Time); Assert.Equal(startTime, series[0].Time);
Assert.Equal(startTime + interval.Ticks, series[1].Time); Assert.Equal(startTime + interval.Ticks, series[1].Time);
Assert.Equal(startTime + 2 * interval.Ticks, series[2].Time); Assert.Equal(startTime + (2 * interval.Ticks), series[2].Time);
} }
[Theory] [Theory]
+9 -9
View File
@@ -113,7 +113,7 @@ public sealed class GBM : IFeed
const double minutesPerYear = 252.0 * 6.5 * 60.0; const double minutesPerYear = 252.0 * 6.5 * 60.0;
double dt = timeframe.TotalMinutes / minutesPerYear; double dt = timeframe.TotalMinutes / minutesPerYear;
_drift = (mu - 0.5 * sigma * sigma) * dt; _drift = (mu - (0.5 * sigma * sigma)) * dt;
_vol = sigma * Math.Sqrt(dt); _vol = sigma * Math.Sqrt(dt);
} }
@@ -218,7 +218,7 @@ public sealed class GBM : IFeed
price = _lastPrice; price = _lastPrice;
} }
double volume = 1000 + NextDouble() * 1000; double volume = 1000 + (NextDouble() * 1000);
double open = _lastPrice; double open = _lastPrice;
double close = price; double close = price;
@@ -226,8 +226,8 @@ public sealed class GBM : IFeed
double rnd1 = NextDouble(); double rnd1 = NextDouble();
double rnd2 = NextDouble(); double rnd2 = NextDouble();
double high = Math.Max(open, close) * (1.0 + rnd1 * 0.01); double high = Math.Max(open, close) * (1.0 + (rnd1 * 0.01));
double low = Math.Min(open, close) * (1.0 - rnd2 * 0.01); double low = Math.Min(open, close) * (1.0 - (rnd2 * 0.01));
// Ensure valid OHLC constraints // Ensure valid OHLC constraints
high = Math.Max(high, Math.Max(open, close)); high = Math.Max(high, Math.Max(open, close));
@@ -252,7 +252,7 @@ public sealed class GBM : IFeed
price = _lastPrice; price = _lastPrice;
} }
double additionalVolume = 1000 + NextDouble() * 1000; double additionalVolume = 1000 + (NextDouble() * 1000);
var bar = _currentBar; var bar = _currentBar;
double newClose = price; double newClose = price;
@@ -412,7 +412,7 @@ public sealed class GBM : IFeed
{ {
const double minutesPerYear = 252.0 * 6.5 * 60.0; const double minutesPerYear = 252.0 * 6.5 * 60.0;
double dt = interval.TotalMinutes / minutesPerYear; double dt = interval.TotalMinutes / minutesPerYear;
double drift = (Mu - 0.5 * Sigma * Sigma) * dt; double drift = (Mu - (0.5 * Sigma * Sigma)) * dt;
double vol = Sigma * Math.Sqrt(dt); double vol = Sigma * Math.Sqrt(dt);
long timeStep = interval.Ticks; long timeStep = interval.Ticks;
@@ -441,8 +441,8 @@ public sealed class GBM : IFeed
o[i] = open; o[i] = open;
c[i] = close; c[i] = close;
double high = Math.Max(open, close) * (1.0 + rnd1 * 0.01); double high = Math.Max(open, close) * (1.0 + (rnd1 * 0.01));
double low = Math.Min(open, close) * (1.0 - rnd2 * 0.01); double low = Math.Min(open, close) * (1.0 - (rnd2 * 0.01));
// Ensure valid OHLC constraints // Ensure valid OHLC constraints
high = Math.Max(high, Math.Max(open, close)); high = Math.Max(high, Math.Max(open, close));
@@ -451,7 +451,7 @@ public sealed class GBM : IFeed
h[i] = high; h[i] = high;
l[i] = low; l[i] = low;
v[i] = 1000 + rnd3 * 1000; v[i] = 1000 + (rnd3 * 1000);
currentPrice = price; currentPrice = price;
currentTime += timeStep; currentTime += timeStep;
+3 -3
View File
@@ -79,7 +79,7 @@ public sealed class BaxterKing : AbstractBase
_pLow = pLow; _pLow = pLow;
_pHigh = pHigh; _pHigh = pHigh;
_k = k; _k = k;
_filterLen = 2 * k + 1; _filterLen = (2 * k) + 1;
Name = $"BaxterKing({pLow},{pHigh},{k})"; Name = $"BaxterKing({pLow},{pHigh},{k})";
WarmupPeriod = _filterLen; WarmupPeriod = _filterLen;
@@ -218,7 +218,7 @@ public sealed class BaxterKing : AbstractBase
{ {
double a = 2.0 * Math.PI / pHigh; // low cutoff angular frequency double a = 2.0 * Math.PI / pHigh; // low cutoff angular frequency
double b = 2.0 * Math.PI / pLow; // high cutoff angular frequency double b = 2.0 * Math.PI / pLow; // high cutoff angular frequency
int filterLen = 2 * k + 1; int filterLen = (2 * k) + 1;
// Compute ideal band-pass weights B[j] for j = 0..K // Compute ideal band-pass weights B[j] for j = 0..K
// B_0 = (b - a) / pi // B_0 = (b - a) / pi
@@ -266,7 +266,7 @@ public sealed class BaxterKing : AbstractBase
public static void Batch(ReadOnlySpan<double> source, Span<double> output, public static void Batch(ReadOnlySpan<double> source, Span<double> output,
int pLow = 6, int pHigh = 32, int k = 12) int pLow = 6, int pHigh = 32, int k = 12)
{ {
int filterLen = 2 * k + 1; int filterLen = (2 * k) + 1;
double[] weights = new double[filterLen]; double[] weights = new double[filterLen];
ComputeWeights(weights, pLow, pHigh, k); ComputeWeights(weights, pLow, pHigh, k);
+2 -2
View File
@@ -252,7 +252,7 @@ public sealed class Bilateral : AbstractBase
// Use Math.Max(0, ...) to handle potential floating point negative zero // Use Math.Max(0, ...) to handle potential floating point negative zero
// Pre-compute inverse for efficiency // Pre-compute inverse for efficiency
double invCount = 1.0 / count; double invCount = 1.0 / count;
double variance = Math.Max(0, (_state.SumSq - sum * sum * invCount) * invCount); double variance = Math.Max(0, (_state.SumSq - (sum * sum * invCount)) * invCount);
double stdev = Math.Sqrt(variance); double stdev = Math.Sqrt(variance);
double sigmaR = Math.Max(stdev * _sigmaRMult, 1e-10); double sigmaR = Math.Max(stdev * _sigmaRMult, 1e-10);
@@ -437,7 +437,7 @@ public sealed class Bilateral : AbstractBase
// Calculate StDev // Calculate StDev
double invCount = 1.0 / count; double invCount = 1.0 / count;
double variance = Math.Max(0, (sumSq - sum * sum * invCount) * invCount); double variance = Math.Max(0, (sumSq - (sum * sum * invCount)) * invCount);
double stdev = Math.Sqrt(variance); double stdev = Math.Sqrt(variance);
double sigmaR = Math.Max(stdev * sigmaRMult, 1e-10); double sigmaR = Math.Max(stdev * sigmaRMult, 1e-10);
+5 -5
View File
@@ -267,7 +267,7 @@ public sealed class Loess : AbstractBase
dist = 0.9999; dist = 0.9999;
} }
double t = 1.0 - dist * dist * dist; double t = 1.0 - (dist * dist * dist);
double w = t * t * t; double w = t * t * t;
double xi = i - halfWindow; double xi = i - halfWindow;
@@ -277,7 +277,7 @@ public sealed class Loess : AbstractBase
x2Sum += xi * xi * w; x2Sum += xi * xi * w;
} }
double delta = weightSum * x2Sum - xSum * xSum; double delta = (weightSum * x2Sum) - (xSum * xSum);
if (Math.Abs(delta) < double.Epsilon) if (Math.Abs(delta) < double.Epsilon)
{ {
delta = 1.0; delta = 1.0;
@@ -293,12 +293,12 @@ public sealed class Loess : AbstractBase
dist = 0.9999; dist = 0.9999;
} }
double t = 1.0 - dist * dist * dist; double t = 1.0 - (dist * dist * dist);
double w = t * t * t; double w = t * t * t;
double xi = i - halfWindow; double xi = i - halfWindow;
double term1 = x2Sum - xi * xSum; double term1 = x2Sum - (xi * xSum);
double term2 = targetX * (xi * weightSum - xSum); double term2 = targetX * ((xi * weightSum) - xSum);
double kValue = (w / delta) * (term1 + term2); double kValue = (w / delta) * (term1 + term2);
@@ -349,7 +349,7 @@ public sealed class AfirmaValidationTests : IDisposable
// Build state well past warmup // Build state well past warmup
for (int i = 0; i < 50; i++) for (int i = 0; i < 50; i++)
{ {
ind.Update(new TValue(t0.AddSeconds(i), 100.0 + i * 0.5)); ind.Update(new TValue(t0.AddSeconds(i), 100.0 + (i * 0.5)));
} }
// Anchor bar // Anchor bar
+11 -11
View File
@@ -316,7 +316,7 @@ public sealed class Afirma : AbstractBase
// Calculation in loop for clarity or formula: // Calculation in loop for clarity or formula:
double dn = (double)n; double dn = (double)n;
sx = (dn - 1.0) * dn * 0.5; sx = (dn - 1.0) * dn * 0.5;
sx2 = (dn - 1.0) * dn * (2.0 * dn - 1.0) / 6.0; sx2 = (dn - 1.0) * dn * ((2.0 * dn) - 1.0) / 6.0;
for (int i = 0; i < n; i++) for (int i = 0; i < n; i++)
{ {
@@ -328,11 +328,11 @@ public sealed class Afirma : AbstractBase
sxy += i * val; sxy += i * val;
} }
double denom = dn * sx2 - sx * sx; double denom = (dn * sx2) - (sx * sx);
if (Math.Abs(denom) > 1e-10) if (Math.Abs(denom) > 1e-10)
{ {
double slope = (dn * sxy - sx * sy) / denom; double slope = ((dn * sxy) - (sx * sy)) / denom;
double intercept = (sy - slope * sx) / dn; double intercept = (sy - (slope * sx)) / dn;
double lsSum = 0.0; double lsSum = 0.0;
double lsCount = 0.0; double lsCount = 0.0;
@@ -345,7 +345,7 @@ public sealed class Afirma : AbstractBase
for (int i = 0; i < count; i++) for (int i = 0; i < count; i++)
{ {
// Use fitted value (intercept + slope * i) for i < n, otherwise use original from buffer // Use fitted value (intercept + slope * i) for i < n, otherwise use original from buffer
double val = i < n ? intercept + slope * i : _buffer[count - 1 - i]; double val = i < n ? intercept + (slope * i) : _buffer[count - 1 - i];
lsSum += val; lsSum += val;
lsCount++; lsCount++;
} }
@@ -390,7 +390,7 @@ public sealed class Afirma : AbstractBase
for (int k = 0; k < _period; k++) for (int k = 0; k < _period; k++)
{ {
double kTwoPiDivP = k * twoPiDivP; double kTwoPiDivP = k * twoPiDivP;
double coef = a0 + a1 * Math.Cos(kTwoPiDivP); double coef = a0 + (a1 * Math.Cos(kTwoPiDivP));
if (Math.Abs(a2) > 1e-9) if (Math.Abs(a2) > 1e-9)
{ {
coef += a2 * Math.Cos(2.0 * kTwoPiDivP); coef += a2 * Math.Cos(2.0 * kTwoPiDivP);
@@ -475,7 +475,7 @@ public sealed class Afirma : AbstractBase
for (int k = 0; k < period; k++) for (int k = 0; k < period; k++)
{ {
double kTwoPiDivP = k * twoPiDivP; double kTwoPiDivP = k * twoPiDivP;
double coef = a0 + a1 * Math.Cos(kTwoPiDivP); double coef = a0 + (a1 * Math.Cos(kTwoPiDivP));
if (Math.Abs(a2) > 1e-9) if (Math.Abs(a2) > 1e-9)
{ {
coef += a2 * Math.Cos(2.0 * kTwoPiDivP); coef += a2 * Math.Cos(2.0 * kTwoPiDivP);
@@ -544,7 +544,7 @@ public sealed class Afirma : AbstractBase
double sx = 0.0, sx2 = 0.0, sy = 0.0, sxy = 0.0; double sx = 0.0, sx2 = 0.0, sy = 0.0, sxy = 0.0;
double dn = (double)n; double dn = (double)n;
sx = (dn - 1.0) * dn * 0.5; sx = (dn - 1.0) * dn * 0.5;
sx2 = (dn - 1.0) * dn * (2.0 * dn - 1.0) / 6.0; sx2 = (dn - 1.0) * dn * ((2.0 * dn) - 1.0) / 6.0;
for (int j = 0; j < n; j++) for (int j = 0; j < n; j++)
{ {
@@ -555,11 +555,11 @@ public sealed class Afirma : AbstractBase
sxy = Math.FusedMultiplyAdd(j, v, sxy); sxy = Math.FusedMultiplyAdd(j, v, sxy);
} }
double denom = dn * sx2 - sx * sx; double denom = (dn * sx2) - (sx * sx);
if (Math.Abs(denom) > 1e-10) if (Math.Abs(denom) > 1e-10)
{ {
double slope = (dn * sxy - sx * sy) / denom; double slope = ((dn * sxy) - (sx * sy)) / denom;
double intercept = (sy - slope * sx) / dn; double intercept = (sy - (slope * sx)) / dn;
double lsSum = 0.0; double lsSum = 0.0;
double lsCount = 0.0; double lsCount = 0.0;
+3 -3
View File
@@ -402,12 +402,12 @@ public sealed class CciValidationTests(ITestOutputHelper output) : IDisposable
// Build state well past warmup // Build state well past warmup
for (int i = 0; i < 50; i++) for (int i = 0; i < 50; i++)
{ {
double p = 100.0 + i * 0.5; double p = 100.0 + (i * 0.5);
ind.Update(new TBar(t0 + i * TimeSpan.TicksPerSecond, p, p + 1, p - 1, p, 1000)); ind.Update(new TBar(t0 + (i * TimeSpan.TicksPerSecond), p, p + 1, p - 1, p, 1000));
} }
// Anchor bar // Anchor bar
long anchorTime = t0 + 50 * TimeSpan.TicksPerSecond; long anchorTime = t0 + (50 * TimeSpan.TicksPerSecond);
var anchorBar = new TBar(anchorTime, 125.0, 126.0, 124.0, 125.0, 1000); var anchorBar = new TBar(anchorTime, 125.0, 126.0, 124.0, 125.0, 1000);
ind.Update(anchorBar, isNew: true); ind.Update(anchorBar, isNew: true);
double anchorResult = ind.Last.Value; double anchorResult = ind.Last.Value;
+1 -1
View File
@@ -248,7 +248,7 @@ public sealed class MacdValidationTests : IDisposable
// Build state well past warmup // Build state well past warmup
for (int i = 0; i < 50; i++) for (int i = 0; i < 50; i++)
{ {
ind.Update(new TValue(t0.AddSeconds(i), 100.0 + i * 0.5)); ind.Update(new TValue(t0.AddSeconds(i), 100.0 + (i * 0.5)));
} }
// Anchor bar // Anchor bar
-1
View File
@@ -129,7 +129,6 @@ public sealed class Macd : 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>
+3 -3
View File
@@ -248,8 +248,8 @@ public class PrsValidationTests
for (int i = 0; i < 10; i++) for (int i = 0; i < 10; i++)
{ {
double basePrice = 100 * (1 + i * 0.05); // 5% growth double basePrice = 100 * (1 + (i * 0.05)); // 5% growth
double compPrice = 50 * (1 + i * 0.05); // 5% growth double compPrice = 50 * (1 + (i * 0.05)); // 5% growth
var result = prs.Update(basePrice, compPrice, true); var result = prs.Update(basePrice, compPrice, true);
results.Add(result.Value); results.Add(result.Value);
} }
@@ -556,7 +556,7 @@ public class PrsValidationTests
// Build state well past warmup // Build state well past warmup
for (int i = 0; i < 50; i++) for (int i = 0; i < 50; i++)
{ {
ind.Update(100.0 + i * 0.5, 98.0 + i * 0.5); ind.Update(100.0 + (i * 0.5), 98.0 + (i * 0.5));
} }
// Anchor bar // Anchor bar
-1
View File
@@ -352,5 +352,4 @@ public sealed class Prs : AbstractBase
TSeries results = Batch(baseSeries, compSeries, smoothPeriod); TSeries results = Batch(baseSeries, compSeries, smoothPeriod);
return (results, indicator); return (results, indicator);
} }
} }
+20 -21
View File
@@ -78,7 +78,6 @@ public class RsxValidationTests
// Core RSX calculations (assuming price input as closing price): // Core RSX calculations (assuming price input as closing price):
double f8 = 100 * price; double f8 = 100 * price;
if (!initialized) if (!initialized)
{ {
lastF8 = f8; lastF8 = f8;
@@ -89,32 +88,32 @@ public class RsxValidationTests
lastF8 = f8; lastF8 = f8;
// First smoothing stage: // First smoothing stage:
f28 = ialpha * f28 + alpha * v8; f28 = (ialpha * f28) + (alpha * v8);
f30 = alpha * f28 + ialpha * f30; f30 = (alpha * f28) + (ialpha * f30);
double vC = 1.5 * f28 - 0.5 * f30; double vC = (1.5 * f28) - (0.5 * f30);
// Second smoothing stage: // Second smoothing stage:
f38 = ialpha * f38 + alpha * vC; f38 = (ialpha * f38) + (alpha * vC);
f40 = alpha * f38 + ialpha * f40; f40 = (alpha * f38) + (ialpha * f40);
double v10 = 1.5 * f38 - 0.5 * f40; double v10 = (1.5 * f38) - (0.5 * f40);
// Third smoothing stage: // Third smoothing stage:
f48 = ialpha * f48 + alpha * v10; f48 = (ialpha * f48) + (alpha * v10);
f50 = alpha * f48 + ialpha * f50; f50 = (alpha * f48) + (ialpha * f50);
double v14 = 1.5 * f48 - 0.5 * f50; double v14 = (1.5 * f48) - (0.5 * f50);
// Repeat stages for absolute value (momentum magnitude): // Repeat stages for absolute value (momentum magnitude):
f58 = ialpha * f58 + alpha * Math.Abs(v8); f58 = (ialpha * f58) + (alpha * Math.Abs(v8));
f60 = alpha * f58 + ialpha * f60; f60 = (alpha * f58) + (ialpha * f60);
double v18 = 1.5 * f58 - 0.5 * f60; double v18 = (1.5 * f58) - (0.5 * f60);
f68 = ialpha * f68 + alpha * v18; f68 = (ialpha * f68) + (alpha * v18);
f70 = alpha * f68 + ialpha * f70; f70 = (alpha * f68) + (ialpha * f70);
double v1C = 1.5 * f68 - 0.5 * f70; double v1C = (1.5 * f68) - (0.5 * f70);
f78 = ialpha * f78 + alpha * v1C; f78 = (ialpha * f78) + (alpha * v1C);
f80 = alpha * f78 + ialpha * f80; f80 = (alpha * f78) + (ialpha * f80);
double v20 = 1.5 * f78 - 0.5 * f80; double v20 = (1.5 * f78) - (0.5 * f80);
// Final RSX value: // Final RSX value:
double rsx; double rsx;
if (v20 > 1e-10) // Avoid division by zero if (v20 > 1e-10) // Avoid division by zero
{ {
double v4 = (v14 / v20 + 1.0) * 50.0; double v4 = ((v14 / v20) + 1.0) * 50.0;
rsx = Math.Clamp(v4, 0.0, 100.0); rsx = Math.Clamp(v4, 0.0, 100.0);
} }
else else
@@ -152,7 +151,7 @@ public class RsxValidationTests
// Build state well past warmup // Build state well past warmup
for (int i = 0; i < 50; i++) for (int i = 0; i < 50; i++)
{ {
ind.Update(new TValue(t0.AddSeconds(i), 100.0 + i * 0.5)); ind.Update(new TValue(t0.AddSeconds(i), 100.0 + (i * 0.5)));
} }
// Anchor bar // Anchor bar
+5 -5
View File
@@ -103,10 +103,10 @@ public class DecayIndicatorTests
{ {
indicator.HistoricalData.AddBar( indicator.HistoricalData.AddBar(
now.AddMinutes(i), now.AddMinutes(i),
100 + i * 2, 100 + (i * 2),
105 + i * 2, 105 + (i * 2),
95 + i * 2, 95 + (i * 2),
102 + i * 2); 102 + (i * 2));
indicator.ProcessUpdate(new UpdateArgs(UpdateReason.HistoricalBar)); indicator.ProcessUpdate(new UpdateArgs(UpdateReason.HistoricalBar));
} }
@@ -158,7 +158,7 @@ public class DecayIndicatorTests
for (int i = 0; i < 10; i++) for (int i = 0; i < 10; i++)
{ {
double price = 100 + i * 5; double price = 100 + (i * 5);
indicator.HistoricalData.AddBar(now.AddMinutes(i), price, price + 2, price - 2, price); indicator.HistoricalData.AddBar(now.AddMinutes(i), price, price + 2, price - 2, price);
indicator.ProcessUpdate(new UpdateArgs(UpdateReason.HistoricalBar)); indicator.ProcessUpdate(new UpdateArgs(UpdateReason.HistoricalBar));
} }
+1 -1
View File
@@ -337,7 +337,7 @@ public class DecayTests
for (int i = 0; i < largeSize; i++) for (int i = 0; i < largeSize; i++)
{ {
source[i] = 100.0 + i * 0.1; source[i] = 100.0 + (i * 0.1);
} }
Decay.Batch(source, output, TestPeriod); Decay.Batch(source, output, TestPeriod);
+1 -1
View File
@@ -331,7 +331,7 @@ public class DwtValidationTests
// Build state well past warmup (WarmupPeriod = 2^4 = 16) // Build state well past warmup (WarmupPeriod = 2^4 = 16)
for (int i = 0; i < 50; i++) for (int i = 0; i < 50; i++)
{ {
ind.Update(new TValue(t0.AddSeconds(i), 100.0 + i * 0.5)); ind.Update(new TValue(t0.AddSeconds(i), 100.0 + (i * 0.5)));
} }
// Anchor bar // Anchor bar
+2 -2
View File
@@ -440,9 +440,9 @@ public sealed class Dwt : AbstractBase
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
static double Get(Span<double> b, int h, int c, int lag) static double Get(Span<double> b, int h, int c, int lag)
{ {
int idx = ((h - 1 - lag) % c + c) % c; int idx = (((h - 1 - lag) % c) + c) % c;
int maxLag = c - 1; int maxLag = c - 1;
if (lag > maxLag) { idx = ((h - 1 - maxLag) % c + c) % c; } if (lag > maxLag) { idx = (((h - 1 - maxLag) % c) + c) % c; }
return b[idx]; return b[idx];
} }
@@ -103,10 +103,10 @@ public class EdecayIndicatorTests
{ {
indicator.HistoricalData.AddBar( indicator.HistoricalData.AddBar(
now.AddMinutes(i), now.AddMinutes(i),
100 + i * 2, 100 + (i * 2),
105 + i * 2, 105 + (i * 2),
95 + i * 2, 95 + (i * 2),
102 + i * 2); 102 + (i * 2));
indicator.ProcessUpdate(new UpdateArgs(UpdateReason.HistoricalBar)); indicator.ProcessUpdate(new UpdateArgs(UpdateReason.HistoricalBar));
} }
@@ -158,7 +158,7 @@ public class EdecayIndicatorTests
for (int i = 0; i < 10; i++) for (int i = 0; i < 10; i++)
{ {
double price = 100 + i * 5; double price = 100 + (i * 5);
indicator.HistoricalData.AddBar(now.AddMinutes(i), price, price + 2, price - 2, price); indicator.HistoricalData.AddBar(now.AddMinutes(i), price, price + 2, price - 2, price);
indicator.ProcessUpdate(new UpdateArgs(UpdateReason.HistoricalBar)); indicator.ProcessUpdate(new UpdateArgs(UpdateReason.HistoricalBar));
} }
+1 -1
View File
@@ -337,7 +337,7 @@ public class EdecayTests
for (int i = 0; i < largeSize; i++) for (int i = 0; i < largeSize; i++)
{ {
source[i] = 100.0 + i * 0.1; source[i] = 100.0 + (i * 0.1);
} }
Edecay.Batch(source, output, TestPeriod); Edecay.Batch(source, output, TestPeriod);
+3 -3
View File
@@ -53,7 +53,7 @@ public class FftValidationTests
for (int i = 0; i < windowSize * 3; i++) for (int i = 0; i < windowSize * 3; i++)
{ {
double signal = 50.0 + 10.0 * Math.Sin(2.0 * Math.PI * i / targetPeriod); double signal = 50.0 + (10.0 * Math.Sin(2.0 * Math.PI * i / targetPeriod));
indicator.Update(new TValue(time.AddMinutes(i), signal), true); indicator.Update(new TValue(time.AddMinutes(i), signal), true);
} }
@@ -74,7 +74,7 @@ public class FftValidationTests
for (int i = 0; i < windowSize * 4; i++) for (int i = 0; i < windowSize * 4; i++)
{ {
double signal = 50.0 + 10.0 * Math.Sin(2.0 * Math.PI * i / targetPeriod); double signal = 50.0 + (10.0 * Math.Sin(2.0 * Math.PI * i / targetPeriod));
indicator.Update(new TValue(time.AddMinutes(i), signal), true); indicator.Update(new TValue(time.AddMinutes(i), signal), true);
} }
@@ -246,7 +246,7 @@ public class FftValidationTests
for (int i = 0; i < 50; i++) for (int i = 0; i < 50; i++)
{ {
ind.Update(new TValue(t0.AddSeconds(i), 100.0 + 10.0 * Math.Sin(2 * Math.PI * i / 8.0))); ind.Update(new TValue(t0.AddSeconds(i), 100.0 + (10.0 * Math.Sin(2 * Math.PI * i / 8.0))));
} }
var anchorTime = t0.AddSeconds(50); var anchorTime = t0.AddSeconds(50);
+4 -4
View File
@@ -84,7 +84,7 @@ public sealed class Fft : AbstractBase
_hanning = new double[windowSize]; _hanning = new double[windowSize];
for (int n = 0; n < windowSize; n++) for (int n = 0; n < windowSize; n++)
{ {
_hanning[n] = 0.5 - 0.5 * Math.Cos(twoPiOverN * n); _hanning[n] = 0.5 - (0.5 * Math.Cos(twoPiOverN * n));
} }
// Precompute bit-reversal permutation table // Precompute bit-reversal permutation table
@@ -262,7 +262,7 @@ public sealed class Fft : AbstractBase
} }
// Parabolic interpolation: shift = 0.5*(a-c)/(a - 2b + c) // Parabolic interpolation: shift = 0.5*(a-c)/(a - 2b + c)
double denom = a - 2.0 * b + c; double denom = a - (2.0 * b) + c;
double shift = Math.Abs(denom) > 0.0 ? 0.5 * (a - c) / denom : 0.0; double shift = Math.Abs(denom) > 0.0 ? 0.5 * (a - c) / denom : 0.0;
double dominantPeriod = (double)_windowSize / (bestK + shift); double dominantPeriod = (double)_windowSize / (bestK + shift);
@@ -417,7 +417,7 @@ public sealed class Fft : AbstractBase
{ {
for (int n = 0; n < windowSize; n++) for (int n = 0; n < windowSize; n++)
{ {
hanning[n] = 0.5 - 0.5 * Math.Cos(twoPiOverN * n); hanning[n] = 0.5 - (0.5 * Math.Cos(twoPiOverN * n));
bitRev[n] = BitReverse(n, log2N); bitRev[n] = BitReverse(n, log2N);
} }
@@ -476,7 +476,7 @@ public sealed class Fft : AbstractBase
workIm[bestK + 1] * workIm[bestK + 1]) workIm[bestK + 1] * workIm[bestK + 1])
: bestMag; : bestMag;
double denom = a - 2.0 * bestMag + c; double denom = a - (2.0 * bestMag) + c;
double shift = Math.Abs(denom) > 0.0 ? 0.5 * (a - c) / denom : 0.0; double shift = Math.Abs(denom) > 0.0 ? 0.5 * (a - c) / denom : 0.0;
double dominant = (double)windowSize / (bestK + shift); double dominant = (double)windowSize / (bestK + shift);
double clamped = Math.Clamp(dominant, minPeriod, maxPeriod); double clamped = Math.Clamp(dominant, minPeriod, maxPeriod);
+2 -2
View File
@@ -73,7 +73,7 @@ public sealed class Ifft : AbstractBase
_hanning = new double[windowSize]; _hanning = new double[windowSize];
for (int n = 0; n < windowSize; n++) for (int n = 0; n < windowSize; n++)
{ {
_hanning[n] = 0.5 - 0.5 * Math.Cos(twoPiOverN * n); _hanning[n] = 0.5 - (0.5 * Math.Cos(twoPiOverN * n));
} }
// Precompute bit-reversal permutation table // Precompute bit-reversal permutation table
@@ -330,7 +330,7 @@ public sealed class Ifft : AbstractBase
{ {
for (int n = 0; n < windowSize; n++) for (int n = 0; n < windowSize; n++)
{ {
hanning[n] = 0.5 - 0.5 * Math.Cos(twoPiOverN * n); hanning[n] = 0.5 - (0.5 * Math.Cos(twoPiOverN * n));
bitRev[n] = BitReverse(n, log2N); bitRev[n] = BitReverse(n, log2N);
} }
+3 -3
View File
@@ -112,7 +112,7 @@ public sealed class QqeValidationTests
// Strongly trending up // Strongly trending up
for (int i = 0; i < 200; i++) for (int i = 0; i < 200; i++)
{ {
ind.Update(new TValue(DateTime.UtcNow.AddMinutes(i), 50.0 + i * 0.5)); ind.Update(new TValue(DateTime.UtcNow.AddMinutes(i), 50.0 + (i * 0.5)));
} }
Assert.True(ind.IsHot); Assert.True(ind.IsHot);
@@ -130,7 +130,7 @@ public sealed class QqeValidationTests
// Strongly trending down // Strongly trending down
for (int i = 0; i < 200; i++) for (int i = 0; i < 200; i++)
{ {
ind.Update(new TValue(DateTime.UtcNow.AddMinutes(i), 200.0 - i * 0.5)); ind.Update(new TValue(DateTime.UtcNow.AddMinutes(i), 200.0 - (i * 0.5)));
} }
Assert.True(ind.IsHot); Assert.True(ind.IsHot);
@@ -251,7 +251,7 @@ public sealed class QqeValidationTests
// Build state well past warmup (WarmupPeriod ≈ 37) // Build state well past warmup (WarmupPeriod ≈ 37)
for (int i = 0; i < 60; i++) for (int i = 0; i < 60; i++)
{ {
ind.Update(new TValue(t0.AddSeconds(i), 100.0 + i * 0.5)); ind.Update(new TValue(t0.AddSeconds(i), 100.0 + (i * 0.5)));
} }
// Anchor bar // Anchor bar
+3 -3
View File
@@ -101,11 +101,11 @@ public sealed class Qqe : AbstractBase
_sfAlpha = 2.0 / (smoothFactor + 1.0); _sfAlpha = 2.0 / (smoothFactor + 1.0);
_sfBeta = 1.0 - _sfAlpha; _sfBeta = 1.0 - _sfAlpha;
int darPeriod = 2 * smoothFactor - 1; int darPeriod = (2 * smoothFactor) - 1;
_darAlpha = 2.0 / (darPeriod + 1.0); _darAlpha = 2.0 / (darPeriod + 1.0);
_darBeta = 1.0 - _darAlpha; _darBeta = 1.0 - _darAlpha;
WarmupPeriod = rsiPeriod + smoothFactor + darPeriod * 2; WarmupPeriod = rsiPeriod + smoothFactor + (darPeriod * 2);
_s = new State( _s = new State(
Count: 0, Count: 0,
@@ -168,7 +168,7 @@ public sealed class Qqe : AbstractBase
double avgGain = s.RmaGain * cRma; double avgGain = s.RmaGain * cRma;
double avgLoss = s.RmaLoss * cRma; double avgLoss = s.RmaLoss * cRma;
double rs = avgLoss < Epsilon ? 100.0 : avgGain / avgLoss; double rs = avgLoss < Epsilon ? 100.0 : avgGain / avgLoss;
double rsiVal = 100.0 - 100.0 / (1.0 + rs); double rsiVal = 100.0 - (100.0 / (1.0 + rs));
// ── Stage 2: EMA smooth of RSI (α = 2/(SF+1)) with §2 warmup → rsiMA ── // ── Stage 2: EMA smooth of RSI (α = 2/(SF+1)) with §2 warmup → rsiMA ──
s.RawRsiMa = Math.FusedMultiplyAdd(s.RawRsiMa, _sfBeta, rsiVal * _sfAlpha); s.RawRsiMa = Math.FusedMultiplyAdd(s.RawRsiMa, _sfBeta, rsiVal * _sfAlpha);
@@ -225,12 +225,12 @@ public sealed class SqueezeValidationTests
// Build state well past warmup (WarmupPeriod = 20) // Build state well past warmup (WarmupPeriod = 20)
for (int i = 0; i < 50; i++) for (int i = 0; i < 50; i++)
{ {
double p = 100.0 + i * 0.5; double p = 100.0 + (i * 0.5);
ind.Update(new TBar(t0 + i * TimeSpan.TicksPerSecond, p, p + 1, p - 1, p, 1000), isNew: true); ind.Update(new TBar(t0 + (i * TimeSpan.TicksPerSecond), p, p + 1, p - 1, p, 1000), isNew: true);
} }
// Anchor bar // Anchor bar
long anchorTime = t0 + 50 * TimeSpan.TicksPerSecond; long anchorTime = t0 + (50 * TimeSpan.TicksPerSecond);
var anchorBar = new TBar(anchorTime, 125.0, 126.0, 124.0, 125.0, 1000); var anchorBar = new TBar(anchorTime, 125.0, 126.0, 124.0, 125.0, 1000);
ind.Update(anchorBar, isNew: true); ind.Update(anchorBar, isNew: true);
double anchorMomentum = ind.Momentum; double anchorMomentum = ind.Momentum;
+10 -10
View File
@@ -213,7 +213,7 @@ public sealed class Squeeze : ITValuePublisher
int n = Math.Max(1, s.SmaCount); int n = Math.Max(1, s.SmaCount);
double smaVal = s.SmaSum / n; double smaVal = s.SmaSum / n;
double variance = Math.Max(0.0, s.SmaSumSq / n - smaVal * smaVal); double variance = Math.Max(0.0, (s.SmaSumSq / n) - (smaVal * smaVal));
double stddev = Math.Sqrt(variance); double stddev = Math.Sqrt(variance);
double bbUpper = Math.FusedMultiplyAdd(_bbMult, stddev, smaVal); double bbUpper = Math.FusedMultiplyAdd(_bbMult, stddev, smaVal);
double bbLower = Math.FusedMultiplyAdd(-_bbMult, stddev, smaVal); double bbLower = Math.FusedMultiplyAdd(-_bbMult, stddev, smaVal);
@@ -269,7 +269,7 @@ public sealed class Squeeze : ITValuePublisher
if (!double.IsNaN(dl) && dl < lowest) { lowest = dl; } if (!double.IsNaN(dl) && dl < lowest) { lowest = dl; }
} }
double donMid = (highest + lowest) * 0.5; double donMid = (highest + lowest) * 0.5;
double delta = close - (donMid + smaVal) * 0.5; double delta = close - ((donMid + smaVal) * 0.5);
// ===== STAGE 5: Linear regression of delta over period (O(1) incremental) ===== // ===== STAGE 5: Linear regression of delta over period (O(1) incremental) =====
UpdateLrBuf(ref s, delta); UpdateLrBuf(ref s, delta);
@@ -277,16 +277,16 @@ public sealed class Squeeze : ITValuePublisher
int pn = Math.Min(s.LrCount, _period); int pn = Math.Min(s.LrCount, _period);
int startIdx = s.LrCount - pn; int startIdx = s.LrCount - pn;
// Closed-form sums: ΣX and ΣX² // Closed-form sums: ΣX and ΣX²
double sumX = (double)pn * (2.0 * startIdx + pn - 1) * 0.5; double sumX = (double)pn * ((2.0 * startIdx) + pn - 1) * 0.5;
double sumX2 = Math.FusedMultiplyAdd( double sumX2 = Math.FusedMultiplyAdd(
pn, (double)startIdx * startIdx, pn, (double)startIdx * startIdx,
Math.FusedMultiplyAdd( Math.FusedMultiplyAdd(
(double)startIdx * (pn - 1), pn, (double)startIdx * (pn - 1), pn,
(double)(pn - 1) * pn * (2 * pn - 1) / 6.0)); (double)(pn - 1) * pn * ((2 * pn) - 1) / 6.0));
double denomX = Math.FusedMultiplyAdd(pn, sumX2, -(sumX * sumX)); double denomX = Math.FusedMultiplyAdd(pn, sumX2, -(sumX * sumX));
double slope = denomX == 0.0 ? 0.0 double slope = denomX == 0.0 ? 0.0
: Math.FusedMultiplyAdd(pn, s.SumXY, -(sumX * s.SumY)) / denomX; : Math.FusedMultiplyAdd(pn, s.SumXY, -(sumX * s.SumY)) / denomX;
double intercept = (s.SumY - slope * sumX) / pn; double intercept = (s.SumY - (slope * sumX)) / pn;
double momentum = Math.FusedMultiplyAdd(slope, s.LrCount - 1, intercept); double momentum = Math.FusedMultiplyAdd(slope, s.LrCount - 1, intercept);
_s = s; _s = s;
@@ -554,7 +554,7 @@ public sealed class Squeeze : ITValuePublisher
int n = Math.Max(1, smaCount); int n = Math.Max(1, smaCount);
double smaVal = smaSum / n; double smaVal = smaSum / n;
double vari = Math.Max(0.0, smaSumSq / n - smaVal * smaVal); double vari = Math.Max(0.0, (smaSumSq / n) - (smaVal * smaVal));
double sd = Math.Sqrt(vari); double sd = Math.Sqrt(vari);
double bbUpper = Math.FusedMultiplyAdd(bbMult, sd, smaVal); double bbUpper = Math.FusedMultiplyAdd(bbMult, sd, smaVal);
double bbLower = Math.FusedMultiplyAdd(-bbMult, sd, smaVal); double bbLower = Math.FusedMultiplyAdd(-bbMult, sd, smaVal);
@@ -602,7 +602,7 @@ public sealed class Squeeze : ITValuePublisher
if (!double.IsNaN(dl) && dl < lowest) { lowest = dl; } if (!double.IsNaN(dl) && dl < lowest) { lowest = dl; }
} }
double donMid = (highest + lowest) * 0.5; double donMid = (highest + lowest) * 0.5;
double delta = c - (donMid + smaVal) * 0.5; double delta = c - ((donMid + smaVal) * 0.5);
// Stage 5: LinReg incremental // Stage 5: LinReg incremental
double oldLr = lrBuf[lrHead]; double oldLr = lrBuf[lrHead];
@@ -620,16 +620,16 @@ public sealed class Squeeze : ITValuePublisher
int pn = Math.Min(lrCount, period); int pn = Math.Min(lrCount, period);
int startI = lrCount - pn; int startI = lrCount - pn;
double sx = (double)pn * (2.0 * startI + pn - 1) * 0.5; double sx = (double)pn * ((2.0 * startI) + pn - 1) * 0.5;
double sx2 = Math.FusedMultiplyAdd( double sx2 = Math.FusedMultiplyAdd(
pn, (double)startI * startI, pn, (double)startI * startI,
Math.FusedMultiplyAdd( Math.FusedMultiplyAdd(
(double)startI * (pn - 1), pn, (double)startI * (pn - 1), pn,
(double)(pn - 1) * pn * (2 * pn - 1) / 6.0)); (double)(pn - 1) * pn * ((2 * pn) - 1) / 6.0));
double denomX = Math.FusedMultiplyAdd(pn, sx2, -(sx * sx)); double denomX = Math.FusedMultiplyAdd(pn, sx2, -(sx * sx));
double slope = denomX == 0.0 ? 0.0 double slope = denomX == 0.0 ? 0.0
: Math.FusedMultiplyAdd(pn, sumXY, -(sx * sumY)) / denomX; : Math.FusedMultiplyAdd(pn, sumXY, -(sx * sumY)) / denomX;
double intc = (sumY - slope * sx) / pn; double intc = (sumY - (slope * sx)) / pn;
double momentum = Math.FusedMultiplyAdd(slope, lrCount - 1, intc); double momentum = Math.FusedMultiplyAdd(slope, lrCount - 1, intc);
momOut[i] = momentum; momOut[i] = momentum;
@@ -415,7 +415,7 @@ public sealed class StochrsiValidationTests : IDisposable
// Build state well past warmup (WarmupPeriod ≈ 31) // Build state well past warmup (WarmupPeriod ≈ 31)
for (int i = 0; i < 50; i++) for (int i = 0; i < 50; i++)
{ {
ind.Update(new TValue(t0.AddSeconds(i), 100.0 + i * 0.5)); ind.Update(new TValue(t0.AddSeconds(i), 100.0 + (i * 0.5)));
} }
// Anchor bar // Anchor bar
-1
View File
@@ -124,7 +124,6 @@ public sealed class Acf : AbstractBase
double oldVal = _buffer.Oldest; double oldVal = _buffer.Oldest;
_sum -= oldVal; _sum -= oldVal;
_sumSq = Math.FusedMultiplyAdd(-oldVal, oldVal, _sumSq); _sumSq = Math.FusedMultiplyAdd(-oldVal, oldVal, _sumSq);
} }
// Add new value // Add new value
@@ -507,5 +507,4 @@ public sealed class Cointegration : AbstractBase
return (result, indicator); return (result, indicator);
} }
} }
@@ -357,5 +357,4 @@ public sealed class Correlation : AbstractBase
return (result, indicator); return (result, indicator);
} }
} }
+8 -8
View File
@@ -117,7 +117,7 @@ public sealed class Covariance : AbstractBase
if (n >= 2) if (n >= 2)
{ {
// Standard covariance formula: (sumXY - sumX*sumY/n) / denom // Standard covariance formula: (sumXY - sumX*sumY/n) / denom
double numerator = _sumXY - (_sumX * _sumY) / n; double numerator = _sumXY - ((_sumX * _sumY) / n);
double denominator = _isPopulation ? n : (n - 1); double denominator = _isPopulation ? n : (n - 1);
cov = numerator / denominator; cov = numerator / denominator;
} }
@@ -278,7 +278,7 @@ public sealed class Covariance : AbstractBase
double n = i + 1; double n = i + 1;
if (n >= 2) if (n >= 2)
{ {
double numerator = sumXY - (sumX * sumY) / n; double numerator = sumXY - ((sumX * sumY) / n);
double denominator = isPopulation ? n : (n - 1); double denominator = isPopulation ? n : (n - 1);
output[i] = numerator / denominator; output[i] = numerator / denominator;
} }
@@ -309,7 +309,7 @@ public sealed class Covariance : AbstractBase
sumX = sumX - oldX + x; sumX = sumX - oldX + x;
sumY = sumY - oldY + y; sumY = sumY - oldY + y;
sumXY = sumXY - oldX * oldY + x * y; sumXY = sumXY - (oldX * oldY) + (x * y);
bufferX[bufferIndex] = x; bufferX[bufferIndex] = x;
bufferY[bufferIndex] = y; bufferY[bufferIndex] = y;
@@ -320,7 +320,7 @@ public sealed class Covariance : AbstractBase
} }
double n = period; double n = period;
double numerator = sumXY - (sumX * sumY) / n; double numerator = sumXY - ((sumX * sumY) / n);
double denominator = isPopulation ? n : (n - 1); double denominator = isPopulation ? n : (n - 1);
output[i] = numerator / denominator; output[i] = numerator / denominator;
@@ -364,7 +364,7 @@ public sealed class Covariance : AbstractBase
double n = i + 1; double n = i + 1;
if (n >= 2) if (n >= 2)
{ {
double num = sumXY - (sumX * sumY) / n; double num = sumXY - ((sumX * sumY) / n);
double den = isPopulation ? n : (n - 1); double den = isPopulation ? n : (n - 1);
Unsafe.Add(ref outRef, i) = num / den; Unsafe.Add(ref outRef, i) = num / den;
} }
@@ -400,7 +400,7 @@ public sealed class Covariance : AbstractBase
var vInvDenom = Vector256.Create(invDenom); var vInvDenom = Vector256.Create(invDenom);
var vZero = Vector256<double>.Zero; var vZero = Vector256<double>.Zero;
int simdEnd = period + ((len - period) / VectorWidth) * VectorWidth; int simdEnd = period + (((len - period) / VectorWidth) * VectorWidth);
int tickCount = period; int tickCount = period;
for (int i = period; i < simdEnd; i += VectorWidth) for (int i = period; i < simdEnd; i += VectorWidth)
@@ -513,9 +513,9 @@ public sealed class Covariance : AbstractBase
sumX = sumX - oldX + x; sumX = sumX - oldX + x;
sumY = sumY - oldY + y; sumY = sumY - oldY + y;
sumXY = sumXY - oldX * oldY + x * y; sumXY = sumXY - (oldX * oldY) + (x * y);
double numerator = sumXY - sumX * sumY * invN; double numerator = sumXY - (sumX * sumY * invN);
Unsafe.Add(ref outRef, i) = numerator * invDenom; Unsafe.Add(ref outRef, i) = numerator * invDenom;
} }
} }
+15 -15
View File
@@ -150,7 +150,7 @@ public sealed class Kurtosis : AbstractBase
// Second central moment (variance): m₂ = Σ(x-μ)²/n // Second central moment (variance): m₂ = Σ(x-μ)²/n
// = (SumSq - Sum²/n) / n // = (SumSq - Sum²/n) / n
double m2Numerator = _sumSq - (_sum * _sum) / n; double m2Numerator = _sumSq - ((_sum * _sum) / n);
if (m2Numerator < Epsilon) if (m2Numerator < Epsilon)
{ {
m2Numerator = 0; m2Numerator = 0;
@@ -165,10 +165,10 @@ public sealed class Kurtosis : AbstractBase
// m₄ = SumQu/n - 4·mean·SumCu/n + 6·mean²·SumSq/n - 3·mean⁴ // m₄ = SumQu/n - 4·mean·SumCu/n + 6·mean²·SumSq/n - 3·mean⁴
// Note: last term -4·mean³·Sum/n + mean⁴ = -4·mean⁴ + mean⁴ = -3·mean⁴ // Note: last term -4·mean³·Sum/n + mean⁴ = -4·mean⁴ + mean⁴ = -3·mean⁴
double meanSq = mean * mean; double meanSq = mean * mean;
double m4 = _sumQu / n double m4 = (_sumQu / n)
- 4.0 * mean * _sumCu / n - (4.0 * mean * _sumCu / n)
+ 6.0 * meanSq * _sumSq / n + (6.0 * meanSq * _sumSq / n)
- 3.0 * meanSq * meanSq; - (3.0 * meanSq * meanSq);
// Population excess kurtosis: g₂ = m₄/m₂² - 3 // Population excess kurtosis: g₂ = m₄/m₂² - 3
double g2 = (m4 / (m2 * m2)) - 3.0; double g2 = (m4 / (m2 * m2)) - 3.0;
@@ -184,7 +184,7 @@ public sealed class Kurtosis : AbstractBase
double denom = (n - 2.0) * (n - 3.0); double denom = (n - 2.0) * (n - 3.0);
if (Math.Abs(denom) > Epsilon) if (Math.Abs(denom) > Epsilon)
{ {
kurtosis = ((n - 1.0) / denom) * ((n + 1.0) * g2 + 6.0); kurtosis = ((n - 1.0) / denom) * (((n + 1.0) * g2) + 6.0);
} }
} }
} }
@@ -327,7 +327,7 @@ public sealed class Kurtosis : AbstractBase
{ {
double mean = sum / n; double mean = sum / n;
double m2Numerator = sumSq - (sum * sum) / n; double m2Numerator = sumSq - ((sum * sum) / n);
if (m2Numerator < Epsilon) if (m2Numerator < Epsilon)
{ {
return 0; return 0;
@@ -342,10 +342,10 @@ public sealed class Kurtosis : AbstractBase
// Fourth central moment via raw moments // Fourth central moment via raw moments
double meanSq = mean * mean; double meanSq = mean * mean;
double m4 = sumQu / n double m4 = (sumQu / n)
- 4.0 * mean * sumCu / n - (4.0 * mean * sumCu / n)
+ 6.0 * meanSq * sumSq / n + (6.0 * meanSq * sumSq / n)
- 3.0 * meanSq * meanSq; - (3.0 * meanSq * meanSq);
double g2 = (m4 / (m2 * m2)) - 3.0; double g2 = (m4 / (m2 * m2)) - 3.0;
@@ -361,7 +361,7 @@ public sealed class Kurtosis : AbstractBase
return 0; return 0;
} }
return ((n - 1.0) / denom) * ((n + 1.0) * g2 + 6.0); return ((n - 1.0) / denom) * (((n + 1.0) * g2) + 6.0);
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -415,8 +415,8 @@ public sealed class Kurtosis : AbstractBase
double oldSq = oldVal * oldVal; double oldSq = oldVal * oldVal;
sum = sum - oldVal + val; sum = sum - oldVal + val;
sumSq = sumSq - oldSq + valSq; sumSq = sumSq - oldSq + valSq;
sumCu = sumCu - oldSq * oldVal + valSq * val; sumCu = sumCu - (oldSq * oldVal) + (valSq * val);
sumQu = sumQu - oldSq * oldSq + valSq * valSq; sumQu = sumQu - (oldSq * oldSq) + (valSq * valSq);
output[i] = CalculateKurtosisFromSums(sum, sumSq, sumCu, sumQu, period, isPopulation); output[i] = CalculateKurtosisFromSums(sum, sumSq, sumCu, sumQu, period, isPopulation);
@@ -507,7 +507,7 @@ public sealed class Kurtosis : AbstractBase
var vFisherNp1 = Vector256.Create(isPopulation ? 1.0 : fisherNp1); var vFisherNp1 = Vector256.Create(isPopulation ? 1.0 : fisherNp1);
var vFisherAdd = Vector256.Create(fisherAdd); var vFisherAdd = Vector256.Create(fisherAdd);
int simdEnd = period + ((len - period) / VectorWidth) * VectorWidth; int simdEnd = period + (((len - period) / VectorWidth) * VectorWidth);
int tickCount = period; int tickCount = period;
for (int i = period; i < simdEnd; i += VectorWidth) for (int i = period; i < simdEnd; i += VectorWidth)
+5 -5
View File
@@ -103,7 +103,7 @@ public sealed class Skew : AbstractBase
// Calculate 2nd moment (Variance) // Calculate 2nd moment (Variance)
// m2 = Sum((x-mean)^2) / n = (SumSq - Sum^2/n) / n // m2 = Sum((x-mean)^2) / n = (SumSq - Sum^2/n) / n
double m2Numerator = _sumSq - (_sum * _sum) / n; double m2Numerator = _sumSq - ((_sum * _sum) / n);
if (m2Numerator < Epsilon) if (m2Numerator < Epsilon)
{ {
m2Numerator = 0; m2Numerator = 0;
@@ -312,8 +312,8 @@ public sealed class Skew : AbstractBase
} }
sum = sum - oldVal + val; sum = sum - oldVal + val;
sumSq = sumSq - oldVal * oldVal + val * val; sumSq = sumSq - (oldVal * oldVal) + (val * val);
sumCu = sumCu - oldVal * oldVal * oldVal + val * val * val; sumCu = sumCu - (oldVal * oldVal * oldVal) + (val * val * val);
output[i] = CalculateSkewFromSums(sum, sumSq, sumCu, period, isPopulation); output[i] = CalculateSkewFromSums(sum, sumSq, sumCu, period, isPopulation);
@@ -349,7 +349,7 @@ public sealed class Skew : AbstractBase
{ {
double mean = sum / n; double mean = sum / n;
double m2Numerator = sumSq - (sum * sum) / n; double m2Numerator = sumSq - ((sum * sum) / n);
if (m2Numerator < Epsilon) if (m2Numerator < Epsilon)
{ {
return 0; return 0;
@@ -422,7 +422,7 @@ public sealed class Skew : 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);
int tickCount = period; int tickCount = period;
for (int i = period; i < simdEnd; i += VectorWidth) for (int i = period; i < simdEnd; i += VectorWidth)
+1 -1
View File
@@ -237,7 +237,7 @@ public sealed class Spearman : AbstractBase
} }
// Average rank: 1-based position = countSmaller + (countEqual - 1) / 2.0 + 1 // Average rank: 1-based position = countSmaller + (countEqual - 1) / 2.0 + 1
ranks[i] = countSmaller + (countEqual - 1) * 0.5 + 1.0; ranks[i] = countSmaller + ((countEqual - 1) * 0.5) + 1.0;
} }
} }
/// <summary>Not supported. This indicator requires two input spans.</summary> /// <summary>Not supported. This indicator requires two input spans.</summary>
+10 -10
View File
@@ -97,7 +97,7 @@ public sealed class Variance : AbstractBase
// Using Sum: // Using Sum:
// Var = (SumSq - (Sum*Sum)/N) / ... // Var = (SumSq - (Sum*Sum)/N) / ...
double numerator = _sumSq - (_buffer.Sum * _buffer.Sum) / n; double numerator = _sumSq - ((_buffer.Sum * _buffer.Sum) / n);
// Handle floating point noise // Handle floating point noise
if (numerator < 0) if (numerator < 0)
@@ -271,7 +271,7 @@ public sealed class Variance : AbstractBase
double n = i + 1; double n = i + 1;
if (n > 1) if (n > 1)
{ {
double numerator = sumSq - (sum * sum) / n; double numerator = sumSq - ((sum * sum) / n);
if (numerator < 0) if (numerator < 0)
{ {
numerator = 0; numerator = 0;
@@ -310,7 +310,7 @@ public sealed class Variance : AbstractBase
} }
double n = period; double n = period;
double numerator = sumSq - (sum * sum) / n; double numerator = sumSq - ((sum * sum) / n);
if (numerator < 0) if (numerator < 0)
{ {
numerator = 0; numerator = 0;
@@ -343,7 +343,7 @@ public sealed class Variance : AbstractBase
double n = i + 1; double n = i + 1;
if (n > 1) if (n > 1)
{ {
double num = sumSq - (sum * sum) / n; double num = sumSq - ((sum * sum) / n);
if (num < 0) if (num < 0)
{ {
num = 0; num = 0;
@@ -382,7 +382,7 @@ public sealed class Variance : AbstractBase
var vInvDenom = Vector512.Create(invDenom); var vInvDenom = Vector512.Create(invDenom);
var vZero = Vector512<double>.Zero; var vZero = Vector512<double>.Zero;
int simdEnd = period + ((len - period) / VectorWidth) * VectorWidth; int simdEnd = period + (((len - period) / VectorWidth) * VectorWidth);
int tickCount = period; int tickCount = period;
for (int i = period; i < simdEnd; i += VectorWidth) for (int i = period; i < simdEnd; i += VectorWidth)
@@ -465,7 +465,7 @@ public sealed class Variance : AbstractBase
sumSq = Math.FusedMultiplyAdd(-oldVal, oldVal, sumSq); sumSq = Math.FusedMultiplyAdd(-oldVal, oldVal, sumSq);
sumSq = Math.FusedMultiplyAdd(val, val, sumSq); sumSq = Math.FusedMultiplyAdd(val, val, sumSq);
double numerator = sumSq - sum * sum * invN; double numerator = sumSq - (sum * sum * invN);
if (numerator < 0) if (numerator < 0)
{ {
numerator = 0; numerator = 0;
@@ -498,7 +498,7 @@ public sealed class Variance : AbstractBase
var vInvDenom = Vector128.Create(invDenom); var vInvDenom = Vector128.Create(invDenom);
var vZero = Vector128<double>.Zero; var vZero = Vector128<double>.Zero;
int simdEnd = period + ((len - period) / VectorWidth) * VectorWidth; int simdEnd = period + (((len - period) / VectorWidth) * VectorWidth);
int tickCount = period; int tickCount = period;
for (int i = period; i < simdEnd; i += VectorWidth) for (int i = period; i < simdEnd; i += VectorWidth)
@@ -569,7 +569,7 @@ public sealed class Variance : AbstractBase
sumSq = Math.FusedMultiplyAdd(-oldVal, oldVal, sumSq); sumSq = Math.FusedMultiplyAdd(-oldVal, oldVal, sumSq);
sumSq = Math.FusedMultiplyAdd(val, val, sumSq); sumSq = Math.FusedMultiplyAdd(val, val, sumSq);
double numerator = sumSq - sum * sum * invN; double numerator = sumSq - (sum * sum * invN);
if (numerator < 0) if (numerator < 0)
{ {
numerator = 0; numerator = 0;
@@ -602,7 +602,7 @@ public sealed class Variance : AbstractBase
var vInvDenom = Vector256.Create(invDenom); var vInvDenom = Vector256.Create(invDenom);
var vZero = Vector256<double>.Zero; var vZero = Vector256<double>.Zero;
int simdEnd = period + ((len - period) / VectorWidth) * VectorWidth; int simdEnd = period + (((len - period) / VectorWidth) * VectorWidth);
int tickCount = period; int tickCount = period;
for (int i = period; i < simdEnd; i += VectorWidth) for (int i = period; i < simdEnd; i += VectorWidth)
@@ -693,7 +693,7 @@ public sealed class Variance : AbstractBase
sumSq = Math.FusedMultiplyAdd(-oldVal, oldVal, sumSq); sumSq = Math.FusedMultiplyAdd(-oldVal, oldVal, sumSq);
sumSq = Math.FusedMultiplyAdd(val, val, sumSq); sumSq = Math.FusedMultiplyAdd(val, val, sumSq);
double numerator = sumSq - sum * sum * invN; double numerator = sumSq - (sum * sum * invN);
if (numerator < 0) if (numerator < 0)
{ {
numerator = 0; numerator = 0;
+2 -2
View File
@@ -255,8 +255,8 @@ public sealed class Nlma : AbstractBase
else else
{ {
// Cycle zone: t continues from 1 upward // Cycle zone: t continues from 1 upward
double numer = (double)(i - phase + 1) * (2 * Cycle - 1); double numer = (double)(i - phase + 1) * ((2 * Cycle) - 1);
double denom = (double)(Cycle * period - 1); double denom = (double)((Cycle * period) - 1);
t = 1.0 + (denom > 0 ? numer / denom : 0.0); t = 1.0 + (denom > 0 ? numer / denom : 0.0);
} }
+7 -7
View File
@@ -127,9 +127,9 @@ public class RviTests
for (int i = 0; i < 50; i++) for (int i = 0; i < 50; i++)
{ {
var time = DateTime.UtcNow.AddSeconds(i); var time = DateTime.UtcNow.AddSeconds(i);
double close = 100.0 + Math.Sin(i * 0.5) * 3.0; // oscillating double close = 100.0 + (Math.Sin(i * 0.5) * 3.0); // oscillating
double high = close + 2.0 + Math.Sin(i * 0.3) * 1.5; // asymmetric highs double high = close + 2.0 + (Math.Sin(i * 0.3) * 1.5); // asymmetric highs
double low = close - 1.0 - Math.Cos(i * 0.7) * 0.8; // asymmetric lows double low = close - 1.0 - (Math.Cos(i * 0.7) * 0.8); // asymmetric lows
rviBar.Update(new TBar(time, close - 0.5, high, low, close, 1000)); rviBar.Update(new TBar(time, close - 0.5, high, low, close, 1000));
rviClose.Update(new TValue(time, close)); rviClose.Update(new TValue(time, close));
@@ -267,7 +267,7 @@ public class RviTests
// Build up some history // Build up some history
for (int i = 0; i < 20; i++) for (int i = 0; i < 20; i++)
{ {
rvi.Update(new TValue(time.AddSeconds(i), 100.0 + i * 0.1), isNew: true); rvi.Update(new TValue(time.AddSeconds(i), 100.0 + (i * 0.1)), isNew: true);
} }
_ = rvi.Last; // Capture state before update _ = rvi.Last; // Capture state before update
@@ -291,7 +291,7 @@ public class RviTests
// Build history // Build history
for (int i = 0; i < 30; i++) for (int i = 0; i < 30; i++)
{ {
rvi.Update(new TValue(time.AddSeconds(i), 100.0 + i * 0.5), isNew: true); rvi.Update(new TValue(time.AddSeconds(i), 100.0 + (i * 0.5)), isNew: true);
} }
// Start a new bar // Start a new bar
@@ -648,7 +648,7 @@ public class RviTests
var source = new TSeries(); var source = new TSeries();
for (int i = 0; i < 50; i++) for (int i = 0; i < 50; i++)
{ {
source.Add(new TValue(DateTime.UtcNow.AddSeconds(i), 100.0 + i * 0.5)); source.Add(new TValue(DateTime.UtcNow.AddSeconds(i), 100.0 + (i * 0.5)));
} }
var result = Rvi.Batch(source, stdevLength: 10, rmaLength: 14); var result = Rvi.Batch(source, stdevLength: 10, rmaLength: 14);
@@ -665,7 +665,7 @@ public class RviTests
for (int i = 0; i < 50; i++) for (int i = 0; i < 50; i++)
{ {
var time = DateTime.UtcNow.AddSeconds(i); var time = DateTime.UtcNow.AddSeconds(i);
double price = 100.0 + i * 0.5; double price = 100.0 + (i * 0.5);
source.Add(new TBar(time, price - 1, price + 1, price - 2, price, 1000)); source.Add(new TBar(time, price - 1, price + 1, price - 2, price, 1000));
} }
+4 -5
View File
@@ -167,7 +167,7 @@ public class RviValidationTests
for (int i = 0; i < 100; i++) for (int i = 0; i < 100; i++)
{ {
rvi.Update(new TValue(DateTime.UtcNow.AddMinutes(i), 100.0 + i * 0.5)); rvi.Update(new TValue(DateTime.UtcNow.AddMinutes(i), 100.0 + (i * 0.5)));
} }
Assert.True(rvi.Last.Value > 80.0, $"Strictly rising prices should produce high RVI, got {rvi.Last.Value}"); Assert.True(rvi.Last.Value > 80.0, $"Strictly rising prices should produce high RVI, got {rvi.Last.Value}");
@@ -183,7 +183,7 @@ public class RviValidationTests
for (int i = 0; i < 100; i++) for (int i = 0; i < 100; i++)
{ {
rvi.Update(new TValue(DateTime.UtcNow.AddMinutes(i), 100.0 - i * 0.5)); rvi.Update(new TValue(DateTime.UtcNow.AddMinutes(i), 100.0 - (i * 0.5)));
} }
Assert.True(rvi.Last.Value < 20.0, $"Strictly falling prices should produce low RVI, got {rvi.Last.Value}"); Assert.True(rvi.Last.Value < 20.0, $"Strictly falling prices should produce low RVI, got {rvi.Last.Value}");
@@ -486,7 +486,7 @@ public class RviValidationTests
// Multiple corrections on same price // Multiple corrections on same price
for (int j = 0; j < 5; j++) for (int j = 0; j < 5; j++)
{ {
var tempPrice = new TValue(prices[29].Time, prices[29].Value * (1.0 + j * 0.01)); var tempPrice = new TValue(prices[29].Time, prices[29].Value * (1.0 + (j * 0.01)));
rvi.Update(tempPrice, isNew: false); rvi.Update(tempPrice, isNew: false);
} }
@@ -575,7 +575,7 @@ public class RviValidationTests
// Symmetric oscillation // Symmetric oscillation
for (int i = 0; i < 200; i++) for (int i = 0; i < 200; i++)
{ {
double price = 100.0 + Math.Sin(i * 0.1) * 5; // Oscillating ±5 double price = 100.0 + (Math.Sin(i * 0.1) * 5); // Oscillating ±5
rvi.Update(new TValue(DateTime.UtcNow.AddMinutes(i), price)); rvi.Update(new TValue(DateTime.UtcNow.AddMinutes(i), price));
} }
@@ -621,5 +621,4 @@ public class RviValidationTests
double mean = values.Average(); double mean = values.Average();
return values.Average(v => Math.Pow(v - mean, 2)); return values.Average(v => Math.Pow(v - mean, 2));
} }
} }
-1
View File
@@ -269,7 +269,6 @@ public sealed class Vwma : ITValuePublisher
return Last; return Last;
} }
/// <summary> /// <summary>
/// Initializes the indicator state using the provided bar series history. /// Initializes the indicator state using the provided bar series history.
/// </summary> /// </summary>