from __future__ import annotations import asyncio from typing import List, Optional import pandas as pd import yfinance as yf from app.schemas.schemas import PriceData YA_SYMBOL = "XAUUSD=X" def _format_dataframe(df: pd.DataFrame) -> List[PriceData]: rows: List[PriceData] = [] if df.empty: return rows df = df.dropna(subset=["Open", "High", "Low", "Close"]) for idx, row in df.iterrows(): timestamp = int(pd.Timestamp(idx).timestamp()) rows.append( PriceData( time=timestamp, open=float(row["Open"]), high=float(row["High"]), low=float(row["Low"]), close=float(row["Close"]), volume=float(row.get("Volume", 0.0) or 0.0), ) ) return rows async def fetch_yfinance_history( symbol: str = YA_SYMBOL, interval: str = "1m", period: str = "1d", start: Optional[str] = None, end: Optional[str] = None, ) -> List[PriceData]: def _download() -> pd.DataFrame: return yf.download( symbol, interval=interval, period=None if start else period, start=start, end=end, progress=False, auto_adjust=False, threads=False, ) df = await asyncio.to_thread(_download) return _format_dataframe(df) async def fetch_yfinance_quote(symbol: str = YA_SYMBOL) -> Optional[dict]: rows = await fetch_yfinance_history(symbol=symbol, interval="1m", period="1d") if not rows: return None latest = rows[-1] previous = rows[-2] if len(rows) > 1 else latest return { "price": latest.close, "previous_close": previous.close, "high_24h": max(r.high for r in rows[-1440:]), "low_24h": min(r.low for r in rows[-1440:]), "volume": latest.volume or 0.0, "updated_at": latest.time, "rows": rows, }