Spaces:
Running
Running
| from __future__ import annotations | |
| from pathlib import Path | |
| from typing import Dict, Tuple, Optional | |
| import pandas as pd | |
| import yfinance as yf | |
| def load_stock_data(symbol: str, data_dir: str) -> Tuple[Optional[pd.DataFrame], Optional[pd.DataFrame]]: | |
| """Load AI signals CSV for symbol and fetch OHLC data via yfinance. | |
| Returns (ohlc_df, signals_df) or (None, None) on error. | |
| """ | |
| data_path = Path(data_dir) | |
| csv_file = data_path / f"daily_analysis_{symbol}.csv" | |
| if not csv_file.exists(): | |
| print(f"Error: File {csv_file} not found!") | |
| return None, None | |
| signals_df = pd.read_csv(csv_file) | |
| signals_df["date"] = pd.to_datetime(signals_df["date"]) | |
| signals_df = signals_df.sort_values("date").reset_index(drop=True) | |
| start_date = signals_df["date"].min() | |
| end_date = signals_df["date"].max() | |
| ticker = yf.Ticker(symbol) | |
| ohlc_data = ticker.history(start=start_date, end=end_date + pd.Timedelta(days=1)) | |
| if ohlc_data.empty: | |
| print(f"No OHLC data available for {symbol}") | |
| return None, None | |
| return ohlc_data.reset_index(), signals_df | |
| def load_all_data(data_dir: str) -> Dict[str, Tuple[pd.DataFrame, pd.DataFrame]]: | |
| """Load all symbols from data_dir as mapping symbol -> (ohlc_df, signals_df).""" | |
| data_path = Path(data_dir) | |
| csv_files = list(data_path.glob("daily_analysis_*.csv")) | |
| all_data: Dict[str, Tuple[pd.DataFrame, pd.DataFrame]] = {} | |
| for csv_file in csv_files: | |
| symbol = csv_file.stem.replace("daily_analysis_", "") | |
| try: | |
| signals_df = pd.read_csv(csv_file) | |
| signals_df["date"] = pd.to_datetime(signals_df["date"]) | |
| signals_df = signals_df.sort_values("date").reset_index(drop=True) | |
| start_date = signals_df["date"].min() | |
| end_date = signals_df["date"].max() | |
| ticker = yf.Ticker(symbol) | |
| ohlc_data = ticker.history(start=start_date, end=end_date + pd.Timedelta(days=1)) | |
| if not ohlc_data.empty: | |
| all_data[symbol] = (ohlc_data.reset_index(), signals_df) | |
| else: | |
| print(f"✗ {symbol}: No OHLC data available") | |
| except Exception as e: | |
| print(f"✗ {symbol}: Failed to load - {e}") | |
| return all_data | |
| def list_available_stocks(data_dir: str) -> list[str]: | |
| """List stock symbols available as CSVs in data_dir.""" | |
| path = Path(data_dir) | |
| if not path.exists(): | |
| return [] | |
| return sorted([p.stem.replace("daily_analysis_", "") for p in path.glob("daily_analysis_*.csv")]) |