Files
gh-jeremylongshore-claude-c…/commands/portfolio-analysis.md
2025-11-29 18:53:07 +08:00

24 KiB

description, shortcut
description shortcut
Analyze entire crypto portfolio with allocation, risk metrics, and rebalancing suggestions pa

Portfolio Analysis

Comprehensive portfolio analysis for cryptocurrency holdings with advanced metrics, risk assessment, and optimization recommendations.

Usage

Analyze the user's complete crypto portfolio to provide insights on:

  • Asset allocation and diversification
  • Risk metrics (Sharpe ratio, volatility, max drawdown)
  • Performance attribution
  • Correlation analysis
  • Rebalancing recommendations

Implementation

1. Portfolio Analytics Engine

class PortfolioAnalyzer {
    constructor() {
        this.riskFreeRate = 0.02; // 2% annual risk-free rate
        this.historicalData = new Map();
        this.correlationMatrix = null;
    }

    async analyzePortfolio(positions) {
        // Fetch current prices and calculate values
        const portfolioData = await this.enrichPositions(positions);

        // Calculate core metrics
        const metrics = {
            totalValue: this.calculateTotalValue(portfolioData),
            totalCost: this.calculateTotalCost(portfolioData),
            totalPnL: this.calculateTotalPnL(portfolioData),
            allocation: this.calculateAllocation(portfolioData),
            concentration: this.calculateConcentration(portfolioData),
            volatility: await this.calculateVolatility(portfolioData),
            sharpeRatio: await this.calculateSharpeRatio(portfolioData),
            sortino: await this.calculateSortinoRatio(portfolioData),
            maxDrawdown: await this.calculateMaxDrawdown(portfolioData),
            correlations: await this.calculateCorrelations(portfolioData),
            var95: this.calculateValueAtRisk(portfolioData, 0.95),
            var99: this.calculateValueAtRisk(portfolioData, 0.99)
        };

        // Generate insights and recommendations
        const analysis = {
            metrics,
            riskAssessment: this.assessRisk(metrics),
            diversificationScore: this.calculateDiversificationScore(metrics),
            rebalancingPlan: this.generateRebalancingPlan(portfolioData, metrics),
            optimizations: this.suggestOptimizations(metrics)
        };

        return analysis;
    }

    calculateAllocation(portfolioData) {
        const totalValue = portfolioData.reduce((sum, p) => sum + p.currentValue, 0);

        return portfolioData.map(position => ({
            symbol: position.symbol,
            value: position.currentValue,
            percentage: (position.currentValue / totalValue) * 100,
            targetPercentage: position.targetAllocation || null,
            deviation: position.targetAllocation
                ? Math.abs(((position.currentValue / totalValue) * 100) - position.targetAllocation)
                : 0
        })).sort((a, b) => b.percentage - a.percentage);
    }

    calculateConcentration(portfolioData) {
        const allocations = this.calculateAllocation(portfolioData);
        const herfindahlIndex = allocations.reduce((sum, a) => {
            return sum + Math.pow(a.percentage / 100, 2);
        }, 0);

        return {
            herfindahlIndex: herfindahlIndex.toFixed(4),
            effectiveAssets: (1 / herfindahlIndex).toFixed(2),
            topAssetConcentration: allocations[0].percentage.toFixed(2),
            top3Concentration: allocations.slice(0, 3).reduce((sum, a) => sum + a.percentage, 0).toFixed(2)
        };
    }

    async calculateVolatility(portfolioData, period = 30) {
        const returns = await this.getHistoricalReturns(portfolioData, period);

        if (returns.length < 2) return null;

        const avgReturn = returns.reduce((sum, r) => sum + r, 0) / returns.length;
        const variance = returns.reduce((sum, r) => sum + Math.pow(r - avgReturn, 2), 0) / (returns.length - 1);
        const volatility = Math.sqrt(variance);

        // Annualized volatility
        return {
            daily: (volatility * 100).toFixed(2),
            weekly: (volatility * Math.sqrt(7) * 100).toFixed(2),
            monthly: (volatility * Math.sqrt(30) * 100).toFixed(2),
            annual: (volatility * Math.sqrt(365) * 100).toFixed(2)
        };
    }

    async calculateSharpeRatio(portfolioData) {
        const returns = await this.getHistoricalReturns(portfolioData, 365);
        if (returns.length < 30) return null;

        const avgReturn = returns.reduce((sum, r) => sum + r, 0) / returns.length;
        const annualizedReturn = avgReturn * 365;

        const stdDev = Math.sqrt(
            returns.reduce((sum, r) => sum + Math.pow(r - avgReturn, 2), 0) / (returns.length - 1)
        );
        const annualizedStdDev = stdDev * Math.sqrt(365);

        const sharpeRatio = (annualizedReturn - this.riskFreeRate) / annualizedStdDev;

        return {
            value: sharpeRatio.toFixed(3),
            interpretation: this.interpretSharpeRatio(sharpeRatio)
        };
    }

    interpretSharpeRatio(ratio) {
        if (ratio < 0) return 'POOR - Returns below risk-free rate';
        if (ratio < 0.5) return 'SUBOPTIMAL - Low risk-adjusted returns';
        if (ratio < 1.0) return 'ACCEPTABLE - Moderate risk-adjusted returns';
        if (ratio < 2.0) return 'GOOD - Strong risk-adjusted returns';
        return 'EXCELLENT - Outstanding risk-adjusted returns';
    }

    async calculateCorrelations(portfolioData) {
        if (portfolioData.length < 2) return null;

        const correlationMatrix = [];
        const symbols = portfolioData.map(p => p.symbol);

        for (let i = 0; i < symbols.length; i++) {
            const row = [];
            for (let j = 0; j < symbols.length; j++) {
                if (i === j) {
                    row.push(1.0);
                } else {
                    const correlation = await this.calculatePairCorrelation(
                        symbols[i],
                        symbols[j],
                        30 // 30-day correlation
                    );
                    row.push(correlation);
                }
            }
            correlationMatrix.push(row);
        }

        // Find highest correlations
        const highCorrelations = [];
        for (let i = 0; i < symbols.length; i++) {
            for (let j = i + 1; j < symbols.length; j++) {
                if (Math.abs(correlationMatrix[i][j]) > 0.7) {
                    highCorrelations.push({
                        pair: `${symbols[i]}-${symbols[j]}`,
                        correlation: correlationMatrix[i][j].toFixed(3),
                        interpretation: correlationMatrix[i][j] > 0 ? 'POSITIVE' : 'NEGATIVE'
                    });
                }
            }
        }

        return {
            matrix: correlationMatrix,
            symbols,
            highCorrelations,
            averageCorrelation: this.calculateAverageCorrelation(correlationMatrix)
        };
    }

    calculateValueAtRisk(portfolioData, confidenceLevel) {
        const returns = this.historicalData.get('portfolio_returns') || [];
        if (returns.length < 100) return null;

        const sortedReturns = returns.sort((a, b) => a - b);
        const index = Math.floor((1 - confidenceLevel) * sortedReturns.length);
        const var_value = sortedReturns[index];
        const totalValue = portfolioData.reduce((sum, p) => sum + p.currentValue, 0);

        return {
            percentage: (var_value * 100).toFixed(2),
            dollarAmount: (totalValue * var_value).toFixed(2),
            confidenceLevel: (confidenceLevel * 100).toFixed(0),
            interpretation: `${confidenceLevel * 100}% chance that losses won't exceed $${Math.abs(totalValue * var_value).toFixed(2)}`
        };
    }

    assessRisk(metrics) {
        const riskFactors = [];
        let riskScore = 0;

        // Concentration risk
        if (metrics.concentration.topAssetConcentration > 50) {
            riskFactors.push({
                type: 'CONCENTRATION',
                severity: 'HIGH',
                description: `Top asset represents ${metrics.concentration.topAssetConcentration}% of portfolio`
            });
            riskScore += 30;
        }

        // Volatility risk
        if (metrics.volatility && metrics.volatility.annual > 100) {
            riskFactors.push({
                type: 'VOLATILITY',
                severity: 'HIGH',
                description: `Annual volatility exceeds 100% (${metrics.volatility.annual}%)`
            });
            riskScore += 25;
        }

        // Correlation risk
        if (metrics.correlations && metrics.correlations.highCorrelations.length > 0) {
            riskFactors.push({
                type: 'CORRELATION',
                severity: 'MEDIUM',
                description: `${metrics.correlations.highCorrelations.length} asset pairs highly correlated`
            });
            riskScore += 15;
        }

        // Drawdown risk
        if (metrics.maxDrawdown && metrics.maxDrawdown.percentage > 40) {
            riskFactors.push({
                type: 'DRAWDOWN',
                severity: 'HIGH',
                description: `Maximum drawdown of ${metrics.maxDrawdown.percentage}% observed`
            });
            riskScore += 20;
        }

        return {
            overallScore: Math.min(riskScore, 100),
            level: this.determineRiskLevel(riskScore),
            factors: riskFactors,
            recommendations: this.generateRiskRecommendations(riskFactors)
        };
    }

    determineRiskLevel(score) {
        if (score < 20) return 'LOW';
        if (score < 40) return 'MODERATE';
        if (score < 60) return 'ELEVATED';
        if (score < 80) return 'HIGH';
        return 'CRITICAL';
    }

    generateRebalancingPlan(portfolioData, metrics) {
        const currentAllocations = metrics.allocation;
        const targetAllocations = this.calculateOptimalAllocation(portfolioData, metrics);
        const totalValue = metrics.totalValue;

        const rebalancingActions = [];

        currentAllocations.forEach((current, index) => {
            const target = targetAllocations[index];
            const currentValue = current.value;
            const targetValue = (target.percentage / 100) * totalValue;
            const difference = targetValue - currentValue;

            if (Math.abs(difference) > totalValue * 0.01) { // Only rebalance if > 1% of portfolio
                rebalancingActions.push({
                    symbol: current.symbol,
                    action: difference > 0 ? 'BUY' : 'SELL',
                    amount: Math.abs(difference).toFixed(2),
                    currentPercentage: current.percentage.toFixed(2),
                    targetPercentage: target.percentage.toFixed(2),
                    reason: target.reason
                });
            }
        });

        return {
            actions: rebalancingActions,
            estimatedCost: this.estimateRebalancingCost(rebalancingActions),
            expectedImprovement: this.estimateImprovementMetrics(targetAllocations, currentAllocations)
        };
    }

    calculateOptimalAllocation(portfolioData, metrics) {
        // Modern Portfolio Theory optimization
        // This is a simplified version - real implementation would use quadratic programming

        const riskTolerance = this.determineRiskTolerance(metrics);
        const correlations = metrics.correlations?.matrix || [];

        // Start with equal weight
        let allocations = portfolioData.map(p => ({
            symbol: p.symbol,
            percentage: 100 / portfolioData.length,
            reason: 'Equal weight baseline'
        }));

        // Adjust based on performance
        allocations = this.adjustForPerformance(allocations, portfolioData);

        // Adjust based on risk
        allocations = this.adjustForRisk(allocations, metrics, riskTolerance);

        // Adjust based on correlations
        if (correlations.length > 0) {
            allocations = this.adjustForCorrelations(allocations, correlations);
        }

        // Apply constraints
        allocations = this.applyAllocationConstraints(allocations);

        return allocations;
    }

    adjustForPerformance(allocations, portfolioData) {
        // Increase allocation to better performers
        const performances = portfolioData.map(p => ({
            symbol: p.symbol,
            performance: p.pnlPercentage
        })).sort((a, b) => b.performance - a.performance);

        return allocations.map(alloc => {
            const perf = performances.find(p => p.symbol === alloc.symbol);
            const rank = performances.indexOf(perf);

            // Top 1/3 get boost, bottom 1/3 get reduction
            if (rank < performances.length / 3) {
                alloc.percentage *= 1.2;
                alloc.reason = 'Strong performance';
            } else if (rank > (performances.length * 2 / 3)) {
                alloc.percentage *= 0.8;
                alloc.reason = 'Weak performance';
            }

            return alloc;
        });
    }

    applyAllocationConstraints(allocations) {
        // No single asset > 40%
        const maxAllocation = 40;
        // No single asset < 5%
        const minAllocation = 5;

        // Normalize to ensure sum = 100
        const total = allocations.reduce((sum, a) => sum + a.percentage, 0);
        allocations = allocations.map(a => ({
            ...a,
            percentage: (a.percentage / total) * 100
        }));

        // Apply constraints
        allocations = allocations.map(alloc => ({
            ...alloc,
            percentage: Math.min(Math.max(alloc.percentage, minAllocation), maxAllocation)
        }));

        // Re-normalize
        const newTotal = allocations.reduce((sum, a) => sum + a.percentage, 0);
        return allocations.map(a => ({
            ...a,
            percentage: (a.percentage / newTotal) * 100
        }));
    }
}

2. Portfolio Visualization

class PortfolioVisualizer {
    generateReport(analysis) {
        return `
╔════════════════════════════════════════════════════════════════════════════╗
║                          PORTFOLIO ANALYSIS REPORT                         ║
╠════════════════════════════════════════════════════════════════════════════╣
║                              SUMMARY METRICS                               ║
╠════════════════════════════════════════════════════════════════════════════╣
║ Total Value:        $${analysis.metrics.totalValue.toFixed(2).padEnd(55)}║ Total Cost:         $${analysis.metrics.totalCost.toFixed(2).padEnd(55)}║ Total P&L:          ${this.formatPnL(analysis.metrics.totalPnL).padEnd(56)}║ Total Return:       ${this.formatPercentage(analysis.metrics.totalReturn).padEnd(56)}╠════════════════════════════════════════════════════════════════════════════╣
║                             RISK METRICS                                   ║
╠════════════════════════════════════════════════════════════════════════════╣
║ Risk Level:         ${analysis.riskAssessment.level.padEnd(56)}║ Risk Score:         ${(analysis.riskAssessment.overallScore + '/100').padEnd(56)}║ Sharpe Ratio:       ${analysis.metrics.sharpeRatio?.value || 'N/A'.padEnd(56)}║ Annual Volatility:  ${analysis.metrics.volatility?.annual + '%' || 'N/A'.padEnd(56)}║ Max Drawdown:       ${analysis.metrics.maxDrawdown?.percentage + '%' || 'N/A'.padEnd(56)}║ VaR (95%):         ${analysis.metrics.var95?.dollarAmount || 'N/A'.padEnd(56)}╠════════════════════════════════════════════════════════════════════════════╣
║                            ASSET ALLOCATION                                ║
╠════════════════════════════════════════════════════════════════════════════╣
${this.formatAllocationTable(analysis.metrics.allocation)}
╠════════════════════════════════════════════════════════════════════════════╣
║                          CONCENTRATION ANALYSIS                            ║
╠════════════════════════════════════════════════════════════════════════════╣
║ Herfindahl Index:   ${analysis.metrics.concentration.herfindahlIndex.padEnd(56)}║ Effective Assets:   ${analysis.metrics.concentration.effectiveAssets.padEnd(56)}║ Top Asset:          ${analysis.metrics.concentration.topAssetConcentration + '%'.padEnd(56)}║ Top 3 Assets:       ${analysis.metrics.concentration.top3Concentration + '%'.padEnd(56)}╠════════════════════════════════════════════════════════════════════════════╣
║                         REBALANCING RECOMMENDATIONS                        ║
╠════════════════════════════════════════════════════════════════════════════╣
${this.formatRebalancingActions(analysis.rebalancingPlan.actions)}
╠════════════════════════════════════════════════════════════════════════════╣
║                            RISK FACTORS                                    ║
╠════════════════════════════════════════════════════════════════════════════╣
${this.formatRiskFactors(analysis.riskAssessment.factors)}
╚════════════════════════════════════════════════════════════════════════════╝
        `;
    }

    formatAllocationTable(allocations) {
        return allocations.slice(0, 5).map(a =>
            `║ ${a.symbol.padEnd(10)} ${(a.percentage.toFixed(2) + '%').padEnd(10)} $${a.value.toFixed(2).padEnd(15)} ${this.getAllocationBar(a.percentage).padEnd(20)} ║`
        ).join('\n');
    }

    getAllocationBar(percentage) {
        const barLength = Math.floor(percentage / 5);
        return '█'.repeat(Math.min(barLength, 20));
    }

    formatRebalancingActions(actions) {
        if (actions.length === 0) {
            return '║ Portfolio is well-balanced. No actions required.                          ║';
        }

        return actions.slice(0, 3).map(a =>
            `║ ${a.action.padEnd(5)} ${a.symbol.padEnd(6)} $${a.amount.padEnd(10)} (${a.currentPercentage}% → ${a.targetPercentage}%)`.padEnd(77) + '║'
        ).join('\n');
    }

    formatRiskFactors(factors) {
        if (factors.length === 0) {
            return '║ No significant risk factors identified.                                   ║';
        }

        return factors.map(f =>
            `║ [${f.severity}] ${f.type}: ${f.description}`.padEnd(77) + '║'
        ).join('\n');
    }

    formatPnL(value) {
        const formatted = `$${Math.abs(value).toFixed(2)}`;
        return value >= 0 ? `+${formatted} ` : `-${formatted} `;
    }

    formatPercentage(value) {
        const formatted = `${Math.abs(value).toFixed(2)}%`;
        return value >= 0 ? `+${formatted} ` : `-${formatted} `;
    }
}

3. Optimization Strategies

class PortfolioOptimizer {
    suggestOptimizations(metrics) {
        const suggestions = [];

        // Diversification suggestions
        if (metrics.concentration.effectiveAssets < 3) {
            suggestions.push({
                priority: 'HIGH',
                category: 'DIVERSIFICATION',
                action: 'Add more uncorrelated assets',
                benefit: 'Reduce concentration risk by 30-40%',
                implementation: `
                    Consider adding:
                    - Large cap altcoins (ETH, BNB) if heavily in BTC
                    - DeFi tokens if heavily in L1s
                    - Stablecoins for risk reduction
                `
            });
        }

        // Rebalancing suggestions
        if (metrics.allocation.some(a => a.deviation > 10)) {
            suggestions.push({
                priority: 'MEDIUM',
                category: 'REBALANCING',
                action: 'Rebalance to target allocations',
                benefit: 'Improve risk-adjusted returns',
                implementation: `
                    Set up periodic rebalancing:
                    - Monthly for volatile markets
                    - Quarterly for stable markets
                    - Threshold-based (when deviation > 15%)
                `
            });
        }

        // Risk management suggestions
        if (!metrics.stopLossesSet) {
            suggestions.push({
                priority: 'HIGH',
                category: 'RISK_MANAGEMENT',
                action: 'Implement stop-loss orders',
                benefit: 'Limit downside risk',
                implementation: `
                    Recommended stop-loss levels:
                    - Conservative: 15% below entry
                    - Moderate: 25% below entry
                    - Aggressive: 35% below entry
                `
            });
        }

        // Performance suggestions
        if (metrics.sharpeRatio && metrics.sharpeRatio.value < 0.5) {
            suggestions.push({
                priority: 'MEDIUM',
                category: 'PERFORMANCE',
                action: 'Improve risk-adjusted returns',
                benefit: 'Better Sharpe ratio',
                implementation: `
                    Options to improve:
                    - Reduce allocation to high-volatility assets
                    - Add yield-generating positions (staking, lending)
                    - Consider market-neutral strategies
                `
            });
        }

        return suggestions;
    }
}

Error Handling

async function executePortfolioAnalysis() {
    try {
        const analyzer = new PortfolioAnalyzer();
        const visualizer = new PortfolioVisualizer();

        // Get all open positions
        const positions = await getOpenPositions();

        if (positions.length === 0) {
            console.log('No positions found. Start by tracking some positions first.');
            return;
        }

        // Run analysis
        console.log('Analyzing portfolio...');
        const analysis = await analyzer.analyzePortfolio(positions);

        // Display report
        const report = visualizer.generateReport(analysis);
        console.log(report);

        // Save analysis
        await saveAnalysis(analysis);

    } catch (error) {
        console.error('Portfolio analysis failed:', error.message);

        if (error.code === 'INSUFFICIENT_DATA') {
            console.log('Not enough historical data for full analysis. Some metrics may be unavailable.');
        } else if (error.code === 'API_ERROR') {
            console.log('Failed to fetch market data. Please check your internet connection.');
        }
    }
}

This comprehensive portfolio analysis command provides institutional-grade analytics for crypto portfolios with actionable insights and optimization recommendations.