- Add advanced metrics dashboard with trade analytics - Add new trading components (EntryTypeAnalysis, MultiDayPositionTracker, NewsEventTracker, etc.) - Add strategy mode selector and trend confirmation - Add risk automation panel and slippage correlation analysis - Add daily trading plan enhancements with modal components - Add custom hooks (useApi, useLocalStorage, useAdvancedTradeMetrics) - Add broker service integration and trading API - Add test setup and vitest configuration - Include parquet data files for live market data - Add comprehensive documentation in docs/ folder
72 lines
1.9 KiB
Python
72 lines
1.9 KiB
Python
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,
|
|
}
|