UNPKG

quantitivecalc

Version:

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

88 lines (87 loc) 4.72 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.calculateVaR = calculateVaR; const getZScore_1 = require("./getZScore"); /** * Calculates Value at Risk (VaR) for a time series of returns using parametric, historical, or Monte Carlo methods. * * @param data - Array of objects representing time series data, each containing a column with returns. * @param returnsColumn - The key in each data object that contains the return value. * @param resultColumn - The key in each data object where the calculated VaR will be stored. * @param confidenceLevel - The confidence level for VaR calculation (e.g., 0.05 for 5% VaR, default is 0.05). * @param windowSize - The number of periods to use for the rolling window calculation (default is 252). * @param method - The method to use for VaR calculation: 'parametric', 'historical', or 'monteCarlo' (default is 'historical'). * @returns A new array of objects with VaR values added in the specified result column. If insufficient data is available for a window, the result is `null`. */ function calculateVaR(data, returnsColumn, resultColumn, confidenceLevel = 0.05, // 5% VaR (95% confidence) windowSize = 252, method = 'historical') { 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 { // Get returns for the window const windowReturns = []; for (let j = i - windowSize + 1; j <= i; j++) { const returnValue = result[j][returnsColumn]; if (typeof returnValue === 'number' && !isNaN(returnValue)) { windowReturns.push(returnValue); } } if (windowReturns.length > 10) { let varValue; switch (method) { case 'parametric': { // Assume normal distribution const mean = windowReturns.reduce((sum, val) => sum + val, 0) / windowReturns.length; const variance = windowReturns.reduce((sum, val) => sum + Math.pow(val - mean, 2), 0) / (windowReturns.length - 1); const stdDev = Math.sqrt(variance); // Z-score for confidence level (e.g., -1.645 for 5% VaR) const zScore = (0, getZScore_1.getZScore)(confidenceLevel); varValue = mean + zScore * stdDev; break; } case 'historical': { // Sort returns and take percentile const sortedReturns = [...windowReturns].sort((a, b) => a - b); // Use Math.ceil to ensure we don't go below the actual percentile const index = Math.max(0, Math.ceil(confidenceLevel * sortedReturns.length) - 1); varValue = sortedReturns[index]; break; } case 'monteCarlo': { // Simple Monte Carlo simulation const mcMean = windowReturns.reduce((sum, val) => sum + val, 0) / windowReturns.length; const mcVariance = windowReturns.reduce((sum, val) => sum + Math.pow(val - mcMean, 2), 0) / (windowReturns.length - 1); const mcStdDev = Math.sqrt(mcVariance); // Generate random scenarios const simulations = 10000; const scenarios = []; for (let k = 0; k < simulations; k++) { // Box-Muller transform for normal random numbers const u1 = Math.random(); const u2 = Math.random(); const z = Math.sqrt(-2 * Math.log(u1)) * Math.cos(2 * Math.PI * u2); scenarios.push(mcMean + z * mcStdDev); } scenarios.sort((a, b) => a - b); const mcIndex = Math.max(0, Math.ceil(confidenceLevel * scenarios.length) - 1); varValue = scenarios[mcIndex]; break; } default: throw new Error(`Unknown VaR method: ${method}`); } result[i][resultColumn] = varValue; } else { result[i][resultColumn] = null; } } } return result; }