trading-signals
Version:
Technical indicators to run technical analysis with JavaScript / TypeScript.
121 lines • 4.48 kB
JavaScript
import { IndicatorSeries } from '../../base/Indicator.js';
export class PSAR extends IndicatorSeries {
accelerationStep;
accelerationMax;
acceleration = 0;
extreme = null;
lastSar = null;
isLong = null;
previousCandle = null;
prePreviousCandle = 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.lastSar !== null;
}
getRequiredInputs() {
return 2;
}
update(candle, replace) {
const { high, low } = candle;
const notEnoughData = !this.previousCandle || this.lastSar === null;
if (replace && notEnoughData) {
this.previousCandle = candle;
return null;
}
if (!this.previousCandle) {
this.previousCandle = candle;
return null;
}
if (this.lastSar === null) {
const currentMidpoint = (high + low) / 2;
const previousMidpoint = (this.previousCandle.high + this.previousCandle.low) / 2;
this.isLong = currentMidpoint >= previousMidpoint;
if (this.isLong) {
this.extreme = high;
this.lastSar = this.previousCandle.low;
}
else {
this.extreme = low;
this.lastSar = this.previousCandle.high;
}
this.acceleration = this.accelerationStep;
this.prePreviousCandle = this.previousCandle;
this.previousCandle = candle;
return this.setResult(this.lastSar, replace);
}
let sar = (this.extreme - this.lastSar) * this.acceleration + this.lastSar;
if (this.isLong) {
const hasPrevPrev = this.prePreviousCandle != null;
if (hasPrevPrev && low < sar) {
if (this.prePreviousCandle.low < sar) {
sar = this.prePreviousCandle.low;
}
sar = this.previousCandle.low < sar ? this.previousCandle.low : sar;
}
else if (this.previousCandle.low < sar) {
sar = this.previousCandle.low;
}
if (high > this.extreme) {
this.extreme = high;
if (this.acceleration < this.accelerationMax) {
this.acceleration += this.accelerationStep;
if (this.acceleration > this.accelerationMax) {
this.acceleration = this.accelerationMax;
}
}
}
if (low < sar) {
this.isLong = false;
sar = this.extreme;
this.extreme = low;
this.acceleration = this.accelerationStep;
}
}
else {
const hasPrevPrev = this.prePreviousCandle != null;
if (hasPrevPrev && high > sar) {
if (this.prePreviousCandle.high > sar) {
sar = this.prePreviousCandle.high;
}
sar = this.previousCandle.high > sar ? this.previousCandle.high : sar;
}
else if (this.previousCandle.high > sar) {
sar = this.previousCandle.high;
}
if (low < this.extreme) {
this.extreme = low;
this.acceleration += this.accelerationStep;
if (this.acceleration > this.accelerationMax) {
this.acceleration = this.accelerationMax;
}
}
if (high > sar) {
this.isLong = true;
sar = this.extreme;
this.extreme = high;
this.acceleration = this.accelerationStep;
if (sar >= low) {
sar = low - 0.01;
}
}
}
this.lastSar = sar;
this.prePreviousCandle = this.previousCandle;
this.previousCandle = candle;
return this.setResult(sar, replace);
}
getResultOrThrow() {
return super.getResultOrThrow();
}
}
//# sourceMappingURL=PSAR.js.map