Bot de criptomonedas. Proyecto separado del bot de acciones: otro mercado,
otra estrategia. De aquel se reutilizan lecciones y patrones de despliegue,
nunca parámetros de estrategia.
Idioma del proyecto y de las respuestas: español.
Fase actual
Medir si hay algo que construir. No se escribe estrategia ni ejecución de
órdenes hasta que una medición diga en qué parte del mercado es económicamente
posible operar. Si no hay dónde, se dice y se para.
Los tres estados, que no se mezclan nunca
Probado con simulaciones
Integrado
Verificado en el entorno real
Estar pendiente en el tercero no devuelve el trabajo al primero. Una limitación
pendiente nunca se presenta como éxito.
Reglas de evidencia
No confundir el artefacto con lo servido. Un commit, un CI en verde o una
rama no son prueba de lo que un usuario ve o un bot ejecuta. Si afirmas algo
sobre lo servido, pídelo por HTTP. Si no puedes: «no comprobable desde este
entorno», nunca «no pasa».
Referencias móviles. Antes de afirmar algo de una rama: refresca la
referencia remota explícitamente y cita el SHA completo en la frase.
Ausencia de evidencia ≠ evidencia de ausencia. Si no alcanzas una fuente,
el resultado es «no comprobable», nunca «no existe».
No heredar suposiciones. Si una recomendación se apoya en un dato del
usuario (presupuesto, tarjeta, tiempo, equipo), pregúntalo antes. Y antes
de preguntar, mira si la respuesta ya está en el repositorio.
Contar la cosa, no el proxy. Coincidencias de grep no son páginas;
archivos no son despliegues; lo que hay en una caché no es lo que ofrece el
proveedor. Si informas un proxy, nómbralo como tal.
Criterios por mecanismo, no por palabras. Un test que busca cadenas falla
en silencio cuando el texto cambia. Comprueba el componente y los valores
concretos. Una expresión regular que no casa no avisa.
Si algo no debe salir, no lo generes. Filtrar después es la segunda
barrera, nunca la primera. Y prueba sobre la salida real, no sobre un
fixture simplificado.
Evidencia generada
Los informes los genera el código. Si un informe sale con un defecto, se
corrige el generador y se regenera. Una evidencia generada no se edita a
mano: en cuanto alguien la retoca, deja de poder saberse qué salió del
generador y qué del editor.
Un informe cita el commit donde existe el código que lo produjo, no el
padre.
Todo informe declara lo que no dice: qué no incluye, qué no demuestra, con
qué datos se hizo y qué le falta.
Las hipótesis se preregistran antes de medirlas, con su métrica de decisión.
Nombre por tipo y fecha, en evidencia/, versionado.
Si un informe anterior está commiteado, bórralo antes de regenerarlo y exige
que exista después: si no, un fallo deja leer el informe viejo como si fuera
el resultado de la corrida nueva.
Lecciones de medición
Calibrar mirando el pasado no funcionó. Validación hacia adelante: elegir
viendo solo el tramo de entrenamiento, aplicar al siguiente, encadenar. En 5
ventanas de 5, elegir por Sharpe pasado escogió la peor variante razonable.
Referencia obligada: comparar contra fijar una variante desde el principio
y contra comprar y no tocar. Si elegir no gana a quedarse quieto, elegir
no aporta.
La ventana de validación se gasta. Cada vez que eliges algo mirando un
periodo, ese periodo deja de ser prueba independiente. Cuéntalas.
Un componente del universo puede dominar el resultado. Mide exclusión de
cada activo (leave-one-out) y sin los dos mejores.
Y marca aparte los activos con cero operaciones: en el bot de acciones,
BTC/USD estaba en el universo, hizo 0 de 144 operaciones y un leave-one-out
lo aprobaba como «el resultado no depende de él». No dependía porque no
existía para la estrategia.
Muestras pequeñas no sustentan decisiones. Menos de ~30 operaciones no
decide nada, y eso se dice en el informe.
Una barra suelta puede arruinar una medición. Para el tramo común del
universo: máximo de las primeras barras y mínimo de las últimas.
El calentamiento de los indicadores se paga. Cada tramo necesita historia
previa y luego recortarse. Si no la hay, se declara qué tramos quedaron
sesgados.
Bruto y neto no se mezclan en la misma tabla. En el bot de acciones, la
P&L por símbolo era bruta de comisión y el retorno neto: la estrategia tenía
expectancy +0.09 % por operación contra un coste de ida y vuelta de
0.50 %. Toda métrica debe decir si incluye comisión y deslizamiento.
Economía del mercado cripto
Estructura de coste, no estrategia. Se mide antes de diseñar reglas.
Comisión Alpaca cripto: ~0.15 % creador / 0.25 % tomador, por lado. Ida y
vuelta cruzando ≈ 0.5 %. En acciones era 0 %. Es el término dominante de
cualquier sistema rápido.
El movimiento crece, el coste no. El desplazamiento típico sobre H barras
crece como √H en un paseo aleatorio sin estructura. Por eso la razón
movimiento/coste mejora al alargar el marco temporal por aritmética. Esa
razón solo sirve para descartar: por debajo de 1 es imposible; por encima
no dice nada. Compárala siempre contra su nulo de √H.
Falta el spread y las barras no lo traen. Cualquier cifra sin spread es una
cota superior optimista. Sácalo de cotizaciones.
Pregunta cuántos pares hay, no lo supongas (asset_class=crypto,
status=active).
Los datos históricos de cripto no exigen credenciales; listar los activos
operables sí.
Seguridad y operación
Nunca claves, tokens ni contraseñas en el chat, en commits ni en archivos.
Solo como secretos del repositorio o en un .env ignorado por git.
La clave de trading nunca llega al navegador ni a un servicio de páginas.
Modo simulado por defecto. Operar con dinero real exige una variable
explícita de confirmación, y es decisión del usuario, nunca de Claude.
Bitácora de decisiones persistente desde el primer día: cada decisión con
su motivo, aunque sea «no hubo señal».
Interruptor de parada que sobreviva a reinicios, y estado persistente que
no se sobrescriba a sí mismo.
Antes de vender tras cancelar protecciones, reconciliar cantidades reales.
Cripto es 24/7: no hay calendario de mercado, pero tampoco hay cierre que
te salve de una posición abierta.
Despliegue — decidido, no reabrir sin datos nuevos
Bot en Python en GitHub Actions · panel generado servido por Cloudflare Pages
· mando por Telegram. Es la arquitectura del bot de acciones, trasplantada.
No propongas un Worker de Cloudflare. Se discutió a fondo el 2026-09-19 y
se descartó. Los motivos, por orden de peso:
El panel se genera, no se sirve dinámicamente. Un comando Python produce
HTML estático desde el mismo SQLite, en el proceso que ya posee el estado.
Al servirlo no hay nada que ejecutar, así que un Worker no aporta nada.
El estado es un fichero SQLite y un Worker no tiene disco. Python Workers
corre sobre Pyodide, cuyo sistema de archivos es en memoria: la base no
sobrevive a la invocación. Habría que replicar el estado en D1/KV/R2, y esa
copia se puede desincronizar. Una segunda fuente de verdad que puede mentir
es justo lo contrario de lo que persigue este proyecto.
Lo interactivo ya tiene canal: Telegram./status, /kill, /resume,
/bitacora son comandos, no páginas, y los ejecuta el propio bot con su
estado real. Para 24/7 es mejor que una web: empuja al móvil, no hay que ir
a mirarla.
El proyecto de Workers del bot de acciones se probó y se retiró: ponía un
check rojo en cada PR (era Workers Builds, la integración con Git).
Dos argumentos que se usaron a favor del Worker y son FALSOS. No los repitas:
~~«Workers no ejecuta Python»~~ — sí lo ejecuta, y FastAPI está soportado
(asgi.entrypoint). La premisa correcta es la 2, no esta.
~~«24/7 no cabe en los 2 000 min/mes de Actions»~~ — se calculó sobre un ciclo
cada 5 min. La medición de viabilidad dice que el único marco que cubre el
coste es el diario, o sea ~30 ejecuciones al mes. Cabe de sobra.
Lo que sigue abierto, y solo eso: con ciclo diario, un /kill tarda hasta
24 h en ejecutarse, y cripto no tiene cierre que acote el daño. Salidas, por
orden: (a) aceptarlo mientras no haya dinero real; (b) un job aparte en Actions
que solo lea Telegram, sin dependencias, cada hora (~720 ejecuciones/mes, cabe);
(c) un Worker que solo enclave la bandera KILL. Se decide cuando exista una
posición que matar, no antes.
GitHub Actions: también lo pesado y ocasional — mediciones, backtests,
informes. Minutos de CPU, y sus registros quedan guardados.
Entorno
El entorno de desarrollo no alcanza Alpaca (el proxy responde 403 a
CONNECT). Las mediciones con datos reales corren en GitHub Actions.
GitHub Actions puede no poder abrir pull requests («GitHub Actions is not
permitted to create or approve pull requests»). Compruébalo pronto: en el
proyecto anterior llevaba meses fallando en silencio tras un || echo.
En pasos con tuberías, usa pipefail. Sin él el código de salida es el del
último comando y un fallo queda en verde.
Las pruebas pueden reescribir archivos generados: revísalo antes de commitear.
Proceso
Cada cambio con sus pruebas, y las pruebas reproducen el defecto; no se
ajustan las expectativas al código nuevo.
Acotar una prueba para que pase es lo que no se debe hacer cuando esconde
un defecto. Si una aserción era demasiado amplia y su intención era otra, se
puede acotar, pero el defecto que destapó se corrige en el código y se dice
explícitamente que son dos cosas distintas.
Verificación por mutación obligatoria (python3 -m pruebas.mutaciones):
cada mecanismo, apagado, debe romper exactamente las pruebas declaradas.
Una prueba que pasa con el mecanismo apagado no comprueba nada.
El arnés corre con el bytecode desactivado: el .pyc guarda el mtime en
segundos enteros y mutar-ejecutar-restaurar dentro del mismo segundo hace que
la corrida siguiente reutilice el bytecode mutado.
Cada PR pasa una revisión adversarial antes de fusionar, con los hallazgos
aplicados y resumidos.
Trato
Discutir, no dar la razón. Si una idea del usuario tiene un fallo, se dice con el
fallo delante. Si insiste dos veces, se dice una tercera y se hace: la decisión
es suya, el diagnóstico es de Claude. Y si Claude se equivoca, se corrige
explícitamente.
Generado desde el commit 8bc83abe2572ab2ef84a13c7405f5c05e2411d20