Team Ai
Apppublic

diegobeyl/backtesting

sourceHugging Faceupdated 9mo agoView on Hugging Face
2likes
data_loader_old.py252 linesDownload Raw Back to core
1"""2Cargador de datos desde yfinance3Soporta criptomonedas, acciones, ETFs e índices4"""5 6import yfinance as yf7import pandas as pd8from typing import Optional, List, Dict9from datetime import datetime, timedelta10import streamlit as st11 12 13# Símbolos disponibles organizados por categoría14# Formato: {categoría: {símbolo: nombre_descriptivo}}15AVAILABLE_SYMBOLS: Dict[str, Dict[str, str]] = {16    'Criptomonedas': {17        'BTC-USD': 'Bitcoin',18        'ETH-USD': 'Ethereum',19        'SOL-USD': 'Solana',20        'BNB-USD': 'Binance Coin',21        'XRP-USD': 'Ripple',22        'DOGE-USD': 'Dogecoin',23        'ADA-USD': 'Cardano',24        'AVAX-USD': 'Avalanche',25        'DOT-USD': 'Polkadot',26        'MATIC-USD': 'Polygon',27        'LINK-USD': 'Chainlink',28        'UNI-USD': 'Uniswap',29        'ATOM-USD': 'Cosmos',30        'LTC-USD': 'Litecoin',31    },32    'Acciones Tech': {33        'AAPL': 'Apple',34        'MSFT': 'Microsoft',35        'GOOGL': 'Google',36        'AMZN': 'Amazon',37        'META': 'Meta (Facebook)',38        'NVDA': 'NVIDIA',39        'TSLA': 'Tesla',40        'AMD': 'AMD',41        'INTC': 'Intel',42        'CRM': 'Salesforce',43        'ADBE': 'Adobe',44        'NFLX': 'Netflix',45        'PYPL': 'PayPal',46        'SHOP': 'Shopify',47    },48    'Acciones Crypto-Related': {49        'MSTR': 'MicroStrategy',50        'COIN': 'Coinbase',51        'MARA': 'Marathon Digital',52        'RIOT': 'Riot Platforms',53        'CLSK': 'CleanSpark',54        'HUT': 'Hut 8 Mining',55    },56    'Acciones Financieras': {57        'JPM': 'JP Morgan',58        'BAC': 'Bank of America',59        'WFC': 'Wells Fargo',60        'GS': 'Goldman Sachs',61        'MS': 'Morgan Stanley',62        'V': 'Visa',63        'MA': 'Mastercard',64    },65    'ETFs': {66        'SPY': 'S&P 500 ETF',67        'QQQ': 'Nasdaq 100 ETF',68        'IWM': 'Russell 2000 ETF',69        'DIA': 'Dow Jones ETF',70        'VTI': 'Total Stock Market',71        'GLD': 'Gold ETF',72        'SLV': 'Silver ETF',73        'USO': 'Oil ETF',74        'IBIT': 'iShares Bitcoin Trust',75        'FBTC': 'Fidelity Bitcoin',76    },77    'Índices': {78        '^GSPC': 'S&P 500 Index',79        '^DJI': 'Dow Jones',80        '^IXIC': 'Nasdaq Composite',81        '^RUT': 'Russell 2000',82        '^VIX': 'VIX Volatility',83    },84    'Forex': {85        'EURUSD=X': 'EUR/USD',86        'GBPUSD=X': 'GBP/USD',87        'USDJPY=X': 'USD/JPY',88        'AUDUSD=X': 'AUD/USD',89        'USDCAD=X': 'USD/CAD',90    },91    'Commodities': {92        'GC=F': 'Gold Futures',93        'SI=F': 'Silver Futures',94        'CL=F': 'Crude Oil Futures',95        'NG=F': 'Natural Gas Futures',96    }97}98 99 100# Lista plana de todos los símbolos101def get_all_symbols() -> List[str]:102    """Retorna lista plana de todos los símbolos disponibles"""103    all_symbols = []104    for category_symbols in AVAILABLE_SYMBOLS.values():105        all_symbols.extend(category_symbols.keys())106    return all_symbols107 108 109# Timeframes disponibles110AVAILABLE_TIMEFRAMES = {111    '1m': '1 Minuto',112    '2m': '2 Minutos',113    '5m': '5 Minutos',114    '15m': '15 Minutos',115    '30m': '30 Minutos',116    '1h': '1 Hora',117    '4h': '4 Horas',  # Se convierte internamente118    '1d': 'Diario',119    '1wk': 'Semanal',120    '1mo': 'Mensual',121}122 123 124class DataLoader:125    """126    Cargador de datos históricos usando yfinance127    """128    129    def __init__(self):130        self._cache = {}131    132    @staticmethod133    @st.cache_data(ttl=3600)134    def download(135        symbol: str,136        start_date: str,137        end_date: str,138        interval: str = '1d'139    ) -> pd.DataFrame:140        """141        Descarga datos históricos de yfinance142        143        Args:144            symbol: Símbolo del activo (ej: 'BTC-USD', 'AAPL')145            start_date: Fecha de inicio (YYYY-MM-DD)146            end_date: Fecha de fin (YYYY-MM-DD)147            interval: Intervalo de las velas148            149        Returns:150            DataFrame con columnas OHLCV151        """152        try:153            # Convertir 4h a formato yfinance (60m * 4 = 240m, pero yfinance no lo soporta)154            # Para 4h, descargar 1h y resamplear155            if interval == '4h':156                df = DataLoader._download_and_resample_4h(symbol, start_date, end_date)157            else:158                ticker = yf.Ticker(symbol)159                df = ticker.history(start=start_date, end=end_date, interval=interval)160            161            if df.empty:162                return pd.DataFrame()163            164            # Renombrar columnas para consistencia165            df = df.rename(columns={166                'Open': 'open',167                'High': 'high',168                'Low': 'low',169                'Close': 'close',170                'Volume': 'volume'171            })172            173            # Eliminar columnas innecesarias174            cols_to_keep = ['open', 'high', 'low', 'close', 'volume']175            df = df[[col for col in cols_to_keep if col in df.columns]]176            177            return df178            179        except Exception as e:180            st.error(f"Error descargando datos para {symbol}: {e}")181            return pd.DataFrame()182    183    @staticmethod184    def _download_and_resample_4h(symbol: str, start_date: str, end_date: str) -> pd.DataFrame:185        """Descarga datos de 1h y los convierte a 4h"""186        try:187            ticker = yf.Ticker(symbol)188            df = ticker.history(start=start_date, end=end_date, interval='1h')189            190            if df.empty:191                return pd.DataFrame()192            193            # Renombrar primero194            df = df.rename(columns={195                'Open': 'open',196                'High': 'high', 197                'Low': 'low',198                'Close': 'close',199                'Volume': 'volume'200            })201            202            # Resamplear a 4 horas203            df_4h = df.resample('4h').agg({204                'open': 'first',205                'high': 'max',206                'low': 'min',207                'close': 'last',208                'volume': 'sum'209            }).dropna()210            211            return df_4h212            213        except Exception as e:214            return pd.DataFrame()215    216    @staticmethod217    def download_multiple(218        symbols: List[str],219        start_date: str,220        end_date: str,221        interval: str = '1d'222    ) -> Dict[str, pd.DataFrame]:223        """224        Descarga datos para múltiples símbolos225        226        Returns:227            Diccionario con símbolo como key y DataFrame como value228        """229        results = {}230        for symbol in symbols:231            df = DataLoader.download(symbol, start_date, end_date, interval)232            if not df.empty:233                results[symbol] = df234        return results235    236    @staticmethod237    def get_symbol_info(symbol: str) -> Optional[Dict]:238        """Obtiene información del símbolo"""239        try:240            ticker = yf.Ticker(symbol)241            info = ticker.info242            return {243                'name': info.get('longName', info.get('shortName', symbol)),244                'currency': info.get('currency', 'USD'),245                'exchange': info.get('exchange', 'Unknown'),246                'type': info.get('quoteType', 'Unknown'),247                'sector': info.get('sector', 'N/A'),248                'industry': info.get('industry', 'N/A'),249            }250        except:251            return None252