trading-platform/docs/02-definicion-modulos/OQI-003-trading-charts/historias-usuario/US-TRD-013-alertas-precio.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

450 lines
16 KiB
Markdown

---
id: "US-TRD-013"
title: "Configurar Alertas de Precio"
type: "User Story"
status: "Done"
priority: "Media"
epic: "OQI-003"
story_points: 5
created_date: "2025-12-05"
updated_date: "2026-01-04"
---
# US-TRD-013: Configurar Alertas de Precio
## Metadata
| Campo | Valor |
|-------|-------|
| **ID** | US-TRD-013 |
| **Épica** | OQI-003 - Trading y Charts |
| **Módulo** | trading |
| **Prioridad** | P2 |
| **Story Points** | 3 |
| **Sprint** | Sprint 6 |
| **Estado** | Pendiente |
| **Asignado a** | Por asignar |
---
## Historia de Usuario
**Como** trader,
**quiero** configurar alertas de precio para símbolos específicos,
**para** recibir notificaciones cuando el precio alcance niveles importantes sin monitorear constantemente.
## Descripción Detallada
El usuario debe poder crear alertas de precio para cualquier símbolo, especificando condiciones como "precio mayor que", "precio menor que", o "precio cruza". Cuando la condición se cumpla, el usuario recibe una notificación push y/o email.
## Mockups/Wireframes
```
┌─────────────────────────────────────────────────────────────────┐
│ PRICE ALERTS │
├─────────────────────────────────────────────────────────────────┤
│ [+ Create Alert] │
│ │
│ Active Alerts (3) │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ BTCUSDT [...] │ │
│ │ When price goes ABOVE $100,000 │ │
│ │ Current: $97,234.50 | Distance: +2.84% │ │
│ │ Created: Dec 5, 2025 10:00 AM │ │
│ │ [🔔 Enabled] │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ ETHUSDT [...] │ │
│ │ When price goes BELOW $3,700 │ │
│ │ Current: $3,845.20 | Distance: -3.92% │ │
│ │ Created: Dec 4, 2025 02:30 PM │ │
│ │ [🔕 Disabled] │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ SOLUSDT [...] │ │
│ │ When price CROSSES $150 (from either direction) │ │
│ │ Current: $142.73 | Distance: -5.09% │ │
│ │ Created: Dec 3, 2025 09:15 AM │ │
│ │ [🔔 Enabled] │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
│ Triggered Alerts (5) [View History] │
└─────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────┐
│ CREATE PRICE ALERT │
├─────────────────────────────────────┤
│ Symbol: │
│ ┌─────────────────────────────────┐ │
│ │ BTCUSDT [▼] │ │
│ └─────────────────────────────────┘ │
│ Current Price: $97,234.50 │
│ │
│ Condition: │
│ ┌─────────────────────────────────┐ │
│ │ Price goes ABOVE [▼] │ │
│ └─────────────────────────────────┘ │
│ Options: Above, Below, Crosses │
│ │
│ Target Price: │
│ ┌─────────────────────────────────┐ │
│ │ 100,000.00 │ │
│ └─────────────────────────────────┘ │
│ Distance: +2.84% │
│ [Set +1%] [Set +5%] [Set +10%] │
│ │
│ Notification Method: │
│ [✓] Push Notification │
│ [✓] Email │
│ [ ] SMS (Premium) │
│ │
│ Message (optional): │
│ ┌─────────────────────────────────┐ │
│ │ BTC hitting resistance │ │
│ └─────────────────────────────────┘ │
│ │
│ Expires After: │
│ ┌─────────────────────────────────┐ │
│ │ Never [▼] │ │
│ └─────────────────────────────────┘ │
│ │
│ [Cancel] [Create Alert] │
└─────────────────────────────────────┘
```
---
## Criterios de Aceptación
**Escenario 1: Crear alerta "price above"**
```gherkin
DADO que el usuario está en Price Alerts
CUANDO hace click en "+ Create Alert"
Y selecciona símbolo "BTCUSDT"
Y selecciona condición "Price goes ABOVE"
Y ingresa precio $100,000
Y habilita "Push Notification" y "Email"
Y hace click en "Create Alert"
ENTONCES se crea la alerta
Y aparece en "Active Alerts"
Y muestra distancia actual (+2.84%)
Y el sistema comienza a monitorear
```
**Escenario 2: Activación de alerta "above"**
```gherkin
DADO que existe alerta BTCUSDT ABOVE $100,000
Y el precio actual es $99,500
CUANDO el precio sube y alcanza $100,000
ENTONCES se dispara la alerta
Y se envía push notification
Y se envía email
Y la alerta pasa a "Triggered Alerts"
Y se deshabilita automáticamente
```
**Escenario 3: Crear alerta "price below"**
```gherkin
DADO que el usuario crea alerta
CUANDO selecciona "Price goes BELOW $3,700" para ETHUSDT
Y el precio actual es $3,845
ENTONCES se crea alerta activa
Y se activa solo cuando el precio baje a $3,700 o menos
```
**Escenario 4: Alerta "crosses" bidireccional**
```gherkin
DADO que el usuario crea alerta "CROSSES $150" para SOLUSDT
CUANDO el precio cruza $150 desde arriba (150.10149.90)
O desde abajo (149.90150.10)
ENTONCES se dispara la alerta
Y notifica al usuario
```
**Escenario 5: Deshabilitar alerta temporalmente**
```gherkin
DADO que el usuario tiene alerta activa
CUANDO hace click en el toggle [🔔 Enabled]
ENTONCES cambia a [🔕 Disabled]
Y el sistema deja de monitorear esa alerta
Y puede re-habilitarla más tarde
```
**Escenario 6: Alerta con expiración**
```gherkin
DADO que el usuario crea alerta
CUANDO selecciona "Expires After: 24 hours"
Y la alerta no se dispara en 24 horas
ENTONCES la alerta se elimina automáticamente
Y se muestra en historial como "Expired"
```
**Escenario 7: Límite de alertas**
```gherkin
DADO que el usuario tiene 10 alertas activas (límite)
CUANDO intenta crear otra
ENTONCES se muestra error "Maximum 10 active alerts"
Y sugiere deshabilitar o eliminar alertas existentes
```
## Criterios Adicionales
- [ ] Click en alerta abre chart del símbolo
- [ ] Sonido diferenciado para alertas
- [ ] Historial de alertas disparadas
- [ ] Plantillas de alertas (niveles psicológicos, ATH, etc.)
- [ ] Re-activar alerta después de dispararse
---
## Tareas Técnicas
**Database:**
- [ ] DB-TRD-021: Crear tabla trading.price_alerts
- Campos: id, user_id, symbol, condition, target_price, notification_methods, message, expires_at, status, triggered_at
- [ ] DB-TRD-022: Crear índice en (user_id, status, symbol)
**Backend:**
- [ ] BE-TRD-070: Crear endpoint POST /trading/alerts
- [ ] BE-TRD-071: Crear endpoint GET /trading/alerts
- [ ] BE-TRD-072: Crear endpoint PATCH /trading/alerts/:id
- [ ] BE-TRD-073: Crear endpoint DELETE /trading/alerts/:id
- [ ] BE-TRD-074: Implementar AlertService.create()
- [ ] BE-TRD-075: Implementar AlertMonitorService (background job)
- [ ] BE-TRD-076: Implementar NotificationService (push, email)
- [ ] BE-TRD-077: Implementar lógica de condiciones (above, below, crosses)
**Frontend:**
- [ ] FE-TRD-070: Crear componente PriceAlertsPanel.tsx
- [ ] FE-TRD-071: Crear componente CreateAlertDialog.tsx
- [ ] FE-TRD-072: Crear componente AlertCard.tsx
- [ ] FE-TRD-073: Crear componente AlertHistory.tsx
- [ ] FE-TRD-074: Implementar hook useAlerts
- [ ] FE-TRD-075: Implementar notificaciones push (Web Push API)
**Tests:**
- [ ] TEST-TRD-034: Test unitario condiciones de alertas
- [ ] TEST-TRD-035: Test integración crear/disparar alerta
- [ ] TEST-TRD-036: Test E2E flujo completo alertas
---
## Dependencias
**Depende de:**
- [ ] US-TRD-001: Ver chart - Estado: Pendiente (necesita precios)
**Bloquea:**
- Ninguna
---
## Notas Técnicas
**Endpoints involucrados:**
| Método | Endpoint | Descripción |
|--------|----------|-------------|
| POST | /trading/alerts | Crear alerta |
| GET | /trading/alerts | Listar alertas |
| PATCH | /trading/alerts/:id | Actualizar/deshabilitar alerta |
| DELETE | /trading/alerts/:id | Eliminar alerta |
| GET | /trading/alerts/history | Historial de alertas disparadas |
**Entidades/Tablas:**
```sql
CREATE TABLE trading.price_alerts (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
user_id UUID NOT NULL REFERENCES auth.users(id) ON DELETE CASCADE,
symbol VARCHAR(20) NOT NULL,
condition VARCHAR(20) NOT NULL, -- 'above', 'below', 'crosses'
target_price DECIMAL(20, 8) NOT NULL,
notification_methods JSONB DEFAULT '{"push": true, "email": true}',
message TEXT,
expires_at TIMESTAMP,
status VARCHAR(20) DEFAULT 'active', -- 'active', 'disabled', 'triggered', 'expired'
triggered_at TIMESTAMP,
triggered_price DECIMAL(20, 8),
created_at TIMESTAMP DEFAULT NOW(),
updated_at TIMESTAMP DEFAULT NOW()
);
CREATE INDEX idx_price_alerts_user_status
ON trading.price_alerts(user_id, status, symbol);
CREATE INDEX idx_price_alerts_active
ON trading.price_alerts(status, symbol)
WHERE status = 'active';
```
**Componentes UI:**
- `PriceAlertsPanel`: Panel principal
- `CreateAlertDialog`: Modal de creación
- `AlertCard`: Card de alerta individual
- `AlertHistory`: Historial de disparadas
- `ConditionSelector`: Selector de condición
**Request Body (Create):**
```typescript
{
symbol: "BTCUSDT",
condition: "above",
targetPrice: 100000.00,
notificationMethods: {
push: true,
email: true,
sms: false
},
message: "BTC hitting resistance",
expiresAt: "2025-12-06T10:00:00Z" // null para never
}
```
**Response:**
```typescript
{
alert: {
id: "uuid",
symbol: "BTCUSDT",
condition: "above",
targetPrice: 100000.00,
currentPrice: 97234.50,
distance: 2.84,
distancePercentage: 2.84,
notificationMethods: {
push: true,
email: true,
sms: false
},
message: "BTC hitting resistance",
expiresAt: "2025-12-06T10:00:00Z",
status: "active",
createdAt: "2025-12-05T10:00:00Z"
}
}
```
**Alert Monitor Logic (Background Job - cada 5 segundos):**
```typescript
const activeAlerts = await getActiveAlerts();
for (const alert of activeAlerts) {
const currentPrice = await getCurrentPrice(alert.symbol);
const previousPrice = await getPreviousPrice(alert.symbol);
let shouldTrigger = false;
switch (alert.condition) {
case 'above':
shouldTrigger = currentPrice >= alert.targetPrice;
break;
case 'below':
shouldTrigger = currentPrice <= alert.targetPrice;
break;
case 'crosses':
// Cruce desde arriba o desde abajo
const crossedFromAbove = previousPrice > alert.targetPrice && currentPrice <= alert.targetPrice;
const crossedFromBelow = previousPrice < alert.targetPrice && currentPrice >= alert.targetPrice;
shouldTrigger = crossedFromAbove || crossedFromBelow;
break;
}
if (shouldTrigger) {
await triggerAlert(alert, currentPrice);
}
// Check expiration
if (alert.expiresAt && new Date() > alert.expiresAt) {
await expireAlert(alert.id);
}
}
```
**Trigger Alert Logic:**
```typescript
async function triggerAlert(alert, price) {
// Update alert status
await updateAlert(alert.id, {
status: 'triggered',
triggeredAt: new Date(),
triggeredPrice: price
});
// Send notifications
if (alert.notificationMethods.push) {
await sendPushNotification(alert.userId, {
title: `Price Alert: ${alert.symbol}`,
body: `${alert.symbol} ${alert.condition} ${alert.targetPrice}. Current: ${price}`,
data: { alertId: alert.id, symbol: alert.symbol }
});
}
if (alert.notificationMethods.email) {
await sendEmail(alert.userId, {
subject: `Price Alert: ${alert.symbol}`,
body: renderAlertEmail(alert, price)
});
}
if (alert.notificationMethods.sms) {
await sendSMS(alert.userId, `${alert.symbol} reached ${price}`);
}
}
```
**Condiciones disponibles:**
- **above**: Se dispara cuando `currentPrice >= targetPrice`
- **below**: Se dispara cuando `currentPrice <= targetPrice`
- **crosses**: Se dispara cuando el precio cruza el nivel en cualquier dirección
**Expiration options:**
- Never
- 1 hour
- 24 hours
- 7 days
- Custom date/time
**Notification Methods:**
- Push Notification (Web Push API)
- Email
- SMS (Premium feature)
---
## 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