mirror of
https://github.com/mihakralj/QuanTAlib.git
synced 2026-08-19 19:18:05 +00:00
Merge branch 'main' of https://github.com/mihakralj/QuanTAlib
This commit is contained in:
@@ -111,7 +111,7 @@ public sealed class Hwc : AbstractBase
|
|||||||
_decayGamma = 1.0 - gamma;
|
_decayGamma = 1.0 - gamma;
|
||||||
_multiplier = multiplier;
|
_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;
|
WarmupPeriod = effectivePeriod;
|
||||||
Name = $"Hwc({alpha:F3},{beta:F3},{gamma:F3},{multiplier:F1})";
|
Name = $"Hwc({alpha:F3},{beta:F3},{gamma:F3},{multiplier:F1})";
|
||||||
_state = new State(double.NaN, 0, 0, 0, double.NaN, false);
|
_state = new State(double.NaN, 0, 0, 0, double.NaN, false);
|
||||||
@@ -179,7 +179,7 @@ public sealed class Hwc : AbstractBase
|
|||||||
double prevA = _state.A;
|
double prevA = _state.A;
|
||||||
|
|
||||||
// HWMA: F = α×src + (1−α)×(prevF + prevV + 0.5×prevA)
|
// 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);
|
double newF = Math.FusedMultiplyAdd(forecast, _decayAlpha, _alpha * val);
|
||||||
|
|
||||||
// V = β×(F − prevF) + (1−β)×(prevV + prevA)
|
// V = β×(F − prevF) + (1−β)×(prevV + prevA)
|
||||||
@@ -188,7 +188,7 @@ public sealed class Hwc : AbstractBase
|
|||||||
// A = γ×(V − prevV) + (1−γ)×prevA
|
// A = γ×(V − prevV) + (1−γ)×prevA
|
||||||
double newA = Math.FusedMultiplyAdd(prevA, _decayGamma, _gamma * (newV - prevV));
|
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
|
// Adaptive volatility filter: filt = α×(src − forecast)² + (1−α)×prevFilt
|
||||||
double err = val - forecast;
|
double err = val - forecast;
|
||||||
@@ -240,7 +240,7 @@ public sealed class Hwc : AbstractBase
|
|||||||
|
|
||||||
for (int i = 0; i < source.Length; i++)
|
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
|
else
|
||||||
{
|
{
|
||||||
double forecast = f + v + 0.5 * a;
|
double forecast = f + v + (0.5 * a);
|
||||||
double newF = Math.FusedMultiplyAdd(forecast, dA, alpha * val);
|
double newF = Math.FusedMultiplyAdd(forecast, dA, alpha * val);
|
||||||
double newV = Math.FusedMultiplyAdd(v + a, dB, beta * (newF - f));
|
double newV = Math.FusedMultiplyAdd(v + a, dB, beta * (newF - f));
|
||||||
double newA = Math.FusedMultiplyAdd(a, dG, gamma * (newV - v));
|
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;
|
double err = val - forecast;
|
||||||
filt = Math.FusedMultiplyAdd(err * err, alpha, filt * dA);
|
filt = Math.FusedMultiplyAdd(err * err, alpha, filt * dA);
|
||||||
|
|||||||
@@ -174,7 +174,7 @@ public sealed class HwcTests
|
|||||||
// Low volatility: small oscillation
|
// Low volatility: small oscillation
|
||||||
indCalm.Update(new TValue(DateTime.UtcNow.AddMinutes(i), 100.0 + Math.Sin(i * 0.1)));
|
indCalm.Update(new TValue(DateTime.UtcNow.AddMinutes(i), 100.0 + Math.Sin(i * 0.1)));
|
||||||
// High volatility: large oscillation
|
// 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;
|
double widthCalm = indCalm.Upper.Value - indCalm.Lower.Value;
|
||||||
|
|||||||
@@ -74,7 +74,7 @@ public sealed class VwmacdTests
|
|||||||
var ind = new Vwmacd(fastPeriod: 3, slowPeriod: 5, signalPeriod: 3);
|
var ind = new Vwmacd(fastPeriod: 3, slowPeriod: 5, signalPeriod: 3);
|
||||||
for (int i = 0; i < 20; i++)
|
for (int i = 0; i < 20; i++)
|
||||||
{
|
{
|
||||||
var bar = new TBar(DateTime.UtcNow.AddMinutes(i), 100 + i, 105 + i, 95 + i, 101 + i, 1000 + i * 10);
|
var bar = new TBar(DateTime.UtcNow.AddMinutes(i), 100 + i, 105 + i, 95 + i, 101 + i, 1000 + (i * 10));
|
||||||
ind.Update(bar);
|
ind.Update(bar);
|
||||||
}
|
}
|
||||||
Assert.True(double.IsFinite(ind.Last.Value));
|
Assert.True(double.IsFinite(ind.Last.Value));
|
||||||
@@ -116,7 +116,7 @@ public sealed class VwmacdTests
|
|||||||
var ind = new Vwmacd(fastPeriod: 5, slowPeriod: 10, signalPeriod: 3);
|
var ind = new Vwmacd(fastPeriod: 5, slowPeriod: 10, signalPeriod: 3);
|
||||||
for (int i = 0; i < 30; i++)
|
for (int i = 0; i < 30; i++)
|
||||||
{
|
{
|
||||||
double price = 100.0 + i * 2;
|
double price = 100.0 + (i * 2);
|
||||||
var bar = new TBar(DateTime.UtcNow.AddMinutes(i), price, price + 1, price - 1, price, 10000);
|
var bar = new TBar(DateTime.UtcNow.AddMinutes(i), price, price + 1, price - 1, price, 10000);
|
||||||
ind.Update(bar);
|
ind.Update(bar);
|
||||||
}
|
}
|
||||||
@@ -130,7 +130,7 @@ public sealed class VwmacdTests
|
|||||||
var ind = new Vwmacd(fastPeriod: 5, slowPeriod: 10, signalPeriod: 3);
|
var ind = new Vwmacd(fastPeriod: 5, slowPeriod: 10, signalPeriod: 3);
|
||||||
for (int i = 0; i < 30; i++)
|
for (int i = 0; i < 30; i++)
|
||||||
{
|
{
|
||||||
double price = 200.0 - i * 2;
|
double price = 200.0 - (i * 2);
|
||||||
var bar = new TBar(DateTime.UtcNow.AddMinutes(i), price, price + 1, price - 1, price, 10000);
|
var bar = new TBar(DateTime.UtcNow.AddMinutes(i), price, price + 1, price - 1, price, 10000);
|
||||||
ind.Update(bar);
|
ind.Update(bar);
|
||||||
}
|
}
|
||||||
@@ -326,7 +326,7 @@ public sealed class VwmacdTests
|
|||||||
// ind1: uniform volume
|
// ind1: uniform volume
|
||||||
ind1.Update(new TBar(DateTime.UtcNow.AddMinutes(i), price, price + 1, price - 1, price, 1000));
|
ind1.Update(new TBar(DateTime.UtcNow.AddMinutes(i), price, price + 1, price - 1, price, 1000));
|
||||||
// ind2: high volume on latter bars (accelerating weight)
|
// ind2: high volume on latter bars (accelerating weight)
|
||||||
ind2.Update(new TBar(DateTime.UtcNow.AddMinutes(i), price, price + 1, price - 1, price, 1000 + i * 500));
|
ind2.Update(new TBar(DateTime.UtcNow.AddMinutes(i), price, price + 1, price - 1, price, 1000 + (i * 500)));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Both should be finite; values may differ due to volume weighting
|
// Both should be finite; values may differ due to volume weighting
|
||||||
|
|||||||
@@ -46,8 +46,8 @@ public sealed class BwMfiValidationTests
|
|||||||
double range1 = mfi1 * vol1;
|
double range1 = mfi1 * vol1;
|
||||||
double range2 = mfi2 * vol2;
|
double range2 = mfi2 * vol2;
|
||||||
|
|
||||||
m.Update(new TBar(t, 100, 100 + range1 / 2, 100 - range1 / 2, 100, vol1));
|
m.Update(new TBar(t, 100, 100 + (range1 / 2), 100 - (range1 / 2), 100, vol1));
|
||||||
m.Update(new TBar(t.AddMinutes(1), 100, 100 + range2 / 2, 100 - range2 / 2, 100, vol2));
|
m.Update(new TBar(t.AddMinutes(1), 100, 100 + (range2 / 2), 100 - (range2 / 2), 100, vol2));
|
||||||
|
|
||||||
Assert.Equal(expectedZone, m.Zone);
|
Assert.Equal(expectedZone, m.Zone);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -173,13 +173,13 @@ public sealed class Atrstop : ITValuePublisher
|
|||||||
double upperEval, lowerEval;
|
double upperEval, lowerEval;
|
||||||
if (_useHighLow)
|
if (_useHighLow)
|
||||||
{
|
{
|
||||||
upperEval = high + _multiplier * atrValue;
|
upperEval = high + (_multiplier * atrValue);
|
||||||
lowerEval = low - _multiplier * atrValue;
|
lowerEval = low - (_multiplier * atrValue);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
upperEval = close + _multiplier * atrValue;
|
upperEval = close + (_multiplier * atrValue);
|
||||||
lowerEval = close - _multiplier * atrValue;
|
lowerEval = close - (_multiplier * atrValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialize bands on first hot bar
|
// Initialize bands on first hot bar
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ public sealed class ConvexityIndicatorTests
|
|||||||
{
|
{
|
||||||
ind.HistoricalData.AddBar(
|
ind.HistoricalData.AddBar(
|
||||||
DateTime.UtcNow.AddMinutes(i),
|
DateTime.UtcNow.AddMinutes(i),
|
||||||
100 + i * 0.5, 101 + i * 0.5, 99 + i * 0.5, 100.5 + i * 0.5, 1000);
|
100 + (i * 0.5), 101 + (i * 0.5), 99 + (i * 0.5), 100.5 + (i * 0.5), 1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
ind.ProcessUpdate(new UpdateArgs(UpdateReason.HistoricalBar));
|
ind.ProcessUpdate(new UpdateArgs(UpdateReason.HistoricalBar));
|
||||||
|
|||||||
@@ -93,10 +93,10 @@ public sealed class ConvexityTests
|
|||||||
for (int i = 1; i <= period; i++)
|
for (int i = 1; i <= period; i++)
|
||||||
{
|
{
|
||||||
double sign = (i % 2 == 0) ? 1 : -1;
|
double sign = (i % 2 == 0) ? 1 : -1;
|
||||||
double magnitude = 0.01 + rng.NextDouble() * 0.03;
|
double magnitude = 0.01 + (rng.NextDouble() * 0.03);
|
||||||
double mktReturn = sign * magnitude;
|
double mktReturn = sign * magnitude;
|
||||||
mkt *= (1 + mktReturn);
|
mkt *= (1 + mktReturn);
|
||||||
ast *= (1 + 2 * mktReturn); // exactly 2x market return
|
ast *= (1 + (2 * mktReturn)); // exactly 2x market return
|
||||||
c.Update(ast, mkt);
|
c.Update(ast, mkt);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -123,7 +123,7 @@ public sealed class ConvexityTests
|
|||||||
for (int i = 1; i <= period; i++)
|
for (int i = 1; i <= period; i++)
|
||||||
{
|
{
|
||||||
double sign = (i % 2 == 0) ? 1 : -1;
|
double sign = (i % 2 == 0) ? 1 : -1;
|
||||||
double magnitude = 0.01 + rng.NextDouble() * 0.03; // 1%-4% varying
|
double magnitude = 0.01 + (rng.NextDouble() * 0.03); // 1%-4% varying
|
||||||
double mktReturn = sign * magnitude;
|
double mktReturn = sign * magnitude;
|
||||||
double astReturn;
|
double astReturn;
|
||||||
if (mktReturn > 0)
|
if (mktReturn > 0)
|
||||||
@@ -157,8 +157,8 @@ public sealed class ConvexityTests
|
|||||||
c.Update(100.0, 100.0);
|
c.Update(100.0, 100.0);
|
||||||
for (int i = 0; i < 50; i++)
|
for (int i = 0; i < 50; i++)
|
||||||
{
|
{
|
||||||
double ast = 100.0 + rng.NextDouble() * 20 - 10;
|
double ast = 100.0 + (rng.NextDouble() * 20) - 10;
|
||||||
double mkt = 100.0 + rng.NextDouble() * 20 - 10;
|
double mkt = 100.0 + (rng.NextDouble() * 20) - 10;
|
||||||
c.Update(ast, mkt);
|
c.Update(ast, mkt);
|
||||||
Assert.True(c.ConvexityValue >= 0, $"Convexity must be ≥ 0, got {c.ConvexityValue} at i={i}");
|
Assert.True(c.ConvexityValue >= 0, $"Convexity must be ≥ 0, got {c.ConvexityValue} at i={i}");
|
||||||
}
|
}
|
||||||
@@ -179,8 +179,8 @@ public sealed class ConvexityTests
|
|||||||
for (int i = 1; i <= period + 5; i++)
|
for (int i = 1; i <= period + 5; i++)
|
||||||
{
|
{
|
||||||
double sign = (i % 2 == 0) ? 1 : -1;
|
double sign = (i % 2 == 0) ? 1 : -1;
|
||||||
double magnitude = 0.005 + rng.NextDouble() * 0.02;
|
double magnitude = 0.005 + (rng.NextDouble() * 0.02);
|
||||||
price *= (1 + sign * magnitude);
|
price *= (1 + (sign * magnitude));
|
||||||
c.Update(price, price);
|
c.Update(price, price);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -296,9 +296,9 @@ public sealed class ConvexityTests
|
|||||||
for (int i = 0; i < 10; i++)
|
for (int i = 0; i < 10; i++)
|
||||||
{
|
{
|
||||||
double sign = (i % 2 == 0) ? 1 : -1;
|
double sign = (i % 2 == 0) ? 1 : -1;
|
||||||
double magnitude = 0.005 + rng.NextDouble() * 0.02;
|
double magnitude = 0.005 + (rng.NextDouble() * 0.02);
|
||||||
ast *= (1 + sign * magnitude * 1.5);
|
ast *= (1 + (sign * magnitude * 1.5));
|
||||||
mkt *= (1 + sign * magnitude);
|
mkt *= (1 + (sign * magnitude));
|
||||||
assetSeries.Add(new TValue(i, ast));
|
assetSeries.Add(new TValue(i, ast));
|
||||||
marketSeries.Add(new TValue(i, mkt));
|
marketSeries.Add(new TValue(i, mkt));
|
||||||
}
|
}
|
||||||
@@ -394,7 +394,7 @@ public sealed class ConvexityTests
|
|||||||
for (int i = 1; i <= period; i++)
|
for (int i = 1; i <= period; i++)
|
||||||
{
|
{
|
||||||
double sign = (i % 2 == 0) ? 1 : -1;
|
double sign = (i % 2 == 0) ? 1 : -1;
|
||||||
double magnitude = 0.01 + rng.NextDouble() * 0.03;
|
double magnitude = 0.01 + (rng.NextDouble() * 0.03);
|
||||||
double mktRet = sign * magnitude;
|
double mktRet = sign * magnitude;
|
||||||
mkt *= (1 + mktRet);
|
mkt *= (1 + mktRet);
|
||||||
ast *= (1 - mktRet); // inverse
|
ast *= (1 - mktRet); // inverse
|
||||||
@@ -440,8 +440,8 @@ public sealed class ConvexityTests
|
|||||||
|
|
||||||
for (int i = 0; i < 1000; i++)
|
for (int i = 0; i < 1000; i++)
|
||||||
{
|
{
|
||||||
ast *= (1 + (rng.NextDouble() - 0.5) * 0.04);
|
ast *= (1 + ((rng.NextDouble() - 0.5) * 0.04));
|
||||||
mkt *= (1 + (rng.NextDouble() - 0.5) * 0.02);
|
mkt *= (1 + ((rng.NextDouble() - 0.5) * 0.02));
|
||||||
c.Update(ast, mkt);
|
c.Update(ast, mkt);
|
||||||
|
|
||||||
Assert.True(double.IsFinite(c.ConvexityValue), $"ConvexityValue not finite at i={i}");
|
Assert.True(double.IsFinite(c.ConvexityValue), $"ConvexityValue not finite at i={i}");
|
||||||
|
|||||||
Reference in New Issue
Block a user