UNPKG

quantitivecalc

Version:

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

66 lines (65 loc) 2.82 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.calculateMovingAverage = calculateMovingAverage; /** * Calculates the moving average (simple or exponential) for a given dataset. * * @param data - The input array of objects containing the data to process. * @param sourceColumn - The key in each object from which to read the numeric value. * @param resultColumn - The key in each object where the calculated moving average will be stored. * @param windowSize - The number of periods to use for the moving average calculation. Defaults to 20. * @param type - The type of moving average to calculate: `'simple'` for Simple Moving Average (SMA), `'exponential'` for Exponential Moving Average (EMA). Defaults to `'simple'`. * @returns A new array of objects with the moving average values added to each object under `resultColumn`. * * @remarks * - For SMA, the result for the first `windowSize - 1` elements will be `null`. * - For EMA, the first valid value is used as the initial EMA. * - Non-numeric or invalid values in `sourceColumn` are skipped for SMA and carry forward the previous EMA for EMA. */ function calculateMovingAverage(data, sourceColumn, resultColumn, windowSize = 20, type = 'simple') { if (!data || data.length === 0) { return []; } const result = data.map(row => ({ ...row })); if (type === 'simple') { // Simple Moving Average for (let i = 0; i < result.length; i++) { if (i < windowSize - 1) { result[i][resultColumn] = null; } else { let sum = 0; let count = 0; for (let j = i - windowSize + 1; j <= i; j++) { const value = result[j][sourceColumn]; if (typeof value === 'number' && !isNaN(value)) { sum += value; count++; } } result[i][resultColumn] = count > 0 ? sum / count : null; } } } else { // Exponential Moving Average const multiplier = 2 / (windowSize + 1); let ema = null; for (let i = 0; i < result.length; i++) { const value = result[i][sourceColumn]; if (typeof value === 'number' && !isNaN(value)) { if (ema === null) { ema = value; // First valid value becomes initial EMA } else { ema = value * multiplier + ema * (1 - multiplier); } result[i][resultColumn] = ema; } else { result[i][resultColumn] = ema; // Keep previous EMA if current value is invalid } } } return result; }