@amcharts/amcharts5
Version:
amCharts 5
87 lines • 3.33 kB
JavaScript
import { ChartIndicator } from "./ChartIndicator";
import { LineSeries } from "../../xy/series/LineSeries";
/**
* An implementation of a [[StockChart]] indicator.
*
* @see {@link https://www.amcharts.com/docs/v5/charts/stock/indicators/} for more info
*/
export class StandardDeviation extends ChartIndicator {
constructor() {
super(...arguments);
this._editableSettings = [{
key: "period",
name: this.root.language.translateAny("Period"),
type: "number",
minValue: 2,
maxValue: 100,
step: 1
}, {
key: "seriesColor",
name: this.root.language.translateAny("Color"),
type: "color"
}, {
key: "field",
name: this.root.language.translateAny("Field"),
type: "dropdown",
options: ["open", "close", "low", "high", "hl/2", "hlc/3", "hlcc/4", "ohlc/4"]
}];
}
_afterNew() {
this._themeTags.push("standarddeviation");
super._afterNew();
}
_createSeries() {
return this.panel.series.push(LineSeries.new(this._root, {
themeTags: ["indicator"],
xAxis: this.xAxis,
yAxis: this.yAxis,
valueXField: "valueX",
valueYField: "deviation",
fill: undefined
}));
}
/**
* @ignore
*/
prepareData() {
super.prepareData();
if (this.series) {
let period = this.get("period", 20);
const stockSeries = this.get("stockSeries");
const dataItems = stockSeries.dataItems;
let data = this._getDataArray(dataItems);
this._sma(data, period, "value_y", "ma");
// Rolling sum / sum of squares over the window, so the standard deviation
// is O(n) instead of O(n * period) and values are read once per bar.
let sum = 0;
let sumSq = 0;
let count = 0;
for (let i = 0, len = data.length; i < len; i++) {
const v = this._getValue(dataItems[i]);
if (v != null) {
sum += v;
sumSq += v * v;
count++;
}
if (i >= period) {
const ov = this._getValue(dataItems[i - period]);
if (ov != null) {
sum -= ov;
sumSq -= ov * ov;
count--;
}
}
if (i >= period - 1) {
// sum((x - m)^2) = sumSq - 2*m*sum + count*m^2, divided by period.
const mean = data[i].ma;
const variance = (sumSq - 2 * mean * sum + count * mean * mean) / period;
data[i].deviation = Math.sqrt(variance < 0 ? 0 : variance);
}
}
this.series.updateData(data);
}
}
}
StandardDeviation.className = "StandardDeviation";
StandardDeviation.classNames = ChartIndicator.classNames.concat([StandardDeviation.className]);
//# sourceMappingURL=StandardDeviation.js.map