using System; using System.ComponentModel; using System.Linq; using System.Windows.Forms; using PolyTrader.Modules.CopyTrading.Persistence; using PolyTraderSharp; using PolyTraderSharp.Models; namespace PolyTrader.Modules.CopyTrading.Ui { /// /// Zeigt die geschlossenen Copytrades des Moduls (mod_copytrading_closed_trades) mit /// aufgelösten Account-/Master-Trader-Namen und einer Kurzauswertung. /// Layout im Designer (ClosedTradesView.Designer.cs), Daten/Logik hier. /// public partial class ClosedTradesView : Form { private ICopyTradeLogRepository? _tradeLog; private TradingState? _state; private CopyTradingState? _copyState; // Parameterloser Konstruktor für den WinForms-Designer. public ClosedTradesView() { InitializeComponent(); colEntry.DefaultCellStyle.Format = "F3"; colExit.DefaultCellStyle.Format = "F3"; colSize.DefaultCellStyle.Format = "F2"; colPnl.DefaultCellStyle.Format = "F2"; colPnlPct.DefaultCellStyle.Format = "F1"; colOpenedAt.DefaultCellStyle.Format = "dd.MM.yyyy HH:mm"; colClosedAt.DefaultCellStyle.Format = "dd.MM.yyyy HH:mm"; btnRefresh.Click += (_, _) => LoadData(); } /// Injiziert die Abhängigkeiten (nach der DI-Auflösung) und lädt die Daten. public void Initialize(ICopyTradeLogRepository tradeLog, TradingState state, CopyTradingState copyState) { _tradeLog = tradeLog; _state = state; _copyState = copyState; LoadData(); } private void LoadData() { if (_tradeLog == null) return; var rows = _tradeLog.Find(_ => true) .OrderByDescending(t => t.ClosedAt) .Select(t => new ClosedTradeRow { TradeId = t.TradeId, AccountId = t.AccountId, SourceTraderId = t.SourceTraderId, IsDemo = t.IsDemo, TokenId = t.TokenId, MarketSlug = t.MarketSlug, MarketQuestion = t.MarketQuestion, Outcome = t.Outcome, Side = t.Side, EntryPrice = t.EntryPrice, ExitPrice = t.ExitPrice, Size = t.Size, RealizedPnl = t.RealizedPnl, PnlPercent = t.PnlPercent, TotalFees = t.TotalFees, OpenedAt = t.OpenedAt, ClosedAt = t.ClosedAt, ExitReason = t.ExitReason, AccountName = ResolveAccount(t.AccountId, t.IsDemo), SourceTraderName = ResolveTrader(t.SourceTraderId) }) .ToList(); dgvTrades.DataSource = new BindingList(rows); decimal totalPnl = rows.Sum(x => x.RealizedPnl); int wins = rows.Count(x => x.RealizedPnl > 0); double winrate = rows.Count > 0 ? (double)wins / rows.Count * 100 : 0; lblSummary.Text = $"{rows.Count} Trades | PnL gesamt: {totalPnl:F2} USDC | Winrate: {winrate:F1}%"; } private string ResolveAccount(int accountId, bool isDemo) { string suffix = isDemo ? " (Demo)" : ""; if (_state != null && _state.Accounts.TryGetValue(accountId, out var acc) && !string.IsNullOrEmpty(acc.Name)) return acc.Name + suffix; return $"#{accountId}{suffix}"; } private string ResolveTrader(int traderId) { if (_copyState != null && _copyState.Traders.TryGetValue(traderId, out var t) && !string.IsNullOrEmpty(t.DisplayName)) return t.DisplayName; return traderId > 0 ? $"#{traderId}" : "Unbekannt"; } } }