| # CLAUDE.md |
|
|
| This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. |
|
|
| ## Project Overview |
|
|
| **PolySignal** β a real-time prediction market intelligence dashboard. It fetches market data from Polymarket, enriches it with financial news via Finnhub, runs AI sentiment analysis (ModernFinBERT + Qwen3-8B), and displays signals on an interactive world map. No real trading β pure analysis and virtual simulation. Built for CIFO Barcelona La Violeta Hackathon (May 2026). UI and docs are in **Spanish**, base currency is **Euro (β¬)**. |
|
|
| ## Common Commands |
|
|
| ```bash |
| # Development (backend + frontend simultaneously) |
| npm run dev:all |
| |
| # Backend only (with --watch) |
| npm run dev |
| |
| # Frontend only (Vite @ :5173) |
| npm run dev:frontend |
| |
| # Production build (frontend) |
| npm run build:frontend |
| |
| # Database |
| npm run db:migrate # Apply Prisma migrations |
| npm run db:generate # Regenerate Prisma client |
| npm run db:studio # Open Prisma Studio GUI |
| |
| # Docker |
| docker-compose up --build # Full stack on port 7860 |
| ``` |
|
|
| Node.js **β₯24.0.0** is required (enforced in package.json engines). |
|
|
| First-time setup: |
| ```bash |
| npm install |
| cp .env.example .env # then fill in API keys |
| npm run db:migrate && npm run db:generate |
| ``` |
|
|
| ## Architecture |
|
|
| Monorepo with two workspaces: `backend/` (Express 5 + Socket.io) and `frontend/` (Vanilla JS + Vite). |
|
|
| ### Backend (`backend/src/`) |
|
|
| Follows a strict **Controller β Service β Repository β Client** layered pattern. Each domain lives in its own directory: |
|
|
| | Directory | Responsibility | |
| |-----------|---------------| |
| | `markets/` | Polymarket Gamma API client + sync job | |
| | `signals/` | AI pipeline (aiPipeline.js) + signals service | |
| | `finnhub/` | Finnhub news client + service | |
| | `positions/` | Virtual position simulator + Kelly Criterion sizing | |
| | `watchlist/` | User-saved markets | |
| | `alerts/` | Telegram Bot notification delivery | |
| | `auth/` | JWT + bcryptjs login | |
| | `socket/` | Socket.io broadcaster | |
| | `middlewares/` | Auth, validation, error handling, rate limiting | |
| | `utils/` | Pino logger, HTTP client, Prisma singleton | |
|
|
| Entry points: `src/index.js` (HTTP server + Socket.io setup) β `src/app.js` (Express middleware + route mounting) β `src/scheduler.js` (cron jobs). |
|
|
| Environment/config validated at startup via **Zod** in `src/config.js` β the app crashes fast if required env vars are missing. |
|
|
| ### Scheduler Jobs |
|
|
| | Job | Frequency | What it does | |
| |-----|-----------|-------------| |
| | `syncMarkets` | 30s | Fetches top 100 active Polymarket markets, broadcasts price changes via Socket.io | |
| | `generateSignals` | 5m | Runs full AI pipeline on top 20 active markets | |
| | `updatePositionsPnL` | 30s | Recalculates P&L for open virtual positions | |
| | `processAlerts` | 1m | Checks watchlist thresholds, fires Telegram alerts | |
|
|
| ### AI Signal Pipeline (`signals/aiPipeline.js`) |
|
|
| Three-phase flow with automatic fallbacks: |
|
|
| 1. **News filtering** β Finnhub headlines β ModernFinBERT (HF Space) β keep only scores β₯ 0.65, drop neutral |
| 2. **Signal generation** β market data + filtered news β Qwen3-8B (HF Space) β `{ signal, confidence, summary, keyRisk }` |
| 3. **Fallback chain**: HF Space β HF direct inference API β OpenRouter (deepseek-chat) β rule-based (price-trend logic) |
|
|
| ### Frontend (`frontend/src/`) |
|
|
| Single-page app with no framework. Key modules: |
|
|
| | File | Role | |
| |------|------| |
| | `app.js` | SPA routing, DOM rendering, Socket.io listeners | |
| | `api.js` | REST client wrapper with JWT token management | |
| | `map.js` | Leaflet world map (bubble size = volume, color = signal) | |
| | `charts.js` | Chart.js sparklines + 7-day price history | |
| | `simulator.js` | Virtual buy/sell logic | |
| | `filters.js` | Market filtering by category, country, continent, trend | |
|
|
| Vite proxies `/api` and `/socket.io` to backend (`localhost:7860`) during development. |
|
|
| ### Database (SQLite via Prisma) |
|
|
| Schema at `backend/prisma/schema.prisma`. Key models: |
| - `Market` β Polymarket data (prices, volume, category, country code) |
| - `AISignal` β sentiment signals with confidence and risk summary |
| - `Position` β virtual trades with entry/exit prices and P&L |
| - `Watchlist` / `Alert` β user market tracking and Telegram history |
| - `User` β auth + optional Telegram chat ID |
|
|
| ### Real-time Communication |
|
|
| REST API at `/api/v1/*` + WebSocket events via Socket.io: |
| - `market_update` β price/volume changes |
| - `ai_signal` β new sentiment signals |
| - `price_alert` β watchlist threshold triggers |
|
|
| ## Deployment Target |
|
|
| The app is designed to run on **HuggingFace Spaces** (port 7860). The Dockerfile uses `node:22-slim`, installs backend deps, copies the frontend `dist/`, runs Prisma generate, and starts the server. The frontend is served as static files by Express in production. |
|
|
| ## Key Environment Variables |
|
|
| See `.env.example` for the full list. Critical ones: |
|
|
| ``` |
| HF_SPACE_MODERNFINBERT_URL # HuggingFace Space for FinBERT |
| HF_SPACE_QWEN_URL # HuggingFace Space for Qwen3-8B |
| HF_TOKEN # HF inference API key (fallback) |
| OPENROUTER_API_KEY # LLM fallback if HF is down |
| FINNHUB_API_KEY # News source |
| TELEGRAM_BOT_TOKEN # Alert delivery |
| JWT_SECRET # Must be β₯32 characters |
| PORT=7860 # Required by HF Spaces |
| DATABASE_URL=file:./backend/prisma/polysignal.db |
| ``` |
|
|