Documentación técnica · Sistema de trading automatizado

Aurix Alpha V1

Informe completo de arquitectura y funciones — main.py · monitor.py · sentinel.py

main.py · Sync Engine monitor.py · Alert Engine sentinel.py · Execution Engine
Arquitectura general del sistema
main.py
Fuente de datos
Loop cada 2s
Escribe JSON
monitor.py
Motor de alertas
Loop cada 1s
Lee JSON · Notifica
sentinel.py
Motor de ejecución
Loop cada 2s
Ejecuta en Bybit
Los tres scripts son independientes y se comunican a través de operaciones_activas.json · MySQL también actúa como fuente de verdad compartida
2s
Ciclo principal
main.py
1s
Ciclo principal
monitor.py
2s
Ciclo principal
sentinel.py

main.py

Fuente de datos · Sincronización continua

Es el cerebro de sincronización del sistema. Se conecta a MySQL y a la API de Bybit para mantener actualizado el archivo operaciones_activas.json cada 2 segundos. Este JSON es la fuente de datos que consumen los otros dos scripts. También actualiza el precio de breakeven real de cada posición en la base de datos cada 5 minutos consultando a Bybit directamente.

update_data() cada 2s
Función principal del loop. Construye y escribe el JSON con todas las operaciones abiertas.
  • Consulta la tabla precios para obtener cotizaciones actuales, tasa de financiamiento y countdown del funding
  • Hace JOIN entre aurixalpha y token para obtener el logo de cada activo
  • Filtra únicamente registros con estado = 'Abierta' ordenados por ID descendente
  • Construye un objeto JSON por cada operación con todos sus campos: entrada, TPs, SL, precio actual, BE, modelo, temporalidad, etc.
  • Escribe el resultado en operaciones_activas.json sobreescribiendo la versión anterior
  • Imprime en consola el timestamp y la cantidad de activos procesados
actualizar_breakeven_logic() cada 5min
Sincroniza el precio de breakeven real de Bybit con la base de datos MySQL.
  • Obtiene la tabla de precios actuales desde MySQL como fallback para BEs vacíos
  • Consulta todos los registros con estado = 'Abierta' para obtener sus IDs y BEs registrados
  • Recorre todas las posiciones abiertas en Bybit con paginación (límite 100 por página)
  • Si breakEvenPrice está vacío o es cero, usa el precio actual del activo como BE
  • Compara el BE de Bybit con el registrado en la BD y solo actualiza si hay diferencia
  • Usa el ID del registro (no orden_serial) en el WHERE del UPDATE para mayor precisión
  • Genera una línea de log en registros/{id}.txt por cada actualización realizada
generar_log_registro()
Sistema de logs individuales por operación. Crea un archivo de texto por cada ID.
  • Crea la carpeta registros/ si no existe
  • Nombre del archivo: {id_registro}.txt (ej: 42.txt)
  • Cada línea incluye timestamp en formato YYYY-MM-DD HH:MM:SS y la etiqueta MAIN
  • Modo append — no sobreescribe el historial previo
enviar_telegram()
Envía alertas de error al hilo de errores del grupo de Telegram configurado.
  • Usa parse_mode: Markdown para formato de texto
  • Apunta específicamente al THREAD_ERRORES (hilo 4)
  • Se activa ante errores en update_data(), actualizar_breakeven_logic() y errores fatales
  • Fallo silencioso si Telegram no responde (no interrumpe el loop)
mostrar_banner()
Limpia la consola y muestra el banner ASCII de Aurix Alpha al iniciar el proceso.
  • Limpia pantalla con cls (Windows) o clear (Linux/Mac)
  • Banner en color cyan con información del proyecto, estado y destino del JSON
  • Se ejecuta una sola vez al arrancar el script
Flujo de arranque de main.py
01
Muestra banner ASCII en consola
02
Conecta a MySQL con los parámetros de DB_CONFIG
03
Ejecuta inmediatamente actualizar_breakeven_logic() sin esperar los 5 minutos
04
Registra el timestamp de la última ejecución de BE
05
Entra al loop infinito: ejecuta update_data() cada 2 segundos
06
Cada 300 segundos (5 min) lanza actualizar_breakeven_logic() en paralelo al loop
07
Ante KeyboardInterrupt cierra la conexión DB limpiamente y termina
08
Ante cualquier excepción fatal envía alerta a Telegram con el detalle del error
Campos que escribe en el JSON

Id · Activo · Direccion · Entrada · Precio_Actual · TP1 · TP2 · TP3 · SL · Fecha_inicio · Modelo · Temporalidad · Estado_Monitor · tasa_financiamiento · tiempo_tasa_financiamiento · precio_be · precio_be_colocado · precio_be_plus · orden_bybit_id · estado_orden_bybit · 12h · cambio_direccion


monitor.py

Motor de alertas · Solo opera sobre modelo BUZZ

Es el motor de decisiones del sistema. Lee el JSON cada 1 segundo, filtra únicamente las operaciones del modelo BUZZ y evalúa si el precio actual ha alcanzado algún nivel relevante (TP1, TP2, TP3, SL). Cuando detecta un evento, actualiza el estado_monitor en MySQL y envía una notificación a Telegram. No ejecuta órdenes en Bybit — eso le corresponde a Sentinel.

procesar_alertas() cada 1s
Núcleo lógico del monitor. Evalúa cada operación y dispara eventos según el precio actual.
  • Ignora operaciones que ya tienen estado final: tp1 completo, tp2 completo, tp3 completo, be completo, sl
  • Determina el SL vigente según el estado actual: en be usa precio_be, en tp1 usa precio de TP1, en otros usa SL original
  • Si precio toca el SL vigente → cierra con el estado final correspondiente y notifica
  • Si precio alcanza TP3 → marca como tp3 completo y notifica con ROI
  • Si precio alcanza TP2 con TP3 activo → mueve estado a tp1 para proteger en TP1
  • Si precio alcanza TP2 sin TP3 → marca como tp2 completo y notifica con ROI
  • Si precio alcanza TP1 desde estado abierta → mueve estado a be para que Sentinel coloque el SL
mostrar_tabla()
Dashboard visual en consola con todas las operaciones BUZZ activas en tiempo real.
  • Limpia la pantalla en cada ciclo para simular un dashboard live
  • Muestra: ID, activo, dirección, precio de entrada, precio actual con PnL, TP1/TP2/TP3, SL vigente, funding rate, countdown del funding, horas activa y estado
  • El PnL se calcula con apalancamiento x5: ((actual - entrada) / entrada) × 100 × 5
  • Colores: verde si va en ganancia, rojo si va en pérdida
  • El SL que muestra es el vigente según el estado (BE, TP1 o SL original)
  • Estados con iconos: ⏳ Abierta · 🛡️ BE · 🎯 TP1 · ✅ TP2 · 💎 TP3 · 🏁 Completo · 🛑 SL
actualizar_estado_monitor_db()
Actualiza el campo estado_monitor en la tabla aurixalpha de MySQL.
  • Abre una conexión nueva por cada llamada (no reutiliza conexión persistente)
  • Ejecuta UPDATE aurixalpha SET estado_monitor = %s WHERE id = %s
  • Registra la conexión en logs/db_conexiones.log
  • Retorna True si el update fue exitoso, False si hubo error
  • Ante error envía alerta detallada a Telegram por el hilo de errores
marcar_tp_ico_db()
Marca el campo tp_ico como 'Si' cuando se alcanza el TP1 por primera vez.
  • Solo actualiza si tp_ico aún no es 'Si' (condición en el WHERE)
  • Se llama únicamente al alcanzar TP1 desde estado abierta
  • Sirve para registrar que la operación tocó al menos su primer objetivo
registrar_actividad_archivo()
Añade una línea al archivo de registro del ID de la operación en la carpeta registros/.
  • Archivo: registros/{id_op}.txt (ruta un nivel arriba del directorio del script)
  • Formato: timestamp, MONITOR: mensaje_del_cambio
  • Modo append — preserva todo el historial de eventos de la operación
  • Errores de escritura van a logs/error_sistema_registros.log
enviar_telegram()
Envía mensajes de alerta o error al grupo de Telegram. Soporta múltiples hilos.
  • Usa parse_mode: HTML para formato (diferente a main.py que usa Markdown)
  • Por defecto envía al THREAD_SEÑALES; errores van al THREAD_ERRORES
  • Respuestas no-200 se registran en logs/error_telegram_api.log
  • Fallos de red se registran en logs/error_red.log
error_telegram()
Versión especial de enviar_telegram para errores técnicos. Incluye stack trace.
  • Captura el traceback completo con traceback.format_exc()
  • Escapa los caracteres HTML del traceback (< y >)
  • Incluye los últimos 400 caracteres del traceback en un bloque <pre>
  • Omite el detalle técnico si el error no tiene información (NoneType)
leer_json() hasta 3 reintentos
Lectura robusta del JSON con reintentos para evitar conflictos de escritura simultánea.
  • Hasta 3 intentos con 100ms de espera entre cada uno
  • Diseñado para tolerar que main.py esté escribiendo el archivo al mismo tiempo
  • Si los 3 intentos fallan retorna lista vacía (no lanza excepción)
pnl_calc()
Calcula el PnL estimado de una posición en porcentaje con apalancamiento x5.
  • LONG: ((actual - entrada) / entrada) × 100 × 5
  • SHORT: ((entrada - actual) / entrada) × 100 × 5
  • Retorna 0 si entrada es 0 para evitar división por cero
obtener_valor_cnt()
Convierte el timestamp del próximo funding a un string legible (ej: "2h 35m").
  • Acepta timestamps en segundos o milisegundos (detecta automáticamente)
  • Calcula la diferencia con el tiempo actual
  • Si el countdown ya pasó retorna "0m"
Tabla de decisiones — procesar_alertas()
Condición Estado previo Acción Nuevo estado
precio ≤ SL (LONG) o precio ≥ SL (SHORT) abierta Actualiza BD + notifica Telegram con ROI sl
precio ≤ precio_be (LONG) o ≥ (SHORT) be Actualiza BD + notifica Telegram con ROI be completo
precio ≤ TP1 (LONG) o ≥ (SHORT) como SL tp1 Actualiza BD + notifica Telegram con ROI tp1 completo
precio ≥ TP1 (LONG) o ≤ (SHORT) abierta Actualiza BD + marca tp_ico + notifica "SL a BE" be
precio ≥ TP2 (LONG), hay TP3 be / abierta Actualiza BD + notifica "SL protegido en TP1" tp1
precio ≥ TP2 (LONG), sin TP3 be / abierta Actualiza BD + notifica con ROI final tp2 completo
precio ≥ TP3 (LONG) o ≤ (SHORT) tp1 Actualiza BD + notifica con ROI final tp3 completo

sentinel.py

Motor de ejecución · Único script que opera en Bybit

Es el ejecutor de órdenes del sistema. Es el único de los tres scripts que envía comandos reales a Bybit (colocar SL, cerrar posiciones, ajustar TPs). Opera en un loop de 2 segundos y ejecuta hasta 4 módulos independientes, cada uno con un interruptor ON/OFF configurable. Toda acción queda registrada en logs locales y en el archivo de registro por ID.

Módulo Variable Estado Descripción
Sincronización de estados MODULO_SINC_ESTADOS ON Detecta cuando una orden Pendiente pasa a Abierta en Bybit
Auditoría de posiciones MODULO_AUDITORIA ON Compara posiciones del JSON contra las reales en Bybit cada 5 min
Cambio de dirección MODULO_CAMBIO_DIRECCION ON Cierra posiciones a mercado cuando cambio_direccion = 'Si'
Tiempo medio (12h) MODULO_12_HORAS ON Gestiona operaciones que superan 12 horas activas
Breakeven engine MODULO_BREAKEVEN ON Coloca y ajusta el SL en Bybit al precio de breakeven
ejecutar_ciclo() cada 2s
Loop principal. Lee el JSON y ejecuta los módulos activos para cada operación.
  • Lee el JSON con hasta 10 reintentos (espera 500ms entre cada uno) para máxima robustez
  • Llama a sincronizar_estados_db() antes de procesar operaciones individuales
  • Itera cada operación ejecutando: Cambio Dirección → 12 Horas → Breakeven (en ese orden)
  • Si hubo algún cambio en memoria, reescribe el JSON al final del ciclo
sincronizar_estados_db()
Detecta cuando una posición BUZZ Pendiente ya está activa en Bybit y actualiza la BD.
  • Solo actúa en operaciones con modelo BUZZ, Estado_Monitor = 'Abierta' y estado_orden_bybit = 'Pendiente'
  • Consulta a Bybit si hay posición abierta con size > 0 para ese símbolo
  • Si la hay: actualiza estado_orden_bybit = 'Abierta' en MySQL
  • Registra el cambio en el archivo de registro del ID
  • Notifica la entrada al grupo de Telegram
colocar_sl_be()
Coloca o ajusta el Stop Loss en Bybit al precio de breakeven calculado.
  • Calcula los decimales necesarios desde el precio de entrada para formatear correctamente
  • Consulta el SL actual en Bybit antes de enviar la orden
  • Si el SL en Bybit ya coincide con el deseado, no hace nada (evita órdenes innecesarias)
  • Ejecuta set_trading_stop con slTriggerBy: MarkPrice y tpslMode: Full
  • Distingue entre protección inicial y ajuste posterior para el mensaje de log
  • Maneja el error 34040 de Bybit ("not modified") como estado OK, no como error
  • Notifica por Telegram al hilo MONITOR con el precio aplicado
  • Registra el evento en el archivo de registro del ID
auditar_posiciones_bybit() cada 5min
Compara las posiciones abiertas en el JSON con las reales en Bybit. Detecta discrepancias.
  • Lee el JSON con hasta 10 reintentos antes de auditar
  • Extrae todos los símbolos con estado_orden_bybit = 'Abierta' del JSON
  • Recorre todas las posiciones reales de Bybit con paginación completa
  • Compara ambas listas y detecta símbolos en el JSON que ya no existen en Bybit
  • Si hay discrepancias, envía un informe al hilo MONITOR con la lista de símbolos afectados
  • Si todo está correcto, registra "Auditoría OK" en el log con la cantidad validada
MODULO_CAMBIO_DIRECCION
Cierra posiciones a mercado cuando la señal cambio_direccion = 'Si' está activa.
  • Lee el campo cambio_direccion del JSON para cada operación
  • Consulta Bybit para obtener el side actual (Buy/Sell) y el size de la posición
  • Ejecuta una orden Market opuesta con reduceOnly: True para cerrar
  • Si el cierre es exitoso: notifica a Telegram, actualiza BD a cambio_direccion = 'Completa' y continúa al siguiente ciclo
  • Registra el evento en el archivo de registro del ID
MODULO_12_HORAS
Gestiona posiciones que llevan más de 12 horas activas. Evalúa dos escenarios posibles.
  • Solo actúa si 12h != 'Activo', estado_orden_bybit = 'Abierta' y no hay estado "completo"
  • Calcula la diferencia entre ahora y fecha_inicio con zona horaria Bogotá
  • Escenario A — precio ya superó TP1: cierra la posición a mercado inmediatamente, actualiza estado a tp1 completo y notifica "Cierre a mercado (Precio > TP1)"
  • Escenario B — precio aún no llegó a TP1: ajusta el Take Profit de Bybit al valor de TP1 para que cierre automáticamente ahí, notifica "Tiempo medio activado"
  • En ambos casos: actualiza 12h = 'Activo' en BD y registra el evento
MODULO_BREAKEVEN (lógica en ejecutar_ciclo)
Detecta si el precio de BE cambió y lo aplica en Bybit como nuevo Stop Loss.
  • Solo actúa en operaciones BUZZ con Estado_Monitor en 'be' o 'tp1' y estado_orden_bybit = 'Abierta'
  • Compara precio_be (calculado por main.py desde Bybit) con precio_be_colocado (el último que Sentinel colocó)
  • Si son iguales: no hace nada
  • Si son diferentes: llama a colocar_sl_be() y si tiene éxito actualiza en BD: protegida = 'Si', Estado_Monitor = 'be', precio_be_colocado = nuevo_valor
  • Determina si es ajuste (precio_be_colocado ya tenía valor) o protección inicial
registrar_log()
Sistema de logging central. Imprime en consola y escribe en be.log.
  • Tipos: INFO · OK · ERROR · WARN · CRIT · DB · AUDIT
  • Cada tipo tiene su propio icono (ℹ️ ✅ ❌ ⚠️ 🔥 🗄️ 🔍)
  • Los tipos ERROR y CRIT también envían alerta a Telegram automáticamente
  • Archivo de log: logs/be.log con timestamps completos
registrar_cambio_id()
Escribe eventos de Sentinel en el archivo de registro individual de cada operación.
  • Archivo: registros/{id_op}.txt (un nivel arriba del directorio del script)
  • Formato: timestamp, Auditor: descripción_del_cambio
  • Errores de escritura se registran en el log principal, no interrumpen el ciclo
limpiar_numero()
Limpia y convierte cualquier valor recibido de la API o del JSON a float de forma segura.
  • Elimina caracteres no numéricos excepto punto y signo menos
  • Maneja None, strings vacíos y valores malformados
  • Retorna None si el valor no es convertible (no lanza excepción)
notificar_telegram_be()
Notificación específica de protección o ajuste de breakeven al hilo MONITOR.
  • Encabezado diferente según sea protección inicial o ajuste posterior
  • Incluye activo, precio colocado e ID de la operación
  • Errores HTTP se registran en el log con el detalle de la respuesta
notificar_entrada_telegram()
Notificación al abrir una posición nueva (cuando pasa de Pendiente a Abierta).
  • Mensaje: "POSICIÓN ABIERTA" con nombre del activo e ID
  • Se envía al hilo MONITOR del grupo de Telegram
  • Solo se dispara una vez por operación gracias a la condición en sincronizar_estados_db
handler_salir()
Manejador de señal SIGINT para cierre limpio con Ctrl+C.
  • Registrado con signal.signal(signal.SIGINT, handler_salir)
  • Registra el mensaje "Cerrando Sentinel de forma segura" en el log
  • Termina el proceso con sys.exit(0)
Flujo completo de ejecutar_ciclo()
01
Verifica que operaciones_activas.json exista
02
Lee el JSON con hasta 10 reintentos (500ms entre cada uno). Si todos fallan, sale sin ejecutar
03
Llama a sincronizar_estados_db() — actualiza órdenes de Pendiente a Abierta
04
Para cada operación en el JSON ejecuta en orden: Cambio Dirección12 HorasBreakeven
05
Si un módulo completa una acción importante, activa la variable hubo_cambio = True
06
Si hubo_cambio es True, reescribe el JSON con los datos actualizados en memoria
Flujo de arranque de sentinel.py
01
Limpia la consola y muestra el banner "SENTINEL ENGINE v11.0"
02
Inicializa la sesión de Bybit con API key/secret desde .env
03
Registra "Sistema Sentinel iniciado correctamente" en el log
04
Registra el timestamp inicial de auditoría
05
Entra al loop infinito: cada iteración comprueba si han pasado 5 min desde la última auditoría
06
Si han pasado 5 min: ejecuta auditar_posiciones_bybit() y actualiza el timestamp
07
Llama a ejecutar_ciclo() y muestra el timestamp con "Sentinel latiendo... OK" en consola
08
Errores inesperados en el loop se registran como CRIT y el loop continúa sin interrumpirse

registros/{id}.txt
Historial completo de eventos por operación. Escrito por los 3 scripts con su etiqueta.
  • MAIN — cambios de precio_be desde main.py
  • MONITOR — cambios de estado desde monitor.py
  • Auditor — acciones de Bybit desde sentinel.py
  • Todos en modo append — el historial nunca se borra
logs/ (sentinel.py)
Logs técnicos de sentinel con detalle de cada operación ejecutada.
  • be.log — todas las acciones del engine con tipo y timestamp
  • db_conexiones.log — cada conexión a MySQL
logs/ (monitor.py)
Logs de errores específicos del monitor.
  • error_telegram_api.log — respuestas HTTP no-200 de Telegram
  • error_red.log — fallos de conexión de red
  • error_sistema_registros.log — errores al escribir archivos de registro
  • db_conexiones.log — conexiones a MySQL