[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.5 * period * (period - 1);
// 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 = period * sumX2 - _sumX * _sumX;
_denominator = (period * sumX2) - (_sumX * _sumX);
Reset();
}
@@ -218,8 +218,8 @@ public sealed class Regchannel : ITValuePublisher
if (count < _period)
{
sx = 0.5 * n * (n - 1);
double sx2 = (n - 1.0) * n * (2.0 * n - 1.0) / 6.0;
denom = n * sx2 - sx * sx;
double sx2 = (n - 1.0) * n * ((2.0 * n) - 1.0) / 6.0;
denom = (n * sx2) - (sx * sx);
}
double slope, intercept, regression;
@@ -232,8 +232,8 @@ public sealed class Regchannel : ITValuePublisher
}
else
{
slope = (n * sumXY - sx * sumY) / denom;
intercept = (sumY - slope * sx) / n;
slope = ((n * sumXY) - (sx * sumY)) / denom;
intercept = (sumY - (slope * sx)) / n;
// Regression value at current point (x = count - 1)
regression = Math.FusedMultiplyAdd(slope, count - 1, intercept);
}
@@ -362,8 +362,8 @@ public sealed class Regchannel : ITValuePublisher
// Precompute constants for full period
double sumXFull = 0.5 * period * (period - 1);
double sumX2Full = (period - 1.0) * period * (2.0 * period - 1.0) / 6.0;
double denomFull = period * sumX2Full - sumXFull * sumXFull;
double sumX2Full = (period - 1.0) * period * ((2.0 * period) - 1.0) / 6.0;
double denomFull = (period * sumX2Full) - (sumXFull * sumXFull);
// Circular buffer of NaN-sanitised values for O(1) sliding-window recurrences.
const int StackAllocThreshold = 256;
@@ -442,8 +442,8 @@ public sealed class Regchannel : ITValuePublisher
if (count < period)
{
sx = 0.5 * n * (n - 1);
double sx2 = (n - 1.0) * n * (2.0 * n - 1.0) / 6.0;
denom = n * sx2 - sx * sx;
double sx2 = (n - 1.0) * n * ((2.0 * n) - 1.0) / 6.0;
denom = (n * sx2) - (sx * sx);
}
else
{
@@ -461,14 +461,14 @@ public sealed class Regchannel : ITValuePublisher
}
else
{
slope = (n * sumXY - sx * sumY) / denom;
intercept = (sumY - slope * sx) / n;
slope = ((n * sumXY) - (sx * sumY)) / denom;
intercept = (sumY - (slope * sx)) / n;
regression = Math.FusedMultiplyAdd(slope, count - 1, intercept);
}
// Closed-form residual variance (normal-equation identity):
// 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 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.5 * period * (period - 1);
// 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 = period * sumX2 - _sumX * _sumX;
_denominator = (period * sumX2) - (_sumX * _sumX);
Reset();
}
@@ -218,8 +218,8 @@ public sealed class Sdchannel : ITValuePublisher
if (count < _period)
{
sx = 0.5 * n * (n - 1);
double sx2 = (n - 1.0) * n * (2.0 * n - 1.0) / 6.0;
denom = n * sx2 - sx * sx;
double sx2 = (n - 1.0) * n * ((2.0 * n) - 1.0) / 6.0;
denom = (n * sx2) - (sx * sx);
}
double slope, intercept, regression;
@@ -232,8 +232,8 @@ public sealed class Sdchannel : ITValuePublisher
}
else
{
slope = (n * sumXY - sx * sumY) / denom;
intercept = (sumY - slope * sx) / n;
slope = ((n * sumXY) - (sx * sumY)) / denom;
intercept = (sumY - (slope * sx)) / n;
// Regression value at current point (x = count - 1)
regression = Math.FusedMultiplyAdd(slope, count - 1, intercept);
}
@@ -362,8 +362,8 @@ public sealed class Sdchannel : ITValuePublisher
// Precompute constants for full period
double sumXFull = 0.5 * period * (period - 1);
double sumX2Full = (period - 1.0) * period * (2.0 * period - 1.0) / 6.0;
double denomFull = period * sumX2Full - sumXFull * sumXFull;
double sumX2Full = (period - 1.0) * period * ((2.0 * period) - 1.0) / 6.0;
double denomFull = (period * sumX2Full) - (sumXFull * sumXFull);
// Circular buffer of NaN-sanitised values for O(1) sliding-window recurrences.
const int StackAllocThreshold = 256;
@@ -441,8 +441,8 @@ public sealed class Sdchannel : ITValuePublisher
if (count < period)
{
sx = 0.5 * n * (n - 1);
double sx2 = (n - 1.0) * n * (2.0 * n - 1.0) / 6.0;
denom = n * sx2 - sx * sx;
double sx2 = (n - 1.0) * n * ((2.0 * n) - 1.0) / 6.0;
denom = (n * sx2) - (sx * sx);
}
else
{
@@ -460,8 +460,8 @@ public sealed class Sdchannel : ITValuePublisher
}
else
{
slope = (n * sumXY - sx * sumY) / denom;
intercept = (sumY - slope * sx) / n;
slope = ((n * sumXY) - (sx * sumY)) / denom;
intercept = (sumY - (slope * sx)) / n;
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++)
{
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);
}
@@ -103,7 +103,7 @@ public class CcorValidationTests
$"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
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,
$"Phasor magnitude should be significant for matched sine: {magnitude:F4}");
}
@@ -138,7 +138,7 @@ public class CcorValidationTests
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);
}
@@ -374,7 +374,7 @@ public class CcorValidationTests
for (int i = 0; i < 100; 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
+6 -6
View File
@@ -158,7 +158,7 @@ public sealed class Ccor : AbstractBase
// Phasor angle (degrees) with quadrant resolution
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)
{
@@ -342,7 +342,7 @@ public sealed class Ccor : AbstractBase
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 y = cosTab[k];
sx += x;
@@ -353,8 +353,8 @@ public sealed class Ccor : AbstractBase
}
double nd = n;
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;
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;
}
output[i] = realVal;
@@ -423,13 +423,13 @@ public sealed class Ccor : AbstractBase
}
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)
{
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);
}
}
+8 -8
View File
@@ -40,7 +40,7 @@ public class EacpValidationTests
// Generate sine wave with known period
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));
}
@@ -155,7 +155,7 @@ public class EacpValidationTests
// Generate sine wave
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));
eacpNormal.Update(new TValue(DateTime.UtcNow.AddSeconds(i), price));
}
@@ -293,7 +293,7 @@ public class EacpValidationTests
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));
}
@@ -308,7 +308,7 @@ public class EacpValidationTests
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));
}
@@ -360,7 +360,7 @@ public class EacpValidationTests
// Generate pure sine wave
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));
}
@@ -406,8 +406,8 @@ public class EacpValidationTests
// Generate two different sine waves
for (int i = 0; i < 500; i++)
{
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 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));
eacp1.Update(new TValue(DateTime.UtcNow.AddSeconds(i), price1));
eacp2.Update(new TValue(DateTime.UtcNow.AddSeconds(i), price2));
@@ -428,7 +428,7 @@ public class EacpValidationTests
for (int i = 0; i < 100; 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
+8 -8
View File
@@ -191,10 +191,10 @@ public sealed class Eacp : AbstractBase
// High-pass filter: removes DC and low-frequency trend
double hp2 = s.Hp1;
double hp1 = s.Hp0;
double coef = (1.0 - _alphaHP / 2.0);
double hp0 = coef * coef * (price0 - 2.0 * price1 + price2)
+ 2.0 * (1.0 - _alphaHP) * hp1
- (1.0 - _alphaHP) * (1.0 - _alphaHP) * hp2;
double coef = (1.0 - (_alphaHP / 2.0));
double hp0 = (coef * coef * (price0 - (2.0 * price1) + price2))
+ (2.0 * (1.0 - _alphaHP) * hp1)
- ((1.0 - _alphaHP) * (1.0 - _alphaHP) * hp2);
// Super-smoother filter: removes high-frequency noise
double filt2 = s.Filt1;
@@ -290,12 +290,12 @@ public sealed class Eacp : AbstractBase
double corrVal = 0;
if (valid > 1)
{
double denomX = valid * sxx - sx * sx;
double denomY = valid * syy - sy * sy;
double denomX = (valid * sxx) - (sx * sx);
double denomY = (valid * syy) - (sy * sy);
double denom = denomX * denomY;
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
double sq = cosAcc * cosAcc + sinAcc * sinAcc;
double sq = (cosAcc * cosAcc) + (sinAcc * sinAcc);
// Smooth the power spectrum (EMA-like smoothing)
// 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++)
{
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
+8 -8
View File
@@ -27,7 +27,7 @@ public class HtDcphaseTests
// Feed data through publisher
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);
@@ -131,7 +131,7 @@ public class HtDcphaseTests
// Prime with data
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);
@@ -153,7 +153,7 @@ public class HtDcphaseTests
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
@@ -187,7 +187,7 @@ public class HtDcphaseTests
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);
@@ -203,7 +203,7 @@ public class HtDcphaseTests
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));
@@ -236,14 +236,14 @@ public class HtDcphaseTests
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;
ht.Reset();
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);
}
@@ -352,7 +352,7 @@ public class HtDcphaseTests
var values = new double[80];
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));
@@ -103,7 +103,7 @@ public sealed class HtDcphaseValidationTests : IDisposable
for (int i = 0; i < 100; 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
+5 -5
View File
@@ -141,8 +141,8 @@ public sealed class HtDcphase : AbstractBase
double input1 = buffer[KEY_Q1];
DoHilbertTransform(buffer, KEY_JQ, input1, true, hilbertIdx, adjustedPrevPeriod);
q2 = 0.2 * (buffer[KEY_Q1] + buffer[KEY_JI]) + 0.8 * prevQ2;
i2 = 0.2 * (i1ForOddPrev3 - buffer[KEY_JQ]) + 0.8 * prevI2;
q2 = (0.2 * (buffer[KEY_Q1] + buffer[KEY_JI])) + (0.8 * prevQ2);
i2 = (0.2 * (i1ForOddPrev3 - buffer[KEY_JQ])) + (0.8 * prevI2);
i1ForEvenPrev3 = i1ForEvenPrev2;
i1ForEvenPrev2 = buffer[KEY_DETRENDER];
@@ -166,8 +166,8 @@ public sealed class HtDcphase : AbstractBase
hilbertIdx = 0;
}
q2 = 0.2 * (buffer[KEY_Q1] + buffer[KEY_JI]) + 0.8 * prevQ2;
i2 = 0.2 * (i1ForEvenPrev3 - buffer[KEY_JQ]) + 0.8 * prevI2;
q2 = (0.2 * (buffer[KEY_Q1] + buffer[KEY_JI])) + (0.8 * prevQ2);
i2 = (0.2 * (i1ForEvenPrev3 - buffer[KEY_JQ])) + (0.8 * prevI2);
i1ForOddPrev3 = i1ForOddPrev2;
i1ForOddPrev2 = buffer[KEY_DETRENDER];
@@ -296,7 +296,7 @@ public sealed class HtDcphase : AbstractBase
}
// 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 -= s.TrailingWMAValue;
@@ -133,7 +133,7 @@ public sealed class HtSineValidationTests : IDisposable
for (int i = 0; i < 100; 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
+7 -7
View File
@@ -161,8 +161,8 @@ public sealed class HtSine : AbstractBase
double input1 = buffer[KEY_Q1];
DoHilbertTransform(buffer, KEY_JQ, input1, true, hilbertIdx, adjustedPrevPeriod);
q2 = 0.2 * (buffer[KEY_Q1] + buffer[KEY_JI]) + 0.8 * prevQ2;
i2 = 0.2 * (i1ForOddPrev3 - buffer[KEY_JQ]) + 0.8 * prevI2;
q2 = (0.2 * (buffer[KEY_Q1] + buffer[KEY_JI])) + (0.8 * prevQ2);
i2 = (0.2 * (i1ForOddPrev3 - buffer[KEY_JQ])) + (0.8 * prevI2);
// The variable I1 is the detrender delayed for 3 price bars.
i1ForEvenPrev3 = i1ForEvenPrev2;
@@ -187,8 +187,8 @@ public sealed class HtSine : AbstractBase
hilbertIdx = 0;
}
q2 = 0.2 * (buffer[KEY_Q1] + buffer[KEY_JI]) + 0.8 * prevQ2;
i2 = 0.2 * (i1ForEvenPrev3 - buffer[KEY_JQ]) + 0.8 * prevI2;
q2 = (0.2 * (buffer[KEY_Q1] + buffer[KEY_JI])) + (0.8 * prevQ2);
i2 = (0.2 * (i1ForEvenPrev3 - buffer[KEY_JQ])) + (0.8 * prevI2);
// The variable i1 is the detrender delayed for 3 price bars.
i1ForOddPrev3 = i1ForOddPrev2;
@@ -199,8 +199,8 @@ public sealed class HtSine : AbstractBase
private static void CalcSmoothedPeriod(
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);
im = Math.FusedMultiplyAdd(0.2, i2 * prevQ2 - q2 * prevI2, 0.8 * im);
re = Math.FusedMultiplyAdd(0.2, (i2 * prevI2) + (q2 * prevQ2), 0.8 * re);
im = Math.FusedMultiplyAdd(0.2, (i2 * prevQ2) - (q2 * prevI2), 0.8 * im);
prevQ2 = q2;
prevI2 = i2;
@@ -373,7 +373,7 @@ public sealed class HtSine : AbstractBase
}
// 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 -= s.TrailingWMAValue;
+1 -1
View File
@@ -476,7 +476,7 @@ public sealed class Adx : ITValuePublisher
double dx = CalcDx(trSmooth, dmPlusSmooth, dmMinusSmooth);
dxSum += dx;
int adxStart = period * 2 - 1;
int adxStart = (period * 2) - 1;
for (int i = period + 1; i <= adxStart; i++)
{
@@ -55,7 +55,7 @@ public sealed class HtTrendmodeValidationTests : IDisposable
// Act - Process with sinusoidal data
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));
}
@@ -74,7 +74,7 @@ public sealed class HtTrendmodeValidationTests : IDisposable
// Act
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));
}
@@ -208,7 +208,7 @@ public sealed class HtTrendmodeValidationTests : IDisposable
for (int i = 0; i < 100; 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
@@ -124,8 +124,8 @@ public sealed class IchimokuValidationTests : IDisposable
// Add 4 bars with increasing trend
for (int i = 0; i < 4; i++)
{
double basePrice = 100 + i * 5;
ichimoku.Update(new TBar(baseTime + i * 60000, basePrice, basePrice + 5, basePrice - 5, basePrice, 1000));
double basePrice = 100 + (i * 5);
ichimoku.Update(new TBar(baseTime + (i * 60000), basePrice, basePrice + 5, basePrice - 5, basePrice, 1000));
}
// 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++)
{
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
@@ -244,7 +244,7 @@ public sealed class IchimokuValidationTests : IDisposable
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
@@ -254,7 +254,7 @@ public sealed class IchimokuValidationTests : IDisposable
Assert.Equal(125.0, ichimoku.SenkouB.Value, Precision);
// 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
// max(110,110,...) = 110, min(90,90,...) = 90
@@ -291,8 +291,8 @@ public sealed class IchimokuValidationTests : IDisposable
for (int i = 0; i < 15; i++)
{
double expectedClose = 100 + i * 1.5;
ichimoku.Update(new TBar(baseTime + i * 60000, expectedClose, expectedClose + 5, expectedClose - 5, expectedClose, 1000));
double expectedClose = 100 + (i * 1.5);
ichimoku.Update(new TBar(baseTime + (i * 60000), expectedClose, expectedClose + 5, expectedClose - 5, expectedClose, 1000));
Assert.Equal(expectedClose, ichimoku.Chikou.Value, Precision);
}
}
@@ -315,14 +315,14 @@ public sealed class IchimokuValidationTests : IDisposable
for (int i = 0; i < 10; i++)
{
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
for (int i = 10; i < 15; i++)
{
double price = 100 + (i - 10) * 2;
ichimoku.Update(new TBar(baseTime + i * 60000, price, price + 5, price - 5, price, 1000));
double price = 100 + ((i - 10) * 2);
ichimoku.Update(new TBar(baseTime + (i * 60000), price, price + 5, price - 5, price, 1000));
}
// 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++)
{
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
for (int i = 10; i < 15; i++)
{
double price = 100 - (i - 10) * 3;
ichimoku.Update(new TBar(baseTime + i * 60000, price, price + 5, price - 5, price, 1000));
double price = 100 - ((i - 10) * 3);
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)
@@ -374,9 +374,9 @@ public sealed class IchimokuValidationTests : IDisposable
for (int i = 0; i < 100; i++)
{
// 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;
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
@@ -406,8 +406,8 @@ public sealed class IchimokuValidationTests : IDisposable
// Process enough bars to warmup
for (int i = 0; i < 70; i++)
{
double price = 40000 + Math.Sin(i * 0.05) * 1000;
ichimoku.Update(new TBar(baseTime + i * 60000, price, price + 50, price - 50, price, 10));
double price = 40000 + (Math.Sin(i * 0.05) * 1000);
ichimoku.Update(new TBar(baseTime + (i * 60000), price, price + 50, price - 50, price, 10));
}
Assert.True(ichimoku.IsHot);
@@ -427,7 +427,7 @@ public sealed class IchimokuValidationTests : IDisposable
for (int i = 0; i < 60; 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
@@ -472,7 +472,7 @@ public sealed class IchimokuValidationTests : IDisposable
for (int i = 0; i < 60; 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);
@@ -500,7 +500,7 @@ public sealed class IchimokuValidationTests : IDisposable
// Phase 1: Ranging market - Tenkan ≈ Kijun
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)
@@ -510,8 +510,8 @@ public sealed class IchimokuValidationTests : IDisposable
// Phase 2: Sharp upward move - Tenkan should rise faster
for (int i = 5; i < 10; i++)
{
double price = 100 + (i - 5) * 5;
ichimoku.Update(new TBar(baseTime + i * 60000, price, price + 3, price - 3, price, 1000));
double price = 100 + ((i - 5) * 5);
ichimoku.Update(new TBar(baseTime + (i * 60000), price, price + 3, price - 3, price, 1000));
}
// Tenkan (short-term) should react faster to the uptrend
@@ -689,7 +689,7 @@ public sealed class IchimokuValidationTests : IDisposable
// Build state well past warmup
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);
}
@@ -22,7 +22,7 @@ public class TtmSqueezeValidationTests
// Very tight range bars - stddev will be near 0
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
@@ -45,7 +45,7 @@ public class TtmSqueezeValidationTests
double high = 105;
double low = 95;
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
@@ -113,7 +113,7 @@ public class TtmSqueezeValidationTests
double midline = 100; // (110 + 90) / 2
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
@@ -135,28 +135,28 @@ public class TtmSqueezeValidationTests
// Uptrend (rising above zero - cyan = 0)
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);
}
// Now weakening but still positive (falling above zero - blue = 1)
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);
}
// Downtrend (falling below zero - red = 2)
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);
}
// Recovering but still negative (rising below zero - yellow = 3)
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);
}
@@ -173,7 +173,7 @@ public class TtmSqueezeValidationTests
// Strong uptrend to ensure positive and rising momentum
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)
@@ -191,7 +191,7 @@ public class TtmSqueezeValidationTests
// Strong downtrend to ensure negative and falling momentum
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)
@@ -215,7 +215,7 @@ public class TtmSqueezeValidationTests
// Start with tight range to build squeeze
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)
{
squeezeFiredCount++;
@@ -226,7 +226,7 @@ public class TtmSqueezeValidationTests
for (int i = 5; i < 10; i++)
{
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)
{
squeezeFiredCount++;
@@ -250,10 +250,10 @@ public class TtmSqueezeValidationTests
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 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
@@ -301,7 +301,7 @@ public class TtmSqueezeValidationTests
// All bars identical
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));
@@ -318,7 +318,7 @@ public class TtmSqueezeValidationTests
for (int i = 0; i < 10; i++)
{
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));
@@ -334,7 +334,7 @@ public class TtmSqueezeValidationTests
// Build state well past warmup
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);
}
+12 -13
View File
@@ -210,8 +210,8 @@ public sealed class TtmSqueeze : ITValuePublisher
// Precompute linear regression constants
_sumX = 0.5 * momPeriod * (momPeriod - 1);
double sumX2 = (momPeriod - 1.0) * momPeriod * (2.0 * momPeriod - 1.0) / 6.0;
_denominator = momPeriod * sumX2 - _sumX * _sumX;
double sumX2 = (momPeriod - 1.0) * momPeriod * ((2.0 * momPeriod) - 1.0) / 6.0;
_denominator = (momPeriod * sumX2) - (_sumX * _sumX);
Reset();
}
@@ -328,11 +328,11 @@ public sealed class TtmSqueeze : ITValuePublisher
double bbCount = Math.Min(_barCount, _bbPeriod);
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 bbUpper = bbMean + _bbMult * bbStdDev;
double bbLower = bbMean - _bbMult * bbStdDev;
double bbUpper = bbMean + (_bbMult * bbStdDev);
double bbLower = bbMean - (_bbMult * bbStdDev);
// === Keltner Channel Calculation ===
// EMA with warmup compensation
@@ -354,8 +354,8 @@ public sealed class TtmSqueeze : ITValuePublisher
_atrE = Math.FusedMultiplyAdd(_atrE, 1 - atrAlpha, 0);
double atr = _atrE < 1.0 ? _atrRma / (1.0 - _atrE) : _atrRma;
double kcUpper = kcMid + _kcMult * atr;
double kcLower = kcMid - _kcMult * atr;
double kcUpper = kcMid + (_kcMult * atr);
double kcLower = kcMid - (_kcMult * atr);
// === Squeeze Detection ===
bool wasSqueezeOn = _prevSqueezeOn;
@@ -380,7 +380,7 @@ public sealed class TtmSqueeze : ITValuePublisher
{
double oldest = _momentumBuffer[0];
double prevSumY = _momentumSumY;
_momentumSumXY = _momentumSumXY + prevSumY - _momPeriod * oldest;
_momentumSumXY = _momentumSumXY + prevSumY - (_momPeriod * oldest);
_momentumSumY -= oldest;
}
_momentumBuffer.Add(deviation);
@@ -411,8 +411,8 @@ public sealed class TtmSqueeze : ITValuePublisher
if (momCount < _momPeriod)
{
sx = 0.5 * n * (n - 1);
double sx2 = (n - 1.0) * n * (2.0 * n - 1.0) / 6.0;
denom = n * sx2 - sx * sx;
double sx2 = (n - 1.0) * n * ((2.0 * n) - 1.0) / 6.0;
denom = (n * sx2) - (sx * sx);
}
else
{
@@ -426,8 +426,8 @@ public sealed class TtmSqueeze : ITValuePublisher
}
else
{
double slope = (n * _momentumSumXY - sx * _momentumSumY) / denom;
double intercept = (_momentumSumY - slope * sx) / n;
double slope = ((n * _momentumSumXY) - (sx * _momentumSumY)) / denom;
double intercept = (_momentumSumY - (slope * sx)) / n;
// Regression value at current point (x = count - 1)
momentum = Math.FusedMultiplyAdd(slope, n - 1, intercept);
}
@@ -561,5 +561,4 @@ public sealed class TtmSqueeze : ITValuePublisher
_lowBuffer.Restore();
_momentumBuffer.Restore();
}
}
+1 -1
View File
@@ -80,7 +80,7 @@ public sealed class MaeValidationTests : IDisposable
// Build state well past warmup
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
+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)
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
+1 -1
View File
@@ -336,7 +336,7 @@ public sealed class Mdae : AbstractBase
}
// 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])
{
(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
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
+1 -1
View File
@@ -82,7 +82,7 @@ public sealed class RmseValidationTests : IDisposable
// Build state well past warmup
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
@@ -203,7 +203,7 @@ public sealed class RsquaredValidationTests : IDisposable
// Build state well past warmup
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
+3 -3
View File
@@ -817,8 +817,8 @@ public sealed class CsvFeedTests : IDisposable
Assert.Equal(startTime, series[0].Time); // Jan 1
Assert.Equal(startTime + interval.Ticks, series[1].Time); // Jan 2
// Gap here (Jan 3 missing)
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 + (3 * interval.Ticks), series[2].Time); // Jan 4
Assert.Equal(startTime + (4 * interval.Ticks), series[3].Time); // Jan 5
}
[Fact]
@@ -941,7 +941,7 @@ public sealed class CsvFeedTests : IDisposable
// Jan 1 and Jan 3 present; Jan 2 absent → Fetch includes both with gap
Assert.Equal(2, series.Count);
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
+1 -1
View File
@@ -276,7 +276,7 @@ public class GBMTests
Assert.Equal(startTime, series[0].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]
+9 -9
View File
@@ -113,7 +113,7 @@ public sealed class GBM : IFeed
const double minutesPerYear = 252.0 * 6.5 * 60.0;
double dt = timeframe.TotalMinutes / minutesPerYear;
_drift = (mu - 0.5 * sigma * sigma) * dt;
_drift = (mu - (0.5 * sigma * sigma)) * dt;
_vol = sigma * Math.Sqrt(dt);
}
@@ -218,7 +218,7 @@ public sealed class GBM : IFeed
price = _lastPrice;
}
double volume = 1000 + NextDouble() * 1000;
double volume = 1000 + (NextDouble() * 1000);
double open = _lastPrice;
double close = price;
@@ -226,8 +226,8 @@ public sealed class GBM : IFeed
double rnd1 = NextDouble();
double rnd2 = NextDouble();
double high = Math.Max(open, close) * (1.0 + rnd1 * 0.01);
double low = Math.Min(open, close) * (1.0 - rnd2 * 0.01);
double high = Math.Max(open, close) * (1.0 + (rnd1 * 0.01));
double low = Math.Min(open, close) * (1.0 - (rnd2 * 0.01));
// Ensure valid OHLC constraints
high = Math.Max(high, Math.Max(open, close));
@@ -252,7 +252,7 @@ public sealed class GBM : IFeed
price = _lastPrice;
}
double additionalVolume = 1000 + NextDouble() * 1000;
double additionalVolume = 1000 + (NextDouble() * 1000);
var bar = _currentBar;
double newClose = price;
@@ -412,7 +412,7 @@ public sealed class GBM : IFeed
{
const double minutesPerYear = 252.0 * 6.5 * 60.0;
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);
long timeStep = interval.Ticks;
@@ -441,8 +441,8 @@ public sealed class GBM : IFeed
o[i] = open;
c[i] = close;
double high = Math.Max(open, close) * (1.0 + rnd1 * 0.01);
double low = Math.Min(open, close) * (1.0 - rnd2 * 0.01);
double high = Math.Max(open, close) * (1.0 + (rnd1 * 0.01));
double low = Math.Min(open, close) * (1.0 - (rnd2 * 0.01));
// Ensure valid OHLC constraints
high = Math.Max(high, Math.Max(open, close));
@@ -451,7 +451,7 @@ public sealed class GBM : IFeed
h[i] = high;
l[i] = low;
v[i] = 1000 + rnd3 * 1000;
v[i] = 1000 + (rnd3 * 1000);
currentPrice = price;
currentTime += timeStep;
+3 -3
View File
@@ -79,7 +79,7 @@ public sealed class BaxterKing : AbstractBase
_pLow = pLow;
_pHigh = pHigh;
_k = k;
_filterLen = 2 * k + 1;
_filterLen = (2 * k) + 1;
Name = $"BaxterKing({pLow},{pHigh},{k})";
WarmupPeriod = _filterLen;
@@ -218,7 +218,7 @@ public sealed class BaxterKing : AbstractBase
{
double a = 2.0 * Math.PI / pHigh; // low 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
// B_0 = (b - a) / pi
@@ -266,7 +266,7 @@ public sealed class BaxterKing : AbstractBase
public static void Batch(ReadOnlySpan<double> source, Span<double> output,
int pLow = 6, int pHigh = 32, int k = 12)
{
int filterLen = 2 * k + 1;
int filterLen = (2 * k) + 1;
double[] weights = new double[filterLen];
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
// Pre-compute inverse for efficiency
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 sigmaR = Math.Max(stdev * _sigmaRMult, 1e-10);
@@ -437,7 +437,7 @@ public sealed class Bilateral : AbstractBase
// Calculate StDev
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 sigmaR = Math.Max(stdev * sigmaRMult, 1e-10);
+5 -5
View File
@@ -267,7 +267,7 @@ public sealed class Loess : AbstractBase
dist = 0.9999;
}
double t = 1.0 - dist * dist * dist;
double t = 1.0 - (dist * dist * dist);
double w = t * t * t;
double xi = i - halfWindow;
@@ -277,7 +277,7 @@ public sealed class Loess : AbstractBase
x2Sum += xi * xi * w;
}
double delta = weightSum * x2Sum - xSum * xSum;
double delta = (weightSum * x2Sum) - (xSum * xSum);
if (Math.Abs(delta) < double.Epsilon)
{
delta = 1.0;
@@ -293,12 +293,12 @@ public sealed class Loess : AbstractBase
dist = 0.9999;
}
double t = 1.0 - dist * dist * dist;
double t = 1.0 - (dist * dist * dist);
double w = t * t * t;
double xi = i - halfWindow;
double term1 = x2Sum - xi * xSum;
double term2 = targetX * (xi * weightSum - xSum);
double term1 = x2Sum - (xi * xSum);
double term2 = targetX * ((xi * weightSum) - xSum);
double kValue = (w / delta) * (term1 + term2);
@@ -349,7 +349,7 @@ public sealed class AfirmaValidationTests : IDisposable
// Build state well past warmup
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
+11 -11
View File
@@ -316,7 +316,7 @@ public sealed class Afirma : AbstractBase
// Calculation in loop for clarity or formula:
double dn = (double)n;
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++)
{
@@ -328,11 +328,11 @@ public sealed class Afirma : AbstractBase
sxy += i * val;
}
double denom = dn * sx2 - sx * sx;
double denom = (dn * sx2) - (sx * sx);
if (Math.Abs(denom) > 1e-10)
{
double slope = (dn * sxy - sx * sy) / denom;
double intercept = (sy - slope * sx) / dn;
double slope = ((dn * sxy) - (sx * sy)) / denom;
double intercept = (sy - (slope * sx)) / dn;
double lsSum = 0.0;
double lsCount = 0.0;
@@ -345,7 +345,7 @@ public sealed class Afirma : AbstractBase
for (int i = 0; i < count; i++)
{
// 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;
lsCount++;
}
@@ -390,7 +390,7 @@ public sealed class Afirma : AbstractBase
for (int k = 0; k < _period; k++)
{
double kTwoPiDivP = k * twoPiDivP;
double coef = a0 + a1 * Math.Cos(kTwoPiDivP);
double coef = a0 + (a1 * Math.Cos(kTwoPiDivP));
if (Math.Abs(a2) > 1e-9)
{
coef += a2 * Math.Cos(2.0 * kTwoPiDivP);
@@ -475,7 +475,7 @@ public sealed class Afirma : AbstractBase
for (int k = 0; k < period; k++)
{
double kTwoPiDivP = k * twoPiDivP;
double coef = a0 + a1 * Math.Cos(kTwoPiDivP);
double coef = a0 + (a1 * Math.Cos(kTwoPiDivP));
if (Math.Abs(a2) > 1e-9)
{
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 dn = (double)n;
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++)
{
@@ -555,11 +555,11 @@ public sealed class Afirma : AbstractBase
sxy = Math.FusedMultiplyAdd(j, v, sxy);
}
double denom = dn * sx2 - sx * sx;
double denom = (dn * sx2) - (sx * sx);
if (Math.Abs(denom) > 1e-10)
{
double slope = (dn * sxy - sx * sy) / denom;
double intercept = (sy - slope * sx) / dn;
double slope = ((dn * sxy) - (sx * sy)) / denom;
double intercept = (sy - (slope * sx)) / dn;
double lsSum = 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
for (int i = 0; i < 50; i++)
{
double p = 100.0 + i * 0.5;
ind.Update(new TBar(t0 + i * TimeSpan.TicksPerSecond, p, p + 1, p - 1, p, 1000));
double p = 100.0 + (i * 0.5);
ind.Update(new TBar(t0 + (i * TimeSpan.TicksPerSecond), p, p + 1, p - 1, p, 1000));
}
// 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);
ind.Update(anchorBar, isNew: true);
double anchorResult = ind.Last.Value;
+1 -1
View File
@@ -248,7 +248,7 @@ public sealed class MacdValidationTests : IDisposable
// Build state well past warmup
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
-1
View File
@@ -129,7 +129,6 @@ public sealed class Macd : ITValuePublisher, IDisposable
return new TSeries(t, v);
}
/// <summary>
/// Initializes the indicator state using the provided series history.
/// </summary>
+3 -3
View File
@@ -248,8 +248,8 @@ public class PrsValidationTests
for (int i = 0; i < 10; i++)
{
double basePrice = 100 * (1 + i * 0.05); // 5% growth
double compPrice = 50 * (1 + i * 0.05); // 5% growth
double basePrice = 100 * (1 + (i * 0.05)); // 5% growth
double compPrice = 50 * (1 + (i * 0.05)); // 5% growth
var result = prs.Update(basePrice, compPrice, true);
results.Add(result.Value);
}
@@ -556,7 +556,7 @@ public class PrsValidationTests
// Build state well past warmup
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
-1
View File
@@ -352,5 +352,4 @@ public sealed class Prs : AbstractBase
TSeries results = Batch(baseSeries, compSeries, smoothPeriod);
return (results, indicator);
}
}
+20 -21
View File
@@ -78,7 +78,6 @@ public class RsxValidationTests
// Core RSX calculations (assuming price input as closing price):
double f8 = 100 * price;
if (!initialized)
{
lastF8 = f8;
@@ -89,32 +88,32 @@ public class RsxValidationTests
lastF8 = f8;
// First smoothing stage:
f28 = ialpha * f28 + alpha * v8;
f30 = alpha * f28 + ialpha * f30;
double vC = 1.5 * f28 - 0.5 * f30;
f28 = (ialpha * f28) + (alpha * v8);
f30 = (alpha * f28) + (ialpha * f30);
double vC = (1.5 * f28) - (0.5 * f30);
// Second smoothing stage:
f38 = ialpha * f38 + alpha * vC;
f40 = alpha * f38 + ialpha * f40;
double v10 = 1.5 * f38 - 0.5 * f40;
f38 = (ialpha * f38) + (alpha * vC);
f40 = (alpha * f38) + (ialpha * f40);
double v10 = (1.5 * f38) - (0.5 * f40);
// Third smoothing stage:
f48 = ialpha * f48 + alpha * v10;
f50 = alpha * f48 + ialpha * f50;
double v14 = 1.5 * f48 - 0.5 * f50;
f48 = (ialpha * f48) + (alpha * v10);
f50 = (alpha * f48) + (ialpha * f50);
double v14 = (1.5 * f48) - (0.5 * f50);
// Repeat stages for absolute value (momentum magnitude):
f58 = ialpha * f58 + alpha * Math.Abs(v8);
f60 = alpha * f58 + ialpha * f60;
double v18 = 1.5 * f58 - 0.5 * f60;
f68 = ialpha * f68 + alpha * v18;
f70 = alpha * f68 + ialpha * f70;
double v1C = 1.5 * f68 - 0.5 * f70;
f78 = ialpha * f78 + alpha * v1C;
f80 = alpha * f78 + ialpha * f80;
double v20 = 1.5 * f78 - 0.5 * f80;
f58 = (ialpha * f58) + (alpha * Math.Abs(v8));
f60 = (alpha * f58) + (ialpha * f60);
double v18 = (1.5 * f58) - (0.5 * f60);
f68 = (ialpha * f68) + (alpha * v18);
f70 = (alpha * f68) + (ialpha * f70);
double v1C = (1.5 * f68) - (0.5 * f70);
f78 = (ialpha * f78) + (alpha * v1C);
f80 = (alpha * f78) + (ialpha * f80);
double v20 = (1.5 * f78) - (0.5 * f80);
// Final RSX value:
double rsx;
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);
}
else
@@ -152,7 +151,7 @@ public class RsxValidationTests
// Build state well past warmup
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
+5 -5
View File
@@ -103,10 +103,10 @@ public class DecayIndicatorTests
{
indicator.HistoricalData.AddBar(
now.AddMinutes(i),
100 + i * 2,
105 + i * 2,
95 + i * 2,
102 + i * 2);
100 + (i * 2),
105 + (i * 2),
95 + (i * 2),
102 + (i * 2));
indicator.ProcessUpdate(new UpdateArgs(UpdateReason.HistoricalBar));
}
@@ -158,7 +158,7 @@ public class DecayIndicatorTests
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.ProcessUpdate(new UpdateArgs(UpdateReason.HistoricalBar));
}
+1 -1
View File
@@ -337,7 +337,7 @@ public class DecayTests
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);
+1 -1
View File
@@ -331,7 +331,7 @@ public class DwtValidationTests
// Build state well past warmup (WarmupPeriod = 2^4 = 16)
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
+2 -2
View File
@@ -440,9 +440,9 @@ public sealed class Dwt : AbstractBase
[MethodImpl(MethodImplOptions.AggressiveInlining)]
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;
if (lag > maxLag) { idx = ((h - 1 - maxLag) % c + c) % c; }
if (lag > maxLag) { idx = (((h - 1 - maxLag) % c) + c) % c; }
return b[idx];
}
@@ -103,10 +103,10 @@ public class EdecayIndicatorTests
{
indicator.HistoricalData.AddBar(
now.AddMinutes(i),
100 + i * 2,
105 + i * 2,
95 + i * 2,
102 + i * 2);
100 + (i * 2),
105 + (i * 2),
95 + (i * 2),
102 + (i * 2));
indicator.ProcessUpdate(new UpdateArgs(UpdateReason.HistoricalBar));
}
@@ -158,7 +158,7 @@ public class EdecayIndicatorTests
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.ProcessUpdate(new UpdateArgs(UpdateReason.HistoricalBar));
}
+1 -1
View File
@@ -337,7 +337,7 @@ public class EdecayTests
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);
+3 -3
View File
@@ -53,7 +53,7 @@ public class FftValidationTests
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);
}
@@ -74,7 +74,7 @@ public class FftValidationTests
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);
}
@@ -246,7 +246,7 @@ public class FftValidationTests
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);
+4 -4
View File
@@ -84,7 +84,7 @@ public sealed class Fft : AbstractBase
_hanning = new double[windowSize];
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
@@ -262,7 +262,7 @@ public sealed class Fft : AbstractBase
}
// 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 dominantPeriod = (double)_windowSize / (bestK + shift);
@@ -417,7 +417,7 @@ public sealed class Fft : AbstractBase
{
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);
}
@@ -476,7 +476,7 @@ public sealed class Fft : AbstractBase
workIm[bestK + 1] * workIm[bestK + 1])
: 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 dominant = (double)windowSize / (bestK + shift);
double clamped = Math.Clamp(dominant, minPeriod, maxPeriod);
+2 -2
View File
@@ -73,7 +73,7 @@ public sealed class Ifft : AbstractBase
_hanning = new double[windowSize];
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
@@ -330,7 +330,7 @@ public sealed class Ifft : AbstractBase
{
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);
}
+3 -3
View File
@@ -112,7 +112,7 @@ public sealed class QqeValidationTests
// Strongly trending up
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);
@@ -130,7 +130,7 @@ public sealed class QqeValidationTests
// Strongly trending down
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);
@@ -251,7 +251,7 @@ public sealed class QqeValidationTests
// Build state well past warmup (WarmupPeriod ≈ 37)
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
+3 -3
View File
@@ -101,11 +101,11 @@ public sealed class Qqe : AbstractBase
_sfAlpha = 2.0 / (smoothFactor + 1.0);
_sfBeta = 1.0 - _sfAlpha;
int darPeriod = 2 * smoothFactor - 1;
int darPeriod = (2 * smoothFactor) - 1;
_darAlpha = 2.0 / (darPeriod + 1.0);
_darBeta = 1.0 - _darAlpha;
WarmupPeriod = rsiPeriod + smoothFactor + darPeriod * 2;
WarmupPeriod = rsiPeriod + smoothFactor + (darPeriod * 2);
_s = new State(
Count: 0,
@@ -168,7 +168,7 @@ public sealed class Qqe : AbstractBase
double avgGain = s.RmaGain * cRma;
double avgLoss = s.RmaLoss * cRma;
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 ──
s.RawRsiMa = Math.FusedMultiplyAdd(s.RawRsiMa, _sfBeta, rsiVal * _sfAlpha);
@@ -225,12 +225,12 @@ public sealed class SqueezeValidationTests
// Build state well past warmup (WarmupPeriod = 20)
for (int i = 0; i < 50; i++)
{
double p = 100.0 + i * 0.5;
ind.Update(new TBar(t0 + i * TimeSpan.TicksPerSecond, p, p + 1, p - 1, p, 1000), isNew: true);
double p = 100.0 + (i * 0.5);
ind.Update(new TBar(t0 + (i * TimeSpan.TicksPerSecond), p, p + 1, p - 1, p, 1000), isNew: true);
}
// 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);
ind.Update(anchorBar, isNew: true);
double anchorMomentum = ind.Momentum;
+10 -10
View File
@@ -213,7 +213,7 @@ public sealed class Squeeze : ITValuePublisher
int n = Math.Max(1, s.SmaCount);
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 bbUpper = 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; }
}
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) =====
UpdateLrBuf(ref s, delta);
@@ -277,16 +277,16 @@ public sealed class Squeeze : ITValuePublisher
int pn = Math.Min(s.LrCount, _period);
int startIdx = s.LrCount - pn;
// 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(
pn, (double)startIdx * startIdx,
Math.FusedMultiplyAdd(
(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 slope = denomX == 0.0 ? 0.0
: 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);
_s = s;
@@ -554,7 +554,7 @@ public sealed class Squeeze : ITValuePublisher
int n = Math.Max(1, smaCount);
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 bbUpper = 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; }
}
double donMid = (highest + lowest) * 0.5;
double delta = c - (donMid + smaVal) * 0.5;
double delta = c - ((donMid + smaVal) * 0.5);
// Stage 5: LinReg incremental
double oldLr = lrBuf[lrHead];
@@ -620,16 +620,16 @@ public sealed class Squeeze : ITValuePublisher
int pn = Math.Min(lrCount, period);
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(
pn, (double)startI * startI,
Math.FusedMultiplyAdd(
(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 slope = denomX == 0.0 ? 0.0
: 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);
momOut[i] = momentum;
@@ -415,7 +415,7 @@ public sealed class StochrsiValidationTests : IDisposable
// Build state well past warmup (WarmupPeriod ≈ 31)
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
-1
View File
@@ -124,7 +124,6 @@ public sealed class Acf : AbstractBase
double oldVal = _buffer.Oldest;
_sum -= oldVal;
_sumSq = Math.FusedMultiplyAdd(-oldVal, oldVal, _sumSq);
}
// Add new value
@@ -507,5 +507,4 @@ public sealed class Cointegration : AbstractBase
return (result, indicator);
}
}
@@ -357,5 +357,4 @@ public sealed class Correlation : AbstractBase
return (result, indicator);
}
}
+8 -8
View File
@@ -117,7 +117,7 @@ public sealed class Covariance : AbstractBase
if (n >= 2)
{
// 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);
cov = numerator / denominator;
}
@@ -278,7 +278,7 @@ public sealed class Covariance : AbstractBase
double n = i + 1;
if (n >= 2)
{
double numerator = sumXY - (sumX * sumY) / n;
double numerator = sumXY - ((sumX * sumY) / n);
double denominator = isPopulation ? n : (n - 1);
output[i] = numerator / denominator;
}
@@ -309,7 +309,7 @@ public sealed class Covariance : AbstractBase
sumX = sumX - oldX + x;
sumY = sumY - oldY + y;
sumXY = sumXY - oldX * oldY + x * y;
sumXY = sumXY - (oldX * oldY) + (x * y);
bufferX[bufferIndex] = x;
bufferY[bufferIndex] = y;
@@ -320,7 +320,7 @@ public sealed class Covariance : AbstractBase
}
double n = period;
double numerator = sumXY - (sumX * sumY) / n;
double numerator = sumXY - ((sumX * sumY) / n);
double denominator = isPopulation ? n : (n - 1);
output[i] = numerator / denominator;
@@ -364,7 +364,7 @@ public sealed class Covariance : AbstractBase
double n = i + 1;
if (n >= 2)
{
double num = sumXY - (sumX * sumY) / n;
double num = sumXY - ((sumX * sumY) / n);
double den = isPopulation ? n : (n - 1);
Unsafe.Add(ref outRef, i) = num / den;
}
@@ -400,7 +400,7 @@ public sealed class Covariance : AbstractBase
var vInvDenom = Vector256.Create(invDenom);
var vZero = Vector256<double>.Zero;
int simdEnd = period + ((len - period) / VectorWidth) * VectorWidth;
int simdEnd = period + (((len - period) / VectorWidth) * VectorWidth);
int tickCount = period;
for (int i = period; i < simdEnd; i += VectorWidth)
@@ -513,9 +513,9 @@ public sealed class Covariance : AbstractBase
sumX = sumX - oldX + x;
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;
}
}
+15 -15
View File
@@ -150,7 +150,7 @@ public sealed class Kurtosis : AbstractBase
// Second central moment (variance): m₂ = Σ(x-μ)²/n
// = (SumSq - Sum²/n) / n
double m2Numerator = _sumSq - (_sum * _sum) / n;
double m2Numerator = _sumSq - ((_sum * _sum) / n);
if (m2Numerator < Epsilon)
{
m2Numerator = 0;
@@ -165,10 +165,10 @@ public sealed class Kurtosis : AbstractBase
// 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⁴
double meanSq = mean * mean;
double m4 = _sumQu / n
- 4.0 * mean * _sumCu / n
+ 6.0 * meanSq * _sumSq / n
- 3.0 * meanSq * meanSq;
double m4 = (_sumQu / n)
- (4.0 * mean * _sumCu / n)
+ (6.0 * meanSq * _sumSq / n)
- (3.0 * meanSq * meanSq);
// Population excess kurtosis: g₂ = m₄/m₂² - 3
double g2 = (m4 / (m2 * m2)) - 3.0;
@@ -184,7 +184,7 @@ public sealed class Kurtosis : AbstractBase
double denom = (n - 2.0) * (n - 3.0);
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 m2Numerator = sumSq - (sum * sum) / n;
double m2Numerator = sumSq - ((sum * sum) / n);
if (m2Numerator < Epsilon)
{
return 0;
@@ -342,10 +342,10 @@ public sealed class Kurtosis : AbstractBase
// Fourth central moment via raw moments
double meanSq = mean * mean;
double m4 = sumQu / n
- 4.0 * mean * sumCu / n
+ 6.0 * meanSq * sumSq / n
- 3.0 * meanSq * meanSq;
double m4 = (sumQu / n)
- (4.0 * mean * sumCu / n)
+ (6.0 * meanSq * sumSq / n)
- (3.0 * meanSq * meanSq);
double g2 = (m4 / (m2 * m2)) - 3.0;
@@ -361,7 +361,7 @@ public sealed class Kurtosis : AbstractBase
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)]
@@ -415,8 +415,8 @@ public sealed class Kurtosis : AbstractBase
double oldSq = oldVal * oldVal;
sum = sum - oldVal + val;
sumSq = sumSq - oldSq + valSq;
sumCu = sumCu - oldSq * oldVal + valSq * val;
sumQu = sumQu - oldSq * oldSq + valSq * valSq;
sumCu = sumCu - (oldSq * oldVal) + (valSq * val);
sumQu = sumQu - (oldSq * oldSq) + (valSq * valSq);
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 vFisherAdd = Vector256.Create(fisherAdd);
int simdEnd = period + ((len - period) / VectorWidth) * VectorWidth;
int simdEnd = period + (((len - period) / VectorWidth) * VectorWidth);
int tickCount = period;
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)
// 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)
{
m2Numerator = 0;
@@ -312,8 +312,8 @@ public sealed class Skew : AbstractBase
}
sum = sum - oldVal + val;
sumSq = sumSq - oldVal * oldVal + val * val;
sumCu = sumCu - oldVal * oldVal * oldVal + val * val * val;
sumSq = sumSq - (oldVal * oldVal) + (val * val);
sumCu = sumCu - (oldVal * oldVal * oldVal) + (val * val * val);
output[i] = CalculateSkewFromSums(sum, sumSq, sumCu, period, isPopulation);
@@ -349,7 +349,7 @@ public sealed class Skew : AbstractBase
{
double mean = sum / n;
double m2Numerator = sumSq - (sum * sum) / n;
double m2Numerator = sumSq - ((sum * sum) / n);
if (m2Numerator < Epsilon)
{
return 0;
@@ -422,7 +422,7 @@ public sealed class Skew : AbstractBase
var vEpsilon = Vector256.Create(Epsilon);
var vZero = Vector256<double>.Zero;
int simdEnd = period + ((len - period) / VectorWidth) * VectorWidth;
int simdEnd = period + (((len - period) / VectorWidth) * VectorWidth);
int tickCount = period;
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
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>
+10 -10
View File
@@ -97,7 +97,7 @@ public sealed class Variance : AbstractBase
// Using Sum:
// 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
if (numerator < 0)
@@ -271,7 +271,7 @@ public sealed class Variance : AbstractBase
double n = i + 1;
if (n > 1)
{
double numerator = sumSq - (sum * sum) / n;
double numerator = sumSq - ((sum * sum) / n);
if (numerator < 0)
{
numerator = 0;
@@ -310,7 +310,7 @@ public sealed class Variance : AbstractBase
}
double n = period;
double numerator = sumSq - (sum * sum) / n;
double numerator = sumSq - ((sum * sum) / n);
if (numerator < 0)
{
numerator = 0;
@@ -343,7 +343,7 @@ public sealed class Variance : AbstractBase
double n = i + 1;
if (n > 1)
{
double num = sumSq - (sum * sum) / n;
double num = sumSq - ((sum * sum) / n);
if (num < 0)
{
num = 0;
@@ -382,7 +382,7 @@ public sealed class Variance : AbstractBase
var vInvDenom = Vector512.Create(invDenom);
var vZero = Vector512<double>.Zero;
int simdEnd = period + ((len - period) / VectorWidth) * VectorWidth;
int simdEnd = period + (((len - period) / VectorWidth) * VectorWidth);
int tickCount = period;
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(val, val, sumSq);
double numerator = sumSq - sum * sum * invN;
double numerator = sumSq - (sum * sum * invN);
if (numerator < 0)
{
numerator = 0;
@@ -498,7 +498,7 @@ public sealed class Variance : AbstractBase
var vInvDenom = Vector128.Create(invDenom);
var vZero = Vector128<double>.Zero;
int simdEnd = period + ((len - period) / VectorWidth) * VectorWidth;
int simdEnd = period + (((len - period) / VectorWidth) * VectorWidth);
int tickCount = period;
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(val, val, sumSq);
double numerator = sumSq - sum * sum * invN;
double numerator = sumSq - (sum * sum * invN);
if (numerator < 0)
{
numerator = 0;
@@ -602,7 +602,7 @@ public sealed class Variance : AbstractBase
var vInvDenom = Vector256.Create(invDenom);
var vZero = Vector256<double>.Zero;
int simdEnd = period + ((len - period) / VectorWidth) * VectorWidth;
int simdEnd = period + (((len - period) / VectorWidth) * VectorWidth);
int tickCount = period;
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(val, val, sumSq);
double numerator = sumSq - sum * sum * invN;
double numerator = sumSq - (sum * sum * invN);
if (numerator < 0)
{
numerator = 0;
+2 -2
View File
@@ -255,8 +255,8 @@ public sealed class Nlma : AbstractBase
else
{
// Cycle zone: t continues from 1 upward
double numer = (double)(i - phase + 1) * (2 * Cycle - 1);
double denom = (double)(Cycle * period - 1);
double numer = (double)(i - phase + 1) * ((2 * Cycle) - 1);
double denom = (double)((Cycle * period) - 1);
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++)
{
var time = DateTime.UtcNow.AddSeconds(i);
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 low = close - 1.0 - Math.Cos(i * 0.7) * 0.8; // asymmetric lows
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 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));
rviClose.Update(new TValue(time, close));
@@ -267,7 +267,7 @@ public class RviTests
// Build up some history
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
@@ -291,7 +291,7 @@ public class RviTests
// Build history
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
@@ -648,7 +648,7 @@ public class RviTests
var source = new TSeries();
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);
@@ -665,7 +665,7 @@ public class RviTests
for (int i = 0; i < 50; 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));
}
+4 -5
View File
@@ -167,7 +167,7 @@ public class RviValidationTests
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}");
@@ -183,7 +183,7 @@ public class RviValidationTests
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}");
@@ -486,7 +486,7 @@ public class RviValidationTests
// Multiple corrections on same price
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);
}
@@ -575,7 +575,7 @@ public class RviValidationTests
// Symmetric oscillation
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));
}
@@ -621,5 +621,4 @@ public class RviValidationTests
double mean = values.Average();
return values.Average(v => Math.Pow(v - mean, 2));
}
}
-1
View File
@@ -269,7 +269,6 @@ public sealed class Vwma : ITValuePublisher
return Last;
}
/// <summary>
/// Initializes the indicator state using the provided bar series history.
/// </summary>