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