Trading bot
DRY_RUN
v0.1.0 · d3b61f2 arrancado 2026-09-11 03:16 UTC último ciclo nunca último sync nunca sqlite:///./trading.db auto-update OFF

Historial de cambios

2026-09-11 — GitHub Actions + panel estático en Cloudflare + comandos por Telegram

  • Hugging Face pasó a exigir PRO para Docker/Gradio: nuevo despliegue gratuito sin tarjeta.
  • bot job auto|execute|sync|snapshot|summary|backup|close: un job por invocación; auto decide por hora de Nueva York (ciclo si el mercado está abierto y no hubo hoy; cierre a partir de las 16:05 ET; sync en cualquier otro caso).
  • .github/workflows/bot.yml: cron en UTC (9:35 ET y cada hora hasta el cierre), restaura y guarda la BD en la rama state, publica el panel en la rama site.
  • Comandos por Telegram (engine/commands.py, bot telegram poll, job cada 5 min en bot run): /kill, /resume, /status, /nota, /watch, /unwatch, /help. Solo del chat configurado.
  • bot site build: panel y documentación como HTML estático (sin formularios ni scripts) para Cloudflare Pages.
  • Guía deploy/GITHUB_ACTIONS.md (secretos, primer lanzamiento, Cloudflare Pages + Access).

2026-09-11 — Hugging Face Spaces: bot y panel 24/7 sin tarjeta

  • engine/state_sync.py y bot state push|pull: la BD (y el archivo KILL) se guardan en la rama state del repositorio con copia consistente de SQLite; commit solo si cambió; al arrancar se restaura si la copia remota es más reciente.
  • Job state_push cada hora al :20 con STATE_SYNC=true; también tras cada ciclo, el resumen diario y al pulsar kill/resume en el panel.
  • deploy/huggingface/Dockerfile (único archivo que se sube al Space: clona el repo con GITHUB_TOKEN y delega en run.sh), run.sh (supervisor de bot run + bot web) y guía paso a paso con cron-job.org para que el Space no se duerma.
  • Corrección crítica: bot run fallaba al arrancar ('Job' object has no attribute 'next_run_time') al listar los jobs antes de iniciar el scheduler; ahora pregunta al trigger.

2026-09-11 — Servidor 24/7: instalador, backup diario y guía Oracle Cloud

  • deploy/install.sh: instalación idempotente en Ubuntu (paquetes, venv, .env, servicios).
  • Unidades systemd como plantillas @usuario, SuccessExitStatus=3 (reinicio por auto-update) y panel con --reload.
  • Job backup a las 16:30 ET y bot backup: copia consistente de trading.db en backups/ (API de backup de SQLite; se conservan 14).
  • Mensajes de inicio y resumen diario con el nombre de la máquina: un solo bot por cuenta.
  • deploy/SERVER.md reescrito: Oracle Cloud paso a paso, Tailscale para el celular, problemas frecuentes.

2026-09-11 — El bot se actualiza solo (AUTO_UPDATE)

  • engine/updater.py: git fetch + merge --ff-only origin/main; reinstala con pip si cambió pyproject.toml; rechaza cambios locales sin commit y ramas divergentes; timeouts en git.
  • Job update en bot run (cada hora al :50, solo con AUTO_UPDATE=true): si hay código nuevo avisa por Telegram con los commits y sale con código 3 para que el supervisor lo relance. Todos los jobs corren en serie bajo un lock: nunca se reinicia a mitad de un ciclo.
  • Errores de actualización notificados una sola vez por mensaje distinto.
  • Nuevo bot update [--check]; bot version y la barra del panel muestran el estado.
  • deploy/run-forever.cmd y deploy/web-forever.cmd (supervisores para Windows); SERVER.md y README actualizados.
  • Operativa: los PR se fusionan en main cuando CI está verde y el bot los recibe solo.

2026-09-11 — Panel: barra de estado, avisos y bot version

  • El panel muestra una barra de estado con versión, commit corto, hora de arranque del proceso, último ciclo, última sincronización, base de datos y carpeta docs/.
  • Avisos automáticos: hay código nuevo en disco (reinicia bot web), el bot no ha ejecutado ningún ciclo hoy, y no se encuentra docs/.
  • Rutas robustas: docs/ se resuelve desde el directorio actual o, si no está, desde la raíz del paquete instalado; docs/backtests se crea si falta.
  • __version__ sale de los metadatos del paquete instalado; nuevo bot version.
  • Las páginas de documentación indican su archivo fuente y cuándo se modificó.
  • README: sección "El panel no se actualiza".
  • apscheduler pasa a dependencia principal (bot run la necesita; CI y pip install -e . no la instalaban).
  • Actualización automática: el navegador sondea /api/heartbeat cada WEB_REFRESH_SECONDS (30 s) y recarga la página cuando hay ciclo, sync, kill switch o docs nuevos; bot web --reload reinicia el servidor al cambiar el código, vigilando la carpeta del paquete.

2026-09-11 — Más horas de mercado: catch-up, healthcheck, despliegue y backtest cripto

  • bot run ejecuta el ciclo del día al arrancar si el mercado está abierto y aún no se hizo (catch-up); siempre sincroniza al arrancar.
  • HEALTHCHECK_URL: ping a healthchecks.io tras cada ciclo y sincronización, para que un servicio externo avise si el bot muere.
  • deploy/: unidades systemd para el bot y el panel, y guía SERVER.md (Windows interino, Oracle Cloud Always Free, Raspberry Pi, Tailscale/túnel SSH).
  • Backtest cripto: CryptoBarsProvider (barras de 1h/4h/1d, sin credenciales, caché BTC-USD_4h.csv), commission_pct por lado en ambos motores, calendar_days en la estrategia (los fines de semana cuentan), bot backtest-portfolio --market crypto con capital = CRYPTO_CAPITAL_PCT × cash, CRYPTO_MAX_OPEN_POSITIONS y benchmark BTC/USD. Reportes PORTFOLIO-CRYPTO-IS_* / -OOS_*.
  • Config nueva: CRYPTO_* (módulo desactivado por defecto) y HEALTHCHECK_URL.
  • Decisión: el módulo cripto en vivo (stop-limit en Alpaca tras el fill, capital separado, jobs cada 4 h) solo se construye si el backtest supera a mantener BTC en Sharpe o drawdown con ≥ 30 operaciones fuera de muestra.

2026-09-10 — Primer backtest de cartera real y corrección de la ventana out-of-sample

  • Reportes PORTFOLIO-IS_2020-07-27_2022-12-30 y PORTFOLIO-OOS_2021-11-29_2026-09-10 commiteados; cierran la versión 1.1 de la estrategia. Resultado honesto: fuera de muestra +14.6 % (take_profit) con drawdown −2.9 % frente a +63.1 % de SPY. Protege capital, no bate al índice. take_profit se mantiene: trailing fue mejor en muestra y peor fuera de muestra.
  • Corrección: la ventana out-of-sample incluía los 400 días previos al corte (necesarios para calentar indicadores) también en las métricas y en el benchmark. Ahora se recortan al corte (backtest.engine.trim). Los reportes OOS anteriores están ligeramente contaminados; el próximo bot backtest-portfolio --split los regenera.
  • Nota de datos: el feed gratuito IEX empieza el 27-07-2020, no en 2019.

2026-09-10 — Fase 2 (código): scheduler y Telegram

  • bot run: APScheduler en hora de Nueva York con cuatro jobs de lunes a viernes: ejecución 9:35, sincronización de órdenes cada hora (10:05–16:05), snapshot de equity 16:10 y resumen diario 16:15. Un job que falla notifica y no mata el proceso.
  • notify/telegram.py (POST con httpx, sin reintentos, nunca propaga errores) y NullNotifier cuando no hay token. bot notify-test para probar.
  • engine/runner.py: run_cycle_and_notify, run_sync_and_notify, take_equity_snapshot, send_daily_summary (incluye posiciones cerradas del día y day trades). bot cycle y bot sync usan el mismo runner que el scheduler.
  • Se abandona el ciclo de 15 minutos: con decisiones diarias y stops en el bróker no aportaba.
  • 14 tests nuevos (114 en total). Queda pendiente la observación: 3 días DRY_RUN + 10 días paper.

2026-09-10 — Fase 1b (parte 2): ciclo de vida de posiciones y sincronización

  • Nueva tabla positions con máquina de estados: SIGNALED → SUBMITTED → OPEN → EXITING → CLOSED, más REJECTED y CANCELLED. Transiciones del bot y de Alpaca en execution/lifecycle.py.
  • execution/sync.py: en cada ciclo se consultan las órdenes por id, se registran fills y patas ejecutadas (stop / take-profit), se cierran posiciones que Alpaca cerró por su cuenta, se reconcilian posiciones ausentes y se cuentan los day trades reales para la regla anti-PDT.
  • Executor: submit_exit cancela las patas abiertas del bracket (una vez, sin reintentos) antes de vender la cantidad real que reporta el bróker. Sin esto Alpaca rechazaba la venta.
  • Recalculo en ejecución: el último precio sustituye al cierre de la señal; stop y take-profit se desplazan a la misma distancia y la cantidad se recalcula. MAX_GAP_PCT (3 %) descarta la entrada si el precio se alejó demasiado.
  • Kill switch diario: la pérdida diaria activa kill_until=hoy; el ciclo lo levanta al día siguiente. El kill manual sigue exigiendo bot resume.
  • Modo trailing en vivo: en HOLD, si el stop calculado es mayor, se actualiza la pata stop del bróker (replace_stop); nunca baja. Las entradas trailing usan orden OTO (entrada + stop).
  • FakeBroker simula fills, vencimientos y patas ejecutadas para los tests. init_db añade columnas nuevas a bases de datos SQLite existentes.
  • 17 tests nuevos del ciclo de vida (100 en total).

2026-09-10 — Fase 1b (parte 1): backtest de cartera y modo de salida trailing

  • bot backtest-portfolio: capital compartido, MAX_OPEN_POSITIONS, mismo position_size, bracket simulado con mínimo/máximo del día y stop primero, selector por fuerza de tendencia (cierre / SMA200 − 1). Reporte PORTFOLIO_*.md + PNG con curva vs benchmark y nota explícita de sesgo de supervivencia. --split genera PORTFOLIO-IS_* y PORTFOLIO-OOS_*.
  • Estrategia: EXIT_MODE=trailing (solo stop, que sube con el máximo alcanzado menos STOP_ATR_MULT × ATR). Signal lleva ahora atr; PositionInfo lleva stop_price y high_water. El motor por símbolo también soporta trailing.
  • Sin reglas de pérdida diaria ni drawdown en esta primera versión, a propósito.

2026-09-10 — Revisión pre-paper: correcciones de plan y reglas

Una revisión externa detectó defectos que romperían el paper trading. Decisiones:

  • Se mantienen las órdenes bracket de Alpaca: el stop vive en el bróker, no en el proceso del bot. En la Fase 6 el capital mínimo pasa a ~1 500–2 000 USD y se filtran símbolos cuyo precio no cabe en MAX_POSITION_PCT × equity.
  • Nueva Fase 1b antes del paper: backtest de cartera (capital compartido, límite de posiciones, selector, comparación take-profit vs trailing) y ciclo de vida de posiciones (cancelar patas del bracket antes de vender, sincronizar fills, recalcular stop y cantidad en ejecución con MAX_GAP_PCT, kill switch diario con expiración, conteo real de day trades).
  • Horario de la Fase 2: ejecución 9:35 ET, sincronización cada hora, snapshot 16:10, resumen 16:15. Se abandona el ciclo de 15 minutos.
  • MIN_CASH_PCT eliminado del gestor de riesgo: con 5 posiciones de 10 % nunca actuaba.
  • Barras diarias ajustadas por splits (adjustment=SPLIT); la caché cambia a *_1d_split.csv.
  • Documentado "stop primero" cuando mínimo y máximo tocan ambos niveles en la misma barra.
  • Retirado el filtro de earnings (sin fuente gratuita). El plan ya no cita backtesting.py.
  • Nuevos parámetros EXIT_MODE y MAX_GAP_PCT (efectivos en Fase 1b).

<details><summary>Archivo: evaluación original de la web (sección 7 del plan)</summary>

Opción Veredicto
FastAPI + Jinja2 + HTMX Recomendada: mismo proceso y modelos que el bot, casi sin JS, fácil de autenticar
Dashboard estático vanilla-JS (estilo SPA) contra /api/* Alternativa válida si prefiere JS; localStorage no sirve porque la fuente de verdad es la BD del bot
Streamlit Útil para explorar backtests, no como dashboard 24/7
CSV / Notion Complemento para notas largas, no sustituto (sin estado en vivo ni kill switch)

MVP en orden: estado + kill switch → bitácora de decisiones (lo más valioso) → journal + watchlist → métricas → logs. No al inicio: velas interactivas, websockets, multiusuario.


</details>

2026-09-10 — Fase 3: panel operativo local y documentación viva

  • bot web sirve un panel FastAPI + Jinja2 en 127.0.0.1:8000 con autenticación básica opcional.
  • Operativo: dashboard (equity, P&L, posiciones, órdenes, decisiones, kill switch con confirmación), bitácora con filtros, journal, watchlist, métricas (curva de equity SVG, drawdown, conteos), logs y API JSON (/api/status, /api/decisions, /health).
  • Documentación: plan, historial con git log, estrategia con parámetros leídos de la configuración real, estructura con el árbol real de src/, índice de backtests y tablero de mejoras (idea / probada / desplegada / descartada) sobre el journal.
  • Nuevos docs/STRATEGY.md y docs/ARCHITECTURE.md. Un test verifica que STRATEGY.md mencione todos los parámetros de estrategia y riesgo de config.py.
  • Se pospone la Fase 2 (scheduler + Telegram); el trabajo parcial queda en la rama feat/phase-2-scheduler.

Una entrada por mejora. Cada cambio de estrategia o de reglas de riesgo debe venir con su backtest en docs/backtests/ y con STRATEGY.md actualizado.

2026-09-10 — Plan revisado con documentación viva y universo S&P 500

  • La Fase 3 (web) incorpora una sección de documentación: plan, historial de cambios, estrategia, estructura, índice de backtests y mejoras propuestas.
  • Nueva Fase 4 para ampliar el universo al S&P 500 (lista de constituyentes, datos por lotes, selector de candidatos, backtest de cartera, sesgo de supervivencia).
  • Hardening pasa a Fase 5 y la decisión de dinero real a Fase 6.
  • Canal de notificaciones confirmado: Telegram.

2026-09-10 — Fase 1: datos históricos y backtesting

  • Descarga de barras diarias con caché CSV en data/cache/.
  • Backtester propio barra a barra que reutiliza SmaCrossStrategy y position_size(). Ejecución en la apertura siguiente con slippage 0.05 % y bracket intradía.
  • Métricas (retorno, CAGR, drawdown, Sharpe, win rate, expectancy, exposición, buy & hold), reporte markdown y gráfico PNG. Comando bot backtest con --split.
  • Cambio de estrategia: entrada permitida hasta 5 barras después del cruce (entry_window=5). Antes solo entraba en la barra exacta del cruce y perdía señales válidas cuando el precio superaba la SMA200 unos días después.

2026-09-10 — Fase 0: base del proyecto

  • Configuración con pydantic-settings; paper y DRY_RUN por defecto; el modo live exige I_UNDERSTAND_LIVE_TRADING=true.
  • Cliente Alpaca (AlpacaBroker) y bróker en memoria (FakeBroker) para tests.
  • Indicadores SMA/EMA/ATR/RSI en pandas puro.
  • Estrategia sma_cross con reason legible en cada señal.
  • Reglas de riesgo puras y RiskManager; executor idempotente por client_order_id.
  • Ciclo completo con bitácora en SQLite; CLI bot status|init-db|signal|cycle|kill|resume.
  • Corrección: el .gitignore excluía src/trading_bot/data; ahora solo ignora /data/ raíz.

2026-09-10 — Repositorio propio

  • El proyecto sale de la carpeta trading-bot/ de HabitOS y pasa a su propio repositorio con todo el historial de commits.
  • Se añade CI en GitHub Actions: ruff + pytest en cada push y PR.

trading-bot v0.1.0 · 2026-09-11 03:16 UTC