Fix embedded-server endpoint drift, add Recalculate All Traders button
- Shared ApiConfiguration.MapPredictalyticsEndpoints() used by both the standalone API and the embedded WinForms Kestrel server: the embedded host was missing /api/watchlist and /api/dev (empty watchlist page), the standalone host was missing /api/search. - New Development menu action "Recalculate All Traders": backfills ResolutionOutcome from snapped outcome prices, wipes derived analytics (snapshots, category stats, rebuildable positions), zeroes aggregates and marks every trader for re-analysis. Raw trades untouched. - Static files now served with Cache-Control: no-cache in both hosts, plus ?v= cache-buster on app.js/style.css (stale browser JS masked earlier UI fixes). - Watchlist hardened: endpoint null-safe, real Analytics.CopytradingScore, Platform field; repository includes Trader.Analytics; page shows a visible error row instead of staying silently blank. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5
parent
1787422243
commit
850c47a404
@@ -346,22 +346,26 @@ async function loadTraders() {
|
||||
}
|
||||
|
||||
async function loadWatchlist() {
|
||||
const data = await api(`/api/watchlist`);
|
||||
if (!data) return;
|
||||
|
||||
const tbody = document.getElementById('watchlistBody');
|
||||
const data = await api(`/api/watchlist`);
|
||||
if (!Array.isArray(data)) {
|
||||
// api() returns null on HTTP errors — show it instead of a silently empty page.
|
||||
tbody.innerHTML = '<tr><td colspan="8">⚠ Failed to load watchlist (see browser console / server log).</td></tr>';
|
||||
return;
|
||||
}
|
||||
|
||||
tbody.innerHTML = data.map(w => `
|
||||
<tr>
|
||||
<td class="trader-name">
|
||||
<div class="avatar">${w.displayName.substring(0, 2).toUpperCase()}</div>
|
||||
<div class="avatar">${(w.displayName || '?').substring(0, 2).toUpperCase()}</div>
|
||||
<div>
|
||||
<strong>${w.displayName}</strong><br>
|
||||
<span style="font-size:12px; color:var(--text-secondary)">${w.platformUserId.substring(0, 8)}...</span>
|
||||
<strong>${w.displayName || '?'}</strong><br>
|
||||
<span style="font-size:12px; color:var(--text-secondary)">${(w.platformUserId || '').substring(0, 8)}...</span>
|
||||
</div>
|
||||
</td>
|
||||
<td>${w.platform ?? 'Unknown'}</td>
|
||||
<td>${Number(w.copytradingScore || 0).toFixed(1)}</td>
|
||||
<td class="${w.winRate > 0.5 ? 'text-green' : 'text-red'}">${fmt.pct(w.winRate)}</td>
|
||||
<td>${fmt.pct(w.winRate)}</td>
|
||||
<td class="${w.totalPnl >= 0 ? 'text-green' : 'text-red'}">${fmt.pnl(w.totalPnl)}</td>
|
||||
<td>${w.label || ''}</td>
|
||||
<td>${new Date(w.createdAt).toLocaleDateString()}</td>
|
||||
|
||||
Reference in New Issue
Block a user