Skip to content

Commit 2b0af51

Browse files
yingwangclaude
andcommitted
Align live positions table with Alpaca dashboard fields
Use Alpaca's native fields: side, qty, cost_basis, unrealized_intraday_pl/plpc for today's P/L instead of calculating manually. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 0cf5013 commit 2b0af51

2 files changed

Lines changed: 20 additions & 15 deletions

File tree

generate_site.py

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -175,13 +175,16 @@ def _fetch_trades_from_alpaca(api_key, secret_key):
175175
for p in api.list_positions():
176176
positions.append({
177177
"symbol": p.symbol,
178-
"shares": float(p.qty),
179-
"avg_cost": float(p.avg_entry_price),
178+
"qty": float(p.qty),
179+
"side": p.side,
180180
"current_price": float(p.current_price),
181181
"market_value": float(p.market_value),
182-
"unrealized_pl": float(p.unrealized_pl),
183-
"unrealized_pl_pct": float(p.unrealized_plpc) * 100,
184-
"change_today": round((float(p.current_price) / float(p.lastday_price) - 1) * 100, 2) if hasattr(p, 'lastday_price') and p.lastday_price else 0,
182+
"avg_entry_price": float(p.avg_entry_price),
183+
"cost_basis": float(p.cost_basis),
184+
"today_pl_pct": float(p.unrealized_intraday_plpc) * 100 if hasattr(p, 'unrealized_intraday_plpc') and p.unrealized_intraday_plpc else 0,
185+
"today_pl": float(p.unrealized_intraday_pl) if hasattr(p, 'unrealized_intraday_pl') and p.unrealized_intraday_pl else 0,
186+
"total_pl_pct": float(p.unrealized_plpc) * 100,
187+
"total_pl": float(p.unrealized_pl),
185188
})
186189

187190
# Recent orders (last 100 filled orders)

site/index.html

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -69,8 +69,9 @@ <h2>Live Positions / 实盘持仓</h2>
6969
<table id="live-positions-table">
7070
<thead>
7171
<tr>
72-
<th>Symbol</th><th>Shares</th><th>Avg Cost</th><th>Price</th>
73-
<th>Value</th><th>P&L</th><th>P&L %</th><th>Today</th>
72+
<th>Symbol</th><th>Side</th><th>Qty</th><th>Price</th>
73+
<th>Market Value</th><th>Avg Entry</th><th>Cost Basis</th>
74+
<th>Today P/L %</th><th>Today P/L $</th><th>Total P/L %</th>
7475
</tr>
7576
</thead>
7677
<tbody></tbody>
@@ -226,18 +227,19 @@ <h2>Trade History / 交易记录</h2>
226227

227228
const tbody = document.querySelector('#live-positions-table tbody');
228229
data.positions.forEach(p => {
229-
const plClass = p.unrealized_pl >= 0 ? 'positive' : 'negative';
230-
const todayClass = (p.change_today || 0) >= 0 ? 'positive' : 'negative';
231-
const today = p.change_today || 0;
230+
const todayClass = (p.today_pl || 0) >= 0 ? 'positive' : 'negative';
231+
const totalClass = (p.total_pl || 0) >= 0 ? 'positive' : 'negative';
232232
tbody.innerHTML += `<tr>
233233
<td class="symbol">${symLink(p.symbol)}</td>
234-
<td>${p.shares}</td>
235-
<td>$${p.avg_cost.toFixed(2)}</td>
234+
<td>${p.side || 'long'}</td>
235+
<td>${p.qty}</td>
236236
<td>$${p.current_price.toFixed(2)}</td>
237237
<td>$${Math.round(p.market_value).toLocaleString()}</td>
238-
<td class="${plClass}">${p.unrealized_pl >= 0 ? '+' : ''}$${p.unrealized_pl.toFixed(0)}</td>
239-
<td class="${plClass}">${p.unrealized_pl_pct >= 0 ? '+' : ''}${p.unrealized_pl_pct.toFixed(1)}%</td>
240-
<td class="${todayClass}">${today >= 0 ? '+' : ''}${today.toFixed(2)}%</td>
238+
<td>$${p.avg_entry_price.toFixed(2)}</td>
239+
<td>$${Math.round(p.cost_basis).toLocaleString()}</td>
240+
<td class="${todayClass}">${p.today_pl_pct >= 0 ? '+' : ''}${p.today_pl_pct.toFixed(2)}%</td>
241+
<td class="${todayClass}">${p.today_pl >= 0 ? '+' : ''}$${p.today_pl.toFixed(0)}</td>
242+
<td class="${totalClass}">${p.total_pl_pct >= 0 ? '+' : ''}${p.total_pl_pct.toFixed(1)}%</td>
241243
</tr>`;
242244
});
243245
}

0 commit comments

Comments
 (0)