# TRACEABILITY.yml - OQI-008 Portfolio Manager # Mapeo de requerimientos a implementacion version: "1.1.0" epic: OQI-008 name: "Portfolio Manager Avanzado" updated: "2026-01-28" status: planned # Resumen de trazabilidad summary: total_requirements: 7 total_specs: 11 total_user_stories: 14 total_files_to_implement: 55 test_coverage: "TBD" story_points: 75 phase: 2 documentation_progress: "100%" # Nuevas especificaciones agregadas 2026-01-28 new_specs: - id: ET-PFM-010 name: "Arquitectura General del Sistema" path: "../especificaciones/ET-PFM-010-architecture.md" description: "Vision completa de arquitectura: capas, flujos de datos, integraciones" added: "2026-01-28" - id: ET-PFM-011 name: "Sistema de Goals Completo" path: "../especificaciones/ET-PFM-011-goals-system.md" description: "Sistema completo de metas: entities, Monte Carlo, proyecciones" added: "2026-01-28" # Mapeo de Requerimientos Funcionales requirements: RF-PFM-001: name: "Dashboard de Portfolio" status: planned specs: - ET-PFM-001 - ET-PFM-005 user_stories: - US-PFM-001 - US-PFM-002 implementation: backend: - path: apps/backend/src/modules/portfolio/services/portfolio.service.ts description: "Servicio principal de portfolio" methods: - getPortfolioSummary - getPortfolioValue - getPortfolioHistory - getAssetAllocation - getDiversificationScore - path: apps/backend/src/modules/portfolio/controllers/portfolio.controller.ts methods: - getSummary - getValue - getHistory - path: apps/backend/src/modules/portfolio/portfolio.routes.ts routes: - "GET /portfolio/summary" - "GET /portfolio/value" - "GET /portfolio/history" - "GET /portfolio/allocation" frontend: - path: apps/frontend/src/modules/portfolio/pages/Portfolio.tsx description: "Página principal de portfolio" - path: apps/frontend/src/modules/portfolio/components/PortfolioSummary.tsx description: "Resumen de portfolio" - path: apps/frontend/src/modules/portfolio/components/PortfolioChart.tsx description: "Gráfico de valor histórico" - path: apps/frontend/src/modules/portfolio/components/AllocationPie.tsx description: "Pie chart de asignación" - path: apps/frontend/src/modules/portfolio/components/NetWorthCard.tsx description: "Tarjeta de patrimonio neto" database: - path: apps/database/schemas/08_portfolio_schema.sql tables: - portfolios - portfolio_snapshots - portfolio_settings enums: - portfolio_type_enum tests: - path: apps/backend/tests/portfolio/portfolio.service.test.ts status: planned RF-PFM-002: name: "Gestión de Holdings" status: planned specs: - ET-PFM-001 - ET-PFM-002 user_stories: - US-PFM-003 - US-PFM-004 implementation: backend: - path: apps/backend/src/modules/portfolio/services/holding.service.ts description: "Servicio de holdings" methods: - getHoldings - getHoldingById - addHolding - updateHolding - removeHolding - getHoldingPerformance - syncWithBroker - path: apps/backend/src/modules/portfolio/controllers/portfolio.controller.ts methods: - getHoldings - addHolding - updateHolding - deleteHolding - path: apps/backend/src/modules/portfolio/portfolio.routes.ts routes: - "GET /portfolio/holdings" - "POST /portfolio/holdings" - "PUT /portfolio/holdings/:id" - "DELETE /portfolio/holdings/:id" - "POST /portfolio/holdings/sync" frontend: - path: apps/frontend/src/modules/portfolio/components/HoldingsTable.tsx description: "Tabla de holdings" - path: apps/frontend/src/modules/portfolio/components/HoldingCard.tsx description: "Tarjeta de holding" - path: apps/frontend/src/modules/portfolio/components/AddHoldingModal.tsx description: "Modal para agregar holding" - path: apps/frontend/src/modules/portfolio/components/HoldingDetail.tsx description: "Detalle de holding" database: - path: apps/database/schemas/08_portfolio_schema.sql tables: - holdings - holding_transactions - holding_lots enums: - holding_type_enum - asset_class_enum tests: - path: apps/backend/tests/portfolio/holding.service.test.ts status: planned RF-PFM-003: name: "Análisis de Rendimiento" status: planned specs: - ET-PFM-003 - ET-PFM-004 user_stories: - US-PFM-005 - US-PFM-006 implementation: backend: - path: apps/backend/src/modules/portfolio/services/performance.service.ts description: "Servicio de análisis de rendimiento" methods: - calculateTWR - calculateMWR - calculateAlpha - calculateBeta - calculateSharpe - calculateSortino - compareWithBenchmark - getAttributionAnalysis - path: apps/backend/src/modules/portfolio/controllers/portfolio.controller.ts methods: - getPerformance - getBenchmarkComparison - getAttribution - path: apps/backend/src/modules/portfolio/portfolio.routes.ts routes: - "GET /portfolio/performance" - "GET /portfolio/performance/metrics" - "GET /portfolio/performance/benchmark" - "GET /portfolio/performance/attribution" frontend: - path: apps/frontend/src/modules/portfolio/pages/Performance.tsx description: "Página de rendimiento" - path: apps/frontend/src/modules/portfolio/components/PerformanceMetrics.tsx description: "Métricas de rendimiento" - path: apps/frontend/src/modules/portfolio/components/BenchmarkComparison.tsx description: "Comparación con benchmark" - path: apps/frontend/src/modules/portfolio/components/ReturnChart.tsx description: "Gráfico de retornos" - path: apps/frontend/src/modules/portfolio/components/DrawdownChart.tsx description: "Gráfico de drawdown" database: - path: apps/database/schemas/08_portfolio_schema.sql tables: - performance_metrics - benchmark_data - performance_attribution tests: - path: apps/backend/tests/portfolio/performance.service.test.ts status: planned RF-PFM-004: name: "Análisis de Riesgo" status: planned specs: - ET-PFM-003 - ET-PFM-004 user_stories: - US-PFM-007 implementation: backend: - path: apps/backend/src/modules/portfolio/services/risk.service.ts description: "Servicio de análisis de riesgo" methods: - calculateVaR - calculateCVaR - calculateVolatility - calculateCorrelation - stressTest - getConcentrationRisk - getSectorExposure - path: apps/backend/src/modules/portfolio/controllers/portfolio.controller.ts methods: - getRiskAnalysis - getVaR - runStressTest - path: apps/backend/src/modules/portfolio/portfolio.routes.ts routes: - "GET /portfolio/risk" - "GET /portfolio/risk/var" - "POST /portfolio/risk/stress-test" - "GET /portfolio/risk/concentration" frontend: - path: apps/frontend/src/modules/portfolio/pages/Risk.tsx description: "Página de análisis de riesgo" - path: apps/frontend/src/modules/portfolio/components/RiskMetrics.tsx description: "Métricas de riesgo" - path: apps/frontend/src/modules/portfolio/components/VaRChart.tsx description: "Gráfico de VaR" - path: apps/frontend/src/modules/portfolio/components/CorrelationMatrix.tsx description: "Matriz de correlación" - path: apps/frontend/src/modules/portfolio/components/StressTestResults.tsx description: "Resultados de stress test" database: - path: apps/database/schemas/08_portfolio_schema.sql tables: - risk_metrics - stress_test_results - correlation_data tests: - path: apps/backend/tests/portfolio/risk.service.test.ts status: planned RF-PFM-005: name: "Rebalanceo" status: planned specs: - ET-PFM-002 - ET-PFM-006 user_stories: - US-PFM-008 - US-PFM-009 implementation: backend: - path: apps/backend/src/modules/portfolio/services/rebalance.service.ts description: "Servicio de rebalanceo" methods: - getTargetAllocation - setTargetAllocation - calculateRebalanceActions - executeRebalance - scheduleRebalance - getRebalanceHistory - path: apps/backend/src/modules/portfolio/controllers/portfolio.controller.ts methods: - getRebalanceSuggestions - setTargetAllocation - executeRebalance - path: apps/backend/src/modules/portfolio/portfolio.routes.ts routes: - "GET /portfolio/rebalance/suggestions" - "POST /portfolio/rebalance/target" - "POST /portfolio/rebalance/execute" - "GET /portfolio/rebalance/history" frontend: - path: apps/frontend/src/modules/portfolio/pages/Rebalance.tsx description: "Página de rebalanceo" - path: apps/frontend/src/modules/portfolio/components/TargetAllocation.tsx description: "Configurar asignación objetivo" - path: apps/frontend/src/modules/portfolio/components/RebalancePreview.tsx description: "Preview de acciones de rebalanceo" - path: apps/frontend/src/modules/portfolio/components/AllocationSliders.tsx description: "Sliders de asignación" database: - path: apps/database/schemas/08_portfolio_schema.sql tables: - target_allocations - rebalance_actions - rebalance_history tests: - path: apps/backend/tests/portfolio/rebalance.service.test.ts status: planned RF-PFM-006: name: "Reportes" status: planned specs: - ET-PFM-005 - ET-PFM-007 user_stories: - US-PFM-010 - US-PFM-011 implementation: backend: - path: apps/backend/src/modules/portfolio/services/report.service.ts description: "Servicio de reportes" methods: - generateReport - getReports - downloadReport - scheduleReport - sendReportEmail - path: apps/backend/src/modules/portfolio/controllers/portfolio.controller.ts methods: - generateReport - getReports - downloadReport - path: apps/backend/src/modules/portfolio/portfolio.routes.ts routes: - "POST /portfolio/reports" - "GET /portfolio/reports" - "GET /portfolio/reports/:id/download" frontend: - path: apps/frontend/src/modules/portfolio/pages/Reports.tsx description: "Página de reportes" - path: apps/frontend/src/modules/portfolio/components/ReportGenerator.tsx description: "Generador de reportes" - path: apps/frontend/src/modules/portfolio/components/ReportPreview.tsx description: "Preview de reporte" - path: apps/frontend/src/modules/portfolio/components/ReportList.tsx description: "Lista de reportes" database: - path: apps/database/schemas/08_portfolio_schema.sql tables: - reports - report_templates - scheduled_reports enums: - report_type_enum - report_frequency_enum tests: - path: apps/backend/tests/portfolio/report.service.test.ts status: planned RF-PFM-007: name: "Objetivos Financieros" status: planned specs: - ET-PFM-006 user_stories: - US-PFM-012 implementation: backend: - path: apps/backend/src/modules/portfolio/services/goal.service.ts description: "Servicio de objetivos" methods: - createGoal - updateGoal - deleteGoal - getGoals - calculateProgress - projectCompletion - suggestContributions - path: apps/backend/src/modules/portfolio/controllers/portfolio.controller.ts methods: - createGoal - getGoals - updateGoal - deleteGoal - path: apps/backend/src/modules/portfolio/portfolio.routes.ts routes: - "GET /portfolio/goals" - "POST /portfolio/goals" - "PUT /portfolio/goals/:id" - "DELETE /portfolio/goals/:id" - "GET /portfolio/goals/:id/progress" frontend: - path: apps/frontend/src/modules/portfolio/pages/Goals.tsx description: "Página de objetivos" - path: apps/frontend/src/modules/portfolio/components/GoalCard.tsx description: "Tarjeta de objetivo" - path: apps/frontend/src/modules/portfolio/components/GoalProgress.tsx description: "Progreso del objetivo" - path: apps/frontend/src/modules/portfolio/components/GoalCreator.tsx description: "Creador de objetivos" - path: apps/frontend/src/modules/portfolio/components/ProjectionChart.tsx description: "Gráfico de proyección" database: - path: apps/database/schemas/08_portfolio_schema.sql tables: - financial_goals - goal_contributions - goal_projections enums: - goal_type_enum - goal_priority_enum tests: - path: apps/backend/tests/portfolio/goal.service.test.ts status: planned # Métricas de portfolio portfolio_metrics: return_metrics: - TWR (Time-Weighted Return) - MWR (Money-Weighted Return) - CAGR - YTD Return - Annualized Return risk_metrics: - Standard Deviation - Sharpe Ratio - Sortino Ratio - Max Drawdown - VaR (95%, 99%) - CVaR / Expected Shortfall - Beta - Tracking Error advanced_metrics: - Alpha - Information Ratio - Treynor Ratio - Calmar Ratio - Ulcer Index # Benchmarks soportados benchmarks: - code: SPY name: "S&P 500" asset_class: equity - code: QQQ name: "NASDAQ 100" asset_class: equity - code: IWM name: "Russell 2000" asset_class: equity - code: AGG name: "US Aggregate Bond" asset_class: fixed_income - code: BTC name: "Bitcoin" asset_class: crypto - code: CUSTOM name: "Custom Benchmark" asset_class: mixed # Mapeo de archivos de configuración config_files: backend: - path: apps/backend/src/modules/portfolio/portfolio.module.ts description: "Módulo de portfolio" - path: apps/backend/src/modules/portfolio/types/portfolio.types.ts description: "Tipos TypeScript" - path: apps/backend/src/modules/portfolio/validators/portfolio.validators.ts description: "Validadores Zod" - path: apps/backend/src/modules/portfolio/cron/portfolio.cron.ts description: "Jobs programados" frontend: - path: apps/frontend/src/modules/portfolio/stores/portfolio.store.ts description: "Store de portfolio Zustand" - path: apps/frontend/src/modules/portfolio/hooks/usePortfolio.ts description: "Hook principal de portfolio" - path: apps/frontend/src/modules/portfolio/services/portfolio.api.ts description: "Cliente API de portfolio" # Dependencias externas external_dependencies: npm_backend: - name: mathjs version: "^12.0.0" usage: "Cálculos financieros" - name: simple-statistics version: "^7.8.0" usage: "Estadísticas" - name: pdfkit version: "^0.14.0" usage: "Generación de reportes PDF" - name: node-cron version: "^3.0.0" usage: "Jobs programados" npm_frontend: - name: recharts version: "^2.10.0" usage: "Gráficos" - name: "@tanstack/react-table" version: "^8.10.0" usage: "Tablas de datos" - name: react-grid-layout version: "^1.4.0" usage: "Dashboard customizable" # APIs de terceros third_party_apis: - name: Alpaca Markets docs: https://alpaca.markets/docs usage: - Posiciones reales (opcional) - Sincronización de cuenta - name: Yahoo Finance docs: https://finance.yahoo.com usage: - Datos históricos de benchmark - Precios de activos - name: Alpha Vantage docs: https://www.alphavantage.co/documentation/ usage: - Datos fundamentales - Información de sectores # Endpoints API api_endpoints: base_path: /api/v1/portfolio endpoints: # Dashboard - method: GET path: /summary requirement: RF-PFM-001 auth: true - method: GET path: /value requirement: RF-PFM-001 auth: true - method: GET path: /history requirement: RF-PFM-001 auth: true - method: GET path: /allocation requirement: RF-PFM-001 auth: true # Holdings - method: GET path: /holdings requirement: RF-PFM-002 auth: true - method: POST path: /holdings requirement: RF-PFM-002 auth: true - method: PUT path: /holdings/:id requirement: RF-PFM-002 auth: true - method: DELETE path: /holdings/:id requirement: RF-PFM-002 auth: true # Performance - method: GET path: /performance requirement: RF-PFM-003 auth: true - method: GET path: /performance/benchmark requirement: RF-PFM-003 auth: true # Risk - method: GET path: /risk requirement: RF-PFM-004 auth: true - method: GET path: /risk/var requirement: RF-PFM-004 auth: true - method: POST path: /risk/stress-test requirement: RF-PFM-004 auth: true # Rebalance - method: GET path: /rebalance/suggestions requirement: RF-PFM-005 auth: true - method: POST path: /rebalance/target requirement: RF-PFM-005 auth: true - method: POST path: /rebalance/execute requirement: RF-PFM-005 auth: true # Reports - method: POST path: /reports requirement: RF-PFM-006 auth: true - method: GET path: /reports requirement: RF-PFM-006 auth: true - method: GET path: /reports/:id/download requirement: RF-PFM-006 auth: true # Goals - method: GET path: /goals requirement: RF-PFM-007 auth: true - method: POST path: /goals requirement: RF-PFM-007 auth: true - method: PUT path: /goals/:id requirement: RF-PFM-007 auth: true - method: DELETE path: /goals/:id requirement: RF-PFM-007 auth: true # Dependencias de épicas dependencies: blocks: [] blocked_by: - epic: OQI-001 reason: "Requiere autenticación" - epic: OQI-003 reason: "Usa datos de trading para holdings" - epic: OQI-004 reason: "Integra cuentas de inversión" # Notas y decisiones notes: - "TWR como métrica principal de rendimiento" - "Snapshots diarios automáticos del portfolio" - "VaR calculado con método histórico (252 días)" - "Rebalanceo manual con preview de acciones" - "Reportes mensuales automáticos opcionales" - "Soporte para holdings manuales y sincronizados" - "Dashboard customizable con drag-and-drop" - "Proyecciones Monte Carlo para objetivos"