UNPKG

quantitivecalc

Version:

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

57 lines (56 loc) 3.02 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.calculateInformationRatio = calculateInformationRatio; /** * Calculates the rolling Information Ratio for a given dataset. * * The Information Ratio is computed as the mean of active returns (asset return minus benchmark return) * divided by the tracking error (standard deviation of active returns), annualized by multiplying by the square root of 252. * The result is stored in the specified result column for each row where enough data is available (windowSize). * For rows with insufficient data, the result column is set to `null`. * * @param data - Array of records containing asset and benchmark returns. * @param assetReturnsColumn - The key in each record representing the asset returns. * @param benchmarkReturnsColumn - The key in each record representing the benchmark returns. * @param resultColumn - The key in each record where the calculated Information Ratio will be stored. * @param windowSize - The number of periods to use for the rolling calculation (default is 252). * @returns A new array of records with the Information Ratio added to each row in the specified result column. */ function calculateInformationRatio(data, assetReturnsColumn, benchmarkReturnsColumn, resultColumn, windowSize = 252) { if (!data || data.length === 0) { return []; } const result = data.map(row => ({ ...row })); for (let i = 0; i < result.length; i++) { if (i < windowSize - 1) { result[i][resultColumn] = null; } else { const activeReturns = []; // Calculate active returns (asset - benchmark) for (let j = i - windowSize + 1; j <= i; j++) { const assetReturn = result[j][assetReturnsColumn]; const benchmarkReturn = result[j][benchmarkReturnsColumn]; if (typeof assetReturn === 'number' && !isNaN(assetReturn) && typeof benchmarkReturn === 'number' && !isNaN(benchmarkReturn)) { activeReturns.push(assetReturn - benchmarkReturn); } } if (activeReturns.length > 1) { // Calculate mean and standard deviation of active returns const meanActiveReturn = activeReturns.reduce((sum, val) => sum + val, 0) / activeReturns.length; const variance = activeReturns.reduce((sum, val) => sum + Math.pow(val - meanActiveReturn, 2), 0) / (activeReturns.length - 1); const trackingError = Math.sqrt(variance); // Information Ratio = Mean Active Return / Tracking Error (annualized) const informationRatio = trackingError > 0 ? (meanActiveReturn / trackingError) * Math.sqrt(252) : 0; result[i][resultColumn] = informationRatio; } else { result[i][resultColumn] = null; } } } return result; }