- ModuleView liefert jetzt ein Form (CreateForm statt CreateControl); die 4 Views (Terminal, Settings, Jobs, Dashboard) von UserControl auf Form umgestellt (im Designer als Fenster bearbeitbar). ViewHostForm entfernt. - ShellUiHost verwaltet offene Forms: Einzelinstanz, bereits offenes Fenster wird in den Vordergrund geholt, OpenStateChanged-Event. - LauncherForm: Fenster-Buttons an View-IDs gebunden; offene Fenster werden am Button markiert (Checked), erneuter Klick holt das Fenster nach vorn. - Build 0 Fehler. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
89 lines
3.3 KiB
C#
89 lines
3.3 KiB
C#
using System;
|
|
using System.ComponentModel;
|
|
using System.Linq;
|
|
using System.Windows.Forms;
|
|
using PolyTrader.Core.Persistence;
|
|
|
|
namespace PolyTraderSharp.Ui.Views
|
|
{
|
|
/// <summary>
|
|
/// Modulübergreifendes Dashboard: zeigt die letzten Trades ALLER Module aus dem
|
|
/// generischen Core-Trade-Log (ITradeLogRepository) und eine Kurzauswertung.
|
|
/// Designbar (DashboardView.Designer.cs).
|
|
/// </summary>
|
|
public partial class DashboardView : Form
|
|
{
|
|
private ITradeLogRepository? _tradeLog;
|
|
private TradingState? _state;
|
|
|
|
public DashboardView()
|
|
{
|
|
InitializeComponent();
|
|
colEntry.DefaultCellStyle.Format = "F3";
|
|
colExit.DefaultCellStyle.Format = "F3";
|
|
colSize.DefaultCellStyle.Format = "F2";
|
|
colPnl.DefaultCellStyle.Format = "F2";
|
|
colPnlPct.DefaultCellStyle.Format = "F1";
|
|
colClosedAt.DefaultCellStyle.Format = "dd.MM.yyyy HH:mm";
|
|
btnRefresh.Click += (_, _) => LoadData();
|
|
}
|
|
|
|
public void Initialize(ITradeLogRepository tradeLog, TradingState state)
|
|
{
|
|
_tradeLog = tradeLog;
|
|
_state = state;
|
|
LoadData();
|
|
}
|
|
|
|
private void LoadData()
|
|
{
|
|
if (_tradeLog == null) return;
|
|
|
|
var rows = _tradeLog.GetRecent(300).Select(r => new DashboardTradeRow
|
|
{
|
|
Module = r.ModuleName,
|
|
Account = ResolveAccount(r.AccountId, r.IsDemo),
|
|
Market = r.MarketQuestion,
|
|
Outcome = r.Outcome,
|
|
Side = r.Side,
|
|
EntryPrice = r.EntryPrice,
|
|
ExitPrice = r.ExitPrice,
|
|
Size = r.Size,
|
|
RealizedPnl = r.RealizedPnl,
|
|
PnlPercent = r.PnlPercent,
|
|
ClosedAt = r.ClosedAt
|
|
}).ToList();
|
|
|
|
dgvTrades.DataSource = new BindingList<DashboardTradeRow>(rows);
|
|
|
|
decimal totalPnl = rows.Sum(x => x.RealizedPnl);
|
|
var perModule = rows.GroupBy(x => x.Module).Select(g => $"{g.Key}: {g.Count()}");
|
|
lblSummary.Text = $"{rows.Count} Trades | PnL gesamt: {totalPnl:F2} USDC | {string.Join(" · ", perModule)}";
|
|
}
|
|
|
|
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}";
|
|
}
|
|
}
|
|
|
|
/// <summary>Anzeige-Zeile für das Dashboard-Grid (Account bereits zu Name aufgelöst).</summary>
|
|
public class DashboardTradeRow
|
|
{
|
|
public string Module { get; set; } = string.Empty;
|
|
public string Account { get; set; } = string.Empty;
|
|
public string Market { 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 DateTime ClosedAt { get; set; }
|
|
}
|
|
}
|