quantitivecalc
Version:
A TypeScript library providing advanced quantitative finance functions for risk analysis, performance metrics, and technical indicators. (Currently in development)
81 lines (80 loc) • 3.95 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.calculateCorrelationMatrix = calculateCorrelationMatrix;
/**
* Calculates the rolling correlation matrix for a set of assets over a specified window size.
*
* @param data - An array of asset return objects, where each object contains asset return values keyed by asset name.
* @param assetColumns - An array of asset names (keys in each data object) to include in the correlation matrix.
* @param windowSize - Optional. The number of periods to use for the rolling window. If not provided, uses the entire data length.
* @returns An array of correlation matrices, each representing the correlations between assets for a window of data.
*
* @remarks
* - If `windowSize` is not specified, the function computes the correlation matrix for the entire dataset.
* - Each correlation matrix is a nested object where the outer keys are asset names, and the inner keys are asset names with correlation values.
* - Correlation values are set to `1` for diagonal elements (self-correlation), and `0` if there is insufficient data.
* - Handles missing or invalid data by skipping those entries in the calculation.
*/
function calculateCorrelationMatrix(data, assetColumns, windowSize) {
if (!data || data.length === 0 || assetColumns.length === 0) {
return [];
}
const results = [];
const effectiveWindowSize = windowSize || data.length;
for (let i = effectiveWindowSize - 1; i < data.length; i++) {
const windowData = data.slice(i - effectiveWindowSize + 1, i + 1);
const correlationMatrix = {};
// Initialize matrix
assetColumns.forEach(asset1 => {
correlationMatrix[asset1] = {};
assetColumns.forEach(asset2 => {
correlationMatrix[asset1][asset2] = asset1 === asset2 ? 1 : 0;
});
});
// Calculate correlations
for (let j = 0; j < assetColumns.length; j++) {
for (let k = j; k < assetColumns.length; k++) {
const asset1 = assetColumns[j];
const asset2 = assetColumns[k];
if (asset1 === asset2) {
correlationMatrix[asset1][asset2] = 1;
continue;
}
// Extract valid data pairs
const pairs = [];
windowData.forEach(row => {
const val1 = row[asset1];
const val2 = row[asset2];
if (typeof val1 === 'number' && typeof val2 === 'number' && !isNaN(val1) && !isNaN(val2)) {
pairs.push([val1, val2]);
}
});
if (pairs.length < 2) {
correlationMatrix[asset1][asset2] = 0;
correlationMatrix[asset2][asset1] = 0;
continue;
}
// Calculate means
const mean1 = pairs.reduce((sum, pair) => sum + pair[0], 0) / pairs.length;
const mean2 = pairs.reduce((sum, pair) => sum + pair[1], 0) / pairs.length;
// Calculate correlation
let numerator = 0;
let sumSq1 = 0;
let sumSq2 = 0;
pairs.forEach(([val1, val2]) => {
const diff1 = val1 - mean1;
const diff2 = val2 - mean2;
numerator += diff1 * diff2;
sumSq1 += diff1 * diff1;
sumSq2 += diff2 * diff2;
});
const denominator = Math.sqrt(sumSq1 * sumSq2);
const correlation = denominator === 0 ? 0 : numerator / denominator;
correlationMatrix[asset1][asset2] = correlation;
correlationMatrix[asset2][asset1] = correlation;
}
}
results.push(correlationMatrix);
}
return results;
}