Fix Estimator scoring and PnL engine cashflow

This commit is contained in:
Richard
2026-07-07 18:30:20 +02:00
parent 8d056653f9
commit 4eb0d99b4e
17 changed files with 2594 additions and 97 deletions
@@ -63,9 +63,11 @@ public class TraderAnalyticsWorker : BackgroundService
{
var db = scope.ServiceProvider.GetRequiredService<AppDbContext>();
// Find traders who have never been analyzed, or whose last analysis was before their latest trade.
// Prioritize never-analyzed traders.
// Bug 5 Fix: Add 30-minute cooldown to prevent CPU looping.
var cooldown = DateTime.UtcNow.AddMinutes(-30);
traderIds = await db.Traders
.Where(t => t.LastAnalyzedAt == null || t.Trades.Any(tr => tr.ExecutedAt > t.LastAnalyzedAt))
.Where(t => t.LastAnalyzedAt == null ||
(t.LastAnalyzedAt < cooldown && t.Trades.Any(tr => tr.ExecutedAt > t.LastAnalyzedAt)))
.OrderBy(t => t.LastAnalyzedAt == null ? 0 : 1)
.ThenBy(t => t.LastAnalyzedAt)
.Select(t => t.Id)
@@ -89,24 +91,31 @@ public class TraderAnalyticsWorker : BackgroundService
// Run CopytradingEstimator
var traderRepo = traderScope.ServiceProvider.GetRequiredService<ITraderRepository>();
var tradeRepo = traderScope.ServiceProvider.GetRequiredService<ITradeRepository>();
var db = traderScope.ServiceProvider.GetRequiredService<AppDbContext>();
var estimator = traderScope.ServiceProvider.GetRequiredService<ICopytradingEstimator>();
var trader = await traderRepo.GetByIdAsync(id, ct);
if (trader != null)
{
var trades = await tradeRepo.GetByTraderIdAsync(id, 0, 1000, ct);
var trades = await db.Trades
.Include(t => t.MarketOutcome)
.Include(t => t.Context)
.Where(t => t.TraderId == id && t.DbMarketId != null)
.OrderByDescending(t => t.ExecutedAt)
.Take(1000)
.ToListAsync(ct);
if (trades.Count > 0)
{
var estScores = await estimator.CalculateScoresAsync(trader, trades, ct);
var scoreObj = trader.CurrentScore ?? new Predictalytics.Domain.Entities.TraderScore { TraderId = trader.Id };
var analyticsObj = trader.Analytics ?? new Predictalytics.Domain.Entities.TraderAnalytics { TraderId = trader.Id };
// Persist advanced copyability and quality scores derived from tape replay
scoreObj.CopytradingScore = estScores.CopyabilityScore;
scoreObj.QualityScore = estScores.QualityScore;
scoreObj.CalculatedAt = DateTime.UtcNow;
analyticsObj.CopytradingScore = estScores.CopyabilityScore;
analyticsObj.CopytradingQualityScore = estScores.QualityScore;
analyticsObj.CopytradingCopyabilityScore = estScores.CopyabilityScore;
trader.CurrentScore = scoreObj;
trader.Analytics = analyticsObj;
}
trader.LastAnalyzedAt = DateTime.UtcNow;
await traderRepo.UpdateAsync(trader, ct);