trading-platform/docs/02-definicion-modulos/OQI-003-trading-charts/historias-usuario/US-TRD-014-reset-balance.md

384 lines
13 KiB
Markdown

# 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