from __future__ import annotations from datetime import datetime import pandas as pd import streamlit as st import yfinance as yf @st.cache_data(ttl=60, show_spinner=False) def fetch_ohlc(symbol: str, interval: str, period: str) -> pd.DataFrame: ticker = yf.Ticker(symbol) df = ticker.history(period=period, interval=interval, auto_adjust=False, actions=False) if df.empty: raise ValueError("No data returned. Check symbol/interval/period compatibility.") df = df.rename(columns=str.title) required = ["Open", "High", "Low", "Close", "Volume"] missing = [c for c in required if c not in df.columns] if missing: raise ValueError(f"Missing required columns: {missing}") return df[required].dropna().copy() def maybe_drop_live_bar(df: pd.DataFrame, interval: str, enabled: bool) -> pd.DataFrame: if not enabled or len(df) < 2: return df last_ts = df.index[-1] if last_ts.tzinfo is None: now = datetime.utcnow() else: now = datetime.now(tz=last_ts.tzinfo) delta = now - last_ts.to_pydatetime() intraday_intervals = { "1m": 1, "2m": 2, "5m": 5, "15m": 15, "30m": 30, "60m": 60, "90m": 90, "1h": 60, } minutes = intraday_intervals.get(interval) if minutes is not None and delta.total_seconds() < minutes * 60: return df.iloc[:-1].copy() return df