# DIRECTIVA: Arquitectura Híbrida Express.js + FastAPI **ID**: DOQ-001 **Tipo**: Arquitectura **Alcance**: Trading Platform (trading-platform) **Versión**: 2.0 **Fecha**: 2025-12-07 **Actualizado desde**: trading (NestJS -> Express.js) ## Propósito Definir la arquitectura híbrida que combina Express.js (TypeScript) para la API principal y FastAPI (Python) para los servicios de Machine Learning. ## Arquitectura General ``` ┌─────────────────────────────────────────────────────────────────┐ │ FRONTEND │ │ React + TypeScript │ │ (Puerto 5173) │ └─────────────────────────────────────────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────────────────────┐ │ API GATEWAY │ │ Express.js (Puerto 3000) │ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ │ │ Auth │ │ Users │ │ Courses │ │ Payments │ │ │ └──────────┘ └──────────┘ └──────────┘ └──────────┘ │ │ ┌──────────┐ ┌──────────┐ ┌──────────────────────┐ │ │ │ Trading │ │ Admin │ │ ML Proxy (Gateway) │ │ │ └──────────┘ └──────────┘ └──────────────────────┘ │ └─────────────────────────────────────────────────────────────────┘ │ │ │ │ HTTP/WebSocket ▼ ▼ ┌─────────────────────┐ ┌─────────────────────────────────────┐ │ PostgreSQL │ │ ML ENGINE │ │ (Puerto 5432) │ │ FastAPI (Puerto 8000) │ │ │ │ ┌──────────┐ ┌──────────┐ │ │ - public │ │ │ Predict │ │ Signals │ │ │ - education │ │ └──────────┘ └──────────┘ │ │ - trading │ │ ┌──────────┐ ┌──────────┐ │ │ - investment │ │ │ Models │ │Backtest │ │ │ - financial │ │ └──────────┘ └──────────┘ │ │ - ml │ │ │ │ │ - audit │ │ ▼ │ └─────────────────────┘ │ ┌──────────────┐ │ │ │ MySQL │ │ │ │ (Puerto 3306)│ │ │ │ Trading Data │ │ │ └──────────────┘ │ └─────────────────────────────────────┘ ``` ## Responsabilidades por Servicio ### Express.js Backend (API Principal) **Responsable de:** - Autenticación y autorización (JWT + OAuth + 2FA) - Gestión de usuarios y perfiles - Sistema de educación (cursos, lecciones, progreso) - Pagos e integración con Stripe - Panel de administración - Proxy/Gateway hacia ML Engine - CRUD de entidades de negocio - Validación de datos de entrada (Zod) - Logging y auditoría (Winston) **NO responsable de:** - Ejecución de modelos ML - Procesamiento de datos de trading - Cálculo de indicadores técnicos - Generación de predicciones ### FastAPI ML Engine **Responsable de:** - Carga y ejecución de modelos ML (XGBoost, GRU, Transformer) - Predicción de precios (multi-horizonte) - Generación de señales de trading - Cálculo de indicadores técnicos - WebSocket streaming de predicciones - Backtesting de estrategias - Acceso a datos históricos (MySQL) **NO responsable de:** - Autenticación de usuarios - Gestión de permisos - Lógica de negocio de la aplicación - Persistencia de datos de usuario ## Comunicación entre Servicios ### HTTP (Request/Response) ```typescript // Express.js -> FastAPI // Endpoint: GET /api/ml/predict/:symbol // routes/ml.routes.ts router.get('/predict/:symbol', authenticate, async (req, res, next) => { try { const { symbol } = req.params; const prediction = await mlGatewayService.predict(symbol); res.json(prediction); } catch (error) { next(error); } }); // services/ml-gateway.service.ts import axios from 'axios'; class MLGatewayService { private mlServiceUrl = process.env.ML_SERVICE_URL || 'http://localhost:8000'; async predict(symbol: string): Promise { const response = await axios.get( `${this.mlServiceUrl}/api/predict/${symbol}`, { timeout: 30000 } ); return response.data; } } ``` ### WebSocket (Streaming) ```typescript // Frontend conecta directamente a FastAPI para streaming // ws://localhost:8000/ws/{symbol} // O mediante proxy en Express.js con socket.io: import { Server } from 'socket.io'; const io = new Server(server, { cors: { origin: 'http://localhost:5173' } }); io.on('connection', (socket) => { socket.on('subscribe', (symbol: string) => { // Proxy a FastAPI WebSocket }); }); ``` ## Reglas de Diseño ### 1. Separación de Concerns - Express.js maneja TODO lo relacionado con usuarios y negocio - FastAPI maneja EXCLUSIVAMENTE ML y datos de trading - Frontend NUNCA accede directamente a MySQL ### 2. Autenticación - JWT generado por Express.js (Passport.js) - FastAPI valida tokens mediante endpoint interno de Express.js - O FastAPI confía en requests desde Express.js (red interna) ### 3. Base de Datos - PostgreSQL: Fuente de verdad para entidades de negocio (7 schemas) - MySQL: Solo datos históricos de trading (OHLCV, indicadores) - NO replicar datos entre bases de datos ### 4. Contratos de API - Definir tipos compartidos en `shared/types/` - Pydantic schemas en FastAPI deben coincidir con tipos TypeScript - Documentar con OpenAPI/Swagger en ambos servicios ### 5. Manejo de Errores ```typescript // Express.js captura errores de ML Engine // middleware/error-handler.ts import { Request, Response, NextFunction } from 'express'; export const errorHandler = ( error: Error, req: Request, res: Response, next: NextFunction ) => { if (error.name === 'MLServiceUnavailableError') { return res.status(503).json({ error: 'ML service unavailable', message: 'Please try again later' }); } // Default error handling res.status(500).json({ error: 'Internal server error', message: error.message }); }; ``` ## Estructura de Directorios ### Express.js Backend ``` apps/backend/src/ ├── modules/ │ ├── auth/ │ │ ├── auth.routes.ts │ │ ├── auth.controller.ts │ │ ├── services/ │ │ │ ├── oauth.service.ts │ │ │ ├── email.service.ts │ │ │ ├── phone.service.ts │ │ │ ├── token.service.ts │ │ │ └── twofa.service.ts │ │ └── validators/ │ ├── users/ │ ├── education/ │ ├── trading/ │ │ ├── trading.routes.ts │ │ ├── trading.controller.ts │ │ └── services/ │ │ └── ml-gateway.service.ts # Comunicación con FastAPI │ ├── investment/ │ ├── payments/ │ └── admin/ ├── middleware/ │ ├── authenticate.ts │ ├── error-handler.ts │ └── rate-limiter.ts ├── config/ │ └── index.ts └── index.ts ``` ### FastAPI ML Engine ``` apps/ml-engine/src/ ├── api/ │ ├── main.py # FastAPI app │ ├── routes/ │ │ ├── predict.py │ │ ├── signals.py │ │ ├── indicators.py │ │ └── backtest.py │ └── schemas/ # Pydantic models ├── models/ │ ├── base/ │ ├── ensemble/ │ └── predictors/ │ ├── range_predictor.py │ ├── tpsl_classifier.py │ └── signal_generator.py ├── data/ │ ├── pipeline.py │ ├── database.py │ ├── features.py │ └── indicators.py └── config/ ├── trading.yaml └── models.yaml ``` ## Endpoints ML Engine (FastAPI) ```yaml # Predicciones GET /api/predict/{symbol} ?horizon=all|scalping|intraday|swing|position # Señales GET /api/signals/{symbol} ?timeframe=5m|15m|1h # Indicadores GET /api/indicators/{symbol} ?indicators=rsi,macd,atr # Datos históricos GET /api/history/{symbol} ?limit=500&timeframe=5m # Backtesting POST /api/backtest Body: { strategy, symbol, start_date, end_date } # Health GET /health GET /api/stats # WebSocket WS /ws/{symbol} ``` ## Configuración de Puertos | Servicio | Puerto | Protocolo | |----------|--------|-----------| | Frontend | 5173 | HTTP | | Express.js API | 3000 | HTTP | | FastAPI ML | 8000 | HTTP | | FastAPI WS | 8000 | WebSocket | | PostgreSQL | 5432 | TCP | | MySQL | 3306 | TCP | | Redis | 6379 | TCP | ## Variables de Entorno ### Express.js (.env) ```env # Server PORT=3000 NODE_ENV=development # Database DATABASE_URL=postgresql://user:pass@localhost:5432/trading # JWT JWT_SECRET=your-secret-key JWT_EXPIRES_IN=15m JWT_REFRESH_SECRET=your-refresh-secret JWT_REFRESH_EXPIRES_IN=7d # ML Services ML_SERVICE_URL=http://localhost:8000 ML_SERVICE_TIMEOUT=30000 # OAuth GOOGLE_CLIENT_ID= GOOGLE_CLIENT_SECRET= FACEBOOK_APP_ID= FACEBOOK_APP_SECRET= GITHUB_CLIENT_ID= GITHUB_CLIENT_SECRET= # Twilio (Phone Auth) TWILIO_ACCOUNT_SID= TWILIO_AUTH_TOKEN= TWILIO_PHONE_NUMBER= # Stripe STRIPE_SECRET_KEY= STRIPE_WEBHOOK_SECRET= # Redis REDIS_URL=redis://localhost:6379 ``` ### FastAPI (.env) ```env # API Configuration API_HOST=0.0.0.0 API_PORT=8000 # MySQL Trading Data MYSQL_HOST=localhost MYSQL_PORT=3306 MYSQL_DATABASE=trading_trading MYSQL_USER=trading_user MYSQL_PASSWORD=secure_password # Models MODEL_PATH=./models MODEL_VERSION=1.0.0 # GPU CUDA_VISIBLE_DEVICES=0 USE_GPU=true # Internal Auth (opcional) EXPRESS_INTERNAL_URL=http://localhost:3000 INTERNAL_API_KEY=shared_secret_key # Logging LOG_LEVEL=INFO ``` ## Validaciones Obligatorias 1. [ ] Express.js puede alcanzar FastAPI en `/health` 2. [ ] Tokens JWT son validados correctamente 3. [ ] Timeouts configurados apropiadamente 4. [ ] Errores de ML Engine se manejan gracefully 5. [ ] WebSocket streaming funciona end-to-end 6. [ ] Tipos TypeScript coinciden con Pydantic schemas 7. [ ] Rate limiting configurado en ambos servicios 8. [ ] CORS configurado correctamente --- *Migrado desde trading y actualizado para Express.js*