Phase 5.3-ClosedTrade: ClosedTrade -> Modul + ICopyTradeLogRepository

- ClosedTrade (+ ClosedTradeRow) nach src/PolyTrader.Modules.CopyTrading/Models/.
- Neues ICopyTradeLogRepository (+ Mongo-Impl) im Modul: EnsureIndexes, Exists,
  Insert, Find(predicate) auf der closed_trades-Collection.
- closed_trades-Zugriffe der Modul-Services vom App-Shim auf das Repo umgestellt:
  TraderMonitorService, PersistenceService, PolymarketWssClient, TraderAnalyticsJob.
  Shim-/DB-Usings dort entfernt.
- TraderMonitorService nutzt kein _db mehr (auch die uebrigen _db-Guards aus 3d
  entfernt, da Repos immer verfuegbar sind). Verhaltensneutral.
- frm_main (UI) + Program.cs (BsonDocument-Cleanup) bleiben auf _db.
- Build 0 Fehler.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Richard
2026-07-01 22:27:22 +02:00
co-authored by Claude Opus 4.8
parent 3be75c0f05
commit 88fc982089
8 changed files with 122 additions and 73 deletions
@@ -0,0 +1,36 @@
namespace PolyTraderSharp.Models
{
public class ClosedTrade
{
[MongoDB.Bson.Serialization.Attributes.BsonId] public int TradeId { get; set; }
public int AccountId { get; set; }
public int SourceTraderId { get; set; }
public bool IsDemo { get; set; }
public string TokenId { get; set; } = string.Empty;
public string MarketSlug { get; set; } = string.Empty;
public string MarketQuestion { get; set; } = string.Empty;
public string Outcome { get; set; } = string.Empty;
public string Side { get; set; } = string.Empty;
public decimal EntryPrice { get; set; }
public decimal ExitPrice { get; set; }
public decimal Size { get; set; }
public decimal RealizedPnl { get; set; }
public decimal PnlPercent { get; set; }
public decimal TotalFees { get; set; }
public DateTime OpenedAt { get; set; }
public DateTime ClosedAt { get; set; }
public string ExitReason { get; set; } = string.Empty;
}
public class ClosedTradeRow : ClosedTrade
{
public string AccountName { get; set; } = string.Empty;
public string SourceTraderName { get; set; } = string.Empty;
[System.ComponentModel.Browsable(false)]
public string SourceTraderAddress { get; set; } = string.Empty;
}
}
@@ -0,0 +1,25 @@
using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using PolyTraderSharp.Models;
namespace PolyTrader.Modules.CopyTrading.Persistence
{
/// <summary>
/// Copytrading-eigener Trade-Log (Collection "closed_trades"). Enthält die kopierten,
/// geschlossenen Trades mit Copytrading-Details (SourceTraderId etc.).
/// Ergänzt später den generischen Core-Trade-Log (TradeRecord).
/// </summary>
public interface ICopyTradeLogRepository
{
void EnsureIndexes();
/// <summary>Prüft, ob für Account + TokenId bereits ein Eintrag existiert (Dedup).</summary>
bool Exists(int accountId, string tokenId);
void Insert(ClosedTrade trade);
/// <summary>Generische Abfrage (ersetzt die bisherigen LiteFind-Zugriffe).</summary>
List<ClosedTrade> Find(Expression<Func<ClosedTrade, bool>> predicate);
}
}
@@ -0,0 +1,45 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using MongoDB.Driver;
using PolyTraderSharp.Models;
namespace PolyTrader.Modules.CopyTrading.Persistence
{
public class MongoCopyTradeLogRepository : ICopyTradeLogRepository
{
private readonly IMongoCollection<ClosedTrade> _col;
public MongoCopyTradeLogRepository(IMongoDatabase db)
{
_col = db.GetCollection<ClosedTrade>("closed_trades");
}
public void EnsureIndexes()
{
CreateIndex(x => x.TradeId);
CreateIndex(x => x.AccountId);
CreateIndex(x => x.TokenId);
CreateIndex(x => x.SourceTraderId);
}
private void CreateIndex(Expression<Func<ClosedTrade, object>> field)
{
try
{
var keys = Builders<ClosedTrade>.IndexKeys.Ascending(field);
_col.Indexes.CreateOne(new CreateIndexModel<ClosedTrade>(keys));
}
catch { }
}
public bool Exists(int accountId, string tokenId) =>
_col.Find(x => x.AccountId == accountId && x.TokenId == tokenId).Any();
public void Insert(ClosedTrade trade) => _col.InsertOne(trade);
public List<ClosedTrade> Find(Expression<Func<ClosedTrade, bool>> predicate) =>
_col.Find(predicate).ToList();
}
}