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
JavaScript
;
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;
}