From 0c6fc6a2afd8361f170e02cba68660f23368d030 Mon Sep 17 00:00:00 2001 From: bergm Date: Wed, 1 Jul 2026 16:42:18 +0200 Subject: [PATCH] Phase 3d (2/2): CopyTradingEngine auf Repositories umgestellt MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - MarketCache-Preload + Market-Hydration -> IMarketRepository (GetActive/FindByTokenId/Upsert). - Demo-/Live-Positionen -> IPositionRepository (UpsertDemo/UpsertLive/DeleteDemo). - Account-Persistenz -> IAccountRepository. - _db (IMongoDatabase) vollständig aus CopyTradingEngine entfernt. - Verhalten unverändert; Build 0 Fehler. Co-Authored-By: Claude Opus 4.8 --- services/CopyTradingEngine.cs | 55 +++++++++++++++++------------------ 1 file changed, 27 insertions(+), 28 deletions(-) diff --git a/services/CopyTradingEngine.cs b/services/CopyTradingEngine.cs index 3301a36..2f05ec6 100644 --- a/services/CopyTradingEngine.cs +++ b/services/CopyTradingEngine.cs @@ -1,5 +1,6 @@ using System; using MongoDB.Driver; +using PolyTrader.Core.Persistence; using PolyTraderSharp.Extensions; using System.Threading; using System.Threading.Channels; @@ -20,7 +21,9 @@ namespace PolyTraderSharp.Services private readonly TerminalLogger _logger; private readonly PolymarketClobClient _clob; private readonly PolymarketApiService _api; - private readonly IMongoDatabase? _db; + private readonly IPositionRepository _positionRepo; + private readonly IMarketRepository _marketRepo; + private readonly IAccountRepository _accountRepo; private readonly ConcurrentDictionary _accountSemaphores = new(); private readonly ConcurrentDictionary _lastInactiveLogPerTrader = new(); @@ -31,7 +34,9 @@ namespace PolyTraderSharp.Services TerminalLogger logger, PolymarketClobClient clob, PolymarketApiService api, - IMongoDatabase? db = null) + IPositionRepository positionRepo, + IMarketRepository marketRepo, + IAccountRepository accountRepo) { _state = state; _signalReader = signalReader; @@ -39,20 +44,19 @@ namespace PolyTraderSharp.Services _logger = logger; _clob = clob; _api = api; - _db = db; + _positionRepo = positionRepo; + _marketRepo = marketRepo; + _accountRepo = accountRepo; } public override async Task StartAsync(CancellationToken cancellationToken) { _logger.Info("Starte Preload des MarketCache aus MongoDB um Flaschenhälse zu vermeiden..."); - if (_db != null) { - var coll = _db.GetCollection("markets"); - // Initialize cache for EVERYTHING in DB that is not closed! - var activeMarkets = coll.LiteFind(x => !x.Closed); + var activeMarkets = _marketRepo.GetActive(); int loaded = 0; - + foreach (var md in activeMarkets) { if (!string.IsNullOrEmpty(md.ClobTokenIds)) @@ -126,24 +130,23 @@ namespace PolyTraderSharp.Services if (cachedData.EndDate.HasValue) signal.EndDate = cachedData.EndDate; isNegRisk = cachedData.NegRisk; } - else if (_db != null) + else { try { - var marketColl = _db.GetCollection("markets"); - var marketData = marketColl.LiteFind(x => x.ClobTokenIds != null && x.ClobTokenIds.Contains(signal.TokenId)).FirstOrDefault(); - + var marketData = _marketRepo.FindByTokenId(signal.TokenId); + if (marketData == null) { var fetchedMarket = await _api.GetMarketByTokenIdAsync(signal.TokenId); - if (fetchedMarket != null) { marketColl.Upsert(fetchedMarket); marketData = fetchedMarket; } + if (fetchedMarket != null) { _marketRepo.Upsert(fetchedMarket); marketData = fetchedMarket; } } if (marketData == null && !string.IsNullOrEmpty(signal.MarketSlug) && !signal.MarketSlug.StartsWith("0x")) { var fetchedMarkets = await _api.GetMarketsByEventSlugAsync(signal.MarketSlug); foreach (var fetched in fetchedMarkets) { - marketColl.Upsert(fetched); + _marketRepo.Upsert(fetched); if (fetched.ClobTokenIds != null && fetched.ClobTokenIds.Contains(signal.TokenId)) marketData = fetched; } } @@ -531,10 +534,10 @@ namespace PolyTraderSharp.Services return old; }); - if (_db != null) _db.GetCollection($"demo_positions_{account.AccountId}").Upsert(finalPos); + _positionRepo.UpsertDemo(account.AccountId, finalPos); account.UpdateBalance(account.AvailableBalance - exactUsdc); - if (_db != null) _db.GetCollection("accounts").Upsert(account); + _accountRepo.Upsert(account); _logger.Trade($"✅ [DEMO AUSGEFÜHRT]\n" + $" Konto: {account.Name}\n" + $" Markt: {signal.MarketQuestion}\n" + @@ -576,17 +579,13 @@ namespace PolyTraderSharp.Services }); account.UpdateBalance(account.AvailableBalance - exactUsdc); - if (_db != null) _db.GetCollection("accounts").Upsert(account); + _accountRepo.Upsert(account); - if (_db != null) + if (account.OpenPositions.TryGetValue(signal.TokenId, out var savedPos)) { - var liveCol = _db.GetCollection($"open_positions_{account.AccountId}"); - if (account.OpenPositions.TryGetValue(signal.TokenId, out var savedPos)) - { - liveCol.Upsert(savedPos); - } + _positionRepo.UpsertLive(account.AccountId, savedPos); } - + // Track order placement time for stale order cleanup string orderKey = $"{account.AccountId}_{signal.TokenId}"; _state.PendingOrderTimestamps[orderKey] = (DateTime.UtcNow, signal.TraderId); @@ -644,14 +643,14 @@ namespace PolyTraderSharp.Services { if (account.IsDemo) { - if (_db != null) _db.GetCollection($"demo_positions_{account.AccountId}").Delete(signal.TokenId); - + _positionRepo.DeleteDemo(account.AccountId, signal.TokenId); + decimal exitUsd = openPos.Size * signal.Price; decimal realizedPnl = exitUsd - openPos.AmountUsd; - + _state.GlobalPnl += realizedPnl; account.UpdateBalance(account.AvailableBalance + exitUsd); - if (_db != null) _db.GetCollection("accounts").Upsert(account); + _accountRepo.Upsert(account); var ct = new ClosedTrade {