datetime,open,high,low,close,volume. Descargá el archivo de práctica binance_btcusdt_1h.csv, guardalo en data/binance_btcusdt_1h.csv y cargalo con bt.feeds.GenericCSVData.
Descargar binance_btcusdt_1h.csv
Si buscás "binance_btcusdt_1h.csv", esta lección incluye un archivo CSV listo para descargar y usar en Backtrader. El archivo de práctica contiene 24 velas BTCUSDT de 1 hora tomadas del endpoint público de Binance el 2026-05-19. Sirve para validar formato, instalación y ejecución de Backtrader antes de trabajar con históricos más grandes.
Descargar binance_btcusdt_1h.csv
Archivo: binance_btcusdt_1h.csv
Columnas: datetime, open, high, low, close, volume
Uso: Backtrader GenericCSVData
Intervalo: BTCUSDT 1h
datetime,open,high,low,close,volume
2026-05-18T04:00:00Z,76924.66000000,77069.77000000,76772.01000000,77038.49000000,354.48166000
2026-05-18T05:00:00Z,77038.49000000,77080.93000000,76884.33000000,76931.40000000,586.83852000
Columnas que espera Backtrader
| Columna | Índice | Uso en Backtrader |
|---|---|---|
datetime | 0 | Fecha y hora de apertura de la vela. |
open | 1 | Precio de apertura. |
high | 2 | Máximo de la vela. |
low | 3 | Mínimo de la vela. |
close | 4 | Precio de cierre. |
volume | 5 | Volumen operado. |
El CSV no incluye openinterest. Por eso se configura openinterest=-1.
Instalar Backtrader y preparar carpetas
python -m venv .venv
source .venv/bin/activate
pip install backtrader pandas matplotlib
mkdir -p data
# colocá el archivo descargado en:
# data/binance_btcusdt_1h.csv
Si estás en Windows, activá el entorno con .venv\Scripts\activate. La estructura mínima del proyecto queda así:
trading-backtest/
data/
binance_btcusdt_1h.csv
backtest_btcusdt.py
Validar el CSV antes del backtest
Antes de abrir Backtrader, comprobá que el archivo tiene columnas, fechas y tipos numéricos correctos:
import pandas as pd
df = pd.read_csv("data/binance_btcusdt_1h.csv")
print(df.head())
print(df.dtypes)
required = ["datetime", "open", "high", "low", "close", "volume"]
missing = [column for column in required if column not in df.columns]
if missing:
raise ValueError(f"Faltan columnas: {missing}")
df["datetime"] = pd.to_datetime(df["datetime"], utc=True)
for column in ["open", "high", "low", "close", "volume"]:
df[column] = pd.to_numeric(df[column])
print(df[required].tail())
Este chequeo evita errores silenciosos: fechas como texto mal interpretado, columnas desordenadas, separadores incorrectos o valores vacíos.
Cargar binance_btcusdt_1h.csv con GenericCSVData
Backtrader lee el archivo con GenericCSVData. La parte importante es mapear cada columna a su índice real:
import backtrader as bt
data = bt.feeds.GenericCSVData(
dataname="data/binance_btcusdt_1h.csv",
dtformat="%Y-%m-%dT%H:%M:%SZ",
datetime=0,
open=1,
high=2,
low=3,
close=4,
volume=5,
openinterest=-1,
)
cerebro = bt.Cerebro()
cerebro.adddata(data, name="BTCUSDT-1h")
Backtest completo con cruce de medias
Este ejemplo es intencionalmente simple. No es recomendación financiera: es una prueba técnica para confirmar que el entorno, el CSV y el motor de backtesting funcionan.
import backtrader as bt
class MovingAverageCross(bt.Strategy):
params = (("fast", 6), ("slow", 12))
def __init__(self):
self.fast_ma = bt.indicators.SimpleMovingAverage(self.data.close, period=self.params.fast)
self.slow_ma = bt.indicators.SimpleMovingAverage(self.data.close, period=self.params.slow)
self.crossover = bt.indicators.CrossOver(self.fast_ma, self.slow_ma)
def next(self):
if not self.position and self.crossover > 0:
self.buy(size=0.01)
elif self.position and self.crossover < 0:
self.close()
data = bt.feeds.GenericCSVData(
dataname="data/binance_btcusdt_1h.csv",
dtformat="%Y-%m-%dT%H:%M:%SZ",
datetime=0,
open=1,
high=2,
low=3,
close=4,
volume=5,
openinterest=-1,
)
cerebro = bt.Cerebro()
cerebro.addstrategy(MovingAverageCross)
cerebro.adddata(data, name="BTCUSDT-1h")
cerebro.broker.setcash(10000)
cerebro.broker.setcommission(commission=0.001)
print(f"Capital inicial: {cerebro.broker.getvalue():.2f}")
cerebro.run()
print(f"Capital final: {cerebro.broker.getvalue():.2f}")
Generar tu propio CSV desde Binance
Binance expone velas con GET /api/v3/klines. Para BTCUSDT de 1 hora usás symbol=BTCUSDT, interval=1h y convertís open time, open, high, low, close y volume al formato que usa esta lección.
import csv
import requests
from datetime import datetime, timezone
url = "https://api.binance.com/api/v3/klines"
params = {"symbol": "BTCUSDT", "interval": "1h", "limit": 100}
rows = requests.get(url, params=params, timeout=20).json()
with open("data/binance_btcusdt_1h.csv", "w", newline="") as file:
writer = csv.writer(file)
writer.writerow(["datetime", "open", "high", "low", "close", "volume"])
for row in rows:
open_time = datetime.fromtimestamp(row[0] / 1000, tz=timezone.utc)
writer.writerow([
open_time.strftime("%Y-%m-%dT%H:%M:%SZ"),
row[1],
row[2],
row[3],
row[4],
row[5],
])
Referencias oficiales: Binance Kline/Candlestick data y Backtrader Data Feeds.
Errores comunes con binance_btcusdt_1h.csv
| Error | Causa probable | Solución |
|---|---|---|
time data does not match format | El formato de fecha no coincide con dtformat. | Usá %Y-%m-%dT%H:%M:%SZ para fechas ISO con Z. |
| Backtest sin operaciones | Muy pocas velas para los períodos de medias. | Bajá fast/slow o descargá más velas. |
| Valores absurdos | Columnas mal mapeadas. | Confirmá índices: datetime 0, open 1, high 2, low 3, close 4, volume 5. |
| Resultados demasiado buenos | Comisiones, slippage o look-ahead bias ignorados. | Agregá comisión realista y no uses datos futuros en next(). |
Checklist para un backtest presentable
- El dataset tiene fuente, fecha de descarga, símbolo, intervalo y columnas documentadas.
- El script corre desde cero con instrucciones de instalación claras.
- La estrategia no usa datos futuros.
- El backtest incluye comisión y capital inicial explícitos.
- El README explica límites: muestra corta, sin recomendación financiera y sin garantía de rendimiento real.
Convertirlo en portfolio laboral
Para que esta práctica sirva en una entrevista o propuesta freelance, subí un repositorio con el CSV de muestra, el script de Backtrader, un README y una captura de salida. Después agregá una versión que descargue datos recientes desde Binance y compare dos estrategias simples.
Este tipo de proyecto conecta con rutas de empleos tech en data, automatización y finanzas, y también con servicios que podés ofrecer en el marketplace de profesionales: limpieza de datos, backtesting básico, dashboards de riesgo o automatizaciones Python.