Files
PolyTraderSharp/src/PolyTrader.Web/wwwroot/index.html
T
RichardandClaude Opus 5 dcc764dec1
CI / Build & Tests (Linux) (push) Canceled after 0s
CI / Plattformneutralität & Hygiene (push) Canceled after 0s
WebUI: Module, Analytics und Buchhaltung als eigene Ansichten
Das WebGUI konnte bisher Dashboard, Konten, Jobs, Logs und Einstellungen.
Die vier Strategie- und Analysemodule waren nur in der Avalonia-Oberflaeche
erreichbar - wer den Server aus der Ferne bediente, sah sie nicht.

Fuenf neue Endpunktgruppen holen sie herein:

  /api/analytics                  KPIs, Equity-Kurve, PnL je Modul und Tag,
                                  durchsuchbare Trade-Historie mit Seitenlauf
  /api/modules/copytrading        Master-Trader (CRUD), offene und
                                  geschlossene Trades, Risikolimits je Konto
  /api/modules/resolutionfarming  Scanner-Kandidaten, Positionen, Historie,
                                  Farming-Parameter je Konto
  /api/modules/supervisor         Profile, Agentenfragen, Berichtsarchiv,
                                  Signal-Dossiers, Counterfactuals
  /api/modules/accounting         BWA-Periodenabrechnung, Ledger-Journal,
                                  PDF- und CSV-Export, Ingest-Laeufe

Dazu im Bestand:
- Dashboard bekommt /overview-widgets: Modul-KPIs (heute/7T/30T), auffaellige
  Trades der letzten 24 Stunden, Warnungen und Fehler des Tages, den letzten
  Supervisor-Bericht.
- Die Kontenliste zeigt 3-Tage-PnL, Winrate, Gesamtergebnis und die
  beteiligten Module statt nur Salden.
- Jobs lassen sich ueber /toggle und /state ein- und ausschalten, nicht nur
  ausloesen.

Die Oberflaeche bleibt ohne Fremdbibliotheken: alle Diagramme sind Inline-SVG,
kein CDN, kein npm. Alle neuen Pfade liegen unter /api/ und damit hinter der
bestehenden Token-Pruefung.

Zwei Fehler nebenbei behoben:

- AccountingReportService.ResolveCurrency lief in eine NullReferenceException,
  wenn der FX-Dienst nicht gesetzt war. Betrifft jeden EUR-Aufruf ohne
  geladene EZB-Kurse.
- Ein Master-Trader, dessen Name ein Apostroph enthaelt, hatte einen toten
  Loeschen-Knopf: escapeHtml laesst ' unberuehrt, und im onclick-Attribut
  beendete das Zeichen das JavaScript-Literal vorzeitig. Laengerer Text mit
  Anfuehrungszeichen konnte darueber eigenen Code einschleusen. Neu setzt
  jsArg() den Wert als JSON-Literal ein; geprueft mit
  O'Brien "quote" <b>bold</b> \ backslash.

McpLightServerTests weicht jetzt aus, wenn HttpListener mangels URL-ACL nicht
binden darf, statt den Lauf scheitern zu lassen.

Geprueft auf der Linux-Test-VM (Ubuntu 26.04, .NET 10): Build ohne Fehler,
533 von 533 Tests bestanden, alle 11 Ansichten und 15 Unteransichten geladen,
alle Endpunkte mit 200 beantwortet, Schreibwege bis in die Datenbank
nachverfolgt, PDF- und CSV-Export gueltig, SSE-Logstrom live.

Offene Befunde aus der Abnahme liegen als #532 (Kopfleiste laeuft unter
1623 px ueber), #533 (EUR-PDF ohne EZB-Kurse liefert Nullbetraege) und #534
(Einstellungen melden Erfolg trotz gescheitertem Speichern) im Bugtracker.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-10 09:17:49 +02:00

1237 lines
74 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>PolyTrader Web</title>
<link rel="stylesheet" href="/css/app.css">
</head>
<body>
<header class="app-header">
<div class="header-brand">
<span>📈</span>
<span>PolyTrader</span>
<span style="font-size: 11px; padding: 2px 6px; background: var(--accent-soft); color: var(--accent); border-radius: 4px; font-weight: normal;">WebGUI</span>
</div>
<nav class="header-nav">
<button class="nav-link active" onclick="switchView('dashboard')">Dashboard</button>
<button class="nav-link" onclick="switchView('analytics')">Analytics</button>
<button class="nav-link" onclick="switchView('copytrading')">CopyTrading</button>
<button class="nav-link" onclick="switchView('resolutionfarming')">Resolution Farming</button>
<button class="nav-link" onclick="switchView('supervisor')">Supervisor</button>
<button class="nav-link" onclick="switchView('accounting')">Accounting</button>
<button class="nav-link" onclick="switchView('accounts')">Konten</button>
<button class="nav-link" onclick="switchView('jobs')">Jobs</button>
<button class="nav-link" onclick="switchView('logs')">Terminal / Logs</button>
<button class="nav-link" onclick="switchView('modules')">Module</button>
<button class="nav-link" onclick="switchView('settings')">Einstellungen</button>
</nav>
<div class="header-actions">
<div class="status-indicator" title="Polymarket / Alchemy Connection">
<span class="dot" id="dotAlchemy"></span>
<span>WSS</span>
</div>
<div class="status-indicator" title="Mullvad VPN Status">
<span class="dot" id="dotVpn"></span>
<span>VPN</span>
</div>
<div class="status-indicator" title="Watchdog Heartbeat">
<span class="dot" id="dotWatchdog"></span>
<span>Watchdog</span>
</div>
<button class="btn btn-secondary" style="padding: 4px 10px; font-size: 12px;" onclick="logout()">Abmelden</button>
</div>
</header>
<main class="app-main">
<!-- VIEW: DASHBOARD -->
<section id="view-dashboard" class="view-panel active">
<div class="grid-4">
<div class="card">
<div class="card-title">Gesamt PnL</div>
<div class="card-value" id="valGlobalPnl">0.00 $</div>
<div class="card-sub">Über alle aktiven Module</div>
</div>
<div class="card">
<div class="card-title">USDC Guthaben</div>
<div class="card-value" id="valTotalUsdc">0.00 $</div>
<div class="card-sub" id="valAccountCount">0 Konten aktiv</div>
</div>
<div class="card">
<div class="card-title">Portfolio-Gesamtwert</div>
<div class="card-value" id="valPortfolioValue">0.00 $</div>
<div class="card-sub">Guthaben + Positionen</div>
</div>
<div class="card">
<div class="card-title">Notfall-Pause</div>
<button class="btn btn-danger" id="btnPause" style="width: 100%; margin-top: 6px;" onclick="togglePause()">
Trading pausieren
</button>
</div>
</div>
<div class="grid-2">
<div class="card">
<div class="card-title">Live Trading Modus</div>
<div style="font-size: 13px; color: var(--muted);">Echtgeld-Ausführung auf Polymarket</div>
<div class="toggle-group" id="groupLiveTrading">
<button class="btn-toggle" onclick="setTradingMode('live', 'Inactive')">Inaktiv</button>
<button class="btn-toggle" onclick="setTradingMode('live', 'SellOnly')">Nur Verkauf</button>
<button class="btn-toggle" onclick="setTradingMode('live', 'Active')">Aktiv</button>
</div>
</div>
<div class="card">
<div class="card-title">Demo Trading Modus</div>
<div style="font-size: 13px; color: var(--muted);">Papertrading und Simulation</div>
<div class="toggle-group" id="groupDemoTrading">
<button class="btn-toggle" onclick="setTradingMode('demo', 'Inactive')">Inaktiv</button>
<button class="btn-toggle" onclick="setTradingMode('demo', 'SellOnly')">Nur Verkauf</button>
<button class="btn-toggle" onclick="setTradingMode('demo', 'Active')">Aktiv</button>
</div>
</div>
</div>
<!-- Modul-KPIs -->
<div class="dashboard-section-title">Modul-KPIs</div>
<div class="kpi-tiles-grid" id="dashModuleKpis">
<div class="card" style="padding: 12px; color: var(--muted); font-size: 13px;">Lade Modul-KPIs …</div>
</div>
<!-- Account-Übersicht -->
<div class="dashboard-section-title">Account-Übersicht</div>
<div class="table-container">
<table>
<thead>
<tr>
<th>Account</th>
<th>Module</th>
<th>Polymarket</th>
<th>Wallet (USDC)</th>
<th>3T PnL</th>
<th>3T Winrate %</th>
<th>Overall P/L</th>
</tr>
</thead>
<tbody id="tblDashAccounts">
<tr><td colspan="7" style="text-align: center; color: var(--muted);">Lade Konten-Übersicht …</td></tr>
</tbody>
</table>
</div>
<!-- Live-Überblick Widgets (3 Spalten) -->
<div class="dashboard-section-title">Live-Überblick</div>
<div class="grid-3">
<!-- Auffällige Trades (24h) -->
<div class="card widget-card">
<div class="card-title">
<span>Auffällige Trades (24h)</span>
<span style="font-size: 11px; color: var(--muted);" id="badgeNotableCount">0</span>
</div>
<div class="widget-table-container">
<table class="compact-table">
<thead>
<tr>
<th>Modul</th>
<th>Markt</th>
<th>PnL</th>
<th>PnL %</th>
</tr>
</thead>
<tbody id="tblNotableTrades">
<tr><td colspan="4" style="text-align: center; color: var(--muted);">Lade Trades …</td></tr>
</tbody>
</table>
</div>
</div>
<!-- Warnungen & Fehler (heute) -->
<div class="card widget-card">
<div class="card-title">
<span id="titleAlerts">Warnungen & Fehler (heute)</span>
<span style="font-size: 11px; color: var(--muted);" id="badgeAlertsCount">0</span>
</div>
<div class="widget-logs-container" id="containerAlerts">
<div style="color: var(--muted); padding: 8px 0; text-align: center;">Keine Warnungen heute.</div>
</div>
</div>
<!-- Supervisor-KI (letzter Bericht) -->
<div class="card widget-card">
<div class="card-title">
<span id="titleSupervisor">Supervisor-KI (letzter Bericht)</span>
<span style="font-size: 11px; color: var(--muted);" id="badgeSupervisorTime">—</span>
</div>
<div class="supervisor-snippet" id="snippetSupervisor">
Lade Supervisor-Bericht …
</div>
</div>
</div>
</section>
<!-- VIEW: ANALYTICS -->
<section id="view-analytics" class="view-panel">
<!-- Filter Toolbar -->
<div class="analytics-toolbar">
<div class="toolbar-group">
<button class="btn btn-primary btn-sm" onclick="loadAnalytics()">Aktualisieren</button>
<div class="toolbar-item">
<label for="selAnalyticsAccount">Konto:</label>
<select id="selAnalyticsAccount" class="form-input form-select" onchange="onAnalyticsFilterChanged()">
<option value="-1">Alle Konten</option>
</select>
</div>
<div class="toolbar-item">
<label for="selAnalyticsModule">Modul:</label>
<select id="selAnalyticsModule" class="form-input form-select" onchange="onAnalyticsFilterChanged()">
<option value="Alle Module">Alle Module</option>
</select>
</div>
<div class="toolbar-item">
<label for="selAnalyticsMode">Modus:</label>
<select id="selAnalyticsMode" class="form-input form-select" onchange="onAnalyticsFilterChanged()">
<option value="Alle">Alle</option>
<option value="Live">Live</option>
<option value="Demo">Demo</option>
</select>
</div>
<div class="toolbar-item">
<label for="selAnalyticsRange">Zeitraum:</label>
<select id="selAnalyticsRange" class="form-input form-select" onchange="onAnalyticsFilterChanged()">
<option value="7">7 Tage</option>
<option value="30" selected>30 Tage</option>
<option value="90">90 Tage</option>
<option value="0">Alle</option>
</select>
</div>
</div>
<div class="analytics-subnav">
<button class="subnav-tab active" id="tabBtnAnalyticsCharts" onclick="switchAnalyticsSubTab('charts')">Auswertung &amp; Diagramme</button>
<button class="subnav-tab" id="tabBtnAnalyticsHistory" onclick="switchAnalyticsSubTab('history')">Tradehistorie</button>
</div>
</div>
<!-- SUB-TAB 1: CHARTS & KPIS -->
<div id="analyticsSubTabCharts" class="analytics-subtab active">
<!-- 5 KPI Cards -->
<div class="grid-5" style="margin-bottom: 20px;">
<div class="card kpi-card">
<div class="card-title">Netto-PnL</div>
<div class="card-value" id="kpiNetPnl">0.00 $</div>
<div class="card-sub">Realisierter Gewinn/Verlust</div>
</div>
<div class="card kpi-card">
<div class="card-title">Winrate</div>
<div class="card-value" id="kpiWinRate">0.0 %</div>
<div class="card-sub">Anteil profitabler Trades</div>
</div>
<div class="card kpi-card">
<div class="card-title">Trades</div>
<div class="card-value" id="kpiTradeCount">0</div>
<div class="card-sub">Ausgeführte Abschlüsse</div>
</div>
<div class="card kpi-card">
<div class="card-title">Ø PnL / Trade</div>
<div class="card-value" id="kpiAvgPnl">0.00 $</div>
<div class="card-sub">Durchschnittliches Ergebnis</div>
</div>
<div class="card kpi-card">
<div class="card-title">Profit-Faktor</div>
<div class="card-value" id="kpiProfitFactor">0.00</div>
<div class="card-sub">Bruttogewinn / -verlust</div>
</div>
</div>
<!-- 3 Charts Grid -->
<!-- Top Chart: Equity Curve (Full Width) -->
<div class="card chart-card" style="margin-bottom: 20px;">
<div class="card-title">
<span>Equity-Kurve (kumulierter PnL)</span>
<span style="font-size: 11px; color: var(--muted);" id="lblEquityTradesCount">0 Datenpunkte</span>
</div>
<div class="chart-container" id="containerEquityChart">
<svg id="svgEquityChart" class="chart-svg"></svg>
</div>
</div>
<!-- Bottom 2 Charts: PnL by Module & PnL by Day -->
<div class="grid-2">
<div class="card chart-card">
<div class="card-title">PnL je Modul</div>
<div class="chart-container" id="containerModuleChart">
<svg id="svgModuleChart" class="chart-svg"></svg>
</div>
</div>
<div class="card chart-card">
<div class="card-title">PnL je Tag</div>
<div class="chart-container" id="containerDayChart">
<svg id="svgDayChart" class="chart-svg"></svg>
</div>
</div>
</div>
</div>
<!-- SUB-TAB 2: TRADEHISTORIE -->
<div id="analyticsSubTabHistory" class="analytics-subtab" style="display: none;">
<!-- Filter Bar -->
<div class="history-toolbar">
<div style="display: flex; gap: 12px; align-items: center; flex-wrap: wrap;">
<div class="toolbar-item" style="flex: 1; min-width: 250px;">
<label for="tbHistorySearch">Suche:</label>
<input type="text" id="tbHistorySearch" class="form-input" placeholder="Markt oder Outcome suchen …" oninput="onHistorySearchInput()">
</div>
<div class="toolbar-item">
<label for="selHistoryWinLoss">Ergebnis:</label>
<select id="selHistoryWinLoss" class="form-input form-select" onchange="onHistoryWinLossChanged()">
<option value="Alle">Alle</option>
<option value="Gewinner">Nur Gewinner</option>
<option value="Verlierer">Nur Verlierer</option>
</select>
</div>
</div>
</div>
<!-- Trades Table -->
<div class="table-container" style="margin-top: 14px;">
<table>
<thead>
<tr>
<th>Zeitpunkt</th>
<th>Modul</th>
<th>Account</th>
<th>Modus</th>
<th>Markt</th>
<th>Outcome</th>
<th>Side</th>
<th>Entry</th>
<th>Exit</th>
<th>Size</th>
<th>PnL</th>
<th>PnL %</th>
</tr>
</thead>
<tbody id="tblAnalyticsTrades">
<tr><td colspan="12" style="text-align: center; color: var(--muted);">Lade Trades …</td></tr>
</tbody>
</table>
</div>
<!-- Pagination -->
<div class="pagination-bar" id="historyPagination">
<span id="lblPaginationInfo" style="color: var(--muted); font-size: 13px;">Zeige 0 von 0 Trades</span>
<div style="display: flex; gap: 6px;">
<button class="btn btn-secondary btn-sm" id="btnPrevPage" onclick="changeAnalyticsPage(-1)">◀ Vorherige</button>
<span id="lblCurrentPage" style="padding: 4px 10px; font-weight: 600; font-size: 13px;">1</span>
<button class="btn btn-secondary btn-sm" id="btnNextPage" onclick="changeAnalyticsPage(1)">Nächste ▶</button>
</div>
</div>
</div>
</section>
<!-- VIEW: COPYTRADING -->
<section id="view-copytrading" class="view-panel">
<div class="module-toolbar">
<div style="display: flex; gap: 8px; align-items: center;">
<span style="font-size: 16px; font-weight: 700; color: var(--text);">CopyTrading Modul</span>
<span class="badge" style="background: rgba(34, 197, 94, 0.15); color: var(--positive); border: 1px solid var(--positive);">Aktiv</span>
</div>
<div class="module-tabs">
<button class="module-tab-btn active" id="ctTabBtn-traders" onclick="switchCtTab('traders')">Master-Trader</button>
<button class="module-tab-btn" id="ctTabBtn-open" onclick="switchCtTab('open')">Offene Positionen</button>
<button class="module-tab-btn" id="ctTabBtn-closed" onclick="switchCtTab('closed')">Geschlossene Trades</button>
<button class="module-tab-btn" id="ctTabBtn-settings" onclick="switchCtTab('settings')">Account-Einstellungen</button>
</div>
<div style="margin-left: auto; display: flex; gap: 8px;">
<button class="btn btn-secondary" onclick="refreshCurrentCtTab()">Aktualisieren</button>
</div>
</div>
<!-- CT SUBTAB: TRADERS -->
<div id="ctTab-traders" class="ct-tab-content active">
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 14px;">
<div style="font-size: 14px; color: var(--muted);" id="ctTradersSummary">Lade Master-Trader …</div>
<button class="btn btn-primary" onclick="openTraderModal(null)">+ Neuer Master-Trader</button>
</div>
<div class="table-container">
<table>
<thead>
<tr>
<th style="width: 50px;">ID</th>
<th>Name</th>
<th>Wallet</th>
<th>Kategorie</th>
<th>Status</th>
<th>Auto-Pause</th>
<th>Maker</th>
<th style="text-align: right;">Winrate (30T)</th>
<th style="text-align: right;">Copy-PnL (30T)</th>
<th style="text-align: right;">Profit-Faktor</th>
<th>Konten</th>
<th style="text-align: center; width: 140px;">Aktionen</th>
</tr>
</thead>
<tbody id="ctTradersTbody">
<tr><td colspan="12" style="text-align: center; color: var(--muted);">Lade Master-Trader …</td></tr>
</tbody>
</table>
</div>
</div>
<!-- CT SUBTAB: OPEN TRADES -->
<div id="ctTab-open" class="ct-tab-content" style="display: none;">
<div style="margin-bottom: 14px; font-size: 13px; color: var(--muted);" id="ctOpenSummary">Lade offene Positionen …</div>
<div class="table-container">
<table>
<thead>
<tr>
<th>Konto</th>
<th>Master-Trader</th>
<th>Marktfrage</th>
<th>Outcome</th>
<th>Side</th>
<th style="text-align: right;">Einstieg</th>
<th style="text-align: right;">Aktuell</th>
<th style="text-align: right;">Shares</th>
<th style="text-align: right;">Einsatz</th>
<th style="text-align: right;">Buchgewinn</th>
<th>Status</th>
<th>Eröffnet</th>
</tr>
</thead>
<tbody id="ctOpenTbody">
<tr><td colspan="12" style="text-align: center; color: var(--muted);">Lade offene Positionen …</td></tr>
</tbody>
</table>
</div>
</div>
<!-- CT SUBTAB: CLOSED TRADES -->
<div id="ctTab-closed" class="ct-tab-content" style="display: none;">
<div class="module-toolbar" style="margin-top: 0; padding: 10px 14px;">
<div style="display: flex; gap: 12px; align-items: center; flex-wrap: wrap; flex: 1;">
<div class="toolbar-item">
<label for="ctClosedFilterTrader">Master:</label>
<select id="ctClosedFilterTrader" class="form-input form-select" onchange="loadCtClosedTrades(1)">
<option value="0">Alle Master</option>
</select>
</div>
<div class="toolbar-item">
<label for="ctClosedFilterResult">Ergebnis:</label>
<select id="ctClosedFilterResult" class="form-input form-select" onchange="loadCtClosedTrades(1)">
<option value="Alle">Alle</option>
<option value="Gewinner">Nur Gewinner</option>
<option value="Verlierer">Nur Verlierer</option>
</select>
</div>
<div class="toolbar-item" style="flex: 1; min-width: 200px;">
<input type="text" id="ctClosedSearch" class="form-input" placeholder="Suche in Markt / Outcome …" oninput="debounceCtClosedSearch()">
</div>
</div>
<div style="font-size: 13px; color: var(--muted);" id="ctClosedSummary">0 Trades</div>
</div>
<div class="table-container">
<table>
<thead>
<tr>
<th>ID</th>
<th>Konto</th>
<th>Master-Trader</th>
<th>Marktfrage</th>
<th>Outcome</th>
<th>Side</th>
<th style="text-align: right;">Einstieg</th>
<th style="text-align: right;">Exit</th>
<th style="text-align: right;">Shares</th>
<th style="text-align: right;">Realisierter PnL</th>
<th style="text-align: right;">Rendite</th>
<th>Geschlossen</th>
<th>Grund</th>
</tr>
</thead>
<tbody id="ctClosedTbody">
<tr><td colspan="13" style="text-align: center; color: var(--muted);">Lade Trades …</td></tr>
</tbody>
</table>
</div>
<div class="pagination-bar" id="ctClosedPagination">
<span id="ctClosedPageInfo" style="font-size: 13px; color: var(--muted);">Seite 1 von 1</span>
<div style="display: flex; gap: 6px;">
<button class="btn btn-secondary btn-sm" id="btnCtClosedPrev" onclick="changeCtClosedPage(-1)">◀ Vorherige</button>
<button class="btn btn-secondary btn-sm" id="btnCtClosedNext" onclick="changeCtClosedPage(1)">Nächste ▶</button>
</div>
</div>
</div>
<!-- CT SUBTAB: SETTINGS -->
<div id="ctTab-settings" class="ct-tab-content" style="display: none;">
<div class="card settings-form" style="max-width: 900px; margin: 0 auto;">
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 18px; border-bottom: 1px solid var(--border); padding-bottom: 12px;">
<div style="display: flex; gap: 10px; align-items: center;">
<label style="font-size: 13px; font-weight: 600;">Konto wählen:</label>
<select id="ctSettingsAccountSelect" class="form-input form-select" style="min-width: 220px;" onchange="loadCtSettingsForSelectedAccount()"></select>
</div>
<div id="ctSettingsStatus" style="font-size: 13px; color: var(--positive); display: none;">✓ Gespeichert</div>
</div>
<form id="ctSettingsForm" onsubmit="saveCtSettings(event)">
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 18px;">
<div class="form-row">
<label for="ctPerMarketLimit">Limit pro Markt (%)</label>
<input type="number" step="0.1" id="ctPerMarketLimit" class="form-input" required>
<div class="form-desc">Max. Einsatz in einen einzelnen Markt (als % des Guthabens).</div>
</div>
<div class="form-row">
<label for="ctPerMasterLimit">Limit pro Master (%)</label>
<input type="number" step="0.1" id="ctPerMasterLimit" class="form-input" required>
<div class="form-desc">Max. gleichzeitiger Gesamteinsatz für einen Master-Trader.</div>
</div>
<div class="form-row">
<label for="ctMaxBuyPrice">Max. Kaufpreis (0–1)</label>
<input type="number" step="0.01" id="ctMaxBuyPrice" class="form-input" min="0" max="1" required>
<div class="form-desc">Preis-Obergrenze (z. B. 0.98 = 98 ¢).</div>
</div>
<div class="form-row">
<label for="ctMaxPriceDiff">Max. Preisaufschlag BUY (%)</label>
<input type="number" step="0.1" id="ctMaxPriceDiff" class="form-input" required>
<div class="form-desc">Maximaler Limit-Aufschlag über dem Master-Einstiegspreis.</div>
</div>
<div class="form-row">
<label for="ctTime6h">Limit &lt; 6h Restlaufzeit (%)</label>
<input type="number" step="0.1" id="ctTime6h" class="form-input" required>
<div class="form-desc">Exposure-Deckel für kurzfristig auflösende Märkte.</div>
</div>
<div class="form-row">
<label for="ctTime24h">Limit 6–24h Restlaufzeit (%)</label>
<input type="number" step="0.1" id="ctTime24h" class="form-input" required>
<div class="form-desc">Exposure-Deckel für Märkte mit 6 bis 24h Restlaufzeit.</div>
</div>
<div class="form-row">
<label for="ctTime72h">Limit 24–72h Restlaufzeit (%)</label>
<input type="number" step="0.1" id="ctTime72h" class="form-input" required>
<div class="form-desc">Exposure-Deckel für Märkte mit 24 bis 72h Restlaufzeit.</div>
</div>
<div class="form-row">
<label for="ctTimeNone">Limit &gt; 72h / kein Datum (%)</label>
<input type="number" step="0.1" id="ctTimeNone" class="form-input" required>
<div class="form-desc">Exposure-Deckel für Märkte mit &gt; 72h Laufzeit.</div>
</div>
<div class="form-row">
<label for="ctProfitTarget">Take-Profit (% Gewinn)</label>
<input type="number" step="0.1" id="ctProfitTarget" class="form-input" required>
<div class="form-desc">Take-Profit-Schwelle in % Gewinn (9999 = deaktiviert).</div>
</div>
<div class="form-row">
<label for="ctPreRedeemLimit">Pre-Redeem-Schwelle (0–1)</label>
<input type="number" step="0.001" id="ctPreRedeemLimit" class="form-input" min="0" max="1" required>
<div class="form-desc">Vorzeitige Glattstellung (z. B. 0.995 = 99,5 ¢, 0 = aus).</div>
</div>
<div class="form-row">
<label for="ctSellFloorPct">SELL-Floor (%)</label>
<input type="number" step="0.1" id="ctSellFloorPct" class="form-input" required>
<div class="form-desc">Mindest-Verkaufspreis = Master-Exit minus diesen Prozentsatz.</div>
</div>
<div class="form-row">
<label for="ctMaxSpreadPct">Max. Spread BUY (%)</label>
<input type="number" step="0.1" id="ctMaxSpreadPct" class="form-input" required>
<div class="form-desc">Orderbuch-Filter gegen überhöhten Spread.</div>
</div>
</div>
<div style="margin-top: 20px; display: flex; gap: 10px; align-items: center;">
<button type="submit" class="btn btn-primary">Einstellungen speichern</button>
</div>
</form>
</div>
</div>
</section>
<!-- VIEW: RESOLUTION FARMING -->
<section id="view-resolutionfarming" class="view-panel">
<div class="module-toolbar">
<div style="display: flex; gap: 8px; align-items: center;">
<span style="font-size: 16px; font-weight: 700; color: var(--text);">Resolution Farming</span>
<span class="badge badge-accent">Favoriten-Arbitrage</span>
</div>
<div class="toolbar-item">
<label for="rfAccountSelect">Konto:</label>
<select id="rfAccountSelect" class="form-input form-select" style="min-width: 180px;" onchange="loadRfForSelectedAccount()"></select>
</div>
<div class="module-tabs">
<button class="module-tab-btn active" id="rfTabBtn-candidates" onclick="switchRfTab('candidates')">Kandidaten</button>
<button class="module-tab-btn" id="rfTabBtn-positions" onclick="switchRfTab('positions')">Offene Positionen</button>
<button class="module-tab-btn" id="rfTabBtn-history" onclick="switchRfTab('history')">Historie</button>
<button class="module-tab-btn" id="rfTabBtn-settings" onclick="switchRfTab('settings')">Einstellungen</button>
</div>
<div style="margin-left: auto; display: flex; gap: 8px;">
<button class="btn btn-secondary" onclick="refreshCurrentRfTab()">Aktualisieren</button>
</div>
</div>
<!-- RF SUBTAB: CANDIDATES -->
<div id="rfTab-candidates" class="rf-tab-content active">
<div style="margin-bottom: 14px; font-size: 13px; color: var(--muted);" id="rfCandidatesSummary">Lade Marktkandidaten …</div>
<div class="table-container">
<table>
<thead>
<tr>
<th>Zeitpunkt</th>
<th>Marktfrage</th>
<th>Outcome</th>
<th>Kategorie</th>
<th style="text-align: right;">Ask</th>
<th style="text-align: right;">Fee (bps)</th>
<th style="text-align: right;">Net Edge %</th>
<th style="text-align: right;">Score</th>
<th>Auflösung</th>
<th>Status</th>
<th>Ablehnungsgrund</th>
</tr>
</thead>
<tbody id="rfCandidatesTbody">
<tr><td colspan="11" style="text-align: center; color: var(--muted);">Lade Kandidaten …</td></tr>
</tbody>
</table>
</div>
</div>
<!-- RF SUBTAB: POSITIONS -->
<div id="rfTab-positions" class="rf-tab-content" style="display: none;">
<div style="margin-bottom: 14px; font-size: 13px; color: var(--muted);" id="rfPositionsSummary">Lade offene Positionen …</div>
<div class="table-container">
<table>
<thead>
<tr>
<th>Konto</th>
<th>Marktfrage</th>
<th>Outcome</th>
<th>Kategorie</th>
<th>Cluster</th>
<th style="text-align: right;">Einstieg</th>
<th style="text-align: right;">Shares</th>
<th style="text-align: right;">Einsatz (USDC)</th>
<th>Eröffnet</th>
<th>Enddatum</th>
<th>Status</th>
</tr>
</thead>
<tbody id="rfPositionsTbody">
<tr><td colspan="11" style="text-align: center; color: var(--muted);">Lade Positionen …</td></tr>
</tbody>
</table>
</div>
</div>
<!-- RF SUBTAB: HISTORY -->
<div id="rfTab-history" class="rf-tab-content" style="display: none;">
<div class="module-toolbar" style="margin-top: 0; padding: 10px 14px;">
<div class="toolbar-item" style="flex: 1; min-width: 250px;">
<input type="text" id="rfHistorySearch" class="form-input" placeholder="Suche in Markt / Outcome / Kategorie …" oninput="debounceRfHistorySearch()">
</div>
<div style="font-size: 13px; color: var(--muted);" id="rfHistorySummary">0 Trades</div>
</div>
<div class="table-container">
<table>
<thead>
<tr>
<th>ID</th>
<th>Konto</th>
<th>Marktfrage</th>
<th>Outcome</th>
<th>Kategorie</th>
<th style="text-align: right;">Einstieg</th>
<th style="text-align: right;">Exit</th>
<th style="text-align: right;">Shares</th>
<th style="text-align: right;">Realisierter PnL</th>
<th style="text-align: right;">Rendite</th>
<th style="text-align: right;">Gebühren</th>
<th>Geschlossen</th>
<th>Redeem-Status</th>
<th>Grund</th>
</tr>
</thead>
<tbody id="rfHistoryTbody">
<tr><td colspan="14" style="text-align: center; color: var(--muted);">Lade Historie …</td></tr>
</tbody>
</table>
</div>
</div>
<!-- RF SUBTAB: SETTINGS -->
<div id="rfTab-settings" class="rf-tab-content" style="display: none;">
<div class="card settings-form" style="max-width: 900px; margin: 0 auto;">
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 18px; border-bottom: 1px solid var(--border); padding-bottom: 12px;">
<div style="font-size: 14px; font-weight: 600;" id="rfSettingsAccountTitle">Einstellungen für Konto</div>
<div id="rfSettingsStatus" style="font-size: 13px; color: var(--positive); display: none;">✓ Gespeichert</div>
</div>
<form id="rfSettingsForm" onsubmit="saveRfSettings(event)">
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 18px;">
<div class="form-row" style="grid-column: span 2;">
<label class="checkbox-label">
<input type="checkbox" id="rfEnabled">
<strong>Modul aktiv</strong> (Schaltet das ResolutionFarming für diesen Account scharf)
</label>
<div class="form-desc">Bei deaktiviertem Schalter wird nur im Hintergrund gescannt (Read-Only).</div>
</div>
<div class="form-row">
<label for="rfMinPrice">Min. Preis (0–1)</label>
<input type="number" step="0.01" id="rfMinPrice" class="form-input" min="0" max="1" required>
<div class="form-desc">Unteres Ende des Preisbands (Standard 0.90 = 90 ¢).</div>
</div>
<div class="form-row">
<label for="rfMaxPrice">Max. Preis (0–1)</label>
<input type="number" step="0.01" id="rfMaxPrice" class="form-input" min="0" max="1" required>
<div class="form-desc">Oberes Ende des Preisbands (Standard 0.98 = 98 ¢).</div>
</div>
<div class="form-row">
<label for="rfMaxHours">Max. Stunden bis Auflösung</label>
<input type="number" id="rfMaxHours" class="form-input" min="1" required>
<div class="form-desc">Nur Märkte scannen, die innerhalb dieses Fensters auflösen (Standard 48h).</div>
</div>
<div class="form-row">
<label for="rfMinEdge">Min. Netto-Edge (%)</label>
<input type="number" step="0.1" id="rfMinEdge" class="form-input" required>
<div class="form-desc">Mindest-Netto-Edge nach Fees (Standard 1.5%).</div>
</div>
<div class="form-row">
<label for="rfMaxPerMarket">Max. Einsatz je Markt (USDC)</label>
<input type="number" step="1" id="rfMaxPerMarket" class="form-input" required>
<div class="form-desc">Obergrenze des Einsatzes in einem einzelnen Markt (Standard 25).</div>
</div>
<div class="form-row">
<label for="rfMaxCluster">Max. Anteil je Cluster (%)</label>
<input type="number" step="1" id="rfMaxCluster" class="form-input" required>
<div class="form-desc">Maximaler Anteil der Bankroll je Ereignis-Cluster (Standard 10%).</div>
</div>
<div class="form-row" style="grid-column: span 2;">
<label for="rfWhitelist">Kategorie-Whitelist (CSV)</label>
<input type="text" id="rfWhitelist" class="form-input" placeholder="Sports,Politics,Geopolitics">
<div class="form-desc">Kommagetrennte Liste der erlaubten Markt-Kategorien (z. B. Krypto ausschließen wegen Fees).</div>
</div>
<div class="form-row" style="grid-column: span 2;">
<label for="rfBlacklist">Blacklist Slugs/Tags (CSV)</label>
<input type="text" id="rfBlacklist" class="form-input" placeholder="z. B. dispute,controversy">
<div class="form-desc">Ausschluss von Märkten mit Dispute-Gefahr (Teil-Match).</div>
</div>
</div>
<div style="margin-top: 20px; display: flex; gap: 10px; align-items: center;">
<button type="submit" class="btn btn-primary">Einstellungen speichern</button>
</div>
</form>
</div>
</div>
</section>
<!-- VIEW: SUPERVISOR -->
<section id="view-supervisor" class="view-panel">
<div class="module-toolbar">
<div style="display: flex; gap: 8px; align-items: center;">
<span style="font-size: 16px; font-weight: 700; color: var(--text);">AI Supervisor & Copilot</span>
<span class="badge" style="background: rgba(137, 180, 250, 0.15); color: var(--accent); border: 1px solid var(--accent);">LLM Agent</span>
</div>
<div class="module-tabs">
<button class="module-tab-btn active" id="supTabBtn-chat" onclick="switchSupTab('chat')">AI Copilot Chat</button>
<button class="module-tab-btn" id="supTabBtn-reports" onclick="switchSupTab('reports')">Berichte-Archiv</button>
<button class="module-tab-btn" id="supTabBtn-signals" onclick="switchSupTab('signals')">Signal-Dossiers</button>
<button class="module-tab-btn" id="supTabBtn-counterfactuals" onclick="switchSupTab('counterfactuals')">Counterfactuals</button>
</div>
<div style="margin-left: auto; display: flex; gap: 8px;">
<button class="btn btn-secondary" onclick="refreshCurrentSupTab()">Aktualisieren</button>
</div>
</div>
<!-- SUP SUBTAB: CHAT -->
<div id="supTab-chat" class="sup-tab-content active">
<div class="supervisor-chat-box">
<div class="chat-presets-bar">
<span class="chat-preset-tag">Schnellabfragen:</span>
<button class="chat-preset-btn" onclick="applySupPreset('Erstelle einen kompakten Tagesbericht über alle Module, PnL und offene Positionen.')">📊 Tagesbericht</button>
<button class="chat-preset-btn" onclick="applySupPreset('Audit aller offenen Positionen: Gibt es Klumpenrisiken oder kritische Restlaufzeiten?')">🛡️ Risiko-Audit</button>
<button class="chat-preset-btn" onclick="applySupPreset('Analysiere die verlorenen Trades der letzten 24 Stunden. Was waren die Hauptursachen?')">🔍 Verlust-Analyse</button>
<button class="chat-preset-btn" onclick="applySupPreset('Bewerte die Performance der aktiven Master-Trader und markiere auffällige Drift.')">👥 Master-Trader Audit</button>
<button class="chat-preset-btn" onclick="applySupPreset('Prüfe die abgelehnten Signale: Hätten wir profitabel getradet (Counterfactuals)?')">💡 Counterfactuals</button>
</div>
<div class="chat-messages-area" id="supChatMessages">
<div class="chat-bubble assistant">
<div class="chat-bubble-header">
<span>🤖 Supervisor Copilot</span>
<span>Bereit</span>
</div>
<div class="chat-bubble-body">Hallo! Ich bin der autonome PolyTrader Supervisor. Ich überwache alle Handelsmodule, Kontosalden, Order-Ereignisse und Gegenwahrscheinlichkeiten.
Wähle ein Profil und stelle mir eine Frage zu deinen Positionen, Risiken oder deiner Trading-Performance.</div>
</div>
</div>
<form id="formSupChat" onsubmit="sendSupQuestion(event)" class="chat-input-row">
<select id="supProfileSelect" class="form-input form-select" style="min-width: 140px; max-width: 160px; font-size: 13px;" title="Supervisor Profil">
<option value="General">General</option>
<option value="Risk">Risk</option>
<option value="Research">Research</option>
</select>
<input type="text" id="supModelInput" class="form-input" style="max-width: 150px; font-size: 13px;" placeholder="Modell (leer = Standard)" title="Optionales KI-Modell (z. B. gpt-4o, claude-3-5-sonnet)">
<input type="text" id="supQuestionInput" class="form-input" style="flex: 1; font-size: 13.5px;" placeholder="Frage an den Supervisor stellen …" required autocomplete="off">
<button type="submit" id="btnSupSend" class="btn btn-primary" style="padding: 8px 18px;">Senden</button>
</form>
</div>
</div>
<!-- SUP SUBTAB: REPORTS -->
<div id="supTab-reports" class="sup-tab-content" style="display: none;">
<div style="margin-bottom: 14px; font-size: 13px; color: var(--muted);" id="supReportsSummary">Lade Berichte-Archiv …</div>
<div class="table-container">
<table>
<thead>
<tr>
<th style="width: 50px;">ID</th>
<th>Zeitpunkt</th>
<th>Profil</th>
<th>Modell</th>
<th>Frage / Auslöser</th>
<th style="text-align: center;">Tools</th>
<th style="text-align: right;">Tokens</th>
<th style="text-align: center; width: 120px;">Aktion</th>
</tr>
</thead>
<tbody id="supReportsTbody">
<tr><td colspan="8" style="text-align: center; color: var(--muted);">Lade Berichte …</td></tr>
</tbody>
</table>
</div>
</div>
<!-- SUP SUBTAB: SIGNALS -->
<div id="supTab-signals" class="sup-tab-content" style="display: none;">
<div style="margin-bottom: 14px; font-size: 13px; color: var(--muted);" id="supSignalsSummary">Lade Signal-Dossiers …</div>
<div class="table-container">
<table>
<thead>
<tr>
<th>Signal-ID</th>
<th>Erkannt am</th>
<th>Modul</th>
<th>Konto</th>
<th>Marktfrage</th>
<th>Side</th>
<th>Letzte Entscheidung</th>
<th>Grund</th>
<th style="text-align: center; width: 120px;">Aktion</th>
</tr>
</thead>
<tbody id="supSignalsTbody">
<tr><td colspan="9" style="text-align: center; color: var(--muted);">Lade Signale …</td></tr>
</tbody>
</table>
</div>
</div>
<!-- SUP SUBTAB: COUNTERFACTUALS -->
<div id="supTab-counterfactuals" class="sup-tab-content" style="display: none;">
<div style="margin-bottom: 14px; font-size: 13px; color: var(--muted);" id="supCounterfactualsSummary">Lade Counterfactual-Analysen (abgelehnte Signale vs. Realität) …</div>
<div class="table-container">
<table>
<thead>
<tr>
<th style="width: 50px;">ID</th>
<th>Geprüft am</th>
<th>Modul</th>
<th>Konto</th>
<th>Markt</th>
<th>Ablehnungsgrund</th>
<th style="text-align: right;">Signal-Preis</th>
<th style="text-align: center;">Ausgang</th>
<th style="text-align: right;">Hypoth. PnL / Share</th>
</tr>
</thead>
<tbody id="supCounterfactualsTbody">
<tr><td colspan="9" style="text-align: center; color: var(--muted);">Lade Counterfactuals …</td></tr>
</tbody>
</table>
</div>
</div>
</section>
<!-- VIEW: ACCOUNTING -->
<section id="view-accounting" class="view-panel">
<div class="module-toolbar">
<div style="display: flex; gap: 8px; align-items: center;">
<span style="font-size: 16px; font-weight: 700; color: var(--text);">Accounting & BWA</span>
<span class="badge" style="background: rgba(166, 227, 161, 0.15); color: var(--positive); border: 1px solid var(--positive);">Finanzbuchhaltung</span>
</div>
<div class="module-tabs">
<button class="module-tab-btn active" id="accTabBtn-bwa" onclick="switchAccTab('bwa')">BWA & Periodenabrechnung</button>
<button class="module-tab-btn" id="accTabBtn-ledger" onclick="switchAccTab('ledger')">Ledger-Journal</button>
<button class="module-tab-btn" id="accTabBtn-runs" onclick="switchAccTab('runs')">Sync & Ingest Läufe</button>
</div>
<div style="margin-left: auto; display: flex; gap: 8px;">
<button class="btn btn-secondary" onclick="refreshCurrentAccTab()">Aktualisieren</button>
</div>
</div>
<!-- ACC SUBTAB: BWA -->
<div id="accTab-bwa" class="acc-tab-content active">
<!-- Filters & Currency -->
<div class="card" style="margin-bottom: 20px;">
<div style="display: flex; flex-wrap: wrap; gap: 16px; align-items: center; justify-content: space-between;">
<div style="display: flex; flex-wrap: wrap; gap: 12px; align-items: center;">
<div class="toolbar-item">
<label for="accFilterAccount" style="font-size: 12px; font-weight: 600;">Konto:</label>
<select id="accFilterAccount" class="form-input form-select" style="min-width: 170px;">
<option value="">Alle Konten</option>
</select>
</div>
<div class="toolbar-item">
<label for="accFilterFrom" style="font-size: 12px; font-weight: 600;">Von:</label>
<input type="date" id="accFilterFrom" class="form-input" style="font-size: 13px;">
</div>
<div class="toolbar-item">
<label for="accFilterTo" style="font-size: 12px; font-weight: 600;">Bis:</label>
<input type="date" id="accFilterTo" class="form-input" style="font-size: 13px;">
</div>
<button class="btn btn-primary" style="margin-top: 14px;" onclick="loadAccountingBwa()">Abrechnung berechnen</button>
</div>
<div style="display: flex; flex-wrap: wrap; gap: 12px; align-items: center;">
<div>
<label style="display: block; font-size: 11px; color: var(--muted); margin-bottom: 2px;">Währung:</label>
<div class="currency-pills">
<button type="button" class="currency-pill active" id="currPill-USDC" onclick="selectAccountingCurrency('USDC')">USDC</button>
<button type="button" class="currency-pill" id="currPill-USD" onclick="selectAccountingCurrency('USD')">USD</button>
<button type="button" class="currency-pill" id="currPill-EUR" onclick="selectAccountingCurrency('EUR')">EUR</button>
</div>
</div>
<div style="margin-top: 14px; display: flex; gap: 8px;">
<button class="btn btn-secondary" onclick="exportAccountingPdf()">📄 PDF Export</button>
<button class="btn btn-secondary" onclick="exportAccountingCsv()">📊 CSV Export</button>
</div>
</div>
</div>
<div id="accCurrencyNote" style="margin-top: 10px; font-size: 11.5px; color: var(--muted); font-style: italic;"></div>
</div>
<!-- BWA KPI Cards -->
<div class="grid-4" style="margin-bottom: 20px;">
<div class="card">
<div class="card-title">Anfangsbestand</div>
<div class="card-value" id="accBwaOpening">0.00</div>
<div class="card-sub" id="accBwaPeriodLabel">Zu Beginn der Periode</div>
</div>
<div class="card">
<div class="card-title">Endbestand</div>
<div class="card-value" id="accBwaClosing">0.00</div>
<div class="card-sub" id="accBwaBalanceChange">Veränderung: 0.00</div>
</div>
<div class="card">
<div class="card-title">Netto Trading-Ergebnis</div>
<div class="card-value" id="accBwaNetResult">0.00</div>
<div class="card-sub" id="accBwaTradeStats">0 Trades | 0 Buchungen</div>
</div>
<div class="card">
<div class="card-title">Handelsvolumen & Gebühren</div>
<div class="card-value" id="accBwaVolume">0.00</div>
<div class="card-sub" id="accBwaFees">Gebühren: 0.00 | Rewards: 0.00</div>
</div>
</div>
<!-- Monthly Breakdown Table -->
<h3 style="margin-bottom: 12px; font-size: 15px; font-weight: 600;">Monatliche BWA-Aufschlüsselung</h3>
<div class="table-container">
<table>
<thead>
<tr>
<th>Monat</th>
<th style="text-align: right;">Anfangsbestand</th>
<th style="text-align: right;">Endbestand</th>
<th style="text-align: right;">Ein-/Auszahlungen</th>
<th style="text-align: right;">Handelsvolumen</th>
<th style="text-align: right;">Gebühren</th>
<th style="text-align: right;">Netto-Ergebnis</th>
<th style="text-align: center;">Trades</th>
<th style="text-align: center;">Buchungen</th>
</tr>
</thead>
<tbody id="accMonthlyTbody">
<tr><td colspan="9" style="text-align: center; color: var(--muted);">Lade Abrechnung …</td></tr>
</tbody>
</table>
</div>
</div>
<!-- ACC SUBTAB: LEDGER -->
<div id="accTab-ledger" class="acc-tab-content" style="display: none;">
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 14px; flex-wrap: wrap; gap: 10px;">
<div style="display: flex; gap: 10px; align-items: center;">
<input type="text" id="accLedgerSearch" class="form-input" style="min-width: 260px;" placeholder="Suchen nach Markt, TX-Hash, Event …" onkeydown="if(event.key==='Enter') searchAccLedger()">
<button class="btn btn-secondary" onclick="searchAccLedger()">Suchen</button>
</div>
<div id="accLedgerSummary" style="font-size: 13px; color: var(--muted);">Lade Journal …</div>
</div>
<div class="table-container">
<table>
<thead>
<tr>
<th>Zeitpunkt</th>
<th>Konto</th>
<th>Ereignis</th>
<th>Side</th>
<th>Markt</th>
<th>Outcome</th>
<th style="text-align: right;">Size</th>
<th style="text-align: right;">Preis</th>
<th style="text-align: right;">Brutto</th>
<th style="text-align: right;">Fee</th>
<th style="text-align: right;">Netto</th>
<th>TX-Hash</th>
</tr>
</thead>
<tbody id="accLedgerTbody">
<tr><td colspan="12" style="text-align: center; color: var(--muted);">Lade Journal …</td></tr>
</tbody>
</table>
</div>
<div class="pagination-bar" id="accLedgerPagination">
<span id="accLedgerPageInfo" style="font-size: 13px; color: var(--muted);">Seite 1 von 1</span>
<div style="display: flex; gap: 6px;">
<button class="btn btn-secondary btn-sm" id="btnAccLedgerPrev" onclick="changeAccLedgerPage(-1)">◀ Vorherige</button>
<button class="btn btn-secondary btn-sm" id="btnAccLedgerNext" onclick="changeAccLedgerPage(1)">Nächste ▶</button>
</div>
</div>
</div>
<!-- ACC SUBTAB: RUNS -->
<div id="accTab-runs" class="acc-tab-content" style="display: none;">
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 14px;">
<div id="accRunsSummary" style="font-size: 13px; color: var(--muted);">Lade Ingestion-Historie …</div>
<button class="btn btn-primary" onclick="triggerManualIngest()">+ Blockchain-Sync manuell starten</button>
</div>
<div class="table-container">
<table>
<thead>
<tr>
<th style="width: 50px;">ID</th>
<th>Konto</th>
<th>Startzeit</th>
<th>Fertiggestellt</th>
<th>Typ</th>
<th style="text-align: right;">Neue Buchungen</th>
<th style="text-align: right;">Duplikate</th>
<th style="text-align: right;">Saldo-Delta</th>
<th style="text-align: center;">Status</th>
<th>Fehlermeldung</th>
</tr>
</thead>
<tbody id="accRunsTbody">
<tr><td colspan="10" style="text-align: center; color: var(--muted);">Lade Ingestion-Läufe …</td></tr>
</tbody>
</table>
</div>
</div>
</section>
<!-- VIEW: ACCOUNTS -->
<section id="view-accounts" class="view-panel">
<h2 style="margin-bottom: 16px; font-size: 18px;">Polymarket Konten</h2>
<div class="table-container">
<table>
<thead>
<tr>
<th>#</th>
<th>Name</th>
<th>Status</th>
<th>Modus</th>
<th>USDC Balance</th>
<th>3T PnL</th>
<th>3T Winrate %</th>
<th>Overall P/L</th>
<th>Proxy Wallet</th>
<th>Polymarket</th>
</tr>
</thead>
<tbody id="tblAccounts">
<tr><td colspan="10" style="text-align: center; color: var(--muted);">Lade Konten …</td></tr>
</tbody>
</table>
</div>
</section>
<!-- VIEW: JOBS -->
<section id="view-jobs" class="view-panel">
<h2 style="margin-bottom: 16px; font-size: 18px;">Server Jobs & Hintergrund-Dienste</h2>
<div class="table-container">
<table>
<thead>
<tr>
<th>Job Name</th>
<th>Beschreibung</th>
<th>Aktiv</th>
<th>Letzter Lauf</th>
<th>Nächster Lauf</th>
<th>Status</th>
<th>Aktion</th>
</tr>
</thead>
<tbody id="tblJobs">
<tr><td colspan="7" style="text-align: center; color: var(--muted);">Lade Jobs …</td></tr>
</tbody>
</table>
</div>
</section>
<!-- VIEW: TERMINAL / LOGS -->
<section id="view-logs" class="view-panel">
<div class="terminal-window">
<div class="terminal-toolbar">
<div style="display: flex; gap: 10px; align-items: center;">
<span style="font-weight: 600;">Echtzeit-Log Stream</span>
<div class="status-indicator" style="padding: 2px 6px; font-size: 11px;">
<span class="dot online" id="sseDot"></span>
<span id="sseStatus">Verbunden</span>
</div>
</div>
<div style="display: flex; gap: 10px; align-items: center;">
<select id="logLevelFilter" class="form-input" style="padding: 4px 8px; font-size: 12px; width: auto;" onchange="applyLogFilter()">
<option value="ALL">Alle Level</option>
<option value="INFO">Info</option>
<option value="WARNING">Warning</option>
<option value="ERROR">Error</option>
<option value="TRADE">Trade</option>
</select>
<label class="checkbox-label" style="font-size: 12px; color: var(--muted);">
<input type="checkbox" id="chkAutoScroll" checked> Auto-Scroll
</label>
<button class="btn btn-secondary" style="padding: 4px 8px; font-size: 12px;" onclick="clearLogs()">Leeren</button>
</div>
</div>
<div class="terminal-logs" id="logContainer"></div>
</div>
</section>
<!-- VIEW: MODULES -->
<section id="view-modules" class="view-panel">
<h2 style="margin-bottom: 16px; font-size: 18px;">Strategie- & Analyse-Module</h2>
<div class="grid-2" id="modulesContainer">
<div class="card"><div class="card-title">Lade Module …</div></div>
</div>
</section>
<!-- VIEW: SETTINGS -->
<section id="view-settings" class="view-panel">
<h2 style="margin-bottom: 16px; font-size: 18px;">WebGUI Anwendungseinstellungen</h2>
<div class="card settings-form">
<form id="settingsForm" onsubmit="saveSettings(event)">
<div class="form-row">
<label class="checkbox-label">
<input type="checkbox" id="cfgEnabled">
WebGUI Server aktiv
</label>
<div class="form-desc">Steuert, ob Kestrel beim Programmstart hochfährt.</div>
</div>
<div class="form-row">
<label for="cfgPort">Server-Port</label>
<input type="number" id="cfgPort" class="form-input" min="1024" max="65535" required>
<div class="form-desc">Standard ist 6001. Änderung wird nach dem nächsten Neustart aktiv.</div>
</div>
<div class="form-row">
<label class="checkbox-label">
<input type="checkbox" id="cfgLocalOnly">
Nur lokaler Zugriff (127.0.0.1)
</label>
<div class="form-desc">Wenn deaktiviert, ist das WebUI über alle Netzwerkschnittstellen (LAN/VPN) erreichbar.</div>
</div>
<div class="form-row">
<label for="cfgToken">Zugangs-Token</label>
<div style="display: flex; gap: 8px;">
<input type="text" id="cfgToken" class="form-input" style="font-family: var(--font-mono); font-size: 12px;" readonly>
<button type="button" class="btn btn-secondary" onclick="copyToken()">Kopieren</button>
<button type="button" class="btn btn-secondary" onclick="generateNewToken()">Neu generieren</button>
</div>
<div class="form-desc">Wird in appsettings.Local.json gespeichert. Bei leerem Token ist das WebUI gesperrt.</div>
</div>
<div style="display: flex; gap: 10px; align-items: center; margin-top: 24px;">
<button type="submit" class="btn btn-primary" id="btnSaveSettings">Einstellungen speichern</button>
<span id="settingsStatusMsg" style="font-size: 13px; color: var(--positive); display: none;">✓ Gespeichert</span>
</div>
</form>
</div>
</section>
</main>
<!-- MODAL: MASTER TRADER EDIT/ADD -->
<div id="modalTrader" class="modal-overlay" style="display: none;">
<div class="modal-dialog">
<div class="modal-header">
<h3 id="modalTraderTitle" style="margin: 0; font-size: 16px;">Master-Trader bearbeiten</h3>
<button class="modal-close" onclick="closeTraderModal()">&times;</button>
</div>
<form id="formTraderModal" onsubmit="saveTraderModal(event)">
<input type="hidden" id="traderModalId">
<div class="modal-body" style="display: grid; grid-template-columns: 1fr 1fr; gap: 14px;">
<div class="form-row" style="grid-column: span 2;">
<label for="traderModalName">Anzeigename</label>
<input type="text" id="traderModalName" class="form-input" required placeholder="z. B. Whale-Alpha">
</div>
<div class="form-row" style="grid-column: span 2;">
<label for="traderModalWallet">Wallet-Adresse (0x...)</label>
<input type="text" id="traderModalWallet" class="form-input" style="font-family: var(--font-mono); font-size: 12px;" required placeholder="0x1234567890abcdef...">
</div>
<div class="form-row">
<label for="traderModalCategory">Kategorie</label>
<select id="traderModalCategory" class="form-input form-select">
<option value="NEW_BIG_BET">NEW_BIG_BET</option>
<option value="HF">HF (High-Frequency)</option>
<option value="INSIDER">INSIDER</option>
<option value="SNIPER">SNIPER</option>
<option value="HOLDER">HOLDER</option>
</select>
</div>
<div class="form-row" style="display: flex; flex-direction: column; justify-content: center; gap: 6px;">
<label class="checkbox-label"><input type="checkbox" id="traderModalActive" checked> <strong>Aktiv</strong> (Kopieren an)</label>
<label class="checkbox-label"><input type="checkbox" id="traderModalAutoPause" checked> Auto-Pause Kill-Switch</label>
<label class="checkbox-label"><input type="checkbox" id="traderModalMaker"> Maker-Einstieg (GTC-Limit)</label>
<label class="checkbox-label"><input type="checkbox" id="traderModalHidden"> Ausgeblendet (Archiv)</label>
</div>
<div class="form-row" style="grid-column: span 2;">
<label for="traderModalDesc">Beschreibung</label>
<input type="text" id="traderModalDesc" class="form-input" placeholder="Optionale Notiz zur Strategie / Herkunft">
</div>
<div class="form-row" style="grid-column: span 2;">
<label for="traderModalReasoning">Begründung / Reasoning</label>
<input type="text" id="traderModalReasoning" class="form-input" placeholder="Warum dieser Master kopiert wird">
</div>
<div class="form-row" style="grid-column: span 2;">
<label style="margin-bottom: 6px; display: block; font-weight: 500; font-size: 13px;">Zugewiesene Konten:</label>
<div id="traderModalAccountsList" style="display: flex; flex-wrap: wrap; gap: 12px; background: var(--surface-alt); padding: 10px; border-radius: var(--radius-sm); border: 1px solid var(--border);"></div>
</div>
</div>
<div class="modal-footer" style="display: flex; justify-content: flex-end; gap: 10px; margin-top: 18px; padding-top: 12px; border-top: 1px solid var(--border);">
<button type="button" class="btn btn-secondary" onclick="closeTraderModal()">Abbrechen</button>
<button type="submit" class="btn btn-primary">Speichern</button>
</div>
</form>
</div>
</div>
<!-- MODAL: REPORT / DOSSIER VIEWER -->
<div id="modalReport" class="modal-overlay" style="display: none;">
<div class="modal-dialog" style="max-width: 860px;">
<div class="modal-header">
<h3 id="modalReportTitle" style="margin: 0; font-size: 16px;">Bericht / Dossier</h3>
<button class="modal-close" onclick="closeReportModal()">&times;</button>
</div>
<div class="modal-body">
<div id="modalReportMeta" style="margin-bottom: 12px; font-size: 12px; color: var(--muted); display: flex; gap: 14px; flex-wrap: wrap;"></div>
<pre id="modalReportContent" class="markdown-pre"></pre>
</div>
<div class="modal-footer" style="display: flex; justify-content: flex-end; margin-top: 14px;">
<button type="button" class="btn btn-secondary" onclick="closeReportModal()">Schließen</button>
</div>
</div>
</div>
<script src="/js/app.js"></script>
</body>
</html>