Sistema de trading bot - Semanas 1-2 completadas
- Infraestructura de datos completa - Descarga desde exchanges (CCXT) - Procesamiento y limpieza de datos - Almacenamiento en PostgreSQL - Sistema anti-duplicados - Script de descarga masiva - Tests unitarios - Documentación completa
This commit is contained in:
173
download_data.py
Normal file
173
download_data.py
Normal file
@@ -0,0 +1,173 @@
|
||||
# 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
|
||||
from pathlib import Path
|
||||
from src.monitoring.logger import log
|
||||
from src.data.fetcher import DataFetcher
|
||||
from src.data.processor import DataProcessor
|
||||
from src.data.storage import StorageManager
|
||||
|
||||
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
|
||||
|
||||
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" 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
|
||||
)
|
||||
|
||||
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)
|
||||
|
||||
# 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
|
||||
Reference in New Issue
Block a user