74 lines
2.0 KiB
C#
74 lines
2.0 KiB
C#
using System.Text.Json;
|
|
using Backend.DatabaseHandler;
|
|
using Backend.Interface;
|
|
|
|
namespace Backend.ServiceHandler;
|
|
|
|
public sealed class TrailingPriceEvaluator : IAlertEvaluator
|
|
{
|
|
public string AlertType => "trailing_price";
|
|
|
|
public Task<AlertEvaluation> EvaluateAsync(AlertRecord alert, MarketDataService marketData)
|
|
{
|
|
var parameters = JsonSerializer.Deserialize<TrailingPriceParameters>(alert.Parameters)
|
|
?? throw new InvalidOperationException($"Invalid parameters for alert {alert.Id}");
|
|
|
|
var snapshot = marketData.GetLiveQuote(alert.Symbol);
|
|
|
|
if (!snapshot.LastPrice.HasValue)
|
|
{
|
|
return Task.FromResult(new AlertEvaluation { Triggered = false });
|
|
}
|
|
|
|
double price = snapshot.LastPrice.Value;
|
|
var state = JsonSerializer.Deserialize<TrailingPriceState>(alert.LastState)
|
|
?? new TrailingPriceState();
|
|
|
|
bool triggered;
|
|
|
|
if (parameters.Direction.Equals("bullish", StringComparison.OrdinalIgnoreCase))
|
|
{
|
|
if (!state.PeakPrice.HasValue || price > state.PeakPrice.Value)
|
|
state.PeakPrice = price;
|
|
|
|
double dropPercent = (state.PeakPrice.Value - price) / state.PeakPrice.Value * 100.0;
|
|
triggered = dropPercent >= parameters.TrailPercent;
|
|
}
|
|
else
|
|
{
|
|
if (!state.TroughPrice.HasValue || price < state.TroughPrice.Value)
|
|
state.TroughPrice = price;
|
|
|
|
double risePercent = state.TroughPrice.Value == 0
|
|
? 0
|
|
: (price - state.TroughPrice.Value) / state.TroughPrice.Value * 100.0;
|
|
triggered = risePercent >= parameters.TrailPercent;
|
|
}
|
|
|
|
string updatedState = JsonSerializer.Serialize(new
|
|
{
|
|
peakPrice = state.PeakPrice,
|
|
troughPrice = state.TroughPrice,
|
|
lastPrice = price
|
|
});
|
|
|
|
return Task.FromResult(new AlertEvaluation
|
|
{
|
|
Triggered = triggered,
|
|
UpdatedLastState = updatedState
|
|
});
|
|
}
|
|
|
|
private sealed class TrailingPriceParameters
|
|
{
|
|
public string Direction { get; set; } = string.Empty;
|
|
public double TrailPercent { get; set; }
|
|
}
|
|
|
|
private sealed class TrailingPriceState
|
|
{
|
|
public double? PeakPrice { get; set; }
|
|
public double? TroughPrice { get; set; }
|
|
}
|
|
}
|