--- id: "STACK-TECNOLOGICO" title: "Stack Tecnologico - Trading Platform" type: "Documentation" project: "trading-platform" version: "1.0.0" updated_date: "2026-02-06" --- # Stack Tecnologico - Trading Platform **Version:** 1.0.0 **Fecha:** 2025-12-05 **ADR Relacionado:** [ADR-001](../97-adr/ADR-001-stack-tecnologico.md) --- ## Resumen del Stack | Capa | Tecnologia | Version | Justificacion | |------|------------|---------|---------------| | Frontend | React + TypeScript | 18.x + 5.x | Ecosistema maduro, tipado fuerte | | Build Tool | Vite | 6.x | HMR rapido, ESM nativo | | Styling | Tailwind CSS | 3.x | Utility-first, dark mode | | State | Zustand | 4.x | Simple, sin boilerplate | | Data Fetching | TanStack Query | 5.x | Cache, refetch, optimistic | | Charts | Lightweight Charts | 4.x | TradingView quality, ligero | | Backend API | Express.js + TypeScript | 5.0.x + 5.x | Probado, flexible | | Validation | Zod | 3.x | Schema validation | | Auth | JWT + Passport | 9.x + 0.7.x | Estandar industria | | ML Engine | Python + FastAPI | 3.11+ + 0.100+ | Async, tipado, OpenAPI | | ML Models | XGBoost | 2.x | Gradient boosting, rapido | | Database | PostgreSQL | 16+ | ACID, JSON, extensiones | | Cache | Redis | 7.x | In-memory, pub/sub | | Payments | Stripe | Latest | PCI compliant | | SMS/WhatsApp | Twilio | Latest | Reach global | --- ## Frontend ### Core ```json { "dependencies": { "react": "^18.2.0", "react-dom": "^18.2.0", "react-router-dom": "^6.20.0", "typescript": "^5.3.0" } } ``` ### State Management ```typescript // Zustand store example import { create } from 'zustand'; interface AuthState { user: User | null; isAuthenticated: boolean; login: (user: User) => void; logout: () => void; } export const useAuthStore = create((set) => ({ user: null, isAuthenticated: false, login: (user) => set({ user, isAuthenticated: true }), logout: () => set({ user: null, isAuthenticated: false }), })); ``` ### Data Fetching ```typescript // TanStack Query example import { useQuery, useMutation } from '@tanstack/react-query'; function useCourses() { return useQuery({ queryKey: ['courses'], queryFn: () => api.get('/courses'), staleTime: 5 * 60 * 1000, // 5 minutes }); } function useEnrollCourse() { return useMutation({ mutationFn: (courseId: string) => api.post(`/courses/${courseId}/enroll`), onSuccess: () => queryClient.invalidateQueries(['enrollments']), }); } ``` ### Charts ```typescript // Lightweight Charts example import { createChart } from 'lightweight-charts'; const chart = createChart(container, { width: 800, height: 400, layout: { background: { color: '#1a1a2e' }, textColor: '#d1d5db', }, grid: { vertLines: { color: '#2d2d44' }, horzLines: { color: '#2d2d44' }, }, }); const candlestickSeries = chart.addCandlestickSeries({ upColor: '#22c55e', downColor: '#ef4444', }); ``` ### Styling ```css /* Tailwind config */ module.exports = { darkMode: 'class', theme: { extend: { colors: { primary: { 50: '#eef2ff', 500: '#6366f1', 900: '#312e81', }, success: '#22c55e', danger: '#ef4444', }, }, }, }; ``` --- ## Backend API ### Core ```json { "dependencies": { "express": "^5.0.1", "typescript": "^5.3.0", "cors": "^2.8.5", "helmet": "^7.1.0", "compression": "^1.7.4" } } ``` ### Authentication ```json { "dependencies": { "jsonwebtoken": "^9.0.2", "bcryptjs": "^2.4.3", "passport": "^0.7.0", "passport-google-oauth20": "^2.0.0", "passport-facebook": "^3.0.0", "passport-twitter": "^1.0.4", "passport-apple": "^2.0.2", "passport-github2": "^0.1.12", "speakeasy": "^2.0.0", "qrcode": "^1.5.3" } } ``` ### Database ```json { "dependencies": { "pg": "^8.11.3", "redis": "^4.6.10" } } ``` ### External Services ```json { "dependencies": { "stripe": "^14.7.0", "twilio": "^4.19.3", "nodemailer": "^6.9.7", "axios": "^1.6.2" } } ``` ### Validation ```typescript // Zod schema example import { z } from 'zod'; export const registerSchema = z.object({ email: z.string().email(), password: z.string().min(8).regex(/[A-Z]/).regex(/[0-9]/), firstName: z.string().min(1).max(100), lastName: z.string().min(1).max(100), acceptTerms: z.literal(true), }); export type RegisterInput = z.infer; ``` --- ## ML Engine ### Core ```txt # requirements.txt fastapi>=0.100.0 uvicorn[standard]>=0.23.0 pydantic>=2.0.0 python-dotenv>=1.0.0 ``` ### ML Libraries ```txt # ML dependencies xgboost>=2.0.0 scikit-learn>=1.3.0 pandas>=2.0.0 numpy>=1.24.0 ta-lib # Technical analysis ``` ### Data Processing ```txt # Data dependencies pyarrow>=14.0.0 polars>=0.19.0 # Fast dataframes ``` ### API Example ```python # FastAPI endpoint from fastapi import FastAPI, HTTPException from pydantic import BaseModel import numpy as np app = FastAPI(title="Trading Platform ML Engine") class PredictionRequest(BaseModel): symbol: str timeframe: str features: list[float] class PredictionResponse(BaseModel): delta_high: float delta_low: float confidence: float signal: str @app.post("/predict", response_model=PredictionResponse) async def predict(request: PredictionRequest): # Load model and predict prediction = model.predict(np.array([request.features])) return PredictionResponse( delta_high=prediction[0][0], delta_low=prediction[0][1], confidence=0.85, signal="BUY" if prediction[0][0] > 0 else "SELL" ) ``` --- ## Database ### PostgreSQL Extensions ```sql -- Required extensions CREATE EXTENSION IF NOT EXISTS "uuid-ossp"; -- UUID generation CREATE EXTENSION IF NOT EXISTS "pgcrypto"; -- Encryption CREATE EXTENSION IF NOT EXISTS "pg_trgm"; -- Text search CREATE EXTENSION IF NOT EXISTS "btree_gin"; -- Index type ``` ### Schema Organization ``` PostgreSQL ├── public # Users, profiles, auth ├── education # Courses, lessons, quizzes ├── trading # Bots, signals, positions ├── investment # Products, accounts ├── financial # Subscriptions, wallets ├── ml # Models, predictions └── audit # Logs, events ``` ### Connection Pool ```typescript // Pool configuration const pool = new Pool({ host: config.database.host, port: config.database.port, database: config.database.name, user: config.database.user, password: config.database.password, max: 20, // Max connections idleTimeoutMillis: 30000, // Close idle after 30s connectionTimeoutMillis: 5000, }); ``` --- ## Redis ### Use Cases | Use Case | TTL | Pattern | |----------|-----|---------| | Session tokens | 7d | `session:{userId}:{sessionId}` | | Rate limiting | 15m | `ratelimit:{ip}:{endpoint}` | | ML predictions cache | 5m | `ml:prediction:{symbol}:{tf}` | | Real-time data | 1s | `realtime:{symbol}` | | User preferences | 1h | `user:{userId}:prefs` | ### Configuration ```typescript import { createClient } from 'redis'; const redis = createClient({ socket: { host: config.redis.host, port: config.redis.port, }, password: config.redis.password, }); // Example usage await redis.setEx(`session:${userId}`, 7 * 24 * 60 * 60, sessionData); ``` --- ## External Services ### Stripe ```typescript import Stripe from 'stripe'; const stripe = new Stripe(config.stripe.secretKey); // Create subscription const subscription = await stripe.subscriptions.create({ customer: customerId, items: [{ price: priceId }], payment_behavior: 'default_incomplete', expand: ['latest_invoice.payment_intent'], }); ``` ### Twilio ```typescript import twilio from 'twilio'; const client = twilio(accountSid, authToken); // Send WhatsApp OTP await client.messages.create({ body: `Tu codigo Trading Platform: ${otp}`, from: 'whatsapp:+14155238886', to: `whatsapp:${phoneNumber}`, }); ``` --- ## DevOps ### Docker ```dockerfile # Backend Dockerfile FROM node:20-alpine WORKDIR /app COPY package*.json ./ RUN npm ci --only=production COPY dist ./dist EXPOSE 3000 CMD ["node", "dist/index.js"] ``` ### Docker Compose ```yaml version: '3.8' services: backend: build: ./apps/backend ports: - "3000:3000" depends_on: - postgres - redis ml-engine: build: ./apps/ml-engine ports: - "8001:8001" postgres: image: postgres:16-alpine volumes: - postgres_data:/var/lib/postgresql/data redis: image: redis:7-alpine volumes: - redis_data:/data volumes: postgres_data: redis_data: ``` --- ## Testing | Layer | Framework | Coverage Target | |-------|-----------|-----------------| | Frontend | Vitest + Testing Library | 70% | | Backend | Jest + Supertest | 80% | | ML Engine | Pytest | 75% | | E2E | Playwright | Critical paths | ### Example Test ```typescript // Jest test example describe('AuthService', () => { describe('login', () => { it('should return tokens for valid credentials', async () => { const result = await authService.login({ email: 'test@example.com', password: 'ValidPass123!', }); expect(result.tokens.accessToken).toBeDefined(); expect(result.tokens.refreshToken).toBeDefined(); }); it('should throw for invalid password', async () => { await expect( authService.login({ email: 'test@example.com', password: 'wrong', }) ).rejects.toThrow('Invalid email or password'); }); }); }); ``` --- ## Version Matrix | Dependency | Min Version | Recommended | Max Version | |------------|-------------|-------------|-------------| | Node.js | 20.0.0 | 20.x LTS | 22.x | | Python | 3.11 | 3.11 | 3.12 | | PostgreSQL | 15 | 16 | 16 | | Redis | 6.x | 7.x | 7.x | | React | 18.0 | 18.2 | 18.x | | TypeScript | 5.0 | 5.3 | 5.x | --- ## Referencias - [ADR-001: Stack Tecnologico](../97-adr/ADR-001-stack-tecnologico.md) - [React Documentation](https://react.dev) - [Express.js](https://expressjs.com) - [FastAPI](https://fastapi.tiangolo.com) - [PostgreSQL](https://www.postgresql.org/docs/) - [Redis](https://redis.io/docs/)