Team Ai
Apppublic

diegobeyl/backtesting

sourceHugging Faceupdated 9mo agoView on Hugging Face
2likes
validate_setra_fixed.py144 linesDownload Raw Back to scripts
1#!/usr/bin/env python32"""Validación SETRA: descarga histórico por ticker y guarda JSON serializable.3 4Genera `scripts/setra_validation.json` con tipos nativos (float, bool, int, str/None).5"""6import os7import sys8 9# Añadir la raíz del repo al PYTHONPATH para permitir imports relativos10ROOT = os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))11if ROOT not in sys.path:12    sys.path.insert(0, ROOT)13 14from backtesting_app.core import data_loader15import yfinance as yf16from datetime import datetime, timedelta17import time18import json19import math20 21threshold = 30_000_00022end = datetime.utcnow()23start = end - timedelta(days=60)24 25# localizar clave SETRA26setra_key = None27for k in data_loader.AVAILABLE_SYMBOLS:28    if 'SETRA' in k or 'Alemania' in k:29        setra_key = k30        break31if not setra_key:32    raise SystemExit('No SETRA key found in AVAILABLE_SYMBOLS')33 34tickers = list(data_loader.AVAILABLE_SYMBOLS[setra_key].keys())35results = {}36 37def to_native(o):38    """Convierte tipos comunes de numpy/pandas a tipos nativos JSON-serializables."""39    if o is None:40        return None41    # números42    try:43        if isinstance(o, (int,)):44            return int(o)45        if isinstance(o, (float,)):46            if math.isfinite(o):47                return float(o)48            return None49    except Exception:50        pass51    # numpy / pandas scalars: intentar casting explícito52    try:53        return int(o)54    except Exception:55        pass56    try:57        f = float(o)58        if math.isfinite(f):59            return f60    except Exception:61        pass62    # booleanos (numpy.bool_ también cae aquí)63    try:64        if str(type(o)).lower().find('bool') != -1:65            return bool(o)66    except Exception:67        pass68    # cadenas69    try:70        return str(o)71    except Exception:72        return None73 74# validar tickers uno a uno para evitar timeouts75for t in tickers:76    try:77        tk = yf.Ticker(t)78        hist = tk.history(start=start.strftime('%Y-%m-%d'), end=end.strftime('%Y-%m-%d'), interval='1d')79        if hist is None or hist.empty:80            results[t] = {'status': 'no_data'}81            time.sleep(0.8)82            continue83        hist = hist.tail(30)84        if 'Close' not in hist.columns or 'Volume' not in hist.columns:85            results[t] = {'status': 'no_ohlc'}86            time.sleep(0.8)87            continue88        hist = hist[['Close', 'Volume']].dropna()89        if hist.empty:90            results[t] = {'status': 'no_data'}91            time.sleep(0.8)92            continue93        hist['traded_value'] = hist['Close'] * hist['Volume']94        monthly_value = float(hist['traded_value'].sum())95        info = {}96        try:97            info = tk.info or {}98        except Exception:99            info = {}100        short = info.get('shortName') if isinstance(info, dict) else None101        exch = info.get('exchange') if isinstance(info, dict) else None102 103        # normalizar valores a tipos nativos104        monthly_native = to_native(monthly_value)105        meets = False if monthly_native is None else bool(monthly_native >= threshold)106        entry = {107            'monthly_value': monthly_native,108            'meets_threshold': meets,109            'name': to_native(short),110            'exchange': to_native(exch),111            'rows': to_native(len(hist))112        }113        results[t] = entry114    except Exception as e:115        results[t] = {'error': to_native(str(e))}116    # pequeña pausa entre tickers117    time.sleep(0.8)118 119# guardar resultados en workspace con metadatos120out = {121    'key': setra_key,122    'timestamp': end.isoformat(),123    'total': to_native(len(results)),124    'threshold': to_native(threshold),125    'results': results,126}127 128out_path = 'scripts/setra_validation.json'129with open(out_path, 'w') as f:130    json.dump(out, f, indent=2, ensure_ascii=False)131 132meet = [t for t, v in results.items() if v.get('meets_threshold')]133not_meet = [t for t, v in results.items() if 'meets_threshold' in v and not v.get('meets_threshold')]134no_data = [t for t, v in results.items() if v.get('status')]135 136print('Wrote', out_path)137print('Checked', len(results), 'tickers')138print('Meets:', len(meet))139print('Not meet:', len(not_meet))140print('No data:', len(no_data))141print('Meets sample:', meet[:20])142print('Not meet sample:', not_meet[:20])143print('No data sample:', no_data[:20])144