import Foundation struct InvestmentMetrics { // Basic Metrics let totalValue: Decimal let totalContributions: Decimal let absoluteReturn: Decimal let percentageReturn: Decimal // Advanced Metrics let cagr: Double // Compound Annual Growth Rate let twr: Double // Time-Weighted Return let volatility: Double // Standard deviation annualized let maxDrawdown: Double // Maximum peak-to-trough decline let sharpeRatio: Double // Risk-adjusted return let bestMonth: MonthlyReturn? let worstMonth: MonthlyReturn? let winRate: Double // Percentage of positive months let averageMonthlyReturn: Double // Time period let startDate: Date? let endDate: Date? let totalMonths: Int struct MonthlyReturn: Identifiable { let id = UUID() let date: Date let returnPercentage: Double var formattedDate: String { let formatter = DateFormatter() formatter.dateFormat = "MMM yyyy" return formatter.string(from: date) } var formattedReturn: String { String(format: "%.1f%%", returnPercentage) } } } // MARK: - Formatting Helpers extension InvestmentMetrics { var formattedTotalValue: String { formatCurrency(totalValue) } var formattedAbsoluteReturn: String { let prefix = absoluteReturn >= 0 ? "+" : "" return prefix + formatCurrency(absoluteReturn) } var formattedPercentageReturn: String { let prefix = percentageReturn >= 0 ? "+" : "" return String(format: "\(prefix)%.2f%%", NSDecimalNumber(decimal: percentageReturn).doubleValue) } var formattedCAGR: String { String(format: "%.2f%%", cagr) } var formattedTWR: String { String(format: "%.2f%%", twr) } var formattedVolatility: String { String(format: "%.2f%%", volatility) } var formattedMaxDrawdown: String { String(format: "%.2f%%", maxDrawdown) } var formattedSharpeRatio: String { String(format: "%.2f", sharpeRatio) } var formattedWinRate: String { String(format: "%.0f%%", winRate) } var formattedAverageMonthlyReturn: String { let prefix = averageMonthlyReturn >= 0 ? "+" : "" return String(format: "\(prefix)%.2f%%", averageMonthlyReturn) } private func formatCurrency(_ value: Decimal) -> String { let formatter = NumberFormatter() formatter.numberStyle = .currency formatter.currencyCode = "EUR" formatter.maximumFractionDigits = 2 return formatter.string(from: value as NSDecimalNumber) ?? "€0.00" } } // MARK: - Empty State extension InvestmentMetrics { static var empty: InvestmentMetrics { InvestmentMetrics( totalValue: 0, totalContributions: 0, absoluteReturn: 0, percentageReturn: 0, cagr: 0, twr: 0, volatility: 0, maxDrawdown: 0, sharpeRatio: 0, bestMonth: nil, worstMonth: nil, winRate: 0, averageMonthlyReturn: 0, startDate: nil, endDate: nil, totalMonths: 0 ) } } // MARK: - Category Metrics struct CategoryMetrics: Identifiable { let id: UUID let categoryName: String let colorHex: String let icon: String let totalValue: Decimal let percentageOfPortfolio: Double let metrics: InvestmentMetrics var formattedTotalValue: String { let formatter = NumberFormatter() formatter.numberStyle = .currency formatter.currencyCode = "EUR" formatter.maximumFractionDigits = 0 return formatter.string(from: totalValue as NSDecimalNumber) ?? "€0" } var formattedPercentage: String { String(format: "%.1f%%", percentageOfPortfolio) } } // MARK: - Portfolio Summary struct PortfolioSummary { let totalValue: Decimal let totalContributions: Decimal let dayChange: Decimal let dayChangePercentage: Double let weekChange: Decimal let weekChangePercentage: Double let monthChange: Decimal let monthChangePercentage: Double let yearChange: Decimal let yearChangePercentage: Double let allTimeReturn: Decimal let allTimeReturnPercentage: Double let sourceCount: Int let lastUpdated: Date? var formattedTotalValue: String { let formatter = NumberFormatter() formatter.numberStyle = .currency formatter.currencyCode = "EUR" formatter.maximumFractionDigits = 0 return formatter.string(from: totalValue as NSDecimalNumber) ?? "€0" } var formattedDayChange: String { formatChange(dayChange, dayChangePercentage) } var formattedMonthChange: String { formatChange(monthChange, monthChangePercentage) } var formattedYearChange: String { formatChange(yearChange, yearChangePercentage) } var formattedAllTimeReturn: String { formatChange(allTimeReturn, allTimeReturnPercentage) } private func formatChange(_ absolute: Decimal, _ percentage: Double) -> String { let formatter = NumberFormatter() formatter.numberStyle = .currency formatter.currencyCode = "EUR" formatter.maximumFractionDigits = 0 let prefix = absolute >= 0 ? "+" : "" let absString = formatter.string(from: absolute as NSDecimalNumber) ?? "€0" let pctString = String(format: "%.2f%%", percentage) return "\(prefix)\(absString) (\(prefix)\(pctString))" } static var empty: PortfolioSummary { PortfolioSummary( totalValue: 0, totalContributions: 0, dayChange: 0, dayChangePercentage: 0, weekChange: 0, weekChangePercentage: 0, monthChange: 0, monthChangePercentage: 0, yearChange: 0, yearChangePercentage: 0, allTimeReturn: 0, allTimeReturnPercentage: 0, sourceCount: 0, lastUpdated: nil ) } }