Fix Aggregated-tier mutable-bucket vs checkpoint bug
The Aggregated ingest tier bucketed trades by hour incl. the current, still-growing hour, then upserted via ON DUPLICATE KEY UPDATE (mutable rows). The PnL engine checkpoints positions by row Id, so a bucket that keeps growing after being applied had its later growth silently skipped (Id <= LastAppliedTradeId). Extract the duplicated aggregation logic from PollingWorker + TradeHistoryWorker into TradeAggregation.AggregateCompletedHours, which only aggregates COMPLETED hours; the current hour is deferred (re-fetched next cycle) so every persisted aggregate is immutable. +3 unit tests. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
3ed0b4df27
commit
be1b90b556
@@ -258,34 +258,11 @@ public class TradeHistoryWorker : BackgroundService
|
||||
|
||||
if (trader.IngestMode == IngestMode.Aggregated && newTrades.Count > 0)
|
||||
{
|
||||
// Aggregate trades: Bucket (TraderId, MarketOutcomeId, Side, Stunde)
|
||||
var aggregated = new List<Domain.Entities.Trade>();
|
||||
foreach (var grp in newTrades.GroupBy(t => new { t.MarketOutcomeId, t.Side, Hour = t.ExecutedAt.ToString("yyyyMMddHH") }))
|
||||
{
|
||||
var first = grp.First();
|
||||
var totalAmount = grp.Sum(t => t.Amount);
|
||||
var totalSize = grp.Sum(t => t.Size);
|
||||
var vwap = totalSize > 0 ? totalAmount / totalSize : first.Price;
|
||||
|
||||
var aggTrade = new Domain.Entities.Trade
|
||||
{
|
||||
PlatformTradeId = $"AGG_{trader.Id}_{grp.Key.MarketOutcomeId}_{grp.Key.Side}_{grp.Key.Hour}",
|
||||
TraderId = trader.Id,
|
||||
MarketOutcomeId = first.MarketOutcomeId,
|
||||
DbMarketId = first.DbMarketId,
|
||||
MarketId = first.MarketId,
|
||||
AssetId = first.AssetId,
|
||||
Outcome = first.Outcome,
|
||||
Side = first.Side,
|
||||
Price = vwap,
|
||||
Amount = totalAmount,
|
||||
Size = totalSize,
|
||||
ExecutedAt = first.ExecutedAt,
|
||||
AggregatedCount = grp.Count()
|
||||
};
|
||||
aggregated.Add(aggTrade);
|
||||
}
|
||||
newTrades = aggregated;
|
||||
// Only completed hours are aggregated+persisted; the current (growing)
|
||||
// hour is deferred so aggregate rows stay immutable for the checkpoint
|
||||
// engine. See TradeAggregation.AggregateCompletedHours.
|
||||
newTrades = Predictalytics.Application.Services.TradeAggregation
|
||||
.AggregateCompletedHours(newTrades, trader.Id, DateTime.UtcNow);
|
||||
}
|
||||
|
||||
if (isWeeklyBiopsy && newTrades.Count > 0)
|
||||
|
||||
Reference in New Issue
Block a user