UNPKG

quantitivecalc

Version:

A TypeScript library providing advanced quantitative finance functions for risk analysis, performance metrics, and technical indicators. (Currently in development)

103 lines (102 loc) 4.94 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.calculateRiskContribution = calculateRiskContribution; const calculateCorrelationMatrix_1 = require("./calculateCorrelationMatrix"); /** * Calculates the risk contribution of each asset in a portfolio based on historical returns, asset weights, and a specified window size. * * The function computes asset volatilities, the correlation matrix, portfolio volatility, and then derives * the marginal risk, component risk, and percentage contribution for each asset. * If insufficient data is provided, returns zeroed results for each asset. * * @param returns - Array of asset return objects, each representing a time period. * @param weights - Object mapping asset names to their portfolio weights. * @param returnColumns - Array of asset names to include in the calculation. * @param windowSize - Number of periods to use for calculations (default: 252). * @returns An object mapping each asset name to its risk contribution metrics: * - volatility: Standard deviation of asset returns. * - marginalRisk: Marginal risk contribution of the asset to the portfolio. * - componentRisk: Component risk contribution (weight × marginal risk). * - contributionPercent: Percentage contribution to total portfolio risk. */ function calculateRiskContribution(returns, weights, returnColumns, windowSize = 252) { if (!returns || returns.length < windowSize || returnColumns.length === 0) { const emptyResult = {}; returnColumns.forEach(asset => { emptyResult[asset] = { volatility: 0, marginalRisk: 0, componentRisk: 0, contributionPercent: 0, }; }); return emptyResult; } // Use the most recent window of data const windowData = returns.slice(-windowSize); // Calculate asset volatilities (standard deviation of returns) const volatilities = {}; const assetReturns = {}; returnColumns.forEach(asset => { const validReturns = []; windowData.forEach(row => { const ret = row[asset]; if (typeof ret === 'number' && !isNaN(ret)) { validReturns.push(ret); } }); assetReturns[asset] = validReturns; if (validReturns.length > 1) { const mean = validReturns.reduce((sum, ret) => sum + ret, 0) / validReturns.length; const variance = validReturns.reduce((sum, ret) => sum + Math.pow(ret - mean, 2), 0) / (validReturns.length - 1); volatilities[asset] = Math.sqrt(variance); } else { volatilities[asset] = 0; } }); // Calculate correlation matrix for the assets const correlationMatrices = (0, calculateCorrelationMatrix_1.calculateCorrelationMatrix)(windowData, returnColumns, windowSize); const correlationMatrix = correlationMatrices.length > 0 ? correlationMatrices[correlationMatrices.length - 1] : {}; // Calculate portfolio volatility let portfolioVariance = 0; returnColumns.forEach(asset1 => { returnColumns.forEach(asset2 => { const weight1 = weights[asset1] || 0; const weight2 = weights[asset2] || 0; const vol1 = volatilities[asset1] || 0; const vol2 = volatilities[asset2] || 0; const correlation = correlationMatrix[asset1] ? correlationMatrix[asset1][asset2] || 0 : 0; portfolioVariance += weight1 * weight2 * vol1 * vol2 * correlation; }); }); const portfolioVolatility = Math.sqrt(Math.max(0, portfolioVariance)); // Calculate risk contributions const riskContribution = {}; returnColumns.forEach(asset => { const assetWeight = weights[asset] || 0; const assetVolatility = volatilities[asset] || 0; // Calculate marginal risk contribution let marginalRisk = 0; if (portfolioVolatility > 0) { returnColumns.forEach(otherAsset => { const otherWeight = weights[otherAsset] || 0; const otherVolatility = volatilities[otherAsset] || 0; const correlation = correlationMatrix[asset] ? correlationMatrix[asset][otherAsset] || 0 : 0; marginalRisk += otherWeight * otherVolatility * assetVolatility * correlation; }); marginalRisk = marginalRisk / portfolioVolatility; } // Calculate component risk contribution const componentRisk = assetWeight * marginalRisk; // Calculate percentage contribution const contributionPercent = portfolioVolatility > 0 ? (componentRisk / portfolioVolatility) * 100 : 0; riskContribution[asset] = { volatility: assetVolatility, marginalRisk, componentRisk, contributionPercent, }; }); return riskContribution; }