YAML Metadata Warning:empty or missing yaml metadata in repo card

Check out the documentation for more information.

PolySignal

Dashboard web de inteligencia de mercados de prediccion en tiempo real.

Que es

PolySignal analiza mercados de Polymarket cruzando noticias de Finnhub con modelos de IA (ModernFinBERT + Qwen3-8B) para generar senales de trading (alcista, bajista, neutral). Incluye simulador de posiciones con capital virtual, lista de seguimiento y alertas por Telegram.

No ejecuta ordenes reales. Es una herramienta de analisis e inteligencia.

Idioma: Espanol. Moneda base: Euro (€).

Stack

  • Backend: Node.js 26 + Express.js 5 + Socket.io + node-cron
  • ORM: Prisma 6 + SQLite
  • Frontend: Vanilla JS + Vite 7 + Leaflet.js + Chart.js + Socket.io client
  • IA: HuggingFace Spaces (ModernFinBERT + Qwen3-8B) + OpenRouter fallback
  • Datos: Polymarket Gamma API + Finnhub REST
  • Deploy: HuggingFace Spaces (Docker, puerto 7860)

Estado del proyecto

El backend es totalmente funcional:

  • API REST completa con autenticacion JWT.
  • Pipeline de IA con cadena de fallback (Spaces HF β†’ API HF β†’ OpenRouter β†’ rule-based).
  • Scheduler de tareas periodicas (sync mercados, generacion de senales, P&L, alertas).
  • WebSocket en tiempo real para precios y senales.
  • Base de datos SQLite con Prisma ORM

El frontend consume datos reales del backend y tiene fallback a datos mock cuando el backend no responde (modo demo sin configuracion).

Mejoras de utilidad

Para que la app sea util mas alla de la demo visual, se han incorporado los siguientes ajustes β€” todos orientados a que las senales tengan edge real y no sean ruido bonito:

1. Fetch diversificado por tag (anti-monotonia)

El endpoint /markets de Polymarket ignora tag_id y siempre devuelve la home feed (politica US + World Cup). El cliente usa ahora el endpoint /events que SI respeta tag_id, con un catalogo curado de ~25 tags de alto valor (crypto-prices, fed, stock-market, tech, openai, middle-east, oil-industry, europe, taiwan-election, etc.) y aplana los mercados por tag.

Resultado: ~1000 mercados activos diarios distribuidos en 6 categorias (cripto, economia, geopolitica, ciencia, politica, entretenimiento) en lugar de los ~100 dominados por una unica categoria.

2. Whitelist de mercados analizables

polymarket.client.js β†’ isAnalyzable() flaggea como no analizables los mercados donde la IA no tiene edge plausible:

  • Predicciones de palabras ("Will Trump say nuclear?")
  • Views de YouTubers, recuentos de tweets
  • "Before GTA VI"-style memes
  • Deportes y entretenimiento

signals.service.js salta la generacion para estos mercados y el frontend pinta el badge "FUERA DE ALCANCE" en lugar de fabricar confianza falsa. Asi, cada senal visible es defendible.

3. Ground truth de cripto via CoinGecko

utils/coingecko.client.js resuelve spot prices (BTC, ETH, SOL, DOGE, ADA, XRP) y los inyecta en el prompt de la IA para mercados de precio objetivo:

GROUND TRUTH: BTC spot $103,400. Target $150,000 (+45.1% required).
Use this to judge whether the implied probability is plausible given typical volatility.

Cache TTL 60s β€” respeta el rate limit gratuito de CoinGecko.

4. Edge gap explicito (impliedProb vs fairProb)

Cada AISignal persiste ahora impliedProb, fairProb y edgePoints. El pipeline mapea (signal, confidence) β†’ fairProb:

Signal Formula
bullish + conf 0.8 fairProb = 0.5 + 0.8 Γ— 0.5 = 0.90
bearish + conf 0.8 fairProb = 0.5 βˆ’ 0.8 Γ— 0.5 = 0.10
neutral fairProb = 0.5

La tarjeta del mercado muestra: Mercado 65% Β· IA 78% Β· Edge +13pp β€” claim cuantitativo en lugar de prosa vaga.

5. Spread-aware sizing (Kelly con costes)

Polymarket expone spread, bestBid, bestAsk por mercado. positions/kelly.js β†’ suggestSize() resta el spread del edge bruto antes de calcular el tamano de posicion:

edgeNeto = |edgePoints/100| - spread
fraction = Quarter-Kelly(price, impliedProb + edgeNeto)
amount   = bankroll * min(0.25, fraction)

Mercados con spread > 5Β’ se marcan como ilΓ­quidos y los botones de compra se desactivan. Endpoint publico: GET /api/v1/positions/suggestion/:marketId.

6. Distribucion geografica del mapa

map.js usa jitter determinista (hash del marketId β†’ desplazamiento en bounding-box del pais) para que multiples mercados del mismo pais no se apilen sobre la capital. Mercados sin pais (cripto, indices, AI) se reparten entre 40 hubs financieros globales (NYC, Sao Paulo, Mumbai, Lagos, Moscu, Yakarta, Sydney, etc.) en vez de caer todos sobre [20,0].

Estructura

polysignal/
β”œβ”€β”€ backend/                      # API REST + Servicios + Scheduler
β”‚   β”œβ”€β”€ package.json
β”‚   β”œβ”€β”€ prisma/
β”‚   β”‚   β”œβ”€β”€ schema.prisma         # Schema SQLite (User, Market, AISignal, Position, Watchlist, Alert)
β”‚   β”‚   β”œβ”€β”€ migrations/           # Migraciones de Prisma
β”‚   β”‚   └── seed.js               # Usuarios demo (admin + user)
β”‚   └── src/
β”‚       β”œβ”€β”€ index.js              # Entry point: HTTP server + Socket.io + scheduler
β”‚       β”œβ”€β”€ app.js                # Express: middlewares + rutas + manejo de errores
β”‚       β”œβ”€β”€ config.js             # Variables de entorno validadas con Zod
β”‚       β”œβ”€β”€ scheduler.js          # Jobs periodicos (cron): sync, senales IA, PnL, alertas
β”‚       β”œβ”€β”€ auth/                 # Autenticacion JWT + bcrypt
β”‚       β”‚   β”œβ”€β”€ auth.controller.js
β”‚       β”‚   β”œβ”€β”€ auth.service.js
β”‚       β”‚   β”œβ”€β”€ auth.routes.js
β”‚       β”‚   β”œβ”€β”€ auth.validators.js
β”‚       β”‚   └── jwt.js
β”‚       β”œβ”€β”€ markets/              # Mercados de Polymarket
β”‚       β”‚   β”œβ”€β”€ markets.controller.js
β”‚       β”‚   β”œβ”€β”€ markets.service.js
β”‚       β”‚   β”œβ”€β”€ markets.routes.js
β”‚       β”‚   β”œβ”€β”€ markets.validators.js
β”‚       β”‚   β”œβ”€β”€ markets.repository.js
β”‚       β”‚   └── polymarket.client.js
β”‚       β”œβ”€β”€ signals/              # Pipeline de IA (ModernFinBERT + Qwen3-8B)
β”‚       β”‚   β”œβ”€β”€ signals.controller.js
β”‚       β”‚   β”œβ”€β”€ signals.service.js
β”‚       β”‚   β”œβ”€β”€ signals.routes.js
β”‚       β”‚   β”œβ”€β”€ signals.repository.js
β”‚       β”‚   β”œβ”€β”€ aiPipeline.js     # Pipeline IA con fallback chain
β”‚       β”‚   └── finnhub.client.js # Noticias financieras
β”‚       β”œβ”€β”€ positions/            # Simulador de posiciones virtuales
β”‚       β”‚   β”œβ”€β”€ positions.controller.js
β”‚       β”‚   β”œβ”€β”€ positions.service.js
β”‚       β”‚   β”œβ”€β”€ positions.routes.js
β”‚       β”‚   β”œβ”€β”€ positions.validators.js
β”‚       β”‚   β”œβ”€β”€ positions.repository.js
β”‚       β”‚   └── kelly.js          # Criterio de Kelly (sizing)
β”‚       β”œβ”€β”€ watchlist/            # Lista de seguimiento
β”‚       β”‚   β”œβ”€β”€ watchlist.controller.js
β”‚       β”‚   β”œβ”€β”€ watchlist.service.js
β”‚       β”‚   β”œβ”€β”€ watchlist.routes.js
β”‚       β”‚   β”œβ”€β”€ watchlist.validators.js
β”‚       β”‚   └── watchlist.repository.js
β”‚       β”œβ”€β”€ alerts/               # Alertas por Telegram
β”‚       β”‚   β”œβ”€β”€ alerts.controller.js
β”‚       β”‚   β”œβ”€β”€ alerts.service.js
β”‚       β”‚   β”œβ”€β”€ alerts.routes.js
β”‚       β”‚   β”œβ”€β”€ alerts.repository.js
β”‚       β”‚   └── telegram.client.js
β”‚       β”œβ”€β”€ middlewares/          # Middlewares reutilizables
β”‚       β”‚   β”œβ”€β”€ validate.js       # Validacion Zod generica
β”‚       β”‚   β”œβ”€β”€ requireAuth.js    # Autenticacion JWT
β”‚       β”‚   β”œβ”€β”€ rateLimitLogin.js # Rate limit login
β”‚       β”‚   β”œβ”€β”€ errorHandler.js   # Manejo centralizado de errores
β”‚       β”‚   └── notFound.js       # 404
β”‚       β”œβ”€β”€ utils/                # Utilidades compartidas
β”‚       β”‚   β”œβ”€β”€ apiResponse.js    # Helpers de respuesta HTTP
β”‚       β”‚   β”œβ”€β”€ httpClient.js     # Cliente HTTP con retry + timeout
β”‚       β”‚   β”œβ”€β”€ logger.js         # Pino (logs estructurados)
β”‚       β”‚   └── prisma.js         # Singleton PrismaClient
β”‚       └── socket/
β”‚           └── broadcaster.js    # Emisor de eventos Socket.io
β”‚
β”œβ”€β”€ frontend/                     # SPA Vanilla JS con Vite
β”‚   β”œβ”€β”€ index.html                # Punto de entrada HTML
β”‚   β”œβ”€β”€ package.json
β”‚   β”œβ”€β”€ vite.config.js            # Proxy a backend + build config
β”‚   └── src/
β”‚       β”œβ”€β”€ main.js               # Entry point de Vite
β”‚       β”œβ”€β”€ app.js                # Logica principal SPA + Socket.io
β”‚       β”œβ”€β”€ api.js                # Cliente REST del backend
β”‚       β”œβ”€β”€ charts.js             # Chart.js (historial + sparklines)
β”‚       β”œβ”€β”€ map.js                # Leaflet (mapa mundial interactivo)
β”‚       β”œβ”€β”€ simulator.js          # Simulador de posiciones virtuales
β”‚       └── style.css             # Estilos dark terminal / fintech
β”‚
β”œβ”€β”€ spaces/                       # HuggingFace Spaces (ZeroGPU)
β”‚   β”œβ”€β”€ modernfinbert/            # Space de ModernFinBERT
β”‚   β”‚   β”œβ”€β”€ app.py
β”‚   β”‚   β”œβ”€β”€ requirements.txt
β”‚   β”‚   └── README.md
β”‚   └── qwen3-8b/                 # Space de Qwen3-8B
β”‚       β”œβ”€β”€ app.py
β”‚       β”œβ”€β”€ Dockerfile
β”‚       β”œβ”€β”€ requirements.txt
β”‚       └── README.md
β”‚
β”œβ”€β”€ package.json                  # Root con workspaces + scripts conjuntos
β”œβ”€β”€ docker-compose.yml            # Orquestacion local
β”œβ”€β”€ Dockerfile                    # Build para HuggingFace Spaces
β”œβ”€β”€ .env.example                  # Variables de entorno de ejemplo
β”œβ”€β”€ SECURITY_HEALTHCHECK.md       # Auditoria de seguridad y arquitectura
└── README.md

Requisitos

  • Node.js >= 26.0.0
  • npm >= 10 (workspaces)

Instalacion rapida

# 1. Instalar dependencias (root + todos los workspaces)
npm install

# 2. Configurar variables de entorno
cp .env.example .env
# Editar .env con tus claves (HF_TOKEN, HF_SPACE_*, OPENROUTER_API_KEY, etc.)

# 3. Generar base de datos y cliente Prisma
npm run db:migrate
npm run db:generate

# 4. Iniciar en desarrollo
npm run dev:all      # Backend + Frontend Vite simultaneamente

Desarrollo solo frontend

Si solo quieres visualizar el dashboard (funciona con datos mock):

cd frontend
npm install
npm run dev
# Abrir http://localhost:5173

El frontend consume datos mock localmente cuando el backend no responde, por lo que el dashboard es totalmente funcional para la demo sin configuracion adicional.

Arquitectura del Backend

El backend sigue una arquitectura Layered (Controller β†’ Service β†’ Repository):

Capa Responsabilidad Ejemplo
Controller Recibir HTTP request, delegar a Service, responder markets.controller.js
Service Logica de negocio, validaciones, coordinacion markets.service.js
Repository Acceso a datos via Prisma ORM markets.repository.js
Client Integracion con APIs externas polymarket.client.js, finnhub.client.js
Middleware Cross-cutting concerns (auth, validacion, rate limiting) requireAuth.js, validate.js

Pipeline de IA

Whitelist analyzable (skip predicciones-de-palabras, sports, memes)
    ↓
Noticias (Finnhub) β†’ relevantes por mercado
    ↓
Filtrado (ModernFinBERT Space / API directa)
    ↓ (descarta neutrales, score < 0.65)
Ground truth crypto (CoinGecko spot β†’ solo si aplica)
    ↓
Generacion de senal (Qwen3-8B Space / API directa)
    ↓
Fallback: OpenRouter (deepseek-chat)
    ↓
Fallback: Rule-based (precio del mercado)
    ↓
Calculo edge: impliedProb vs fairProb β†’ edgePoints
    ↓
Persistencia (SQLite) + Emision Socket.io

Scheduler (node-cron)

Job Frecuencia Descripcion
syncMarkets Cada 30s Sincroniza precios + spread desde Polymarket Gamma (fetch diversificado por tag)
generateSignals Cada 5 min Genera senales IA para 40 mercados diversificados por categoria (solo analyzable=true)
updatePositionsPnL Cada 30s Recalcula P&L de posiciones abiertas
processAlerts Cada 60s Revisa watchlist y envia alertas Telegram

Arquitectura del Frontend

El frontend es una SPA construida con Vite 7 como bundler y dev server.

Caracteristicas visuales

  • Estetica dark terminal / fintech: paleta #0a0c10, tipografias Syne + DM Mono.
  • Layout ajustable: sidebar colapsable, paneles del dashboard colapsables individualmente.
  • Mapa global interactivo: Leaflet con burbujas por pais (tamano = volumen, color = senal IA), jitter determinista para evitar apilamientos y 40 hubs financieros para mercados sin pais.
  • Panel de senales IA: mercados con badges alcista/bajista/neutral, fila de edge cuantitativa (Mercado X% Β· IA Y% Β· Edge Β±N pp) y badge "FUERA DE ALCANCE" para mercados no analizables.
  • Detalle de mercado: sparklines, historial 7d, analisis IA, simulador de posiciones con sugerencia de tamano Quarter-Kelly cost-aware (servida por GET /positions/suggestion/:marketId) y deshabilitacion automatica para mercados con spread > 5Β’.
  • Vistas adicionales: Posiciones abiertas, Lista de seguimiento, Historial de alertas.

Flujo de desarrollo

Servicio Comando URL local
Backend (Express + Socket.io) npm run dev http://localhost:7860
Frontend (Vite + HMR) npm run dev:frontend http://localhost:5173
Ambos a la vez npm run dev:all β€”

Vite esta configurado con un proxy que redirige automaticamente las peticiones a /api y /socket.io hacia el backend en el puerto 7860, eliminando problemas de CORS durante el desarrollo local.

Scripts disponibles

# Levantar solo el backend
npm run dev

# Levantar solo el frontend (Vite con hot reload)
npm run dev:frontend

# Levantar backend y frontend simultaneamente
npm run dev:all

# Build de produccion del frontend (genera frontend/dist/)
npm run build:frontend

# Preview del build de produccion
npm run preview:frontend

# Base de datos
npm run db:migrate      # Crear/actualizar migraciones
npm run db:generate     # Generar cliente Prisma
npm run db:studio       # Explorar BD con Prisma Studio

Deploy en HuggingFace Spaces

  1. Crear Space tipo "Docker"
  2. Subir codigo (git push)
  3. Configurar Secrets en la interfaz de HF con las variables de .env
  4. El contenedor expone el puerto 7860 automaticamente

Docker local (opcional)

# Build y run con docker-compose
docker-compose up --build

# O solo docker build
docker build -t polysignal .
docker run -p 7860:7860 --env-file .env polysignal

Variables de entorno

# HuggingFace
HF_TOKEN=                          # API key de HuggingFace (Inference API)
HF_SPACE_MODERNFINBERT_URL=        # URL del Space (ej: usuario/modernfinbert)
HF_SPACE_QWEN_URL=                 # URL del Space (ej: usuario/qwen3-8b)

# Fallbacks y datos
OPENROUTER_API_KEY=                # Fallback LLM si HF esta saturado
FINNHUB_API_KEY=                   # Noticias financieras (finnhub.io)

# Alertas
TELEGRAM_BOT_TOKEN=                # Bot de alertas (@BotFather)

# Base de datos y auth
DATABASE_URL=file:./backend/prisma/polysignal.db
JWT_SECRET=minimo-32-caracteres    # Secreto para firmar JWT

# Servidor
PORT=7860                          # Puerto requerido por HuggingFace Spaces
NODE_ENV=production                # development | production

Equipo

Hackathon CIFO Barcelona La Violeta β€” 13-18 mayo 2026

Licencia

MIT

Downloads last month

-

Downloads are not tracked for this model. How to track
Inference Providers NEW
This model isn't deployed by any Inference Provider. πŸ™‹ Ask for provider support