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 <noreply@anthropic.com>
This commit is contained in:
Adrian Flores Cortes 2026-01-26 17:02:41 -06:00
parent f7a5ddcca8
commit c18459558f

View File

@ -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<string, unknown> | 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<Portfolio>;
}
export interface AllocationUpdateEvent {
type: 'allocation_update';
portfolioId: string;
allocationId: string;
data: Partial<PortfolioAllocation>;
}
export interface GoalProgressEvent {
type: 'goal_progress';
goalId: string;
currentAmount: number;
progress: number;
projectedCompletionDate: Date | null;
}
export type PortfolioWebSocketEvent =
| PortfolioUpdateEvent
| AllocationUpdateEvent
| GoalProgressEvent;