refactoring

This commit is contained in:
Miha Kralj
2025-12-16 21:16:50 -08:00
parent a67ad65fa5
commit d277e08056
137 changed files with 5074 additions and 3178 deletions
+1 -1
View File
@@ -28,7 +28,7 @@ public class HtitIndicatorTests
{
var time = DateTime.UtcNow.AddMinutes(i);
indicator.HistoricalData.AddBar(time, 100 + i, 100 + i, 100 + i, 100 + i);
var args = new UpdateArgs(UpdateReason.NewBar);
indicator.ProcessUpdate(args);
}
+1 -1
View File
@@ -48,7 +48,7 @@ public class HtitIndicator : Indicator, IWatchlistIndicator
{
TValue input = this.GetInputValue(args, Source);
bool isNew = args.Reason == UpdateReason.NewBar || args.Reason == UpdateReason.HistoricalBar;
TValue result = _htit!.Update(input, isNew);
Series!.SetValue(result.Value);
Series!.SetMarker(0, Color.Transparent);
+1 -1
View File
@@ -165,7 +165,7 @@ public class HtitTests
var series = bars.Close;
// 1. Batch Mode
var batchSeries = Htit.Calculate(series);
var batchSeries = Htit.Batch(series);
double expected = batchSeries.Last.Value;
// 2. Span Mode
+24 -20
View File
@@ -17,13 +17,8 @@ namespace QuanTAlib;
/// https://dotnet.stockindicators.dev/indicators/HtTrendline/
/// </remarks>
[SkipLocalsInit]
public sealed class Htit : ITValuePublisher
public sealed class Htit : AbstractBase
{
public string Name { get; }
public bool IsHot { get; private set; }
public event Action<TValue>? Pub;
public TValue Last { get; private set; }
private readonly RingBuffer _priceBuffer;
private readonly RingBuffer _smoothBuffer;
private readonly RingBuffer _detrenderBuffer;
@@ -37,9 +32,12 @@ public sealed class Htit : ITValuePublisher
private State _state;
private State _p_state;
public override bool IsHot => _priceBuffer.Count >= WarmupPeriod;
public Htit()
{
Name = "Htit";
WarmupPeriod = 12; // Based on logic: _priceBuffer.Count >= 12
_priceBuffer = new RingBuffer(50);
_smoothBuffer = new RingBuffer(7);
_detrenderBuffer = new RingBuffer(7);
@@ -56,7 +54,7 @@ public sealed class Htit : ITValuePublisher
source.Pub += (item) => Update(item);
}
public void Init()
private void Init()
{
_priceBuffer.Clear();
_smoothBuffer.Clear();
@@ -68,12 +66,11 @@ public sealed class Htit : ITValuePublisher
_itBuffer.Clear();
_state = default;
_p_state = default;
IsHot = false;
Last = default;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public TValue Update(TValue input, bool isNew = true)
public override TValue Update(TValue input, bool isNew = true)
{
ManageState(isNew);
double price = ValidateInput(input.Value);
@@ -123,13 +120,12 @@ public sealed class Htit : ITValuePublisher
? (4 * _itBuffer[^1] + 3 * _itBuffer[^2] + 2 * _itBuffer[^3] + _itBuffer[^4]) / 10.0
: price;
IsHot = _priceBuffer.Count >= 12;
Last = new TValue(input.Time, trendline);
Pub?.Invoke(Last);
PubEvent(Last);
return Last;
}
public TSeries Update(TSeries source)
public override TSeries Update(TSeries source)
{
if (source.Count == 0) return [];
@@ -157,6 +153,14 @@ public sealed class Htit : ITValuePublisher
return new TSeries(t, v);
}
public override void Prime(ReadOnlySpan<double> source)
{
foreach (var value in source)
{
Update(new TValue(DateTime.MinValue, value));
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private void ManageState(bool isNew)
{
@@ -173,7 +177,7 @@ public sealed class Htit : ITValuePublisher
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private void UpdateBuffer(RingBuffer buffer, double val, bool isNew)
private static void UpdateBuffer(RingBuffer buffer, double val, bool isNew)
{
if (isNew) buffer.Add(val);
else buffer.UpdateNewest(val);
@@ -190,7 +194,7 @@ public sealed class Htit : ITValuePublisher
UpdateBuffer(_itBuffer, price, isNew);
Last = new TValue(input.Time, price);
Pub?.Invoke(Last);
PubEvent(Last);
return Last;
}
@@ -253,7 +257,7 @@ public sealed class Htit : ITValuePublisher
return count > 0 ? sumPr / count : price;
}
public static TSeries Calculate(TSeries source)
public static TSeries Batch(TSeries source)
{
var htit = new Htit();
return htit.Update(source);
@@ -318,12 +322,12 @@ public sealed class Htit : ITValuePublisher
// 2. Detrender
double prevPeriod = periodBuffer[(pdIdx - 1 + 2) % 2];
double adj = (0.075 * prevPeriod) + 0.54;
double s0 = smoothBuffer[sIdx];
double s2 = smoothBuffer[(sIdx - 2 + 7) % 7];
double s4 = smoothBuffer[(sIdx - 4 + 7) % 7];
double s6 = smoothBuffer[(sIdx - 6 + 7) % 7];
double detrender = (0.0962 * s0 + 0.5769 * s2 - 0.5769 * s4 - 0.0962 * s6) * adj;
detrenderBuffer[dIdx] = detrender;
@@ -332,10 +336,10 @@ public sealed class Htit : ITValuePublisher
double d2 = detrenderBuffer[(dIdx - 2 + 7) % 7];
double d4 = detrenderBuffer[(dIdx - 4 + 7) % 7];
double d6 = detrenderBuffer[(dIdx - 6 + 7) % 7];
double q1 = (0.0962 * d0 + 0.5769 * d2 - 0.5769 * d4 - 0.0962 * d6) * adj;
double i1 = detrenderBuffer[(dIdx - 3 + 7) % 7];
q1Buffer[q1Idx] = q1;
i1Buffer[i1Idx] = i1;
@@ -438,7 +442,7 @@ public sealed class Htit : ITValuePublisher
}
}
public void Reset()
public override void Reset()
{
Init();
}
+2 -2
View File
@@ -47,12 +47,12 @@ TValue result = htit.Update(new TValue(time, price));
// Batch
var series = new TSeries(times, prices);
var resultSeries = Htit.Calculate(series);
var resultSeries = Htit.Batch(series);
// Span (Zero-Allocation)
double[] input = ...;
double[] output = new double[input.Length];
Htit.Calculate(input, output);
Htit.Batch(input, output);
```
## Interpretation