coderkrow
[pt]
~$./lang --switchMudar idioma
~$cycle --themeclaro → oscuro → sistema
[log] // ~/posts/trading-tui-monitor-mercados-python.md

trading-tui: construyendo un monitor de mercados con Python

Hay proyectos que empiezan con una arquitectura perfectamente diseñada.

Y después está trading-tui. La idea inicial era simple:

Quiero ver mercados, precios y alertas directamente desde mi terminal.

Nada de abrir cinco pestañas. Nada de dashboards gigantes. Nada de construir una aplicación web para terminar mirando una tabla.

Una TUI. Y ahí empezó el problema.

¿Qué es trading-tui?

trading-tui es un proyecto open source para monitorizar mercados desde terminal. Está construido con Python + FastAPI + Textual y actualmente permite consultar datos de mercado, trabajar con watchlists, utilizar screeners, crear alertas de precio y persistir configuración y alertas localmente. La idea termina creciendo mucho más allá de un simple monitor.

plaintext
trading-tui

├── Market data
├── Watchlists
├── Screeners
├── Price alerts
├── Notifications
├── Technical indicators
├── Charts
└── ...

El objetivo no es construir "otro trading terminal". Es aprender construyéndolo.

¿Por qué Python?

Quería usar el proyecto como excusa para profundizar en Python moderno. Hacía mucho tiempo que no desarrollaba algo más allá de scripts de automatización para tareas repetitivas en mi día de trabajo. No quería hacer el típico hello_world.py.

La idea es construir algo donde aparecen problemas reales:

  • Código async
  • APIs externas
  • Validación
  • Persistencia
  • WebSockets
  • Testing
  • Arquitectura
  • Docker
  • REST
  • Eventos
  • Patrones de diseño;
  • Interfaces de usuario
  • Manejo de errores;
  • Configuración.

Cuando un proyecto tiene suficientes piezas, las decisiones de arquitectura dejan de ser teoría. Empiezan a doler. Eso es lo interesante.

De una API a una TUI

trading-tui tiene un backend sobre FastAPI y una interfaz de terminal construida con Textual. El backend expone endpoints para consultar candles, quotes y screeners. La TUI consume esa API y se mantiene separada de la lógica de negocio. La separación es deliberada:

plaintext
TUI


REST API


Services

 ├── Market data
 ├── Alerts
 ├── Notifications
 └── Persistence

La TUI no debería saber cómo se evalúa una alerta. Solo necesita saber:

"Krowdy, dime qué alertas tengo."

Y dejar que otro componente se preocupe por el resto.

Y entonces aparecieron los patrones de diseño

Una de las partes más interesantes del proyecto ha sido descubrir que los patrones de diseño tienen mucho más sentido cuando aparecen para solucionar problemas reales.

Distintas condiciones de alerta:

plaintext
Price
├── Above
├── Below
└── Crossing

En lugar de llenar el código de if y elif, cada condición puede encapsular su propia estrategia de evaluación. Ahí aparece Strategy Pattern.

Distintos proveedores de datos:

plaintext
MarketData
├── Yahoo
└── Binance

Cada proveedor tiene sus diferencias respecto a configuraciones y endpoints, pero el resto de la aplicación no debería preocuparse por ellas. Ahí aparece Adapter Pattern.

Cuando llega un nuevo precio:

plaintext
Market price update


AlertService

        ├── evaluate conditions
        └── emit notification

Flujo inspirado en Observer.

Además, las alertas usan un Repository para separar dominio y persistencia, una Factory para construir condiciones y Dependency Injection para conectar servicios dentro de FastAPI.

Ninguno apareció porque "tocaba usar un patrón". Aparecieron porque había un problema.

La alerta fue cuando el proyecto empezó a ponerse interesante

Una alerta parece sencilla:

plaintext
ETHUSDT > 3,794.94

Pero rápidamente aparecen preguntas. ¿Qué significa "crossing"?

No es:

plaintext
price == 3794.94

Es una transición.

plaintext
previous < target

current >= target

Por eso necesitamos definir el comportamiento del trigger:

- ONCE: dispara una vez y queda marcada como TRIGGERED.

- EVERY_TIME: puede volver a dispararse cada vez que la condición se cumpla de nuevo.

Parece un detalle pequeño, pero cambia cómo manejamos el estado de cada alerta.

¿Y qué pasa cuando expira?

plaintext
ACTIVE

   ├── TRIGGERED
   ├── EXPIRED
   └── DISABLED

¿Y si queremos dos condiciones?

plaintext
ETHUSDT > 3,500
AND
ETHUSDT < 4,000

¿O?

plaintext
BTCUSD > 100,000
OR
ETHUSD > 5,000

Lo que parecía ser "una alerta" terminó siendo un pequeño sistema de reglas. Ahí está buena parte del aprendizaje.

El proyecto también necesita fallar

Una de mis reglas para este proyecto: no intentar diseñar todo perfectamente antes de escribir código.

plaintext
Idea

Código

Funciona

Problema

"¿Por qué hice esto?"

Refactor

Mejor diseño

Nuevo problema

Primero aparece el problema. Después la solución. Después, probablemente, otro problema. Entonces, refactor.

Ese ciclo también es parte del proyecto. Y probablemente será parte de esta serie.

¿Qué viene?

trading-tui todavía está lejos de estar terminado. Algunas piezas en el roadmap:

- WebSocket para market data en tiempo real

- Notificaciones reales: email, webhooks, Discord, Telegram

- Portfolio

- Charts

- Indicadores técnicos

- Evaluación automática de alertas

- Mejor observabilidad

- CI/CD

- Tooling de Python

- Más adapters

El repo ya tiene Docker, docker-compose, scripts CLI, SQLite, tests para backend y TUI, y una arquitectura preparada para seguir creciendo.

Y eso abre otra pregunta: ¿hasta dónde podemos llevar una aplicación de este tipo sin convertirla en un monstruo?

Vamos a descubrirlo.

Esto no es un tutorial

trading-tui será una especie de laboratorio público.

Vamos a construir. Vamos a romper cosas. Vamos a entender por qué se rompieron.

Y vamos a aprender Python, arquitectura, infraestructura y software engineering en el proceso.

Ver el proyecto en GitHub