trading-platform/docs/02-definicion-modulos/OQI-004-investment-accounts/requerimientos/RF-INV-004-retiros.md
rckrdmrd a7cca885f0 feat: Major platform documentation and architecture updates
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>
2026-01-07 05:33:35 -06:00

10 KiB

id title type status priority epic project version created_date updated_date
RF-INV-004 Sistema de Retiros Requirement Done Alta OQI-004 trading-platform 1.0.0 2025-12-05 2026-01-04

RF-INV-004: Sistema de Retiros

Metadata

Campo Valor
ID RF-INV-004
Épica OQI-004 - Cuentas de Inversión
Tipo Requerimiento Funcional
Prioridad P0
Story Points 10
Estado Aprobado
Última actualización 2025-12-05

Descripción

El sistema debe permitir a los usuarios retirar fondos de sus cuentas de inversión hacia su wallet interno o directamente a su cuenta bancaria/tarjeta, con validaciones de seguridad y procesamiento seguro.


Destinos de Retiro

1. Wallet Interno

Característica Valor
Mínimo $10 USD
Máximo Balance disponible
Comisión Sin comisión
Tiempo procesamiento Instantáneo
Disponibilidad Inmediata para re-inversión o retiro externo

2. Stripe (Payout a banco/tarjeta)

Característica Valor
Mínimo $50 USD
Máximo $25,000 USD
Comisión 0.25% (mín $0.25)
Tiempo procesamiento 2-5 días hábiles
Requisito Cuenta bancaria o tarjeta débito verificada

Balance Disponible vs Total

┌─────────────────────────────────────────────────────────────┐
│                    BALANCE DE CUENTA                         │
├─────────────────────────────────────────────────────────────┤
│                                                              │
│   Balance Total = Balance Disponible + Balance Bloqueado    │
│                                                              │
│   ┌──────────────────┐    ┌────────────────────────────┐   │
│   │ DISPONIBLE       │    │ BLOQUEADO                   │   │
│   │                  │    │                             │   │
│   │ • Para retiro    │    │ • Margin usado en trades    │   │
│   │ • Para trading   │    │ • Retiros pendientes        │   │
│   │                  │    │ • Reservas de seguridad     │   │
│   └──────────────────┘    └────────────────────────────┘   │
│                                                              │
└─────────────────────────────────────────────────────────────┘

Cálculo de Balance Disponible

availableBalance = totalBalance
  - unrealizedPnl  // P&L no realizado de posiciones abiertas
  - marginUsed     // Margen usado en posiciones abiertas
  - pendingWithdrawals  // Retiros en proceso
  - reserveAmount  // Reserva mínima (5% del balance)

Flujo de Retiro

Diagrama de Flujo

┌─────────┐     ┌──────────┐     ┌──────────┐     ┌──────────┐
│ Request │────▶│ Validate │────▶│ Security │────▶│ Process  │
│ Withdraw│     │  Amount  │     │  Check   │     │ Withdraw │
└─────────┘     └──────────┘     └──────────┘     └────┬─────┘
                                                       │
                    ┌──────────────────────────────────┘
                    ▼
              ┌──────────┐     ┌──────────┐     ┌──────────┐
              │ Confirm  │────▶│ Transfer │────▶│  Notify  │
              │  Email   │     │  Funds   │     │   User   │
              └──────────┘     └──────────┘     └──────────┘

Estados de Retiro

Estado Descripción
pending_confirmation Esperando confirmación por email
pending Confirmado, esperando procesamiento
processing En proceso de transferencia
completed Fondos transferidos
failed Error en procesamiento
cancelled Cancelado por usuario

Funcionalidades Requeridas

RF-INV-004.1: Solicitar Retiro

El usuario debe poder:

  • Ver balance disponible para retiro
  • Seleccionar destino (wallet o payout)
  • Ingresar monto a retirar
  • Ver resumen con comisiones
  • Confirmar solicitud

RF-INV-004.2: Verificación de Seguridad

Para retiros, el sistema debe validar:

  • Confirmación por email (link válido por 1 hora)
  • 2FA si está habilitado
  • Límites diarios no excedidos
  • Cuenta no en proceso de cierre

RF-INV-004.3: Retiro a Wallet

interface WalletWithdrawalRequest {
  accountId: string;           // Cuenta de inversión origen
  amount: number;              // Monto en USD
}

interface WalletWithdrawalResponse {
  withdrawalId: string;
  status: 'completed';
  amount: number;
  fee: 0;
  newAccountBalance: number;
  newWalletBalance: number;
}

RF-INV-004.4: Retiro Externo (Stripe Payout)

interface ExternalWithdrawalRequest {
  accountId: string;
  amount: number;
  payoutMethodId: string;      // Stripe connected account o método guardado
}

interface ExternalWithdrawalResponse {
  withdrawalId: string;
  status: 'pending';
  amount: number;
  fee: number;
  netAmount: number;
  estimatedArrival: Date;      // 2-5 días hábiles
}

RF-INV-004.5: Límites y Validaciones

Validación Límite Mensaje de Error
Mínimo wallet $10 "El monto mínimo para retiro a wallet es $10"
Mínimo externo $50 "El monto mínimo para retiro externo es $50"
Máximo diario $25,000 "Has alcanzado el límite diario de retiros"
Balance insuficiente - "Balance disponible insuficiente"
Posiciones abiertas - "Debes cerrar posiciones antes de retirar todo"

Modelo de Datos

Entidad: WithdrawalTransaction

interface WithdrawalTransaction {
  id: string;                   // UUID
  accountId: string;            // FK a investment_accounts
  userId: string;               // FK a users

  destination: 'wallet' | 'bank' | 'card';
  status: WithdrawalStatus;

  // Montos
  amount: number;               // Monto solicitado
  fee: number;                  // Comisión
  netAmount: number;            // Monto a recibir
  currency: 'USD';

  // Stripe specific
  stripePayoutId?: string;
  stripeTransferId?: string;

  // Wallet specific
  walletTransactionId?: string;

  // Seguridad
  confirmationToken?: string;
  confirmedAt?: Date;
  confirmationIp?: string;

  // Metadata
  ipAddress: string;
  userAgent: string;

  // Timestamps
  createdAt: Date;
  processedAt?: Date;
  completedAt?: Date;
  failedAt?: Date;
  cancelledAt?: Date;

  // Error handling
  failureReason?: string;
}

Reglas de Negocio

  1. RN-030: Los retiros requieren confirmación por email
  2. RN-031: No se puede retirar más del balance disponible
  3. RN-032: Retiro total requiere cerrar posiciones abiertas primero
  4. RN-033: Límite diario de $25,000 USD en retiros
  5. RN-034: Retiros a wallet son instantáneos
  6. RN-035: Retiros externos tienen período de espera de 2-5 días
  7. RN-036: Los retiros pueden cancelarse antes de ser procesados
  8. RN-037: Cooldown de 24 horas para retiro después de agregar nuevo método de pago

Criterios de Aceptación

Escenario: Retiro a wallet exitoso
DADO que el usuario tiene $1,000 disponibles en su cuenta Atlas
CUANDO solicita retirar $500 a su wallet
Y confirma por email
ENTONCES el balance de la cuenta disminuye en $500
Y el balance del wallet aumenta en $500
Y no se cobra comisión
Y recibe confirmación instantánea

Escenario: Retiro externo exitoso
DADO que el usuario tiene cuenta bancaria verificada
Y tiene $5,000 disponibles en su cuenta
CUANDO solicita retirar $1,000 a su banco
Y confirma por email
ENTONCES el retiro queda en estado "processing"
Y se muestra fecha estimada de llegada
Y recibe email cuando los fondos se envíen

Escenario: Retiro supera límite diario
DADO que el usuario ya retiró $20,000 hoy
CUANDO intenta retirar $10,000 adicionales
ENTONCES recibe error "Has alcanzado el límite diario de retiros"
Y se muestra cuándo se reinicia el límite

Escenario: Retiro con posiciones abiertas
DADO que el usuario tiene $1,000 disponibles
Y tiene $200 en margen usado por posiciones abiertas
CUANDO intenta retirar $900
ENTONCES recibe error "Balance disponible insuficiente"
Y ve que su balance disponible es $800
Y tiene opción de ver posiciones abiertas

API Endpoints

Método Endpoint Descripción
GET /investment/withdrawals/available Ver balance disponible
POST /investment/withdrawals/wallet Retirar a wallet
POST /investment/withdrawals/payout Retirar externo
GET /investment/withdrawals Listar retiros
GET /investment/withdrawals/:id Detalle de retiro
POST /investment/withdrawals/:id/confirm Confirmar retiro
DELETE /investment/withdrawals/:id Cancelar retiro

Notificaciones

Evento Canal Contenido
Retiro solicitado Email Link de confirmación
Retiro confirmado Email + Push Confirmación y ETA
Retiro procesado Email + Push Fondos en camino
Retiro completado Email Fondos recibidos
Retiro fallido Email + Push Razón + pasos a seguir

Referencias


Autor: Requirements-Analyst Fecha: 2025-12-05