Files
2026-05-18 00:31:08 +03:00

109 lines
3.5 KiB
HTML

{% extends "layout.html" %}
{% block title %}Portfolio — IBKR Dashboard{% endblock %}
{% block content %}
<h1>Portfolio</h1>
<div class="portfolio-summary" id="pnlCards">
<div class="summary-card">
<div class="card-label">Net Liquidation</div>
<div class="card-value" id="netLiq"></div>
</div>
<div class="summary-card">
<div class="card-label">Total Cash</div>
<div class="card-value" id="totalCash"></div>
</div>
<div class="summary-card">
<div class="card-label">Unrealized P&amp;L</div>
<div class="card-value" id="unrealizedPnl"></div>
</div>
<div class="summary-card">
<div class="card-label">Realized P&amp;L</div>
<div class="card-value" id="realizedPnl"></div>
</div>
</div>
<div class="dashboard-container" style="margin-top: 24px;">
<table>
<thead>
<tr>
<th>Symbol</th>
<th>Position</th>
<th>Avg Cost</th>
<th>Chart</th>
</tr>
</thead>
<tbody id="positionsBody">
<tr><td colspan="4" class="empty-state">Loading positions...</td></tr>
</tbody>
</table>
</div>
{% endblock %}
{% block extra_scripts %}
<script>
function fmt(val) {
if (val === undefined || val === null) return '—';
return '$' + parseFloat(val).toLocaleString('en-US', { minimumFractionDigits: 2, maximumFractionDigits: 2 });
}
function colorClass(val) {
const n = parseFloat(val);
if (isNaN(n)) return '';
return n >= 0 ? 'positive' : 'negative';
}
async function loadPnl() {
try {
const res = await fetch('/portfolio/pnl');
const d = await res.json();
document.getElementById('netLiq').textContent = fmt(d.NetLiquidation);
document.getElementById('totalCash').textContent = fmt(d.TotalCashValue);
const upEl = document.getElementById('unrealizedPnl');
upEl.textContent = fmt(d.UnrealizedPnL);
upEl.className = 'card-value ' + colorClass(d.UnrealizedPnL);
const rpEl = document.getElementById('realizedPnl');
rpEl.textContent = fmt(d.RealizedPnL);
rpEl.className = 'card-value ' + colorClass(d.RealizedPnL);
} catch (e) {
console.error('PnL fetch error:', e);
}
}
async function loadPositions() {
try {
const res = await fetch('/portfolio/data');
const data = await res.json();
const tbody = document.getElementById('positionsBody');
if (!Array.isArray(data) || data.length === 0) {
tbody.innerHTML = '<tr><td colspan="4" class="empty-state">No open positions.</td></tr>';
return;
}
tbody.innerHTML = data.map(p => `
<tr>
<td><a class="symbol-link" href="/?symbol=${p.symbol}">${p.symbol}</a></td>
<td>${p.position}</td>
<td class="price-cell">${fmt(p.avg_cost)}</td>
<td><a class="symbol-link" href="/?symbol=${p.symbol}">View Chart</a></td>
</tr>
`).join('');
} catch (e) {
console.error('Positions fetch error:', e);
}
}
function refresh() {
loadPnl();
loadPositions();
}
window.addEventListener('DOMContentLoaded', () => {
refresh();
setInterval(refresh, 30000);
});
</script>
{% endblock %}