Phase 3d (2/2): CopyTradingEngine auf Repositories umgestellt
- 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 <noreply@anthropic.com>
This commit is contained in:
@@ -1,5 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using MongoDB.Driver;
|
using MongoDB.Driver;
|
||||||
|
using PolyTrader.Core.Persistence;
|
||||||
using PolyTraderSharp.Extensions;
|
using PolyTraderSharp.Extensions;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Channels;
|
using System.Threading.Channels;
|
||||||
@@ -20,7 +21,9 @@ namespace PolyTraderSharp.Services
|
|||||||
private readonly TerminalLogger _logger;
|
private readonly TerminalLogger _logger;
|
||||||
private readonly PolymarketClobClient _clob;
|
private readonly PolymarketClobClient _clob;
|
||||||
private readonly PolymarketApiService _api;
|
private readonly PolymarketApiService _api;
|
||||||
private readonly IMongoDatabase? _db;
|
private readonly IPositionRepository _positionRepo;
|
||||||
|
private readonly IMarketRepository _marketRepo;
|
||||||
|
private readonly IAccountRepository _accountRepo;
|
||||||
private readonly ConcurrentDictionary<int, SemaphoreSlim> _accountSemaphores = new();
|
private readonly ConcurrentDictionary<int, SemaphoreSlim> _accountSemaphores = new();
|
||||||
private readonly ConcurrentDictionary<int, DateTime> _lastInactiveLogPerTrader = new();
|
private readonly ConcurrentDictionary<int, DateTime> _lastInactiveLogPerTrader = new();
|
||||||
|
|
||||||
@@ -31,7 +34,9 @@ namespace PolyTraderSharp.Services
|
|||||||
TerminalLogger logger,
|
TerminalLogger logger,
|
||||||
PolymarketClobClient clob,
|
PolymarketClobClient clob,
|
||||||
PolymarketApiService api,
|
PolymarketApiService api,
|
||||||
IMongoDatabase? db = null)
|
IPositionRepository positionRepo,
|
||||||
|
IMarketRepository marketRepo,
|
||||||
|
IAccountRepository accountRepo)
|
||||||
{
|
{
|
||||||
_state = state;
|
_state = state;
|
||||||
_signalReader = signalReader;
|
_signalReader = signalReader;
|
||||||
@@ -39,20 +44,19 @@ namespace PolyTraderSharp.Services
|
|||||||
_logger = logger;
|
_logger = logger;
|
||||||
_clob = clob;
|
_clob = clob;
|
||||||
_api = api;
|
_api = api;
|
||||||
_db = db;
|
_positionRepo = positionRepo;
|
||||||
|
_marketRepo = marketRepo;
|
||||||
|
_accountRepo = accountRepo;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override async Task StartAsync(CancellationToken cancellationToken)
|
public override async Task StartAsync(CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
_logger.Info("Starte Preload des MarketCache aus MongoDB um Flaschenhälse zu vermeiden...");
|
_logger.Info("Starte Preload des MarketCache aus MongoDB um Flaschenhälse zu vermeiden...");
|
||||||
if (_db != null)
|
|
||||||
{
|
{
|
||||||
var coll = _db.GetCollection<MarketData>("markets");
|
|
||||||
|
|
||||||
// Initialize cache for EVERYTHING in DB that is not closed!
|
// Initialize cache for EVERYTHING in DB that is not closed!
|
||||||
var activeMarkets = coll.LiteFind(x => !x.Closed);
|
var activeMarkets = _marketRepo.GetActive();
|
||||||
int loaded = 0;
|
int loaded = 0;
|
||||||
|
|
||||||
foreach (var md in activeMarkets)
|
foreach (var md in activeMarkets)
|
||||||
{
|
{
|
||||||
if (!string.IsNullOrEmpty(md.ClobTokenIds))
|
if (!string.IsNullOrEmpty(md.ClobTokenIds))
|
||||||
@@ -126,24 +130,23 @@ namespace PolyTraderSharp.Services
|
|||||||
if (cachedData.EndDate.HasValue) signal.EndDate = cachedData.EndDate;
|
if (cachedData.EndDate.HasValue) signal.EndDate = cachedData.EndDate;
|
||||||
isNegRisk = cachedData.NegRisk;
|
isNegRisk = cachedData.NegRisk;
|
||||||
}
|
}
|
||||||
else if (_db != null)
|
else
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var marketColl = _db.GetCollection<MarketData>("markets");
|
var marketData = _marketRepo.FindByTokenId(signal.TokenId);
|
||||||
var marketData = marketColl.LiteFind(x => x.ClobTokenIds != null && x.ClobTokenIds.Contains(signal.TokenId)).FirstOrDefault();
|
|
||||||
|
|
||||||
if (marketData == null)
|
if (marketData == null)
|
||||||
{
|
{
|
||||||
var fetchedMarket = await _api.GetMarketByTokenIdAsync(signal.TokenId);
|
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"))
|
if (marketData == null && !string.IsNullOrEmpty(signal.MarketSlug) && !signal.MarketSlug.StartsWith("0x"))
|
||||||
{
|
{
|
||||||
var fetchedMarkets = await _api.GetMarketsByEventSlugAsync(signal.MarketSlug);
|
var fetchedMarkets = await _api.GetMarketsByEventSlugAsync(signal.MarketSlug);
|
||||||
foreach (var fetched in fetchedMarkets) {
|
foreach (var fetched in fetchedMarkets) {
|
||||||
marketColl.Upsert(fetched);
|
_marketRepo.Upsert(fetched);
|
||||||
if (fetched.ClobTokenIds != null && fetched.ClobTokenIds.Contains(signal.TokenId)) marketData = fetched;
|
if (fetched.ClobTokenIds != null && fetched.ClobTokenIds.Contains(signal.TokenId)) marketData = fetched;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -531,10 +534,10 @@ namespace PolyTraderSharp.Services
|
|||||||
return old;
|
return old;
|
||||||
});
|
});
|
||||||
|
|
||||||
if (_db != null) _db.GetCollection<Position>($"demo_positions_{account.AccountId}").Upsert(finalPos);
|
_positionRepo.UpsertDemo(account.AccountId, finalPos);
|
||||||
|
|
||||||
account.UpdateBalance(account.AvailableBalance - exactUsdc);
|
account.UpdateBalance(account.AvailableBalance - exactUsdc);
|
||||||
if (_db != null) _db.GetCollection<AccountState>("accounts").Upsert(account);
|
_accountRepo.Upsert(account);
|
||||||
_logger.Trade($"✅ [DEMO AUSGEFÜHRT]\n" +
|
_logger.Trade($"✅ [DEMO AUSGEFÜHRT]\n" +
|
||||||
$" Konto: {account.Name}\n" +
|
$" Konto: {account.Name}\n" +
|
||||||
$" Markt: {signal.MarketQuestion}\n" +
|
$" Markt: {signal.MarketQuestion}\n" +
|
||||||
@@ -576,17 +579,13 @@ namespace PolyTraderSharp.Services
|
|||||||
});
|
});
|
||||||
|
|
||||||
account.UpdateBalance(account.AvailableBalance - exactUsdc);
|
account.UpdateBalance(account.AvailableBalance - exactUsdc);
|
||||||
if (_db != null) _db.GetCollection<AccountState>("accounts").Upsert(account);
|
_accountRepo.Upsert(account);
|
||||||
|
|
||||||
if (_db != null)
|
if (account.OpenPositions.TryGetValue(signal.TokenId, out var savedPos))
|
||||||
{
|
{
|
||||||
var liveCol = _db.GetCollection<Position>($"open_positions_{account.AccountId}");
|
_positionRepo.UpsertLive(account.AccountId, savedPos);
|
||||||
if (account.OpenPositions.TryGetValue(signal.TokenId, out var savedPos))
|
|
||||||
{
|
|
||||||
liveCol.Upsert(savedPos);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Track order placement time for stale order cleanup
|
// Track order placement time for stale order cleanup
|
||||||
string orderKey = $"{account.AccountId}_{signal.TokenId}";
|
string orderKey = $"{account.AccountId}_{signal.TokenId}";
|
||||||
_state.PendingOrderTimestamps[orderKey] = (DateTime.UtcNow, signal.TraderId);
|
_state.PendingOrderTimestamps[orderKey] = (DateTime.UtcNow, signal.TraderId);
|
||||||
@@ -644,14 +643,14 @@ namespace PolyTraderSharp.Services
|
|||||||
{
|
{
|
||||||
if (account.IsDemo)
|
if (account.IsDemo)
|
||||||
{
|
{
|
||||||
if (_db != null) _db.GetCollection<Position>($"demo_positions_{account.AccountId}").Delete(signal.TokenId);
|
_positionRepo.DeleteDemo(account.AccountId, signal.TokenId);
|
||||||
|
|
||||||
decimal exitUsd = openPos.Size * signal.Price;
|
decimal exitUsd = openPos.Size * signal.Price;
|
||||||
decimal realizedPnl = exitUsd - openPos.AmountUsd;
|
decimal realizedPnl = exitUsd - openPos.AmountUsd;
|
||||||
|
|
||||||
_state.GlobalPnl += realizedPnl;
|
_state.GlobalPnl += realizedPnl;
|
||||||
account.UpdateBalance(account.AvailableBalance + exitUsd);
|
account.UpdateBalance(account.AvailableBalance + exitUsd);
|
||||||
if (_db != null) _db.GetCollection<AccountState>("accounts").Upsert(account);
|
_accountRepo.Upsert(account);
|
||||||
|
|
||||||
var ct = new ClosedTrade
|
var ct = new ClosedTrade
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user