El mercado, a 0 fotogramas por segundo.
Kairos es un puesto de operación bursátil completo que corre entero en el navegador: acción del precio, libro de órdenes, cartera en papel y calendario macroeconómico sobre un mismo reloj.
Arquitecto y desarrollador único (front-end, motor de gráficos, dominio y despliegue)
21
tipologías de gráfico declaradas (6 renderizando)
32
indicadores en el catálogo del TA-Engine
22
marcos temporales, de 1 segundo a 1 año
caminata determinista · 66 velas · 1 rAF por panel · 0 renders de React por tick
Capacidades · lectura en vivo
Dos lados del mismo libro
El estado del arte se vende como gráfico con indicadores encima o como terminal cerrado y carísimo. La posición contraria es un puesto completo que corre entero en el navegador.
Corto · el problema
Las plataformas de trading al uso o son gráficos con indicadores encima, o son terminales profesionales cerrados y carísimos. Reproducir un puesto institucional en la web choca con tres muros: el navegador no está pensado para redibujar a 60 FPS mientras recibe cientos de mensajes por segundo, React se convierte en un cuello de botella si cada tick provoca un render, y el cómputo de indicadores sobre series largas bloquea el hilo de interfaz. A eso se suma un problema de honestidad: una plataforma que muestra un mercado simulado y encima cobra depósitos reales no es un bróker, es un mercado ficticio con dinero real dentro.
Largo · la solución
Un terminal construido en Clean Architecture donde la dependencia apunta siempre hacia dentro y el dominio no conoce ni React, ni el canvas, ni el transporte. El mercado se almacena en un búfer circular columnar sobre un único ArrayBuffer con seis columnas y un Int32Array de control apto para Atomics: se comparte con los Web Workers sin serializar nada. El motor de gráficos es un renderizador Canvas 2D por capas, agnóstico de React, con un requestAnimationFrame por panel y bandera de suciedad. La autenticación pasó al SDK de Firebase en el navegador, lo que permite publicar el sitio como export estático; lo que protege de verdad los datos son las reglas de Firestore evaluadas en el servidor contra el uid, no ninguna comprobación del cliente. Y el alcance financiero se corta donde debe: cartera en papel, cero depósitos, y una lista explícita de requisitos previos a cualquier módulo de fondos.
Siete niveles de este libro
Lo que sostiene el terminal, apilado como se apila la profundidad: arriba lo que se paga en rendimiento, abajo lo que se cobra en honestidad.
Cinco franjas, un solo reloj
El terminal ocupa el alto completo de la ventana sin scroll: barra superior, estado de cuenta, cuerpo, bitácora y barra de estado.

Kairos
Fase 1 · Data Nivel 1
Saldo
10.000,00
Equity
10.412,55
P&L flotante
+412,55
Margen usado
1.240,00
Margen libre
9.172,55
Nivel
839,7 %
Lista de seguimiento
Terminal · rejilla multiactivo
Cartera en papel: las órdenes se ejecutan contra el simulador local y no salen a ningún mercado.
Panel de ejecución (ticket de orden)
Entorno macroeconómico
Alertas ON⚠ Volatilidad extrema inminente
IPC subyacente (EE. UU.) · desviación esperada 24,0 %
Fed Watch · próxima decisión
Módulo macroeconómico

Acceso de operador
No se almacenan contraseñas: la identidad la verifica Google mediante Firebase Authentication.
Continuar con GoogleEntrar como invitadoLa sesión la gestiona Firebase y persiste en este navegador. Los datos quedan protegidos por reglas evaluadas en el servidor.
Acceso de operador
Las maquetas reproducen la interfaz real; los datos que muestran son de ejemplo.
Lo que corre y lo que está declarado
La especificación va por niveles y la landing no los confunde: un nivel operativo de extremo a extremo y dos con los contratos de datos cerrados y tipados.
Acción del precio y entorno
- ·OHLCV en búfer columnar
- ·22 marcos con frontera UTC
- ·Indicadores en TA-Engine
- ·Cartera en papel
- ·Calendario macro
Microestructura
- ·Entidad MarketDepth
- ·Libro por niveles
- ·Cinta de operaciones
- ·Puerto tipado declarado
- ·Sin adaptador activo
Flujo institucional y motor 3D
- ·Entidad QuantAnalytics
- ·WebGL reservado
- ·Mapa de calor térmico
- ·Puerto tipado declarado
- ·Sin adaptador activo
Catorce módulos enrutados
Con qué está construido
Aplicación
Next.js 16.3·React 19.2·TypeScript 5·App Router·output: 'export' (sitio estático)
Interfaz
Tailwind CSS 4·@tailwindcss/postcss·Tokens Material Design 3 (esquema oscuro)·Tipografía del sistema (sin recursos de terceros)
Motor de gráficos
Canvas 2D API·Renderizador propio por capas·Escalas y controlador de viewport propios·WebGL reservado para el motor 3D de Nivel 3
Cómputo y concurrencia
Web Workers·SharedArrayBuffer·Float64Array / Int32Array·Atomics·COOP + COEP acotados a /terminal
Datos de mercado
WebSocket (data-stream.binance.vision)·REST klines (data-api.binance.vision)·Simulador determinista mulberry32·Feed compuesto con reconexión de retroceso exponencial
Backend gestionado
Firebase 12·Firebase Authentication (Google + anónimo)·Cloud Firestore·Firebase Hosting
Calidad y herramientas
ESLint 9 + eslint-config-next·tsx·Verificador de analítica propio (52 comprobaciones)
La dependencia siempre hacia dentro
src/presentation
React · 8 contextos apilados
→
src/application
Servicios: agregador, cartera, analítica
→
src/core
Entidades, value-objects y puertos · sin framework
Clean Architecture estricta con la dependencia siempre hacia dentro: presentation → application → domain. El núcleo (src/core) es puro TypeScript sin framework: entidades (Candle, Instrument, TopOfBook, Order, Position, TradingAccount, MacroEvent, MarketDepth de Fase 2, QuantAnalytics de Fase 3), value-objects (Timeframe con alineación UTC real), puertos (MarketDataFeed, CandleRepository, IndicatorEngine, MacroCalendarRepository) y servicios de aplicación (agregador de velas, motor de cartera en papel, analítica de rendimiento, desviación de volatilidad). src/infrastructure implementa esos puertos: adaptadores de Binance, simulador, feed compuesto y factoría, capa anticorrupción snake_case → dominio en los mapeadores del protocolo WebSocket, y la integración con Firebase. src/charting es el motor de gráficos, agnóstico de React: interfaz ChartRenderer, escalas, viewport, registro de las 21 tipologías y un renderizador Canvas 2D con diez capas. src/presentation contiene React con ocho contextos apilados en el orden de las dependencias (transporte → instantánea de mercado → analítica → macro → cartera → preferencias → espacio de trabajo). src/workers es un directorio aislado con el deserializador de WebSocket y el TA-Engine, comunicados por contratos de mensajería tipados. No hay rutas de servidor ni Cloud Functions: el sitio se compila como export estático y la seguridad recae íntegramente en las reglas de Firestore, que niegan por defecto y sólo abren users/{uid} a su propietario. Unas 14.200 líneas de TypeScript y TSX.
Ocho incidencias y su cierre
Cada una se abrió contra un síntoma medible y se cerró contra una causa. Las que siguen abiertas están anotadas como tales.
1Síntoma
Un terminal que redibuja a cada tick y recalcula indicadores en el hilo principal se entrecorta en cuanto el mercado se acelera; con React en medio, cada impresión de la cinta provocaría un render del árbol completo.
Cierre
Se sacó el mercado de React por completo: cada tick escribe en un búfer circular columnar de Float64Array y sólo marca el lienzo como sucio, con un requestAnimationFrame por panel. El transporte agrupa mensajes y emite un postMessage por fotograma en vez de uno por tick, y las peticiones al TA-Engine se fusionan a ~8 Hz porque recalcular a los 20 Hz del feed sería tirar trabajo. Resultado medido: 1,25 ms por fotograma.
2Síntoma
El aislamiento de origen cruzado (COOP: same-origin) es requisito del navegador para exponer SharedArrayBuffer, pero impide que un documento hable con la ventana emergente que abre — y el acceso con Google de Firebase usa exactamente eso.
Cierre
El aislamiento se acotó a /terminal, dejando /acceso fuera. Además se eligió ventana emergente en lugar de redirección, porque signInWithRedirect deposita estado en el almacenamiento del authDomain, que es un tercero respecto al sitio, y falla de forma intermitente con el bloqueo de cookies de terceros. Como output: 'export' deja inactiva la función headers() de Next en producción, las cabeceras están duplicadas a propósito en firebase.json.
3Síntoma
El dominio principal de Binance devuelve HTTP 451 (ubicación restringida) desde buena parte de Latinoamérica, y como la petición sale del navegador de cada usuario, la restricción se aplicaría a cada uno por separado dejando el terminal sin precios.
Cierre
Se usa el espejo público de datos de mercado (data-api.binance.vision y data-stream.binance.vision), que sirve lo mismo sin esa puerta y devuelve access-control-allow-origin: *, así que además atraviesa el COEP de /terminal. Se abren tres streams por instrumento en una única conexión combinada: @trade para el OHLC, @bookTicker para el spread en tiempo real y @ticker por la apertura de 24 h.
4Síntoma
Binance no ofrece marcos de 5 s, 15 s, 30 s ni los multi-mes, y componerlos agrupando de N en N desde el índice 0 del array producía velas desfasadas — 13 s de desvío medidos en un marco de 15 s — que no casaban con las que forma el agregador en vivo, dejando una costura visible entre el histórico y el tiempo real.
Cierre
Se agrupa por frontera temporal alineada en lugar de por posición en el array. La corrección resuelve además los huecos de segundos sin negociación. Verificado en producción: el bid del panel coincide exactamente con el de la API, y la apertura de sesión también.
5Síntoma
Al pasar a export estático se cayó el modelo anterior de seguridad, que verificaba una cookie firmada con HMAC en un proxy antes de servir el terminal. El HTML y el JavaScript son ahora descargables por cualquiera y ninguna comprobación del navegador puede impedirlo.
Cierre
Se separó experiencia de protección: AuthGuard sólo evita mostrar un terminal sin sesión, y quien protege de verdad son las reglas de Firestore, que Google evalúa en el servidor contra el uid del token, con denegación por defecto y una única ruta abierta a su propietario. Para una aplicación cuyo mercado es un simulador en el propio navegador es el reparto correcto: lo valioso son los datos del operador, no el código de la página. Verificado en producción: una lectura sin credenciales devuelve 403.
6Síntoma
La reconciliación entre la cartera local y la de la nube sólo sincronizaba los cambios posteriores al inicio de sesión, de modo que una cartera ya existente en el navegador no llegaba nunca al servidor. Y arrastrar un Stop Loss sobre el gráfico disparaba una escritura por cada movimiento del ratón.
Cierre
Reconciliación en dos direcciones: al entrar, lo remoto manda si trae operaciones; si la nube está vacía y hay cartera local, se sube. Las escrituras se agrupan a 1,5 s. Nada que dependa de localStorage o del reloj se inicializa con useState — eso abortaría la hidratación del árbol entero —, sino con useSyncExternalStore y su getServerSnapshot.
7Síntoma
next build con Turbopack emite los Web Workers como TypeScript en crudo dentro de _next/static/media/, y su arranque generado usa importScripts(), así que el entrypoint falla antes de ejecutar una sola línea propia. El TA-Engine llevaba roto sin que nada lo delatara.
Cierre
La causa está diagnosticada y documentada como incumplimiento abierto, con las tres vías descartadas anotadas (ruta relativa en vez de alias, quitar type: 'module', desactivar el export estático). De ahí salió una regla dura: todo worker DEBE tener onerror, porque sin él fallan en silencio. El feed de Binance se dejó en el hilo principal tras medir que sus ~720 msg/s cuestan 0,007 ms por fotograma.
8Síntoma
ctx.font no resuelve custom properties de CSS: una cadena de fuente con var(--…) es inválida y el canvas revierte en silencio a 10px sans-serif, sin error, dejando toda la tipografía del gráfico rota.
Cierre
charting/theme.ts declara pilas de fuentes literales, espejadas explícitamente en globals.css junto al resto de la paleta, de modo que la interfaz en DOM y el dibujo en canvas nunca divergen de color ni de tipografía.
El presupuesto son 16,6 milisegundos
Sesenta fotogramas por segundo no es una promesa de marketing: es un techo de tiempo por fotograma que se mide o no se tiene.
1,25 ms
coste medido de un fotograma con tres indicadores, oscilador, marcadores macro y 140 velas
0
coste de transferencia entre el TA-Engine y el renderizador: leen la misma memoria
O(n)
SMA por suma deslizante; RSI con suavizado de Wilder
Tiempo por fotograma · 56 muestras
0 por encima del presupuesto
tres indicadores · panel de oscilador · marcadores macro · 140 velas
3
rutas: landing, acceso y terminal
21
tipologías de gráfico declaradas (6 renderizando)
32
indicadores en el catálogo del TA-Engine
22
marcos temporales, de 1 segundo a 1 año
8
instrumentos en catálogo (futuros, cripto, acciones, FX, índice)
10
capas independientes del renderizador Canvas 2D
2
Web Workers: deserializador y TA-Engine
52
comprobaciones del verificador de analítica
1,25 ms
coste medido de un fotograma (7,5 % del presupuesto)
~14.200
líneas de TypeScript y TSX
Identidad · monograma, lockup y tarjeta social




Lo que no está, se dice.Implementa una especificación técnica por niveles: el Nivel 1 (acción del precio y entorno) está operativo de extremo a extremo, mientras que los Niveles 2 (microestructura) y 3 (flujo institucional y motor 3D) tienen ya cerrados y tipados sus contratos de datos.
El reto real no era dibujar velas, sino sostener 60 FPS mientras la cinta imprime miles de operaciones por segundo: el mercado nunca pasa por React, escribe directamente en búferes columnares Float64Array y marca el lienzo como sucio.
Los pares de criptomoneda cotizan en vivo contra el espejo público de datos de Binance; futuros, acciones, divisa e índice los sirve un simulador determinista, y un feed compuesto enruta cada instrumento sin que la interfaz note la diferencia.
El proyecto documenta con el mismo rigor lo que NO implementa: la verificación en dos pasos, el módulo de fondos y 30 de los 32 indicadores del catálogo aparecen como estado real, no como interruptores decorativos.
Kairos · Trading Institucional
¿Quieres algo así para tu producto?
Un terminal de mercado a 60 fotogramas por segundo en el navegador, con el dominio fuera de React y la seguridad donde de verdad se evalúa. Si tu producto vive de datos que llegan más rápido de lo que se pueden pintar, ése es mi terreno.