--- id: "US-ML-010" title: "Scan Multi-Símbolo" type: "User Story" status: "Pending" priority: "Media" epic: "OQI-006" project: "trading-platform" story_points: 5 created_date: "2026-01-25" updated_date: "2026-01-25" --- # US-ML-010: Scan Multi-Símbolo ## Metadata | Campo | Valor | |-------|-------| | **ID** | US-ML-010 | | **Épica** | OQI-006 - Señales ML y Predicciones | | **Módulo** | ml-signals | | **Prioridad** | P2 (Media) | | **Story Points** | 5 | | **Sprint** | Por asignar | | **Estado** | Pendiente | | **Asignado a** | Por asignar | --- ## Historia de Usuario **Como** trader/inversor, **quiero** escanear múltiples símbolos simultáneamente en busca de señales de trading, **para** encontrar las mejores oportunidades disponibles en el mercado de forma eficiente. ## Descripción Detallada El usuario debe poder seleccionar una lista de símbolos (desde una lista predefinida, watchlist personal, o subir lista personalizada), ejecutar un escaneo que genere señales ML para todos ellos en paralelo, y visualizar los resultados filtrados y ordenados por confianza. El escaneo debe completarse en menos de 10 segundos para máximo 50 símbolos. ## Mockups/Wireframes ``` ┌──────────────────────────────────────────────────────────────────┐ │ MULTI-SYMBOL SCAN │ ├──────────────────────────────────────────────────────────────────┤ │ │ │ Symbol Selection: │ │ ┌────────────────────────────────────────────────────────────┐ │ │ │ ▼ Select from: [Popular ▼] [My Watchlist ▼] [Custom ▼] │ │ │ │ │ │ │ │ ☑ BTCUSDT ☑ ETHUSDT ☑ BNBUSDT │ │ │ │ ☑ ADAUSDT ☑ XRPUSDT ☑ DOGEUSDT │ │ │ │ ☑ MATICUSDT ☑ SOLUSDT ☑ LINKUSDT │ │ │ │ │ │ │ │ [Clear All] [Select All] [Select: 9 symbols] │ │ │ │ │ │ │ │ Or upload CSV: [Choose File] upload-symbols.csv │ │ │ └────────────────────────────────────────────────────────────┘ │ │ │ │ Filter & Sort: │ │ ┌────────────────────────────────────────────────────────────┐ │ │ │ Signal Type: [All ▼] Action: [BUY ▼] Horizon: [All ▼] │ │ │ │ Min Confidence: [50% ▼] Sort by: [Confidence ▼] │ │ │ │ │ │ │ │ [🔄 Scan Now] [⏸️ Cancel] Scanning: 7/9 │ │ │ └────────────────────────────────────────────────────────────┘ │ │ │ │ ══════════════════════════════════════════════════════════════ │ │ │ │ SCAN RESULTS - 9 Symbols, 12 Signals Found │ │ │ │ ┌────────────────────────────────────────────────────────────┐ │ │ │ Symbol Action Horizon Conf. Score Entry Status │ │ │ ├────────────────────────────────────────────────────────────┤ │ │ │ BTCUSDT 🟢 BUY Scalping 85% 9.2/10 $89,400 ✅ Ready│ │ │ │ ETHUSDT 🟢 BUY Intraday 78% 8.8/10 $3,240 ✅ Ready│ │ │ │ BNBUSDT 🟢 BUY Swing 72% 8.1/10 $620 ✅ Ready│ │ │ │ ADAUSDT 🔴 SELL Intraday 68% 7.6/10 $1.05 ✅ Ready│ │ │ │ LINKUSDT 🟢 BUY Swing 65% 7.3/10 $28.50 ✅ Ready│ │ │ │ SOLUSDT 🔵 HOLD Position 58% 6.9/10 $190.50 ⚠️ Weak │ │ │ │ XRPUSDT 🔴 SELL Scalping 55% 6.2/10 $2.45 ⚠️ Weak │ │ │ │ MATICUSDT - - - - - - ❌ NoSig│ │ │ │ DOGEUSDT - - - - - - ❌ NoSig│ │ │ └────────────────────────────────────────────────────────────┘ │ │ │ │ [View Details] [Add to Watchlist] [Export Results] │ │ │ │ SUMMARY │ │ ══════════════════════════════════════════════════════════════ │ │ Total Symbols Scanned: 9 │ │ Signals Found: 7 (77.8%) │ │ Strong Signals (>70%): 4 │ │ Weak Signals (50-70%): 3 │ │ Avg Confidence: 68.3% │ │ │ │ [Create Portfolio from BUY Signals] [Refresh Scan] │ │ │ └──────────────────────────────────────────────────────────────────┘ ┌──────────────────────────────────────────────────────────────────┐ │ SCAN PROGRESS [✕ Cancel] │ ├──────────────────────────────────────────────────────────────────┤ │ │ │ Scanning 9 symbols in parallel... │ │ │ │ ✅ BTCUSDT (2.1s) │ │ ✅ ETHUSDT (1.8s) │ │ ✅ BNBUSDT (1.5s) │ │ ⏳ ADAUSDT (Generating signal...) │ │ ⏳ XRPUSDT (Generating signal...) │ │ ⏳ LINKUSDT (Analyzing indicators...) │ │ ⏳ SOLUSDT (Analyzing indicators...) │ │ ⏳ MATICUSDT (Analyzing indicators...) │ │ ⏳ DOGEUSDT (Analyzing indicators...) │ │ │ │ Completed: 3/9 • Elapsed: 5.2s • Est. time: ~7.8s │ │ ████░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ 33% │ │ │ │ [View Real-time Feed] [Pause] [Cancel] │ │ │ └──────────────────────────────────────────────────────────────────┘ ``` --- ## Criterios de Aceptación **Escenario 1: Seleccionar símbolos desde lista predefinida** ```gherkin DADO que el usuario está en la pantalla Multi-Symbol Scan CUANDO hace click en "Popular" ENTONCES se muestran los 50 símbolos más populares/líquidos Y puede seleccionar hasta 50 símbolos con checkboxes Y se muestra el contador "Select: X symbols" ``` **Escenario 2: Usar watchlist personal** ```gherkin DADO que el usuario tiene una watchlist guardada CUANDO selecciona "My Watchlist" ENTONCES se cargan automáticamente los símbolos de la watchlist Y puede desseleccionar símbolos si lo desea Y se mantiene la selección al cambiar de filtro ``` **Escenario 3: Subir lista personalizada en CSV** ```gherkin DADO que el usuario está en Symbol Selection CUANDO hace click en "Choose File" y selecciona un CSV ENTONCES el sistema parsea el archivo (formato: 1 símbolo por línea) Y agrega los símbolos a la selección Y muestra cantidad de símbolos cargados (validando que sean correctos) Y permite deseleccionar los que no desea ``` **Escenario 4: Ejecutar escaneo multi-símbolo** ```gherkin DADO que el usuario ha seleccionado 9 símbolos Y ha configurado filtros (tipo de señal, confianza mínima) CUANDO hace click en "Scan Now" ENTONCES inicia escaneo paralelo en todos los símbolos Y muestra progreso en tiempo real (símbolos completados) Y el escaneo completa en menos de 10 segundos para 50 símbolos Y muestra "Scanning: 3/9" mientras se ejecuta ``` **Escenario 5: Ver resultados en tabla** ```gherkin DADO que el escaneo se ha completado CUANDO se muestran los resultados ENTONCES se visualiza tabla con columnas: - Símbolo - Acción (BUY/SELL/HOLD) - Horizonte - Confianza % - Score (0-10) - Precio de entrada - Estado (✅ Ready / ⚠️ Weak / ❌ No Signal) Y cada fila es clickeable para ver detalles completos ``` **Escenario 6: Filtrar resultados por confianza** ```gherkin DADO que se muestran los resultados del escaneo CUANDO selecciona "Min Confidence: 70%" ENTONCES se muestran solo señales con confianza >= 70% Y se actualiza el contador "7 of 12 signals" Y el resumen se recalcula solo para señales filtradas ``` **Escenario 7: Filtrar por tipo de señal** ```gherkin DADO que se muestran los resultados CUANDO selecciona "Action: BUY" ENTONCES muestra solo señales de compra Y se pueden combinar filtros (ej: Action=BUY AND Horizon=Scalping) ``` **Escenario 8: Ordenar por confianza** ```gherkin DADO que se muestran resultados CUANDO hace click en "Sort by: Confidence" (descendente) ENTONCES la tabla se ordena con señales más confiables primero Y se puede invertir el orden (ascendente/descendente) Y se pueden ordenar también por Score, Símbolo, etc. ``` **Escenario 9: Exportar resultados** ```gherkin DADO que se muestran los resultados del escaneo CUANDO hace click en "Export Results" ENTONCES descarga archivo CSV con: - Symbol, Action, Horizon, Confidence, Score, Entry Price - Nombre: "scan-results-2026-01-25-09-30.csv" ``` **Escenario 10: Crear portfolio desde resultados** ```gherkin DADO que se muestran resultados del escaneo CUANDO hace click en "Create Portfolio from BUY Signals" ENTONCES se abre modal para crear nuevo portfolio Y se preseleccionan automáticamente todos los BUY signals Y el usuario puede ajustar pesos y confirmar creación ``` ## Criterios Adicionales - [ ] El escaneo debe soportar máximo 50 símbolos simultáneamente - [ ] El tiempo máximo debe ser menor a 10 segundos - [ ] Los resultados deben mostrarse ordenados por confianza descendente - [ ] El CSV debe ser válido y con header - [ ] Debe mostrar progreso en tiempo real durante el escaneo - [ ] Debe manejar símbolos inválidos (ignorarlos o marcar con error) - [ ] La tabla debe ser responsive en móvil - [ ] Los filtros deben ser combinables --- ## Tareas Técnicas **Backend:** - [ ] BE-ML-020: Crear endpoint POST /api/ml/scan - [ ] BE-ML-021: Implementar worker para escaneo paralelo (queue-based) - [ ] BE-ML-022: Validar símbolos de entrada - [ ] BE-ML-023: Parsear CSV de símbolos - [ ] BE-ML-024: Implementar filtros (action, horizon, confidence_min) - [ ] BE-ML-025: Generar respuesta con resultados ordenados - [ ] BE-ML-026: Implementar export a CSV **Frontend:** - [ ] FE-ML-040: Crear componente `MultiSymbolScan.tsx` - [ ] FE-ML-041: Crear componente `SymbolSelector.tsx` - [ ] FE-ML-042: Crear componente `ScanFilters.tsx` - [ ] FE-ML-043: Crear componente `ScanResults.tsx` - [ ] FE-ML-044: Crear componente `ScanProgress.tsx` - [ ] FE-ML-045: Implementar upload de CSV - [ ] FE-ML-046: Implementar tabla con sorting y filtros - [ ] FE-ML-047: Implementar export a CSV - [ ] FE-ML-048: Integración con TanStack Query (react-query) - [ ] FE-ML-049: Real-time progress updates (WebSocket/SSE) **ML Engine:** - [ ] ML-020: Optimizar generación de señales para múltiples símbolos - [ ] ML-021: Implementar ejecución paralela de análisis - [ ] ML-022: Cachear indicadores técnicos por símbolo **Tests:** - [ ] TEST-ML-020: Test de validación de símbolos - [ ] TEST-ML-021: Test de parseo CSV - [ ] TEST-ML-022: Test de escaneo paralelo (timeout, errores) - [ ] TEST-ML-023: Test de filtrado y ordenamiento - [ ] TEST-ML-024: Test E2E completo del multi-scan --- ## Dependencias **Depende de:** - [ ] US-ML-002: Ver señal - Estado: Pendiente - [ ] RF-ML-001: Generación de señales ML - [ ] Infrastructure: Worker queue (Bull/RabbitMQ) **Bloquea:** - [ ] US-ML-011: Alertas de señales (requiere resultados del scan) - [ ] US-ML-012: Portfolio builder (requiere scan multi-símbolo) --- ## Notas Técnicas **Endpoints involucrados:** | Método | Endpoint | Descripción | |--------|----------|-------------| | POST | /api/ml/scan | Ejecutar escaneo multi-símbolo | | GET | /api/ml/scan/:scanId/progress | Obtener progreso en tiempo real | | GET | /api/ml/scan/:scanId/results | Obtener resultados del escaneo | | GET | /api/ml/scan/:scanId/export.csv | Exportar resultados a CSV | | GET | /api/symbols/popular | Lista de símbolos populares | | GET | /api/watchlists/:id/symbols | Símbolos de watchlist | **Request esperado:** ```typescript interface MultiSymbolScanRequest { symbols: string[]; // Array de símbolos (ej: ['BTCUSDT', 'ETHUSDT']) filters: { signal_type?: 'BUY' | 'SELL' | 'HOLD' | 'ALL'; horizon?: string; confidence_min?: number; // 0-100 action?: 'BUY' | 'SELL'; }; sort_by?: 'confidence' | 'score' | 'symbol'; sort_order?: 'asc' | 'desc'; } ``` **Response esperado:** ```typescript interface MultiSymbolScanResponse { scan_id: string; status: 'completed' | 'in_progress' | 'failed'; timestamp: string; symbols_scanned: number; signals_found: number; results: SignalResult[]; summary: { total_symbols: number; signals_found: number; strong_signals: number; // confidence >= 70% weak_signals: number; // 50% <= confidence < 70% avg_confidence: number; }; execution_time_ms: number; } interface SignalResult { symbol: string; action: 'BUY' | 'SELL' | 'HOLD' | null; horizon?: string; confidence?: number; score?: number; entry_price?: number; status: 'ready' | 'weak' | 'no_signal' | 'error'; error_message?: string; } ``` **CSV Upload Parser:** ```typescript // Soporta formatos: // 1. Un símbolo por línea (simple) BTCUSDT ETHUSDT BNBUSDT // 2. CSV con header Symbol,Exchange,Type BTCUSDT,BINANCE,SPOT ETHUSDT,BINANCE,SPOT ``` **Componentes UI:** - `MultiSymbolScan`: Container principal - `SymbolSelector`: Selector de símbolos con pestañas - `SymbolListPicker`: Selector desde lista predefinida - `WatchlistPicker`: Selector desde watchlist personal - `CSVUploader`: Componente de upload de CSV - `ScanFilters`: Filtros de escaneo - `ScanResults`: Tabla de resultados - `ScanProgress`: Modal de progreso en tiempo real - `ResultsActions`: Acciones sobre resultados (export, create portfolio) **Estado (Zustand):** ```typescript interface MultiSymbolScanStore { selectedSymbols: string[]; scanResults: SignalResult[]; scanProgress: { total: number; completed: number; currentSymbol: string; }; filters: ScanFilters; isScanning: boolean; sortBy: 'confidence' | 'score' | 'symbol'; sortOrder: 'asc' | 'desc'; setSelectedSymbols: (symbols: string[]) => void; startScan: () => Promise; updateProgress: (progress: ScanProgress) => void; updateFilters: (filters: Partial) => void; setSortBy: (field: string, order: 'asc' | 'desc') => void; exportToCSV: () => void; } ``` **Real-time Progress:** - Usar WebSocket o SSE para enviar actualizaciones de progreso - Endpoint: `/api/ml/scan/:scanId/progress` con streaming - O usar polling cada 500ms si WebSocket no disponible **Performance Targets:** - 50 símbolos scanned: < 10 segundos - 20 símbolos scanned: < 5 segundos - 10 símbolos scanned: < 3 segundos --- ## Definition of Ready (DoR) - [x] Historia claramente escrita (quién, qué, por qué) - [x] Criterios de aceptación definidos - [x] Story points estimados - [x] Dependencias identificadas - [x] Diseño/mockup disponible - [x] Targets de performance definidos - [x] Formatos de datos especificados ## Definition of Done (DoD) - [ ] Código implementado según criterios - [ ] Tests unitarios escritos y pasando - [ ] Tests E2E pasando - [ ] Code review aprobado - [ ] Documentación actualizada - [ ] QA aprobado en staging - [ ] Escaneo paralelo funciona correctamente - [ ] Real-time progress updates funcionan - [ ] CSV upload y export validan correctamente - [ ] Filtros y ordenamiento funcionan - [ ] Performance meets targets (< 10s para 50 símbolos) - [ ] Manejo de errores robusto (símbolos inválidos, timeouts) - [ ] Responsive en móvil - [ ] Desplegado en producción --- ## Historial de Cambios | Fecha | Cambio | Autor | |-------|--------|-------| | 2026-01-25 | Creación | Requirements-Analyst | --- **Creada por:** Requirements-Analyst **Fecha:** 2026-01-25 **Última actualización:** 2026-01-25