mirror of
https://github.com/mihakralj/QuanTAlib.git
synced 2026-08-13 16:18:05 +00:00
feat: Implement IEquatable for state structures in Dema, Ema, T3, Tema, and Hma classes; update IsHot logic in Hma
This commit is contained in:
@@ -24,7 +24,7 @@ namespace QuanTAlib;
|
||||
[SkipLocalsInit]
|
||||
public sealed class Dema : ITValuePublisher
|
||||
{
|
||||
private struct EmaState
|
||||
private struct EmaState : IEquatable<EmaState>
|
||||
{
|
||||
public double Ema;
|
||||
public double E;
|
||||
@@ -32,6 +32,20 @@ public sealed class Dema : ITValuePublisher
|
||||
public bool IsCompensated;
|
||||
|
||||
public static EmaState New() => new() { Ema = 0, E = 1.0, IsHot = false, IsCompensated = false };
|
||||
|
||||
public override bool Equals(object? obj) => obj is EmaState other && Equals(other);
|
||||
|
||||
public bool Equals(EmaState other) =>
|
||||
Ema == other.Ema &&
|
||||
E == other.E &&
|
||||
IsHot == other.IsHot &&
|
||||
IsCompensated == other.IsCompensated;
|
||||
|
||||
public override int GetHashCode() => HashCode.Combine(Ema, E, IsHot, IsCompensated);
|
||||
|
||||
public static bool operator ==(EmaState left, EmaState right) => left.Equals(right);
|
||||
|
||||
public static bool operator !=(EmaState left, EmaState right) => !left.Equals(right);
|
||||
}
|
||||
|
||||
private readonly double _alpha;
|
||||
|
||||
+15
-1
@@ -27,7 +27,7 @@ namespace QuanTAlib;
|
||||
[SkipLocalsInit]
|
||||
public sealed class Ema : ITValuePublisher
|
||||
{
|
||||
private struct State
|
||||
private struct State : IEquatable<State>
|
||||
{
|
||||
public double Ema;
|
||||
public double E;
|
||||
@@ -35,6 +35,20 @@ public sealed class Ema : ITValuePublisher
|
||||
public bool IsCompensated;
|
||||
|
||||
public static State New() => new() { Ema = 0, E = 1.0, IsHot = false, IsCompensated = false };
|
||||
|
||||
public override bool Equals(object? obj) => obj is State other && Equals(other);
|
||||
|
||||
public bool Equals(State other) =>
|
||||
Ema == other.Ema &&
|
||||
E == other.E &&
|
||||
IsHot == other.IsHot &&
|
||||
IsCompensated == other.IsCompensated;
|
||||
|
||||
public override int GetHashCode() => HashCode.Combine(Ema, E, IsHot, IsCompensated);
|
||||
|
||||
public static bool operator ==(State left, State right) => left.Equals(right);
|
||||
|
||||
public static bool operator !=(State left, State right) => !left.Equals(right);
|
||||
}
|
||||
|
||||
private readonly double _alpha;
|
||||
|
||||
@@ -37,9 +37,9 @@ public class HmaTests
|
||||
// IsHot is defined as Full.IsHot && Sqrt.IsHot.
|
||||
// Full becomes hot after 9 updates.
|
||||
// Sqrt becomes hot after 3 updates.
|
||||
// So HMA should be hot after 9 updates.
|
||||
// So HMA should be hot after 9 + 3 - 1 = 11 updates.
|
||||
|
||||
for (int i = 0; i < 8; i++)
|
||||
for (int i = 0; i < 10; i++)
|
||||
{
|
||||
hma.Update(new TValue(DateTime.UtcNow, 100));
|
||||
Assert.False(hma.IsHot);
|
||||
|
||||
@@ -21,13 +21,15 @@ namespace QuanTAlib;
|
||||
public sealed class Hma : ITValuePublisher
|
||||
{
|
||||
private readonly int _period;
|
||||
private readonly int _sqrtPeriod;
|
||||
private readonly Wma _wmaFull;
|
||||
private readonly Wma _wmaHalf;
|
||||
private readonly Wma _wmaSqrt;
|
||||
private int _sampleCount;
|
||||
|
||||
public string Name { get; }
|
||||
public TValue Last { get; private set; }
|
||||
public bool IsHot => _wmaFull.IsHot && _wmaSqrt.IsHot;
|
||||
public bool IsHot => _sampleCount >= _period + _sqrtPeriod - 1;
|
||||
public event Action<TValue>? Pub;
|
||||
|
||||
public Hma(int period)
|
||||
@@ -36,11 +38,11 @@ public sealed class Hma : ITValuePublisher
|
||||
|
||||
_period = period;
|
||||
int halfPeriod = period / 2;
|
||||
int sqrtPeriod = (int)Math.Sqrt(period);
|
||||
_sqrtPeriod = (int)Math.Sqrt(period);
|
||||
|
||||
_wmaFull = new Wma(period);
|
||||
_wmaHalf = new Wma(halfPeriod);
|
||||
_wmaSqrt = new Wma(sqrtPeriod);
|
||||
_wmaSqrt = new Wma(_sqrtPeriod);
|
||||
|
||||
Name = $"Hma({period})";
|
||||
}
|
||||
@@ -53,6 +55,8 @@ public sealed class Hma : ITValuePublisher
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public TValue Update(TValue input, bool isNew = true)
|
||||
{
|
||||
if (isNew) _sampleCount++;
|
||||
|
||||
// 1. Calculate WMA(n)
|
||||
TValue full = _wmaFull.Update(input, isNew);
|
||||
|
||||
@@ -188,6 +192,7 @@ public sealed class Hma : ITValuePublisher
|
||||
_wmaFull.Reset();
|
||||
_wmaHalf.Reset();
|
||||
_wmaSqrt.Reset();
|
||||
_sampleCount = 0;
|
||||
Last = default;
|
||||
}
|
||||
}
|
||||
|
||||
+28
-2
@@ -26,15 +26,28 @@ namespace QuanTAlib;
|
||||
[SkipLocalsInit]
|
||||
public sealed class T3 : ITValuePublisher
|
||||
{
|
||||
private struct State
|
||||
private struct State : IEquatable<State>
|
||||
{
|
||||
public double E1, E2, E3, E4, E5, E6;
|
||||
public bool IsInitialized;
|
||||
|
||||
public static State New() => new() { IsInitialized = false };
|
||||
|
||||
public override bool Equals(object? obj) => obj is State other && Equals(other);
|
||||
|
||||
public bool Equals(State other) =>
|
||||
E1 == other.E1 && E2 == other.E2 && E3 == other.E3 &&
|
||||
E4 == other.E4 && E5 == other.E5 && E6 == other.E6 &&
|
||||
IsInitialized == other.IsInitialized;
|
||||
|
||||
public override int GetHashCode() => HashCode.Combine(E1, E2, E3, E4, E5, E6, IsInitialized);
|
||||
|
||||
public static bool operator ==(State left, State right) => left.Equals(right);
|
||||
|
||||
public static bool operator !=(State left, State right) => !left.Equals(right);
|
||||
}
|
||||
|
||||
private readonly struct Parameters
|
||||
private readonly struct Parameters : IEquatable<Parameters>
|
||||
{
|
||||
public readonly double Alpha;
|
||||
public readonly double C1, C2, C3, C4;
|
||||
@@ -47,6 +60,19 @@ public sealed class T3 : ITValuePublisher
|
||||
C3 = c3;
|
||||
C4 = c4;
|
||||
}
|
||||
|
||||
public override bool Equals(object? obj) => obj is Parameters other && Equals(other);
|
||||
|
||||
public bool Equals(Parameters other) =>
|
||||
Alpha == other.Alpha &&
|
||||
C1 == other.C1 && C2 == other.C2 &&
|
||||
C3 == other.C3 && C4 == other.C4;
|
||||
|
||||
public override int GetHashCode() => HashCode.Combine(Alpha, C1, C2, C3, C4);
|
||||
|
||||
public static bool operator ==(Parameters left, Parameters right) => left.Equals(right);
|
||||
|
||||
public static bool operator !=(Parameters left, Parameters right) => !left.Equals(right);
|
||||
}
|
||||
|
||||
private readonly Parameters _params;
|
||||
|
||||
@@ -26,7 +26,7 @@ namespace QuanTAlib;
|
||||
[SkipLocalsInit]
|
||||
public sealed class Tema : ITValuePublisher
|
||||
{
|
||||
private struct EmaState
|
||||
private struct EmaState : IEquatable<EmaState>
|
||||
{
|
||||
public double Ema;
|
||||
public double E;
|
||||
@@ -34,6 +34,20 @@ public sealed class Tema : ITValuePublisher
|
||||
public bool IsCompensated;
|
||||
|
||||
public static EmaState New() => new() { Ema = 0, E = 1.0, IsHot = false, IsCompensated = false };
|
||||
|
||||
public override bool Equals(object? obj) => obj is EmaState other && Equals(other);
|
||||
|
||||
public bool Equals(EmaState other) =>
|
||||
Ema == other.Ema &&
|
||||
E == other.E &&
|
||||
IsHot == other.IsHot &&
|
||||
IsCompensated == other.IsCompensated;
|
||||
|
||||
public override int GetHashCode() => HashCode.Combine(Ema, E, IsHot, IsCompensated);
|
||||
|
||||
public static bool operator ==(EmaState left, EmaState right) => left.Equals(right);
|
||||
|
||||
public static bool operator !=(EmaState left, EmaState right) => !left.Equals(right);
|
||||
}
|
||||
|
||||
private readonly double _alpha;
|
||||
|
||||
Reference in New Issue
Block a user