trading-signals
Version:
Technical indicators to run technical analysis with JavaScript / TypeScript.
72 lines • 2.97 kB
JavaScript
import { TradingSignal, TrendIndicatorSeries } from '../../base/Indicator.js';
import { pushUpdate } from '../../util/pushUpdate.js';
export class UltimateOscillator extends TrendIndicatorSeries {
#candles = [];
#overbought;
#oversold;
shortPeriod;
mediumPeriod;
longPeriod;
constructor({ longPeriod = 28, mediumPeriod = 14, shortPeriod = 7 } = {}, { overbought = 70, oversold = 30 } = {}) {
super();
this.shortPeriod = shortPeriod;
this.mediumPeriod = mediumPeriod;
this.longPeriod = longPeriod;
this.#overbought = overbought;
this.#oversold = oversold;
}
getRequiredInputs() {
return this.longPeriod + 1;
}
update(candle, replace) {
pushUpdate(this.#candles, replace, candle, this.getRequiredInputs());
if (this.#candles.length < this.getRequiredInputs()) {
return null;
}
const buyingPressures = [];
const trueRanges = [];
for (let i = 1; i < this.#candles.length; i++) {
const { close, high, low } = this.#candles[i];
const previousClose = this.#candles[i - 1].close;
const trueLow = Math.min(low, previousClose);
const trueHigh = Math.max(high, previousClose);
buyingPressures.push(close - trueLow);
trueRanges.push(trueHigh - trueLow);
}
const average = (period) => {
let buyingPressureSum = 0;
let trueRangeSum = 0;
for (let i = trueRanges.length - period; i < trueRanges.length; i++) {
buyingPressureSum += buyingPressures[i];
trueRangeSum += trueRanges[i];
}
return { buyingPressureSum, trueRangeSum };
};
const short = average(this.shortPeriod);
if (short.trueRangeSum === 0) {
return this.setResult(50, replace);
}
const medium = average(this.mediumPeriod);
const long = average(this.longPeriod);
const shortAverage = short.buyingPressureSum / short.trueRangeSum;
const mediumAverage = medium.buyingPressureSum / medium.trueRangeSum;
const longAverage = long.buyingPressureSum / long.trueRangeSum;
return this.setResult((100 * (4 * shortAverage + 2 * mediumAverage + longAverage)) / 7, replace);
}
calculateSignalState(result) {
const hasResult = result !== null && result !== undefined;
const isOversold = hasResult && result <= this.#oversold;
const isOverbought = hasResult && result >= this.#overbought;
switch (true) {
case !hasResult:
return TradingSignal.UNKNOWN;
case isOversold:
return TradingSignal.BEARISH;
case isOverbought:
return TradingSignal.BULLISH;
default:
return TradingSignal.SIDEWAYS;
}
}
}
//# sourceMappingURL=UltimateOscillator.js.map