highcharts
Version:
JavaScript charting framework
14 lines • 8.96 kB
JavaScript
/**
* Highstock JS v12.6.0 (2026-04-13)
* @module highcharts/indicators/volume-by-price
* @requires highcharts
* @requires highcharts/modules/stock
*
* Indicator series type for Highcharts Stock
*
* (c) 2010-2026 Highsoft AS
* Author: Paweł Dalek
*
* A commercial license may be required depending on use.
* See www.highcharts.com/license
*/import*as e from"../highcharts.js";var t={};t.n=e=>{var o=e&&e.__esModule?()=>e.default:()=>e;return t.d(o,{a:o}),o},t.d=(e,o)=>{for(var n in o)t.o(o,n)&&!t.o(e,n)&&Object.defineProperty(e,n,{enumerable:!0,get:o[n]})},t.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t);let o=e.default;var n=t.n(o);let i=e.default.SeriesRegistry;var s=t.n(i);let{sma:{prototype:{pointClass:r}}}=s().seriesTypes,a=class extends r{destroy(){this.negativeGraphic&&(this.negativeGraphic=this.negativeGraphic.destroy()),super.destroy.apply(this,arguments)}},{doc:l,win:p}=n();function u(e,t,o,i={}){let s="function"==typeof e&&e.prototype||e;Object.hasOwnProperty.call(s,"hcEvents")||(s.hcEvents={});let r=s.hcEvents;n().Point&&e instanceof n().Point&&e.series&&e.series.chart&&(e.series.chart.runTrackerClick=!0);let a=e.addEventListener;a&&a.call(e,t,o,!!n().supportsPassiveEvents&&{passive:void 0===i.passive?-1!==t.indexOf("touch"):i.passive,capture:!1}),r[t]||(r[t]=[]);let l={fn:o,order:"number"==typeof i.order?i.order:1/0};return r[t].push(l),r[t].sort((e,t)=>e.order-t.order),function(){!function(e,t,o){function n(t,o){let n=e.removeEventListener;n&&n.call(e,t,o,!1)}function i(o){let i,s;e.nodeName&&(t?(i={})[t]=!0:i=o,g(i,function(e,t){if(o[t])for(s=o[t].length;s--;)n(t,o[t][s].fn)}))}let s="function"==typeof e&&e.prototype||e;if(Object.hasOwnProperty.call(s,"hcEvents")){let e=s.hcEvents;if(t){let s=e[t]||[];o?(e[t]=s.filter(function(e){return o!==e.fn}),n(t,o)):(i(e),e[t]=[])}else i(e),delete s.hcEvents}}(e,t,o)}}function h(e){let t=e.length,o=e[0];for(;t--;)e[t]>o&&(o=e[t]);return o}function d(e,t){return e>1e14?e:parseFloat(e.toPrecision(t||14))}function c(e,t){let o;for(o in e||(e={}),t)e[o]=t[o];return e}function m(e){return v(e)&&"number"==typeof e.nodeType}function f(e){let t=Object.prototype.toString.call(e);return"[object Array]"===t||"[object Array Iterator]"===t}function v(e,t){return!!e&&"object"==typeof e&&(!t||!f(e))}function g(e,t,o){for(let n in e)Object.hasOwnProperty.call(e,n)&&t.call(o||e[n],e[n],n,e)}Array.prototype.find;let{animObject:y}=n(),{noop:x}=n(),{column:{prototype:b},sma:D}=s().seriesTypes,V=Math.abs;class P extends D{init(e,t){let o=this;delete t.data,super.init.apply(o,arguments);let n=u(this.chart.constructor,"afterLinkSeries",function(){if(o.options){let t=o.options.params,n=o.linkedParent,i=e.get(t.volumeSeriesID);o.addCustomEvents(n,i)}n()},{order:1});return o}addCustomEvents(e,t){let o=this,n=()=>{o.chart.redraw(),o.setData([]),o.zoneStarts=[],o.zoneLinesSVG&&(o.zoneLinesSVG=o.zoneLinesSVG.destroy())};return o.dataEventsToUnbind.push(u(e,"remove",function(){n()})),t&&o.dataEventsToUnbind.push(u(t,"remove",function(){n()})),o}animate(e){let t=this,o=t.chart.inverted,n=t.group,i={};if(!e&&n){let e=o?t.yAxis.top:t.xAxis.left;o?(n["forceAnimate:translateY"]=!0,i.translateY=e):(n["forceAnimate:translateX"]=!0,i.translateX=e),n.animate(i,c(y(t.options.animation),{step:function(e,o){t.group.attr({scaleX:Math.max(.001,o.pos)})}}))}}drawPoints(){this.options.volumeDivision.enabled&&(this.posNegVolume(!0,!0),b.drawPoints.apply(this,arguments),this.posNegVolume(!1,!1)),b.drawPoints.apply(this,arguments)}posNegVolume(e,t){let o=t?["positive","negative"]:["negative","positive"],n=this.options.volumeDivision,i=this.points.length,s=[],r=[],a=0,l,p,u,h;for(e?(this.posWidths=s,this.negWidths=r):(s=this.posWidths,r=this.negWidths);a<i;a++)(h=this.points[a])[o[0]+"Graphic"]=h.graphic,h.graphic=h[o[1]+"Graphic"],e&&(l=h.shapeArgs.width,(u=(p=this.priceZones[a]).wholeVolumeData)?(s.push(l/u*p.positiveVolumeData),r.push(l/u*p.negativeVolumeData)):(s.push(0),r.push(0))),h.color=t?n.styles.positiveColor:n.styles.negativeColor,h.shapeArgs.width=t?this.posWidths[a]:this.negWidths[a],h.shapeArgs.x=t?h.shapeArgs.x:this.posWidths[a]}translate(){let e=this,t=e.options,o=e.chart,n=e.yAxis,i=n.min,s=e.options.zoneLines,r=e.priceZones,a=0,l,p,u,c,m,f,v,g,y,x;b.translate.apply(e);let D=e.points;D.length&&(v=t.pointPadding<.5?t.pointPadding:.1,l=h(e.volumeDataArray),p=o.plotWidth/2,g=o.plotTop,u=V(n.toPixels(i)-n.toPixels(i+e.rangeStep)),m=V(n.toPixels(i)-n.toPixels(i+e.rangeStep)),v&&(c=V(u*(1-2*v)),a=V((u-c)/2),u=V(c)),D.forEach(function(t,o){y=t.barX=t.plotX=0,x=t.plotY=n.toPixels(r[o].start)-g-(n.reversed?u-m:u)-a,t.pointWidth=f=d(p*r[o].wholeVolumeData/l),t.shapeArgs=e.crispCol.apply(e,[y,x,f,u]),t.volumeNeg=r[o].negativeVolumeData,t.volumePos=r[o].positiveVolumeData,t.volumeAll=r[o].wholeVolumeData}),s.enabled&&e.drawZones(o,n,e.zoneStarts,s.styles))}getExtremes(){let e,t=this.options.compare,o=this.options.cumulative;return this.options.compare?(this.options.compare=void 0,e=super.getExtremes(),this.options.compare=t):this.options.cumulative?(this.options.cumulative=!1,e=super.getExtremes(),this.options.cumulative=o):e=super.getExtremes(),e}getValues(e,t){let n=e.getColumn("x",!0),i=e.processedYData,s=this.chart,r=t.ranges,a=[],l=[],p=[],u=s.get(t.volumeSeriesID);if(!e.chart)return void(0,o.error)("Base series not found! In case it has been removed, add a new one.",!0,s);if(!u||!u.getColumn("x",!0).length){let e=u&&!u.getColumn("x",!0).length?" does not contain any data.":" not found! Check `volumeSeriesID`.";(0,o.error)("Series "+t.volumeSeriesID+e,!0,s);return}let h=f(i[0]);return h&&4!==i[0].length?void(0,o.error)("Type of "+e.name+" series is different than line, OHLC or candlestick.",!0,s):((this.priceZones=this.specifyZones(h,n,i,r,u)).forEach(function(e,t){a.push([e.x,e.end]),l.push(a[t][0]),p.push(a[t][1])}),{values:a,xData:l,yData:p})}specifyZones(e,t,o,n,i){let s=!!e&&function(e){let t=e.length,o=e[0][3],n=o,i=1,s;for(;i<t;i++)(s=e[i][3])<o&&(o=s),s>n&&(n=s);return{min:o,max:n}}(o),r=this.zoneStarts=[],a=[],l=s?s.min:function(e){let t=e.length,o=e[0];for(;t--;)e[t]<o&&(o=e[t]);return o}(o),p=s?s.max:h(o),u=0,c=1,m=this.linkedParent;if(!this.options.compareToMain&&m.dataModify&&(l=m.dataModify.modifyValue(l),p=m.dataModify.modifyValue(p)),null==l||null==p)return this.points.length&&(this.setData([]),this.zoneStarts=[],this.zoneLinesSVG&&(this.zoneLinesSVG=this.zoneLinesSVG.destroy())),[];let f=this.rangeStep=d(p-l)/n;for(r.push(l);u<n-1;u++)r.push(d(r[u]+f));r.push(p);let v=r.length;for(;c<v;c++)a.push({index:c-1,x:t[0],start:r[c-1],end:r[c]});return this.volumePerZone(e,a,i,t,o)}volumePerZone(e,t,o,n,i){let s,r,a,l,p,u=this,h=o.getColumn("x",!0),d=o.getColumn("y",!0),c=t.length-1,m=i.length,f=d.length;return V(m-f)&&(n[0]!==h[0]&&d.unshift(0),n[m-1]!==h[f-1]&&d.push(0)),u.volumeDataArray=[],t.forEach(function(t){for(p=0,t.wholeVolumeData=0,t.positiveVolumeData=0,t.negativeVolumeData=0;p<m;p++){r=!1,a=!1,l=e?i[p][3]:i[p],s=p?e?i[p-1][3]:i[p-1]:l;let o=u.linkedParent;!u.options.compareToMain&&o.dataModify&&(l=o.dataModify.modifyValue(l),s=o.dataModify.modifyValue(s)),l<=t.start&&0===t.index&&(r=!0),l>=t.end&&t.index===c&&(a=!0),(l>t.start||r)&&(l<t.end||a)&&(t.wholeVolumeData+=d[p],s>l?t.negativeVolumeData+=d[p]:t.positiveVolumeData+=d[p])}u.volumeDataArray.push(t.wholeVolumeData)}),t}drawZones(e,t,o,n){let i=e.renderer,s=e.plotWidth,r=e.plotTop,a=this.zoneLinesSVG,l=[],p;o.forEach(function(o){p=t.toPixels(o)-r,l=l.concat(e.renderer.crispLine([["M",0,p],["L",s,p]],n.lineWidth))}),a?a.animate({d:l}):a=this.zoneLinesSVG=i.path(l).attr({"stroke-width":n.lineWidth,stroke:n.color,dashstyle:n.dashStyle,zIndex:this.group.zIndex+.1}).add(this.group)}}P.defaultOptions=function(e,...t){let o,n=[e,...t],i={},s=function(e,t){return"object"!=typeof e&&(e={}),g(t,function(o,n){if("__proto__"!==n&&"constructor"!==n){let i;!v(o,!0)||(i=o?.constructor,v(o,!0)&&!m(o)&&i?.name&&"Object"!==i.name)||m(o)?e[n]=t[n]:e[n]=s(e[n]||{},o)}}),e};!0===e&&(i=n[1],n=Array.prototype.slice.call(n,2));let r=n.length;for(o=0;o<r;o++)i=s(i,n[o]);return i}(D.defaultOptions,{params:{index:void 0,period:void 0,ranges:12,volumeSeriesID:"volume"},zoneLines:{enabled:!0,styles:{color:"#0A9AC9",dashStyle:"LongDash",lineWidth:1}},volumeDivision:{enabled:!0,styles:{positiveColor:"rgba(144, 237, 125, 0.8)",negativeColor:"rgba(244, 91, 91, 0.8)"}},animationLimit:1e3,enableMouseTracking:!1,pointPadding:0,zIndex:-1,crisp:!0,dataGrouping:{enabled:!1},dataLabels:{align:"left",allowOverlap:!0,enabled:!0,format:"P: {point.volumePos:.2f} | N: {point.volumeNeg:.2f}",padding:0,style:{fontSize:"0.5em"},verticalAlign:"top"}}),c(P.prototype,{nameBase:"Volume by Price",nameComponents:["ranges"],calculateOn:{chart:"render",xAxis:"afterSetExtremes"},pointClass:a,markerAttribs:x,drawGraph:x,getColumnMetrics:b.getColumnMetrics,crispCol:b.crispCol}),s().registerSeriesType("vbp",P);let S=n();export{S as default};