highcharts
Version:
JavaScript charting framework
12 lines • 5.28 kB
JavaScript
/**
* Highcharts Stock JS v12.3.0 (2025-06-21)
* @module highcharts/indicators/klinger
* @requires highcharts
* @requires highcharts/modules/stock
*
* Indicator series type for Highcharts Stock
*
* (c) 2010-2025 Karol Kolodziej
*
* License: www.highcharts.com/license
*/import*as e from"../highcharts.js";import"../modules/stock.js";var t,r={};r.n=e=>{var t=e&&e.__esModule?()=>e.default:()=>e;return r.d(t,{a:t}),t},r.d=(e,t)=>{for(var a in t)r.o(t,a)&&!r.o(e,a)&&Object.defineProperty(e,a,{enumerable:!0,get:t[a]})},r.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t);let a=e.default;var i=r.n(a);r.d({},{});let o=e.default.SeriesRegistry;var s=r.n(o);let{sma:{prototype:l}}=s().seriesTypes,{defined:n,error:p,merge:h}=i();!function(e){let t=["bottomLine"],r=["top","bottom"],a=["top"];function i(e){return"plot"+e.charAt(0).toUpperCase()+e.slice(1)}function o(e,t){let r=[];return(e.pointArrayMap||[]).forEach(e=>{e!==t&&r.push(i(e))}),r}function s(){let e=this,t=e.pointValKey,r=e.linesApiNames,a=e.areaLinesNames,s=e.points,g=e.options,u=e.graph,c={options:{gapSize:g.gapSize}},d=[],f=o(e,t),m=s.length,y;if(f.forEach((e,t)=>{for(d[t]=[];m--;)y=s[m],d[t].push({x:y.x,plotX:y.plotX,plotY:y[e],isNull:!n(y[e])});m=s.length}),e.userOptions.fillColor&&a.length){let t=d[f.indexOf(i(a[0]))],r=1===a.length?s:d[f.indexOf(i(a[1]))],o=e.color;e.points=r,e.nextPoints=t,e.color=e.userOptions.fillColor,e.options=h(s,c),e.graph=e.area,e.fillGraph=!0,l.drawGraph.call(e),e.area=e.graph,delete e.nextPoints,delete e.fillGraph,e.color=o}r.forEach((t,r)=>{d[r]?(e.points=d[r],g[t]?e.options=h(g[t].styles,c):p('Error: "There is no '+t+' in DOCS options declared. Check if linesApiNames are consistent with your DOCS line names."'),e.graph=e["graph"+t],l.drawGraph.call(e),e["graph"+t]=e.graph):p('Error: "'+t+" doesn't have equivalent in pointArrayMap. To many elements in linesApiNames relative to pointArrayMap.\"")}),e.points=s,e.options=g,e.graph=u,l.drawGraph.call(e)}function g(e){let t,r=[],a=[];if(e=e||this.points,this.fillGraph&&this.nextPoints){if((t=l.getGraphPath.call(this,this.nextPoints))&&t.length){t[0][0]="L",r=l.getGraphPath.call(this,e),a=t.slice(0,r.length);for(let e=a.length-1;e>=0;e--)r.push(a[e])}}else r=l.getGraphPath.apply(this,arguments);return r}function u(e){let t=[];return(this.pointArrayMap||[]).forEach(r=>{t.push(e[r])}),t}function c(){let e=this.pointArrayMap,t=[],r;t=o(this),l.translate.apply(this,arguments),this.points.forEach(a=>{e.forEach((e,i)=>{r=a[e],this.dataModify&&(r=this.dataModify.modifyValue(r)),null!==r&&(a[t[i]]=this.yAxis.toPixels(r,!0))})})}e.compose=function(e){let i=e.prototype;return i.linesApiNames=i.linesApiNames||t.slice(),i.pointArrayMap=i.pointArrayMap||r.slice(),i.pointValKey=i.pointValKey||"top",i.areaLinesNames=i.areaLinesNames||a.slice(),i.drawGraph=s,i.getGraphPath=g,i.toYData=u,i.translate=c,e}}(t||(t={}));let g=t,{ema:u,sma:c}=s().seriesTypes,{correctFloat:d,error:f,extend:m,isArray:y,merge:A}=i();class v extends c{calculateTrend(e,t){return e[t][1]+e[t][2]+e[t][3]>e[t-1][1]+e[t-1][2]+e[t-1][3]?1:-1}isValidData(e){let t=this.chart,r=this.options,a=this.linkedParent,i=y(e)&&4===e.length,o=this.volumeSeries||(this.volumeSeries=t.get(r.params.volumeSeriesID));return o||f("Series "+r.params.volumeSeriesID+" not found! Check `volumeSeriesID`.",!0,a.chart),!!([a,o].every(function(e){return e&&e.dataTable.rowCount>=r.params.slowAvgPeriod})&&i)}getCM(e,t,r,a,i){return d(t+(r===a?e:i))}getDM(e,t){return d(e-t)}getVolumeForce(e){let t=[],r=0,a,i=1,o=0,s=e[0][1]-e[0][2],l=0,n;for(;i<e.length;i++)n=this.calculateTrend(e,i),a=this.getDM(e[i][1],e[i][2]),r=this.getCM(o,a,n,l,s),t.push([this.volumeSeries.getColumn("y")[i]*n*Math.abs(2*(a/r-1))*100]),l=n,o=r,s=a;return t}getEMA(e,t,r,a,i,o,s){return u.prototype.calculateEma(s||[],e,void 0===o?1:o,a,t,void 0===i?-1:i,r)}getSMA(e,t,r){return u.prototype.accumulatePeriodPoints(e,t,r)/e}getValues(e,t){let r=[],a=e.xData,i=e.yData,o=[],s=[],l=[],n,p=0,h=0,g,u,c,f=null;if(!this.isValidData(i[0]))return;let m=this.getVolumeForce(i),y=this.getSMA(t.fastAvgPeriod,0,m),A=this.getSMA(t.slowAvgPeriod,0,m),v=2/(t.fastAvgPeriod+1),P=2/(t.slowAvgPeriod+1);for(;p<i.length;p++)p>=t.fastAvgPeriod&&(u=h=this.getEMA(m,u,y,v,0,p,a)[1]),p>=t.slowAvgPeriod&&(c=g=this.getEMA(m,c,A,P,0,p,a)[1],l.push(n=d(h-g)),l.length>=t.signalPeriod&&(f=l.slice(-t.signalPeriod).reduce((e,t)=>e+t)/t.signalPeriod),r.push([a[p],n,f]),o.push(a[p]),s.push([n,f]));return{values:r,xData:o,yData:s}}}v.defaultOptions=A(c.defaultOptions,{params:{fastAvgPeriod:34,slowAvgPeriod:55,signalPeriod:13,volumeSeriesID:"volume"},signalLine:{styles:{lineWidth:1,lineColor:"#ff0000"}},dataGrouping:{approximation:"averages"},tooltip:{pointFormat:'<span style="color: {point.color}">●</span><b> {series.name}</b><br/><span style="color: {point.color}">Klinger</span>: {point.y}<br/><span style="color: {point.series.options.signalLine.styles.lineColor}">Signal</span>: {point.signal}<br/>'}}),m(v.prototype,{areaLinesNames:[],linesApiNames:["signalLine"],nameBase:"Klinger",nameComponents:["fastAvgPeriod","slowAvgPeriod"],pointArrayMap:["y","signal"],parallelArrays:["x","y","signal"],pointValKey:"y"}),g.compose(v),s().registerSeriesType("klinger",v);let P=i();export{P as default};