06/01 Optimize porfolio page

This commit is contained in:
2026-06-01 17:29:57 -04:00
parent e040f0a0f8
commit 7815060e89
3 changed files with 111 additions and 13 deletions
+84 -7
View File
@@ -111,13 +111,81 @@ TIMEFRAME_MAP = {
}
def _extract_day_change_from_meta(meta):
"""
Extract open-to-current day change from a Yahoo Finance v8 meta block.
Returns (open_price, current_price, day_change, day_change_pct) or (None,)*4.
Yahoo Finance always includes regularMarketOpen (session open) and
regularMarketPrice (latest trade), so this gives the true intraday move
rather than the previous-close-to-latest approximation.
"""
try:
open_price = float(meta['regularMarketOpen'])
current_price = float(meta['regularMarketPrice'])
day_change = round(current_price - open_price, 4)
day_change_pct = round(day_change / open_price * 100, 2) if open_price != 0 else 0
return open_price, current_price, day_change, day_change_pct
except (KeyError, TypeError, ValueError):
return None, None, None, None
def fetch_day_change(ticker):
"""
Lightweight call: fetch today's open price and current price only.
Uses meta.regularMarketOpen / meta.regularMarketPrice from Yahoo Finance.
Returns dict: {ticker, open, current, day_change, day_change_pct}
or None on failure.
"""
if not ticker:
return None
ticker = ticker.upper().strip()
for subdomain in ('query1', 'query2'):
url = (
f'https://{subdomain}.finance.yahoo.com/v8/finance/chart/{ticker}'
f'?range=1d&interval=1d&includePrePost=false'
)
try:
resp = requests.get(url, headers=HEADERS, timeout=10)
if resp.status_code != 200:
continue
result = resp.json().get('chart', {}).get('result')
if not result:
return None
meta = result[0].get('meta', {})
open_p, curr, chg, chg_pct = _extract_day_change_from_meta(meta)
if open_p is None:
return None
log.info('[investment] %s day change: open=%.4f current=%.4f chg=%.4f (%.2f%%)',
ticker, open_p, curr, chg, chg_pct)
return {
'ticker': ticker,
'open': open_p,
'current': curr,
'day_change': chg,
'day_change_pct': chg_pct,
}
except Exception as exc:
log.warning('[investment] %s day-change fetch failed (%s): %s', ticker, subdomain, exc)
return None
def fetch_price_history(ticker, timeframe='1M'):
"""
Fetch historical closing prices for a ticker via Yahoo Finance v8 API.
timeframe: '1W' | '1M' | '3M' | '6M' | '1Y'
day_change / day_change_pct reflect the true intraday move
(regularMarketOpen → regularMarketPrice) from the response meta,
not the close-to-close approximation.
Returns dict:
ticker, current, prev_close, day_change, day_change_pct,
ticker, current, open_price, day_change, day_change_pct,
period_change, period_change_pct, dates, closes, timeframe
Returns None on failure.
"""
@@ -141,6 +209,7 @@ def fetch_price_history(ticker, timeframe='1M'):
if not result:
return None
meta = result[0].get('meta', {})
timestamps = result[0].get('timestamp', [])
closes_raw = result[0]['indicators']['quote'][0].get('close', [])
pairs = [(t, c) for t, c in zip(timestamps, closes_raw) if c is not None]
@@ -150,18 +219,26 @@ def fetch_price_history(ticker, timeframe='1M'):
dates = [datetime.utcfromtimestamp(t).strftime('%Y-%m-%d') for t, _ in pairs]
closes = [round(float(c), 4) for _, c in pairs]
current = closes[-1]
prev = closes[-2] if len(closes) > 1 else current
day_change = round(current - prev, 4)
day_change_pct = round(day_change / prev * 100, 2) if prev != 0 else 0
# Use meta for accurate day change (open → current), fall back to
# close-to-close only when meta fields are absent.
open_p, curr, day_change, day_change_pct = _extract_day_change_from_meta(meta)
if open_p is None:
curr = closes[-1]
prev = closes[-2] if len(closes) > 1 else curr
day_change = round(curr - prev, 4)
day_change_pct = round(day_change / prev * 100, 2) if prev != 0 else 0
open_p = prev
current = curr if curr is not None else closes[-1]
period_change = round(current - closes[0], 4)
period_change_pct = round(period_change / closes[0] * 100, 2) if closes[0] != 0 else 0
log.info('[investment] %s history: %d points (%s)', ticker, len(closes), timeframe)
log.info('[investment] %s history: %d points (%s) day_chg=%.2f%%',
ticker, len(closes), timeframe, day_change_pct)
return {
'ticker': ticker,
'current': current,
'prev_close': prev,
'open_price': open_p,
'day_change': day_change,
'day_change_pct': day_change_pct,
'period_change': period_change,