Fix WinRate 0% bug: Optimize TradeReconciliationWorker with bulk SQL and reset Trader analytics flag

This commit is contained in:
Richard
2026-07-07 10:56:52 +02:00
parent 910d25159a
commit d24f0ecc2e
2 changed files with 35 additions and 28 deletions
BIN
View File
Binary file not shown.
@@ -16,7 +16,7 @@ public class TradeReconciliationWorker : BackgroundService
private readonly ILogger<TradeReconciliationWorker> _logger; private readonly ILogger<TradeReconciliationWorker> _logger;
private const int BatchSize = 250; private const int BatchSize = 250;
private const int IntervalMinutes = 15; private const int IntervalSeconds = 30;
public TradeReconciliationWorker(IServiceProvider services, ILogger<TradeReconciliationWorker> logger) public TradeReconciliationWorker(IServiceProvider services, ILogger<TradeReconciliationWorker> logger)
{ {
@@ -26,7 +26,7 @@ public class TradeReconciliationWorker : BackgroundService
protected override async Task ExecuteAsync(CancellationToken stoppingToken) protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{ {
_logger.LogInformation("🛠️ TradeReconciliationWorker started (batch: {Batch}, interval: {Min}m)", BatchSize, IntervalMinutes); _logger.LogInformation("🛠️ TradeReconciliationWorker started (batch: {Batch}, interval: {Sec}s)", BatchSize, IntervalSeconds);
// Initial delay to let other workers settle // Initial delay to let other workers settle
await Task.Delay(TimeSpan.FromSeconds(30), stoppingToken); await Task.Delay(TimeSpan.FromSeconds(30), stoppingToken);
@@ -52,7 +52,7 @@ public class TradeReconciliationWorker : BackgroundService
_logger.LogError(ex, "Error in TradeReconciliationWorker cycle"); _logger.LogError(ex, "Error in TradeReconciliationWorker cycle");
} }
await Task.Delay(TimeSpan.FromMinutes(IntervalMinutes), stoppingToken); await Task.Delay(TimeSpan.FromSeconds(IntervalSeconds), stoppingToken);
} }
_logger.LogInformation("🛠️ TradeReconciliationWorker stopped"); _logger.LogInformation("🛠️ TradeReconciliationWorker stopped");
@@ -61,37 +61,44 @@ public class TradeReconciliationWorker : BackgroundService
private async Task<int> ReconcileBatchAsync(CancellationToken ct) private async Task<int> ReconcileBatchAsync(CancellationToken ct)
{ {
using var scope = _services.CreateScope(); using var scope = _services.CreateScope();
var tradeRepo = scope.ServiceProvider.GetRequiredService<ITradeRepository>(); var db = scope.ServiceProvider.GetRequiredService<Predictalytics.Infrastructure.Data.AppDbContext>();
var marketRepo = scope.ServiceProvider.GetRequiredService<IMarketRepository>();
var orphanedTrades = await tradeRepo.GetOrphanedTradesAsync(BatchSize, ct); // Bulk update orphaned trades
if (orphanedTrades.Count == 0) return 0; int reconciledCount = 0;
try
int count = 0;
foreach (var trade in orphanedTrades)
{ {
if (ct.IsCancellationRequested) break; reconciledCount = await Microsoft.EntityFrameworkCore.RelationalDatabaseFacadeExtensions.ExecuteSqlRawAsync(db.Database, @"
UPDATE Trades t
INNER JOIN MarketOutcomes o ON t.AssetId = o.TokenId
INNER JOIN Markets m ON o.MarketId = m.Id
SET t.MarketOutcomeId = o.Id,
t.Outcome = o.Label,
t.DbMarketId = m.Id
WHERE t.MarketOutcomeId IS NULL AND t.AssetId != '';
", ct);
try if (reconciledCount > 0)
{ {
var outcome = await marketRepo.GetOutcomeByTokenIdAsync(trade.AssetId, ct); // Force re-analysis of traders who now have new linked trades that haven't been applied
if (outcome != null) await Microsoft.EntityFrameworkCore.RelationalDatabaseFacadeExtensions.ExecuteSqlRawAsync(db.Database, @"
{ UPDATE Traders t
trade.MarketOutcomeId = outcome.Id; SET LastAnalyzedAt = NULL
trade.Outcome = outcome.Label; WHERE LastAnalyzedAt IS NOT NULL
if (outcome.Market != null) AND EXISTS (
trade.DbMarketId = outcome.Market.Id; SELECT 1 FROM Trades tr
LEFT JOIN TraderPositions tp ON tr.TraderId = tp.TraderId AND tr.MarketOutcomeId = tp.MarketOutcomeId
await tradeRepo.UpdateAsync(trade, ct); WHERE tr.TraderId = t.Id
count++; AND tr.MarketOutcomeId IS NOT NULL
} AND (tp.Id IS NULL OR tr.Id > tp.LastAppliedTradeId)
} );
catch (Exception ex) ", ct);
{
_logger.LogWarning("Failed to reconcile trade {TradeId}: {Msg}", trade.Id, ex.Message);
} }
} }
catch (Exception ex)
{
_logger.LogError(ex, "Error executing bulk reconciliation SQL");
}
return count; return reconciledCount;
} }
} }