--- id: "RF-TRD-004" title: "Paper Trading" type: "Requirement" status: "Done" priority: "Alta" module: "trading" epic: "OQI-003" version: "1.0" created_date: "2025-12-05" updated_date: "2026-01-04" --- # RF-TRD-004: Paper Trading **Versión:** 1.0.0 **Fecha:** 2025-12-05 **Épica:** OQI-003 - Trading y Charts **Prioridad:** P0 **Story Points:** 13 --- ## Descripción El sistema debe proporcionar un entorno de paper trading (simulación) que permita a los usuarios practicar estrategias de trading sin arriesgar dinero real, utilizando un balance virtual. --- ## Requisitos Funcionales ### RF-TRD-004.1: Balance Virtual El sistema debe: - Asignar $10,000 USD virtuales a cada usuario nuevo - Mostrar balance disponible en tiempo real - Mostrar equity (balance + PnL no realizado) - Calcular margen usado por posiciones abiertas - Permitir reset del balance a $10,000 (máximo 1 vez por semana) ### RF-TRD-004.2: Tipos de Órdenes El sistema debe soportar: | Tipo | Descripción | Ejecución | |------|-------------|-----------| | Market | Al precio actual | Inmediata | | Limit | A precio específico | Cuando se alcanza | | Stop-Limit | Stop + limit price | Cuando stop se activa | ### RF-TRD-004.3: Ejecución de Órdenes El sistema debe: - Ejecutar órdenes market inmediatamente al precio actual - Monitorear órdenes limit y ejecutar cuando precio alcanza - Validar balance suficiente antes de crear orden - Aplicar slippage simulado (0.1% para market orders) - No cobrar comisiones (simplificación MVP) ### RF-TRD-004.4: Gestión de Posiciones El sistema debe: - Permitir una posición por símbolo (long o short) - Calcular PnL no realizado en tiempo real - Permitir cerrar posición parcial o total - Soportar Take Profit automático - Soportar Stop Loss automático ### RF-TRD-004.5: Liquidación El sistema debe: - Liquidar posición si pérdida > 80% del margen - Notificar al usuario antes de liquidación - Registrar liquidación en historial --- ## Datos de Entrada ### Crear Orden ```typescript interface CreateOrderDto { symbol: string; // BTCUSDT side: 'buy' | 'sell'; type: 'market' | 'limit' | 'stop_limit'; quantity: number; // Cantidad del activo price?: number; // Solo para limit stopPrice?: number; // Solo para stop_limit takeProfit?: number; // Opcional stopLoss?: number; // Opcional } ``` --- ## Datos de Salida ### Orden Ejecutada ```typescript interface Order { id: string; userId: string; symbol: string; side: 'buy' | 'sell'; type: 'market' | 'limit' | 'stop_limit'; status: 'pending' | 'filled' | 'cancelled' | 'rejected'; quantity: number; price: number | null; filledQuantity: number; filledPrice: number | null; takeProfit: number | null; stopLoss: number | null; createdAt: string; filledAt: string | null; } ``` ### Posición ```typescript interface Position { id: string; symbol: string; side: 'long' | 'short'; quantity: number; entryPrice: number; currentPrice: number; unrealizedPnl: number; unrealizedPnlPercent: number; takeProfit: number | null; stopLoss: number | null; openedAt: string; } ``` ### Balance ```typescript interface PaperBalance { balance: number; // Disponible equity: number; // Balance + unrealized PnL marginUsed: number; // En posiciones marginAvailable: number; // Para nuevas posiciones unrealizedPnl: number; // Total de posiciones } ``` --- ## Reglas de Negocio 1. **Balance inicial:** $10,000 USD para todos los usuarios 2. **Posiciones:** Máximo 1 posición por símbolo 3. **Tamaño mínimo:** $10 USD equivalente 4. **Tamaño máximo:** 100% del balance disponible 5. **Apalancamiento:** 1x (sin apalancamiento en MVP) 6. **Slippage:** 0.1% en órdenes market 7. **Reset:** Máximo 1 vez cada 7 días --- ## Criterios de Aceptación ```gherkin Escenario: Usuario crea orden market de compra DADO que el usuario tiene balance de $10,000 Y el precio de BTCUSDT es $50,000 CUANDO crea una orden market BUY de 0.1 BTC ENTONCES la orden se ejecuta inmediatamente Y se crea una posición long de 0.1 BTC Y el balance se reduce en ~$5,005 (precio + slippage) Escenario: Usuario cierra posición con ganancia DADO que el usuario tiene posición long BTCUSDT Y el entry price fue $50,000 Y el precio actual es $52,000 CUANDO cierra la posición ENTONCES el PnL realizado es +$200 (4%) Y el balance aumenta correspondientemente Y se registra el trade en historial Escenario: Stop Loss se activa DADO que el usuario tiene posición long BTCUSDT Y el entry price fue $50,000 Y el Stop Loss está en $48,000 CUANDO el precio baja a $48,000 ENTONCES la posición se cierra automáticamente Y se registra pérdida de ~$200 (4%) Escenario: Usuario intenta orden sin balance DADO que el usuario tiene balance de $100 CUANDO intenta crear orden de $1,000 ENTONCES la orden es rechazada Y se muestra mensaje "Balance insuficiente" ``` --- ## Estados de Orden ``` ┌─────────────┐ │ PENDING │ └──────┬──────┘ │ ┌───────────┼───────────┐ │ │ │ ▼ ▼ ▼ ┌─────────┐ ┌─────────┐ ┌─────────┐ │ FILLED │ │CANCELLED│ │REJECTED │ └─────────┘ └─────────┘ └─────────┘ ``` --- ## Dependencias - RF-TRD-001: Charts (precio actual) - WebSocket para monitoreo de precios - Cron job para verificar órdenes limit --- ## Notas Técnicas - Ejecutar verificación de órdenes limit cada 1 segundo - Usar transacciones para operaciones de balance - Implementar locks para evitar race conditions - Guardar snapshots de precio para auditoría --- ## Métricas a Trackear - Órdenes creadas por día - Win rate por usuario - Volumen total operado - Tiempo promedio de posición