Fuentes de Datos Históricos

Overview

La calidad de tus datos determina la calidad de tu backtesting. Aquí están las fuentes que uso actualmente, cada una con sus pros y contras.

Yahoo Finance

Características

Instalación y Uso

pip install yfinance
import yfinance as yf
import pandas as pd

# Datos diarios
ticker = yf.Ticker("AAPL")
data = ticker.history(start="2023-01-01", end="2023-12-31")

# Múltiples tickers
tickers = ["AAPL", "MSFT", "GOOGL"]
data = yf.download(tickers, start="2023-01-01", end="2023-12-31")

# Datos intraday (últimos 60 días max)
intraday = ticker.history(period="1d", interval="1m")

Limitaciones

Cuándo Usar

Polygon.io

Características

Setup

pip install polygon-api-client
from polygon import RESTClient
import os

client = RESTClient(api_key=os.getenv("POLYGON_API_KEY"))

# Aggregates (barras)
aggs = client.get_aggs(
    ticker="AAPL",
    multiplier=5,
    timespan="minute",
    from_="2023-01-01",
    to="2023-12-31"
)

# Trades (tick data)
trades = client.list_trades(
    ticker="AAPL",
    timestamp="2023-06-01"
)

# Quote data (NBBO)
quotes = client.list_quotes(
    ticker="AAPL",
    timestamp="2023-06-01"
)

Planes y Precios (2024)

Nota: Precios para usuarios individuales. Planes profesionales tienen costos diferentes.

Cuándo Usar

TWS de Interactive Brokers

Características

Configuración con ib_insync

pip install ib_insync
from ib_insync import *

ib = IB()
ib.connect('127.0.0.1', 7497, clientId=1)  # Paper: 7497, Live: 7496

# Contract
contract = Stock('AAPL', 'SMART', 'USD')

# Datos históricos
bars = ib.reqHistoricalData(
    contract,
    endDateTime='',
    durationStr='30 D',
    barSizeSetting='1 min',
    whatToShow='TRADES',
    useRTH=True
)

# Convertir a DataFrame
df = util.df(bars)

# Real-time bars
def onBarUpdate(bars, hasNewBar):
    print(bars[-1])

bars = ib.reqRealTimeBars(contract, 5, 'TRADES', True)
bars.updateEvent += onBarUpdate

Limitaciones

Cuándo Usar

DAS Trader

Características

Exportar Datos

# DAS guarda logs en formato CSV
import pandas as pd
import glob

# Leer trades ejecutados
trades_files = glob.glob('C:/DAS/Trades/*.csv')
trades = pd.concat([pd.read_csv(f) for f in trades_files])

# Procesar para análisis
trades['Time'] = pd.to_datetime(trades['Time'])
trades['PnL'] = trades['ExitPrice'] - trades['EntryPrice']

Integración con Python

# Usar DAS API (requiere DAS Trader Pro)
import win32com.client

das = win32com.client.Dispatch("DAS.Application")
das.SendOrder("BUY", "AAPL", 100, "MARKET")

Cuándo Usar

QuantConnect

Características

Ejemplo de Algoritmo

class MyAlgorithm(QCAlgorithm):
    def Initialize(self):
        self.SetStartDate(2023, 1, 1)
        self.SetEndDate(2023, 12, 31)
        self.SetCash(100000)
        
        # Agregar securities
        self.spy = self.AddEquity("SPY", Resolution.Minute)
        
        # Indicadores
        self.sma = self.SMA("SPY", 20, Resolution.Daily)
        
    def OnData(self, data):
        if not self.sma.IsReady:
            return
            
        if data["SPY"].Price > self.sma.Current.Value:
            self.SetHoldings("SPY", 1.0)
        else:
            self.Liquidate("SPY")

Ventajas

Cuándo Usar

Flash Research

Características

Casos de Uso

# Ejemplo conceptual - Flash Research provee insights, no raw data
insights = {
    'institutional_accumulation': ['AAPL', 'MSFT'],
    'unusual_options_activity': [
        {'ticker': 'NVDA', 'strike': 500, 'volume': 10000}
    ],
    'dark_pool_prints': [
        {'ticker': 'TSLA', 'size': 500000, 'price': 250.50}
    ]
}

# Usar estos insights para filtrar universo
universe = screen_stocks(insights['institutional_accumulation'])

Cuándo Usar

Mi Stack Actual

# config.py
DATA_SOURCES = {
    'historical': 'polygon',      # Para backtesting preciso
    'realtime': 'ibkr_tws',      # Para ejecución
    'screening': 'yahoo',         # Para ideas rápidas
    'research': 'quantconnect',   # Para estrategias complejas
    'insights': 'flash_research'  # Para confirmación
}

# data_manager.py
class DataManager:
    def __init__(self):
        self.polygon = PolygonClient()
        self.yahoo = YahooClient()
        self.ibkr = IBKRClient()
        
    def get_data(self, ticker, source='auto'):
        if source == 'auto':
            # Lógica para elegir mejor fuente
            if self.need_intraday:
                return self.polygon.get_data(ticker)
            else:
                return self.yahoo.get_data(ticker)

Costos Mensuales

Fuente Costo Lo que obtienes
Yahoo Finance $0 EOD data, screening básico
Polygon.io $79 10 años intraday, websocket
IBKR $10 + comms Real-time, ejecución
DAS Trader $150 Plataforma pro + data
QuantConnect $0-$200 Backtest + live deployment
Flash Research Variable Market intelligence

Total: ~$300-400/mes para setup profesional

Tips para Empezar

  1. Empieza gratis: Yahoo Finance + paper trading IBKR
  2. Primer upgrade: Polygon.io Developer ($79)
  3. Cuando seas consistente: Agrega DAS o similar
  4. Para escalar: QuantConnect para múltiples estrategias

Data Quality Checklist

def validate_data(df):
    checks = {
        'no_gaps': df.index.is_monotonic_increasing,
        'no_nulls': not df.isnull().any().any(),
        'volume_positive': (df['Volume'] >= 0).all(),
        'prices_positive': (df[['Open', 'High', 'Low', 'Close']] > 0).all().all(),
        'high_low_valid': (df['High'] >= df['Low']).all(),
        'ohlc_valid': (
            (df['High'] >= df[['Open', 'Close']].max(axis=1)).all() &
            (df['Low'] <= df[['Open', 'Close']].min(axis=1)).all()
        )
    }
    
    return pd.Series(checks)

Siguiente Paso

Continúa con Tipos de Datos para entender las diferencias entre EOD, intraday y tick data.