trading-platform/docs/02-definicion-modulos/OQI-003-trading-charts/requerimientos/RF-TRD-006-gestion-posiciones.md
rckrdmrd a7cca885f0 feat: Major platform documentation and architecture updates
Changes include:
- Updated architecture documentation
- Enhanced module definitions (OQI-001 to OQI-008)
- ML integration documentation updates
- Trading strategies documentation
- Orchestration and inventory updates
- Docker configuration updates

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-07 05:33:35 -06:00

14 KiB
Raw Permalink Blame History

id title type status priority module epic version created_date updated_date
RF-TRD-006 Gestion de Posiciones Requirement Done Alta trading OQI-003 1.0 2025-12-05 2026-01-04

RF-TRD-006: Gestión de Posiciones

Versión: 1.0.0 Fecha: 2025-12-05 Épica: OQI-003 - Trading y Charts Prioridad: P0 Story Points: 8


Descripción

El sistema debe proporcionar una gestión completa de posiciones abiertas, permitiendo a los usuarios monitorear su exposición al mercado, PnL en tiempo real, y ejecutar acciones sobre sus posiciones de manera eficiente y segura.


Requisitos Funcionales

RF-TRD-006.1: Apertura de Posiciones

El sistema debe:

  • Crear posición automáticamente al ejecutar orden buy/sell
  • Soportar posiciones long (compra) y short (venta, futuro)
  • Permitir una posición por símbolo en paper trading MVP
  • Calcular precio promedio de entrada
  • Registrar timestamp de apertura
  • Aplicar stop loss y take profit si fueron configurados

RF-TRD-006.2: Información de Posición

El sistema debe mostrar para cada posición:

Campo Descripción Cálculo
Symbol Par de trading -
Side Long/Short -
Entry Price Precio promedio de entrada Weighted average
Current Price Precio actual del mercado Real-time
Quantity Cantidad del activo -
Position Value Valor actual de la posición quantity × currentPrice
Unrealized PnL Ganancia/pérdida no realizada (currentPrice - entryPrice) × quantity
Unrealized PnL % Porcentaje de ganancia/pérdida ((currentPrice - entryPrice) / entryPrice) × 100
Margin Used Margen ocupado positionValue / leverage
Liquidation Price Precio de liquidación Calculado según leverage
Duration Tiempo abierta now - openedAt

RF-TRD-006.3: Actualización en Tiempo Real

El sistema debe:

  • Actualizar precios actuales cada 1 segundo vía WebSocket
  • Recalcular PnL automáticamente con cada update
  • Mostrar animación visual en cambios de precio
  • Destacar posiciones en riesgo (pérdida > 50%)
  • Actualizar métricas agregadas (total PnL, total margin)

RF-TRD-006.4: Panel de Posiciones

El sistema debe proporcionar tabla con:

  • Lista de todas las posiciones abiertas
  • Resumen agregado en header
  • Filtros por símbolo, side, PnL
  • Ordenamiento por cualquier columna
  • Indicadores visuales de estado
  • Acciones rápidas por posición

Resumen agregado:

Total Positions: 5
Total Margin Used: $15,234.56
Total Unrealized PnL: +$1,234.56 (+8.1%)

RF-TRD-006.5: Cerrar Posiciones

El sistema debe permitir:

Cierre total:

  • Cerrar 100% de la posición
  • Ejecutar orden market al precio actual
  • Calcular PnL realizado
  • Actualizar balance
  • Registrar trade en historial

Cierre parcial:

  • Cerrar porcentaje específico (25%, 50%, 75%)
  • Mantener resto de posición abierta
  • Recalcular precio promedio
  • Registrar trade parcial

Confirmación:

  • Modal con previsualización del cierre
  • Mostrar PnL estimado
  • Mostrar balance después del cierre
  • Requiere confirmación del usuario

RF-TRD-006.6: Stop Loss y Take Profit

El sistema debe:

Configuración:

  • Añadir SL/TP a posición existente
  • Modificar SL/TP existentes
  • Eliminar SL/TP
  • Validar precios lógicos según side

Monitoreo automático:

  • Verificar precios cada 1 segundo
  • Ejecutar cierre automático al alcanzar nivel
  • Notificar al usuario
  • Registrar motivo de cierre

Trailing Stop Loss:

  • Actualizar SL automáticamente según ganancia
  • Configurar trailing distance (% o USD)
  • Activar solo cuando posición es ganadora

RF-TRD-006.7: Alertas y Notificaciones

El sistema debe notificar cuando:

  • Posición alcanza +X% de ganancia
  • Posición alcanza -X% de pérdida
  • Stop Loss está cerca de activarse (5%)
  • Take Profit está cerca de activarse (5%)
  • Posición está en riesgo de liquidación
  • Posición ha estado abierta > 24h

RF-TRD-006.8: Gestión de Riesgo

El sistema debe:

Validaciones:

  • Impedir apertura si margin used > 80% del balance
  • Advertir si posición representa > 50% del portfolio
  • Bloquear si existe ya posición del mismo símbolo
  • Validar que stop loss sea lógico

Liquidación:

  • Calcular precio de liquidación
  • Liquidar automáticamente al alcanzarlo
  • Notificar antes de liquidación (margen < 20%)
  • Registrar liquidación en historial

Métricas de riesgo:

  • Exposure por símbolo
  • Exposure total
  • Ratio de margen (margin used / balance)
  • Win rate actual
  • Average holding time

Datos de Entrada

Modificar Posición

interface UpdatePositionDto {
  positionId: string;
  stopLoss?: {
    type: 'price' | 'percent';
    value: number;
    trailing?: {
      enabled: boolean;
      distance: number;  // % o USD
    };
  };
  takeProfit?: {
    type: 'price' | 'percent';
    value: number;
  };
}

Cerrar Posición

interface ClosePositionDto {
  positionId: string;
  percentage: number;  // 1-100, default 100
  type: 'market' | 'limit';
  limitPrice?: number;
}

Datos de Salida

Posición

interface Position {
  id: string;
  userId: string;
  symbol: string;
  side: 'long' | 'short';

  // Cantidades
  quantity: number;
  entryPrice: number;
  currentPrice: number;

  // PnL
  unrealizedPnl: number;
  unrealizedPnlPercent: number;
  realizedPnl: number;        // De cierres parciales

  // Valores
  positionValue: number;
  marginUsed: number;

  // Stop Loss / Take Profit
  stopLoss: PositionStopLoss | null;
  takeProfit: PositionTakeProfit | null;

  // Liquidación
  liquidationPrice: number | null;
  liquidationRisk: 'low' | 'medium' | 'high';

  // Timestamps
  openedAt: string;
  lastUpdatedAt: string;
  duration: number;  // Segundos

  // Estado
  status: 'open' | 'closing' | 'closed';
  isInProfit: boolean;
}

interface PositionStopLoss {
  price: number;
  type: 'price' | 'percent';
  isTrailing: boolean;
  trailingDistance?: number;
  originalPrice?: number;  // Para trailing
}

interface PositionTakeProfit {
  price: number;
  type: 'price' | 'percent';
}

Resumen de Posiciones

interface PositionsSummary {
  totalPositions: number;
  totalMarginUsed: number;
  totalUnrealizedPnl: number;
  totalUnrealizedPnlPercent: number;
  marginRatio: number;  // marginUsed / balance

  byStatus: {
    profitable: number;
    unprofitable: number;
  };

  bySide: {
    long: number;
    short: number;
  };

  topGainer: Position | null;
  topLoser: Position | null;
}

Reglas de Negocio

  1. Posiciones simultáneas:

    • MVP: 1 posición por símbolo
    • Futuro: Múltiples posiciones (avg down/up)
  2. Cierre de posiciones:

    • Cierre parcial mínimo: 10%
    • Siempre ejecutar a precio market
    • Actualizar entrada promedio en parciales
  3. Stop Loss:

    • Debe estar por debajo del entry (long) o por encima (short)
    • Mínimo 0.5% del entry price
    • Máximo 50% del entry price
  4. Take Profit:

    • Debe estar por encima del entry (long) o por debajo (short)
    • Mínimo 0.5% del entry price
    • Sin límite máximo
  5. Liquidación:

    • Ocurre si pérdida > 80% del margen
    • Notificar cuando margen < 20%
    • Liquidar todo, no parcial
  6. Trailing Stop:

    • Solo se activa si posición en ganancia
    • Se mueve solo hacia ganancia, nunca retrocede
    • Mínima distancia: 0.5%

Criterios de Aceptación

Escenario: Posición se crea al ejecutar orden
  DADO que el usuario creó orden buy de 0.5 BTC a $50,000
  CUANDO la orden se ejecuta
  ENTONCES se crea posición long
  Y entry price es $50,000
  Y quantity es 0.5 BTC
  Y aparece en panel de posiciones

Escenario: PnL se actualiza en tiempo real
  DADO que el usuario tiene posición long con entry $50,000
  Y quantity es 0.5 BTC
  CUANDO el precio sube a $51,000
  ENTONCES unrealized PnL muestra +$500 (+2%)
  Y el valor se actualiza cada segundo
  Y se muestra en color verde

Escenario: Usuario cierra posición parcialmente
  DADO que el usuario tiene posición de 1 BTC
  CUANDO cierra 50% de la posición
  ENTONCES se ejecuta orden sell de 0.5 BTC
  Y la posición se reduce a 0.5 BTC
  Y se calcula PnL realizado de la mitad cerrada
  Y se registra trade en historial

Escenario: Stop Loss se activa
  DADO que el usuario tiene posición long entry $50,000
  Y stop loss configurado en $48,000
  CUANDO el precio baja a $48,000
  ENTONCES se ejecuta orden market sell automática
  Y la posición se cierra completamente
  Y se registra PnL realizado de -4%
  Y aparece notificación "Stop Loss activado"

Escenario: Trailing Stop se ajusta
  DADO que el usuario tiene trailing stop con 5% de distancia
  Y posición long entry $50,000
  Y stop loss inicial $47,500
  CUANDO el precio sube a $55,000
  ENTONCES stop loss se actualiza a $52,250 (5% debajo)
  Y se muestra en panel de posiciones
  Y se preserva ganancia de +4.5%

Escenario: Advertencia de riesgo de liquidación
  DADO que el usuario tiene posición con 80% de pérdida
  CUANDO se actualiza el precio
  ENTONCES aparece alerta "Riesgo de liquidación"
  Y se destaca la posición en rojo
  Y se sugiere añadir margen o cerrar

Escenario: Usuario modifica Stop Loss
  DADO que el usuario tiene posición con SL en $48,000
  CUANDO modifica SL a $49,000
  ENTONCES el nuevo SL se guarda
  Y se monitorea el nuevo nivel
  Y aparece confirmación

Interfaz de Usuario

┌────────────────────────────────────────────────────────────────┐
│                    OPEN POSITIONS                              │
├────────────────────────────────────────────────────────────────┤
│  Total: 3  │  Margin: $15,234  │  PnL: +$1,234 (+8.1%)      │
├────────────────────────────────────────────────────────────────┤
│                                                                │
│  Symbol  │ Side │ Entry  │ Current │  Qty   │    PnL   │     │
│──────────┼──────┼────────┼─────────┼────────┼──────────┼─────│
│ BTCUSDT  │ LONG │ 50,000 │ 51,500  │ 0.5    │ +$750    │ ... │
│          │      │        │         │        │ (+3.0%)  │     │
│          │      │ SL: $48,000  TP: $55,000           │ Close│
│──────────┼──────┼────────┼─────────┼────────┼──────────┼─────│
│ ETHUSDT  │ LONG │  3,200 │  3,350  │ 2.0    │ +$300    │ ... │
│          │      │        │         │        │ (+4.7%)  │     │
│          │      │ SL: None     TP: $3,500            │ Close│
│──────────┼──────┼────────┼─────────┼────────┼──────────┼─────│
│ BNBUSDT  │ LONG │    450 │    425  │ 10     │ -$250    │ ... │
│          │      │        │         │        │ (-5.6%)  │     │
│          │      │ SL: $400     TP: None              │ Close│
└────────────────────────────────────────────────────────────────┘

Estados de Posición

┌──────────┐
│   OPEN   │  ← Estado normal
└────┬─────┘
     │
     ├─→ Profitable (PnL > 0)
     ├─→ Unprofitable (PnL < 0)
     ├─→ At Risk (loss > 50%)
     │
     ├─→ [SL triggered] → CLOSING → CLOSED
     ├─→ [TP triggered] → CLOSING → CLOSED
     ├─→ [User closes]  → CLOSING → CLOSED
     └─→ [Liquidated]   → LIQUIDATED

Dependencias

  • RF-TRD-005: Sistema de Órdenes (crear órdenes de cierre)
  • RF-TRD-004: Paper Trading (balance y ejecución)
  • RF-TRD-007: Historial (registrar trades cerrados)
  • WebSocket para precios en tiempo real

Notas Técnicas

  • Actualizar PnL con debounce de 1 segundo
  • Usar transacciones para cierres de posición
  • Implementar locks para evitar double-close
  • Cachear cálculos pesados (liquidation price)
  • Guardar snapshots de precio cada minuto
  • Implementar circuit breaker para liquidaciones masivas
  • Usar Redis para monitoreo eficiente de SL/TP
  • Indexar por userId y status para queries rápidas

Cálculos Importantes

PnL para Long Position

Unrealized PnL = (currentPrice - entryPrice) × quantity
Unrealized PnL % = ((currentPrice - entryPrice) / entryPrice) × 100

PnL para Short Position (futuro)

Unrealized PnL = (entryPrice - currentPrice) × quantity
Unrealized PnL % = ((entryPrice - currentPrice) / entryPrice) × 100

Liquidation Price (sin apalancamiento)

Liquidation Price = entryPrice × 0.2  (pérdida del 80%)

Trailing Stop Loss Update

New SL = currentPrice × (1 - trailingDistance)  // Para long

Métricas a Trackear

  • Posiciones abiertas concurrentes
  • Tiempo promedio de holding
  • Win rate (profitable / total)
  • Profit factor (gross profit / gross loss)
  • Activaciones de SL vs TP
  • Liquidaciones (debería ser 0 idealmente)
  • Máximo drawdown por posición