trading-platform/docs/02-definicion-modulos/OQI-003-trading-charts/historias-usuario/US-TRD-015-exportar-trades.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

15 KiB

id title type status priority epic story_points created_date updated_date
US-TRD-015 Exportar Historial de Trades a CSV User Story Done Media OQI-003 3 2025-12-05 2026-01-04

US-TRD-015: Exportar Historial de Trades a CSV

Metadata

Campo Valor
ID US-TRD-015
Épica OQI-003 - Trading y Charts
Módulo trading
Prioridad P2
Story Points 2
Sprint Sprint 6
Estado Pendiente
Asignado a Por asignar

Historia de Usuario

Como trader practicante, quiero exportar mi historial de trades a formato CSV, para analizarlo en Excel u otras herramientas externas y llevar un registro personal.

Descripción Detallada

El usuario debe poder descargar su historial completo de trades (o filtrado) en formato CSV, incluyendo todos los detalles relevantes: fechas, símbolos, precios, P&L, duración, etc. Esto permite análisis externo y mantener registros personales.

Mockups/Wireframes

┌─────────────────────────────────────────────────────────────────┐
│  TRADE HISTORY                                                  │
├─────────────────────────────────────────────────────────────────┤
│  Filters:                                                        │
│  Date Range: [Last 30 days ▼]  Symbol: [All ▼]  Side: [All ▼] │
│  Result: [All ▼]  [🔍 Search]  [📥 Export CSV]                 │
│                                                 └─────────────┘  │
│                                                                  │
│  ┌────────────────────────────────────────────────────────────┐ │
│  │ EXPORT TO CSV                                              │ │
│  ├────────────────────────────────────────────────────────────┤ │
│  │                                                             │ │
│  │ Export Options:                                            │ │
│  │                                                             │ │
│  │ Date Range:                                                │ │
│  │ ○ Current filter (Last 30 days - 45 trades)               │ │
│  │ ○ Custom range                                             │ │
│  │   From: [2025-11-01] To: [2025-12-05]                     │ │
│  │ ○ All time (127 trades)                                    │ │
│  │                                                             │ │
│  │ Include Columns:                                           │ │
│  │ [✓] Trade ID                                               │ │
│  │ [✓] Symbol                                                 │ │
│  │ [✓] Side (Long/Short)                                      │ │
│  │ [✓] Entry Price                                            │ │
│  │ [✓] Exit Price                                             │ │
│  │ [✓] Quantity                                               │ │
│  │ [✓] P&L (USD)                                              │ │
│  │ [✓] P&L (%)                                                │ │
│  │ [✓] Opened At                                              │ │
│  │ [✓] Closed At                                              │ │
│  │ [✓] Duration                                               │ │
│  │ [✓] Close Reason                                           │ │
│  │ [ ] Entry Order ID                                         │ │
│  │ [ ] Exit Order ID                                          │ │
│  │                                                             │ │
│  │ Format:                                                    │ │
│  │ ○ CSV (Comma-separated)                                    │ │
│  │ ○ CSV (Semicolon-separated - Excel Europe)                │ │
│  │ ○ TSV (Tab-separated)                                      │ │
│  │                                                             │ │
│  │ File name:                                                 │ │
│  │ ┌─────────────────────────────────────────────────────┐   │ │
│  │ │ trades_2025-11-05_to_2025-12-05.csv                 │   │ │
│  │ └─────────────────────────────────────────────────────┘   │ │
│  │                                                             │ │
│  │ Estimated file size: ~15 KB (45 trades)                   │ │
│  │                                                             │ │
│  │  [Cancel]  [Download CSV]                                  │ │
│  └────────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────┘

Criterios de Aceptación

Escenario 1: Exportar con filtros actuales

DADO que el usuario tiene filtro "Last 30 days" activo
Y hay 45 trades en ese rango
CUANDO hace click en "Export CSV"
Y selecciona "Current filter"
Y hace click en "Download CSV"
ENTONCES se descarga archivo trades_2025-11-05_to_2025-12-05.csv
Y contiene 45 trades + 1 línea de headers
Y las columnas corresponden a las seleccionadas

Escenario 2: Exportar rango personalizado

DADO que el usuario abre el diálogo de export
CUANDO selecciona "Custom range"
Y elige From: 2025-10-01, To: 2025-10-31
Y hay 23 trades en octubre
Y hace click en "Download CSV"
ENTONCES se descarga archivo con 23 trades de octubre
Y el nombre refleja las fechas: trades_2025-10-01_to_2025-10-31.csv

Escenario 3: Exportar todo el historial

DADO que el usuario tiene 127 trades en total
CUANDO selecciona "All time"
Y descarga
ENTONCES se exportan los 127 trades
Y el archivo se llama trades_all_time.csv

Escenario 4: Seleccionar columnas específicas

DADO que el usuario abre opciones de export
CUANDO desmarca "Entry Order ID" y "Exit Order ID"
Y solo deja las columnas principales marcadas
Y descarga
ENTONCES el CSV contiene solo las columnas seleccionadas
Y no incluye las columnas desmarcadas

Escenario 5: Formato separador para Excel Europa

DADO que el usuario usa Excel con configuración europea
CUANDO selecciona formato "CSV (Semicolon-separated)"
Y descarga
ENTONCES el archivo usa punto y coma como separador
Y los decimales usan coma (ej: 123,45 en lugar de 123.45)

Escenario 6: Validar contenido del CSV

DADO que se exporta un archivo CSV
CUANDO se abre el archivo
ENTONCES contiene:
  - Primera línea: Headers de columnas
  - Líneas siguientes: Datos de trades
  - Formato de fechas: YYYY-MM-DD HH:MM:SS
  - Formato de precios: Con 2 decimales
  - Formato de P&L: Con signo +/- y 2 decimales
  - Sin errores de encoding (UTF-8)

Criterios Adicionales

  • Máximo 1000 trades por exportación
  • Progreso de descarga para archivos grandes
  • Opción de incluir resumen estadístico al final
  • Exportar también a JSON (futuro)
  • Exportar también a Excel XLSX (futuro)

Tareas Técnicas

Database:

  • No requiere cambios en DB

Backend:

  • BE-TRD-086: Crear endpoint GET /trading/paper/trades/export/csv
  • BE-TRD-087: Implementar ExportService.generateCSV()
  • BE-TRD-088: Implementar diferentes formatos (comma, semicolon, tab)
  • BE-TRD-089: Implementar conversión de decimales según formato
  • BE-TRD-090: Optimizar queries para exportaciones grandes
  • BE-TRD-091: Implementar streaming para archivos grandes

Frontend:

  • FE-TRD-081: Crear componente ExportCSVDialog.tsx
  • FE-TRD-082: Crear componente ColumnSelector.tsx
  • FE-TRD-083: Crear componente FormatSelector.tsx
  • FE-TRD-084: Implementar hook useExportTrades
  • FE-TRD-085: Implementar descarga de archivo blob

Tests:

  • TEST-TRD-040: Test unitario generación CSV
  • TEST-TRD-041: Test integración export endpoint
  • TEST-TRD-042: Test E2E descarga archivo

Dependencias

Depende de:

  • US-TRD-010: Ver historial - Estado: Pendiente

Bloquea:

  • Ninguna

Notas Técnicas

Endpoints involucrados:

Método Endpoint Descripción
GET /trading/paper/trades/export/csv Exportar CSV
GET /trading/paper/trades/export/json Exportar JSON (futuro)

Componentes UI:

  • ExportCSVDialog: Modal de opciones de export
  • ColumnSelector: Checklist de columnas
  • FormatSelector: Radio buttons de formato
  • DateRangePicker: Selector de rango

Query Parameters:

{
  dateFrom: "2025-11-05",
  dateTo: "2025-12-05",
  symbol: "BTCUSDT",      // opcional
  side: "long",            // opcional
  result: "win",           // opcional
  columns: ["id", "symbol", "side", "entry_price", "exit_price", "quantity", "pnl", "pnl_percentage", "opened_at", "closed_at", "duration", "close_reason"],
  format: "csv",           // csv, csv-semicolon, tsv
  locale: "en-US"          // en-US, es-ES, etc.
}

CSV Headers:

Trade ID,Symbol,Side,Entry Price,Exit Price,Quantity,P&L (USD),P&L (%),Opened At,Closed At,Duration,Close Reason

CSV Example (Comma-separated, en-US):

Trade ID,Symbol,Side,Entry Price,Exit Price,Quantity,P&L (USD),P&L (%),Opened At,Closed At,Duration,Close Reason
550e8400-e29b-41d4-a716-446655440000,BTCUSDT,long,95000.00,97234.50,0.10,+223.45,+2.35,2025-12-05 08:00:00,2025-12-05 10:30:00,2h 30m,manual
660e8400-e29b-41d4-a716-446655440001,ETHUSDT,long,3800.00,3750.00,2.50,-125.00,-1.32,2025-12-04 14:15:00,2025-12-04 19:35:00,5h 20m,stop_loss
770e8400-e29b-41d4-a716-446655440002,SOLUSDT,short,145.00,142.73,10.00,+22.70,+1.56,2025-12-03 09:00:00,2025-12-04 12:45:00,1d 3h 45m,take_profit

CSV Example (Semicolon-separated, es-ES):

Trade ID;Symbol;Side;Entry Price;Exit Price;Quantity;P&L (USD);P&L (%);Opened At;Closed At;Duration;Close Reason
550e8400-e29b-41d4-a716-446655440000;BTCUSDT;long;95000,00;97234,50;0,10;+223,45;+2,35;2025-12-05 08:00:00;2025-12-05 10:30:00;2h 30m;manual

Backend Implementation:

async function generateCSV(params) {
  const {
    dateFrom,
    dateTo,
    columns,
    format,
    locale
  } = params;

  // Obtener trades
  const trades = await getTradesForExport(params);

  // Configuración según formato
  const config = {
    delimiter: format === 'csv-semicolon' ? ';' : (format === 'tsv' ? '\t' : ','),
    decimalSeparator: locale.startsWith('es') ? ',' : '.',
    dateFormat: 'YYYY-MM-DD HH:mm:ss'
  };

  // Headers
  const headers = columns.map(col => COLUMN_LABELS[col]);
  let csv = headers.join(config.delimiter) + '\n';

  // Data rows
  for (const trade of trades) {
    const row = columns.map(col => {
      const value = formatValue(trade[col], col, config);
      return escapeCSV(value, config.delimiter);
    });
    csv += row.join(config.delimiter) + '\n';
  }

  return csv;
}

function formatValue(value, column, config) {
  if (value === null || value === undefined) return '';

  switch (column) {
    case 'pnl':
    case 'pnl_percentage':
      const sign = value >= 0 ? '+' : '';
      const formatted = value.toFixed(2);
      return sign + (config.decimalSeparator === ',' ? formatted.replace('.', ',') : formatted);

    case 'entry_price':
    case 'exit_price':
      return value.toFixed(2).replace('.', config.decimalSeparator);

    case 'opened_at':
    case 'closed_at':
      return moment(value).format(config.dateFormat);

    case 'duration':
      return formatDuration(value);

    default:
      return String(value);
  }
}

function escapeCSV(value, delimiter) {
  const str = String(value);
  if (str.includes(delimiter) || str.includes('"') || str.includes('\n')) {
    return '"' + str.replace(/"/g, '""') + '"';
  }
  return str;
}

Frontend Download:

async function downloadCSV(params) {
  // Request CSV from backend
  const response = await fetch('/trading/paper/trades/export/csv?' + new URLSearchParams(params));
  const blob = await response.blob();

  // Create download link
  const url = window.URL.createObjectURL(blob);
  const link = document.createElement('a');
  link.href = url;
  link.download = generateFilename(params);
  document.body.appendChild(link);
  link.click();
  document.body.removeChild(link);
  window.URL.revokeObjectURL(url);
}

function generateFilename(params) {
  const { dateFrom, dateTo } = params;
  if (dateFrom && dateTo) {
    return `trades_${dateFrom}_to_${dateTo}.csv`;
  }
  return `trades_all_time.csv`;
}

Column Labels:

const COLUMN_LABELS = {
  id: 'Trade ID',
  symbol: 'Symbol',
  side: 'Side',
  entry_price: 'Entry Price',
  exit_price: 'Exit Price',
  quantity: 'Quantity',
  pnl: 'P&L (USD)',
  pnl_percentage: 'P&L (%)',
  opened_at: 'Opened At',
  closed_at: 'Closed At',
  duration_seconds: 'Duration',
  close_reason: 'Close Reason',
  entry_order_id: 'Entry Order ID',
  exit_order_id: 'Exit Order ID'
};

Definition of Ready (DoR)

  • Historia claramente escrita
  • Criterios de aceptación definidos
  • Story points estimados
  • Dependencias identificadas
  • 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