From c18459558fb02d8435643eaf005964c2fea09fe4 Mon Sep 17 00:00:00 2001 From: Adrian Flores Cortes Date: Mon, 26 Jan 2026 17:02:41 -0600 Subject: [PATCH] fix(coherence): Create centralized portfolio types (E-COH-004, ST1.3) - Created src/types/portfolio.types.ts - Added all portfolio type definitions aligned with DDL - Includes WebSocket event types for real-time updates - Types match backend portfolio.types.ts structure Part of coherence gap fix E-COH-004 - Frontend portfolio types. Types align with DDL schema (portfolio.* enums and tables). Co-Authored-By: Claude Opus 4.5 --- src/types/portfolio.types.ts | 227 +++++++++++++++++++++++++++++++++++ 1 file changed, 227 insertions(+) create mode 100644 src/types/portfolio.types.ts diff --git a/src/types/portfolio.types.ts b/src/types/portfolio.types.ts new file mode 100644 index 0000000..053776f --- /dev/null +++ b/src/types/portfolio.types.ts @@ -0,0 +1,227 @@ +/** + * Portfolio Module Types + * Type definitions for portfolio management, allocations, goals, and rebalancing + * Aligned with portfolio schema DDL (00-enums.sql) + */ + +// ============================================================================ +// Portfolio Enums (Alineado con portfolio.* DDL) +// ============================================================================ + +// Alineado con portfolio.risk_profile (DDL) +export type RiskProfile = 'conservative' | 'moderate' | 'aggressive'; + +// Alineado con portfolio.goal_status (DDL) +export type GoalStatus = 'active' | 'completed' | 'abandoned'; + +// Alineado con portfolio.rebalance_action (DDL) +export type RebalanceAction = 'buy' | 'sell' | 'hold'; + +// Alineado con portfolio.allocation_status (DDL) +export type AllocationStatus = 'active' | 'inactive' | 'rebalancing'; + +// ============================================================================ +// Portfolio Interfaces +// ============================================================================ + +export interface Portfolio { + id: string; + userId: string; + name: string; + description: string | null; + riskProfile: RiskProfile; + totalValue: number; + totalCost: number; + unrealizedPnl: number; + unrealizedPnlPercent: number; + dayChangePercent: number; + weekChangePercent: number; + monthChangePercent: number; + allTimeChangePercent: number; + isActive: boolean; + isPrimary: boolean; + lastRebalancedAt: Date | null; + createdAt: Date; + updatedAt: Date; +} + +export interface PortfolioAllocation { + id: string; + portfolioId: string; + asset: string; + targetPercent: number; + currentPercent: number; + deviation: number; + quantity: number; + avgCost: number; + currentPrice: number; + value: number; + cost: number; + pnl: number; + pnlPercent: number; + status: AllocationStatus; + lastUpdatedAt: Date; + createdAt: Date; +} + +export interface PortfolioGoal { + id: string; + userId: string; + portfolioId: string | null; + name: string; + description: string | null; + targetAmount: number; + currentAmount: number; + targetDate: Date; + monthlyContribution: number; + progress: number; + projectedCompletionDate: Date | null; + monthsRemaining: number | null; + requiredMonthlyContribution: number | null; + status: GoalStatus; + completedAt: Date | null; + createdAt: Date; + updatedAt: Date; +} + +export interface RebalanceHistory { + id: string; + portfolioId: string; + asset: string; + action: RebalanceAction; + targetPercent: number; + actualPercentBefore: number; + actualPercentAfter: number; + quantityChange: number; + valueChange: number; + priceAtRebalance: number; + executedAt: Date; + executionStatus: string; + executionNotes: string | null; + createdAt: Date; +} + +export interface PortfolioSnapshot { + id: string; + portfolioId: string; + snapshotDate: Date; + totalValue: number; + totalCost: number; + unrealizedPnl: number; + unrealizedPnlPercent: number; + dayChange: number; + dayChangePercent: number; + allocations: Record | null; + createdAt: Date; +} + +// ============================================================================ +// API Request/Response Types +// ============================================================================ + +export interface CreatePortfolioRequest { + name: string; + description?: string; + riskProfile: RiskProfile; +} + +export interface UpdatePortfolioRequest { + name?: string; + description?: string; + riskProfile?: RiskProfile; + isActive?: boolean; + isPrimary?: boolean; +} + +export interface CreateAllocationRequest { + portfolioId: string; + asset: string; + targetPercent: number; + quantity?: number; + avgCost?: number; +} + +export interface UpdateAllocationRequest { + targetPercent?: number; + quantity?: number; + avgCost?: number; + status?: AllocationStatus; +} + +export interface CreateGoalRequest { + portfolioId?: string; + name: string; + description?: string; + targetAmount: number; + targetDate: string; + monthlyContribution?: number; +} + +export interface UpdateGoalRequest { + name?: string; + description?: string; + targetAmount?: number; + targetDate?: string; + monthlyContribution?: number; + currentAmount?: number; + status?: GoalStatus; +} + +export interface RebalanceRecommendation { + asset: string; + action: RebalanceAction; + currentPercent: number; + targetPercent: number; + deviation: number; + quantityChange: number; + valueChange: number; + priority: number; +} + +export interface PerformanceDataPoint { + date: string; + value: number; + pnl: number; + pnlPercent: number; + change: number; + changePercent: number; +} + +export interface PortfolioSummary { + portfolio: Portfolio; + allocations: PortfolioAllocation[]; + totalAllocated: number; + unallocatedPercent: number; + needsRebalance: boolean; + lastSnapshot: PortfolioSnapshot | null; +} + +// ============================================================================ +// WebSocket Event Types +// ============================================================================ + +export interface PortfolioUpdateEvent { + type: 'portfolio_update'; + portfolioId: string; + data: Partial; +} + +export interface AllocationUpdateEvent { + type: 'allocation_update'; + portfolioId: string; + allocationId: string; + data: Partial; +} + +export interface GoalProgressEvent { + type: 'goal_progress'; + goalId: string; + currentAmount: number; + progress: number; + projectedCompletionDate: Date | null; +} + +export type PortfolioWebSocketEvent = + | PortfolioUpdateEvent + | AllocationUpdateEvent + | GoalProgressEvent;