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>
379 lines
14 KiB
Markdown
379 lines
14 KiB
Markdown
---
|
|
id: "US-TRD-012"
|
|
title: "Configurar Take Profit y Stop Loss"
|
|
type: "User Story"
|
|
status: "Done"
|
|
priority: "Alta"
|
|
epic: "OQI-003"
|
|
story_points: 5
|
|
created_date: "2025-12-05"
|
|
updated_date: "2026-01-04"
|
|
---
|
|
|
|
# US-TRD-012: Configurar Take Profit y Stop Loss
|
|
|
|
## Metadata
|
|
|
|
| Campo | Valor |
|
|
|-------|-------|
|
|
| **ID** | US-TRD-012 |
|
|
| **Épica** | OQI-003 - Trading y Charts |
|
|
| **Módulo** | trading |
|
|
| **Prioridad** | P1 |
|
|
| **Story Points** | 3 |
|
|
| **Sprint** | Sprint 5 |
|
|
| **Estado** | Pendiente |
|
|
| **Asignado a** | Por asignar |
|
|
|
|
---
|
|
|
|
## Historia de Usuario
|
|
|
|
**Como** trader practicante,
|
|
**quiero** configurar niveles de Take Profit y Stop Loss en mis posiciones,
|
|
**para** automatizar la gestión de riesgo y asegurar ganancias sin monitoreo constante.
|
|
|
|
## Descripción Detallada
|
|
|
|
El usuario debe poder establecer niveles de Take Profit (TP) y Stop Loss (SL) en posiciones abiertas, tanto al crear una orden como después de que la posición esté abierta. El sistema debe monitorear estos niveles y ejecutar automáticamente el cierre cuando el precio los alcance.
|
|
|
|
## Mockups/Wireframes
|
|
|
|
```
|
|
┌─────────────────────────────────────────────────────────────────┐
|
|
│ CONFIGURE TP/SL - BTCUSDT LONG Position │
|
|
├─────────────────────────────────────────────────────────────────┤
|
|
│ Position Details: │
|
|
│ Size: 0.1 BTC | Entry: $95,000 | Current: $97,234.50 │
|
|
│ Current P&L: +$223.45 (+2.35%) │
|
|
│ │
|
|
│ ┌───────────────────────────────────────────────────────────┐ │
|
|
│ │ TAKE PROFIT [✓ Enable]│ │
|
|
│ ├───────────────────────────────────────────────────────────┤ │
|
|
│ │ Price: │ │
|
|
│ │ ┌─────────────────────────────────────┐ │ │
|
|
│ │ │ 100,000.00 │ │ │
|
|
│ │ └─────────────────────────────────────┘ │ │
|
|
│ │ Distance: +2.84% (+$2,765.50) │ │
|
|
│ │ [Set 1%] [Set 2%] [Set 5%] [Set 10%] │ │
|
|
│ │ │ │
|
|
│ │ Est. Profit if triggered: +$500.00 (+5.26%) │ │
|
|
│ └───────────────────────────────────────────────────────────┘ │
|
|
│ │
|
|
│ ┌───────────────────────────────────────────────────────────┐ │
|
|
│ │ STOP LOSS [✓ Enable]│ │
|
|
│ ├───────────────────────────────────────────────────────────┤ │
|
|
│ │ Price: │ │
|
|
│ │ ┌─────────────────────────────────────┐ │ │
|
|
│ │ │ 93,000.00 │ │ │
|
|
│ │ └─────────────────────────────────────┘ │ │
|
|
│ │ Distance: -4.35% (-$4,234.50) │ │
|
|
│ │ [Set 1%] [Set 2%] [Set 5%] [Set 10%] │ │
|
|
│ │ │ │
|
|
│ │ Est. Loss if triggered: -$200.00 (-2.11%) │ │
|
|
│ │ ⚠ Warning: SL is below entry price │ │
|
|
│ └───────────────────────────────────────────────────────────┘ │
|
|
│ │
|
|
│ Risk/Reward Ratio: 2.50 (Good) │
|
|
│ │
|
|
│ ┌───────────────────────────────────────────────────────────┐ │
|
|
│ │ │ │
|
|
│ │ Chart Preview: │ │
|
|
│ │ $100,000 ─────────────────── TP (Green line) │ │
|
|
│ │ $97,234 ████ Current Price │ │
|
|
│ │ $95,000 ──── Entry (Blue line) │ │
|
|
│ │ $93,000 ─────────────────── SL (Red line) │ │
|
|
│ │ │ │
|
|
│ └───────────────────────────────────────────────────────────┘ │
|
|
│ │
|
|
│ [Cancel] [Save TP/SL] │
|
|
└─────────────────────────────────────────────────────────────────┘
|
|
```
|
|
|
|
---
|
|
|
|
## Criterios de Aceptación
|
|
|
|
**Escenario 1: Configurar TP y SL en posición existente**
|
|
```gherkin
|
|
DADO que el usuario tiene posición long BTCUSDT a $95,000
|
|
Y el precio actual es $97,234.50
|
|
CUANDO abre el diálogo de TP/SL
|
|
Y habilita Take Profit en $100,000
|
|
Y habilita Stop Loss en $93,000
|
|
Y hace click en "Save"
|
|
ENTONCES se guardan los niveles
|
|
Y aparecen en el panel de posiciones
|
|
Y se muestran líneas horizontales en el chart
|
|
Y el sistema comienza a monitorear estos niveles
|
|
```
|
|
|
|
**Escenario 2: Activación automática de Take Profit**
|
|
```gherkin
|
|
DADO que la posición tiene TP en $100,000
|
|
CUANDO el precio sube y alcanza $100,000
|
|
ENTONCES se ejecuta automáticamente orden market sell
|
|
Y la posición se cierra
|
|
Y el P&L realizado es +$500.00
|
|
Y el close_reason es "take_profit"
|
|
Y se envía notificación "Take Profit triggered at $100,000"
|
|
```
|
|
|
|
**Escenario 3: Activación automática de Stop Loss**
|
|
```gherkin
|
|
DADO que la posición tiene SL en $93,000
|
|
CUANDO el precio baja y alcanza $93,000
|
|
ENTONCES se ejecuta automáticamente orden market sell
|
|
Y la posición se cierra con pérdida
|
|
Y el P&L realizado es -$200.00
|
|
Y el close_reason es "stop_loss"
|
|
Y se envía notificación "Stop Loss triggered at $93,000"
|
|
```
|
|
|
|
**Escenario 4: Validación de niveles lógicos**
|
|
```gherkin
|
|
DADO que el usuario tiene posición LONG
|
|
CUANDO intenta configurar TP=$90,000 (menor al precio actual)
|
|
ENTONCES se muestra warning "TP should be above current price for LONG"
|
|
Y permite continuar (puede ser trailing stop futuro)
|
|
|
|
CUANDO intenta configurar SL=$105,000 (mayor al precio actual)
|
|
ENTONCES se muestra warning "SL should be below current price for LONG"
|
|
```
|
|
|
|
**Escenario 5: Modificar TP/SL existentes**
|
|
```gherkin
|
|
DADO que la posición tiene TP=$100,000 y SL=$93,000
|
|
CUANDO el usuario modifica TP a $105,000
|
|
Y guarda los cambios
|
|
ENTONCES el sistema actualiza solo el TP
|
|
Y mantiene el SL en $93,000
|
|
Y las líneas en el chart se actualizan
|
|
```
|
|
|
|
**Escenario 6: Deshabilitar TP o SL**
|
|
```gherkin
|
|
DADO que la posición tiene TP y SL configurados
|
|
CUANDO el usuario deshabilita el checkbox de TP
|
|
Y guarda
|
|
ENTONCES el TP se elimina
|
|
Y solo queda activo el SL
|
|
Y la línea verde desaparece del chart
|
|
```
|
|
|
|
**Escenario 7: Mostrar Risk/Reward Ratio**
|
|
```gherkin
|
|
DADO que el usuario configura TP=$100,000 y SL=$93,000
|
|
CUANDO el sistema calcula
|
|
ENTONCES muestra Risk/Reward = 2.50
|
|
- Potencial ganancia: $500 (riesgo hacia arriba)
|
|
- Potencial pérdida: $200 (riesgo hacia abajo)
|
|
- Ratio: 500 / 200 = 2.50
|
|
Y muestra indicador "Good" si ratio > 2.0
|
|
```
|
|
|
|
## Criterios Adicionales
|
|
|
|
- [ ] Botones rápidos para configurar TP/SL en %
|
|
- [ ] Trailing Stop Loss (futuro enhancement)
|
|
- [ ] Notificación cuando el precio se acerca a TP/SL (±1%)
|
|
- [ ] Mostrar distancia a TP/SL en tiempo real
|
|
- [ ] Histórico de TP/SL activados
|
|
|
|
---
|
|
|
|
## Tareas Técnicas
|
|
|
|
**Database:**
|
|
- [ ] DB-TRD-019: Añadir campos take_profit, stop_loss a paper_positions
|
|
- [ ] DB-TRD-020: Añadir índice en (take_profit, stop_loss) para queries
|
|
|
|
**Backend:**
|
|
- [ ] BE-TRD-064: Crear endpoint PATCH /trading/paper/positions/:id/tp-sl
|
|
- [ ] BE-TRD-065: Implementar PositionService.updateTPSL()
|
|
- [ ] BE-TRD-066: Implementar TPSLMonitorService (background job)
|
|
- [ ] BE-TRD-067: Implementar lógica de activación de TP
|
|
- [ ] BE-TRD-068: Implementar lógica de activación de SL
|
|
- [ ] BE-TRD-069: Integrar con PositionService.closePosition()
|
|
|
|
**Frontend:**
|
|
- [ ] FE-TRD-064: Crear componente ConfigureTPSLDialog.tsx
|
|
- [ ] FE-TRD-065: Crear componente TPSLInput.tsx
|
|
- [ ] FE-TRD-066: Crear componente RiskRewardIndicator.tsx
|
|
- [ ] FE-TRD-067: Añadir líneas de TP/SL en TradingChart
|
|
- [ ] FE-TRD-068: Implementar hook useConfigureTPSL
|
|
- [ ] FE-TRD-069: Actualizar PositionRow con indicadores de TP/SL
|
|
|
|
**Tests:**
|
|
- [ ] TEST-TRD-031: Test unitario cálculo risk/reward
|
|
- [ ] TEST-TRD-032: Test integración activación TP/SL
|
|
- [ ] TEST-TRD-033: Test E2E flujo completo TP/SL
|
|
|
|
---
|
|
|
|
## Dependencias
|
|
|
|
**Depende de:**
|
|
- [ ] US-TRD-009: Ver posiciones - Estado: Pendiente
|
|
- [ ] US-TRD-008: Cerrar posición - Estado: Pendiente
|
|
|
|
**Bloquea:**
|
|
- Ninguna
|
|
|
|
---
|
|
|
|
## Notas Técnicas
|
|
|
|
**Endpoints involucrados:**
|
|
| Método | Endpoint | Descripción |
|
|
|--------|----------|-------------|
|
|
| PATCH | /trading/paper/positions/:id/tp-sl | Configurar/actualizar TP/SL |
|
|
| DELETE | /trading/paper/positions/:id/tp-sl | Eliminar TP/SL |
|
|
|
|
**Entidades/Tablas:**
|
|
```sql
|
|
ALTER TABLE trading.paper_positions
|
|
ADD COLUMN take_profit DECIMAL(20, 8),
|
|
ADD COLUMN stop_loss DECIMAL(20, 8);
|
|
|
|
CREATE INDEX idx_positions_tp_sl
|
|
ON trading.paper_positions(take_profit, stop_loss)
|
|
WHERE take_profit IS NOT NULL OR stop_loss IS NOT NULL;
|
|
```
|
|
|
|
**Componentes UI:**
|
|
- `ConfigureTPSLDialog`: Modal de configuración
|
|
- `TPSLInput`: Input con validación
|
|
- `RiskRewardIndicator`: Indicador de ratio
|
|
- `TPSLLines`: Líneas horizontales en chart
|
|
- `QuickPercentButtons`: Botones de % rápidos
|
|
|
|
**Request Body:**
|
|
```typescript
|
|
{
|
|
takeProfit: 100000.00, // null para deshabilitar
|
|
stopLoss: 93000.00 // null para deshabilitar
|
|
}
|
|
```
|
|
|
|
**Response:**
|
|
```typescript
|
|
{
|
|
position: {
|
|
id: "uuid",
|
|
symbol: "BTCUSDT",
|
|
side: "long",
|
|
quantity: 0.1,
|
|
entryPrice: 95000.00,
|
|
currentPrice: 97234.50,
|
|
takeProfit: 100000.00,
|
|
stopLoss: 93000.00,
|
|
riskRewardRatio: 2.50
|
|
},
|
|
preview: {
|
|
distanceToTP: 2.84,
|
|
distanceToSL: -4.35,
|
|
potentialProfit: 500.00,
|
|
potentialLoss: -200.00,
|
|
riskRewardRatio: 2.50
|
|
}
|
|
}
|
|
```
|
|
|
|
**TP/SL Monitor Logic (Background Job - cada segundo):**
|
|
```typescript
|
|
// Para posición LONG
|
|
const positions = await getPositionsWithTPSL();
|
|
|
|
for (const position of positions) {
|
|
const currentPrice = await getCurrentPrice(position.symbol);
|
|
|
|
// Check Take Profit
|
|
if (position.takeProfit && currentPrice >= position.takeProfit) {
|
|
await closePosition(position.id, 'take_profit');
|
|
await sendNotification(`TP triggered at ${currentPrice}`);
|
|
}
|
|
|
|
// Check Stop Loss
|
|
if (position.stopLoss && currentPrice <= position.stopLoss) {
|
|
await closePosition(position.id, 'stop_loss');
|
|
await sendNotification(`SL triggered at ${currentPrice}`);
|
|
}
|
|
}
|
|
|
|
// Para posición SHORT (lógica inversa)
|
|
// TP se activa cuando currentPrice <= takeProfit
|
|
// SL se activa cuando currentPrice >= stopLoss
|
|
```
|
|
|
|
**Cálculos:**
|
|
```typescript
|
|
// Risk/Reward Ratio
|
|
const potentialProfit = Math.abs(takeProfit - entryPrice) * quantity;
|
|
const potentialLoss = Math.abs(entryPrice - stopLoss) * quantity;
|
|
const riskRewardRatio = potentialProfit / potentialLoss;
|
|
|
|
// Distance to TP/SL (%)
|
|
const distanceToTP = ((takeProfit - currentPrice) / currentPrice) * 100;
|
|
const distanceToSL = ((stopLoss - currentPrice) / currentPrice) * 100;
|
|
|
|
// Validaciones para LONG
|
|
const validTPForLong = takeProfit > currentPrice;
|
|
const validSLForLong = stopLoss < currentPrice;
|
|
|
|
// Validaciones para SHORT
|
|
const validTPForShort = takeProfit < currentPrice;
|
|
const validSLForShort = stopLoss > currentPrice;
|
|
```
|
|
|
|
**Quick Percentage Buttons:**
|
|
```typescript
|
|
// Para posición LONG, TP
|
|
const tp1Percent = currentPrice * 1.01; // +1%
|
|
const tp2Percent = currentPrice * 1.02; // +2%
|
|
const tp5Percent = currentPrice * 1.05; // +5%
|
|
const tp10Percent = currentPrice * 1.10; // +10%
|
|
|
|
// Para posición LONG, SL
|
|
const sl1Percent = currentPrice * 0.99; // -1%
|
|
const sl2Percent = currentPrice * 0.98; // -2%
|
|
const sl5Percent = currentPrice * 0.95; // -5%
|
|
const sl10Percent = currentPrice * 0.90; // -10%
|
|
```
|
|
|
|
---
|
|
|
|
## 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
|