trading-signals
Version:
Technical indicators to run technical analysis with JavaScript / TypeScript.
75 lines • 2.76 kB
JavaScript
import { SMA } from '../../trend/SMA/SMA.js';
import { TechnicalIndicator, TradingSignal } from '../../base/Indicator.js';
import { pushUpdate } from '../../util/pushUpdate.js';
export class StochasticOscillator extends TechnicalIndicator {
candles = [];
#smoothK;
#smoothD;
#previousResult;
kPeriod;
kSlowingPeriod;
dPeriod;
#overbought;
#oversold;
constructor({ dPeriod, kPeriod, kSlowingPeriod }, { overbought = 80, oversold = 20 } = {}) {
super();
this.kPeriod = kPeriod;
this.kSlowingPeriod = kSlowingPeriod;
this.dPeriod = dPeriod;
this.#smoothK = new SMA(kSlowingPeriod);
this.#smoothD = new SMA(dPeriod);
this.#overbought = overbought;
this.#oversold = oversold;
}
getRequiredInputs() {
return this.kPeriod + this.dPeriod + 1;
}
update(candle, replace) {
pushUpdate(this.candles, replace, candle, this.kPeriod);
if (this.candles.length === this.kPeriod) {
const highest = Math.max(...this.candles.map(candle => candle.high));
const lowest = Math.min(...this.candles.map(candle => candle.low));
const divisor = highest - lowest;
let fastK = (candle.close - lowest) * 100;
fastK = fastK / (divisor === 0 ? 1 : divisor);
const stochK = this.#smoothK.update(fastK, replace);
const stochD = stochK && this.#smoothD.update(stochK, replace);
if (stochK !== null && stochD !== null) {
if (replace) {
this.result = this.#previousResult;
}
this.#previousResult = this.result;
return (this.result = {
stochD,
stochK,
});
}
}
return null;
}
calculateSignal(result) {
const hasResult = result !== null && result !== undefined;
const isOversold = hasResult && result.stochK <= this.#oversold;
const isOverbought = hasResult && result.stochK >= this.#overbought;
switch (true) {
case !hasResult:
return TradingSignal.UNKNOWN;
case isOversold:
return TradingSignal.BEARISH;
case isOverbought:
return TradingSignal.BULLISH;
default:
return TradingSignal.SIDEWAYS;
}
}
getSignal() {
const previousState = this.calculateSignal(this.#previousResult);
const state = this.calculateSignal(this.getResult());
const hasChanged = previousState !== state;
return {
hasChanged,
state,
};
}
}
//# sourceMappingURL=StochasticOscillator.js.map