Skip to main content
Glama
dun999

FinSight

analyze_compare

Compare two investment portfolios across 9 key risk and performance metrics to identify superior strategies or evaluate rebalancing options.

Instructions

Side-by-side comparison of two portfolios across 9 key metrics: Sharpe ratio, Sortino ratio, VaR, CVaR, max drawdown, diversification score, stress test loss, market beta, and overall risk tier. Returns winner per metric and delta values. Useful for A/B testing portfolio strategies or comparing current vs. rebalanced allocation. Costs $0.05 USDC.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
portfolio_aYesFirst portfolio to compare.
portfolio_bYesSecond portfolio to compare against portfolio_a.

Implementation Reference

  • The implementation of the `analyzeCompare` tool handler, which computes and compares various risk, VaR, and diversification metrics between two portfolios to determine an overall recommendation.
    export function analyzeCompare(portfolioA: Portfolio, portfolioB: Portfolio): CompareResult {
      const riskA = analyzeRisk(portfolioA)
      const riskB = analyzeRisk(portfolioB)
      const varA  = analyzeVaR(portfolioA)
      const varB  = analyzeVaR(portfolioB)
      const divA  = analyzeDiversification(portfolioA)
      const divB  = analyzeDiversification(portfolioB)
    
      const metrics: MetricComparison[] = [
        {
          metric: 'Sharpe Ratio',
          portfolio_a: riskA.portfolioSharpe,
          portfolio_b: riskB.portfolioSharpe,
          winner: winner(riskA.portfolioSharpe, riskB.portfolioSharpe, true, 0.02),
          delta: riskA.portfolioSharpe - riskB.portfolioSharpe,
          description: 'Risk-adjusted return per unit of total volatility. Higher is better.',
        },
        {
          metric: 'Sortino Ratio',
          portfolio_a: riskA.portfolioSortino,
          portfolio_b: riskB.portfolioSortino,
          winner: winner(riskA.portfolioSortino, riskB.portfolioSortino, true, 0.02),
          delta: riskA.portfolioSortino - riskB.portfolioSortino,
          description: 'Return relative to downside risk only. Higher is better.',
        },
        {
          metric: 'Calmar Ratio',
          portfolio_a: riskA.portfolioCalmar,
          portfolio_b: riskB.portfolioCalmar,
          winner: winner(riskA.portfolioCalmar, riskB.portfolioCalmar, true, 0.02),
          delta: riskA.portfolioCalmar - riskB.portfolioCalmar,
          description: 'Return relative to max drawdown. Higher is better.',
        },
        {
          metric: 'Annual Volatility',
          portfolio_a: riskA.portfolioVolatility,
          portfolio_b: riskB.portfolioVolatility,
          winner: winner(riskA.portfolioVolatility, riskB.portfolioVolatility, false, 0.005),
          delta: riskA.portfolioVolatility - riskB.portfolioVolatility,
          description: 'Annualised price fluctuation. Lower is better for capital-preservation goals.',
        },
        {
          metric: 'Market Beta',
          portfolio_a: riskA.portfolioBeta,
          portfolio_b: riskB.portfolioBeta,
          winner: winner(Math.abs(riskA.portfolioBeta - 1), Math.abs(riskB.portfolioBeta - 1), false, 0.05),
          delta: riskA.portfolioBeta - riskB.portfolioBeta,
          description: 'Sensitivity to broad market movements. Lower = more defensive.',
        },
        {
          metric: 'VaR 95% Daily',
          portfolio_a: varA.confidence95.dailyVaR,
          portfolio_b: varB.confidence95.dailyVaR,
          winner: winner(varA.confidence95.dailyVaR, varB.confidence95.dailyVaR, false, 0.001),
          delta: varA.confidence95.dailyVaR - varB.confidence95.dailyVaR,
          description: 'Daily downside at 95% confidence (loss fraction). Lower is better.',
        },
        {
          metric: 'CVaR 99% Annual',
          portfolio_a: varA.confidence99.annualCVaR,
          portfolio_b: varB.confidence99.annualCVaR,
          winner: winner(varA.confidence99.annualCVaR, varB.confidence99.annualCVaR, false, 0.005),
          delta: varA.confidence99.annualCVaR - varB.confidence99.annualCVaR,
          description: 'Expected annual loss in worst 1% of years (loss fraction). Lower is better.',
        },
        {
          metric: 'HHI Concentration',
          portfolio_a: divA.hhi,
          portfolio_b: divB.hhi,
          winner: winner(divA.hhi, divB.hhi, false, 100),
          delta: divA.hhi - divB.hhi,
          description: 'Herfindahl-Hirschman concentration index (0–10000). Lower = better diversified.',
        },
        {
          metric: 'Effective Assets',
          portfolio_a: divA.effectiveAssets,
          portfolio_b: divB.effectiveAssets,
          winner: winner(divA.effectiveAssets, divB.effectiveAssets, true, 0.1),
          delta: divA.effectiveAssets - divB.effectiveAssets,
          description: 'Equivalent independent positions. Higher = better diversification.',
        },
      ]
    
      const aWins = metrics.filter((m) => m.winner === 'a').length
      const bWins = metrics.filter((m) => m.winner === 'b').length
      const total = metrics.length
    
      const overall_winner: 'a' | 'b' | 'tie' =
        aWins > bWins ? 'a' : bWins > aWins ? 'b' : 'tie'
    
      const a_advantages = metrics.filter((m) => m.winner === 'a').map((m) => m.metric)
      const b_advantages = metrics.filter((m) => m.winner === 'b').map((m) => m.metric)
    
      let recommendation: string
      if (overall_winner === 'a') {
        recommendation =
          `Portfolio A is stronger overall (wins ${aWins}/${total} metrics). ` +
          `Key advantages: ${a_advantages.join(', ')}.`
      } else if (overall_winner === 'b') {
        recommendation =
          `Portfolio B is stronger overall (wins ${bWins}/${total} metrics). ` +
          `Key advantages: ${b_advantages.join(', ')}.`
      } else {
        const aStr = a_advantages.length > 0 ? `A leads: ${a_advantages.join(', ')}` : ''
        const bStr = b_advantages.length > 0 ? `B leads: ${b_advantages.join(', ')}` : ''
        recommendation =
          `Portfolios are evenly matched. Choose based on your primary objective. ` +
          [aStr, bStr].filter(Boolean).join('. ') + '.'
      }
    
      return { metrics, overall_winner, a_advantages, b_advantages, recommendation }
    }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/dun999/finsight-mpp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server