StockBot
De una exploración en un chat a un bot de alertas de opciones corriendo solo y gratis — y a descubrir que armar el agente era la parte fácil: lo difícil es que acierte.
Ver producto →Resumen rápido
- Rol
- Builder solo
- Periodo
- 9 de septiembre → octubre de 2026
- Stack técnico
- Exploración en chat de Claude → implementación y despliegue en Claude Code, sobre Python, Alpaca, Telegram y GitHub Actions → evaluación en sombra de las recomendaciones
- Producto
- t.me/CelsoStockBot
El problema
IONQ es una acción que sigo normalmente. La idea de StockBot no fue armar un sistema de trading algorítmico ambicioso desde el día uno, sino algo mucho más chico: dejar de tener que mirar el chart todo el día para no perderme una entrada, y en vez de eso recibir un aviso por Telegram cuando las condiciones técnicas (RSI, MACD, EMA) apunten a una oportunidad de compra de opciones (calls o puts).
Elegí empezar con una sola acción — la que ya sigo — en vez de armar algo genérico para cualquier ticker desde el arranque. La idea era validar el concepto completo (señal → contrato sugerido → aviso → seguimiento de la posición) sobre un caso concreto antes de pensar en escalarlo a más símbolos.
La construcción
Exploración (9 de septiembre) — chat de Claude
Toda la arquitectura se pensó y se escribió en una conversación de chat con Claude (claude.ai), sin ejecutar nada todavía: las reglas de análisis técnico, la integración con Alpaca para datos y cadena de opciones, el formato de las alertas de Telegram, y el plan de despliegue en GitHub Actions. Salió el código completo de un saque, pero un chat no tiene forma de instalar dependencias, pegarle a una API real, ni decirte si algo realmente funciona — quedó como un diseño completo, sin validar.
Implementación y despliegue (10 de septiembre) — Claude Code
Acá es donde el proyecto pasó de “código que parece terminado” a “bot corriendo de verdad”. Se armó el repo, se probó todo con credenciales reales, se debuggearon los problemas que solo aparecen al ejecutar, y se puso en producción.
- Python + pandas — motor de indicadores técnicos (RSI, MACD, EMA, ATR) calculado a mano, sin
pandas_ta, porque esa librería todavía no soporta la versión de Python usada localmente. - Alpaca Markets API — datos de velas intradía y cadena de opciones, sobre el plan Basic gratuito (feed IEX para acciones, feed indicativo para opciones) con una cuenta paper usada solo para leer datos.
- Telegram Bot API — canal de alertas de entrada/salida, y luego también lectura de mensajes entrantes para poder saber si alguien más le escribe al bot.
- GitHub + GitHub Actions — repo, control de versiones, y el intento inicial de host gratuito para correr el bot cada 15 minutos vía cron.
- cron-job.org — disparador externo que llama a la API de GitHub para forzar la ejecución del workflow, agregado cuando el cron nativo de Actions no funcionó (ver Escalamiento).
Evaluación en sombra y primeras calibraciones (septiembre → octubre)
Con el bot corriendo, lo dejé recomendando sin poner plata real: las alertas se evaluaron “en sombra”, como si las hubiera seguido en una simulación. Lo primero que apareció fue que la regla casi no disparaba: un backtest de 10 días sobre los 4 símbolos mostró cero señales, porque exigía que el RSI extremo, el cruce de MACD y la posición del precio respecto a su EMA coincidieran en la misma vela de 15 minutos — condiciones que, en la práctica, ocurren en momentos distintos del mismo movimiento. Saqué el filtro de EMA y pasé el RSI extremo a una ventana de las últimas 6 velas, y ahí sí empezó a haber señales.
El problema es que “dispara más” no es lo mismo que “recomienda bien”. Al evaluar en sombra lo que realmente recomendaba, las recomendaciones resultaron bastante malas: recomendó comprar unas calls y justo el mercado cayó, y en la simulación se perdió bastante dinero. La calibración había sido a ojo, ajustando contra pocos días de datos y con la única vara de “que genere señales” — no de “que esas señales sirvan”.
Escalamiento
- De “cron nativo de GitHub Actions” a “disparador externo por HTTP”: el
schedulede Actions nunca disparó solo, ni una vez, en más de 2.5 horas — con la configuración 100% correcta (rama, permisos, sintaxis del cron, workflow activo). Se probaron las mitigaciones conocidas (desfasar los minutos del cron para evitar los picos de carga en :00/:15/:30/:45, y forzar el re-registro deshabilitando y rehabilitando el workflow) y ninguna lo arregló. La solución fue sacar a GitHub Actions del rol de “scheduler” y dejarlo solo como ejecutor: ahora un servicio externo gratuito (cron-job.org) llama cada 15 minutos al endpoint deworkflow_dispatchde la API de GitHub para disparar la corrida. - De “el agente funciona” a “el agente acierta”: el quiebre más importante no fue de infraestructura sino de calidad. El bot corría sin errores, mandaba alertas y respetaba los filtros, pero las recomendaciones eran malas y estaban mal calibradas. Ajustar umbrales mirando unos pocos días de datos no alcanza para saber si una regla es buena; hace falta construir evals para probarla en laboratorio (backtests sobre historia amplia, con métricas de resultado y no solo de cantidad de señales) y observabilidad en producción para medir la calidad de los outputs una vez desplegado (qué se recomendó, qué pasó después, cuánto se hubiera ganado o perdido).
Resultados
| Etapa | Periodo | Resultado | Costo |
|---|---|---|---|
| Exploración | 9-sep-2026 | Código y arquitectura completos, nunca ejecutados | $0 |
| Implementación y despliegue | 10-sep-2026 | Bot en producción, respondiendo con información real (señales de TA, estado del mercado) | $0 (plan gratuito de Alpaca + GitHub Actions + cron-job.org) |
| Evaluación en sombra | sep → oct-2026 | Las recomendaciones resultaron malas: recomendó comprar calls justo antes de una caída del mercado y la simulación perdió bastante dinero. Regla mal calibrada | $0 en infraestructura; la pérdida fue solo simulada, sin plata real |
No hay una cifra consolidada de la pérdida en la simulación, ni un registro sistemático de cada recomendación contra lo que pasó después — justamente lo que hoy falta construir. Hasta que existan evals y observabilidad, no hay forma de decir con datos cuán buena o mala es la regla más allá de estos casos puntuales.
Aprendizajes
- Montar el agente es lo más fácil; lo complejo es asegurar la calidad de la respuesta. En StockBot tener algo corriendo, conectado a datos reales y mandando alertas llevó un par de días. Saber si lo que recomienda es bueno todavía no lo tengo resuelto: las recomendaciones en sombra fueron malas y la regla estaba mal calibrada. Antes de confiar en un agente hacen falta evals para probarlo en laboratorio y observabilidad en producción para medir la calidad de sus outputs en el tiempo.
- Conviene probar e ir descubriendo los bloqueantes y sus soluciones a medida que se avanza, en vez de intentar preverlos todos de entrada. Ni el problema de las credenciales ni el del scheduler de GitHub Actions se podían haber anticipado en la fase de diseño — aparecieron recién al ejecutar, y se resolvieron sobre la marcha.
- Un chat de LLM sin ejecución real puede producir código que parece terminado pero nunca corrió. Toda la exploración en claude.ai generó un proyecto completo y coherente, pero la única forma de saber si de verdad funcionaba era correrlo — cosa que ese entorno no permite.
- Verificar credenciales con una llamada real a la API, no con la ausencia de errores. Un secret mal cargado puede devolver “sin excepción” y aun así estar apuntando a un token o chat equivocado — hay que confirmar con una respuesta concreta (
getMe,/v2/account) antes de asumir que algo quedó bien configurado. - No asumir que una pieza de infraestructura conocida (el cron de GitHub Actions) va a funcionar como está documentada. Cuando falló sin causa identificable, tener un plan B simple (un disparador HTTP externo) resolvió más rápido que seguir insistiendo con la pieza rota.