Phase 3d (1/2): TraderMonitorService auf Repositories umgestellt

- 8 Positions-Zugriffe (open_positions_{id}) -> IPositionRepository
  (FindLive/UpsertLive/DeleteLive).
- 1 Market-Upsert -> IMarketRepository.
- closed_trades bleibt auf _db (ClosedTrade-Repo folgt in Phase 5).
- Verhalten unverändert (Repos bilden Shim-Semantik 1:1 nach); Build 0 Fehler.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
bergm
2026-07-01 16:39:28 +02:00
co-authored by Claude Opus 4.8
parent 41c43fa3aa
commit a0e367e645
+16 -13
View File
@@ -1,5 +1,6 @@
using System;
using MongoDB.Driver;
using PolyTrader.Core.Persistence;
using PolyTraderSharp.Extensions;
using System.Collections.Concurrent;
using System.Linq;
@@ -21,6 +22,8 @@ namespace PolyTraderSharp.Services
private readonly ChannelWriter<ClosedTrade> _closedTradeWriter;
private readonly TerminalLogger _logger;
private readonly IMongoDatabase? _db;
private readonly IPositionRepository _positionRepo;
private readonly IMarketRepository _marketRepo;
// Prevents duplicates. Fast O(1) lookup cache to prevent DB spam.
private readonly ConcurrentDictionary<string, DateTime> _processedTxHashes = new();
@@ -42,6 +45,8 @@ namespace PolyTraderSharp.Services
ChannelWriter<CopySignal> signalWriter,
ChannelWriter<ClosedTrade> closedTradeWriter,
TerminalLogger logger,
IPositionRepository positionRepo,
IMarketRepository marketRepo,
IMongoDatabase? db = null)
{
_state = state;
@@ -50,6 +55,8 @@ namespace PolyTraderSharp.Services
_signalWriter = signalWriter;
_closedTradeWriter = closedTradeWriter;
_logger = logger;
_positionRepo = positionRepo;
_marketRepo = marketRepo;
_db = db;
}
@@ -332,8 +339,7 @@ namespace PolyTraderSharp.Services
{
_ = Task.Run(() => {
try {
var mdColl = _db.GetCollection<MarketData>("markets");
mdColl.Upsert(coldItem);
_marketRepo.Upsert(coldItem);
} catch { } // Failsafe
});
}
@@ -549,8 +555,7 @@ namespace PolyTraderSharp.Services
{
try
{
var liveCol = _db.GetCollection<Position>($"open_positions_{acc.AccountId}");
var dbPos = liveCol.LiteFindOne(x => x.TokenId == asset);
var dbPos = _positionRepo.FindLive(acc.AccountId, asset);
if (dbPos != null && dbPos.SourceTraderId > 0)
{
resolvedSourceId = dbPos.SourceTraderId;
@@ -705,7 +710,7 @@ namespace PolyTraderSharp.Services
existing.CurrentValueUsd = curValue;
if (expiry.HasValue) existing.ExpiryDate = expiry;
if (_db != null) { try { _db.GetCollection<Position>($"open_positions_{acc.AccountId}").Upsert(existing); } catch { } }
try { _positionRepo.UpsertLive(acc.AccountId, existing); } catch { }
// Auto-Redeem Fallback via REST
if (acc.PreRedeemLimit > 0 && curPrice >= acc.PreRedeemLimit && acc.IsActive)
@@ -791,8 +796,7 @@ namespace PolyTraderSharp.Services
{
try
{
var liveCol = _db.GetCollection<Position>($"open_positions_{acc.AccountId}");
var dbPos = liveCol.LiteFindOne(x => x.TokenId == asset);
var dbPos = _positionRepo.FindLive(acc.AccountId, asset);
if (dbPos != null)
{
if (dbPos.SourceTraderId > 0)
@@ -829,7 +833,7 @@ namespace PolyTraderSharp.Services
OpenedAt = resolvedOpenedAt
};
acc.OpenPositions.TryAdd(asset, newPos);
if (_db != null) { try { _db.GetCollection<Position>($"open_positions_{acc.AccountId}").Upsert(newPos); } catch { } }
try { _positionRepo.UpsertLive(acc.AccountId, newPos); } catch { }
if (resolvedTraderId > 0)
_logger.Info($"🌐 Live Position erkannt: {title} ({newPos.Outcome}) - ${amountUsd} - Account: {acc.Name} [Zugeordnet: {resolvedTraderName}]");
@@ -857,8 +861,7 @@ namespace PolyTraderSharp.Services
{
try
{
var liveCol = _db.GetCollection<Position>($"open_positions_{acc.AccountId}");
var dbPos = liveCol.LiteFindOne(x => x.TokenId == k);
var dbPos = _positionRepo.FindLive(acc.AccountId, k);
if (dbPos != null && dbPos.SourceTraderId > 0)
{
removedPos.SourceTraderId = dbPos.SourceTraderId;
@@ -880,7 +883,7 @@ namespace PolyTraderSharp.Services
if (matchedClose.HasValue)
{
acc.OpenPositions.TryRemove(k, out _); // Safe removal!
if (_db != null) { try { _db.GetCollection<Position>($"open_positions_{acc.AccountId}").Delete(k); } catch { } }
try { _positionRepo.DeleteLive(acc.AccountId, k); } catch { }
decimal realizedPnl = 0m;
DateTime resolvedClosedAt = DateTime.UtcNow;
@@ -953,7 +956,7 @@ namespace PolyTraderSharp.Services
if (isClosed)
{
acc.OpenPositions.TryRemove(k, out _); // Safe removal!
if (_db != null) { try { _db.GetCollection<Position>($"open_positions_{acc.AccountId}").Delete(k); } catch { } }
try { _positionRepo.DeleteLive(acc.AccountId, k); } catch { }
decimal exitPrice = isWinner ? 1.0m : 0.0m;
decimal exitUsd = removedPos.Size * exitPrice;
@@ -1029,7 +1032,7 @@ namespace PolyTraderSharp.Services
{
if (acc.OpenPositions.TryRemove(k, out _))
{
if (_db != null) { try { _db.GetCollection<Position>($"open_positions_{acc.AccountId}").Delete(k); } catch { } }
try { _positionRepo.DeleteLive(acc.AccountId, k); } catch { }
_logger.Info($"🌐 Live Position {removedPos.MarketQuestion} final entfernt (Ext. Verkauft/Wartend nach {ageMinutes:F0} Min.)");
}
}