# US-TRD-014: Resetear Balance de Paper Trading ## Metadata | Campo | Valor | |-------|-------| | **ID** | US-TRD-014 | | **Épica** | OQI-003 - Trading y Charts | | **Módulo** | trading | | **Prioridad** | P2 | | **Story Points** | 1 | | **Sprint** | Sprint 6 | | **Estado** | Pendiente | | **Asignado a** | Por asignar | --- ## Historia de Usuario **Como** trader practicante, **quiero** resetear mi balance de paper trading a $10,000, **para** empezar de nuevo con una cuenta limpia y practicar con nuevas estrategias. ## Descripción Detallada El usuario debe poder resetear completamente su cuenta de paper trading, eliminando todas las posiciones abiertas, órdenes pendientes, y restaurando el balance a $10,000 USD. Esta funcionalidad es útil cuando el usuario quiere empezar de cero o después de hacer pruebas extensivas. ## Mockups/Wireframes ``` ┌─────────────────────────────────────────────────────────────────┐ │ ACCOUNT SETTINGS - Paper Trading │ ├─────────────────────────────────────────────────────────────────┤ │ │ │ Current Balance: $8,456.78 │ │ Equity: $8,567.23 │ │ Open Positions: 3 │ │ Pending Orders: 2 │ │ Total Trades: 67 │ │ │ │ ┌────────────────────────────────────────────────────────────┐ │ │ │ ⚠ RESET ACCOUNT │ │ │ ├────────────────────────────────────────────────────────────┤ │ │ │ │ │ │ │ Reset your paper trading account to start fresh: │ │ │ │ │ │ │ │ This action will: │ │ │ │ ✓ Close all open positions (3) │ │ │ │ ✓ Cancel all pending orders (2) │ │ │ │ ✓ Reset balance to $10,000.00 │ │ │ │ ✓ Clear trade history (67 trades) │ │ │ │ ✓ Reset statistics │ │ │ │ │ │ │ │ ⚠ This action CANNOT be undone! │ │ │ │ │ │ │ │ [Reset Account] │ │ │ └────────────────────────────────────────────────────────────┘ │ └─────────────────────────────────────────────────────────────────┘ ┌─────────────────────────────────────┐ │ CONFIRM ACCOUNT RESET │ ├─────────────────────────────────────┤ │ Are you sure you want to reset │ │ your paper trading account? │ │ │ │ You will lose: │ │ • All open positions (3) │ │ • All pending orders (2) │ │ • Trade history (67 trades) │ │ • All statistics │ │ │ │ Your account will be reset to: │ │ • Balance: $10,000.00 │ │ • No positions │ │ • No history │ │ │ │ Type "RESET" to confirm: │ │ ┌─────────────────────────────────┐ │ │ │ │ │ │ └─────────────────────────────────┘ │ │ │ │ [Cancel] [Confirm Reset] │ └─────────────────────────────────────┘ ``` --- ## Criterios de Aceptación **Escenario 1: Reset exitoso con confirmación** ```gherkin DADO que el usuario tiene: - Balance: $8,456.78 - 3 posiciones abiertas - 2 órdenes pendientes - 67 trades en historial CUANDO hace click en "Reset Account" Y confirma escribiendo "RESET" Y hace click en "Confirm Reset" ENTONCES se cierran todas las posiciones Y se cancelan todas las órdenes Y el balance se resetea a $10,000.00 Y el historial se limpia Y las estadísticas se resetean Y se muestra mensaje "Account reset successfully" ``` **Escenario 2: Cancelar reset** ```gherkin DADO que el usuario abre el diálogo de reset CUANDO hace click en "Cancel" ENTONCES no se realiza ningún cambio Y el diálogo se cierra Y el balance permanece igual ``` **Escenario 3: Validación de confirmación** ```gherkin DADO que el usuario está en el diálogo de reset CUANDO no escribe "RESET" correctamente ENTONCES el botón "Confirm Reset" está deshabilitado Y no puede proceder CUANDO escribe "RESET" exactamente ENTONCES el botón se habilita Y puede confirmar ``` **Escenario 4: Reset sin posiciones abiertas** ```gherkin DADO que el usuario no tiene posiciones ni órdenes Y solo quiere resetear el balance CUANDO ejecuta el reset ENTONCES el balance se restaura a $10,000 Y el historial se limpia Y se muestra mensaje confirmando el reset ``` **Escenario 5: Cooldown period** ```gherkin DADO que el usuario acaba de resetear su cuenta CUANDO intenta resetear nuevamente inmediatamente ENTONCES se muestra mensaje "You can reset again in 23:59:45" Y el botón "Reset Account" está deshabilitado por 24 horas ``` ## Criterios Adicionales - [ ] Cooldown de 24 horas entre resets - [ ] Backup automático antes de reset (último estado) - [ ] Email de confirmación después del reset - [ ] Opción de "Undo" durante 5 minutos después del reset - [ ] Contador de resets en perfil de usuario --- ## Tareas Técnicas **Database:** - [ ] DB-TRD-023: Crear tabla trading.account_resets - Campos: id, user_id, previous_balance, reset_at - [ ] DB-TRD-024: Añadir soft delete a trades (backup) **Backend:** - [ ] BE-TRD-078: Crear endpoint POST /trading/paper/reset - [ ] BE-TRD-079: Implementar AccountResetService.reset() - [ ] BE-TRD-080: Cerrar todas las posiciones - [ ] BE-TRD-081: Cancelar todas las órdenes pendientes - [ ] BE-TRD-082: Limpiar/archivar historial - [ ] BE-TRD-083: Resetear balance a $10,000 - [ ] BE-TRD-084: Implementar cooldown de 24 horas - [ ] BE-TRD-085: Crear backup antes del reset **Frontend:** - [ ] FE-TRD-076: Crear componente AccountSettings.tsx - [ ] FE-TRD-077: Crear componente ResetAccountDialog.tsx - [ ] FE-TRD-078: Crear componente ConfirmResetDialog.tsx - [ ] FE-TRD-079: Implementar hook useResetAccount - [ ] FE-TRD-080: Implementar countdown para cooldown **Tests:** - [ ] TEST-TRD-037: Test unitario reset completo - [ ] TEST-TRD-038: Test integración reset con posiciones - [ ] TEST-TRD-039: Test E2E flujo completo reset --- ## Dependencias **Depende de:** - [ ] US-TRD-006: Crear orden - Estado: Pendiente - [ ] US-TRD-008: Cerrar posición - Estado: Pendiente **Bloquea:** - Ninguna --- ## Notas Técnicas **Endpoints involucrados:** | Método | Endpoint | Descripción | |--------|----------|-------------| | POST | /trading/paper/reset | Resetear cuenta | | GET | /trading/paper/reset/status | Verificar si puede resetear | **Entidades/Tablas:** ```sql CREATE TABLE trading.account_resets ( id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), user_id UUID NOT NULL REFERENCES auth.users(id), previous_balance DECIMAL(20, 8) NOT NULL, previous_equity DECIMAL(20, 8) NOT NULL, open_positions INTEGER DEFAULT 0, pending_orders INTEGER DEFAULT 0, total_trades INTEGER DEFAULT 0, reset_at TIMESTAMP DEFAULT NOW() ); CREATE INDEX idx_account_resets_user ON trading.account_resets(user_id, reset_at DESC); -- Para cooldown ALTER TABLE auth.users ADD COLUMN last_reset_at TIMESTAMP; ``` **Componentes UI:** - `AccountSettings`: Página de configuración - `ResetAccountDialog`: Diálogo principal - `ConfirmResetDialog`: Modal de confirmación - `CooldownTimer`: Timer de cooldown **Request Body:** ```typescript { confirmation: "RESET" } ``` **Response (Reset):** ```typescript { success: true, previousState: { balance: 8456.78, equity: 8567.23, openPositions: 3, pendingOrders: 2, totalTrades: 67 }, newState: { balance: 10000.00, equity: 10000.00, openPositions: 0, pendingOrders: 0, totalTrades: 0 }, resetAt: "2025-12-05T10:00:00Z", nextResetAvailableAt: "2025-12-06T10:00:00Z" } ``` **Response (Status):** ```typescript { canReset: false, lastResetAt: "2025-12-05T10:00:00Z", nextResetAvailableAt: "2025-12-06T10:00:00Z", cooldownRemaining: 82800 // segundos } ``` **Reset Process:** ```typescript async function resetAccount(userId: string) { // 1. Verificar cooldown const lastReset = await getLastResetTime(userId); if (lastReset && Date.now() - lastReset < 24 * 60 * 60 * 1000) { throw new Error('Cooldown active'); } // 2. Crear backup del estado actual const currentState = await getCurrentAccountState(userId); await createBackup(userId, currentState); // 3. Cerrar todas las posiciones const positions = await getOpenPositions(userId); for (const position of positions) { await closePosition(position.id, 'account_reset'); } // 4. Cancelar todas las órdenes const orders = await getPendingOrders(userId); for (const order of orders) { await cancelOrder(order.id); } // 5. Archivar historial (soft delete) await archiveTradeHistory(userId); // 6. Resetear balance await updateBalance(userId, 10000.00); // 7. Resetear estadísticas await resetStatistics(userId); // 8. Registrar reset await createResetRecord(userId, currentState); // 9. Actualizar timestamp de último reset await updateLastResetTime(userId, new Date()); // 10. Enviar email de confirmación await sendResetConfirmationEmail(userId); return { success: true, previousState: currentState, newState: { balance: 10000.00, equity: 10000.00, openPositions: 0, pendingOrders: 0 } }; } ``` **Cooldown Calculation:** ```typescript const COOLDOWN_MS = 24 * 60 * 60 * 1000; // 24 horas function getCooldownStatus(lastResetAt: Date) { const now = Date.now(); const lastReset = lastResetAt.getTime(); const nextAvailable = lastReset + COOLDOWN_MS; const remaining = Math.max(0, nextAvailable - now); return { canReset: remaining === 0, lastResetAt, nextResetAvailableAt: new Date(nextAvailable), cooldownRemaining: Math.floor(remaining / 1000) }; } ``` --- ## 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