package.es-modules.Stock.Indicators.DMI.DMIIndicator.js Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of highcharts Show documentation
Show all versions of highcharts Show documentation
JavaScript charting framework
The newest version!
/* *
* (c) 2010-2024 Rafal Sebestjanski
*
* Directional Movement Index (DMI) indicator for Highcharts Stock
*
* License: www.highcharts.com/license
*
* !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
*
* */
'use strict';
import MultipleLinesComposition from '../MultipleLinesComposition.js';
import SeriesRegistry from '../../../Core/Series/SeriesRegistry.js';
const { sma: SMAIndicator } = SeriesRegistry.seriesTypes;
import U from '../../../Core/Utilities.js';
const { correctFloat, extend, isArray, merge } = U;
/* *
*
* Class
*
* */
/**
* The Directional Movement Index (DMI) series type.
*
* @private
* @class
* @name Highcharts.seriesTypes.dmi
*
* @augments Highcharts.Series
*/
class DMIIndicator extends SMAIndicator {
/* *
*
* Functions
*
* */
calculateDM(yVal, i, isPositiveDM) {
const currentHigh = yVal[i][1], currentLow = yVal[i][2], previousHigh = yVal[i - 1][1], previousLow = yVal[i - 1][2];
let DM;
if (currentHigh - previousHigh > previousLow - currentLow) {
// For +DM
DM = isPositiveDM ? Math.max(currentHigh - previousHigh, 0) : 0;
}
else {
// For -DM
DM = !isPositiveDM ? Math.max(previousLow - currentLow, 0) : 0;
}
return correctFloat(DM);
}
calculateDI(smoothedDM, tr) {
return smoothedDM / tr * 100;
}
calculateDX(plusDI, minusDI) {
return correctFloat(Math.abs(plusDI - minusDI) / Math.abs(plusDI + minusDI) * 100);
}
smoothValues(accumulatedValues, currentValue, period) {
return correctFloat(accumulatedValues - accumulatedValues / period + currentValue);
}
getTR(currentPoint, prevPoint) {
return correctFloat(Math.max(
// `currentHigh - currentLow`
currentPoint[1] - currentPoint[2],
// `currentHigh - previousClose`
!prevPoint ? 0 : Math.abs(currentPoint[1] - prevPoint[3]),
// `currentLow - previousClose`
!prevPoint ? 0 : Math.abs(currentPoint[2] - prevPoint[3])));
}
getValues(series, params) {
const period = params.period, xVal = series.xData, yVal = series.yData, yValLen = yVal ? yVal.length : 0, DMI = [], xData = [], yData = [];
if (
// Check period, if bigger than points length, skip
(xVal.length <= period) ||
// Only ohlc data is valid
!isArray(yVal[0]) ||
yVal[0].length !== 4) {
return;
}
let prevSmoothedPlusDM = 0, prevSmoothedMinusDM = 0, prevSmoothedTR = 0, i;
for (i = 1; i < yValLen; i++) {
let smoothedPlusDM, smoothedMinusDM, smoothedTR, plusDM, // +DM
minusDM, // -DM
TR, plusDI, // +DI
minusDI, // -DI
DX;
if (i <= period) {
plusDM = this.calculateDM(yVal, i, true);
minusDM = this.calculateDM(yVal, i);
TR = this.getTR(yVal[i], yVal[i - 1]);
// Accumulate first period values to smooth them later
prevSmoothedPlusDM += plusDM;
prevSmoothedMinusDM += minusDM;
prevSmoothedTR += TR;
// Get all values for the first point
if (i === period) {
plusDI = this.calculateDI(prevSmoothedPlusDM, prevSmoothedTR);
minusDI = this.calculateDI(prevSmoothedMinusDM, prevSmoothedTR);
DX = this.calculateDX(prevSmoothedPlusDM, prevSmoothedMinusDM);
DMI.push([xVal[i], DX, plusDI, minusDI]);
xData.push(xVal[i]);
yData.push([DX, plusDI, minusDI]);
}
}
else {
// Calculate current values
plusDM = this.calculateDM(yVal, i, true);
minusDM = this.calculateDM(yVal, i);
TR = this.getTR(yVal[i], yVal[i - 1]);
// Smooth +DM, -DM and TR
smoothedPlusDM = this.smoothValues(prevSmoothedPlusDM, plusDM, period);
smoothedMinusDM = this.smoothValues(prevSmoothedMinusDM, minusDM, period);
smoothedTR = this.smoothValues(prevSmoothedTR, TR, period);
// Save current smoothed values for the next step
prevSmoothedPlusDM = smoothedPlusDM;
prevSmoothedMinusDM = smoothedMinusDM;
prevSmoothedTR = smoothedTR;
// Get all next points (except the first one calculated above)
plusDI = this.calculateDI(prevSmoothedPlusDM, prevSmoothedTR);
minusDI = this.calculateDI(prevSmoothedMinusDM, prevSmoothedTR);
DX = this.calculateDX(prevSmoothedPlusDM, prevSmoothedMinusDM);
DMI.push([xVal[i], DX, plusDI, minusDI]);
xData.push(xVal[i]);
yData.push([DX, plusDI, minusDI]);
}
}
return {
values: DMI,
xData: xData,
yData: yData
};
}
}
/* *
*
* Static Properties
*
* */
/**
* Directional Movement Index (DMI).
* This series requires the `linkedTo` option to be set and should
* be loaded after the `stock/indicators/indicators.js` file.
*
* @sample stock/indicators/dmi
* DMI indicator
*
* @extends plotOptions.sma
* @since 9.1.0
* @product highstock
* @excluding allAreas, colorAxis, joinBy, keys, navigatorOptions,
* pointInterval, pointIntervalUnit, pointPlacement,
* pointRange, pointStart, showInNavigator, stacking
* @requires stock/indicators/indicators
* @requires stock/indicators/dmi
* @optionparent plotOptions.dmi
*/
DMIIndicator.defaultOptions = merge(SMAIndicator.defaultOptions, {
/**
* @excluding index
*/
params: {
index: void 0 // Unused index, do not inherit (#15362)
},
marker: {
enabled: false
},
tooltip: {
pointFormat: '' +
'\u25CF {series.name}
' +
'DX: {point.y}
' +
'' +
'+DI: {point.plusDI}
' +
'' +
'-DI: {point.minusDI}
'
},
/**
* +DI line options.
*/
plusDILine: {
/**
* Styles for the +DI line.
*/
styles: {
/**
* Pixel width of the line.
*/
lineWidth: 1,
/**
* Color of the line.
*
* @type {Highcharts.ColorString}
*/
lineColor: "#06b535" /* Palette.positiveColor */ // Green-ish
}
},
/**
* -DI line options.
*/
minusDILine: {
/**
* Styles for the -DI line.
*/
styles: {
/**
* Pixel width of the line.
*/
lineWidth: 1,
/**
* Color of the line.
*
* @type {Highcharts.ColorString}
*/
lineColor: "#f21313" /* Palette.negativeColor */ // Red-ish
}
},
dataGrouping: {
approximation: 'averages'
}
});
extend(DMIIndicator.prototype, {
areaLinesNames: [],
nameBase: 'DMI',
linesApiNames: ['plusDILine', 'minusDILine'],
pointArrayMap: ['y', 'plusDI', 'minusDI'],
parallelArrays: ['x', 'y', 'plusDI', 'minusDI'],
pointValKey: 'y'
});
MultipleLinesComposition.compose(DMIIndicator);
SeriesRegistry.registerSeriesType('dmi', DMIIndicator);
/* *
*
* Default Export
*
* */
export default DMIIndicator;
/* *
*
* API Options
*
* */
/**
* The Directional Movement Index (DMI) indicator series.
* If the [type](#series.dmi.type) option is not
* specified, it is inherited from [chart.type](#chart.type).
*
* @extends series,plotOptions.dmi
* @since 9.1.0
* @product highstock
* @excluding allAreas, colorAxis, dataParser, dataURL, joinBy, keys,
* navigatorOptions, pointInterval, pointIntervalUnit,
* pointPlacement, pointRange, pointStart, showInNavigator, stacking
* @requires stock/indicators/indicators
* @requires stock/indicators/dmi
* @apioption series.dmi
*/
''; // To include the above in the js output