---
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
