# download_data.py """ Script para descargar datos históricos de múltiples símbolos y timeframes """ import os from dotenv import load_dotenv from datetime import datetime, timedelta from pathlib import Path from src.utils.logger import log from src.data.fetcher import DataFetcher from src.data.processor import DataProcessor from src.data.storage import StorageManager from src.data import indicators def setup_environment(): """Carga variables de entorno""" env_path = Path(__file__).parent / 'config' / 'secrets.env' load_dotenv(dotenv_path=env_path) log.success("✓ Variables de entorno cargadas") def download_multiple_symbols(): """ Descarga datos históricos para múltiples símbolos y timeframes """ log.info("="*70) log.info("📥 DESCARGA MASIVA DE DATOS HISTÓRICOS") log.info("="*70) # Configuración setup_environment() exchange_name = os.getenv('EXCHANGE_NAME', 'binance') # Símbolos a descargar (puedes añadir más) symbols = [ 'BTC/USDT', 'ETH/USDT', 'BNB/USDT', 'SOL/USDT', 'XRP/USDT', ] # Timeframes a descargar timeframes = [ '1h', # 1 hora '4h', # 4 horas '1d', # 1 día ] # Días históricos # days_back = 120 # 4 meses END_DATE = datetime.utcnow() START_DATE = END_DATE - timedelta(days=365 * 3) log.info(f"\n📊 Configuración:") log.info(f" Exchange: {exchange_name}") log.info(f" Símbolos: {len(symbols)} → {symbols}") log.info(f" Timeframes: {timeframes}") # log.info(f" Días históricos: {days_back}") log.info(f" Días históricos: from {START_DATE} until {END_DATE}") log.info(f" Total descargas: {len(symbols) * len(timeframes)}") # Confirmar print("\n" + "="*70) response = input("¿Continuar con la descarga? (s/n): ").lower() if response != 's': log.warning("Descarga cancelada por el usuario") return # Inicializar componentes log.info("\n🔧 Inicializando componentes...") fetcher = DataFetcher( exchange_name=exchange_name, api_key=os.getenv('API_KEY') if os.getenv('API_KEY') else None, api_secret=os.getenv('API_SECRET') if os.getenv('API_SECRET') else None ) processor = DataProcessor() storage = StorageManager( db_host=os.getenv('DB_HOST'), db_port=int(os.getenv('DB_PORT', 5432)), db_name=os.getenv('DB_NAME'), db_user=os.getenv('DB_USER'), db_password=os.getenv('DB_PASSWORD'), redis_host=os.getenv('REDIS_HOST', 'localhost'), redis_port=int(os.getenv('REDIS_PORT', 6379)) ) # Estadísticas total_downloads = len(symbols) * len(timeframes) current_download = 0 successful = 0 failed = 0 total_records = 0 # Descargar datos log.info("\n" + "="*70) log.info("🚀 INICIANDO DESCARGAS...") log.info("="*70 + "\n") for symbol in symbols: for timeframe in timeframes: current_download += 1 log.info(f"\n{'='*70}") log.info(f"📥 [{current_download}/{total_downloads}] {symbol} @ {timeframe}") log.info(f"{'='*70}") try: # Verificar si ya existen datos last_timestamp = storage.get_latest_timestamp(symbol, timeframe) if last_timestamp: log.info(f"⚠️ Ya existen datos hasta: {last_timestamp}") log.info(f" Se descargarán solo datos nuevos...") # Descargar datos df = fetcher.fetch_historical( symbol=symbol, timeframe=timeframe, # days=days_back since=START_DATE, until=END_DATE ) if df.empty: log.warning(f"❌ No se obtuvieron datos para {symbol} @ {timeframe}") failed += 1 continue # Procesar log.info(f"🧹 Procesando datos...") df_clean = processor.clean_data(df) df_clean = processor.calculate_returns(df_clean) df_clean = indicators.add_adx(df_clean) # Guardar log.info(f"💾 Guardando en base de datos...") records_saved = storage.save_ohlcv(df_clean) total_records += records_saved successful += 1 log.success(f"✅ {symbol} @ {timeframe} → {records_saved} registros guardados") except Exception as e: log.error(f"❌ Error descargando {symbol} @ {timeframe}: {e}") failed += 1 continue # Resumen final log.info("\n" + "="*70) log.info("📊 RESUMEN DE DESCARGA") log.info("="*70) log.info(f"✅ Exitosas: {successful}/{total_downloads}") log.info(f"❌ Fallidas: {failed}/{total_downloads}") log.info(f"📦 Total registros guardados: {total_records:,}") # Ver datos disponibles log.info("\n📋 Datos disponibles en base de datos:") available_data = storage.get_available_data() print(available_data.to_string(index=False)) # Cleanup storage.close() log.info("\n" + "="*70) log.success("✅ DESCARGA COMPLETADA") log.info("="*70) if __name__ == "__main__": try: download_multiple_symbols() except KeyboardInterrupt: log.warning("\n⚠️ Descarga interrumpida por el usuario") except Exception as e: log.error(f"\n❌ Error fatal: {e}") raise