Merge main into dev

This commit is contained in:
Miha Kralj
2026-09-21 11:17:12 +02:00
560 changed files with 1735 additions and 1825 deletions
+1 -1
View File
@@ -608,7 +608,7 @@ public class AberrTests
var series = new TSeries();
for (int i = 0; i < 10; i++)
{
series.Add(DateTime.UtcNow, 100 + i * 10); // 100, 110, 120, ...
series.Add(DateTime.UtcNow, 100 + (i * 10)); // 100, 110, 120, ...
}
// Multiplier 1.0
+18 -18
View File
@@ -179,8 +179,8 @@ public class AccBandsTests
// SMA(3) of adjLow: (54 + 58.80952 + 63.63636) / 3 ≈ 58.81529
// SMA(3) of Close: (100+105+110)/3 = 105
double expectedUpper = (154.0 + 115.0 * (1.0 + 4.0 * 20.0 / 210.0) + 120.0 * (1.0 + 4.0 * 20.0 / 220.0)) / 3.0;
double expectedLower = (54.0 + 95.0 * (1.0 - 4.0 * 20.0 / 210.0) + 100.0 * (1.0 - 4.0 * 20.0 / 220.0)) / 3.0;
double expectedUpper = (154.0 + (115.0 * (1.0 + (4.0 * 20.0 / 210.0))) + (120.0 * (1.0 + (4.0 * 20.0 / 220.0)))) / 3.0;
double expectedLower = (54.0 + (95.0 * (1.0 - (4.0 * 20.0 / 210.0))) + (100.0 * (1.0 - (4.0 * 20.0 / 220.0)))) / 3.0;
Assert.Equal(105.0, accBands.Last.Value, 1e-10);
Assert.Equal(expectedUpper, accBands.Upper.Value, 1e-10);
@@ -399,8 +399,8 @@ public class AccBandsTests
// adjLow = 100*(1-4*0.090909) = 100*0.636364 ≈ 63.63636
accBands.Update(new TBar(DateTime.UtcNow, 110, 120, 100, 110, 1000));
Assert.Equal(110.0, accBands.Last.Value, 1e-10);
Assert.Equal(120.0 * (1.0 + 4.0 * 20.0 / 220.0), accBands.Upper.Value, 1e-10);
Assert.Equal(100.0 * (1.0 - 4.0 * 20.0 / 220.0), accBands.Lower.Value, 1e-10);
Assert.Equal(120.0 * (1.0 + (4.0 * 20.0 / 220.0)), accBands.Upper.Value, 1e-10);
Assert.Equal(100.0 * (1.0 - (4.0 * 20.0 / 220.0)), accBands.Lower.Value, 1e-10);
}
// ============== Span API Tests ==============
@@ -496,12 +496,12 @@ public class AccBandsTests
// Bar 2: H=120, L=100 => w=20/220, adjH=120*(1+4*20/220), adjL=100*(1-4*20/220)
// SMA(3) of Close: (100+105+110)/3 = 105
double adjH0 = 110.0 * (1.0 + 4.0 * 20.0 / 200.0);
double adjH1 = 115.0 * (1.0 + 4.0 * 20.0 / 210.0);
double adjH2 = 120.0 * (1.0 + 4.0 * 20.0 / 220.0);
double adjL0 = 90.0 * (1.0 - 4.0 * 20.0 / 200.0);
double adjL1 = 95.0 * (1.0 - 4.0 * 20.0 / 210.0);
double adjL2 = 100.0 * (1.0 - 4.0 * 20.0 / 220.0);
double adjH0 = 110.0 * (1.0 + (4.0 * 20.0 / 200.0));
double adjH1 = 115.0 * (1.0 + (4.0 * 20.0 / 210.0));
double adjH2 = 120.0 * (1.0 + (4.0 * 20.0 / 220.0));
double adjL0 = 90.0 * (1.0 - (4.0 * 20.0 / 200.0));
double adjL1 = 95.0 * (1.0 - (4.0 * 20.0 / 210.0));
double adjL2 = 100.0 * (1.0 - (4.0 * 20.0 / 220.0));
Assert.Equal(105.0, middle[2], 1e-10);
Assert.Equal((adjH0 + adjH1 + adjH2) / 3.0, upper[2], 1e-10);
@@ -657,12 +657,12 @@ public class AccBandsTests
// Bar 2: H=120,L=100,C=110 -> w=20/220, adjH=120*(1+80/220), adjL=100*(1-80/220)
// Bar 3: H=125,L=105,C=115 -> w=20/230, adjH=125*(1+80/230), adjL=105*(1-80/230)
// Bar 4: H=130,L=110,C=120 -> w=20/240, adjH=130*(1+80/240), adjL=110*(1-80/240)
double adjH2 = 120.0 * (1.0 + 4.0 * 20.0 / 220.0);
double adjL2 = 100.0 * (1.0 - 4.0 * 20.0 / 220.0);
double adjH3 = 125.0 * (1.0 + 4.0 * 20.0 / 230.0);
double adjL3 = 105.0 * (1.0 - 4.0 * 20.0 / 230.0);
double adjH4 = 130.0 * (1.0 + 4.0 * 20.0 / 240.0);
double adjL4 = 110.0 * (1.0 - 4.0 * 20.0 / 240.0);
double adjH2 = 120.0 * (1.0 + (4.0 * 20.0 / 220.0));
double adjL2 = 100.0 * (1.0 - (4.0 * 20.0 / 220.0));
double adjH3 = 125.0 * (1.0 + (4.0 * 20.0 / 230.0));
double adjL3 = 105.0 * (1.0 - (4.0 * 20.0 / 230.0));
double adjH4 = 130.0 * (1.0 + (4.0 * 20.0 / 240.0));
double adjL4 = 110.0 * (1.0 - (4.0 * 20.0 / 240.0));
Assert.Equal(115.0, accBands.Last.Value, 1e-10);
Assert.Equal((adjH2 + adjH3 + adjH4) / 3.0, accBands.Upper.Value, 1e-10);
@@ -672,8 +672,8 @@ public class AccBandsTests
accBands.Update(new TBar(DateTime.UtcNow, 125, 135, 115, 125, 1000));
// New window: bars [3,4,5]
// Bar 5: H=135,L=115,C=125 -> w=20/250, adjH=135*(1+80/250), adjL=115*(1-80/250)
double adjH5 = 135.0 * (1.0 + 4.0 * 20.0 / 250.0);
double adjL5 = 115.0 * (1.0 - 4.0 * 20.0 / 250.0);
double adjH5 = 135.0 * (1.0 + (4.0 * 20.0 / 250.0));
double adjL5 = 115.0 * (1.0 - (4.0 * 20.0 / 250.0));
Assert.Equal(120.0, accBands.Last.Value, 1e-10);
Assert.Equal((adjH3 + adjH4 + adjH5) / 3.0, accBands.Upper.Value, 1e-10);
@@ -63,12 +63,12 @@ public sealed class AccBandsValidationTests : IDisposable
var accBands = new AccBands(3, 4.0);
var (middle, upper, lower) = accBands.Update(series);
double adjH0 = 12.0 * (1.0 + 4.0 * 4.0 / 20.0);
double adjH1 = 14.0 * (1.0 + 4.0 * 4.0 / 24.0);
double adjH2 = 16.0 * (1.0 + 4.0 * 4.0 / 28.0);
double adjL0 = 8.0 * (1.0 - 4.0 * 4.0 / 20.0);
double adjL1 = 10.0 * (1.0 - 4.0 * 4.0 / 24.0);
double adjL2 = 12.0 * (1.0 - 4.0 * 4.0 / 28.0);
double adjH0 = 12.0 * (1.0 + (4.0 * 4.0 / 20.0));
double adjH1 = 14.0 * (1.0 + (4.0 * 4.0 / 24.0));
double adjH2 = 16.0 * (1.0 + (4.0 * 4.0 / 28.0));
double adjL0 = 8.0 * (1.0 - (4.0 * 4.0 / 20.0));
double adjL1 = 10.0 * (1.0 - (4.0 * 4.0 / 24.0));
double adjL2 = 12.0 * (1.0 - (4.0 * 4.0 / 28.0));
Assert.Equal(12.0, middle.Last.Value, 1e-10);
Assert.Equal((adjH0 + adjH1 + adjH2) / 3.0, upper.Last.Value, 1e-10);
@@ -106,8 +106,8 @@ public sealed class AccBandsValidationTests : IDisposable
double l = c - 5;
double denom = h + l;
double w = (h - l) / denom;
sumAdjH += h * (1.0 + 4.0 * w);
sumAdjL += l * (1.0 - 4.0 * w);
sumAdjH += h * (1.0 + (4.0 * w));
sumAdjL += l * (1.0 - (4.0 * w));
}
Assert.Equal(sumAdjH / 5.0, upper.Last.Value, 1e-10);
Assert.Equal(sumAdjL / 5.0, lower.Last.Value, 1e-10);
@@ -39,7 +39,6 @@ public sealed class ApchannelValidationTests : IDisposable
/// we validate against mathematical correctness by comparing the span and streaming results
/// with manually calculated EMA values for high and low prices.
/// </summary>
[Fact]
public void Validate_AllModes_ProduceSameResult()
{
+1 -1
View File
@@ -168,7 +168,7 @@ public class ApzTests
// Generate 9 corrections with isNew=false (different values)
for (int i = 0; i < 9; i++)
{
var correctionBar = new TBar(tenthBar.Time, tenthBar.Open + i, tenthBar.High + i * 2, tenthBar.Low - i, tenthBar.Close + i, tenthBar.Volume);
var correctionBar = new TBar(tenthBar.Time, tenthBar.Open + i, tenthBar.High + (i * 2), tenthBar.Low - i, tenthBar.Close + i, tenthBar.Volume);
apz.Update(correctionBar, isNew: false);
}
@@ -383,7 +383,7 @@ public sealed class ApzValidationTests : IDisposable
}
else
{
ema = alpha * bar.Close + (1 - alpha) * ema;
ema = (alpha * bar.Close) + ((1 - alpha) * ema);
}
emaResults.Add(ema);
@@ -332,8 +332,8 @@ public sealed class AtrBandsValidationTests : IDisposable
double expectedMid = smaResult[i].Sma!.Value;
double expectedAtr = atrResult[i].Atr!.Value;
double expectedUp = expectedMid + multiplier * expectedAtr;
double expectedLo = expectedMid - multiplier * expectedAtr;
double expectedUp = expectedMid + (multiplier * expectedAtr);
double expectedLo = expectedMid - (multiplier * expectedAtr);
Assert.True(
Math.Abs(qMid[i].Value - expectedMid) <= ValidationHelper.SkenderTolerance,
+1 -2
View File
@@ -223,7 +223,7 @@ public sealed class Bbands : AbstractBase
for (int i = 0; i < source.Length; i++)
{
Update(new TValue(startTime + i * step.Value, source[i]), isNew: true);
Update(new TValue(startTime + (i * step.Value), source[i]), isNew: true);
}
}
@@ -367,5 +367,4 @@ public sealed class Bbands : AbstractBase
TSeries results = indicator.Update(source);
return (results, indicator);
}
}
+1 -1
View File
@@ -411,7 +411,7 @@ public class BbandsTests
DateTime startTime = DateTime.UtcNow;
for (int i = 0; i < data.Length; i++)
{
streamBbands.Update(new TValue(startTime + i * TimeSpan.FromSeconds(1), data[i]), isNew: true);
streamBbands.Update(new TValue(startTime + (i * TimeSpan.FromSeconds(1)), data[i]), isNew: true);
}
Assert.Equal(streamBbands.Middle.Value, primedBbands.Middle.Value, precision: 10);
+6 -6
View File
@@ -111,7 +111,7 @@ public sealed class Hwc : AbstractBase
_decayGamma = 1.0 - gamma;
_multiplier = multiplier;
int effectivePeriod = Math.Max((int)(2.0 / alpha - 1.0), 1);
int effectivePeriod = Math.Max((int)((2.0 / alpha) - 1.0), 1);
WarmupPeriod = effectivePeriod;
Name = $"Hwc({alpha:F3},{beta:F3},{gamma:F3},{multiplier:F1})";
_state = new State(double.NaN, 0, 0, 0, double.NaN, false);
@@ -179,7 +179,7 @@ public sealed class Hwc : AbstractBase
double prevA = _state.A;
// HWMA: F = α×src + (1−α)×(prevF + prevV + 0.5×prevA)
double forecast = prevF + prevV + 0.5 * prevA;
double forecast = prevF + prevV + (0.5 * prevA);
double newF = Math.FusedMultiplyAdd(forecast, _decayAlpha, _alpha * val);
// V = β×(F − prevF) + (1−β)×(prevV + prevA)
@@ -188,7 +188,7 @@ public sealed class Hwc : AbstractBase
// A = γ×(V − prevV) + (1−γ)×prevA
double newA = Math.FusedMultiplyAdd(prevA, _decayGamma, _gamma * (newV - prevV));
result = newF + newV + 0.5 * newA;
result = newF + newV + (0.5 * newA);
// Adaptive volatility filter: filt = α×(src − forecast)² + (1−α)×prevFilt
double err = val - forecast;
@@ -240,7 +240,7 @@ public sealed class Hwc : AbstractBase
for (int i = 0; i < source.Length; i++)
{
Update(new TValue(startTime + i * step.Value, source[i]), isNew: true);
Update(new TValue(startTime + (i * step.Value), source[i]), isNew: true);
}
}
@@ -299,11 +299,11 @@ public sealed class Hwc : AbstractBase
}
else
{
double forecast = f + v + 0.5 * a;
double forecast = f + v + (0.5 * a);
double newF = Math.FusedMultiplyAdd(forecast, dA, alpha * val);
double newV = Math.FusedMultiplyAdd(v + a, dB, beta * (newF - f));
double newA = Math.FusedMultiplyAdd(a, dG, gamma * (newV - v));
result = newF + newV + 0.5 * newA;
result = newF + newV + (0.5 * newA);
double err = val - forecast;
filt = Math.FusedMultiplyAdd(err * err, alpha, filt * dA);
+1 -1
View File
@@ -174,7 +174,7 @@ public sealed class HwcTests
// Low volatility: small oscillation
indCalm.Update(new TValue(DateTime.UtcNow.AddMinutes(i), 100.0 + Math.Sin(i * 0.1)));
// High volatility: large oscillation
indVolatile.Update(new TValue(DateTime.UtcNow.AddMinutes(i), 100.0 + Math.Sin(i * 0.1) * 20));
indVolatile.Update(new TValue(DateTime.UtcNow.AddMinutes(i), 100.0 + (Math.Sin(i * 0.1) * 20)));
}
double widthCalm = indCalm.Upper.Value - indCalm.Lower.Value;
+1 -1
View File
@@ -23,7 +23,7 @@ public sealed class JbandsIndicator : Indicator, IWatchlistIndicator
private Jbands? _indicator;
public int MinHistoryDepths => (int)Math.Ceiling(20.0 + 80.0 * Math.Pow(Period, 0.36));
public int MinHistoryDepths => (int)Math.Ceiling(20.0 + (80.0 * Math.Pow(Period, 0.36)));
public override string ShortName => $"Jbands({Period},{Phase})";
public JbandsIndicator()
+1 -1
View File
@@ -99,7 +99,7 @@ public sealed class Jbands : ITValuePublisher, IDisposable
_logLengthDivider = Math.Log(Math.Max(_lengthDivider, 1e-12));
_logSqrtDivider = Math.Log(Math.Max(sqrtDivider, 1e-12));
WarmupPeriod = (int)Math.Ceiling(20.0 + 80.0 * Math.Pow(period, 0.36));
WarmupPeriod = (int)Math.Ceiling(20.0 + (80.0 * Math.Pow(period, 0.36)));
_handler = Handle;
Name = $"Jbands({period},{phase})";
@@ -22,7 +22,7 @@ public class JbandsIndicatorTests
public void MinHistoryDepths_MatchesWarmupFormula()
{
var ind = new JbandsIndicator { Period = 14 };
int expected = (int)Math.Ceiling(20.0 + 80.0 * Math.Pow(14, 0.36));
int expected = (int)Math.Ceiling(20.0 + (80.0 * Math.Pow(14, 0.36)));
Assert.Equal(expected, ind.MinHistoryDepths);
}
@@ -155,7 +155,7 @@ public class JbandsIndicatorTests
var now = DateTime.UtcNow;
for (int i = 0; i < 30; i++)
{
double price = 100 + Math.Sin(i * 0.3) * 10;
double price = 100 + (Math.Sin(i * 0.3) * 10);
indZero.HistoricalData.AddBar(now.AddMinutes(i), price - 1, price + 2, price - 2, price);
indPos.HistoricalData.AddBar(now.AddMinutes(i), price - 1, price + 2, price - 2, price);
indZero.ProcessUpdate(new UpdateArgs(i == 0 ? UpdateReason.HistoricalBar : UpdateReason.NewBar));
@@ -185,7 +185,7 @@ public class JbandsIndicatorTests
var now = DateTime.UtcNow;
for (int i = 0; i < 30; i++)
{
double price = 100 + Math.Sin(i * 0.3) * 10;
double price = 100 + (Math.Sin(i * 0.3) * 10);
indPos.HistoricalData.AddBar(now.AddMinutes(i), price - 1, price + 2, price - 2, price);
indNeg.HistoricalData.AddBar(now.AddMinutes(i), price - 1, price + 2, price - 2, price);
indPos.ProcessUpdate(new UpdateArgs(i == 0 ? UpdateReason.HistoricalBar : UpdateReason.NewBar));
+1 -1
View File
@@ -617,7 +617,7 @@ public class JbandsTests
for (int i = 0; i < 100; i++)
{
var val = new TValue(DateTime.UtcNow.AddMinutes(i), 100 + i * 0.5);
var val = new TValue(DateTime.UtcNow.AddMinutes(i), 100 + (i * 0.5));
src.Add(val.Time, val.Value);
j.Update(val, isNew: true);
}
+2 -2
View File
@@ -197,7 +197,7 @@ public sealed class Kc : ITValuePublisher
double trueRange = Math.Max(tr1, Math.Max(tr2, tr3));
// ATR using RMA with warmup compensation
double newRawRma = (_state.RawRma * (_period - 1) + trueRange) / _period;
double newRawRma = ((_state.RawRma * (_period - 1)) + trueRange) / _period;
double newE = (1.0 - _atrAlpha) * _state.E;
double atrValue = newE > Epsilon ? newRawRma / (1.0 - newE) : newRawRma;
@@ -360,7 +360,7 @@ public sealed class Kc : ITValuePublisher
double tr = Math.Max(tr1, Math.Max(tr2, tr3));
// ATR (RMA with warmup)
rawRma = (rawRma * (period - 1) + tr) / period;
rawRma = ((rawRma * (period - 1)) + tr) / period;
e = (1.0 - atrAlpha) * e;
double atr = e > Epsilon ? rawRma / (1.0 - e) : rawRma;
+1 -1
View File
@@ -158,7 +158,7 @@ public class MaenvTests
// Actual: first bar w=9, second bar: newest w=9, oldest w=6; sum=110*9+100*6=990+600=1590; norm=15
// WMA = 1590/15 = 106
m.Update(new TValue(DateTime.UtcNow, 110));
double expected2 = (110 * 9 + 100 * 6) / 15.0;
double expected2 = ((110 * 9) + (100 * 6)) / 15.0;
Assert.Equal(expected2, m.Last.Value, 1e-10);
}
@@ -120,11 +120,11 @@ public sealed class MaenvValidationTests : IDisposable
Assert.Equal(100.0, ind.Last.Value, 1e-10);
ind.Update(series[1]);
double expected2 = (110.0 * 9 + 100.0 * 6) / 15.0;
double expected2 = ((110.0 * 9) + (100.0 * 6)) / 15.0;
Assert.Equal(expected2, ind.Last.Value, 1e-10);
ind.Update(series[2]);
double expected3 = (120.0 * 9 + 110.0 * 6 + 100.0 * 3) / 18.0;
double expected3 = ((120.0 * 9) + (110.0 * 6) + (100.0 * 3)) / 18.0;
Assert.Equal(expected3, ind.Last.Value, 1e-10);
_output.WriteLine("Maenv WMA manual calculation validated");
@@ -129,7 +129,7 @@ public class RegchannelIndicatorTests
// Add some volatility to ensure non-zero stddev
for (int i = 0; i < 20; i++)
{
double price = 100 + Math.Sin(i * 0.5) * 10;
double price = 100 + (Math.Sin(i * 0.5) * 10);
ind.HistoricalData.AddBar(now.AddMinutes(i), price, price + 5, price - 5, price, 1000);
ind.ProcessUpdate(new UpdateArgs(i == 0 ? UpdateReason.HistoricalBar : UpdateReason.NewBar));
}
@@ -173,7 +173,7 @@ public class RegchannelIndicatorTests
var now = DateTime.UtcNow;
for (int i = 0; i < 20; i++)
{
double price = 100 + i * 0.5;
double price = 100 + (i * 0.5);
ind1.HistoricalData.AddBar(now.AddMinutes(i), price, price + 5, price - 5, price);
ind2.HistoricalData.AddBar(now.AddMinutes(i), price, price + 5, price - 5, price);
ind1.ProcessUpdate(new UpdateArgs(i == 0 ? UpdateReason.HistoricalBar : UpdateReason.NewBar));
@@ -266,14 +266,14 @@ public class RegchannelIndicatorTests
var now = DateTime.UtcNow;
for (int i = 0; i < 30; i++)
{
double price = 100 + i * 2; // Strong uptrend
double price = 100 + (i * 2); // Strong uptrend
ind.HistoricalData.AddBar(now.AddMinutes(i), price, price + 2, price - 2, price);
ind.ProcessUpdate(new UpdateArgs(i == 0 ? UpdateReason.HistoricalBar : UpdateReason.NewBar));
}
// After warmup, middle should be close to the current regression line value
double middle = ind.LinesSeries[0].GetValue(0);
double lastPrice = 100 + 29 * 2; // 158
double lastPrice = 100 + (29 * 2); // 158
// Middle should be close to last price (within reasonable range for regression)
Assert.True(Math.Abs(middle - lastPrice) < 10, $"Middle ({middle}) should be close to last price ({lastPrice})");
@@ -90,7 +90,7 @@ public class RegchannelTests
// Feed perfect linear data: y = 100 + 2*i (slope = 2)
for (int i = 0; i < 20; i++)
{
ind.Update(new TValue(now.AddMinutes(i), 100 + 2 * i));
ind.Update(new TValue(now.AddMinutes(i), 100 + (2 * i)));
}
// Slope should be 2
@@ -107,13 +107,13 @@ public class RegchannelTests
// Low volatility: close to linear
for (int i = 0; i < 20; i++)
{
ind1.Update(new TValue(now.AddMinutes(i), 100 + i + 0.1 * Math.Sin(i)));
ind1.Update(new TValue(now.AddMinutes(i), 100 + i + (0.1 * Math.Sin(i))));
}
// High volatility: large deviations from linear
for (int i = 0; i < 20; i++)
{
ind2.Update(new TValue(now.AddMinutes(i), 100 + i + 5 * Math.Sin(i)));
ind2.Update(new TValue(now.AddMinutes(i), 100 + i + (5 * Math.Sin(i))));
}
double width1 = ind1.Upper.Value - ind1.Lower.Value;
@@ -130,7 +130,7 @@ public class RegchannelTests
for (int i = 0; i < 20; i++)
{
ind.Update(new TValue(now.AddMinutes(i), 100 + i + Math.Sin(i) * 3));
ind.Update(new TValue(now.AddMinutes(i), 100 + i + (Math.Sin(i) * 3)));
}
double upperDist = ind.Upper.Value - ind.Last.Value;
@@ -148,7 +148,7 @@ public class RegchannelTests
for (int i = 0; i < 20; i++)
{
double val = 100 + i + Math.Sin(i) * 3;
double val = 100 + i + (Math.Sin(i) * 3);
ind1.Update(new TValue(now.AddMinutes(i), val));
ind2.Update(new TValue(now.AddMinutes(i), val));
}
@@ -465,7 +465,7 @@ public class RegchannelTests
for (int i = 0; i < 10000; i++)
{
double val = 100 + Math.Sin(i * 0.01) * 10 + i * 0.001;
double val = 100 + (Math.Sin(i * 0.01) * 10) + (i * 0.001);
ind.Update(new TValue(now.AddMinutes(i), val));
}
@@ -81,7 +81,7 @@ public sealed class RegchannelValidationTests : IDisposable
// Perfect linear trend: 100, 110, 120, 130, 140
for (int i = 0; i < 5; i++)
{
series.Add(new TValue(t0.AddMinutes(i), 100 + i * 10));
series.Add(new TValue(t0.AddMinutes(i), 100 + (i * 10)));
}
var ind = new Regchannel(5, 2.0);
@@ -424,7 +424,7 @@ public sealed class RegchannelValidationTests : IDisposable
var t0 = DateTime.UtcNow;
for (int i = 0; i < 20; i++)
{
uptrend.Add(new TValue(t0.AddMinutes(i), 100 + i * 2 + (i % 3))); // Noisy uptrend
uptrend.Add(new TValue(t0.AddMinutes(i), 100 + (i * 2) + (i % 3))); // Noisy uptrend
}
var indUp = new Regchannel(10, 2.0);
@@ -438,7 +438,7 @@ public sealed class RegchannelValidationTests : IDisposable
var downtrend = new TSeries();
for (int i = 0; i < 20; i++)
{
downtrend.Add(new TValue(t0.AddMinutes(i), 200 - i * 2 + (i % 3))); // Noisy downtrend
downtrend.Add(new TValue(t0.AddMinutes(i), 200 - (i * 2) + (i % 3))); // Noisy downtrend
}
var indDown = new Regchannel(10, 2.0);
@@ -129,7 +129,7 @@ public class SdchannelIndicatorTests
// Add some volatility to ensure non-zero stddev
for (int i = 0; i < 20; i++)
{
double price = 100 + Math.Sin(i * 0.5) * 10;
double price = 100 + (Math.Sin(i * 0.5) * 10);
ind.HistoricalData.AddBar(now.AddMinutes(i), price, price + 5, price - 5, price, 1000);
ind.ProcessUpdate(new UpdateArgs(i == 0 ? UpdateReason.HistoricalBar : UpdateReason.NewBar));
}
@@ -173,7 +173,7 @@ public class SdchannelIndicatorTests
var now = DateTime.UtcNow;
for (int i = 0; i < 20; i++)
{
double price = 100 + i * 0.5;
double price = 100 + (i * 0.5);
ind1.HistoricalData.AddBar(now.AddMinutes(i), price, price + 5, price - 5, price);
ind2.HistoricalData.AddBar(now.AddMinutes(i), price, price + 5, price - 5, price);
ind1.ProcessUpdate(new UpdateArgs(i == 0 ? UpdateReason.HistoricalBar : UpdateReason.NewBar));
@@ -266,14 +266,14 @@ public class SdchannelIndicatorTests
var now = DateTime.UtcNow;
for (int i = 0; i < 30; i++)
{
double price = 100 + i * 2; // Strong uptrend
double price = 100 + (i * 2); // Strong uptrend
ind.HistoricalData.AddBar(now.AddMinutes(i), price, price + 2, price - 2, price);
ind.ProcessUpdate(new UpdateArgs(i == 0 ? UpdateReason.HistoricalBar : UpdateReason.NewBar));
}
// After warmup, middle should be close to the current regression line value
double middle = ind.LinesSeries[0].GetValue(0);
double lastPrice = 100 + 29 * 2; // 158
double lastPrice = 100 + (29 * 2); // 158
// Middle should be close to last price (within reasonable range for regression)
Assert.True(Math.Abs(middle - lastPrice) < 10, $"Middle ({middle}) should be close to last price ({lastPrice})");
@@ -192,7 +192,7 @@ public class SdchannelTests
// Perfect linear trend: 100, 102, 104, 106, 108
for (int i = 0; i < 5; i++)
{
s.Update(new TValue(DateTime.UtcNow, 100 + i * 2));
s.Update(new TValue(DateTime.UtcNow, 100 + (i * 2)));
}
// All points lie exactly on regression line
@@ -90,7 +90,7 @@ public sealed class SdchannelValidationTests : IDisposable
// Perfect linear trend: 100, 110, 120, 130, 140
for (int i = 0; i < 5; i++)
{
series.Add(new TValue(t0.AddMinutes(i), 100 + i * 10));
series.Add(new TValue(t0.AddMinutes(i), 100 + (i * 10)));
}
var ind = new Sdchannel(5, 2.0);
@@ -433,7 +433,7 @@ public sealed class SdchannelValidationTests : IDisposable
var t0 = DateTime.UtcNow;
for (int i = 0; i < 20; i++)
{
uptrend.Add(new TValue(t0.AddMinutes(i), 100 + i * 2 + (i % 3))); // Noisy uptrend
uptrend.Add(new TValue(t0.AddMinutes(i), 100 + (i * 2) + (i % 3))); // Noisy uptrend
}
var indUp = new Sdchannel(10, 2.0);
@@ -447,7 +447,7 @@ public sealed class SdchannelValidationTests : IDisposable
var downtrend = new TSeries();
for (int i = 0; i < 20; i++)
{
downtrend.Add(new TValue(t0.AddMinutes(i), 200 - i * 2 + (i % 3))); // Noisy downtrend
downtrend.Add(new TValue(t0.AddMinutes(i), 200 - (i * 2) + (i % 3))); // Noisy downtrend
}
var indDown = new Sdchannel(10, 2.0);
+2 -2
View File
@@ -192,7 +192,7 @@ public sealed class Starchannel : ITValuePublisher
double trueRange = Math.Max(tr1, Math.Max(tr2, tr3));
// ATR using RMA with warmup compensation (uses _atrPeriod for separate ATR smoothing)
double newRawRma = (_state.RawRma * (_atrPeriod - 1) + trueRange) / _atrPeriod;
double newRawRma = ((_state.RawRma * (_atrPeriod - 1)) + trueRange) / _atrPeriod;
double newE = (1.0 - _atrAlpha) * _state.E;
double atrValue = newE > Epsilon ? newRawRma / (1.0 - newE) : newRawRma;
@@ -406,7 +406,7 @@ public sealed class Starchannel : ITValuePublisher
double tr = Math.Max(tr1, Math.Max(tr2, tr3));
// ATR (RMA with warmup compensation, uses effectiveAtrPeriod)
rawRma = (rawRma * (effectiveAtrPeriod - 1) + tr) / effectiveAtrPeriod;
rawRma = ((rawRma * (effectiveAtrPeriod - 1)) + tr) / effectiveAtrPeriod;
e = (1.0 - atrAlpha) * e;
double atr = e > Epsilon ? rawRma / (1.0 - e) : rawRma;
@@ -396,7 +396,7 @@ public sealed class StarchannelValidationTests : IDisposable
// Create predictable data: 100, 102, 104, 106, 108
for (int i = 0; i < 5; i++)
{
double close = 100 + i * 2;
double close = 100 + (i * 2);
series.Add(new TBar(t0.AddMinutes(i), close, close + 5, close - 5, close, 100));
}
+1 -2
View File
@@ -279,7 +279,7 @@ public sealed class Stbands : AbstractBase
for (int i = 0; i < source.Length; i++)
{
// Treat as close price only
Update(new TValue(startTime + i * step.Value, source[i]), isNew: true);
Update(new TValue(startTime + (i * step.Value), source[i]), isNew: true);
}
}
@@ -406,5 +406,4 @@ public sealed class Stbands : AbstractBase
TSeries results = indicator.Update(source);
return (results, indicator);
}
}
+1 -1
View File
@@ -403,7 +403,7 @@ public class StbandsTests
var series = new TSeries();
for (int i = 0; i < 20; i++)
{
series.Add(DateTime.UtcNow.AddMinutes(i), 100 + i * 0.5);
series.Add(DateTime.UtcNow.AddMinutes(i), 100 + (i * 0.5));
}
TSeries result = stbands.Update(series);
+16 -16
View File
@@ -136,9 +136,9 @@ public sealed class TtmLrc : ITValuePublisher
// sumX = 0 + 1 + ... + (n-1) = n(n-1)/2
_sumX = 0.5 * period * (period - 1);
// sumX² = 0² + 1² + ... + (n-1)² = (n-1)n(2n-1)/6
double sumX2 = (period - 1.0) * period * (2.0 * period - 1.0) / 6.0;
double sumX2 = (period - 1.0) * period * ((2.0 * period) - 1.0) / 6.0;
// denominator = n * sumX² - sumX²
_denominator = period * sumX2 - _sumX * _sumX;
_denominator = (period * sumX2) - (_sumX * _sumX);
Reset();
}
@@ -253,8 +253,8 @@ public sealed class TtmLrc : 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;
@@ -267,8 +267,8 @@ public sealed class TtmLrc : 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);
}
@@ -304,8 +304,8 @@ public sealed class TtmLrc : ITValuePublisher
Midline = new TValue(input.Time, regression);
Upper1 = new TValue(input.Time, regression + stdDev);
Lower1 = new TValue(input.Time, regression - stdDev);
Upper2 = new TValue(input.Time, regression + 2.0 * stdDev);
Lower2 = new TValue(input.Time, regression - 2.0 * stdDev);
Upper2 = new TValue(input.Time, regression + (2.0 * stdDev));
Lower2 = new TValue(input.Time, regression - (2.0 * stdDev));
PubEvent(Midline, isNew);
return Midline;
@@ -412,8 +412,8 @@ public sealed class TtmLrc : 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);
// Track last valid value for NaN substitution
double lastValid = double.NaN;
@@ -483,8 +483,8 @@ public sealed class TtmLrc : 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
{
@@ -502,8 +502,8 @@ public sealed class TtmLrc : 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);
}
@@ -533,8 +533,8 @@ public sealed class TtmLrc : ITValuePublisher
midline[i] = regression;
upper1[i] = regression + stdDev;
lower1[i] = regression - stdDev;
upper2[i] = regression + 2.0 * stdDev;
lower2[i] = regression - 2.0 * stdDev;
upper2[i] = regression + (2.0 * stdDev);
lower2[i] = regression - (2.0 * stdDev);
}
}
@@ -132,7 +132,7 @@ public class TtmLrcIndicatorTests
// Add some volatility to ensure non-zero stddev
for (int i = 0; i < 20; i++)
{
double price = 100 + Math.Sin(i * 0.5) * 10;
double price = 100 + (Math.Sin(i * 0.5) * 10);
ind.HistoricalData.AddBar(now.AddMinutes(i), price, price + 5, price - 5, price, 1000);
ind.ProcessUpdate(new UpdateArgs(i == 0 ? UpdateReason.HistoricalBar : UpdateReason.NewBar));
}
@@ -214,7 +214,7 @@ public class TtmLrcIndicatorTests
// Perfect linear data: y = 100 + 2*i
for (int i = 0; i < 20; i++)
{
double price = 100 + i * 2;
double price = 100 + (i * 2);
ind.HistoricalData.AddBar(now.AddMinutes(i), price, price, price, price);
ind.ProcessUpdate(new UpdateArgs(i == 0 ? UpdateReason.HistoricalBar : UpdateReason.NewBar));
}
@@ -264,14 +264,14 @@ public class TtmLrcIndicatorTests
var now = DateTime.UtcNow;
for (int i = 0; i < 30; i++)
{
double price = 100 + i * 2; // Strong uptrend
double price = 100 + (i * 2); // Strong uptrend
ind.HistoricalData.AddBar(now.AddMinutes(i), price, price + 2, price - 2, price);
ind.ProcessUpdate(new UpdateArgs(i == 0 ? UpdateReason.HistoricalBar : UpdateReason.NewBar));
}
// After warmup, midline should be close to the current regression line value
double midline = ind.LinesSeries[0].GetValue(0);
double lastPrice = 100 + 29 * 2; // 158
double lastPrice = 100 + (29 * 2); // 158
// Midline should be close to last price (within reasonable range for regression)
Assert.True(Math.Abs(midline - lastPrice) < 10, $"Midline ({midline}) should be close to last price ({lastPrice})");
+11 -11
View File
@@ -166,7 +166,7 @@ public class TtmLrcTests
// Perfect linear data: y = 100 + 2*x
for (int i = 0; i < 15; i++)
{
indicator.Update(new TValue(now.AddMinutes(i), 100 + 2.0 * i), isNew: true);
indicator.Update(new TValue(now.AddMinutes(i), 100 + (2.0 * i)), isNew: true);
}
Assert.True(indicator.IsHot);
@@ -189,7 +189,7 @@ public class TtmLrcTests
for (int i = 0; i < 15; i++)
{
indicator.Update(new TValue(now.AddMinutes(i), 100 + 5.0 * i), isNew: true);
indicator.Update(new TValue(now.AddMinutes(i), 100 + (5.0 * i)), isNew: true);
}
Assert.True(indicator.Slope > 0, $"Slope should be positive for uptrend, got {indicator.Slope}");
@@ -203,7 +203,7 @@ public class TtmLrcTests
for (int i = 0; i < 15; i++)
{
indicator.Update(new TValue(now.AddMinutes(i), 100 - 3.0 * i), isNew: true);
indicator.Update(new TValue(now.AddMinutes(i), 100 - (3.0 * i)), isNew: true);
}
Assert.True(indicator.Slope < 0, $"Slope should be negative for downtrend, got {indicator.Slope}");
@@ -236,7 +236,7 @@ public class TtmLrcTests
for (int i = 0; i < 15; i++)
{
indicator.Update(new TValue(now.AddMinutes(i), 100 + 2.0 * i), isNew: true);
indicator.Update(new TValue(now.AddMinutes(i), 100 + (2.0 * i)), isNew: true);
}
Assert.True(Math.Abs(indicator.RSquared - 1.0) < 1e-9, $"R² should be 1.0 for perfect linear fit, got {indicator.RSquared}");
@@ -313,7 +313,7 @@ public class TtmLrcTests
for (int i = 0; i < 8; i++)
{
indicator.Update(new TValue(now.AddMinutes(i), 100 + i * 2), isNew: true);
indicator.Update(new TValue(now.AddMinutes(i), 100 + (i * 2)), isNew: true);
}
double baseMid = indicator.Midline.Value;
@@ -321,11 +321,11 @@ public class TtmLrcTests
// Multiple corrections
for (int j = 0; j < 5; j++)
{
indicator.Update(new TValue(now.AddMinutes(7), 150 + j * 10), isNew: false);
indicator.Update(new TValue(now.AddMinutes(7), 150 + (j * 10)), isNew: false);
}
// Revert to original
indicator.Update(new TValue(now.AddMinutes(7), 100 + 7 * 2), isNew: false);
indicator.Update(new TValue(now.AddMinutes(7), 100 + (7 * 2)), isNew: false);
Assert.Equal(baseMid, indicator.Midline.Value, 10);
}
@@ -492,7 +492,7 @@ public class TtmLrcTests
for (int i = 0; i < 10; i++)
{
indicator.Update(new TValue(now.AddMinutes(i), 100 + i * 2), isNew: true);
indicator.Update(new TValue(now.AddMinutes(i), 100 + (i * 2)), isNew: true);
}
Assert.True(indicator.IsHot);
@@ -546,7 +546,7 @@ public class TtmLrcTests
for (int i = 0; i < 15; i++)
{
times.Add(now.AddMinutes(i).Ticks);
values.Add(100 + i * 2);
values.Add(100 + (i * 2));
}
var source = new TSeries(times, values);
@@ -565,7 +565,7 @@ public class TtmLrcTests
for (int i = 0; i < 8; i++)
{
source.Add(new TValue(now.AddMinutes(i), 100 + i * 3), isNew: true);
source.Add(new TValue(now.AddMinutes(i), 100 + (i * 3)), isNew: true);
}
Assert.True(indicator.IsHot);
@@ -720,7 +720,7 @@ public class TtmLrcTests
for (int i = 0; i < 8; i++)
{
indicator.Update(new TValue(now.AddMinutes(i), 100 + i * 2), isNew: true);
indicator.Update(new TValue(now.AddMinutes(i), 100 + (i * 2)), isNew: true);
}
Assert.NotNull(lastPubValue);
@@ -74,8 +74,8 @@ public sealed class TtmLrcValidationTests : IDisposable
Assert.Equal(115.0 - expectedStdDev, ind.Lower1.Value, 1e-10);
// Verify ±2σ bands
Assert.Equal(115.0 + 2.0 * expectedStdDev, ind.Upper2.Value, 1e-10);
Assert.Equal(115.0 - 2.0 * expectedStdDev, ind.Lower2.Value, 1e-10);
Assert.Equal(115.0 + (2.0 * expectedStdDev), ind.Upper2.Value, 1e-10);
Assert.Equal(115.0 - (2.0 * expectedStdDev), ind.Lower2.Value, 1e-10);
_output.WriteLine("TtmLrc manual calculation validated");
}
@@ -89,7 +89,7 @@ public sealed class TtmLrcValidationTests : IDisposable
// Perfect linear trend: 100, 110, 120, 130, 140
for (int i = 0; i < 5; i++)
{
series.Add(new TValue(t0.AddMinutes(i), 100 + i * 10));
series.Add(new TValue(t0.AddMinutes(i), 100 + (i * 10)));
}
var ind = new TtmLrc(5);
@@ -362,7 +362,7 @@ public sealed class TtmLrcValidationTests : IDisposable
// Feed perfect linear data
for (int i = 0; i < 10; i++)
{
ind.Update(new TValue(t0.AddMinutes(i), 100 + i * 5));
ind.Update(new TValue(t0.AddMinutes(i), 100 + (i * 5)));
}
Assert.Equal(1.0, ind.RSquared, 1e-9);
@@ -481,7 +481,7 @@ public sealed class TtmLrcValidationTests : IDisposable
var t0 = DateTime.UtcNow;
for (int i = 0; i < 20; i++)
{
uptrend.Add(new TValue(t0.AddMinutes(i), 100 + i * 2 + (i % 3))); // Noisy uptrend
uptrend.Add(new TValue(t0.AddMinutes(i), 100 + (i * 2) + (i % 3))); // Noisy uptrend
}
var indUp = new TtmLrc(10);
@@ -495,7 +495,7 @@ public sealed class TtmLrcValidationTests : IDisposable
var downtrend = new TSeries();
for (int i = 0; i < 20; i++)
{
downtrend.Add(new TValue(t0.AddMinutes(i), 200 - i * 2 + (i % 3))); // Noisy downtrend
downtrend.Add(new TValue(t0.AddMinutes(i), 200 - (i * 2) + (i % 3))); // Noisy downtrend
}
var indDown = new TtmLrc(10);
+3 -4
View File
@@ -100,7 +100,7 @@ public sealed class Ubands : AbstractBase
// Precompute coefficients for FMA optimization
_k0 = 1.0 - c1; // coefficient for val
_k1 = 2.0 * c1 - _c2; // coefficient for PrevInput1
_k1 = (2.0 * c1) - _c2; // coefficient for PrevInput1
_k2 = -(c1 + _c3); // coefficient for PrevInput2
WarmupPeriod = period;
@@ -261,7 +261,7 @@ public sealed class Ubands : AbstractBase
for (int i = 0; i < source.Length; i++)
{
Update(new TValue(startTime + i * step.Value, source[i]), isNew: true);
Update(new TValue(startTime + (i * step.Value), source[i]), isNew: true);
}
}
@@ -316,7 +316,7 @@ public sealed class Ubands : AbstractBase
double c1 = (1.0 + c2 - c3) / 4.0;
double k0 = 1.0 - c1;
double k1 = 2.0 * c1 - c2;
double k1 = (2.0 * c1) - c2;
double k2 = -(c1 + c3);
// Use stackalloc for residual buffer if small enough
@@ -404,5 +404,4 @@ public sealed class Ubands : AbstractBase
TSeries results = indicator.Update(source);
return (results, indicator);
}
}
@@ -409,7 +409,7 @@ public sealed class UbandsValidationTests : IDisposable
_output.WriteLine($"Source variance: {sourceVar:F4}");
_output.WriteLine($"Middle (USF) variance: {middleVar:F4}");
_output.WriteLine($"Noise reduction: {(1 - middleVar / sourceVar) * 100:F1}%");
_output.WriteLine($"Noise reduction: {(1 - (middleVar / sourceVar)) * 100:F1}%");
Assert.True(middleVar < sourceVar, "Smoothed signal should have lower variance");
}
+5 -5
View File
@@ -217,7 +217,7 @@ public sealed class Uchannel : AbstractBase
{
// USF: (1-c1)*s0 + (2*c1-c2)*s1 - (c1+c3)*s2 + c2*usf1 + c3*usf2
strValue = Math.FusedMultiplyAdd(1 - _c1_str, str_s0,
Math.FusedMultiplyAdd(2 * _c1_str - _c2_str, str_s1,
Math.FusedMultiplyAdd((2 * _c1_str) - _c2_str, str_s1,
Math.FusedMultiplyAdd(-(_c1_str + _c3_str), str_s2,
Math.FusedMultiplyAdd(_c2_str, usStr1, _c3_str * usStr2))));
}
@@ -237,7 +237,7 @@ public sealed class Uchannel : AbstractBase
else
{
cenValue = Math.FusedMultiplyAdd(1 - _c1_cen, cen_s0,
Math.FusedMultiplyAdd(2 * _c1_cen - _c2_cen, cen_s1,
Math.FusedMultiplyAdd((2 * _c1_cen) - _c2_cen, cen_s1,
Math.FusedMultiplyAdd(-(_c1_cen + _c3_cen), cen_s2,
Math.FusedMultiplyAdd(_c2_cen, usCen1, _c3_cen * usCen2))));
}
@@ -337,7 +337,7 @@ public sealed class Uchannel : AbstractBase
for (int i = 0; i < source.Length; i++)
{
// Treat as close price only
Update(new TValue(startTime + i * step.Value, source[i]), isNew: true);
Update(new TValue(startTime + (i * step.Value), source[i]), isNew: true);
}
}
@@ -471,7 +471,7 @@ public sealed class Uchannel : AbstractBase
else
{
strValue = Math.FusedMultiplyAdd(1 - c1_str, str_s0,
Math.FusedMultiplyAdd(2 * c1_str - c2_str, str_s1,
Math.FusedMultiplyAdd((2 * c1_str) - c2_str, str_s1,
Math.FusedMultiplyAdd(-(c1_str + c3_str), str_s2,
Math.FusedMultiplyAdd(c2_str, usStr1, c3_str * usStr2))));
}
@@ -489,7 +489,7 @@ public sealed class Uchannel : AbstractBase
else
{
cenValue = Math.FusedMultiplyAdd(1 - c1_cen, cen_s0,
Math.FusedMultiplyAdd(2 * c1_cen - c2_cen, cen_s1,
Math.FusedMultiplyAdd((2 * c1_cen) - c2_cen, cen_s1,
Math.FusedMultiplyAdd(-(c1_cen + c3_cen), cen_s2,
Math.FusedMultiplyAdd(c2_cen, usCen1, c3_cen * usCen2))));
}
@@ -358,7 +358,7 @@ public class UchannelQuantowerTests
double width2 = indicator2.LinesSeries[4].GetValue(0);
// Width2 should be approximately 2x Width1
Assert.True(Math.Abs(width2 - 2 * width1) < 0.0001,
Assert.True(Math.Abs(width2 - (2 * width1)) < 0.0001,
$"Width2 ({width2}) should be ~2x Width1 ({width1})");
}
@@ -377,7 +377,7 @@ public class UchannelQuantowerTests
var now = DateTime.UtcNow;
for (int i = 0; i < 30; i++)
{
double close = 100 + (i % 5) * 2;
double close = 100 + ((i % 5) * 2);
indicator1.HistoricalData.AddBar(now.AddMinutes(i), close, close + 3, close - 3, close, 1000);
indicator1.ProcessUpdate(new UpdateArgs(UpdateReason.HistoricalBar));
indicator2.HistoricalData.AddBar(now.AddMinutes(i), close, close + 3, close - 3, close, 1000);
+11 -11
View File
@@ -206,9 +206,9 @@ public sealed class Vwapbands : AbstractBase
{
_state = _state with
{
SumPV = _state.SumPV + price * vol,
SumPV = _state.SumPV + (price * vol),
SumVol = _state.SumVol + vol,
SumPV2 = _state.SumPV2 + price * price * vol,
SumPV2 = _state.SumPV2 + (price * price * vol),
Count = _state.Count + 1
};
}
@@ -228,10 +228,10 @@ public sealed class Vwapbands : AbstractBase
double stdev = Math.Sqrt(variance);
// Calculate bands
double upper1 = vwap + _multiplier * stdev;
double lower1 = vwap - _multiplier * stdev;
double upper2 = vwap + 2.0 * _multiplier * stdev;
double lower2 = vwap - 2.0 * _multiplier * stdev;
double upper1 = vwap + (_multiplier * stdev);
double lower1 = vwap - (_multiplier * stdev);
double upper2 = vwap + (2.0 * _multiplier * stdev);
double lower2 = vwap - (2.0 * _multiplier * stdev);
// Update output values
Vwap = new TValue(input.Time, vwap);
@@ -316,7 +316,7 @@ public sealed class Vwapbands : AbstractBase
for (int i = 0; i < source.Length; i++)
{
Update(new TValue(startTime + i * step.Value, source[i]), 1.0, isNew: true, reset: false);
Update(new TValue(startTime + (i * step.Value), source[i]), 1.0, isNew: true, reset: false);
}
}
@@ -423,10 +423,10 @@ public sealed class Vwapbands : AbstractBase
vwap[i] = vwapVal;
stdDev[i] = stdev;
upper1[i] = vwapVal + multiplier * stdev;
lower1[i] = vwapVal - multiplier * stdev;
upper2[i] = vwapVal + 2.0 * multiplier * stdev;
lower2[i] = vwapVal - 2.0 * multiplier * stdev;
upper1[i] = vwapVal + (multiplier * stdev);
lower1[i] = vwapVal - (multiplier * stdev);
upper2[i] = vwapVal + (2.0 * multiplier * stdev);
lower2[i] = vwapVal - (2.0 * multiplier * stdev);
}
}
}
@@ -148,7 +148,7 @@ public class VwapbandsIndicatorTests
var now = DateTime.UtcNow;
for (int i = 0; i < 5; i++)
{
indicator.HistoricalData.AddBar(now.AddMinutes(i), 100 + i, 105 + i, 95 + i, 102 + i, 1000 + i * 100);
indicator.HistoricalData.AddBar(now.AddMinutes(i), 100 + i, 105 + i, 95 + i, 102 + i, 1000 + (i * 100));
indicator.ProcessUpdate(new UpdateArgs(UpdateReason.HistoricalBar));
}
@@ -120,7 +120,7 @@ public class VwapbandsTests
// Make multiple corrections
for (int i = 0; i < 10; i++)
{
var correctionBar = new TBar(DateTime.UtcNow, 150 + i, 160 + i, 140 + i, 155 + i, 2000 + i * 100);
var correctionBar = new TBar(DateTime.UtcNow, 150 + i, 160 + i, 140 + i, 155 + i, 2000 + (i * 100));
vwapbands.Update(correctionBar, isNew: false);
}
@@ -359,7 +359,7 @@ public class VwapbandsTests
vwapbands.Update(bar2);
// VWAP = (100*1000 + 110*2000) / (1000+2000) = 320000/3000 = 106.666...
double expectedVwap = (100.0 * 1000 + 110.0 * 2000) / (1000 + 2000);
double expectedVwap = ((100.0 * 1000) + (110.0 * 2000)) / (1000 + 2000);
Assert.Equal(expectedVwap, vwapbands.Vwap.Value, precision: 10);
}
@@ -600,7 +600,7 @@ public class VwapbandsTests
// VWAP should be closer to 100 due to higher volume
// VWAP = (100*10000 + 200*100) / (10000+100) = 1020000/10100 ≈ 100.99
double expectedVwap = (100.0 * 10000 + 200.0 * 100) / (10000 + 100);
double expectedVwap = ((100.0 * 10000) + (200.0 * 100)) / (10000 + 100);
Assert.Equal(expectedVwap, vwapbands.Vwap.Value, precision: 10);
Assert.True(vwapbands.Vwap.Value < 110, "VWAP should be heavily weighted toward 100");
}
@@ -273,7 +273,7 @@ public sealed class VwapbandsValidationTests : IDisposable
// VWAP should be closer to 100 (high volume price)
// VWAP = (100 × 10000 + 200 × 100) / (10000 + 100) = 1020000 / 10100 ≈ 100.99
double expectedVwap = (100.0 * 10000 + 200.0 * 100) / (10000 + 100);
double expectedVwap = ((100.0 * 10000) + (200.0 * 100)) / (10000 + 100);
Assert.Equal(expectedVwap, vwapbands.Vwap.Value, precision: 10);
Assert.True(vwapbands.Vwap.Value < 110, "VWAP should be heavily weighted toward 100");
@@ -434,7 +434,7 @@ public sealed class VwapbandsValidationTests : IDisposable
// Multiple zero-volume bars with different prices
for (int i = 0; i < 5; i++)
{
var zeroVolBar = new TBar(DateTime.UtcNow.AddMinutes(i + 1), 200 + i * 10, 200 + i * 10, 200 + i * 10, 200 + i * 10, 0);
var zeroVolBar = new TBar(DateTime.UtcNow.AddMinutes(i + 1), 200 + (i * 10), 200 + (i * 10), 200 + (i * 10), 200 + (i * 10), 0);
vwapbands.Update(zeroVolBar);
}
+7 -7
View File
@@ -200,9 +200,9 @@ public sealed class Vwapsd : AbstractBase
{
_state = _state with
{
SumPV = _state.SumPV + price * vol,
SumPV = _state.SumPV + (price * vol),
SumVol = _state.SumVol + vol,
SumPV2 = _state.SumPV2 + price * price * vol,
SumPV2 = _state.SumPV2 + (price * price * vol),
Count = _state.Count + 1
};
}
@@ -222,8 +222,8 @@ public sealed class Vwapsd : AbstractBase
double stdev = Math.Sqrt(variance);
// Calculate bands
double upper = vwap + _numDevs * stdev;
double lower = vwap - _numDevs * stdev;
double upper = vwap + (_numDevs * stdev);
double lower = vwap - (_numDevs * stdev);
// Update output values
Vwap = new TValue(input.Time, vwap);
@@ -302,7 +302,7 @@ public sealed class Vwapsd : AbstractBase
for (int i = 0; i < source.Length; i++)
{
Update(new TValue(startTime + i * step.Value, source[i]), 1.0, isNew: true, reset: false);
Update(new TValue(startTime + (i * step.Value), source[i]), 1.0, isNew: true, reset: false);
}
}
@@ -405,8 +405,8 @@ public sealed class Vwapsd : AbstractBase
vwap[i] = vwapVal;
stdDev[i] = stdev;
upper[i] = vwapVal + numDevs * stdev;
lower[i] = vwapVal - numDevs * stdev;
upper[i] = vwapVal + (numDevs * stdev);
lower[i] = vwapVal - (numDevs * stdev);
}
}
}
@@ -242,7 +242,7 @@ public class VwapsdIndicatorTests
var now = DateTime.UtcNow;
for (int i = 0; i < 5; i++)
{
indicator.HistoricalData.AddBar(now.AddMinutes(i), 100 + i, 105 + i, 95 + i, 102 + i, 1000 + i * 100);
indicator.HistoricalData.AddBar(now.AddMinutes(i), 100 + i, 105 + i, 95 + i, 102 + i, 1000 + (i * 100));
indicator.ProcessUpdate(new UpdateArgs(UpdateReason.HistoricalBar));
}
@@ -344,7 +344,7 @@ public class VwapsdIndicatorTests
double width2 = indicator2.LinesSeries[3].GetValue(0);
// Width2 should be approximately 2x Width1
Assert.True(Math.Abs(width2 - 2 * width1) < 0.0001,
Assert.True(Math.Abs(width2 - (2 * width1)) < 0.0001,
$"Width2 ({width2}) should be ~2x Width1 ({width1})");
}
+3 -3
View File
@@ -136,7 +136,7 @@ public class VwapsdTests
// Make multiple corrections
for (int i = 0; i < 10; i++)
{
var correctionBar = new TBar(DateTime.UtcNow, 150 + i, 160 + i, 140 + i, 155 + i, 2000 + i * 100);
var correctionBar = new TBar(DateTime.UtcNow, 150 + i, 160 + i, 140 + i, 155 + i, 2000 + (i * 100));
vwapsd.Update(correctionBar, isNew: false);
}
@@ -371,7 +371,7 @@ public class VwapsdTests
vwapsd.Update(bar2);
// VWAP = (100*1000 + 110*2000) / (1000+2000) = 320000/3000 = 106.666...
double expectedVwap = (100.0 * 1000 + 110.0 * 2000) / (1000 + 2000);
double expectedVwap = ((100.0 * 1000) + (110.0 * 2000)) / (1000 + 2000);
Assert.Equal(expectedVwap, vwapsd.Vwap.Value, precision: 10);
}
@@ -634,7 +634,7 @@ public class VwapsdTests
// VWAP should be closer to 100 due to higher volume
// VWAP = (100*10000 + 200*100) / (10000+100) = 1020000/10100 ≈ 100.99
double expectedVwap = (100.0 * 10000 + 200.0 * 100) / (10000 + 100);
double expectedVwap = ((100.0 * 10000) + (200.0 * 100)) / (10000 + 100);
Assert.Equal(expectedVwap, vwapsd.Vwap.Value, precision: 10);
Assert.True(vwapsd.Vwap.Value < 110, "VWAP should be heavily weighted toward 100");
}
@@ -305,7 +305,7 @@ public sealed class VwapsdValidationTests : IDisposable
// VWAP should be closer to 100 (high volume price)
// VWAP = (100 × 10000 + 200 × 100) / (10000 + 100) = 1020000 / 10100 ≈ 100.99
double expectedVwap = (100.0 * 10000 + 200.0 * 100) / (10000 + 100);
double expectedVwap = ((100.0 * 10000) + (200.0 * 100)) / (10000 + 100);
Assert.Equal(expectedVwap, vwapsd.Vwap.Value, precision: 10);
Assert.True(vwapsd.Vwap.Value < 110, "VWAP should be heavily weighted toward 100");
@@ -466,7 +466,7 @@ public sealed class VwapsdValidationTests : IDisposable
// Multiple zero-volume bars with different prices
for (int i = 0; i < 5; i++)
{
var zeroVolBar = new TBar(DateTime.UtcNow.AddMinutes(i + 1), 200 + i * 10, 200 + i * 10, 200 + i * 10, 200 + i * 10, 0);
var zeroVolBar = new TBar(DateTime.UtcNow.AddMinutes(i + 1), 200 + (i * 10), 200 + (i * 10), 200 + (i * 10), 200 + (i * 10), 0);
vwapsd.Update(zeroVolBar);
}
@@ -100,10 +100,10 @@ public class MidpointIndicatorTests
{
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));
}
-1
View File
@@ -2,7 +2,6 @@ using System.Buffers;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
namespace QuanTAlib;
/// <summary>
+1 -1
View File
@@ -433,7 +433,7 @@ public static class ErrorHelpers
double diff = act - pred;
double ratio = diff / delta;
// δ² * (√(1 + (error/δ)²) - 1)
output[i] = deltaSquared * (Math.Sqrt(1.0 + ratio * ratio) - 1.0);
output[i] = deltaSquared * (Math.Sqrt(1.0 + (ratio * ratio)) - 1.0);
}
}
@@ -1223,9 +1223,9 @@ public class TBarSeriesTests
{
times[i] = i;
opens[i] = i * 10.0;
highs[i] = i * 10.0 + 5.0;
lows[i] = i * 10.0 - 5.0;
closes[i] = i * 10.0 + 2.0;
highs[i] = (i * 10.0) + 5.0;
lows[i] = (i * 10.0) - 5.0;
closes[i] = (i * 10.0) + 2.0;
volumes[i] = i * 100.0;
}
@@ -1233,7 +1233,7 @@ public class TBarSeriesTests
Assert.Equal(N, series.Count);
Assert.Equal(0, series[0].Time);
Assert.Equal((N - 1) * 10.0 + 2.0, series[N - 1].Close);
Assert.Equal(((N - 1) * 10.0) + 2.0, series[N - 1].Close);
Assert.Equal((N - 1) * 100.0, series[N - 1].Volume);
}
@@ -1246,7 +1246,7 @@ public class TBarSeriesTests
for (int i = 0; i < N; i++)
{
bars[i] = new TBar(i, i * 10.0, i * 10.0 + 5.0, i * 10.0 - 5.0, i * 10.0 + 2.0, i * 100.0);
bars[i] = new TBar(i, i * 10.0, (i * 10.0) + 5.0, (i * 10.0) - 5.0, (i * 10.0) + 2.0, i * 100.0);
}
series.AddRange(bars);
@@ -1254,6 +1254,6 @@ public class TBarSeriesTests
Assert.Equal(N, series.Count);
Assert.Equal(0, series[0].Time);
Assert.Equal(2.0, series[0].Close);
Assert.Equal((N - 1) * 10.0 + 2.0, series[N - 1].Close);
Assert.Equal(((N - 1) * 10.0) + 2.0, series[N - 1].Close);
}
}
+8 -8
View File
@@ -82,7 +82,7 @@ public class BiInputIndicatorBaseTests
var indicator = new Mae(5);
for (int i = 0; i < 4; i++)
{
indicator.Update(i * 10.0, i * 10.0 + 5.0);
indicator.Update(i * 10.0, (i * 10.0) + 5.0);
Assert.False(indicator.IsHot);
}
}
@@ -93,7 +93,7 @@ public class BiInputIndicatorBaseTests
var indicator = new Mae(5);
for (int i = 0; i < 5; i++)
{
indicator.Update(i * 10.0, i * 10.0 + 5.0);
indicator.Update(i * 10.0, (i * 10.0) + 5.0);
}
Assert.True(indicator.IsHot);
}
@@ -104,7 +104,7 @@ public class BiInputIndicatorBaseTests
var indicator = new Mae(3);
for (int i = 0; i < 20; i++)
{
indicator.Update(i * 10.0, i * 10.0 + 5.0);
indicator.Update(i * 10.0, (i * 10.0) + 5.0);
}
Assert.True(indicator.IsHot);
}
@@ -268,7 +268,7 @@ public class BiInputIndicatorBaseTests
for (int i = 0; i < 10; i++)
{
indicator.Update(i * 10.0, i * 10.0 + 5.0);
indicator.Update(i * 10.0, (i * 10.0) + 5.0);
}
double original = indicator.Last.Value;
@@ -360,7 +360,7 @@ public class BiInputIndicatorBaseTests
var indicator = new Mae(3);
for (int i = 0; i < 5; i++)
{
indicator.Update(i * 10.0, i * 10.0 + 5.0);
indicator.Update(i * 10.0, (i * 10.0) + 5.0);
}
Assert.True(indicator.IsHot);
@@ -563,7 +563,7 @@ public class BiInputIndicatorBaseTests
for (int i = 0; i < 20; i++)
{
actual.Add(now.AddMinutes(i), i * 10.0);
predicted.Add(now.AddMinutes(i), i * 10.0 + 5.0);
predicted.Add(now.AddMinutes(i), (i * 10.0) + 5.0);
}
var result = Mae.Batch(actual, predicted, 5);
@@ -603,7 +603,7 @@ public class BiInputIndicatorBaseTests
for (int i = 0; i < 10; i++)
{
actual.Add(now.AddMinutes(i), i * 10.0);
predicted.Add(now.AddMinutes(i), i * 10.0 + 3.0);
predicted.Add(now.AddMinutes(i), (i * 10.0) + 3.0);
}
var (results, indicator) = Mae.Calculate(actual, predicted, 5);
@@ -647,7 +647,7 @@ public class BiInputIndicatorBaseTests
{
var bar = gbm.Next();
actual[i] = bar.Close;
predicted[i] = bar.Close * 1.03 + 1.0;
predicted[i] = (bar.Close * 1.03) + 1.0;
}
// Streaming
-1
View File
@@ -536,7 +536,6 @@ public class TSeriesTests
Assert.Equal(3.0, series[2].Value);
}
[Fact]
public void GetEnumerator_ExplicitGenericInterface_Works()
{
@@ -100,7 +100,7 @@ public sealed class WclpriceValidationTests : IDisposable
var bar = new TBar(DateTime.UtcNow, open: 10.0, high: 20.0, low: 8.0, close: 16.0, volume: 1000);
var ind = new Wclprice();
var result = ind.Update(bar, isNew: true);
double expected = (20.0 + 8.0 + 2.0 * 16.0) / 4.0; // = 15.0
double expected = (20.0 + 8.0 + (2.0 * 16.0)) / 4.0; // = 15.0
Assert.Equal(expected, result.Value, 1e-12);
_output.WriteLine($"WCLPRICE formula: expected={expected}, actual={result.Value}: PASSED");
}
+3 -3
View File
@@ -305,7 +305,7 @@ public class AcpIndicatorTests
// Generate sine wave pattern
for (int i = 0; i < 200; 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));
indicator.HistoricalData.AddBar(now.AddMinutes(i), price, price + 1, price - 1, price);
indicator.ProcessUpdate(new UpdateArgs(UpdateReason.HistoricalBar));
}
@@ -324,7 +324,7 @@ public class AcpIndicatorTests
var now = DateTime.UtcNow;
for (int i = 0; i < 100; 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));
indicator.HistoricalData.AddBar(now.AddMinutes(i), price, price + 1, price - 1, price);
indicator.ProcessUpdate(new UpdateArgs(UpdateReason.HistoricalBar));
}
@@ -348,7 +348,7 @@ public class AcpIndicatorTests
// Add same data to both
for (int i = 0; i < 100; 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));
indicatorEnhanced.HistoricalData.AddBar(now.AddMinutes(i), price, price + 1, price - 1, price);
indicatorNormal.HistoricalData.AddBar(now.AddMinutes(i), price, price + 1, price - 1, price);
indicatorEnhanced.ProcessUpdate(new UpdateArgs(UpdateReason.HistoricalBar));
+5 -5
View File
@@ -169,7 +169,7 @@ public class AcpTests
// Build some history
for (int i = 0; i < 100; i++)
{
acp.Update(new TValue(DateTime.UtcNow.AddSeconds(i), 100.0 + Math.Sin(i * 0.1) * 10), isNew: true);
acp.Update(new TValue(DateTime.UtcNow.AddSeconds(i), 100.0 + (Math.Sin(i * 0.1) * 10)), isNew: true);
}
acp.Update(new TValue(DateTime.UtcNow.AddSeconds(100), 110.0), isNew: true);
@@ -237,7 +237,7 @@ public class AcpTests
// First run
for (int i = 0; i < 200; i++)
{
acp.Update(new TValue(DateTime.UtcNow.AddSeconds(i), 100.0 + Math.Sin(i * 0.1) * 10));
acp.Update(new TValue(DateTime.UtcNow.AddSeconds(i), 100.0 + (Math.Sin(i * 0.1) * 10)));
}
var firstResult = acp.Last.Value;
@@ -246,7 +246,7 @@ public class AcpTests
// Second run with same data
for (int i = 0; i < 200; i++)
{
acp.Update(new TValue(DateTime.UtcNow.AddSeconds(i), 100.0 + Math.Sin(i * 0.1) * 10));
acp.Update(new TValue(DateTime.UtcNow.AddSeconds(i), 100.0 + (Math.Sin(i * 0.1) * 10)));
}
var secondResult = acp.Last.Value;
@@ -431,7 +431,7 @@ public class AcpTests
for (int i = 0; i < 200; i++)
{
source.Add(new TValue(DateTime.UtcNow.AddSeconds(i), 100.0 + Math.Sin(i * 0.1) * 10));
source.Add(new TValue(DateTime.UtcNow.AddSeconds(i), 100.0 + (Math.Sin(i * 0.1) * 10)));
}
Assert.True(acp.IsHot);
@@ -447,7 +447,7 @@ public class AcpTests
for (int i = 0; i < 300; i++)
{
source.Add(new TValue(DateTime.UtcNow.AddSeconds(i), 100.0 + Math.Sin(i * 0.1) * 10));
source.Add(new TValue(DateTime.UtcNow.AddSeconds(i), 100.0 + (Math.Sin(i * 0.1) * 10)));
}
// Both should have values
@@ -122,7 +122,7 @@ public class CcorIndicatorTests
var now = DateTime.UtcNow;
for (int i = 0; i < 30; i++)
{
double price = 100 + 5 * Math.Sin(2 * Math.PI * i / 20.0);
double price = 100 + (5 * Math.Sin(2 * Math.PI * i / 20.0));
indicator.HistoricalData.AddBar(now.AddMinutes(i), price, price + 2, price - 2, price + 1);
indicator.ProcessUpdate(new UpdateArgs(UpdateReason.HistoricalBar));
}
+1 -1
View File
@@ -488,7 +488,7 @@ public class CcorTests
// Feed a perfect sine wave of the same period
for (int i = 0; i < 100; 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));
_ = ind.Update(new TValue(DateTime.UtcNow.AddMinutes(i), val));
}
+8 -8
View File
@@ -59,7 +59,7 @@ public sealed class Ccyc : AbstractBase
throw new ArgumentException("Alpha must be between 0 and 1 (exclusive).", nameof(alpha));
}
double halfAlpha = 1.0 - 0.5 * alpha;
double halfAlpha = 1.0 - (0.5 * alpha);
_chp = halfAlpha * halfAlpha;
double oneMinusAlpha = 1.0 - alpha;
_cfb1 = 2.0 * oneMinusAlpha;
@@ -125,7 +125,7 @@ public sealed class Ccyc : AbstractBase
double price0 = price;
// 4-tap FIR smoother: smooth = (x + 2*x1 + 2*x2 + x3) / 6
double smooth = (price0 + 2.0 * price1 + 2.0 * price2 + price3) / 6.0;
double smooth = (price0 + (2.0 * price1) + (2.0 * price2) + price3) / 6.0;
// Shift smooth history
double smooth2 = s.Smooth1;
@@ -136,13 +136,13 @@ public sealed class Ccyc : AbstractBase
if (count < 7)
{
// Bootstrap: second-difference of raw price
cycle = (price0 - 2.0 * price1 + price2) * 0.25;
cycle = (price0 - (2.0 * price1) + price2) * 0.25;
}
else
{
// Steady-state: 2-pole high-pass IIR on smoothed input
// cycle = c_hp * (smooth - 2*smooth1 + smooth2) + c_fb1*cycle1 + c_fb2*cycle2
double diff = smooth0 - 2.0 * smooth1 + smooth2;
double diff = smooth0 - (2.0 * smooth1) + smooth2;
cycle = Math.FusedMultiplyAdd(_chp, diff,
Math.FusedMultiplyAdd(_cfb1, s.Cycle1, _cfb2 * s.Cycle2));
}
@@ -240,7 +240,7 @@ public sealed class Ccyc : AbstractBase
return;
}
double halfAlpha = 1.0 - 0.5 * alpha;
double halfAlpha = 1.0 - (0.5 * alpha);
double chp = halfAlpha * halfAlpha;
double oneMinusAlpha = 1.0 - alpha;
double cfb1 = 2.0 * oneMinusAlpha;
@@ -263,7 +263,7 @@ public sealed class Ccyc : AbstractBase
price1 = price0;
price0 = val;
double smooth = (price0 + 2.0 * price1 + 2.0 * price2 + price3) / 6.0;
double smooth = (price0 + (2.0 * price1) + (2.0 * price2) + price3) / 6.0;
smooth2 = smooth1;
smooth1 = smooth0;
smooth0 = smooth;
@@ -272,11 +272,11 @@ public sealed class Ccyc : AbstractBase
int barNum = i + 1;
if (barNum < 7)
{
cycle = (price0 - 2.0 * price1 + price2) * 0.25;
cycle = (price0 - (2.0 * price1) + price2) * 0.25;
}
else
{
double diff = smooth0 - 2.0 * smooth1 + smooth2;
double diff = smooth0 - (2.0 * smooth1) + smooth2;
cycle = Math.FusedMultiplyAdd(chp, diff,
Math.FusedMultiplyAdd(cfb1, cycle1, cfb2 * cycle2));
}
@@ -116,7 +116,7 @@ public class CcycIndicatorTests
var now = DateTime.UtcNow;
for (int i = 0; i < 20; i++)
{
double price = 100 + 5 * Math.Sin(2 * Math.PI * i / 20.0);
double price = 100 + (5 * Math.Sin(2 * Math.PI * i / 20.0));
indicator.HistoricalData.AddBar(now.AddMinutes(i), price, price + 2, price - 2, price + 1);
indicator.ProcessUpdate(new UpdateArgs(UpdateReason.HistoricalBar));
}
+2 -2
View File
@@ -425,7 +425,7 @@ public class CcycTests
for (int i = 0; i < 200; i++)
{
double value = 100 + 10 * Math.Sin(2 * Math.PI * i / period);
double value = 100 + (10 * Math.Sin(2 * Math.PI * i / period));
ccyc.Update(new TValue(DateTime.UtcNow.AddDays(i), value), true);
}
@@ -459,7 +459,7 @@ public class CcycTests
double[] primeData = new double[50];
for (int i = 0; i < 50; i++)
{
primeData[i] = 100 + 5 * Math.Sin(2 * Math.PI * i / 20.0);
primeData[i] = 100 + (5 * Math.Sin(2 * Math.PI * i / 20.0));
}
ccyc.Prime(primeData.AsSpan());
@@ -41,7 +41,7 @@ public class CcycValidationTests
for (int i = 0; i < 500; i++)
{
ccyc.Update(new TValue(DateTime.UtcNow.AddMinutes(i), 100.0 + 0.5 * i), true);
ccyc.Update(new TValue(DateTime.UtcNow.AddMinutes(i), 100.0 + (0.5 * i)), true);
}
// After warmup, should be near zero since linear trend has no cycle component
@@ -58,7 +58,7 @@ public class CcycValidationTests
for (int i = 0; i < 200; i++)
{
double value = 100 + 10 * Math.Sin(2 * Math.PI * i / period);
double value = 100 + (10 * Math.Sin(2 * Math.PI * i / period));
ccyc.Update(new TValue(DateTime.UtcNow.AddMinutes(i), value), true);
}
@@ -80,7 +80,7 @@ public class CcycValidationTests
for (int i = 0; i < 300; i++)
{
double value = 100 + 10 * Math.Sin(2 * Math.PI * i / period);
double value = 100 + (10 * Math.Sin(2 * Math.PI * i / period));
var r = ccyc.Update(new TValue(DateTime.UtcNow.AddMinutes(i), value), true);
if (i > 20 && prev * r.Value < 0 && prev != 0)
@@ -169,7 +169,7 @@ public class CcycValidationTests
double noiseVal = rng.Next().Close;
ccycNoise.Update(new TValue(DateTime.UtcNow.AddMinutes(i), noiseVal), true);
double sineVal = 100 + 10 * Math.Sin(2 * Math.PI * i / 20.0);
double sineVal = 100 + (10 * Math.Sin(2 * Math.PI * i / 20.0));
var sineResult = ccycSine.Update(new TValue(DateTime.UtcNow.AddMinutes(i), sineVal), true);
if (i > 30)
@@ -216,7 +216,7 @@ public class CcycValidationTests
for (int i = 0; i < 300; i++)
{
double value = 100 + 10 * Math.Sin(2 * Math.PI * i / 20.0);
double value = 100 + (10 * Math.Sin(2 * Math.PI * i / 20.0));
ccyc.Update(new TValue(DateTime.UtcNow.AddMinutes(i), value), true);
if (i > 20)
@@ -340,7 +340,7 @@ public class CcycValidationTests
for (int i = 0; i < 20; i++)
{
double value = 100 + 5 * Math.Sin(2 * Math.PI * i / 20.0);
double value = 100 + (5 * Math.Sin(2 * Math.PI * i / 20.0));
var r = ccyc.Update(new TValue(DateTime.UtcNow.AddMinutes(i), value), true);
results.Add(r.Value);
}
-2
View File
@@ -43,7 +43,6 @@ public sealed class Cg : AbstractBase
private double _p_weightedSum;
private double _p_sum;
public override bool IsHot => _buffer.IsFull;
/// <summary>
@@ -112,7 +111,6 @@ public sealed class Cg : AbstractBase
// after each update (or track differential updates which is complex)
RecalculateSums();
// Calculate CG
double cg = CalculateCg();
+1 -1
View File
@@ -262,7 +262,7 @@ public class CgIndicatorTests
var now = DateTime.UtcNow;
double[] closes = { 100, 102, 98, 105, 97, 110, 95, 108, 92, 115, 90, 120 };
double maxExpectedBound = (10 - 1) / 2.0 + 1.0; // Period-based bound with margin
double maxExpectedBound = ((10 - 1) / 2.0) + 1.0; // Period-based bound with margin
foreach (var close in closes)
{
+3 -3
View File
@@ -79,7 +79,7 @@ public class CgTests
var cg = new Cg(5);
for (int i = 0; i < 10; i++)
{
cg.Update(new TValue(DateTime.UtcNow.AddSeconds(i), 100 + i * 10));
cg.Update(new TValue(DateTime.UtcNow.AddSeconds(i), 100 + (i * 10)));
}
Assert.True(cg.Last.Value > 0, $"Expected positive CG, got {cg.Last.Value}");
}
@@ -91,7 +91,7 @@ public class CgTests
var cg = new Cg(5);
for (int i = 0; i < 10; i++)
{
cg.Update(new TValue(DateTime.UtcNow.AddSeconds(i), 200 - i * 10));
cg.Update(new TValue(DateTime.UtcNow.AddSeconds(i), 200 - (i * 10)));
}
Assert.True(cg.Last.Value < 0, $"Expected negative CG, got {cg.Last.Value}");
}
@@ -328,7 +328,7 @@ public class CgTests
// Generate and store values
for (int i = 0; i < 20; i++)
{
inputs.Add(new TValue(DateTime.UtcNow.AddSeconds(i), 100 + i * 0.5));
inputs.Add(new TValue(DateTime.UtcNow.AddSeconds(i), 100 + (i * 0.5)));
}
// First pass
+10 -10
View File
@@ -28,7 +28,7 @@ public class CgValidationTests
var gbm = new GBM(seed: 42);
var bars = gbm.Fetch(500, DateTime.UtcNow.Ticks, TimeSpan.FromMinutes(1));
double maxAbsValue = (period - 1) / 2.0 + 0.5; // Allow small margin
double maxAbsValue = ((period - 1) / 2.0) + 0.5; // Allow small margin
foreach (var bar in bars)
{
@@ -65,7 +65,7 @@ public class CgValidationTests
for (int i = 0; i < 50; i++)
{
double price = 100.0 + i * 1.0; // Linear uptrend
double price = 100.0 + (i * 1.0); // Linear uptrend
cg.Update(new TValue(DateTime.UtcNow.AddSeconds(i), price));
}
@@ -82,7 +82,7 @@ public class CgValidationTests
for (int i = 0; i < 50; i++)
{
double price = 200.0 - i * 1.0; // Linear downtrend
double price = 200.0 - (i * 1.0); // Linear downtrend
cg.Update(new TValue(DateTime.UtcNow.AddSeconds(i), price));
}
@@ -100,7 +100,7 @@ public class CgValidationTests
for (int i = 0; i < 50; i++)
{
double expPrice = 100.0 * Math.Exp(i * 0.02);
double linPrice = 100.0 + i * 2.0;
double linPrice = 100.0 + (i * 2.0);
cgExp.Update(new TValue(DateTime.UtcNow.AddSeconds(i), expPrice));
cgLin.Update(new TValue(DateTime.UtcNow.AddSeconds(i), linPrice));
}
@@ -120,7 +120,7 @@ public class CgValidationTests
// Generate sine wave to simulate price oscillation
for (int i = 0; i < 100; i++)
{
double price = 100.0 + 10.0 * Math.Sin(i * 0.2);
double price = 100.0 + (10.0 * Math.Sin(i * 0.2));
cg.Update(new TValue(DateTime.UtcNow.AddSeconds(i), price));
if (cg.IsHot)
{
@@ -162,9 +162,9 @@ public class CgValidationTests
// num = 1*10 + 2*12 + 3*11 + 4*13 + 5*15 = 10 + 24 + 33 + 52 + 75 = 194
// den = 10 + 12 + 11 + 13 + 15 = 61
// result = 194/61 - (5+1)/2 = 3.1803... - 3 = 0.1803...
double expectedNum = 1 * 10 + 2 * 12 + 3 * 11 + 4 * 13 + 5 * 15;
double expectedNum = (1 * 10) + (2 * 12) + (3 * 11) + (4 * 13) + (5 * 15);
double expectedDen = 10 + 12 + 11 + 13 + 15;
double expectedCg = (expectedNum / expectedDen) - (period + 1) / 2.0;
double expectedCg = (expectedNum / expectedDen) - ((period + 1) / 2.0);
var cg = new Cg(period);
for (int i = 0; i < prices.Length; i++)
@@ -287,7 +287,7 @@ public class CgValidationTests
Assert.True(double.IsFinite(cg.Last.Value));
// CG bounds check
double maxAbsValue = (period - 1) / 2.0 + 1.0;
double maxAbsValue = ((period - 1) / 2.0) + 1.0;
Assert.True(Math.Abs(cg.Last.Value) <= maxAbsValue,
$"CG with period {period} should be within ±{maxAbsValue}, got {cg.Last.Value}");
}
@@ -337,7 +337,7 @@ public class CgValidationTests
// Uptrend
for (int i = 0; i < 30; i++)
{
double price = 100.0 + i * 0.5;
double price = 100.0 + (i * 0.5);
cg.Update(new TValue(DateTime.UtcNow.AddSeconds(i), price));
prices.Add(price);
if (cg.IsHot)
@@ -349,7 +349,7 @@ public class CgValidationTests
// Plateau/slight decline
for (int i = 30; i < 50; i++)
{
double price = 115.0 - (i - 30) * 0.2;
double price = 115.0 - ((i - 30) * 0.2);
cg.Update(new TValue(DateTime.UtcNow.AddSeconds(i), price));
prices.Add(price);
cgValues.Add(cg.Last.Value);
+1 -1
View File
@@ -326,7 +326,7 @@ public class DspIndicatorTests
// Generate sine wave price pattern
for (int i = 0; i < 100; i++)
{
double price = 100.0 + 10.0 * Math.Sin(i * 0.1);
double price = 100.0 + (10.0 * Math.Sin(i * 0.1));
indicator.HistoricalData.AddBar(now.AddMinutes(i), price, price + 1, price - 1, price);
indicator.ProcessUpdate(new UpdateArgs(UpdateReason.HistoricalBar));
values.Add(indicator.LinesSeries[0].GetValue(0));
+3 -3
View File
@@ -103,7 +103,7 @@ public class DspTests
for (int i = 0; i < 100; i++)
{
double price = 100.0 + i * 1.0;
double price = 100.0 + (i * 1.0);
dsp.Update(new TValue(DateTime.UtcNow.AddSeconds(i), price));
}
@@ -118,7 +118,7 @@ public class DspTests
for (int i = 0; i < 100; i++)
{
double price = 200.0 - i * 1.0;
double price = 200.0 - (i * 1.0);
dsp.Update(new TValue(DateTime.UtcNow.AddSeconds(i), price));
}
@@ -414,7 +414,7 @@ public class DspTests
for (int i = 0; i < 100; i++)
{
source.Add(new TValue(DateTime.UtcNow.AddSeconds(i), 100.0 + Math.Sin(i * 0.1) * 10));
source.Add(new TValue(DateTime.UtcNow.AddSeconds(i), 100.0 + (Math.Sin(i * 0.1) * 10)));
}
// Both should have values
+4 -4
View File
@@ -69,7 +69,7 @@ public class DspValidationTests
// Generate sine wave to simulate price oscillation
for (int i = 0; i < 200; i++)
{
double price = 100.0 + 10.0 * Math.Sin(i * 0.1);
double price = 100.0 + (10.0 * Math.Sin(i * 0.1));
dsp.Update(new TValue(DateTime.UtcNow.AddSeconds(i), price));
if (dsp.IsHot)
{
@@ -310,7 +310,7 @@ public class DspValidationTests
for (int i = 0; i < 100; i++)
{
double price = 0.0001 + i * 0.00001;
double price = 0.0001 + (i * 0.00001);
dsp.Update(new TValue(DateTime.UtcNow.AddSeconds(i), price));
}
@@ -325,7 +325,7 @@ public class DspValidationTests
for (int i = 0; i < 100; i++)
{
double price = 1e10 + i * 1e8;
double price = 1e10 + (i * 1e8);
dsp.Update(new TValue(DateTime.UtcNow.AddSeconds(i), price));
}
@@ -363,7 +363,7 @@ public class DspValidationTests
// Strong uptrend with some noise
for (int i = 0; i < 300; i++)
{
double trend = 100.0 + i * 0.5;
double trend = 100.0 + (i * 0.5);
double noise = Math.Sin(i * 0.3) * 2.0;
double price = trend + noise;
dsp.Update(new TValue(DateTime.UtcNow.AddSeconds(i), price));
+2 -2
View File
@@ -185,7 +185,7 @@ public sealed class Ebsw : AbstractBase
double wave = (filt0 + filt1 + filt2) / 3.0;
// Power: 3-bar average of squared filtered values
double pwr = (filt0 * filt0 + filt1 * filt1 + filt2 * filt2) / 3.0;
double pwr = ((filt0 * filt0) + (filt1 * filt1) + (filt2 * filt2)) / 3.0;
// Automatic gain control: normalize by RMS, clamp to [-1, +1]
double sineWave = pwr > 0 ? wave / Math.Sqrt(pwr) : 0;
@@ -326,7 +326,7 @@ public sealed class Ebsw : AbstractBase
double wave = (filt0 + filt1 + filt2) / 3.0;
// Power
double pwr = (filt0 * filt0 + filt1 * filt1 + filt2 * filt2) / 3.0;
double pwr = ((filt0 * filt0) + (filt1 * filt1) + (filt2 * filt2)) / 3.0;
// AGC normalization
double sineWave = pwr > 0 ? wave / Math.Sqrt(pwr) : 0;
@@ -316,7 +316,7 @@ public class EbswIndicatorTests
// Add varying price bars
for (int i = 0; i < 100; i++)
{
double price = 100 + 20 * Math.Sin(i * 0.2);
double price = 100 + (20 * Math.Sin(i * 0.2));
indicator.HistoricalData.AddBar(now.AddMinutes(i), price, price + 2, price - 2, price);
indicator.ProcessUpdate(new UpdateArgs(UpdateReason.HistoricalBar));
@@ -338,7 +338,7 @@ public class EbswIndicatorTests
// Generate sine wave price pattern
for (int i = 0; i < 200; i++)
{
double price = 100.0 + 10.0 * Math.Sin(i * 0.1);
double price = 100.0 + (10.0 * Math.Sin(i * 0.1));
indicator.HistoricalData.AddBar(now.AddMinutes(i), price, price + 1, price - 1, price);
indicator.ProcessUpdate(new UpdateArgs(UpdateReason.HistoricalBar));
values.Add(indicator.LinesSeries[0].GetValue(0));
@@ -364,7 +364,7 @@ public class EbswIndicatorTests
// Generate sine wave price pattern
for (int i = 0; i < 200; i++)
{
double price = 100.0 + 10.0 * Math.Sin(i * 0.15);
double price = 100.0 + (10.0 * Math.Sin(i * 0.15));
indicator.HistoricalData.AddBar(now.AddMinutes(i), price, price + 1, price - 1, price);
indicator.ProcessUpdate(new UpdateArgs(UpdateReason.HistoricalBar));
values.Add(indicator.LinesSeries[0].GetValue(0));
+5 -5
View File
@@ -137,7 +137,7 @@ public class EbswTests
for (int i = 0; i < 200; i++)
{
double price = 100.0 + 10.0 * Math.Sin(i * frequency);
double price = 100.0 + (10.0 * Math.Sin(i * frequency));
ebsw.Update(new TValue(DateTime.UtcNow.AddSeconds(i), price));
}
@@ -235,7 +235,7 @@ public class EbswTests
// First run
for (int i = 0; i < 100; i++)
{
ebsw.Update(new TValue(DateTime.UtcNow.AddSeconds(i), 100.0 + Math.Sin(i * 0.1) * 10));
ebsw.Update(new TValue(DateTime.UtcNow.AddSeconds(i), 100.0 + (Math.Sin(i * 0.1) * 10)));
}
var firstResult = ebsw.Last.Value;
@@ -244,7 +244,7 @@ public class EbswTests
// Second run with same data
for (int i = 0; i < 100; i++)
{
ebsw.Update(new TValue(DateTime.UtcNow.AddSeconds(i), 100.0 + Math.Sin(i * 0.1) * 10));
ebsw.Update(new TValue(DateTime.UtcNow.AddSeconds(i), 100.0 + (Math.Sin(i * 0.1) * 10)));
}
var secondResult = ebsw.Last.Value;
@@ -451,7 +451,7 @@ public class EbswTests
for (int i = 0; i < 100; i++)
{
source.Add(new TValue(DateTime.UtcNow.AddSeconds(i), 100.0 + Math.Sin(i * 0.1) * 10));
source.Add(new TValue(DateTime.UtcNow.AddSeconds(i), 100.0 + (Math.Sin(i * 0.1) * 10)));
}
Assert.True(ebsw.IsHot);
@@ -467,7 +467,7 @@ public class EbswTests
for (int i = 0; i < 200; i++)
{
source.Add(new TValue(DateTime.UtcNow.AddSeconds(i), 100.0 + Math.Sin(i * 0.1) * 10));
source.Add(new TValue(DateTime.UtcNow.AddSeconds(i), 100.0 + (Math.Sin(i * 0.1) * 10)));
}
// Both should have values
@@ -89,7 +89,7 @@ public class EbswValidationTests
// Generate sine wave to simulate price oscillation
for (int i = 0; i < 200; i++)
{
double price = 100.0 + 10.0 * Math.Sin(i * 0.1);
double price = 100.0 + (10.0 * Math.Sin(i * 0.1));
ebsw.Update(new TValue(DateTime.UtcNow.AddSeconds(i), price));
if (ebsw.IsHot)
{
@@ -186,7 +186,7 @@ public class EbswValidationTests
// Larger amplitude oscillation to ensure EBSW detects cycles
for (int i = 0; i < 300; i++)
{
double trend = 100.0 + i * 0.5;
double trend = 100.0 + (i * 0.5);
double oscillation = Math.Sin(i * 0.15) * 10.0; // Larger amplitude, longer period
double price = trend + oscillation;
ebsw.Update(new TValue(DateTime.UtcNow.AddSeconds(i), price));
@@ -252,7 +252,7 @@ public class EbswValidationTests
double frequency = 2.0 * Math.PI / 40.0;
for (int i = 0; i < 500; i++)
{
double price = 100.0 + 10.0 * Math.Sin(i * frequency);
double price = 100.0 + (10.0 * Math.Sin(i * frequency));
ebsw.Update(new TValue(DateTime.UtcNow.AddSeconds(i), price));
if (ebsw.IsHot)
{
@@ -405,7 +405,7 @@ public class EbswValidationTests
for (int i = 0; i < 100; i++)
{
double price = 0.0001 + i * 0.00001;
double price = 0.0001 + (i * 0.00001);
ebsw.Update(new TValue(DateTime.UtcNow.AddSeconds(i), price));
}
@@ -421,7 +421,7 @@ public class EbswValidationTests
for (int i = 0; i < 100; i++)
{
double price = 1e10 + i * 1e8;
double price = 1e10 + (i * 1e8);
ebsw.Update(new TValue(DateTime.UtcNow.AddSeconds(i), price));
}
+6 -6
View File
@@ -162,10 +162,10 @@ public sealed class Homod : AbstractBase
double price0 = price;
// Calculate bandwidth based on smooth period
double bandwidth = 0.075 * s.SmoothPeriod + 0.54;
double bandwidth = (0.075 * s.SmoothPeriod) + 0.54;
// 4-bar weighted moving average: (4*p0 + 3*p1 + 2*p2 + p3) / 10
double smoothPrice = (4.0 * price0 + 3.0 * price1 + 2.0 * price2 + price3) / 10.0;
double smoothPrice = ((4.0 * price0) + (3.0 * price1) + (2.0 * price2) + price3) / 10.0;
// Shift smooth price history
double sp6 = s.Sp5;
@@ -177,7 +177,7 @@ public sealed class Homod : AbstractBase
double sp0 = smoothPrice;
// Hilbert Transform detrender: coefficients [0.0962, 0, 0.5769, 0, -0.5769, 0, -0.0962] * bandwidth
double detrender = (0.0962 * sp0 + 0.5769 * sp2 - 0.5769 * sp4 - 0.0962 * sp6) * bandwidth;
double detrender = ((0.0962 * sp0) + (0.5769 * sp2) - (0.5769 * sp4) - (0.0962 * sp6)) * bandwidth;
// Shift detrender history
double det6 = s.Det5;
@@ -189,7 +189,7 @@ public sealed class Homod : AbstractBase
double det0 = detrender;
// Q1 via Hilbert Transform of detrender
double q1 = (0.0962 * det0 + 0.5769 * det2 - 0.5769 * det4 - 0.0962 * det6) * bandwidth;
double q1 = ((0.0962 * det0) + (0.5769 * det2) - (0.5769 * det4) - (0.0962 * det6)) * bandwidth;
// I1 is detrender delayed by 3 bars
double i1 = det3;
@@ -213,10 +213,10 @@ public sealed class Homod : AbstractBase
double q1_0 = q1;
// JI = Hilbert Transform of I1
double ji = (0.0962 * i1_0 + 0.5769 * i1_2 - 0.5769 * i1_4 - 0.0962 * i1_6) * bandwidth;
double ji = ((0.0962 * i1_0) + (0.5769 * i1_2) - (0.5769 * i1_4) - (0.0962 * i1_6)) * bandwidth;
// JQ = Hilbert Transform of Q1
double jq = (0.0962 * q1_0 + 0.5769 * q1_2 - 0.5769 * q1_4 - 0.0962 * q1_6) * bandwidth;
double jq = ((0.0962 * q1_0) + (0.5769 * q1_2) - (0.5769 * q1_4) - (0.0962 * q1_6)) * bandwidth;
// Calculate I2 and Q2 (phasor rotation)
double i2Raw = i1 - jq;
@@ -269,7 +269,7 @@ public class HomodIndicatorTests
// Generate sine wave pattern
for (int i = 0; i < 200; 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));
indicator.HistoricalData.AddBar(now.AddMinutes(i), price, price + 1, price - 1, price);
indicator.ProcessUpdate(new UpdateArgs(UpdateReason.HistoricalBar));
}
@@ -309,7 +309,7 @@ public class HomodIndicatorTests
for (int i = 0; i < 100; i++)
{
double price = 100.0 + i * 0.5; // Trending up
double price = 100.0 + (i * 0.5); // Trending up
indicator.HistoricalData.AddBar(now.AddMinutes(i), price, price + 1, price - 1, price);
indicator.ProcessUpdate(new UpdateArgs(UpdateReason.HistoricalBar));
}
+5 -5
View File
@@ -146,7 +146,7 @@ public class HomodTests
// Build some history
for (int i = 0; i < 100; i++)
{
homod.Update(new TValue(DateTime.UtcNow.AddSeconds(i), 100.0 + Math.Sin(i * 0.1) * 10), isNew: true);
homod.Update(new TValue(DateTime.UtcNow.AddSeconds(i), 100.0 + (Math.Sin(i * 0.1) * 10)), isNew: true);
}
homod.Update(new TValue(DateTime.UtcNow.AddSeconds(100), 110.0), isNew: true);
@@ -213,7 +213,7 @@ public class HomodTests
// First run
for (int i = 0; i < 200; i++)
{
homod.Update(new TValue(DateTime.UtcNow.AddSeconds(i), 100.0 + Math.Sin(i * 0.1) * 10));
homod.Update(new TValue(DateTime.UtcNow.AddSeconds(i), 100.0 + (Math.Sin(i * 0.1) * 10)));
}
var firstResult = homod.Last.Value;
@@ -222,7 +222,7 @@ public class HomodTests
// Second run with same data
for (int i = 0; i < 200; i++)
{
homod.Update(new TValue(DateTime.UtcNow.AddSeconds(i), 100.0 + Math.Sin(i * 0.1) * 10));
homod.Update(new TValue(DateTime.UtcNow.AddSeconds(i), 100.0 + (Math.Sin(i * 0.1) * 10)));
}
var secondResult = homod.Last.Value;
@@ -407,7 +407,7 @@ public class HomodTests
for (int i = 0; i < 200; i++)
{
source.Add(new TValue(DateTime.UtcNow.AddSeconds(i), 100.0 + Math.Sin(i * 0.1) * 10));
source.Add(new TValue(DateTime.UtcNow.AddSeconds(i), 100.0 + (Math.Sin(i * 0.1) * 10)));
}
Assert.True(homod.IsHot);
@@ -423,7 +423,7 @@ public class HomodTests
for (int i = 0; i < 300; i++)
{
source.Add(new TValue(DateTime.UtcNow.AddSeconds(i), 100.0 + Math.Sin(i * 0.1) * 10));
source.Add(new TValue(DateTime.UtcNow.AddSeconds(i), 100.0 + (Math.Sin(i * 0.1) * 10)));
}
// Both should have values
@@ -110,7 +110,7 @@ public class HomodValidationTests
// Generate 500 bars of sine wave
for (int i = 0; i < 500; i++)
{
double value = 100.0 + 10.0 * Math.Sin(2.0 * Math.PI * i / knownPeriod);
double value = 100.0 + (10.0 * Math.Sin(2.0 * Math.PI * i / knownPeriod));
homod.Update(new TValue(DateTime.UtcNow.AddSeconds(i), value));
}
@@ -131,7 +131,7 @@ public class HomodValidationTests
// Generate sine wave with specified period
for (int i = 0; i < 600; i++)
{
double value = 100.0 + 10.0 * Math.Sin(2.0 * Math.PI * i / period);
double value = 100.0 + (10.0 * Math.Sin(2.0 * Math.PI * i / period));
homod.Update(new TValue(DateTime.UtcNow.AddSeconds(i), value));
}
@@ -282,7 +282,7 @@ public class HomodValidationTests
// Strong uptrend with no cyclical component
for (int i = 0; i < 500; i++)
{
double value = 100.0 + i * 0.5;
double value = 100.0 + (i * 0.5);
var result = homod.Update(new TValue(DateTime.UtcNow.AddSeconds(i), value));
Assert.True(double.IsFinite(result.Value));
}
@@ -339,7 +339,7 @@ public class HomodValidationTests
// Generate synthetic cycle
for (int i = 0; i < 200; i++)
{
double value = 100.0 + 10.0 * Math.Sin(2.0 * Math.PI * i / 20);
double value = 100.0 + (10.0 * Math.Sin(2.0 * Math.PI * i / 20));
homod.Update(new TValue(DateTime.UtcNow.AddSeconds(i), value));
}
@@ -347,7 +347,7 @@ public class HomodValidationTests
var postWarmupValues = new List<double>();
for (int i = 200; i < 400; i++)
{
double value = 100.0 + 10.0 * Math.Sin(2.0 * Math.PI * i / 20);
double value = 100.0 + (10.0 * Math.Sin(2.0 * Math.PI * i / 20));
var result = homod.Update(new TValue(DateTime.UtcNow.AddSeconds(i), value));
postWarmupValues.Add(result.Value);
}
+5 -5
View File
@@ -139,8 +139,8 @@ public sealed class HtDcperiod : 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];
@@ -164,8 +164,8 @@ public sealed class HtDcperiod : 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];
@@ -289,7 +289,7 @@ public sealed class HtDcperiod : 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;
@@ -178,7 +178,7 @@ public class HtDcperiodIndicatorTests
// HT_DCPERIOD needs significant warmup - feed sinusoidal data
for (int i = 0; i < 100; i++)
{
double price = 100 + 10 * Math.Sin(i * 0.3);
double price = 100 + (10 * Math.Sin(i * 0.3));
indicator.HistoricalData.AddBar(
time: now.AddMinutes(i),
open: price - 1,
@@ -339,7 +339,7 @@ public class HtDcperiodIndicatorTests
// Feed sinusoidal data with known period (~21 bars)
for (int i = 0; i < 100; i++)
{
double price = 100 + 10 * Math.Sin(2 * Math.PI * i / 21.0);
double price = 100 + (10 * Math.Sin(2 * Math.PI * i / 21.0));
indicator.HistoricalData.AddBar(
time: now.AddMinutes(i),
open: price - 0.5,
@@ -27,7 +27,7 @@ public class HtDcperiodTests
// Feed data through publisher
for (int i = 0; i < 40; 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);
@@ -144,7 +144,7 @@ public class HtDcperiodTests
// Prime with data
for (int i = 0; i < 50; 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);
@@ -203,7 +203,7 @@ public class HtDcperiodTests
// Feed valid data to warm up
for (int i = 0; i < 50; 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);
@@ -221,7 +221,7 @@ public class HtDcperiodTests
for (int i = 0; i < 50; 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(50), double.PositiveInfinity));
@@ -255,7 +255,7 @@ public class HtDcperiodTests
// First use
for (int i = 0; i < 50; 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);
var firstResult = ht.Last.Value;
@@ -266,7 +266,7 @@ public class HtDcperiodTests
for (int i = 0; i < 50; 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.Equal(firstResult, ht.Last.Value);
@@ -387,7 +387,7 @@ public class HtDcperiodTests
var values = new double[50];
for (int i = 0; i < 50; 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));
@@ -443,7 +443,7 @@ public class HtDcperiodTests
for (int i = 0; i < 300; i++)
{
ht.Update(new TValue(now.AddMinutes(i), 100 + 10 * Math.Sin(omega * i)));
ht.Update(new TValue(now.AddMinutes(i), 100 + (10 * Math.Sin(omega * i))));
}
// After sufficient data, the detected period should be
+8 -8
View File
@@ -142,8 +142,8 @@ public sealed class HtPhasor : 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];
@@ -167,8 +167,8 @@ public sealed class HtPhasor : 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];
@@ -178,8 +178,8 @@ public sealed class HtPhasor : 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;
@@ -228,7 +228,7 @@ public sealed class HtPhasor : AbstractBase
double p2 = Get(priceHistory, historyIdx, 2);
double p3 = Get(priceHistory, historyIdx, 3);
double smoothedValue = (4.0 * p0 + 3.0 * p1 + 2.0 * p2 + p3) * 0.1;
double smoothedValue = ((4.0 * p0) + (3.0 * p1) + (2.0 * p2) + p3) * 0.1;
s.PeriodWMASub = p0 + p1 + p2 + p3;
s.PeriodWMASum = smoothedValue * 10.0;
@@ -306,7 +306,7 @@ public sealed class HtPhasor : AbstractBase
double prevQ2 = s.PrevQ2;
double period = s.Period;
double adjustedPrevPeriod = 0.075 * period + 0.54;
double adjustedPrevPeriod = (0.075 * period) + 0.54;
_smoothPrice[s.SmoothPriceIdx] = smoothedValue;
double q2, i2;
+3 -3
View File
@@ -54,7 +54,7 @@ public class HtPhasorTests
for (int i = 0; i < 100; i++)
{
phasor.Update(new TValue(DateTime.UtcNow.AddSeconds(i), 100.0 + Math.Sin(i * 0.1) * 5));
phasor.Update(new TValue(DateTime.UtcNow.AddSeconds(i), 100.0 + (Math.Sin(i * 0.1) * 5)));
}
Assert.True(double.IsFinite(phasor.Quadrature));
@@ -126,7 +126,7 @@ public class HtPhasorTests
for (int i = 0; i < 50; i++)
{
source.Add(new TValue(DateTime.UtcNow.AddSeconds(i), 100.0 + Math.Sin(i * 0.2) * 10));
source.Add(new TValue(DateTime.UtcNow.AddSeconds(i), 100.0 + (Math.Sin(i * 0.2) * 10)));
}
Assert.True(phasor.IsHot);
@@ -238,7 +238,7 @@ public class HtPhasorTests
double[] data = new double[50];
for (int i = 0; i < 50; i++)
{
data[i] = 100.0 + Math.Sin(i * 0.3) * 10;
data[i] = 100.0 + (Math.Sin(i * 0.3) * 10);
}
phasor1.Prime(data);
@@ -207,7 +207,7 @@ public class HtSineIndicatorTests
// Add enough bars to pass warmup (63 bars)
for (int i = 0; i < 70; i++)
{
double price = 100.0 + 10.0 * Math.Sin(i * 0.15);
double price = 100.0 + (10.0 * Math.Sin(i * 0.15));
indicator.HistoricalData.AddBar(now.AddMinutes(i), price, price + 1, price - 1, price);
indicator.ProcessUpdate(new UpdateArgs(UpdateReason.HistoricalBar));
}
@@ -231,7 +231,7 @@ public class HtSineIndicatorTests
// Generate enough data
for (int i = 0; i < 100; i++)
{
double price = 100.0 + 10.0 * Math.Sin(i * 0.15);
double price = 100.0 + (10.0 * Math.Sin(i * 0.15));
indicator.HistoricalData.AddBar(now.AddMinutes(i), price, price + 1, price - 1, price);
indicator.ProcessUpdate(new UpdateArgs(UpdateReason.HistoricalBar));
}
@@ -260,7 +260,7 @@ public class HtSineIndicatorTests
// Generate cyclic price pattern
for (int i = 0; i < 100; i++)
{
double price = 100.0 + 10.0 * Math.Sin(i * 0.15);
double price = 100.0 + (10.0 * Math.Sin(i * 0.15));
indicator.HistoricalData.AddBar(now.AddMinutes(i), price, price + 1, price - 1, price);
indicator.ProcessUpdate(new UpdateArgs(UpdateReason.HistoricalBar));
sineValues.Add(indicator.LinesSeries[0].GetValue(0));
+8 -8
View File
@@ -91,7 +91,7 @@ public class HtSineTests
for (int i = 0; i < 100; i++)
{
htSine.Update(new TValue(DateTime.UtcNow.AddSeconds(i), 100.0 + Math.Sin(i * 0.1) * 10));
htSine.Update(new TValue(DateTime.UtcNow.AddSeconds(i), 100.0 + (Math.Sin(i * 0.1) * 10)));
}
Assert.True(double.IsFinite(htSine.LeadSine));
@@ -106,7 +106,7 @@ public class HtSineTests
const int period = 20;
for (int i = 0; i < 500; i++)
{
double price = 100.0 + 10.0 * Math.Sin(2.0 * Math.PI * i / period);
double price = 100.0 + (10.0 * Math.Sin(2.0 * Math.PI * i / period));
htSine.Update(new TValue(DateTime.UtcNow.AddSeconds(i), price));
}
@@ -128,7 +128,7 @@ public class HtSineTests
// Build some history first
for (int i = 0; i < 100; i++)
{
htSine.Update(new TValue(DateTime.UtcNow.AddSeconds(i), 100.0 + i * 0.1), isNew: true);
htSine.Update(new TValue(DateTime.UtcNow.AddSeconds(i), 100.0 + (i * 0.1)), isNew: true);
}
var first = htSine.Last.Value;
@@ -147,7 +147,7 @@ public class HtSineTests
// Build some history first
for (int i = 0; i < 100; i++)
{
htSine.Update(new TValue(DateTime.UtcNow.AddSeconds(i), 100.0 + i * 0.1), isNew: true);
htSine.Update(new TValue(DateTime.UtcNow.AddSeconds(i), 100.0 + (i * 0.1)), isNew: true);
}
htSine.Update(new TValue(DateTime.UtcNow.AddSeconds(100), 150.0), isNew: true);
@@ -168,7 +168,7 @@ public class HtSineTests
// Build some history
for (int i = 0; i < 100; i++)
{
htSine.Update(new TValue(DateTime.UtcNow.AddSeconds(i), 100.0 + i * 0.1), isNew: true);
htSine.Update(new TValue(DateTime.UtcNow.AddSeconds(i), 100.0 + (i * 0.1)), isNew: true);
}
// Add a new bar
@@ -215,7 +215,7 @@ public class HtSineTests
// First run
for (int i = 0; i < 100; i++)
{
double price = 100.0 + 10.0 * Math.Sin(i * 0.1);
double price = 100.0 + (10.0 * Math.Sin(i * 0.1));
htSine.Update(new TValue(DateTime.UtcNow.AddSeconds(i), price));
}
var firstResult = htSine.Last.Value;
@@ -225,7 +225,7 @@ public class HtSineTests
// Second run with same data
for (int i = 0; i < 100; i++)
{
double price = 100.0 + 10.0 * Math.Sin(i * 0.1);
double price = 100.0 + (10.0 * Math.Sin(i * 0.1));
htSine.Update(new TValue(DateTime.UtcNow.AddSeconds(i), price));
}
var secondResult = htSine.Last.Value;
@@ -412,7 +412,7 @@ public class HtSineTests
for (int i = 0; i < 100; i++)
{
source.Add(new TValue(DateTime.UtcNow.AddSeconds(i), 100.0 + Math.Sin(i * 0.1) * 10));
source.Add(new TValue(DateTime.UtcNow.AddSeconds(i), 100.0 + (Math.Sin(i * 0.1) * 10)));
}
Assert.True(htSine.IsHot);
@@ -247,7 +247,7 @@ public class SsfdspIndicatorTests
// Generate trending then ranging price pattern
for (int i = 0; i < 100; i++)
{
double price = 100.0 + 10.0 * Math.Sin(i * 0.15);
double price = 100.0 + (10.0 * Math.Sin(i * 0.15));
indicator.HistoricalData.AddBar(now.AddMinutes(i), price, price + 1, price - 1, price);
indicator.ProcessUpdate(new UpdateArgs(UpdateReason.HistoricalBar));
values.Add(indicator.LinesSeries[0].GetValue(0));
+3 -3
View File
@@ -103,7 +103,7 @@ public class SsfdspTests
for (int i = 0; i < 100; i++)
{
double price = 100.0 + i * 1.0;
double price = 100.0 + (i * 1.0);
ssfdsp.Update(new TValue(DateTime.UtcNow.AddSeconds(i), price));
}
@@ -118,7 +118,7 @@ public class SsfdspTests
for (int i = 0; i < 100; i++)
{
double price = 200.0 - i * 1.0;
double price = 200.0 - (i * 1.0);
ssfdsp.Update(new TValue(DateTime.UtcNow.AddSeconds(i), price));
}
@@ -423,7 +423,7 @@ public class SsfdspTests
for (int i = 0; i < 100; i++)
{
source.Add(new TValue(DateTime.UtcNow.AddSeconds(i), 100.0 + Math.Sin(i * 0.1) * 10));
source.Add(new TValue(DateTime.UtcNow.AddSeconds(i), 100.0 + (Math.Sin(i * 0.1) * 10)));
}
// Both should have values
@@ -159,7 +159,7 @@ public class SsfdspValidationTests
for (int i = 0; i < 200; i++)
{
double price = 100 + 10 * Math.Sin(frequency * i);
double price = 100 + (10 * Math.Sin(frequency * i));
ssfdsp.Update(new TValue(DateTime.UtcNow.AddSeconds(i), price));
if (i >= 80) // After warmup
{
@@ -337,7 +337,7 @@ public class SsfdspValidationTests
for (int i = 0; i < 1000; i++)
{
double price = 100 + 10 * Math.Sin(2 * Math.PI * i / 40);
double price = 100 + (10 * Math.Sin(2 * Math.PI * i / 40));
ssfdsp.Update(new TValue(DateTime.UtcNow.AddSeconds(i), price));
if (i >= 100) // After warmup
-2
View File
@@ -293,7 +293,6 @@ public sealed class Alligator : ITValuePublisher
return new TSeries(tList, vList);
}
/// <summary>
/// Initializes the indicator state using the provided bar series history.
/// </summary>
@@ -337,7 +336,6 @@ public sealed class Alligator : ITValuePublisher
return (results, indicator);
}
/// <summary>
/// Gets the Jaw period value.
/// </summary>
@@ -78,7 +78,7 @@ public sealed class AlligatorValidationTests : IDisposable
// Create strong uptrend
for (int i = 0; i < 100; i++)
{
double price = 100.0 + i * 2.0;
double price = 100.0 + (i * 2.0);
var bar = new TBar(DateTime.UtcNow.AddMinutes(i), price, price + 1, price - 1, price, 1000);
alligator.Update(bar);
}
-1
View File
@@ -642,5 +642,4 @@ public sealed class Amat : ITValuePublisher, IDisposable
TSeries results = amat.Update(source);
return (results, amat);
}
}
+4 -4
View File
@@ -83,7 +83,7 @@ public class AmatTests
// Feed rising prices to create bullish trend
for (int i = 0; i < 20; i++)
{
amat.Update(new TValue(DateTime.UtcNow, 100 + i * 2));
amat.Update(new TValue(DateTime.UtcNow, 100 + (i * 2)));
}
// Trend should be +1, -1, or 0
@@ -99,7 +99,7 @@ public class AmatTests
// Feed steadily rising prices
for (int i = 0; i < 50; i++)
{
amat.Update(new TValue(DateTime.UtcNow, 100 + i * 3));
amat.Update(new TValue(DateTime.UtcNow, 100 + (i * 3)));
}
// Should be bullish when fast EMA > slow EMA and both rising
@@ -121,7 +121,7 @@ public class AmatTests
// Feed steadily falling prices
for (int i = 0; i < 50; i++)
{
amat.Update(new TValue(DateTime.UtcNow, 200 - i * 3));
amat.Update(new TValue(DateTime.UtcNow, 200 - (i * 3)));
}
// Should be bearish when fast EMA < slow EMA and both falling
@@ -471,7 +471,7 @@ public class AmatTests
// Feed rising prices to create divergence
for (int i = 0; i < 30; i++)
{
amat.Update(new TValue(DateTime.UtcNow, 100 + i * 5));
amat.Update(new TValue(DateTime.UtcNow, 100 + (i * 5)));
}
// Strength should be positive when there's divergence
@@ -273,7 +273,7 @@ public sealed class AmatValidationTests : IDisposable
// Phase 2: Falling prices (reversal)
for (int i = 50; i < 150; i++)
{
double price = 150 - (i - 50) * 2; // Fall faster than rise
double price = 150 - ((i - 50) * 2); // Fall faster than rise
amat.Update(new TValue(time.AddMinutes(i), price));
}
double bearishTrend = amat.Last.Value;
-2
View File
@@ -240,7 +240,6 @@ public sealed class Chop : ITValuePublisher
return Math.Clamp(chop, 0.0, 100.0);
}
/// <summary>
/// Initializes the indicator state using the provided bar series history.
/// </summary>
@@ -282,5 +281,4 @@ public sealed class Chop : ITValuePublisher
TSeries results = indicator.Update(source);
return (results, indicator);
}
}
+1 -1
View File
@@ -34,7 +34,7 @@ public class ChopTests
// Generate trending bars: each bar higher than the last
for (int i = 0; i < 50; i++)
{
double basePrice = 100 + i * 2; // Strong uptrend
double basePrice = 100 + (i * 2); // Strong uptrend
bars.Add(new TBar(
time: DateTime.UtcNow.AddMinutes(i),
open: basePrice - 0.5,
@@ -74,7 +74,7 @@ public sealed class ChopValidationTests : IDisposable
for (int i = 0; i < 100; i++)
{
double price = 100.0 + i * 3.0; // Strong linear uptrend
double price = 100.0 + (i * 3.0); // Strong linear uptrend
var bar = new TBar(DateTime.UtcNow.AddMinutes(i), price, price + 0.5, price - 0.5, price, 1000);
chop.Update(bar);
}
@@ -95,7 +95,7 @@ public sealed class ChopValidationTests : IDisposable
for (int i = 0; i < 100; i++)
{
// Oscillating price with wide range but no trend
double price = 100.0 + 5.0 * Math.Sin(2.0 * Math.PI * i / 3.0);
double price = 100.0 + (5.0 * Math.Sin(2.0 * Math.PI * i / 3.0));
double high = price + 3.0;
double low = price - 3.0;
var bar = new TBar(DateTime.UtcNow.AddMinutes(i), price, high, low, price, 1000);
@@ -52,7 +52,7 @@ public sealed class HtTrendmodeIndicator : Indicator, IWatchlistIndicator
SourceType.HL2 => (GetPrice(PriceType.High) + GetPrice(PriceType.Low)) / 2,
SourceType.HLC3 => (GetPrice(PriceType.High) + GetPrice(PriceType.Low) + GetPrice(PriceType.Close)) / 3,
SourceType.OHLC4 => (GetPrice(PriceType.Open) + GetPrice(PriceType.High) + GetPrice(PriceType.Low) + GetPrice(PriceType.Close)) / 4,
SourceType.HLCC4 => (GetPrice(PriceType.High) + GetPrice(PriceType.Low) + 2 * GetPrice(PriceType.Close)) / 4,
SourceType.HLCC4 => (GetPrice(PriceType.High) + GetPrice(PriceType.Low) + (2 * GetPrice(PriceType.Close))) / 4,
_ => GetPrice(PriceType.Close)
};
+6 -6
View File
@@ -186,8 +186,8 @@ public sealed class HtTrendmode : 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];
@@ -211,8 +211,8 @@ public sealed class HtTrendmode : 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];
@@ -304,7 +304,7 @@ public sealed class HtTrendmode : 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;
@@ -488,7 +488,7 @@ public sealed class HtTrendmode : AbstractBase
double smaValue = (dcPeriodInt > 0) ? sumPrice / (double)dcPeriodInt : price;
// WMA smoothing of SMA: (4*current + 3*prev1 + 2*prev2 + prev3) / 10
double trendline = (4.0 * smaValue + 3.0 * s.ITrend1 + 2.0 * s.ITrend2 + s.ITrend3) / 10.0;
double trendline = ((4.0 * smaValue) + (3.0 * s.ITrend1) + (2.0 * s.ITrend2) + s.ITrend3) / 10.0;
s.ITrend3 = s.ITrend2;
s.ITrend2 = s.ITrend1;
s.ITrend1 = smaValue;
@@ -60,7 +60,7 @@ public class HtTrendmodeTests
// Feed data
for (int i = 0; i < 50; i++)
{
indicator.Update(new TValue(DateTime.UtcNow.AddMinutes(i), 100.0 + i * 0.5));
indicator.Update(new TValue(DateTime.UtcNow.AddMinutes(i), 100.0 + (i * 0.5)));
}
// TrendMode property should match output
@@ -76,7 +76,7 @@ public class HtTrendmodeTests
// Feed data
for (int i = 0; i < 50; i++)
{
indicator.Update(new TValue(DateTime.UtcNow.AddMinutes(i), 100.0 + Math.Sin(i * 0.2) * 10));
indicator.Update(new TValue(DateTime.UtcNow.AddMinutes(i), 100.0 + (Math.Sin(i * 0.2) * 10)));
}
// SmoothPeriod should be in valid range
@@ -93,7 +93,7 @@ public class HtTrendmodeTests
// Feed data
for (int i = 0; i < 50; i++)
{
indicator.Update(new TValue(DateTime.UtcNow.AddMinutes(i), 100.0 + Math.Sin(i * 0.3) * 8));
indicator.Update(new TValue(DateTime.UtcNow.AddMinutes(i), 100.0 + (Math.Sin(i * 0.3) * 8)));
}
// InstPeriod should be positive
@@ -109,7 +109,7 @@ public class HtTrendmodeTests
// Strong trend: monotonically increasing
for (int i = 0; i < 100; i++)
{
indicator.Update(new TValue(DateTime.UtcNow.AddMinutes(i), 100.0 + i * 2.0));
indicator.Update(new TValue(DateTime.UtcNow.AddMinutes(i), 100.0 + (i * 2.0)));
}
// With strong trend, inst_period should be larger → trend mode likely
@@ -126,7 +126,7 @@ public class HtTrendmodeTests
// Pure sinusoidal data (strong cycle)
for (int i = 0; i < 100; i++)
{
double value = 100.0 + Math.Sin(i * 0.4) * 10.0;
double value = 100.0 + (Math.Sin(i * 0.4) * 10.0);
indicator.Update(new TValue(DateTime.UtcNow.AddMinutes(i), value));
}
@@ -195,7 +195,7 @@ public class HtTrendmodeTests
for (int i = 0; i < 100; i++)
{
series.Add(DateTime.UtcNow.AddMinutes(i), 100.0 + Math.Sin(i * 0.2) * 10);
series.Add(DateTime.UtcNow.AddMinutes(i), 100.0 + (Math.Sin(i * 0.2) * 10));
}
var result = indicator.Update(series);
@@ -218,7 +218,7 @@ public class HtTrendmodeTests
for (int i = 0; i < input.Length; i++)
{
input[i] = 100.0 + Math.Sin(i * 0.15) * 8;
input[i] = 100.0 + (Math.Sin(i * 0.15) * 8);
}
HtTrendmode.Batch(input.AsSpan(), output.AsSpan());
@@ -238,7 +238,7 @@ public class HtTrendmodeTests
for (int i = 0; i < 100; i++)
{
series.Add(DateTime.UtcNow.AddMinutes(i), 100.0 + Math.Sin(i * 0.25) * 12);
series.Add(DateTime.UtcNow.AddMinutes(i), 100.0 + (Math.Sin(i * 0.25) * 12));
}
var result = HtTrendmode.Batch(series);
@@ -278,7 +278,7 @@ public class HtTrendmodeTests
for (int i = 0; i < 100; i++)
{
double value = 100.0 + Math.Sin(i * 0.2) * 10 + Math.Cos(i * 0.3) * 5;
double value = 100.0 + (Math.Sin(i * 0.2) * 10) + (Math.Cos(i * 0.3) * 5);
series.Add(DateTime.UtcNow.AddMinutes(i), value);
var result = streamingIndicator.Update(new TValue(DateTime.UtcNow.AddMinutes(i), value));
@@ -303,7 +303,7 @@ public class HtTrendmodeTests
double[] primeData = new double[70];
for (int i = 0; i < primeData.Length; i++)
{
primeData[i] = 100.0 + i * 0.5;
primeData[i] = 100.0 + (i * 0.5);
}
indicator.Prime(primeData);
@@ -174,7 +174,7 @@ public class IchimokuIndicatorTests
var now = DateTime.UtcNow;
for (int i = 0; i < 20; i++)
{
double basePrice = 100 + i * 2;
double basePrice = 100 + (i * 2);
indicator.HistoricalData.AddBar(now.AddMinutes(i), basePrice, basePrice + 5, basePrice - 5, basePrice);
var args = new UpdateArgs(UpdateReason.HistoricalBar);
indicator.ProcessUpdate(args);
+16 -16
View File
@@ -83,7 +83,7 @@ public class IchimokuTests
for (int i = 0; i < 52; i++)
{
var bar = new TBar(baseTime + i * 60000, 100 + i, 105 + i, 95 + i, 102 + i, 1000);
var bar = new TBar(baseTime + (i * 60000), 100 + i, 105 + i, 95 + i, 102 + i, 1000);
ichimoku.Update(bar);
}
@@ -241,18 +241,18 @@ public class IchimokuTests
// Add some initial bars
for (int i = 0; i < 3; 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 state before update (use underscore to indicate intentionally unused)
_ = ichimoku.Tenkan.Value;
// Update with new bar
ichimoku.Update(new TBar(baseTime + 3 * 60000, 110, 120, 100, 115, 1000), isNew: true);
ichimoku.Update(new TBar(baseTime + (3 * 60000), 110, 120, 100, 115, 1000), isNew: true);
double tenkanAfterNew = ichimoku.Tenkan.Value;
// Correct the bar (isNew=false) with different values
ichimoku.Update(new TBar(baseTime + 3 * 60000, 90, 95, 85, 90, 1000), isNew: false);
ichimoku.Update(new TBar(baseTime + (3 * 60000), 90, 95, 85, 90, 1000), isNew: false);
double tenkanAfterCorrection = ichimoku.Tenkan.Value;
// Values should differ based on the correction
@@ -268,17 +268,17 @@ public class IchimokuTests
// Fill buffer
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));
}
// First update
ichimoku.Update(new TBar(baseTime + 5 * 60000, 105, 110, 100, 105, 1000), isNew: true);
ichimoku.Update(new TBar(baseTime + (5 * 60000), 105, 110, 100, 105, 1000), isNew: true);
double firstTenkan = ichimoku.Tenkan.Value;
// Multiple corrections should converge
for (int i = 0; i < 3; i++)
{
ichimoku.Update(new TBar(baseTime + 5 * 60000, 105, 110, 100, 105, 1000), isNew: false);
ichimoku.Update(new TBar(baseTime + (5 * 60000), 105, 110, 100, 105, 1000), isNew: false);
}
Assert.Equal(firstTenkan, ichimoku.Tenkan.Value, Precision);
@@ -344,7 +344,7 @@ public class IchimokuTests
// Process some bars
for (int i = 0; i < 60; i++)
{
ichimoku.Update(new TBar(baseTime + i * 60000, 100 + i, 105 + i, 95 + i, 100 + i, 1000));
ichimoku.Update(new TBar(baseTime + (i * 60000), 100 + i, 105 + i, 95 + i, 100 + i, 1000));
}
Assert.True(ichimoku.IsHot);
@@ -368,7 +368,7 @@ public class IchimokuTests
// First use
for (int i = 0; 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));
}
double firstTenkan = ichimoku.Tenkan.Value;
@@ -378,7 +378,7 @@ public class IchimokuTests
for (int i = 0; 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));
}
Assert.Equal(firstTenkan, ichimoku.Tenkan.Value, Precision);
@@ -396,7 +396,7 @@ public class IchimokuTests
for (int i = 0; i < 60; i++)
{
source.Add(new TBar(baseTime + i * 60000, 100, 110, 90, 100, 1000));
source.Add(new TBar(baseTime + (i * 60000), 100, 110, 90, 100, 1000));
}
var (tenkan, kijun, senkouA, senkouB, chikou) = Ichimoku.Batch(source);
@@ -430,7 +430,7 @@ public class IchimokuTests
for (int i = 0; i < 20; i++)
{
source.Add(new TBar(baseTime + i * 60000, 100 + i, 110 + i, 90 + i, 100 + i, 1000));
source.Add(new TBar(baseTime + (i * 60000), 100 + i, 110 + i, 90 + i, 100 + i, 1000));
}
var (tenkan, _, _, _, _) = Ichimoku.Batch(source, 3, 5, 10, 5);
@@ -446,7 +446,7 @@ public class IchimokuTests
for (int i = 0; i < 60; i++)
{
source.Add(new TBar(baseTime + i * 60000, 100, 110, 90, 100, 1000));
source.Add(new TBar(baseTime + (i * 60000), 100, 110, 90, 100, 1000));
}
var (results, indicator) = Ichimoku.Calculate(source);
@@ -469,7 +469,7 @@ public class IchimokuTests
// Constant high=low=close=100
for (int i = 0; i < 10; i++)
{
ichimoku.Update(new TBar(baseTime + i * 60000, 100, 100, 100, 100, 1000));
ichimoku.Update(new TBar(baseTime + (i * 60000), 100, 100, 100, 100, 1000));
}
Assert.Equal(100.0, ichimoku.Tenkan.Value, Precision);
@@ -506,8 +506,8 @@ public class IchimokuTests
// Uptrend: increasing highs and lows
for (int i = 0; i < 15; i++)
{
double basePrice = 100 + i * 2;
ichimoku.Update(new TBar(baseTime + i * 60000, basePrice, basePrice + 5, basePrice - 5, basePrice, 1000));
double basePrice = 100 + (i * 2);
ichimoku.Update(new TBar(baseTime + (i * 60000), basePrice, basePrice + 5, basePrice - 5, basePrice, 1000));
}
// In uptrend, Tenkan should be above Kijun (faster vs slower)
+1 -1
View File
@@ -234,7 +234,7 @@ public sealed class Pfe : AbstractBase
_s = default;
_ps = default;
int warmupLength = Math.Min(source.Length, WarmupPeriod + _smoothPeriod * 3);
int warmupLength = Math.Min(source.Length, WarmupPeriod + (_smoothPeriod * 3));
int startIndex = source.Length - warmupLength;
// Seed LastValidValue
+2 -2
View File
@@ -507,8 +507,8 @@ public class QstickTests
for (int i = 0; i < 20; i++)
{
double open = 100.0 + i * 0.5;
double close = open + (i % 3 - 1); // varies between -1, 0, 1
double open = 100.0 + (i * 0.5);
double close = open + ((i % 3) - 1); // varies between -1, 0, 1
bars.Add(new TBar(time.AddMinutes(i).Ticks, open, open + 2, open - 1, close, 1000));
}
@@ -123,7 +123,7 @@ public sealed class QstickValidationTests : IDisposable
// Bar 2: diff = 3, EMA = alpha * 3 + (1-alpha) * 6-
qstick.Update(new TBar(time.AddMinutes(1).Ticks, 100.0, 108.0, 96.0, 103.0, 1000));
expectedEma = alpha * 3 + (1 - alpha) * expectedEma;
expectedEma = (alpha * 3) + ((1 - alpha) * expectedEma);
Assert.Equal(expectedEma, qstick.Last.Value, 10);
}

Some files were not shown because too many files have changed in this diff Show More