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>
16 KiB
| id | title | type | status | priority | epic | story_points | created_date | updated_date |
|---|---|---|---|---|---|---|---|---|
| US-TRD-013 | Configurar Alertas de Precio | User Story | Done | Media | OQI-003 | 5 | 2025-12-05 | 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"
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"
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"
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
DADO que el usuario crea alerta "CROSSES $150" para SOLUSDT
CUANDO el precio cruza $150 desde arriba (150.10 → 149.90)
O desde abajo (149.90 → 150.10)
ENTONCES se dispara la alerta
Y notifica al usuario
Escenario 5: Deshabilitar alerta temporalmente
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
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
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:
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 principalCreateAlertDialog: Modal de creaciónAlertCard: Card de alerta individualAlertHistory: Historial de disparadasConditionSelector: Selector de condición
Request Body (Create):
{
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:
{
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):
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:
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)
- SMS (Premium feature)
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