182 lines
5.8 KiB
Python
182 lines
5.8 KiB
Python
# 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 = [
|
|
'1m', # 1 min
|
|
# '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)
|
|
START_DATE = END_DATE - timedelta(days=50)
|
|
|
|
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 |