quantitivecalc
Version:
A TypeScript library providing advanced quantitative finance functions for risk analysis, performance metrics, and technical indicators. (Currently in development)
69 lines (68 loc) • 2.84 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.calculateRSI = calculateRSI;
/**
* Calculates the Relative Strength Index (RSI) for a given dataset.
*
* The RSI is a momentum oscillator that measures the speed and change of price movements.
* It is typically used in technical analysis to identify overbought or oversold conditions.
*
* @param data - An array of objects representing the dataset. Each object should contain the source column.
* @param sourceColumn - The key in each data object that contains the numeric value to calculate RSI from.
* @param resultColumn - The key to store the calculated RSI value in each result object. Defaults to `'rsi'`.
* @param windowSize - The number of periods to use for the RSI calculation. Defaults to `14`.
* @returns A new array of objects with the RSI value added under the specified result column.
*
* @remarks
* - If there is insufficient data to calculate RSI for a given row (i.e., fewer than `windowSize` periods), the result will be `null` for that row.
* - If the average loss is zero, the RSI will be set to `100` for that row.
*/
function calculateRSI(data, sourceColumn, resultColumn = 'rsi', windowSize = 14) {
if (!data || data.length === 0) {
return [];
}
const result = data.map(row => ({ ...row }));
for (let i = 0; i < result.length; i++) {
if (i < windowSize) {
result[i][resultColumn] = null;
continue;
}
let gains = 0;
let losses = 0;
let gainCount = 0;
let lossCount = 0;
// Calculate gains and losses over the window
for (let j = i - windowSize + 1; j <= i; j++) {
const currentValue = result[j][sourceColumn];
const previousValue = result[j - 1][sourceColumn];
if (typeof currentValue === 'number' &&
typeof previousValue === 'number' &&
!isNaN(currentValue) &&
!isNaN(previousValue)) {
const change = currentValue - previousValue;
if (change > 0) {
gains += change;
gainCount++;
}
else if (change < 0) {
losses += Math.abs(change);
lossCount++;
}
}
}
if (gainCount === 0 && lossCount === 0) {
result[i][resultColumn] = null;
continue;
}
const avgGain = gainCount > 0 ? gains / windowSize : 0;
const avgLoss = lossCount > 0 ? losses / windowSize : 0;
if (avgLoss === 0) {
result[i][resultColumn] = 100;
}
else {
const rs = avgGain / avgLoss;
result[i][resultColumn] = 100 - 100 / (1 + rs);
}
}
return result;
}