@amcharts/amcharts5
Version:
amCharts 5
256 lines • 11.1 kB
JavaScript
import { __awaiter } from "tslib";
import { Indicator } from "./Indicator";
import { LineSeries } from "../../xy/series/LineSeries";
import * as $array from "../../../core/util/Array";
/**
* An implementation of a [[StockChart]] indicator.
*
* @see {@link https://www.amcharts.com/docs/v5/charts/stock/indicators/} for more info
*/
export class SuperTrend extends Indicator {
constructor() {
super(...arguments);
this._editableSettings = [{
key: "period",
name: this.root.language.translateAny("Period"),
type: "number",
minValue: 2,
maxValue: 100,
step: 1
}, {
key: "multiplier",
name: this.root.language.translateAny("Multiplier"),
type: "number",
minValue: 0.5,
maxValue: 10,
step: 0.1
}, {
key: "upperColor",
name: this.root.language.translateAny("Upper"),
type: "color"
}, {
key: "lowerColor",
name: this.root.language.translateAny("Lower"),
type: "color"
}];
}
_afterNew() {
super._afterNew();
const stockSeries = this.get("stockSeries");
const chart = stockSeries.chart;
if (chart) {
const series = chart.series.push(LineSeries.new(this._root, {
valueXField: "valueX",
valueYField: "ma",
groupDataDisabled: true,
calculateAggregates: true,
xAxis: stockSeries.get("xAxis"),
yAxis: stockSeries.get("yAxis"),
themeTags: ["indicator", "supertrend"],
name: "Super Trend",
}));
series.setPrivate("baseValueSeries", stockSeries);
this.series = series;
const upperBandSeries = chart.series.push(LineSeries.new(this._root, {
valueXField: "valueX",
valueYField: "upper",
openValueYField: "value_close",
xAxis: stockSeries.get("xAxis"),
yAxis: stockSeries.get("yAxis"),
groupDataDisabled: true,
calculateAggregates: true,
connect: false,
autoGapCount: Infinity,
themeTags: ["indicator", "supertrend", "upper"]
}));
upperBandSeries.fills.template.set("visible", true);
upperBandSeries.setPrivate("baseValueSeries", stockSeries);
this.upperBandSeries = upperBandSeries;
const lowerBandSeries = chart.series.push(LineSeries.new(this._root, {
valueXField: "valueX",
valueYField: "lower",
openValueYField: "value_close",
xAxis: stockSeries.get("xAxis"),
yAxis: stockSeries.get("yAxis"),
groupDataDisabled: true,
calculateAggregates: true,
connect: false,
autoGapCount: Infinity,
themeTags: ["indicator", "supertrend", "lower"]
}));
lowerBandSeries.fills.template.set("visible", true);
lowerBandSeries.setPrivate("baseValueSeries", stockSeries);
this.lowerBandSeries = lowerBandSeries;
this._handleLegend(this.series);
}
}
_updateChildren() {
super._updateChildren();
if (this.isDirty("upperColor")) {
const color = this.get("upperColor");
const upperBandSeries = this.upperBandSeries;
upperBandSeries.set("stroke", color);
upperBandSeries.set("fill", color);
upperBandSeries.strokes.template.set("stroke", color);
this._updateSeriesColor(upperBandSeries, color, "upperColor");
}
if (this.isDirty("lowerColor")) {
const color = this.get("lowerColor");
const lowerBandSeries = this.lowerBandSeries;
lowerBandSeries.set("stroke", color);
lowerBandSeries.set("fill", color);
lowerBandSeries.strokes.template.set("stroke", color);
this._updateSeriesColor(lowerBandSeries, color, "lowerColor");
}
if (this.isDirty("multiplier")) {
this.markDataDirty();
this.setCustomData("multiplier", this.get("multiplier"));
}
}
_getDataArray(dataItems) {
const data = [];
$array.each(dataItems, (dataItem) => {
data.push({ valueX: dataItem.get("valueX"), value_close: dataItem.get("valueY"), value_high: dataItem.get("highValueY"), value_low: dataItem.get("lowValueY") });
});
return data;
}
/**
* @ignore
*/
prepareData() {
if (this.series) {
let period = this.get("period", 10);
const stockSeries = this.get("stockSeries");
const dataItems = stockSeries.dataItems;
let data = this._getDataArray(dataItems);
let i = 0;
let index = 0;
let tr = 0;
let prevClose;
let prevATR;
let multiplier = this.get("multiplier", 3);
let atr;
let trendDirection = false;
let prevSuperTrend;
let prevUpperBand;
let prevLowerBand;
let upperBand;
let lowerBand;
let superTrend;
$array.each(data, (dataItem) => {
let valueClose = dataItem.value_close;
if (valueClose != null && prevClose != null) {
i++;
tr = Math.max(dataItem.value_high - dataItem.value_low, Math.abs(dataItem.value_high - prevClose), Math.abs(dataItem.value_low - prevClose));
dataItem.tr = tr;
if (i >= period) {
if (i == period) {
let sum = 0;
let k = 0;
for (let j = index; j >= 0; j--) {
sum += data[j].tr;
k++;
if (k == period) {
break;
}
}
atr = sum / period;
}
else {
if (prevATR != null) {
atr = (prevATR * (period - 1) + tr) / period;
}
}
prevATR = atr;
let basicUpperBand = (dataItem.value_high + dataItem.value_low) / 2 + (multiplier * Number(atr));
let basicLowerBand = (dataItem.value_high + dataItem.value_low) / 2 - (multiplier * Number(atr));
// Adjusted bands
if (i === period) {
upperBand = basicUpperBand;
lowerBand = basicLowerBand;
}
else {
upperBand = basicUpperBand < Number(prevUpperBand) || prevClose > Number(prevUpperBand)
? basicUpperBand
: prevUpperBand;
lowerBand = basicLowerBand > Number(prevLowerBand) || prevClose < Number(prevLowerBand)
? basicLowerBand
: prevLowerBand;
}
if (i === period) {
superTrend = valueClose <= Number(upperBand) ? upperBand : lowerBand;
}
else {
if (prevSuperTrend === prevUpperBand && valueClose <= Number(upperBand)) {
superTrend = upperBand;
trendDirection = false; // downtrend
}
else if (prevSuperTrend === prevUpperBand && valueClose > Number(upperBand)) {
superTrend = lowerBand;
trendDirection = true; // uptrend
}
else if (prevSuperTrend === prevLowerBand && valueClose >= Number(lowerBand)) {
superTrend = lowerBand;
trendDirection = true; // uptrend
}
else if (prevSuperTrend === prevLowerBand && valueClose < Number(lowerBand)) {
superTrend = upperBand;
trendDirection = false; // downtrend
}
else {
superTrend = prevSuperTrend;
}
}
if (trendDirection) {
dataItem.lower = superTrend;
dataItem.upper = undefined;
}
else {
dataItem.upper = superTrend;
dataItem.lower = undefined;
}
prevLowerBand = lowerBand;
prevUpperBand = upperBand;
prevSuperTrend = superTrend;
}
}
index++;
prevClose = valueClose;
});
this.upperBandSeries.updateData(data);
this.lowerBandSeries.updateData(data);
}
}
_dispose() {
this.upperBandSeries.dispose();
this.lowerBandSeries.dispose();
super._dispose();
}
hide(duration) {
const _super = Object.create(null, {
hide: { get: () => super.hide }
});
return __awaiter(this, void 0, void 0, function* () {
return Promise.all([
_super.hide.call(this, duration),
this.upperBandSeries.hide(duration),
this.lowerBandSeries.hide(duration)
]);
});
}
show(duration) {
const _super = Object.create(null, {
show: { get: () => super.show }
});
return __awaiter(this, void 0, void 0, function* () {
return Promise.all([
_super.show.call(this, duration),
this.upperBandSeries.show(duration),
this.lowerBandSeries.show(duration)
]);
});
}
}
SuperTrend.className = "SuperTrend";
SuperTrend.classNames = Indicator.classNames.concat([SuperTrend.className]);
//# sourceMappingURL=SuperTrend.js.map