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>
396 lines
13 KiB
Markdown
396 lines
13 KiB
Markdown
---
|
|
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
|