Trading bot
etapa: DRY_RUN (sin órdenes) · observación no iniciada · código que opera 33a2295 · más… v0.1.0 · 97853d1 arrancado 2026-09-11 23:42 Lima último ciclo 2026-09-11 08:44 último sync 2026-09-11 15:17 sqlite:///./trading.db código que opera: release · 33a2295 · esta página: main · 97853d1 etapa: DRY_RUN (sin órdenes) observación no iniciada resumen

Backtest de cartera (2020-07-27 → 2022-12-30)

Estrategia: sma_cross · Selector: fuerza de tendencia (cierre / SMA200 − 1)
Parámetros: {'fast': 20, 'slow': 50, 'trend': 200, 'atr_period': 14, 'stop_atr_mult': 2.0, 'take_profit_atr_mult': 3.0, 'max_hold_days': 40, 'calendar_days': False, 'volume_filter_ratio': 0.8, 'entry_window': 5, 'exit_mode': 'take_profit'}
Universo (10): SPY QQQ AAPL MSFT NVDA AMZN GOOGL META JPM XOM · Benchmark: SPY

Métricas por modo de salida

Símbolo Periodo Retorno CAGR Max DD Sharpe Trades Win % Expectancy Exposición Buy & Hold
PORTFOLIO-REAL2000-IS (take_profit) 2020-07-27 → 2022-12-30 +2.4% +1.0% -1.1% 0.91 10 80% +3.57% 23% +18.3%

La columna Buy & Hold es SPY en el mismo periodo.

Detalle take_profit

Operaciones cerradas: 10 · Máx. posiciones simultáneas: 2/5 · Señales descartadas por falta de huecos: 0 · por régimen: 0 · por hueco de apertura: 0 · Reglas de riesgo: 0 kills diarios, 0 días vetados por drawdown, 0 señales descartadas, 0 vetadas por anti-PDT (0 day trades) · Precios nominales: sí (0 posiciones atravesaron un split)

Riesgo comparable: SPY a la misma volatilidad (mezcla con efectivo, vol móvil 60 d): +0.3 % · IC 90 % del retorno anualizado (bootstrap por bloques): [-0.1 %, +2.0 %]

Símbolo Trades Win % P&L Ret. medio
AAPL 3 67% +4.94 +1.46%
JPM 2 100% +16.78 +5.98%
XOM 5 80% +26.54 +3.87%

Por año y régimen take_profit

Grupo Ops Win rate P&L medio P&L total Ret. medio
2021 5 100% +8.42 +42.11 +5.15%
régimen bull 7 86% +6.17 +43.17 +3.91%
2022 5 60% +1.23 +6.15 +1.99%
régimen bear 3 67% +1.70 +5.09 +2.76%

Últimas operaciones take_profit

Entrada Salida Precio in Precio out Qty P&L Ret. Motivo salida
2021-05-14 2021-06-16 60.04 64.25 3 +12.62 +7.01% take-profit: close 64.37 >= 64.10; SMA20=60.60 SMA50=59.05 SMA200=47.50 ATR=1.35 close=64.37
2021-06-29 2021-07-06 134.77 140.56 1 +5.79 +4.30% bracket take-profit
2021-08-18 2021-09-27 156.27 164.75 1 +8.48 +5.43% bracket take-profit
2021-10-05 2021-11-10 62.46 65.29 3 +8.48 +4.52% take-profit: close 66.36 >= 66.33; SMA20=63.86 SMA50=59.77 SMA200=58.01 ATR=1.29 close=66.36
2021-11-10 2021-11-18 150.11 156.84 1 +6.74 +4.49% bracket take-profit
2022-01-12 2022-01-26 71.46 75.78 2 +8.64 +6.05% bracket take-profit
2022-04-06 2022-04-18 172.37 164.78 1 -7.59 -4.40% bracket stop-loss
2022-08-19 2022-09-23 94.19 88.55 2 -11.27 -5.98% bracket stop-loss
2022-10-20 2022-11-07 104.26 112.32 1 +8.07 +7.74% take-profit: close 112.30 >= 112.06; SMA20=105.27 SMA50=98.42 SMA200=89.64 ATR=2.60 close=112.30
2022-11-01 2022-11-11 127.06 135.36 1 +8.30 +6.53% take-profit: close 135.13 >= 134.71; SMA20=124.39 SMA50=116.70 SMA200=124.82 ATR=2.55 close=135.13

Lectura honesta

  • Sesgo de supervivencia. El universo son símbolos que hoy sabemos que sobrevivieron y subieron; sobre datos de 2019 en adelante eso infla el resultado. Compara siempre contra el benchmark y trata estas cifras como techo, no como expectativa.
  • Este backtest de cartera es el que se compara con el paper: mismo capital compartido, mismo límite de posiciones, mismo sizing y mismo selector.
  • Paridad con el bot: hueco de apertura > MAX_GAP_PCT descarta la entrada y stop/take-profit se desplazan con el precio de apertura, como en engine/cycle.py. Lo que el backtest NO reproduce: la cancelación de entradas sin fill (aquí toda entrada se llena en la apertura), los fills parciales y la latencia real del cron. La regla anti-PDT SÍ se simula con --risk-rules (solo veta entradas, como en vivo).
  • Reglas de pérdida diaria y drawdown solo con --risk-rules (el workflow automático las activa): con el histórico gratuito (desde 2020-07-27) nunca se disparan; se prueban con un crash sintético en tests/test_kill_switch_system.py.
  • El objetivo de take-profit de la regla al cierre se recalcula cada día con el ATR actual (entrada + 3×ATR), mientras la pata bracket queda fija en la entrada: cuando la volatilidad baja, la regla al cierre vence antes. El bot hace exactamente lo mismo (docs/STRATEGY.md).
  • El número de operaciones no es un umbral universal de validez: mira el intervalo de confianza del retorno anualizado (bootstrap por bloques, abajo) y recuerda que esta ventana participó en la selección de variantes.

Cómo se calcula

  • Sharpe: retornos diarios de la equity de la cartera, tipo libre de riesgo 0, media ÷ desviación × √252. Sin remuneración del efectivo (la cuenta paper no paga intereses).
  • Costes: comisión 0.00 % por lado + 0.00 USD por orden; slippage 0.050 % por lado sobre apertura, stop y objetivo.
  • Drawdown máximo: caída desde el máximo previo de la equity diaria al cierre.
  • Exposición: % de días con alguna posición abierta. Es tiempo invertido, no capital ni riesgo: no se usa como denominador de nada.
  • Benchmark a la misma volatilidad: mezcla benchmark + efectivo cuyo peso sigue la volatilidad móvil de 60 días de la estrategia (solo datos pasados). Descriptivo.
  • IC 90 % del retorno anualizado: bootstrap por bloques de 10 días sobre los retornos diarios (1 000 remuestreos). Conserva la dependencia dentro del bloque; NO corrige que la ventana fuera de muestra participó en la selección del modo de salida.
  • Precios: indicadores sobre barras ajustadas por splits (IEX); dinero, tamaños enteros, stop y objetivo con precios nominales del día: sí.
  • Anti-PDT (con reglas de riesgo): veta entradas nuevas tras 3 operaciones abiertas y cerradas el mismo día en 5 días hábiles si la equity está bajo 25,000 USD; nunca bloquea una salida. Como en vivo.
  • Evidencia técnica vs económica: este reporte mide si el sistema hace lo que dice; no demuestra ventaja económica. Esa se plantea aparte, con la observación en paper y estos intervalos, nunca con el retorno acumulado solo.

Reproducir

  • Commit del código: 957a040
  • Comando: bot backtest-portfolio --start 2019-01-01 --split 2023-01-01 --cash 2000 --exit-mode take_profit --risk-rules --tag REAL2000 --no-png
  • Hash de los datos (cachés CSV usadas): 8bfaba63e4ea
  • Datos conservados en: backtest-data/2026-09-12
  • Ajuste y feed: split (indicadores) + raw (dinero), feed IEX
  • alpaca-py: 0.44.0
  • Generado: 2026-09-12 04:37 UTC
  • Mismo commit + mismos archivos de caché + mismo comando → mismo resultado (tests/test_backtest_reproducible.py). Sin el archivo de datos el hash no sirve.

trading-bot v0.1.0 · 2026-09-11 23:42 Lima (04:42 UTC)