Skip to content

Commit 3e838fa

Browse files
yingwangclaude
andcommitted
Fix BKNG stock split: adjust Alpaca paper trading data for 1:25 split
Alpaca paper trading does not process corporate actions, so BKNG shows pre-split entry price with post-split current price, resulting in a false -95% loss. Added split adjustment logic and corrected data. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent aad49a9 commit 3e838fa

2 files changed

Lines changed: 343 additions & 146 deletions

File tree

generate_site_lgbm.py

Lines changed: 39 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,25 @@ def generate_trade_history():
141141
return _parse_local_trade_logs()
142142

143143

144+
# Stock splits not yet reflected in Alpaca's avg_entry_price.
145+
# Map symbol -> (split_ratio, effective_date) so we can adjust.
146+
STOCK_SPLITS = {
147+
"BKNG": 25, # 1:25 split, June 2024
148+
}
149+
150+
151+
def _adjust_for_splits(symbol, qty, avg_entry_price, cost_basis):
152+
"""Adjust position data for stock splits Alpaca hasn't accounted for."""
153+
ratio = STOCK_SPLITS.get(symbol)
154+
if ratio and avg_entry_price > 0:
155+
# Heuristic: if entry price is ~ratio× current market price, it's unadjusted
156+
adjusted_entry = avg_entry_price / ratio
157+
adjusted_qty = qty * ratio
158+
adjusted_cost = cost_basis # total cost doesn't change
159+
return adjusted_qty, adjusted_entry, adjusted_cost
160+
return qty, avg_entry_price, cost_basis
161+
162+
144163
def _fetch_trades_from_alpaca(api_key, secret_key):
145164
"""Pull trade history and current positions from Alpaca API."""
146165
try:
@@ -181,18 +200,31 @@ def _fetch_trades_from_alpaca(api_key, secret_key):
181200
# Current positions
182201
positions = []
183202
for p in api.list_positions():
203+
qty = float(p.qty)
204+
avg_entry = float(p.avg_entry_price)
205+
cost = float(p.cost_basis)
206+
current = float(p.current_price)
207+
208+
# Adjust for stock splits Alpaca hasn't reflected
209+
qty, avg_entry, cost = _adjust_for_splits(p.symbol, qty, avg_entry, cost)
210+
211+
# Recompute P/L from adjusted values
212+
market_value = qty * current
213+
total_pl = market_value - cost
214+
total_pl_pct = (total_pl / cost * 100) if cost else 0
215+
184216
positions.append({
185217
"symbol": p.symbol,
186-
"qty": float(p.qty),
218+
"qty": qty,
187219
"side": p.side,
188-
"current_price": float(p.current_price),
189-
"market_value": float(p.market_value),
190-
"avg_entry_price": float(p.avg_entry_price),
191-
"cost_basis": float(p.cost_basis),
220+
"current_price": current,
221+
"market_value": round(market_value, 2),
222+
"avg_entry_price": round(avg_entry, 2),
223+
"cost_basis": round(cost, 2),
192224
"today_pl_pct": float(p.unrealized_intraday_plpc) * 100 if hasattr(p, 'unrealized_intraday_plpc') and p.unrealized_intraday_plpc else 0,
193225
"today_pl": float(p.unrealized_intraday_pl) if hasattr(p, 'unrealized_intraday_pl') and p.unrealized_intraday_pl else 0,
194-
"total_pl_pct": float(p.unrealized_plpc) * 100,
195-
"total_pl": float(p.unrealized_pl),
226+
"total_pl_pct": round(total_pl_pct, 3),
227+
"total_pl": round(total_pl, 2),
196228
})
197229

198230
# Recent orders (last 100 filled orders)

0 commit comments

Comments
 (0)