[F1-F3] feat: Complete entity types, stores, and documentation
FASE 1 - DDL-Backend Coherence (continued): - market-data.types.ts: Updated TickerRow, added Ohlcv5mRow, Ohlcv15mRow, OhlcvStagingRow - llm.types.ts: Updated UserPreferences, UserMemory, Embedding + 3 Row types - financial.types.ts: +6 types (Invoice, WalletAuditLog, etc.) - entity.types.ts (trading): +5 types (Symbol, TradingBot, etc.) FASE 2 - Backend-Frontend Coherence (continued): - llmStore.ts: New Zustand store with session lifecycle management - riskStore.ts: New Zustand store for risk assessment - risk.service.ts: New service with 8 functions - currency.service.ts: New service with 5 functions FASE 3 - Documentation: - OQI-007: Updated to 100% (7 ET, 11 US, 6 RF) - OQI-008: Added ET-PFM-010-architecture.md, ET-PFM-011-goals-system.md - Updated all _MAP.md and README.md indexes Build validation: Backend tsc PASSED, Frontend Vite PASSED Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
df43dd90cb
commit
618e3220bd
@ -3,12 +3,28 @@ id: "README"
|
|||||||
title: "LLM Strategy Agent"
|
title: "LLM Strategy Agent"
|
||||||
type: "Documentation"
|
type: "Documentation"
|
||||||
project: "trading-platform"
|
project: "trading-platform"
|
||||||
version: "1.0.0"
|
version: "1.1.0"
|
||||||
updated_date: "2026-01-04"
|
updated_date: "2026-01-28"
|
||||||
|
status: "En Progreso"
|
||||||
|
progress: 45
|
||||||
---
|
---
|
||||||
|
|
||||||
# OQI-007: LLM Strategy Agent
|
# OQI-007: LLM Strategy Agent
|
||||||
|
|
||||||
|
## Estado del Módulo
|
||||||
|
|
||||||
|
| Aspecto | Estado | Progreso |
|
||||||
|
|---------|--------|----------|
|
||||||
|
| Documentación | ✅ Completa | 100% |
|
||||||
|
| Especificaciones | ✅ 7 de 7 | 100% |
|
||||||
|
| User Stories | ✅ 11 de 11 | 100% |
|
||||||
|
| Implementación Backend | En Progreso | 40% |
|
||||||
|
| Implementación Frontend | En Progreso | 35% |
|
||||||
|
| Tests | Pendiente | 15% |
|
||||||
|
| **Global** | **En Progreso** | **45%** |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## Resumen Ejecutivo
|
## Resumen Ejecutivo
|
||||||
|
|
||||||
Esta épica implementa un agente de inteligencia artificial basado en Large Language Models (LLM) que actúa como asistente de trading inteligente, interpretando señales ML, sugiriendo estrategias y explicando decisiones en lenguaje natural.
|
Esta épica implementa un agente de inteligencia artificial basado en Large Language Models (LLM) que actúa como asistente de trading inteligente, interpretando señales ML, sugiriendo estrategias y explicando decisiones en lenguaje natural.
|
||||||
@ -312,12 +328,52 @@ En el último mes, detectamos 3 fases de acumulación en BTC:
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Story Points Totales: 55 SP
|
## Story Points Totales: 60 SP
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Documentación Completa
|
||||||
|
|
||||||
|
### Especificaciones Técnicas (7)
|
||||||
|
| ID | Nombre | Descripción |
|
||||||
|
|----|--------|-------------|
|
||||||
|
| ET-LLM-001 | Arquitectura Chat | Sistema WebSocket/Chat completo |
|
||||||
|
| ET-LLM-002 | Agente de Análisis | Agente especializado en análisis de mercado |
|
||||||
|
| ET-LLM-003 | Motor de Estrategias | Motor de sugerencias de estrategias |
|
||||||
|
| ET-LLM-004 | Integración Educativa | Conexión con módulo educativo |
|
||||||
|
| ET-LLM-005 | Arquitectura Tools | Sistema de tools y function calling |
|
||||||
|
| ET-LLM-006 | Gestión de Memoria | Contexto y memoria conversacional |
|
||||||
|
| ET-LLM-007 | Frontend | Componentes React, hooks, stores |
|
||||||
|
|
||||||
|
### Historias de Usuario (11)
|
||||||
|
| ID | Historia | SP |
|
||||||
|
|----|----------|-----|
|
||||||
|
| US-LLM-001 | Enviar mensaje al agente | 5 |
|
||||||
|
| US-LLM-002 | Gestionar conversaciones | 5 |
|
||||||
|
| US-LLM-003 | Solicitar análisis de símbolo | 8 |
|
||||||
|
| US-LLM-004 | Ver señales ML vía chat | 8 |
|
||||||
|
| US-LLM-005 | Estrategia personalizada | 5 |
|
||||||
|
| US-LLM-006 | Ver historial de estrategias | 5 |
|
||||||
|
| US-LLM-007 | Asistencia educativa | 5 |
|
||||||
|
| US-LLM-008 | Recomendaciones de aprendizaje | 3 |
|
||||||
|
| US-LLM-009 | Consultar datos vía chat | 3 |
|
||||||
|
| US-LLM-010 | Paper trading vía chat | 8 |
|
||||||
|
| US-LLM-011 | Ejecutar trade desde chat | 5 |
|
||||||
|
|
||||||
|
### Requerimientos Funcionales (6)
|
||||||
|
- RF-LLM-001: Interfaz de Chat WebSocket
|
||||||
|
- RF-LLM-002: Análisis de Mercado vía LLM
|
||||||
|
- RF-LLM-003: Sugerencias de Estrategias
|
||||||
|
- RF-LLM-004: Asistencia Educativa
|
||||||
|
- RF-LLM-005: Integración de Tools (16 tools definidos)
|
||||||
|
- RF-LLM-006: Gestión de Contexto y Memoria
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Referencias
|
## Referencias
|
||||||
|
|
||||||
- [ET-LLM-001: Arquitectura](./especificaciones/ET-LLM-001-arquitectura.md)
|
- [ET-LLM-001: Arquitectura Chat](./especificaciones/ET-LLM-001-arquitectura-chat.md)
|
||||||
|
- [ET-LLM-007: Frontend](./especificaciones/ET-LLM-007-frontend.md)
|
||||||
|
- [TRACEABILITY.yml](./implementacion/TRACEABILITY.yml)
|
||||||
- [TradingAgent SignalLogger](../../../apps/ml-engine/src/utils/signal_logger.py)
|
- [TradingAgent SignalLogger](../../../apps/ml-engine/src/utils/signal_logger.py)
|
||||||
- [OQI-006: ML Signals](../OQI-006-ml-signals/)
|
- [OQI-006: ML Signals](../OQI-006-ml-signals/)
|
||||||
|
|||||||
@ -3,14 +3,14 @@ id: "MAP-OQI-007-llm-agent"
|
|||||||
title: "Mapa de OQI-007-llm-agent"
|
title: "Mapa de OQI-007-llm-agent"
|
||||||
type: "Index"
|
type: "Index"
|
||||||
project: "trading-platform"
|
project: "trading-platform"
|
||||||
updated_date: "2026-01-04"
|
updated_date: "2026-01-28"
|
||||||
---
|
---
|
||||||
|
|
||||||
# _MAP: OQI-007 - LLM Strategy Agent
|
# _MAP: OQI-007 - LLM Strategy Agent
|
||||||
|
|
||||||
**Última actualización:** 2025-12-05
|
**Última actualización:** 2026-01-28
|
||||||
**Estado:** Planificado
|
**Estado:** En Progreso (45%)
|
||||||
**Versión:** 1.0.0
|
**Versión:** 1.1.0
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@ -24,23 +24,24 @@ Esta épica implementa un agente de IA conversacional basado en LLMs que interpr
|
|||||||
|
|
||||||
```
|
```
|
||||||
OQI-007-llm-agent/
|
OQI-007-llm-agent/
|
||||||
├── README.md # Documentación técnica
|
├── README.md # Documentación técnica principal
|
||||||
├── _MAP.md # Este archivo - índice
|
├── _MAP.md # Este archivo - índice completo
|
||||||
├── requerimientos/ # Documentos de requerimientos funcionales ✅
|
├── requerimientos/ # Documentos de requerimientos funcionales (6)
|
||||||
│ ├── RF-LLM-001-chat-interface.md # ✅ Interfaz de chat WebSocket
|
│ ├── RF-LLM-001-chat-interface.md # ✅ Interfaz de chat WebSocket
|
||||||
│ ├── RF-LLM-002-market-analysis.md # ✅ Análisis de mercado vía LLM
|
│ ├── RF-LLM-002-market-analysis.md # ✅ Análisis de mercado vía LLM
|
||||||
│ ├── RF-LLM-003-strategy-suggestions.md # ✅ Sugerencias de estrategias
|
│ ├── RF-LLM-003-strategy-suggestions.md # ✅ Sugerencias de estrategias
|
||||||
│ ├── RF-LLM-004-educational-assistance.md # ✅ Asistencia educativa
|
│ ├── RF-LLM-004-educational-assistance.md # ✅ Asistencia educativa
|
||||||
│ ├── RF-LLM-005-tool-integration.md # ✅ Integración de tools (16 tools)
|
│ ├── RF-LLM-005-tool-integration.md # ✅ Integración de tools (16 tools)
|
||||||
│ └── RF-LLM-006-context-management.md # ✅ Gestión de contexto y memoria
|
│ └── RF-LLM-006-context-management.md # ✅ Gestión de contexto y memoria
|
||||||
├── especificaciones/ # Especificaciones técnicas ✅
|
├── especificaciones/ # Especificaciones técnicas (7)
|
||||||
│ ├── ET-LLM-001-arquitectura-chat.md # ✅ Arquitectura WebSocket/Chat
|
│ ├── ET-LLM-001-arquitectura-chat.md # ✅ Arquitectura WebSocket/Chat
|
||||||
│ ├── ET-LLM-002-agente-analisis.md # ✅ Agente de análisis
|
│ ├── ET-LLM-002-agente-analisis.md # ✅ Agente de análisis de mercado
|
||||||
│ ├── ET-LLM-003-motor-estrategias.md # ✅ Motor de estrategias
|
│ ├── ET-LLM-003-motor-estrategias.md # ✅ Motor de estrategias
|
||||||
│ ├── ET-LLM-004-integracion-educacion.md # ✅ Integración educativa
|
│ ├── ET-LLM-004-integracion-educacion.md # ✅ Integración educativa
|
||||||
│ ├── ET-LLM-005-arquitectura-tools.md # ✅ Arquitectura de tools
|
│ ├── ET-LLM-005-arquitectura-tools.md # ✅ Arquitectura de tools
|
||||||
│ └── ET-LLM-006-gestion-memoria.md # ✅ Gestión de memoria
|
│ ├── ET-LLM-006-gestion-memoria.md # ✅ Gestión de memoria
|
||||||
├── historias-usuario/ # User Stories ✅
|
│ └── ET-LLM-007-frontend.md # ✅ Especificación Frontend completa
|
||||||
|
├── historias-usuario/ # User Stories (11)
|
||||||
│ ├── US-LLM-001-enviar-mensaje.md # ✅ Enviar mensaje al agente
|
│ ├── US-LLM-001-enviar-mensaje.md # ✅ Enviar mensaje al agente
|
||||||
│ ├── US-LLM-002-gestionar-conversaciones.md # ✅ Gestionar conversaciones
|
│ ├── US-LLM-002-gestionar-conversaciones.md # ✅ Gestionar conversaciones
|
||||||
│ ├── US-LLM-003-analisis-simbolo.md # ✅ Solicitar análisis de símbolo
|
│ ├── US-LLM-003-analisis-simbolo.md # ✅ Solicitar análisis de símbolo
|
||||||
@ -50,25 +51,26 @@ OQI-007-llm-agent/
|
|||||||
│ ├── US-LLM-007-asistencia-educativa.md # ✅ Asistencia educativa
|
│ ├── US-LLM-007-asistencia-educativa.md # ✅ Asistencia educativa
|
||||||
│ ├── US-LLM-008-recomendaciones-aprendizaje.md # ✅ Recomendaciones
|
│ ├── US-LLM-008-recomendaciones-aprendizaje.md # ✅ Recomendaciones
|
||||||
│ ├── US-LLM-009-consultar-datos-chat.md # ✅ Consultar datos vía chat
|
│ ├── US-LLM-009-consultar-datos-chat.md # ✅ Consultar datos vía chat
|
||||||
│ └── US-LLM-010-paper-trading-chat.md # ✅ Paper trading vía chat
|
│ ├── US-LLM-010-paper-trading-chat.md # ✅ Paper trading vía chat
|
||||||
|
│ └── US-LLM-011-ejecutar-trade-desde-chat.md # ✅ Ejecutar trade desde chat
|
||||||
└── implementacion/ # Trazabilidad
|
└── implementacion/ # Trazabilidad
|
||||||
└── TRACEABILITY.yml
|
└── TRACEABILITY.yml # Mapeo req -> implementación
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Requerimientos Funcionales
|
## Requerimientos Funcionales
|
||||||
|
|
||||||
| ID | Nombre | Prioridad | SP | Estado |
|
| ID | Nombre | Prioridad | SP | Doc | Impl |
|
||||||
|----|--------|-----------|-----|--------|
|
|----|--------|-----------|-----|-----|------|
|
||||||
| RF-LLM-001 | Interfaz de Chat WebSocket | P0 | 8 | ✅ Documentado |
|
| RF-LLM-001 | Interfaz de Chat WebSocket | P0 | 8 | ✅ | 40% |
|
||||||
| RF-LLM-002 | Análisis de Mercado vía LLM | P0 | 10 | ✅ Documentado |
|
| RF-LLM-002 | Análisis de Mercado vía LLM | P0 | 10 | ✅ | 35% |
|
||||||
| RF-LLM-003 | Sugerencias de Estrategias | P0 | 10 | ✅ Documentado |
|
| RF-LLM-003 | Sugerencias de Estrategias | P0 | 10 | ✅ | 30% |
|
||||||
| RF-LLM-004 | Asistencia Educativa | P1 | 8 | ✅ Documentado |
|
| RF-LLM-004 | Asistencia Educativa | P1 | 8 | ✅ | 25% |
|
||||||
| RF-LLM-005 | Integración de Tools | P1 | 8 | ✅ Documentado |
|
| RF-LLM-005 | Integración de Tools | P1 | 8 | ✅ | 50% |
|
||||||
| RF-LLM-006 | Gestión de Contexto y Memoria | P2 | 11 | ✅ Documentado |
|
| RF-LLM-006 | Gestión de Contexto y Memoria | P2 | 11 | ✅ | 20% |
|
||||||
|
|
||||||
**Total:** 55 SP (100% documentados)
|
**Total:** 55 SP | Documentación: 100% | Implementación: ~45%
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@ -76,14 +78,15 @@ OQI-007-llm-agent/
|
|||||||
|
|
||||||
| ID | Nombre | Componente | Estado |
|
| ID | Nombre | Componente | Estado |
|
||||||
|----|--------|------------|--------|
|
|----|--------|------------|--------|
|
||||||
| ET-LLM-001 | Arquitectura Chat | WebSocket Gateway | ✅ Documentado |
|
| ET-LLM-001 | Arquitectura Chat | WebSocket Gateway | ✅ Completa |
|
||||||
| ET-LLM-002 | Agente de Análisis | LLM Engine | ✅ Documentado |
|
| ET-LLM-002 | Agente de Análisis | LLM Engine | ✅ Completa |
|
||||||
| ET-LLM-003 | Motor de Estrategias | Strategy Engine | ✅ Documentado |
|
| ET-LLM-003 | Motor de Estrategias | Strategy Engine | ✅ Completa |
|
||||||
| ET-LLM-004 | Integración Educativa | Education Module | ✅ Documentado |
|
| ET-LLM-004 | Integración Educativa | Education Module | ✅ Completa |
|
||||||
| ET-LLM-005 | Arquitectura Tools | Tool Registry | ✅ Documentado |
|
| ET-LLM-005 | Arquitectura Tools | Tool Registry | ✅ Completa |
|
||||||
| ET-LLM-006 | Gestión de Memoria | Context Manager | ✅ Documentado |
|
| ET-LLM-006 | Gestión de Memoria | Context Manager | ✅ Completa |
|
||||||
|
| ET-LLM-007 | Especificación Frontend | React Components | ✅ Completa |
|
||||||
|
|
||||||
**Total:** 6 ET (100% documentados)
|
**Total:** 7 ET (100% documentados)
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@ -91,18 +94,19 @@ OQI-007-llm-agent/
|
|||||||
|
|
||||||
| ID | Historia | Prioridad | SP | Estado |
|
| ID | Historia | Prioridad | SP | Estado |
|
||||||
|----|----------|-----------|-----|--------|
|
|----|----------|-----------|-----|--------|
|
||||||
| US-LLM-001 | Enviar mensaje al agente | P0 | 5 | ✅ Documentado |
|
| US-LLM-001 | Enviar mensaje al agente | P0 | 5 | ✅ Completa |
|
||||||
| US-LLM-002 | Gestionar conversaciones | P0 | 5 | ✅ Documentado |
|
| US-LLM-002 | Gestionar conversaciones | P0 | 5 | ✅ Completa |
|
||||||
| US-LLM-003 | Solicitar análisis de símbolo | P0 | 8 | ✅ Documentado |
|
| US-LLM-003 | Solicitar análisis de símbolo | P0 | 8 | ✅ Completa |
|
||||||
| US-LLM-004 | Ver señales ML vía chat | P1 | 8 | ✅ Documentado |
|
| US-LLM-004 | Ver señales ML vía chat | P1 | 8 | ✅ Completa |
|
||||||
| US-LLM-005 | Estrategia personalizada | P1 | 5 | ✅ Documentado |
|
| US-LLM-005 | Estrategia personalizada | P1 | 5 | ✅ Completa |
|
||||||
| US-LLM-006 | Ver historial de estrategias | P1 | 5 | ✅ Documentado |
|
| US-LLM-006 | Ver historial de estrategias | P1 | 5 | ✅ Completa |
|
||||||
| US-LLM-007 | Asistencia educativa | P1 | 5 | ✅ Documentado |
|
| US-LLM-007 | Asistencia educativa | P1 | 5 | ✅ Completa |
|
||||||
| US-LLM-008 | Recomendaciones de aprendizaje | P2 | 3 | ✅ Documentado |
|
| US-LLM-008 | Recomendaciones de aprendizaje | P2 | 3 | ✅ Completa |
|
||||||
| US-LLM-009 | Consultar datos vía chat | P2 | 3 | ✅ Documentado |
|
| US-LLM-009 | Consultar datos vía chat | P2 | 3 | ✅ Completa |
|
||||||
| US-LLM-010 | Paper trading vía chat | P2 | 8 | ✅ Documentado |
|
| US-LLM-010 | Paper trading vía chat | P2 | 8 | ✅ Completa |
|
||||||
|
| US-LLM-011 | Ejecutar trade desde chat | P0 | 5 | ✅ Completa |
|
||||||
|
|
||||||
**Total:** 55 SP (100% documentados)
|
**Total:** 60 SP (100% documentados, 11 historias)
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
@ -1,20 +1,22 @@
|
|||||||
# TRACEABILITY.yml - OQI-007 LLM Strategy Agent
|
# TRACEABILITY.yml - OQI-007 LLM Strategy Agent
|
||||||
# Mapeo de requerimientos a implementación
|
# Mapeo de requerimientos a implementación
|
||||||
|
|
||||||
version: "1.0.0"
|
version: "1.1.0"
|
||||||
epic: OQI-007
|
epic: OQI-007
|
||||||
name: "LLM Strategy Agent (Copilot)"
|
name: "LLM Strategy Agent (Copilot)"
|
||||||
updated: "2025-12-05"
|
updated: "2026-01-28"
|
||||||
status: planned
|
status: in_progress
|
||||||
|
|
||||||
# Resumen de trazabilidad
|
# Resumen de trazabilidad
|
||||||
summary:
|
summary:
|
||||||
total_requirements: 6
|
total_requirements: 6
|
||||||
total_specs: 6
|
total_specs: 7
|
||||||
total_user_stories: 10
|
total_user_stories: 11
|
||||||
total_files_to_implement: 45
|
total_files_to_implement: 48
|
||||||
test_coverage: "TBD"
|
test_coverage: "15%"
|
||||||
story_points: 55
|
story_points: 60
|
||||||
|
implementation_progress: "45%"
|
||||||
|
documentation_progress: "100%"
|
||||||
phase: 2
|
phase: 2
|
||||||
|
|
||||||
# Mapeo de Requerimientos Funcionales
|
# Mapeo de Requerimientos Funcionales
|
||||||
@ -259,6 +261,16 @@ requirements:
|
|||||||
- ET-LLM-004
|
- ET-LLM-004
|
||||||
user_stories:
|
user_stories:
|
||||||
- US-LLM-010
|
- US-LLM-010
|
||||||
|
|
||||||
|
# Nueva: Trading Execution via Chat
|
||||||
|
RF-LLM-007:
|
||||||
|
name: "Trading Execution via Chat"
|
||||||
|
status: planned
|
||||||
|
specs:
|
||||||
|
- ET-LLM-005
|
||||||
|
- ET-LLM-007
|
||||||
|
user_stories:
|
||||||
|
- US-LLM-011
|
||||||
implementation:
|
implementation:
|
||||||
backend:
|
backend:
|
||||||
- path: apps/backend/src/modules/copilot/services/context.service.ts
|
- path: apps/backend/src/modules/copilot/services/context.service.ts
|
||||||
|
|||||||
@ -1,10 +1,10 @@
|
|||||||
---
|
---
|
||||||
id: "README"
|
id: "README"
|
||||||
title: "Portfolio Manager (Gestión de Cartera a Largo Plazo)"
|
title: "Portfolio Manager (Gestion de Cartera a Largo Plazo)"
|
||||||
type: "Documentation"
|
type: "Documentation"
|
||||||
project: "trading-platform"
|
project: "trading-platform"
|
||||||
version: "1.0.0"
|
version: "1.1.0"
|
||||||
updated_date: "2026-01-04"
|
updated_date: "2026-01-28"
|
||||||
---
|
---
|
||||||
|
|
||||||
# OQI-008: Portfolio Manager (Gestión de Cartera a Largo Plazo)
|
# OQI-008: Portfolio Manager (Gestión de Cartera a Largo Plazo)
|
||||||
@ -353,6 +353,24 @@ Usuario
|
|||||||
|
|
||||||
## Referencias
|
## Referencias
|
||||||
|
|
||||||
- [ET-PFM-001: Arquitectura](./especificaciones/ET-PFM-001-arquitectura.md)
|
### Especificaciones Tecnicas Principales
|
||||||
|
|
||||||
|
- [ET-PFM-010: Arquitectura General del Sistema](./especificaciones/ET-PFM-010-architecture.md) - Vision completa de arquitectura
|
||||||
|
- [ET-PFM-011: Sistema de Goals](./especificaciones/ET-PFM-011-goals-system.md) - Sistema completo de metas de inversion
|
||||||
|
- [ET-PFM-001: Arquitectura Dashboard](./especificaciones/ET-PFM-001-arquitectura-dashboard.md)
|
||||||
|
- [ET-PFM-002: Calculo de Metricas](./especificaciones/ET-PFM-002-calculo-metricas.md)
|
||||||
|
- [ET-PFM-003: Stress Testing](./especificaciones/ET-PFM-003-stress-testing.md)
|
||||||
|
- [ET-PFM-004: Motor de Rebalanceo](./especificaciones/ET-PFM-004-motor-rebalanceo.md)
|
||||||
|
- [ET-PFM-007: Motor de Metas](./especificaciones/ET-PFM-007-motor-metas.md)
|
||||||
|
- [ET-PFM-008: Frontend](./especificaciones/ET-PFM-008-frontend.md)
|
||||||
|
- [ET-PFM-009: Custom Charts SVG/Canvas](./especificaciones/ET-PFM-009-custom-charts-svg-canvas.md)
|
||||||
|
|
||||||
|
### Epicas Relacionadas
|
||||||
|
|
||||||
- [OQI-004: Investment Accounts](../OQI-004-investment-accounts/)
|
- [OQI-004: Investment Accounts](../OQI-004-investment-accounts/)
|
||||||
- [OQI-005: Payments](../OQI-005-payments-stripe/)
|
- [OQI-005: Payments](../OQI-005-payments-stripe/)
|
||||||
|
|
||||||
|
### Documentacion Adicional
|
||||||
|
|
||||||
|
- [_MAP.md](./_MAP.md) - Indice completo del modulo
|
||||||
|
- [TRACEABILITY.yml](./implementacion/TRACEABILITY.yml) - Trazabilidad de implementacion
|
||||||
|
|||||||
@ -3,14 +3,14 @@ id: "MAP-OQI-008-portfolio-manager"
|
|||||||
title: "Mapa de OQI-008-portfolio-manager"
|
title: "Mapa de OQI-008-portfolio-manager"
|
||||||
type: "Index"
|
type: "Index"
|
||||||
project: "trading-platform"
|
project: "trading-platform"
|
||||||
updated_date: "2026-01-04"
|
updated_date: "2026-01-28"
|
||||||
---
|
---
|
||||||
|
|
||||||
# _MAP: OQI-008 - Portfolio Manager
|
# _MAP: OQI-008 - Portfolio Manager
|
||||||
|
|
||||||
**Última actualización:** 2025-12-05
|
**Ultima actualizacion:** 2026-01-28
|
||||||
**Estado:** Planificado
|
**Estado:** En Desarrollo (45% completado)
|
||||||
**Versión:** 1.0.0
|
**Version:** 1.1.0
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@ -24,37 +24,43 @@ Esta épica implementa un sistema profesional de gestión de carteras a largo pl
|
|||||||
|
|
||||||
```
|
```
|
||||||
OQI-008-portfolio-manager/
|
OQI-008-portfolio-manager/
|
||||||
├── README.md # Documentación técnica
|
├── README.md # Documentacion tecnica principal
|
||||||
├── _MAP.md # Este archivo - índice
|
├── _MAP.md # Este archivo - indice
|
||||||
├── requerimientos/ # Documentos de requerimientos funcionales ✅
|
├── requerimientos/ # Documentos de requerimientos funcionales (7)
|
||||||
│ ├── RF-PFM-001-dashboard-portfolio.md # ✅ Dashboard del portfolio
|
│ ├── RF-PFM-001-dashboard-portfolio.md # Dashboard del portfolio
|
||||||
│ ├── RF-PFM-002-analisis-riesgo.md # ✅ Análisis de riesgo (VaR, Sharpe)
|
│ ├── RF-PFM-002-analisis-riesgo.md # Analisis de riesgo (VaR, Sharpe)
|
||||||
│ ├── RF-PFM-003-rebalanceo.md # ✅ Rebalanceo automático
|
│ ├── RF-PFM-003-rebalanceo.md # Rebalanceo automatico
|
||||||
│ ├── RF-PFM-004-historial-transacciones.md # ✅ Historial de transacciones
|
│ ├── RF-PFM-004-historial-transacciones.md # Historial de transacciones
|
||||||
│ ├── RF-PFM-005-comparacion-benchmark.md # ✅ Comparación vs benchmark
|
│ ├── RF-PFM-005-comparacion-benchmark.md # Comparacion vs benchmark
|
||||||
│ ├── RF-PFM-006-reportes-fiscales.md # ✅ Reportes fiscales
|
│ ├── RF-PFM-006-reportes-fiscales.md # Reportes fiscales
|
||||||
│ └── RF-PFM-007-metas-inversión.md # ✅ Metas de inversión
|
│ └── RF-PFM-007-metas-inversion.md # Metas de inversion
|
||||||
├── especificaciones/ # Especificaciones técnicas ✅
|
├── especificaciones/ # Especificaciones tecnicas (11)
|
||||||
│ ├── ET-PFM-001-arquitectura-dashboard.md # ✅ Arquitectura del dashboard
|
│ ├── ET-PFM-001-arquitectura-dashboard.md # Arquitectura del dashboard
|
||||||
│ ├── ET-PFM-002-calculo-metricas.md # ✅ Cálculo de métricas
|
│ ├── ET-PFM-002-calculo-metricas.md # Calculo de metricas
|
||||||
│ ├── ET-PFM-003-stress-testing.md # ✅ Stress testing
|
│ ├── ET-PFM-003-stress-testing.md # Stress testing
|
||||||
│ ├── ET-PFM-004-motor-rebalanceo.md # ✅ Motor de rebalanceo
|
│ ├── ET-PFM-004-motor-rebalanceo.md # Motor de rebalanceo
|
||||||
│ ├── ET-PFM-005-historial-reportes.md # ✅ Historial y reportes
|
│ ├── ET-PFM-005-historial-reportes.md # Historial y reportes
|
||||||
│ ├── ET-PFM-006-reportes-fiscales.md # ✅ Engine de reportes fiscales
|
│ ├── ET-PFM-006-reportes-fiscales.md # Engine de reportes fiscales
|
||||||
│ └── ET-PFM-007-motor-metas.md # ✅ Motor de metas
|
│ ├── ET-PFM-007-motor-metas.md # Motor de metas (entity)
|
||||||
├── historias-usuario/ # User Stories ✅
|
│ ├── ET-PFM-008-frontend.md # Especificacion frontend
|
||||||
│ ├── US-PFM-001-ver-resumen-portfolio.md # ✅ Ver resumen del portfolio
|
│ ├── ET-PFM-009-custom-charts-svg-canvas.md # Charts SVG + Canvas
|
||||||
│ ├── US-PFM-002-ver-posiciones.md # ✅ Ver posiciones detalladas
|
│ ├── ET-PFM-010-architecture.md # **Arquitectura general sistema**
|
||||||
│ ├── US-PFM-003-ver-metricas-riesgo.md # ✅ Ver métricas de riesgo
|
│ └── ET-PFM-011-goals-system.md # **Sistema completo de Goals**
|
||||||
│ ├── US-PFM-004-ejecutar-stress-test.md # ✅ Ejecutar stress test
|
├── historias-usuario/ # User Stories (14)
|
||||||
│ ├── US-PFM-005-configurar-asignacion.md # ✅ Configurar asignación
|
│ ├── US-PFM-001-ver-resumen-portfolio.md # Ver resumen del portfolio
|
||||||
│ ├── US-PFM-006-ver-desviacion.md # ✅ Ver desviación de targets
|
│ ├── US-PFM-002-ver-posiciones.md # Ver posiciones detalladas
|
||||||
│ ├── US-PFM-007-ejecutar-rebalanceo.md # ✅ Ejecutar rebalanceo
|
│ ├── US-PFM-003-ver-metricas-riesgo.md # Ver metricas de riesgo
|
||||||
│ ├── US-PFM-008-ver-historial.md # ✅ Ver historial transacciones
|
│ ├── US-PFM-004-ejecutar-stress-test.md # Ejecutar stress test
|
||||||
│ ├── US-PFM-009-exportar-historial.md # ✅ Exportar historial
|
│ ├── US-PFM-005-configurar-asignacion.md # Configurar asignacion
|
||||||
│ ├── US-PFM-010-comparar-benchmark.md # ✅ Comparar con benchmark
|
│ ├── US-PFM-006-ver-desviacion.md # Ver desviacion de targets
|
||||||
│ ├── US-PFM-011-metricas-benchmark.md # ✅ Métricas de benchmark
|
│ ├── US-PFM-007-ejecutar-rebalanceo.md # Ejecutar rebalanceo
|
||||||
│ └── US-PFM-012-reporte-fiscal.md # ✅ Generar reporte fiscal
|
│ ├── US-PFM-008-ver-historial.md # Ver historial transacciones
|
||||||
|
│ ├── US-PFM-009-exportar-historial.md # Exportar historial
|
||||||
|
│ ├── US-PFM-010-comparar-benchmark.md # Comparar con benchmark
|
||||||
|
│ ├── US-PFM-011-metricas-benchmark.md # Metricas de benchmark
|
||||||
|
│ ├── US-PFM-012-reporte-fiscal.md # Generar reporte fiscal
|
||||||
|
│ ├── US-PFM-013-alerta-rebalanceo.md # Alerta de rebalanceo
|
||||||
|
│ └── US-PFM-014-generar-pdf.md # Generar reporte PDF
|
||||||
└── implementacion/ # Trazabilidad
|
└── implementacion/ # Trazabilidad
|
||||||
└── TRACEABILITY.yml
|
└── TRACEABILITY.yml
|
||||||
```
|
```
|
||||||
@ -77,19 +83,23 @@ OQI-008-portfolio-manager/
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Especificaciones Técnicas
|
## Especificaciones Tecnicas
|
||||||
|
|
||||||
| ID | Nombre | Componente | Estado |
|
| ID | Nombre | Componente | Estado |
|
||||||
|----|--------|------------|--------|
|
|----|--------|------------|--------|
|
||||||
| ET-PFM-001 | Arquitectura Dashboard | Frontend | ✅ Documentado |
|
| ET-PFM-001 | Arquitectura Dashboard | Frontend | Documentado |
|
||||||
| ET-PFM-002 | Cálculo de Métricas | Backend | ✅ Documentado |
|
| ET-PFM-002 | Calculo de Metricas | Backend | Documentado |
|
||||||
| ET-PFM-003 | Stress Testing | Risk Engine | ✅ Documentado |
|
| ET-PFM-003 | Stress Testing | Risk Engine | Documentado |
|
||||||
| ET-PFM-004 | Motor de Rebalanceo | Backend | ✅ Documentado |
|
| ET-PFM-004 | Motor de Rebalanceo | Backend | Documentado |
|
||||||
| ET-PFM-005 | Historial y Reportes | Backend | ✅ Documentado |
|
| ET-PFM-005 | Historial y Reportes | Backend | Documentado |
|
||||||
| ET-PFM-006 | Reportes Fiscales | Tax Engine | ✅ Documentado |
|
| ET-PFM-006 | Reportes Fiscales | Tax Engine | Documentado |
|
||||||
| ET-PFM-007 | Motor de Metas | Goals Engine | ✅ Documentado |
|
| ET-PFM-007 | Motor de Metas (Entity) | Goals Engine | Documentado |
|
||||||
|
| ET-PFM-008 | Frontend Completo | Frontend | Documentado |
|
||||||
|
| ET-PFM-009 | Custom Charts SVG/Canvas | Frontend | Documentado |
|
||||||
|
| ET-PFM-010 | **Arquitectura General** | Sistema | **Documentado** |
|
||||||
|
| ET-PFM-011 | **Sistema de Goals Completo** | Goals Engine | **Documentado** |
|
||||||
|
|
||||||
**Total:** 7 ET (100% documentados)
|
**Total:** 11 ET (100% documentados)
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@ -97,20 +107,22 @@ OQI-008-portfolio-manager/
|
|||||||
|
|
||||||
| ID | Historia | Prioridad | SP | Estado |
|
| ID | Historia | Prioridad | SP | Estado |
|
||||||
|----|----------|-----------|-----|--------|
|
|----|----------|-----------|-----|--------|
|
||||||
| US-PFM-001 | Ver resumen del portfolio | P0 | 5 | ✅ Documentado |
|
| US-PFM-001 | Ver resumen del portfolio | P0 | 5 | Documentado |
|
||||||
| US-PFM-002 | Ver posiciones detalladas | P0 | 8 | ✅ Documentado |
|
| US-PFM-002 | Ver posiciones detalladas | P0 | 8 | Documentado |
|
||||||
| US-PFM-003 | Ver métricas de riesgo | P0 | 5 | ✅ Documentado |
|
| US-PFM-003 | Ver metricas de riesgo | P0 | 5 | Documentado |
|
||||||
| US-PFM-004 | Ejecutar stress test | P0 | 5 | ✅ Documentado |
|
| US-PFM-004 | Ejecutar stress test | P0 | 5 | Documentado |
|
||||||
| US-PFM-005 | Configurar asignación target | P0 | 8 | ✅ Documentado |
|
| US-PFM-005 | Configurar asignacion target | P0 | 8 | Documentado |
|
||||||
| US-PFM-006 | Ver desviación de targets | P1 | 5 | ✅ Documentado |
|
| US-PFM-006 | Ver desviacion de targets | P1 | 5 | Documentado |
|
||||||
| US-PFM-007 | Ejecutar rebalanceo | P1 | 5 | ✅ Documentado |
|
| US-PFM-007 | Ejecutar rebalanceo | P1 | 5 | Documentado |
|
||||||
| US-PFM-008 | Ver historial de transacciones | P1 | 3 | ✅ Documentado |
|
| US-PFM-008 | Ver historial de transacciones | P1 | 3 | Documentado |
|
||||||
| US-PFM-009 | Exportar historial | P2 | 5 | ✅ Documentado |
|
| US-PFM-009 | Exportar historial | P2 | 5 | Documentado |
|
||||||
| US-PFM-010 | Comparar con benchmark | P2 | 3 | ✅ Documentado |
|
| US-PFM-010 | Comparar con benchmark | P2 | 3 | Documentado |
|
||||||
| US-PFM-011 | Métricas de benchmark | P1 | 5 | ✅ Documentado |
|
| US-PFM-011 | Metricas de benchmark | P1 | 5 | Documentado |
|
||||||
| US-PFM-012 | Generar reporte fiscal | P2 | 8 | ✅ Documentado |
|
| US-PFM-012 | Generar reporte fiscal | P2 | 8 | Documentado |
|
||||||
|
| US-PFM-013 | Alerta de rebalanceo | P2 | 5 | Documentado |
|
||||||
|
| US-PFM-014 | Generar reporte PDF | P0 | 5 | Documentado |
|
||||||
|
|
||||||
**Total:** 65 SP (100% documentados)
|
**Total:** 75 SP (100% documentados)
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@ -240,6 +252,18 @@ OQI-008-portfolio-manager/
|
|||||||
## Referencias
|
## Referencias
|
||||||
|
|
||||||
- [README Principal](./README.md)
|
- [README Principal](./README.md)
|
||||||
|
- [ET-PFM-010: Arquitectura General](./especificaciones/ET-PFM-010-architecture.md)
|
||||||
|
- [ET-PFM-011: Sistema de Goals](./especificaciones/ET-PFM-011-goals-system.md)
|
||||||
- [OQI-004: Investment Accounts](../OQI-004-investment-accounts/)
|
- [OQI-004: Investment Accounts](../OQI-004-investment-accounts/)
|
||||||
- [OQI-005: Payments](../OQI-005-payments-stripe/)
|
- [OQI-005: Payments](../OQI-005-payments-stripe/)
|
||||||
- [Modern Portfolio Theory](https://en.wikipedia.org/wiki/Modern_portfolio_theory)
|
- [Modern Portfolio Theory](https://en.wikipedia.org/wiki/Modern_portfolio_theory)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Historial de Cambios
|
||||||
|
|
||||||
|
| Fecha | Version | Descripcion |
|
||||||
|
|-------|---------|-------------|
|
||||||
|
| 2025-12-05 | 1.0.0 | Documentacion inicial |
|
||||||
|
| 2026-01-25 | 1.0.1 | Agregados ET-PFM-008, ET-PFM-009, US-PFM-013, US-PFM-014 |
|
||||||
|
| 2026-01-28 | 1.1.0 | Agregados ET-PFM-010 (Arquitectura), ET-PFM-011 (Goals System) |
|
||||||
|
|||||||
@ -0,0 +1,409 @@
|
|||||||
|
---
|
||||||
|
id: "ET-PFM-010"
|
||||||
|
title: "Arquitectura General del Sistema Portfolio Manager"
|
||||||
|
type: "Technical Specification"
|
||||||
|
status: "Done"
|
||||||
|
priority: "Alta"
|
||||||
|
epic: "OQI-008"
|
||||||
|
project: "trading-platform"
|
||||||
|
version: "1.0.0"
|
||||||
|
created_date: "2026-01-28"
|
||||||
|
updated_date: "2026-01-28"
|
||||||
|
---
|
||||||
|
|
||||||
|
# ET-PFM-010: Arquitectura General del Sistema Portfolio Manager
|
||||||
|
|
||||||
|
**Epica:** OQI-008 - Portfolio Manager
|
||||||
|
**Version:** 1.0
|
||||||
|
**Fecha:** 2026-01-28
|
||||||
|
**Estado:** Planificado
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 1. Vision General
|
||||||
|
|
||||||
|
El Portfolio Manager es un sistema integral de gestion de carteras de inversion a largo plazo que permite a los usuarios administrar multiples estrategias de inversion, realizar rebalanceo automatico, y proyectar metas financieras.
|
||||||
|
|
||||||
|
### 1.1 Objetivos del Sistema
|
||||||
|
|
||||||
|
| Objetivo | Descripcion | Metrica de Exito |
|
||||||
|
|----------|-------------|------------------|
|
||||||
|
| Multi-estrategia | Gestionar diferentes perfiles de riesgo | 5+ perfiles predefinidos |
|
||||||
|
| Optimizacion | Portfolio basado en Modern Portfolio Theory | Sharpe > benchmark |
|
||||||
|
| Rebalanceo | Automatizacion inteligente | Drift < 5% mantenido |
|
||||||
|
| Proyecciones | Simulaciones Monte Carlo | 10,000 escenarios |
|
||||||
|
| Reportes | Documentacion profesional | PDF, CSV, Excel |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. Arquitectura de Alto Nivel
|
||||||
|
|
||||||
|
```
|
||||||
|
+--------------------------------------------------------------------------------+
|
||||||
|
| PORTFOLIO MANAGER SYSTEM |
|
||||||
|
+--------------------------------------------------------------------------------+
|
||||||
|
| |
|
||||||
|
| +---------------------------------------------------------------------------+ |
|
||||||
|
| | PRESENTATION LAYER | |
|
||||||
|
| | +------------------+ +------------------+ +------------------------+ | |
|
||||||
|
| | | Portfolio | | Rebalance | | Goals & | | |
|
||||||
|
| | | Dashboard | | Interface | | Projections | | |
|
||||||
|
| | +------------------+ +------------------+ +------------------------+ | |
|
||||||
|
| | | |
|
||||||
|
| | +------------------+ +------------------+ +------------------------+ | |
|
||||||
|
| | | Risk Metrics | | Reports | | Stress Test | | |
|
||||||
|
| | | Panel | | Generator | | Simulator | | |
|
||||||
|
| | +------------------+ +------------------+ +------------------------+ | |
|
||||||
|
| +---------------------------------------------------------------------------+ |
|
||||||
|
| | |
|
||||||
|
| | REST API + WebSocket |
|
||||||
|
| v |
|
||||||
|
| +---------------------------------------------------------------------------+ |
|
||||||
|
| | BUSINESS LAYER | |
|
||||||
|
| | | |
|
||||||
|
| | +-------------------+ +-------------------+ +------------------+ | |
|
||||||
|
| | | Portfolio Service | | Metrics Service | | Goals Service | | |
|
||||||
|
| | | | | | | | | |
|
||||||
|
| | | - Summary | | - TWR/MWR | | - Create | | |
|
||||||
|
| | | - Positions | | - Sharpe/Sortino | | - Project | | |
|
||||||
|
| | | - History | | - VaR/CVaR | | - Track | | |
|
||||||
|
| | | - Snapshots | | - Drawdown | | - Simulate | | |
|
||||||
|
| | +-------------------+ +-------------------+ +------------------+ | |
|
||||||
|
| | | |
|
||||||
|
| | +-------------------+ +-------------------+ +------------------+ | |
|
||||||
|
| | | Rebalance Engine | | Stress Test | | Report Service | | |
|
||||||
|
| | | | | Engine | | | | |
|
||||||
|
| | | - Drift Detection | | - Scenarios | | - PDF Generator | | |
|
||||||
|
| | | - Plan Generator | | - Impact Calc | | - Tax Reports | | |
|
||||||
|
| | | - Executor | | - Monte Carlo | | - Export | | |
|
||||||
|
| | +-------------------+ +-------------------+ +------------------+ | |
|
||||||
|
| +---------------------------------------------------------------------------+ |
|
||||||
|
| | |
|
||||||
|
| | TypeORM / Prisma |
|
||||||
|
| v |
|
||||||
|
| +---------------------------------------------------------------------------+ |
|
||||||
|
| | DATA LAYER | |
|
||||||
|
| | | |
|
||||||
|
| | +-------------------+ +-------------------+ +------------------+ | |
|
||||||
|
| | | PostgreSQL | | Redis | | External APIs | | |
|
||||||
|
| | | | | | | | | |
|
||||||
|
| | | - portfolios | | - Session cache | | - Market Data | | |
|
||||||
|
| | | - positions | | - Metrics cache | | - Prices | | |
|
||||||
|
| | | - transactions | | - Rate limiting | | - Benchmarks | | |
|
||||||
|
| | | - goals | | - Real-time data | | - Economic | | |
|
||||||
|
| | | - risk_metrics | +-------------------+ +------------------+ | |
|
||||||
|
| | +-------------------+ | |
|
||||||
|
| +---------------------------------------------------------------------------+ |
|
||||||
|
| |
|
||||||
|
+--------------------------------------------------------------------------------+
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. Componentes Principales
|
||||||
|
|
||||||
|
### 3.1 Frontend (React + TypeScript)
|
||||||
|
|
||||||
|
| Componente | Descripcion | Archivo |
|
||||||
|
|------------|-------------|---------|
|
||||||
|
| PortfolioDashboard | Vista principal del portfolio | `Portfolio.tsx` |
|
||||||
|
| PositionsTable | Tabla de posiciones | `PositionsTable.tsx` |
|
||||||
|
| AllocationChart | Grafico donut de asignacion | `AllocationChart.tsx` |
|
||||||
|
| PerformanceChart | Grafico de rendimiento | `PerformanceChart.tsx` |
|
||||||
|
| RiskMetricsPanel | Panel de metricas de riesgo | `RiskMetricsPanel.tsx` |
|
||||||
|
| RebalanceModal | Modal de rebalanceo | `RebalanceModal.tsx` |
|
||||||
|
| StressTestSimulator | Simulador de stress test | `StressTestSimulator.tsx` |
|
||||||
|
| GoalTracker | Seguimiento de metas | `GoalTracker.tsx` |
|
||||||
|
| ReportGenerator | Generador de reportes | `ReportGenerator.tsx` |
|
||||||
|
|
||||||
|
### 3.2 Backend (Express.js + TypeScript)
|
||||||
|
|
||||||
|
| Servicio | Responsabilidad | Endpoints |
|
||||||
|
|----------|-----------------|-----------|
|
||||||
|
| PortfolioService | CRUD de portfolios | `/api/portfolio/*` |
|
||||||
|
| PositionService | Gestion de posiciones | `/api/portfolio/positions/*` |
|
||||||
|
| MetricsService | Calculo de metricas | `/api/portfolio/metrics/*` |
|
||||||
|
| RebalanceService | Motor de rebalanceo | `/api/portfolio/rebalance/*` |
|
||||||
|
| GoalService | Gestion de metas | `/api/goals/*` |
|
||||||
|
| StressTestService | Stress testing | `/api/portfolio/stress-test/*` |
|
||||||
|
| ReportService | Generacion de reportes | `/api/portfolio/reports/*` |
|
||||||
|
| TaxReportService | Reportes fiscales | `/api/portfolio/tax/*` |
|
||||||
|
|
||||||
|
### 3.3 Database (PostgreSQL)
|
||||||
|
|
||||||
|
| Tabla | Descripcion | Relaciones |
|
||||||
|
|-------|-------------|------------|
|
||||||
|
| `portfolios` | Portfolios de usuarios | 1:N positions |
|
||||||
|
| `positions` | Posiciones activas | N:1 portfolio |
|
||||||
|
| `transactions` | Historial de transacciones | N:1 portfolio |
|
||||||
|
| `portfolio_snapshots` | Snapshots diarios | N:1 portfolio |
|
||||||
|
| `investment_goals` | Metas de inversion | N:1 user |
|
||||||
|
| `goal_contributions` | Contribuciones a metas | N:1 goal |
|
||||||
|
| `target_allocations` | Asignaciones objetivo | N:1 portfolio |
|
||||||
|
| `rebalance_history` | Historial de rebalanceo | N:1 portfolio |
|
||||||
|
| `risk_metrics` | Metricas de riesgo calculadas | N:1 portfolio |
|
||||||
|
| `stress_test_results` | Resultados de stress tests | N:1 portfolio |
|
||||||
|
| `reports` | Reportes generados | N:1 portfolio |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4. Flujos de Datos
|
||||||
|
|
||||||
|
### 4.1 Flujo de Carga del Dashboard
|
||||||
|
|
||||||
|
```
|
||||||
|
Usuario accede /portfolio
|
||||||
|
|
|
||||||
|
v
|
||||||
|
[Frontend] GET /api/portfolio/{id}
|
||||||
|
|
|
||||||
|
v
|
||||||
|
[PortfolioService] getPortfolioSummary()
|
||||||
|
|
|
||||||
|
+---> [PositionService] getPositions()
|
||||||
|
|
|
||||||
|
+---> [MetricsService] calculateMetrics()
|
||||||
|
|
|
||||||
|
+---> [Cache] Redis (TTL: 15s para precios)
|
||||||
|
|
|
||||||
|
v
|
||||||
|
[Response] PortfolioSummary + Positions + Metrics
|
||||||
|
|
|
||||||
|
v
|
||||||
|
[Frontend] Renderiza Dashboard
|
||||||
|
|
|
||||||
|
v
|
||||||
|
[WebSocket] Suscripcion a updates de precios
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4.2 Flujo de Rebalanceo
|
||||||
|
|
||||||
|
```
|
||||||
|
Usuario solicita rebalanceo
|
||||||
|
|
|
||||||
|
v
|
||||||
|
[Frontend] GET /api/portfolio/rebalance/suggestions
|
||||||
|
|
|
||||||
|
v
|
||||||
|
[RebalanceService] calculateDeviation()
|
||||||
|
|
|
||||||
|
+---> Compara currentAllocation vs targetAllocation
|
||||||
|
|
|
||||||
|
+---> Calcula drift por cada activo
|
||||||
|
|
|
||||||
|
v
|
||||||
|
[RebalanceService] generatePlan()
|
||||||
|
|
|
||||||
|
+---> Determina ordenes: BUY/SELL
|
||||||
|
|
|
||||||
|
+---> Ordena: ventas primero (genera liquidez)
|
||||||
|
|
|
||||||
|
+---> Calcula costos estimados
|
||||||
|
|
|
||||||
|
v
|
||||||
|
[Response] RebalancePlan con ordenes sugeridas
|
||||||
|
|
|
||||||
|
v
|
||||||
|
[Frontend] Muestra preview al usuario
|
||||||
|
|
|
||||||
|
v
|
||||||
|
Usuario confirma
|
||||||
|
|
|
||||||
|
v
|
||||||
|
[Frontend] POST /api/portfolio/rebalance/execute
|
||||||
|
|
|
||||||
|
v
|
||||||
|
[RebalanceService] executePlan()
|
||||||
|
|
|
||||||
|
+---> [OrderService] createOrder() x N
|
||||||
|
|
|
||||||
|
v
|
||||||
|
[TransactionService] recordTransactions()
|
||||||
|
|
|
||||||
|
v
|
||||||
|
[Response] RebalanceResult (success/fail por orden)
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4.3 Flujo de Proyeccion Monte Carlo
|
||||||
|
|
||||||
|
```
|
||||||
|
Usuario solicita proyeccion de meta
|
||||||
|
|
|
||||||
|
v
|
||||||
|
[Frontend] POST /api/goals/{id}/projection
|
||||||
|
|
|
||||||
|
v
|
||||||
|
[GoalProjectionService] calculateProjection()
|
||||||
|
|
|
||||||
|
+---> Obtiene parametros:
|
||||||
|
| - current_amount
|
||||||
|
| - monthly_contribution
|
||||||
|
| - expected_return
|
||||||
|
| - target_date
|
||||||
|
|
|
||||||
|
+---> Ejecuta simulacion Monte Carlo
|
||||||
|
| - 10,000 escenarios
|
||||||
|
| - Distribucion normal de retornos
|
||||||
|
| - Random walk
|
||||||
|
|
|
||||||
|
v
|
||||||
|
[Response] GoalProjection
|
||||||
|
|
|
||||||
|
+---> projectedValue
|
||||||
|
+---> probability_of_success
|
||||||
|
+---> percentiles (P10, P50, P90)
|
||||||
|
+---> requiredContribution (para alcanzar meta)
|
||||||
|
|
|
||||||
|
v
|
||||||
|
[Frontend] Renderiza grafico de proyeccion
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 5. Integraciones Externas
|
||||||
|
|
||||||
|
### 5.1 Market Data Providers
|
||||||
|
|
||||||
|
| Proveedor | Uso | Frecuencia |
|
||||||
|
|-----------|-----|------------|
|
||||||
|
| Binance API | Precios crypto | Real-time |
|
||||||
|
| Alpha Vantage | Datos fundamentales | Diario |
|
||||||
|
| Yahoo Finance | Benchmarks | Diario |
|
||||||
|
| TradingView (futuro) | Charts avanzados | Real-time |
|
||||||
|
|
||||||
|
### 5.2 Servicios Internos
|
||||||
|
|
||||||
|
| Servicio | Puerto | Integracion |
|
||||||
|
|----------|--------|-------------|
|
||||||
|
| MCP-Investment | 3093 | Cuentas de inversion |
|
||||||
|
| MCP-Wallet | 3090 | Balance de wallet |
|
||||||
|
| MCP-Auth | 3095 | Autenticacion |
|
||||||
|
| ML-Engine | 3083 | Predicciones (futuro) |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 6. Seguridad
|
||||||
|
|
||||||
|
### 6.1 Autenticacion y Autorizacion
|
||||||
|
|
||||||
|
- JWT Bearer tokens
|
||||||
|
- Refresh token rotation
|
||||||
|
- Rate limiting: 100 req/min por usuario
|
||||||
|
- Verificacion de ownership en cada request
|
||||||
|
|
||||||
|
### 6.2 Validacion de Datos
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// Ejemplo: validacion de orden de rebalanceo
|
||||||
|
const RebalanceOrderSchema = z.object({
|
||||||
|
portfolioId: z.string().uuid(),
|
||||||
|
orders: z.array(z.object({
|
||||||
|
symbol: z.string().min(1).max(10),
|
||||||
|
action: z.enum(['BUY', 'SELL']),
|
||||||
|
amount: z.number().positive().max(1000000),
|
||||||
|
})),
|
||||||
|
dryRun: z.boolean().default(false),
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
### 6.3 Audit Trail
|
||||||
|
|
||||||
|
- Todas las transacciones registradas
|
||||||
|
- Logs de acceso a datos sensibles
|
||||||
|
- Historial de cambios de configuracion
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 7. Escalabilidad
|
||||||
|
|
||||||
|
### 7.1 Caching Strategy
|
||||||
|
|
||||||
|
| Dato | TTL | Estrategia |
|
||||||
|
|------|-----|------------|
|
||||||
|
| Precios | 15s | Write-through |
|
||||||
|
| Metricas basicas | 1 min | Lazy load |
|
||||||
|
| Metricas avanzadas | 1 hora | Background job |
|
||||||
|
| Snapshots | 24 horas | Scheduled job |
|
||||||
|
|
||||||
|
### 7.2 Background Jobs
|
||||||
|
|
||||||
|
| Job | Frecuencia | Descripcion |
|
||||||
|
|-----|------------|-------------|
|
||||||
|
| SnapshotJob | Diario 00:00 UTC | Captura estado del portfolio |
|
||||||
|
| MetricsJob | Cada 1 hora | Recalcula metricas avanzadas |
|
||||||
|
| AlertsJob | Cada 5 min | Verifica drift y envia alertas |
|
||||||
|
| ReportJob | Bajo demanda | Genera reportes PDF |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 8. Metricas de Rendimiento
|
||||||
|
|
||||||
|
### 8.1 SLAs
|
||||||
|
|
||||||
|
| Operacion | Target | Max |
|
||||||
|
|-----------|--------|-----|
|
||||||
|
| Dashboard load | < 1s | 2s |
|
||||||
|
| Calculo de metricas | < 500ms | 1s |
|
||||||
|
| Simulacion Monte Carlo | < 3s | 5s |
|
||||||
|
| Generacion de PDF | < 10s | 30s |
|
||||||
|
|
||||||
|
### 8.2 Limites del Sistema
|
||||||
|
|
||||||
|
| Recurso | Limite | Razon |
|
||||||
|
|---------|--------|-------|
|
||||||
|
| Posiciones por portfolio | 100 | Performance de calculos |
|
||||||
|
| Escenarios Monte Carlo | 10,000 | Balance precision/tiempo |
|
||||||
|
| Historial de transacciones | 10,000 | Paginacion requerida |
|
||||||
|
| Tamanio de reporte PDF | 10 MB | Limite de descarga |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 9. Stack Tecnologico Detallado
|
||||||
|
|
||||||
|
### 9.1 Frontend
|
||||||
|
|
||||||
|
| Tecnologia | Version | Uso |
|
||||||
|
|------------|---------|-----|
|
||||||
|
| React | 18.x | Framework UI |
|
||||||
|
| TypeScript | 5.x | Tipado estatico |
|
||||||
|
| Zustand | 4.x | State management |
|
||||||
|
| TanStack Query | 5.x | Data fetching |
|
||||||
|
| Recharts | 2.x | Graficos |
|
||||||
|
| TailwindCSS | 3.x | Estilos |
|
||||||
|
| Zod | 3.x | Validacion schemas |
|
||||||
|
|
||||||
|
### 9.2 Backend
|
||||||
|
|
||||||
|
| Tecnologia | Version | Uso |
|
||||||
|
|------------|---------|-----|
|
||||||
|
| Node.js | 20.x LTS | Runtime |
|
||||||
|
| Express.js | 5.x | Framework HTTP |
|
||||||
|
| TypeScript | 5.x | Tipado estatico |
|
||||||
|
| TypeORM | 0.3.x | ORM |
|
||||||
|
| Bull | 4.x | Job queues |
|
||||||
|
| Node-cron | 3.x | Scheduled jobs |
|
||||||
|
| PDFKit | 0.14.x | Generacion PDF |
|
||||||
|
|
||||||
|
### 9.3 Infraestructura
|
||||||
|
|
||||||
|
| Tecnologia | Version | Uso |
|
||||||
|
|------------|---------|-----|
|
||||||
|
| PostgreSQL | 16.x | Database principal |
|
||||||
|
| Redis | 7.x | Cache + queues |
|
||||||
|
| Docker | 24.x | Contenedores |
|
||||||
|
| Nginx | 1.25.x | Reverse proxy |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 10. Referencias
|
||||||
|
|
||||||
|
- [ET-PFM-001: Arquitectura Dashboard](./ET-PFM-001-arquitectura-dashboard.md)
|
||||||
|
- [ET-PFM-002: Calculo de Metricas](./ET-PFM-002-calculo-metricas.md)
|
||||||
|
- [ET-PFM-003: Stress Testing](./ET-PFM-003-stress-testing.md)
|
||||||
|
- [ET-PFM-004: Motor de Rebalanceo](./ET-PFM-004-motor-rebalanceo.md)
|
||||||
|
- [ET-PFM-007: Motor de Metas](./ET-PFM-007-motor-metas.md)
|
||||||
|
- [TRACEABILITY.yml](../implementacion/TRACEABILITY.yml)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
*Especificacion tecnica - Sistema NEXUS*
|
||||||
@ -0,0 +1,874 @@
|
|||||||
|
---
|
||||||
|
id: "ET-PFM-011"
|
||||||
|
title: "Sistema de Goals (Metas de Inversion)"
|
||||||
|
type: "Technical Specification"
|
||||||
|
status: "Done"
|
||||||
|
priority: "Alta"
|
||||||
|
epic: "OQI-008"
|
||||||
|
project: "trading-platform"
|
||||||
|
version: "1.0.0"
|
||||||
|
created_date: "2026-01-28"
|
||||||
|
updated_date: "2026-01-28"
|
||||||
|
---
|
||||||
|
|
||||||
|
# ET-PFM-011: Sistema de Goals (Metas de Inversion)
|
||||||
|
|
||||||
|
**Epica:** OQI-008 - Portfolio Manager
|
||||||
|
**Version:** 1.0
|
||||||
|
**Fecha:** 2026-01-28
|
||||||
|
**Estado:** Planificado
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 1. Vision General
|
||||||
|
|
||||||
|
El Sistema de Goals permite a los usuarios definir, seguir y proyectar metas financieras a largo plazo como retiro, compra de casa, educacion de hijos, etc. Integra simulaciones Monte Carlo para proyectar probabilidades de exito.
|
||||||
|
|
||||||
|
### 1.1 Tipos de Metas Soportadas
|
||||||
|
|
||||||
|
| Tipo | Icono | Descripcion | Horizonte Tipico |
|
||||||
|
|------|-------|-------------|------------------|
|
||||||
|
| `retirement` | 🏖️ | Retiro/Jubilacion | 10-30 anos |
|
||||||
|
| `home` | 🏠 | Compra de casa/enganche | 2-10 anos |
|
||||||
|
| `education` | 🎓 | Educacion de hijos | 5-18 anos |
|
||||||
|
| `emergency` | 🚨 | Fondo de emergencia | 1-2 anos |
|
||||||
|
| `travel` | ✈️ | Viaje mayor | 1-5 anos |
|
||||||
|
| `vehicle` | 🚗 | Compra de vehiculo | 1-5 anos |
|
||||||
|
| `wedding` | 💍 | Boda/evento | 1-3 anos |
|
||||||
|
| `custom` | 🎯 | Meta personalizada | Variable |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. Modelo de Datos
|
||||||
|
|
||||||
|
### 2.1 Entity: InvestmentGoal
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
@Entity('investment_goals')
|
||||||
|
export class InvestmentGoal {
|
||||||
|
@PrimaryGeneratedColumn('uuid')
|
||||||
|
id: string;
|
||||||
|
|
||||||
|
@Column({ name: 'user_id' })
|
||||||
|
@Index()
|
||||||
|
userId: string;
|
||||||
|
|
||||||
|
@Column({ length: 100 })
|
||||||
|
name: string;
|
||||||
|
|
||||||
|
@Column({ length: 500, nullable: true })
|
||||||
|
description: string;
|
||||||
|
|
||||||
|
@Column({
|
||||||
|
type: 'enum',
|
||||||
|
enum: GoalType,
|
||||||
|
default: GoalType.CUSTOM,
|
||||||
|
})
|
||||||
|
type: GoalType;
|
||||||
|
|
||||||
|
@Column('decimal', { precision: 18, scale: 2, name: 'target_amount' })
|
||||||
|
targetAmount: number;
|
||||||
|
|
||||||
|
@Column('decimal', { precision: 18, scale: 2, name: 'current_amount', default: 0 })
|
||||||
|
currentAmount: number;
|
||||||
|
|
||||||
|
@Column('decimal', { precision: 18, scale: 2, name: 'initial_amount', default: 0 })
|
||||||
|
initialAmount: number;
|
||||||
|
|
||||||
|
@Column('decimal', { precision: 18, scale: 2, name: 'monthly_contribution', default: 0 })
|
||||||
|
monthlyContribution: number;
|
||||||
|
|
||||||
|
@Column({ name: 'target_date', type: 'date' })
|
||||||
|
targetDate: Date;
|
||||||
|
|
||||||
|
@Column('decimal', { precision: 5, scale: 2, name: 'expected_return', default: 7.0 })
|
||||||
|
expectedReturn: number; // Annual return %
|
||||||
|
|
||||||
|
@Column('decimal', { precision: 5, scale: 2, name: 'expected_volatility', default: 15.0 })
|
||||||
|
expectedVolatility: number; // Annual volatility %
|
||||||
|
|
||||||
|
@Column({
|
||||||
|
type: 'enum',
|
||||||
|
enum: GoalStatus,
|
||||||
|
default: GoalStatus.ON_TRACK,
|
||||||
|
})
|
||||||
|
status: GoalStatus;
|
||||||
|
|
||||||
|
@Column({
|
||||||
|
type: 'enum',
|
||||||
|
enum: GoalPriority,
|
||||||
|
default: GoalPriority.MEDIUM,
|
||||||
|
})
|
||||||
|
priority: GoalPriority;
|
||||||
|
|
||||||
|
@Column({ name: 'linked_account_id', type: 'uuid', nullable: true })
|
||||||
|
linkedAccountId: string | null;
|
||||||
|
|
||||||
|
@Column({ name: 'is_active', default: true })
|
||||||
|
isActive: boolean;
|
||||||
|
|
||||||
|
@Column('jsonb', { name: 'risk_profile', nullable: true })
|
||||||
|
riskProfile: GoalRiskProfile | null;
|
||||||
|
|
||||||
|
@Column('jsonb', { name: 'last_projection', nullable: true })
|
||||||
|
lastProjection: GoalProjection | null;
|
||||||
|
|
||||||
|
@CreateDateColumn({ name: 'created_at' })
|
||||||
|
createdAt: Date;
|
||||||
|
|
||||||
|
@UpdateDateColumn({ name: 'updated_at' })
|
||||||
|
updatedAt: Date;
|
||||||
|
|
||||||
|
@OneToMany(() => GoalContribution, (c) => c.goal)
|
||||||
|
contributions: GoalContribution[];
|
||||||
|
|
||||||
|
@OneToMany(() => GoalMilestone, (m) => m.goal)
|
||||||
|
milestones: GoalMilestone[];
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2.2 Enums
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
enum GoalType {
|
||||||
|
RETIREMENT = 'retirement',
|
||||||
|
HOME = 'home',
|
||||||
|
EDUCATION = 'education',
|
||||||
|
EMERGENCY = 'emergency',
|
||||||
|
TRAVEL = 'travel',
|
||||||
|
VEHICLE = 'vehicle',
|
||||||
|
WEDDING = 'wedding',
|
||||||
|
CUSTOM = 'custom',
|
||||||
|
}
|
||||||
|
|
||||||
|
enum GoalStatus {
|
||||||
|
ON_TRACK = 'on_track',
|
||||||
|
AHEAD = 'ahead',
|
||||||
|
BEHIND = 'behind',
|
||||||
|
AT_RISK = 'at_risk',
|
||||||
|
ACHIEVED = 'achieved',
|
||||||
|
PAUSED = 'paused',
|
||||||
|
}
|
||||||
|
|
||||||
|
enum GoalPriority {
|
||||||
|
HIGH = 'high',
|
||||||
|
MEDIUM = 'medium',
|
||||||
|
LOW = 'low',
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2.3 Entity: GoalContribution
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
@Entity('goal_contributions')
|
||||||
|
export class GoalContribution {
|
||||||
|
@PrimaryGeneratedColumn('uuid')
|
||||||
|
id: string;
|
||||||
|
|
||||||
|
@Column({ name: 'goal_id' })
|
||||||
|
goalId: string;
|
||||||
|
|
||||||
|
@ManyToOne(() => InvestmentGoal, (g) => g.contributions)
|
||||||
|
@JoinColumn({ name: 'goal_id' })
|
||||||
|
goal: InvestmentGoal;
|
||||||
|
|
||||||
|
@Column('decimal', { precision: 18, scale: 2 })
|
||||||
|
amount: number;
|
||||||
|
|
||||||
|
@Column({
|
||||||
|
type: 'enum',
|
||||||
|
enum: ContributionType,
|
||||||
|
default: ContributionType.DEPOSIT,
|
||||||
|
})
|
||||||
|
type: ContributionType;
|
||||||
|
|
||||||
|
@Column({ nullable: true })
|
||||||
|
source: string; // 'manual', 'automatic', 'dividend', 'interest'
|
||||||
|
|
||||||
|
@Column({ type: 'text', nullable: true })
|
||||||
|
notes: string;
|
||||||
|
|
||||||
|
@Column({ name: 'transaction_id', nullable: true })
|
||||||
|
transactionId: string;
|
||||||
|
|
||||||
|
@CreateDateColumn({ name: 'contributed_at' })
|
||||||
|
contributedAt: Date;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum ContributionType {
|
||||||
|
DEPOSIT = 'deposit',
|
||||||
|
WITHDRAWAL = 'withdrawal',
|
||||||
|
INTEREST = 'interest',
|
||||||
|
DIVIDEND = 'dividend',
|
||||||
|
ADJUSTMENT = 'adjustment',
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2.4 Entity: GoalMilestone
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
@Entity('goal_milestones')
|
||||||
|
export class GoalMilestone {
|
||||||
|
@PrimaryGeneratedColumn('uuid')
|
||||||
|
id: string;
|
||||||
|
|
||||||
|
@Column({ name: 'goal_id' })
|
||||||
|
goalId: string;
|
||||||
|
|
||||||
|
@ManyToOne(() => InvestmentGoal, (g) => g.milestones)
|
||||||
|
@JoinColumn({ name: 'goal_id' })
|
||||||
|
goal: InvestmentGoal;
|
||||||
|
|
||||||
|
@Column({ length: 100 })
|
||||||
|
name: string;
|
||||||
|
|
||||||
|
@Column('decimal', { precision: 18, scale: 2, name: 'target_amount' })
|
||||||
|
targetAmount: number;
|
||||||
|
|
||||||
|
@Column('decimal', { precision: 5, scale: 2, name: 'target_percentage' })
|
||||||
|
targetPercentage: number; // % of goal
|
||||||
|
|
||||||
|
@Column({ name: 'target_date', type: 'date', nullable: true })
|
||||||
|
targetDate: Date | null;
|
||||||
|
|
||||||
|
@Column({ name: 'achieved_at', type: 'timestamp', nullable: true })
|
||||||
|
achievedAt: Date | null;
|
||||||
|
|
||||||
|
@Column({ default: false })
|
||||||
|
isAchieved: boolean;
|
||||||
|
|
||||||
|
@CreateDateColumn({ name: 'created_at' })
|
||||||
|
createdAt: Date;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. Interfaces de Proyeccion
|
||||||
|
|
||||||
|
### 3.1 GoalProjection
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
interface GoalProjection {
|
||||||
|
// Metadata
|
||||||
|
goalId: string;
|
||||||
|
calculatedAt: Date;
|
||||||
|
|
||||||
|
// Current State
|
||||||
|
currentAmount: number;
|
||||||
|
targetAmount: number;
|
||||||
|
progressPercent: number;
|
||||||
|
monthsRemaining: number;
|
||||||
|
|
||||||
|
// Projections
|
||||||
|
projectedValue: number;
|
||||||
|
projectedProgress: number;
|
||||||
|
shortfall: number;
|
||||||
|
|
||||||
|
// Probability Analysis
|
||||||
|
probabilityOfSuccess: number;
|
||||||
|
confidenceInterval: {
|
||||||
|
low: number; // P10
|
||||||
|
mid: number; // P50 (median)
|
||||||
|
high: number; // P90
|
||||||
|
};
|
||||||
|
|
||||||
|
// Scenarios
|
||||||
|
scenarios: GoalScenarios;
|
||||||
|
|
||||||
|
// Recommendations
|
||||||
|
requiredMonthlyContribution: number;
|
||||||
|
suggestedActions: string[];
|
||||||
|
}
|
||||||
|
|
||||||
|
interface GoalScenarios {
|
||||||
|
optimistic: ScenarioResult;
|
||||||
|
base: ScenarioResult;
|
||||||
|
pessimistic: ScenarioResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ScenarioResult {
|
||||||
|
projectedValue: number;
|
||||||
|
endDate: Date;
|
||||||
|
returnRate: number;
|
||||||
|
probabilityOfSuccess: number;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3.2 MonteCarloParams
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
interface MonteCarloParams {
|
||||||
|
initialAmount: number;
|
||||||
|
monthlyContribution: number;
|
||||||
|
expectedReturn: number; // Annual, e.g., 0.07 for 7%
|
||||||
|
volatility: number; // Annual, e.g., 0.15 for 15%
|
||||||
|
months: number;
|
||||||
|
numSimulations: number; // Default: 10000
|
||||||
|
targetAmount: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface MonteCarloResult {
|
||||||
|
simulations: number[][]; // [sim][month]
|
||||||
|
finalValues: number[]; // Final value per simulation
|
||||||
|
percentiles: {
|
||||||
|
p10: number;
|
||||||
|
p25: number;
|
||||||
|
p50: number;
|
||||||
|
p75: number;
|
||||||
|
p90: number;
|
||||||
|
p95: number;
|
||||||
|
};
|
||||||
|
probabilityOfSuccess: number;
|
||||||
|
averageFinalValue: number;
|
||||||
|
medianFinalValue: number;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4. Servicio de Goals
|
||||||
|
|
||||||
|
### 4.1 GoalService
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
@Injectable()
|
||||||
|
export class GoalService {
|
||||||
|
constructor(
|
||||||
|
@InjectRepository(InvestmentGoal)
|
||||||
|
private goalRepo: Repository<InvestmentGoal>,
|
||||||
|
@InjectRepository(GoalContribution)
|
||||||
|
private contributionRepo: Repository<GoalContribution>,
|
||||||
|
private projectionService: GoalProjectionService,
|
||||||
|
private eventEmitter: EventEmitter2,
|
||||||
|
) {}
|
||||||
|
|
||||||
|
async createGoal(dto: CreateGoalDto): Promise<InvestmentGoal> {
|
||||||
|
const goal = this.goalRepo.create({
|
||||||
|
...dto,
|
||||||
|
status: GoalStatus.ON_TRACK,
|
||||||
|
currentAmount: dto.initialAmount || 0,
|
||||||
|
});
|
||||||
|
|
||||||
|
// Create default milestones
|
||||||
|
goal.milestones = this.createDefaultMilestones(goal);
|
||||||
|
|
||||||
|
const saved = await this.goalRepo.save(goal);
|
||||||
|
|
||||||
|
// Calculate initial projection
|
||||||
|
const projection = await this.projectionService.calculateProjection(saved);
|
||||||
|
saved.lastProjection = projection;
|
||||||
|
saved.status = this.determineStatus(projection);
|
||||||
|
|
||||||
|
await this.goalRepo.save(saved);
|
||||||
|
this.eventEmitter.emit('goal.created', saved);
|
||||||
|
|
||||||
|
return saved;
|
||||||
|
}
|
||||||
|
|
||||||
|
async addContribution(
|
||||||
|
goalId: string,
|
||||||
|
dto: AddContributionDto
|
||||||
|
): Promise<GoalContribution> {
|
||||||
|
const goal = await this.getGoalById(goalId);
|
||||||
|
|
||||||
|
const contribution = this.contributionRepo.create({
|
||||||
|
goalId,
|
||||||
|
...dto,
|
||||||
|
});
|
||||||
|
|
||||||
|
await this.contributionRepo.save(contribution);
|
||||||
|
|
||||||
|
// Update goal current amount
|
||||||
|
const delta = dto.type === ContributionType.WITHDRAWAL
|
||||||
|
? -dto.amount
|
||||||
|
: dto.amount;
|
||||||
|
|
||||||
|
goal.currentAmount = Number(goal.currentAmount) + delta;
|
||||||
|
|
||||||
|
// Recalculate projection
|
||||||
|
const projection = await this.projectionService.calculateProjection(goal);
|
||||||
|
goal.lastProjection = projection;
|
||||||
|
goal.status = this.determineStatus(projection);
|
||||||
|
|
||||||
|
// Check milestones
|
||||||
|
await this.checkMilestones(goal);
|
||||||
|
|
||||||
|
await this.goalRepo.save(goal);
|
||||||
|
this.eventEmitter.emit('goal.contribution.added', { goal, contribution });
|
||||||
|
|
||||||
|
return contribution;
|
||||||
|
}
|
||||||
|
|
||||||
|
async getGoalsByUser(userId: string): Promise<InvestmentGoal[]> {
|
||||||
|
return this.goalRepo.find({
|
||||||
|
where: { userId, isActive: true },
|
||||||
|
relations: ['contributions', 'milestones'],
|
||||||
|
order: { priority: 'ASC', targetDate: 'ASC' },
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async getGoalProgress(goalId: string): Promise<GoalProgressDto> {
|
||||||
|
const goal = await this.getGoalById(goalId);
|
||||||
|
const projection = await this.projectionService.calculateProjection(goal);
|
||||||
|
|
||||||
|
const contributions = await this.contributionRepo.find({
|
||||||
|
where: { goalId },
|
||||||
|
order: { contributedAt: 'DESC' },
|
||||||
|
take: 12, // Last 12 contributions
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
goal,
|
||||||
|
projection,
|
||||||
|
contributions,
|
||||||
|
milestones: goal.milestones.map(m => ({
|
||||||
|
...m,
|
||||||
|
progress: (goal.currentAmount / m.targetAmount) * 100,
|
||||||
|
})),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private createDefaultMilestones(goal: InvestmentGoal): GoalMilestone[] {
|
||||||
|
return [
|
||||||
|
{ name: '25% alcanzado', targetPercentage: 25, targetAmount: goal.targetAmount * 0.25 },
|
||||||
|
{ name: '50% alcanzado', targetPercentage: 50, targetAmount: goal.targetAmount * 0.50 },
|
||||||
|
{ name: '75% alcanzado', targetPercentage: 75, targetAmount: goal.targetAmount * 0.75 },
|
||||||
|
{ name: 'Meta completada', targetPercentage: 100, targetAmount: goal.targetAmount },
|
||||||
|
].map(m => this.milestoneRepo.create({ ...m, goalId: goal.id }));
|
||||||
|
}
|
||||||
|
|
||||||
|
private determineStatus(projection: GoalProjection): GoalStatus {
|
||||||
|
if (projection.probabilityOfSuccess >= 95) return GoalStatus.AHEAD;
|
||||||
|
if (projection.probabilityOfSuccess >= 75) return GoalStatus.ON_TRACK;
|
||||||
|
if (projection.probabilityOfSuccess >= 50) return GoalStatus.BEHIND;
|
||||||
|
return GoalStatus.AT_RISK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 5. Servicio de Proyeccion
|
||||||
|
|
||||||
|
### 5.1 GoalProjectionService
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
@Injectable()
|
||||||
|
export class GoalProjectionService {
|
||||||
|
|
||||||
|
async calculateProjection(goal: InvestmentGoal): Promise<GoalProjection> {
|
||||||
|
const monthsRemaining = this.getMonthsRemaining(goal.targetDate);
|
||||||
|
|
||||||
|
// Deterministic projection (Future Value formula)
|
||||||
|
const projectedValue = this.calculateFutureValue(
|
||||||
|
goal.currentAmount,
|
||||||
|
goal.monthlyContribution,
|
||||||
|
goal.expectedReturn / 100 / 12, // Monthly rate
|
||||||
|
monthsRemaining
|
||||||
|
);
|
||||||
|
|
||||||
|
// Monte Carlo simulation
|
||||||
|
const mcResult = await this.runMonteCarloSimulation({
|
||||||
|
initialAmount: Number(goal.currentAmount),
|
||||||
|
monthlyContribution: Number(goal.monthlyContribution),
|
||||||
|
expectedReturn: goal.expectedReturn / 100,
|
||||||
|
volatility: goal.expectedVolatility / 100,
|
||||||
|
months: monthsRemaining,
|
||||||
|
numSimulations: 10000,
|
||||||
|
targetAmount: Number(goal.targetAmount),
|
||||||
|
});
|
||||||
|
|
||||||
|
const progressPercent = (goal.currentAmount / goal.targetAmount) * 100;
|
||||||
|
const projectedProgress = (projectedValue / goal.targetAmount) * 100;
|
||||||
|
|
||||||
|
return {
|
||||||
|
goalId: goal.id,
|
||||||
|
calculatedAt: new Date(),
|
||||||
|
|
||||||
|
currentAmount: Number(goal.currentAmount),
|
||||||
|
targetAmount: Number(goal.targetAmount),
|
||||||
|
progressPercent,
|
||||||
|
monthsRemaining,
|
||||||
|
|
||||||
|
projectedValue,
|
||||||
|
projectedProgress,
|
||||||
|
shortfall: Math.max(0, Number(goal.targetAmount) - projectedValue),
|
||||||
|
|
||||||
|
probabilityOfSuccess: mcResult.probabilityOfSuccess,
|
||||||
|
confidenceInterval: {
|
||||||
|
low: mcResult.percentiles.p10,
|
||||||
|
mid: mcResult.percentiles.p50,
|
||||||
|
high: mcResult.percentiles.p90,
|
||||||
|
},
|
||||||
|
|
||||||
|
scenarios: this.calculateScenarios(goal, monthsRemaining),
|
||||||
|
|
||||||
|
requiredMonthlyContribution: this.calculateRequiredContribution(goal),
|
||||||
|
suggestedActions: this.generateSuggestions(goal, mcResult.probabilityOfSuccess),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Future Value with regular deposits
|
||||||
|
* FV = PV(1+r)^n + PMT × ((1+r)^n - 1) / r
|
||||||
|
*/
|
||||||
|
private calculateFutureValue(
|
||||||
|
presentValue: number,
|
||||||
|
monthlyPayment: number,
|
||||||
|
monthlyRate: number,
|
||||||
|
months: number
|
||||||
|
): number {
|
||||||
|
if (monthlyRate === 0) {
|
||||||
|
return presentValue + monthlyPayment * months;
|
||||||
|
}
|
||||||
|
|
||||||
|
const growthFactor = Math.pow(1 + monthlyRate, months);
|
||||||
|
const fvOfPresentValue = presentValue * growthFactor;
|
||||||
|
const fvOfPayments = monthlyPayment * ((growthFactor - 1) / monthlyRate);
|
||||||
|
|
||||||
|
return fvOfPresentValue + fvOfPayments;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Monte Carlo Simulation
|
||||||
|
* Geometric Brownian Motion: S(t+1) = S(t) * exp((mu - sigma^2/2)*dt + sigma*sqrt(dt)*Z)
|
||||||
|
*/
|
||||||
|
async runMonteCarloSimulation(params: MonteCarloParams): Promise<MonteCarloResult> {
|
||||||
|
const { initialAmount, monthlyContribution, expectedReturn, volatility, months, numSimulations, targetAmount } = params;
|
||||||
|
|
||||||
|
const monthlyReturn = expectedReturn / 12;
|
||||||
|
const monthlyVolatility = volatility / Math.sqrt(12);
|
||||||
|
const dt = 1; // 1 month
|
||||||
|
|
||||||
|
const simulations: number[][] = [];
|
||||||
|
const finalValues: number[] = [];
|
||||||
|
|
||||||
|
for (let sim = 0; sim < numSimulations; sim++) {
|
||||||
|
const path: number[] = [initialAmount];
|
||||||
|
let value = initialAmount;
|
||||||
|
|
||||||
|
for (let month = 1; month <= months; month++) {
|
||||||
|
// Random normal (Box-Muller transform)
|
||||||
|
const z = this.randomNormal();
|
||||||
|
|
||||||
|
// GBM step
|
||||||
|
const drift = (monthlyReturn - 0.5 * monthlyVolatility ** 2) * dt;
|
||||||
|
const diffusion = monthlyVolatility * Math.sqrt(dt) * z;
|
||||||
|
value = value * Math.exp(drift + diffusion) + monthlyContribution;
|
||||||
|
|
||||||
|
path.push(Math.max(0, value)); // No negative values
|
||||||
|
}
|
||||||
|
|
||||||
|
simulations.push(path);
|
||||||
|
finalValues.push(path[path.length - 1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sort for percentile calculation
|
||||||
|
const sorted = [...finalValues].sort((a, b) => a - b);
|
||||||
|
|
||||||
|
const percentile = (p: number) => sorted[Math.floor(p * numSimulations)];
|
||||||
|
|
||||||
|
const successCount = finalValues.filter(v => v >= targetAmount).length;
|
||||||
|
|
||||||
|
return {
|
||||||
|
simulations,
|
||||||
|
finalValues,
|
||||||
|
percentiles: {
|
||||||
|
p10: percentile(0.10),
|
||||||
|
p25: percentile(0.25),
|
||||||
|
p50: percentile(0.50),
|
||||||
|
p75: percentile(0.75),
|
||||||
|
p90: percentile(0.90),
|
||||||
|
p95: percentile(0.95),
|
||||||
|
},
|
||||||
|
probabilityOfSuccess: (successCount / numSimulations) * 100,
|
||||||
|
averageFinalValue: finalValues.reduce((a, b) => a + b, 0) / numSimulations,
|
||||||
|
medianFinalValue: percentile(0.50),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Box-Muller transform for normal distribution
|
||||||
|
*/
|
||||||
|
private randomNormal(): number {
|
||||||
|
const u1 = Math.random();
|
||||||
|
const u2 = Math.random();
|
||||||
|
return Math.sqrt(-2 * Math.log(u1)) * Math.cos(2 * Math.PI * u2);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculate required monthly contribution to reach target
|
||||||
|
* PMT = (FV - PV(1+r)^n) × r / ((1+r)^n - 1)
|
||||||
|
*/
|
||||||
|
calculateRequiredContribution(goal: InvestmentGoal): number {
|
||||||
|
const months = this.getMonthsRemaining(goal.targetDate);
|
||||||
|
const monthlyRate = goal.expectedReturn / 100 / 12;
|
||||||
|
|
||||||
|
if (months <= 0) return 0;
|
||||||
|
if (monthlyRate === 0) {
|
||||||
|
return (Number(goal.targetAmount) - Number(goal.currentAmount)) / months;
|
||||||
|
}
|
||||||
|
|
||||||
|
const growthFactor = Math.pow(1 + monthlyRate, months);
|
||||||
|
const fvOfCurrent = Number(goal.currentAmount) * growthFactor;
|
||||||
|
const remaining = Number(goal.targetAmount) - fvOfCurrent;
|
||||||
|
|
||||||
|
if (remaining <= 0) return 0;
|
||||||
|
|
||||||
|
const factor = (growthFactor - 1) / monthlyRate;
|
||||||
|
return remaining / factor;
|
||||||
|
}
|
||||||
|
|
||||||
|
private calculateScenarios(goal: InvestmentGoal, months: number): GoalScenarios {
|
||||||
|
return {
|
||||||
|
optimistic: this.projectWithReturn(goal, months, goal.expectedReturn + 3),
|
||||||
|
base: this.projectWithReturn(goal, months, goal.expectedReturn),
|
||||||
|
pessimistic: this.projectWithReturn(goal, months, goal.expectedReturn - 3),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private projectWithReturn(goal: InvestmentGoal, months: number, annualReturn: number): ScenarioResult {
|
||||||
|
const monthlyRate = annualReturn / 100 / 12;
|
||||||
|
const projectedValue = this.calculateFutureValue(
|
||||||
|
Number(goal.currentAmount),
|
||||||
|
Number(goal.monthlyContribution),
|
||||||
|
monthlyRate,
|
||||||
|
months
|
||||||
|
);
|
||||||
|
|
||||||
|
return {
|
||||||
|
projectedValue,
|
||||||
|
endDate: goal.targetDate,
|
||||||
|
returnRate: annualReturn,
|
||||||
|
probabilityOfSuccess: projectedValue >= Number(goal.targetAmount) ? 100 : (projectedValue / Number(goal.targetAmount)) * 100,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private generateSuggestions(goal: InvestmentGoal, probability: number): string[] {
|
||||||
|
const suggestions: string[] = [];
|
||||||
|
|
||||||
|
if (probability < 50) {
|
||||||
|
const required = this.calculateRequiredContribution(goal);
|
||||||
|
const increase = required - Number(goal.monthlyContribution);
|
||||||
|
if (increase > 0) {
|
||||||
|
suggestions.push(`Incrementar aportacion mensual en $${increase.toFixed(0)} para alcanzar meta`);
|
||||||
|
}
|
||||||
|
suggestions.push('Considerar extender la fecha objetivo');
|
||||||
|
suggestions.push('Evaluar perfil de riesgo para mayor rendimiento esperado');
|
||||||
|
} else if (probability < 75) {
|
||||||
|
suggestions.push('Meta en riesgo. Considerar aumentar aportaciones');
|
||||||
|
} else if (probability < 95) {
|
||||||
|
suggestions.push('Meta en buen camino. Mantener aportaciones actuales');
|
||||||
|
} else {
|
||||||
|
suggestions.push('Excelente progreso! Meta muy probable de alcanzar');
|
||||||
|
}
|
||||||
|
|
||||||
|
return suggestions;
|
||||||
|
}
|
||||||
|
|
||||||
|
private getMonthsRemaining(targetDate: Date): number {
|
||||||
|
const now = new Date();
|
||||||
|
const target = new Date(targetDate);
|
||||||
|
return Math.max(0, (target.getFullYear() - now.getFullYear()) * 12 +
|
||||||
|
(target.getMonth() - now.getMonth()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 6. API Endpoints
|
||||||
|
|
||||||
|
### 6.1 Goals CRUD
|
||||||
|
|
||||||
|
| Method | Endpoint | Descripcion |
|
||||||
|
|--------|----------|-------------|
|
||||||
|
| GET | `/api/goals` | Lista de metas del usuario |
|
||||||
|
| POST | `/api/goals` | Crear nueva meta |
|
||||||
|
| GET | `/api/goals/:id` | Detalle de meta |
|
||||||
|
| PUT | `/api/goals/:id` | Actualizar meta |
|
||||||
|
| DELETE | `/api/goals/:id` | Eliminar meta |
|
||||||
|
| PATCH | `/api/goals/:id/pause` | Pausar meta |
|
||||||
|
| PATCH | `/api/goals/:id/resume` | Reanudar meta |
|
||||||
|
|
||||||
|
### 6.2 Contributions
|
||||||
|
|
||||||
|
| Method | Endpoint | Descripcion |
|
||||||
|
|--------|----------|-------------|
|
||||||
|
| GET | `/api/goals/:id/contributions` | Historial de contribuciones |
|
||||||
|
| POST | `/api/goals/:id/contributions` | Agregar contribucion |
|
||||||
|
|
||||||
|
### 6.3 Projections & Analytics
|
||||||
|
|
||||||
|
| Method | Endpoint | Descripcion |
|
||||||
|
|--------|----------|-------------|
|
||||||
|
| GET | `/api/goals/:id/progress` | Progreso con proyeccion |
|
||||||
|
| GET | `/api/goals/:id/projection` | Proyeccion Monte Carlo |
|
||||||
|
| POST | `/api/goals/:id/simulate` | Simular escenarios custom |
|
||||||
|
| GET | `/api/goals/:id/milestones` | Estado de milestones |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 7. Componentes Frontend
|
||||||
|
|
||||||
|
### 7.1 GoalDashboard
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
interface GoalDashboardProps {
|
||||||
|
userId: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Componentes hijos:
|
||||||
|
// - GoalSummaryCard: Resumen de todas las metas
|
||||||
|
// - GoalList: Lista de metas con progreso
|
||||||
|
// - AddGoalButton: Crear nueva meta
|
||||||
|
```
|
||||||
|
|
||||||
|
### 7.2 GoalCard
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
interface GoalCardProps {
|
||||||
|
goal: InvestmentGoal;
|
||||||
|
onEdit: () => void;
|
||||||
|
onContribute: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Muestra:
|
||||||
|
// - Nombre e icono del tipo
|
||||||
|
// - Barra de progreso visual
|
||||||
|
// - Monto actual / objetivo
|
||||||
|
// - Fecha objetivo
|
||||||
|
// - Estado (on_track, behind, etc.)
|
||||||
|
// - Probabilidad de exito
|
||||||
|
```
|
||||||
|
|
||||||
|
### 7.3 GoalProjectionChart
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
interface GoalProjectionChartProps {
|
||||||
|
projection: GoalProjection;
|
||||||
|
height?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Grafico que muestra:
|
||||||
|
// - Linea de progreso actual
|
||||||
|
// - Bandas de confianza (P10, P50, P90)
|
||||||
|
// - Linea objetivo
|
||||||
|
// - Fecha objetivo
|
||||||
|
```
|
||||||
|
|
||||||
|
### 7.4 GoalWizard
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
interface GoalWizardProps {
|
||||||
|
onComplete: (goal: InvestmentGoal) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pasos:
|
||||||
|
// 1. Seleccionar tipo de meta
|
||||||
|
// 2. Definir nombre y monto objetivo
|
||||||
|
// 3. Fecha objetivo
|
||||||
|
// 4. Aportacion mensual inicial
|
||||||
|
// 5. Perfil de riesgo (conservador/moderado/agresivo)
|
||||||
|
// 6. Confirmar y ver proyeccion inicial
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 8. Configuraciones por Tipo de Meta
|
||||||
|
|
||||||
|
### 8.1 Defaults por Tipo
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
const GOAL_DEFAULTS: Record<GoalType, GoalDefaults> = {
|
||||||
|
retirement: {
|
||||||
|
expectedReturn: 7.0,
|
||||||
|
expectedVolatility: 12.0,
|
||||||
|
suggestedHorizon: '20+ years',
|
||||||
|
riskProfile: 'moderate',
|
||||||
|
},
|
||||||
|
home: {
|
||||||
|
expectedReturn: 5.0,
|
||||||
|
expectedVolatility: 8.0,
|
||||||
|
suggestedHorizon: '3-7 years',
|
||||||
|
riskProfile: 'conservative',
|
||||||
|
},
|
||||||
|
education: {
|
||||||
|
expectedReturn: 6.0,
|
||||||
|
expectedVolatility: 10.0,
|
||||||
|
suggestedHorizon: '5-18 years',
|
||||||
|
riskProfile: 'moderate',
|
||||||
|
},
|
||||||
|
emergency: {
|
||||||
|
expectedReturn: 2.0,
|
||||||
|
expectedVolatility: 2.0,
|
||||||
|
suggestedHorizon: '6-12 months',
|
||||||
|
riskProfile: 'conservative',
|
||||||
|
},
|
||||||
|
travel: {
|
||||||
|
expectedReturn: 4.0,
|
||||||
|
expectedVolatility: 5.0,
|
||||||
|
suggestedHorizon: '1-3 years',
|
||||||
|
riskProfile: 'conservative',
|
||||||
|
},
|
||||||
|
vehicle: {
|
||||||
|
expectedReturn: 4.0,
|
||||||
|
expectedVolatility: 6.0,
|
||||||
|
suggestedHorizon: '1-5 years',
|
||||||
|
riskProfile: 'conservative',
|
||||||
|
},
|
||||||
|
wedding: {
|
||||||
|
expectedReturn: 3.0,
|
||||||
|
expectedVolatility: 4.0,
|
||||||
|
suggestedHorizon: '1-3 years',
|
||||||
|
riskProfile: 'conservative',
|
||||||
|
},
|
||||||
|
custom: {
|
||||||
|
expectedReturn: 5.0,
|
||||||
|
expectedVolatility: 10.0,
|
||||||
|
suggestedHorizon: 'Variable',
|
||||||
|
riskProfile: 'moderate',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 9. Notificaciones y Alertas
|
||||||
|
|
||||||
|
### 9.1 Eventos de Notificacion
|
||||||
|
|
||||||
|
| Evento | Trigger | Canal |
|
||||||
|
|--------|---------|-------|
|
||||||
|
| `goal.milestone.reached` | Progreso >= milestone % | Push, Email |
|
||||||
|
| `goal.status.changed` | Status cambia a behind/at_risk | Push, Email |
|
||||||
|
| `goal.achieved` | Monto actual >= objetivo | Push, Email, Celebracion UI |
|
||||||
|
| `goal.contribution.reminder` | Dia de aportacion programada | Push |
|
||||||
|
| `goal.review.monthly` | Primer dia del mes | Email digest |
|
||||||
|
|
||||||
|
### 9.2 Configuracion de Alertas
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
interface GoalAlertSettings {
|
||||||
|
goalId: string;
|
||||||
|
milestoneAlerts: boolean;
|
||||||
|
statusChangeAlerts: boolean;
|
||||||
|
contributionReminders: boolean;
|
||||||
|
reminderDayOfMonth: number; // 1-28
|
||||||
|
channels: ('push' | 'email' | 'sms')[];
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 10. Referencias
|
||||||
|
|
||||||
|
- [ET-PFM-007: Motor de Metas](./ET-PFM-007-motor-metas.md)
|
||||||
|
- [RF-PFM-007: Metas de Inversion](../requerimientos/RF-PFM-007-metas-inversion.md)
|
||||||
|
- [US-PFM-012: Reporte Fiscal](../historias-usuario/US-PFM-012-reporte-fiscal.md)
|
||||||
|
- [TRACEABILITY.yml](../implementacion/TRACEABILITY.yml)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
*Especificacion tecnica - Sistema NEXUS*
|
||||||
@ -1,21 +1,35 @@
|
|||||||
# TRACEABILITY.yml - OQI-008 Portfolio Manager
|
# TRACEABILITY.yml - OQI-008 Portfolio Manager
|
||||||
# Mapeo de requerimientos a implementación
|
# Mapeo de requerimientos a implementacion
|
||||||
|
|
||||||
version: "1.0.0"
|
version: "1.1.0"
|
||||||
epic: OQI-008
|
epic: OQI-008
|
||||||
name: "Portfolio Manager Avanzado"
|
name: "Portfolio Manager Avanzado"
|
||||||
updated: "2025-12-05"
|
updated: "2026-01-28"
|
||||||
status: planned
|
status: planned
|
||||||
|
|
||||||
# Resumen de trazabilidad
|
# Resumen de trazabilidad
|
||||||
summary:
|
summary:
|
||||||
total_requirements: 7
|
total_requirements: 7
|
||||||
total_specs: 7
|
total_specs: 11
|
||||||
total_user_stories: 12
|
total_user_stories: 14
|
||||||
total_files_to_implement: 50
|
total_files_to_implement: 55
|
||||||
test_coverage: "TBD"
|
test_coverage: "TBD"
|
||||||
story_points: 65
|
story_points: 75
|
||||||
phase: 2
|
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
|
# Mapeo de Requerimientos Funcionales
|
||||||
requirements:
|
requirements:
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user