---
id: "US-TRD-014"
title: "Resetear Balance de Paper Trading"
type: "User Story"
status: "Done"
priority: "Media"
epic: "OQI-003"
story_points: 2
created_date: "2025-12-05"
updated_date: "2026-01-04"
---

# 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
