trading-signals
Version:
Technical indicators to run technical analysis with JavaScript / TypeScript.
120 lines • 4.46 kB
JavaScript
import { IndicatorSeries } from '../../base/Indicator.js';
export class PSAR extends IndicatorSeries {
accelerationStep;
accelerationMax;
state = {
acceleration: 0,
extreme: null,
isLong: null,
lastSar: null,
prePreviousCandle: null,
previousCandle: null,
};
constructor(config) {
super();
this.accelerationStep = config.accelerationStep;
this.accelerationMax = config.accelerationMax;
if (this.accelerationStep <= 0) {
throw new Error('Acceleration step must be greater than 0');
}
if (this.accelerationMax <= this.accelerationStep) {
throw new Error('Acceleration max must be greater than acceleration step');
}
}
get isStable() {
return this.state.lastSar !== null;
}
getRequiredInputs() {
return 2;
}
update(candle, replace) {
const { high, low } = candle;
this.trackState(replace);
const state = this.state;
if (!state.previousCandle) {
state.previousCandle = candle;
return null;
}
if (state.lastSar === null) {
const currentMidpoint = (high + low) / 2;
const previousMidpoint = (state.previousCandle.high + state.previousCandle.low) / 2;
state.isLong = currentMidpoint >= previousMidpoint;
if (state.isLong) {
state.extreme = high;
state.lastSar = state.previousCandle.low;
}
else {
state.extreme = low;
state.lastSar = state.previousCandle.high;
}
state.acceleration = this.accelerationStep;
state.prePreviousCandle = state.previousCandle;
state.previousCandle = candle;
return this.setResult(state.lastSar, replace);
}
let sar = (state.extreme - state.lastSar) * state.acceleration + state.lastSar;
if (state.isLong) {
const hasPrevPrev = state.prePreviousCandle != null;
if (hasPrevPrev && low < sar) {
if (state.prePreviousCandle.low < sar) {
sar = state.prePreviousCandle.low;
}
sar = state.previousCandle.low < sar ? state.previousCandle.low : sar;
}
else if (state.previousCandle.low < sar) {
sar = state.previousCandle.low;
}
if (high > state.extreme) {
state.extreme = high;
if (state.acceleration < this.accelerationMax) {
state.acceleration += this.accelerationStep;
if (state.acceleration > this.accelerationMax) {
state.acceleration = this.accelerationMax;
}
}
}
if (low < sar) {
state.isLong = false;
sar = state.extreme;
state.extreme = low;
state.acceleration = this.accelerationStep;
}
}
else {
const hasPrevPrev = state.prePreviousCandle != null;
if (hasPrevPrev && high > sar) {
if (state.prePreviousCandle.high > sar) {
sar = state.prePreviousCandle.high;
}
sar = state.previousCandle.high > sar ? state.previousCandle.high : sar;
}
else if (state.previousCandle.high > sar) {
sar = state.previousCandle.high;
}
if (low < state.extreme) {
state.extreme = low;
state.acceleration += this.accelerationStep;
if (state.acceleration > this.accelerationMax) {
state.acceleration = this.accelerationMax;
}
}
if (high > sar) {
state.isLong = true;
sar = state.extreme;
state.extreme = high;
state.acceleration = this.accelerationStep;
if (sar >= low) {
sar = low - 0.01;
}
}
}
state.lastSar = sar;
state.prePreviousCandle = state.previousCandle;
state.previousCandle = candle;
return this.setResult(sar, replace);
}
getResultOrThrow() {
return super.getResultOrThrow();
}
}
//# sourceMappingURL=PSAR.js.map