trading-platform/docs/02-definicion-modulos/OQI-003-trading-charts/historias-usuario/US-TRD-008-cerrar-posicion.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

10 KiB

id title type status priority epic story_points created_date updated_date
US-TRD-008 Cerrar Posicion User Story Done Alta OQI-003 3 2025-12-05 2026-01-04

US-TRD-008: Cerrar Posición

Metadata

Campo Valor
ID US-TRD-008
É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 cerrar mis posiciones abiertas total o parcialmente, para realizar mis ganancias o limitar mis pérdidas en el momento que decida.

Descripción Detallada

El usuario debe poder cerrar posiciones long o short en cualquier momento, ya sea completamente o una porción específica. Al cerrar, se ejecuta una orden market en dirección opuesta y se calcula el P&L (profit and loss) realizado.

Mockups/Wireframes

┌─────────────────────────────────────────────────────────────────┐
│  OPEN POSITIONS                                                 │
├─────────────────────────────────────────────────────────────────┤
│  Symbol    Side  Size    Entry      Current    PnL      Actions │
│  ──────────────────────────────────────────────────────────────  │
│  BTCUSDT   LONG  0.1 BTC $95,000   $97,234.50  +$223.45  [Close]│
│                                                  (+2.35%)  [ ▼ ] │
│  ──────────────────────────────────────────────────────────────  │
│                                                                   │
│  ┌────────────────────────────────────┐                         │
│  │ CLOSE POSITION                     │                         │
│  ├────────────────────────────────────┤                         │
│  │ Symbol: BTCUSDT                    │                         │
│  │ Position: 0.1 BTC LONG             │                         │
│  │                                     │                         │
│  │ Amount to close:                   │                         │
│  │ ┌──────────────────────────────┐  │                         │
│  │ │ 0.1 BTC                      │  │                         │
│  │ └──────────────────────────────┘  │                         │
│  │ [25%] [50%] [75%] [100%]           │                         │
│  │                                     │                         │
│  │ Entry Price: $95,000.00            │                         │
│  │ Current Price: $97,234.50          │                         │
│  │ Est. P&L: +$223.45 (+2.35%)        │                         │
│  │                                     │                         │
│  │  [Cancel]     [Close Position]     │                         │
│  └────────────────────────────────────┘                         │
└─────────────────────────────────────────────────────────────────┘

Criterios de Aceptación

Escenario 1: Cerrar posición long completa

DADO que el usuario tiene posición long de 0.1 BTC en BTCUSDT
Y el precio de entrada fue $95,000
Y el precio actual es $97,234.50
CUANDO hace click en "Close" en la posición
Y selecciona cerrar 100% (0.1 BTC)
Y confirma
ENTONCES se ejecuta orden market SELL de 0.1 BTC
Y la posición se cierra completamente
Y se calcula P&L: +$223.45 (+2.35%)
Y el balance se incrementa en $9,723.45 ($9,500 + $223.45)
Y la posición desaparece de "Open Positions"
Y se muestra notificación "Position closed. P&L: +$223.45"

Escenario 2: Cerrar posición short con ganancia

DADO que el usuario tiene posición short de 0.05 BTC
Y el precio de entrada fue $97,000
Y el precio actual es $96,000
CUANDO cierra la posición completa
ENTONCES se ejecuta orden market BUY de 0.05 BTC
Y se calcula P&L: +$50.00 (+1.03%)
Y la posición se cierra

Escenario 3: Cerrar posición parcial (50%)

DADO que el usuario tiene posición long de 0.1 BTC
CUANDO hace click en "Close"
Y selecciona 50% (0.05 BTC)
Y confirma
ENTONCES se cierra solo 0.05 BTC
Y la posición restante es 0.05 BTC
Y el P&L parcial se registra
Y la posición sigue apareciendo con nuevo tamaño

Escenario 4: Cerrar posición con pérdida

DADO que el usuario tiene posición long a $97,000
Y el precio actual es $95,000
CUANDO cierra la posición
ENTONCES se calcula P&L: -$200.00 (-2.06%)
Y el balance se reduce en $200
Y se registra la pérdida en el historial

Escenario 5: Confirmación antes de cerrar

DADO que el usuario hace click en "Close"
CUANDO se abre el diálogo de confirmación
ENTONCES muestra:
  - Cantidad a cerrar
  - Precio de entrada vs actual
  - P&L estimado
  - Botón de confirmar
Y debe confirmar antes de ejecutar

Criterios Adicionales

  • Slippage aplicado al cerrar (±0.1%)
  • Keyboard shortcut: Esc para cancelar
  • Color verde para P&L positivo, rojo para negativo
  • Mostrar ROI (Return on Investment) en %
  • Registro en trade history

Tareas Técnicas

Database:

  • DB-TRD-012: Crear tabla paper_trade_history
  • DB-TRD-013: Añadir campo closed_at a paper_positions

Backend:

  • BE-TRD-038: Crear endpoint POST /trading/paper/positions/:id/close
  • BE-TRD-039: Implementar PositionService.closePosition()
  • BE-TRD-040: Implementar cálculo de P&L
  • BE-TRD-041: Implementar cierre parcial
  • BE-TRD-042: Actualizar BalanceService con P&L
  • BE-TRD-043: Crear registro en trade_history

Frontend:

  • FE-TRD-038: Crear componente OpenPositionsPanel.tsx
  • FE-TRD-039: Crear componente ClosePositionDialog.tsx
  • FE-TRD-040: Crear componente PositionRow.tsx con P&L
  • FE-TRD-041: Implementar hook useClosePosition
  • FE-TRD-042: Actualizar positionStore con cierres
  • FE-TRD-043: Implementar animación al cerrar

Tests:

  • TEST-TRD-019: Test unitario cálculo P&L
  • TEST-TRD-020: Test integración cerrar posición
  • TEST-TRD-021: Test E2E flujo completo cierre

Dependencias

Depende de:

  • US-TRD-006: Crear orden market - Estado: Pendiente (necesita posiciones abiertas)

Bloquea:

  • US-TRD-010: Ver historial de trades

Notas Técnicas

Endpoints involucrados:

Método Endpoint Descripción
POST /trading/paper/positions/:id/close Cerrar posición
GET /trading/paper/positions Listar posiciones abiertas
GET /trading/paper/positions/:id Obtener detalles de posición

Entidades/Tablas:

CREATE TABLE trading.paper_trade_history (
  id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
  user_id UUID NOT NULL REFERENCES auth.users(id),
  symbol VARCHAR(20) NOT NULL,
  side VARCHAR(10) NOT NULL,
  quantity DECIMAL(20, 8) NOT NULL,
  entry_price DECIMAL(20, 8) NOT NULL,
  exit_price DECIMAL(20, 8) NOT NULL,
  pnl DECIMAL(20, 8) NOT NULL,
  pnl_percentage DECIMAL(10, 4) NOT NULL,
  opened_at TIMESTAMP NOT NULL,
  closed_at TIMESTAMP DEFAULT NOW(),
  duration_seconds INTEGER
);

ALTER TABLE trading.paper_positions ADD COLUMN closed_at TIMESTAMP;
ALTER TABLE trading.paper_positions ADD COLUMN status VARCHAR(20) DEFAULT 'open';

Componentes UI:

  • OpenPositionsPanel: Panel de posiciones abiertas
  • ClosePositionDialog: Modal de confirmación
  • PositionRow: Fila con datos de posición
  • PnLBadge: Badge con P&L coloreado

Request Body:

{
  quantity: 0.05,  // Cantidad a cerrar (o null para cerrar todo)
  percentage: 50   // O porcentaje (25, 50, 75, 100)
}

Response:

{
  trade: {
    id: "uuid",
    symbol: "BTCUSDT",
    side: "long",
    quantity: 0.05,
    entryPrice: 95000.00,
    exitPrice: 97234.50,
    pnl: 111.73,
    pnlPercentage: 2.35,
    openedAt: "2025-12-05T09:00:00Z",
    closedAt: "2025-12-05T10:30:00Z",
    durationSeconds: 5400
  },
  position: {
    id: "uuid",
    remainingQuantity: 0.05,  // Si cierre parcial
    status: "open"  // o "closed"
  },
  balance: {
    balance: 9611.73,
    equity: 9723.46,
    marginUsed: 4762.50
  }
}

Cálculo de P&L:

// Para posición LONG
const pnl = (exitPrice - entryPrice) * quantity;
const pnlPercentage = ((exitPrice - entryPrice) / entryPrice) * 100;

// Para posición SHORT
const pnl = (entryPrice - exitPrice) * quantity;
const pnlPercentage = ((entryPrice - exitPrice) / entryPrice) * 100;

// Aplicar slippage (simulación)
const slippage = 0.001; // 0.1%
const actualExitPrice = side === 'long'
  ? currentPrice * (1 - slippage)
  : currentPrice * (1 + slippage);

Definition of Ready (DoR)

  • Historia claramente escrita
  • Criterios de aceptación definidos
  • Story points estimados
  • Dependencias identificadas
  • 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