--- id: "US-TRD-009" title: "Ver Panel de Posiciones Abiertas" type: "User Story" status: "Done" priority: "Alta" epic: "OQI-003" story_points: 3 created_date: "2025-12-05" updated_date: "2026-01-04" --- # US-TRD-009: Ver Panel de Posiciones Abiertas ## Metadata | Campo | Valor | |-------|-------| | **ID** | US-TRD-009 | | **Épica** | OQI-003 - Trading y Charts | | **Módulo** | trading | | **Prioridad** | P0 | | **Story Points** | 3 | | **Sprint** | Sprint 4 | | **Estado** | Pendiente | | **Asignado a** | Por asignar | --- ## Historia de Usuario **Como** trader practicante, **quiero** ver un panel con todas mis posiciones abiertas y su P&L en tiempo real, **para** monitorear el rendimiento actual de mis trades y tomar decisiones informadas. ## Descripción Detallada El usuario debe tener acceso a un panel dedicado que muestre todas las posiciones abiertas con información crítica: símbolo, dirección (long/short), tamaño, precio de entrada, precio actual, P&L no realizado en dólares y porcentaje, y acciones rápidas (cerrar, modificar TP/SL). ## Mockups/Wireframes ``` ┌─────────────────────────────────────────────────────────────────────────┐ │ OPEN POSITIONS Total P&L: +$345.67 │ ├─────────────────────────────────────────────────────────────────────────┤ │ Symbol Side Size Entry Current PnL Actions │ │ ───────────────────────────────────────────────────────────────────── │ │ BTCUSDT LONG 0.10 BTC $95,000.00 $97,234.50 +$223.45 [...] │ │ (+2.35%) ▲ │ │ TP: $100,000 | SL: $93,000 │ │ ───────────────────────────────────────────────────────────────────── │ │ ETHUSDT LONG 2.5 ETH $3,800.00 $3,850.20 +$125.50 [...] │ │ (+1.32%) ▲ │ │ TP: $4,000 | SL: $3,700 │ │ ───────────────────────────────────────────────────────────────────── │ │ SOLUSDT SHORT 10 SOL $145.00 $142.73 +$22.70 [...] │ │ (+1.56%) ▲ │ │ TP: $140.00 | SL: $148.00 │ │ ───────────────────────────────────────────────────────────────────── │ │ │ │ Summary: │ │ Total Margin Used: $7,450.00 | Free Balance: $2,550.00 │ │ Total Equity: $10,345.67 | Margin Level: 138.9% │ └─────────────────────────────────────────────────────────────────────────┘ ┌─────────────────────────┐ │ POSITION ACTIONS │ ├─────────────────────────┤ │ > Close Position │ │ > Modify TP/SL │ │ > Add to Position │ │ > View on Chart │ └─────────────────────────┘ ``` --- ## Criterios de Aceptación **Escenario 1: Ver panel con múltiples posiciones** ```gherkin DADO que el usuario tiene 3 posiciones abiertas CUANDO navega al panel de posiciones ENTONCES se muestran las 3 posiciones en una tabla Y cada fila muestra: símbolo, side, size, entry, current, P&L Y el P&L total aparece en el header Y los valores se actualizan cada segundo ``` **Escenario 2: Actualización de P&L en tiempo real** ```gherkin DADO que el usuario tiene posición long BTCUSDT Y el precio actual es $97,234.50 CUANDO el precio sube a $97,500.00 ENTONCES el P&L se actualiza automáticamente Y muestra +$250.00 (+2.63%) Y el color cambia según el valor (verde positivo, rojo negativo) ``` **Escenario 3: Mostrar TP y SL configurados** ```gherkin DADO que la posición tiene TP=$100,000 y SL=$93,000 CUANDO el usuario ve la posición ENTONCES se muestran ambos valores debajo de la fila principal Y se indica la distancia en % al TP y SL Ejemplo: "TP: $100,000 (+2.84%) | SL: $93,000 (-4.35%)" ``` **Escenario 4: Panel vacío** ```gherkin DADO que el usuario no tiene posiciones abiertas CUANDO accede al panel de posiciones ENTONCES se muestra mensaje "No open positions" Y se muestra botón "Start Trading" Y el total P&L es $0.00 ``` **Escenario 5: Ordenar por P&L** ```gherkin DADO que el usuario tiene múltiples posiciones CUANDO hace click en el header "PnL" ENTONCES las posiciones se ordenan por P&L descendente Y un segundo click ordena ascendente ``` **Escenario 6: Filtrar por símbolo** ```gherkin DADO que el usuario tiene posiciones en BTC, ETH, SOL CUANDO escribe "BTC" en el filtro ENTONCES solo se muestran posiciones de BTCUSDT ``` ## Criterios Adicionales - [ ] Resaltar posiciones con P&L > ±5% en color intenso - [ ] Sonido de alerta cuando P&L alcanza ±10% - [ ] Mostrar duración de la posición (ej: "2h 35m") - [ ] Indicador visual cuando el precio se acerca al TP o SL (±2%) - [ ] Exportar posiciones a CSV --- ## Tareas Técnicas **Database:** - [ ] DB-TRD-014: Crear vista positions_with_pnl con cálculos **Backend:** - [ ] BE-TRD-044: Crear endpoint GET /trading/paper/positions - [ ] BE-TRD-045: Implementar PositionService.listPositions() - [ ] BE-TRD-046: Implementar cálculo de P&L no realizado - [ ] BE-TRD-047: Implementar WebSocket para actualizaciones de P&L - [ ] BE-TRD-048: Añadir filtros y ordenamiento **Frontend:** - [ ] FE-TRD-044: Crear componente PositionsPanel.tsx - [ ] FE-TRD-045: Crear componente PositionRow.tsx - [ ] FE-TRD-046: Crear componente PositionSummary.tsx - [ ] FE-TRD-047: Crear componente PositionActions.tsx - [ ] FE-TRD-048: Implementar hook usePositions con WebSocket - [ ] FE-TRD-049: Implementar animación de cambios de P&L **Tests:** - [ ] TEST-TRD-022: Test unitario cálculo P&L no realizado - [ ] TEST-TRD-023: Test integración listar posiciones - [ ] TEST-TRD-024: Test E2E actualización en tiempo real --- ## Dependencias **Depende de:** - [ ] US-TRD-006: Crear orden market - Estado: Pendiente (necesita posiciones) - [ ] US-TRD-001: Ver chart - Estado: Pendiente (para precios) **Bloquea:** - [ ] US-TRD-008: Cerrar posición - [ ] US-TRD-012: Configurar TP/SL --- ## Notas Técnicas **Endpoints involucrados:** | Método | Endpoint | Descripción | |--------|----------|-------------| | GET | /trading/paper/positions | Listar posiciones abiertas | | GET | /trading/paper/positions/summary | Resumen de posiciones | | WS | /trading/positions/stream | Stream de actualizaciones P&L | **Entidades/Tablas:** ```sql CREATE VIEW trading.positions_with_pnl AS SELECT p.*, t.price as current_price, CASE WHEN p.side = 'long' THEN (t.price - p.entry_price) * p.quantity WHEN p.side = 'short' THEN (p.entry_price - t.price) * p.quantity END as unrealized_pnl, CASE WHEN p.side = 'long' THEN ((t.price - p.entry_price) / p.entry_price) * 100 WHEN p.side = 'short' THEN ((p.entry_price - t.price) / p.entry_price) * 100 END as unrealized_pnl_percentage, EXTRACT(EPOCH FROM (NOW() - p.created_at)) as duration_seconds FROM trading.paper_positions p LEFT JOIN trading.current_prices t ON p.symbol = t.symbol WHERE p.status = 'open'; ``` **Componentes UI:** - `PositionsPanel`: Panel principal - `PositionRow`: Fila de posición con datos - `PositionSummary`: Resumen total - `PositionActions`: Menú de acciones - `PnLCell`: Celda con P&L coloreado y animado **Response (List Positions):** ```typescript { positions: [ { id: "uuid-1", symbol: "BTCUSDT", side: "long", quantity: 0.1, entryPrice: 95000.00, currentPrice: 97234.50, unrealizedPnl: 223.45, unrealizedPnlPercentage: 2.35, marginUsed: 9500.00, takeProfit: 100000.00, stopLoss: 93000.00, durationSeconds: 8640, createdAt: "2025-12-05T08:00:00Z" }, // ... más posiciones ], summary: { totalPositions: 3, totalMarginUsed: 7450.00, totalUnrealizedPnl: 345.67, totalUnrealizedPnlPercentage: 4.64, freeBalance: 2550.00, totalEquity: 10345.67, marginLevel: 138.9 } } ``` **WebSocket Update:** ```typescript { type: "position_update", data: { positionId: "uuid-1", currentPrice: 97500.00, unrealizedPnl: 250.00, unrealizedPnlPercentage: 2.63, timestamp: 1733414400 } } ``` **Cálculos importantes:** ```typescript // P&L no realizado (unrealized) const unrealizedPnl = side === 'long' ? (currentPrice - entryPrice) * quantity : (entryPrice - currentPrice) * quantity; // Equity const equity = balance + totalUnrealizedPnl; // Margin Level const marginLevel = (equity / totalMarginUsed) * 100; // Distancia a TP/SL const distanceToTP = ((takeProfit - currentPrice) / currentPrice) * 100; const distanceToSL = ((stopLoss - currentPrice) / currentPrice) * 100; ``` --- ## Definition of Ready (DoR) - [x] Historia claramente escrita - [x] Criterios de aceptación definidos - [x] Story points estimados - [x] Dependencias identificadas - [x] Sin bloqueadores - [ ] Diseño/mockup disponible - [ ] API spec disponible ## Definition of Done (DoD) - [ ] Código implementado según criterios - [ ] Tests unitarios escritos y pasando - [ ] Tests de integración pasando - [ ] Code review aprobado - [ ] Documentación actualizada - [ ] QA aprobado - [ ] Desplegado en ambiente de pruebas --- ## Historial de Cambios | Fecha | Cambio | Autor | |-------|--------|-------| | 2025-12-05 | Creación | Requirements-Analyst | --- **Creada por:** Requirements-Analyst **Fecha:** 2025-12-05 **Última actualización:** 2025-12-05