72 lines
1.8 KiB
C#
72 lines
1.8 KiB
C#
using System.Text.Json;
|
|
using Backend.DatabaseHandler;
|
|
using Backend.Interface;
|
|
|
|
namespace Backend.ServiceHander;
|
|
|
|
public sealed class PriceSpikeEvaluator : IAlertEvaluator
|
|
{
|
|
public string AlertType => "price_spike";
|
|
|
|
public Task<AlertEvaluation> EvaluateAsync(AlertRecord alert, MarketDataService marketData)
|
|
{
|
|
var parameters = JsonSerializer.Deserialize<PriceSpikeParameters>(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 now = DateTime.UtcNow;
|
|
|
|
var state = JsonSerializer.Deserialize<PriceSpikeState>(alert.LastState)
|
|
?? new PriceSpikeState();
|
|
|
|
state.Prices ??= new List<PricePoint>();
|
|
state.Prices.Add(new PricePoint { Price = price, Timestamp = now });
|
|
|
|
var cutoff = now.AddMinutes(-parameters.WindowMinutes);
|
|
state.Prices.RemoveAll(p => p.Timestamp < cutoff);
|
|
|
|
bool triggered = false;
|
|
if (state.Prices.Count >= 2)
|
|
{
|
|
double oldest = state.Prices[0].Price;
|
|
if (oldest != 0)
|
|
{
|
|
double change = Math.Abs((price - oldest) / oldest * 100.0);
|
|
triggered = change >= parameters.PercentChange;
|
|
}
|
|
}
|
|
|
|
string updatedState = JsonSerializer.Serialize(state);
|
|
|
|
return Task.FromResult(new AlertEvaluation
|
|
{
|
|
Triggered = triggered,
|
|
UpdatedLastState = updatedState
|
|
});
|
|
}
|
|
|
|
private sealed class PriceSpikeParameters
|
|
{
|
|
public double PercentChange { get; set; }
|
|
public int WindowMinutes { get; set; } = 15;
|
|
}
|
|
|
|
private sealed class PriceSpikeState
|
|
{
|
|
public List<PricePoint>? Prices { get; set; }
|
|
}
|
|
|
|
private sealed class PricePoint
|
|
{
|
|
public double Price { get; set; }
|
|
public DateTime Timestamp { get; set; }
|
|
}
|
|
}
|