--- /home/source/chartjs-chart-financial/Chart.Financial.js 2017-10-31 15:09:02.053048106 -0400 +++ Chart.Financial.js 2017-11-06 11:48:15.044129907 -0500 @@ -47,8 +47,12 @@ var h = data.datasets[tooltipItem.datasetIndex].data[tooltipItem.index].h; var l = data.datasets[tooltipItem.datasetIndex].data[tooltipItem.index].l; var c = data.datasets[tooltipItem.datasetIndex].data[tooltipItem.index].c; +// j mod + var v = data.datasets[tooltipItem.datasetIndex].data[tooltipItem.index].v; + + return ' O ' + o + ' H ' + h + ' L ' + l + ' C ' + c + ' V ' + v; +// - return ' O ' + o + ' H ' + h + ' L ' + l + ' C ' + c; } } } @@ -81,6 +85,7 @@ upCandleColor: dataset.upCandleColor, downCandleColor: dataset.downCandleColor, outlineCandleColor: dataset.outlineCandleColor, + volumeColor: dataset.volumeColor, // j mod outlineCandleWidth: dataset.outlineCandleWidth, }; @@ -102,7 +107,14 @@ var vpixels = me.calculateBarValuePixels(me.index, index); var ipixels = me.calculateBarIndexPixels(me.index, index, ruler); - model.horizontal = horizontal; + +// jmod + model.obase = base; // y height of graph + model.vcalc = base * 0.1; // volume chart to use only 10% of height + model.vtop = base - model.vcalc; + model.maxv = 500; //TODO dynamic max volume per period in trend thus far + model.vheight = model.vcalc/model.maxv; +// model.base = reset ? base : vpixels.base; model.x = horizontal ? reset ? base : vpixels.head : ipixels.center; model.y = horizontal ? ipixels.center : reset ? base : vpixels.head; @@ -120,11 +132,32 @@ var scale = me.getValueScale(); var datasets = chart.data.datasets; +// j mod + var trends = []; + var vol = 0, it=0; + if(typeof datasets[datasetIndex].data[index].v !== 'undefined') vol= Number(datasets[datasetIndex].data[index].v); + if(typeof datasets[datasetIndex].data[index].trends_v === 'object') { // [0]={},[1]={} +// console.log(" trends_v type=",datasets[datasetIndex].data[index].trends_v); + datasets[datasetIndex].data[index].trends_v.forEach(function (ele) { + if(typeof ele==='object') { + for(it in ele) { + trends.push(scale.getPixelForValue(Number(ele[it]))); +// console.log(" trends_v it="+it+" ele[it]="+ele[it]); + } + } + else { trends.push(scale.getPixelForValue(Number(ele))); } + }); +// console.log(" trends length="+trends.length); + } +// + return { o: scale.getPixelForValue(Number(datasets[datasetIndex].data[index].o)), h: scale.getPixelForValue(Number(datasets[datasetIndex].data[index].h)), l: scale.getPixelForValue(Number(datasets[datasetIndex].data[index].l)), - c: scale.getPixelForValue(Number(datasets[datasetIndex].data[index].c)) + c: scale.getPixelForValue(Number(datasets[datasetIndex].data[index].c)), + v: vol, // j mod volume + trends_v: trends // j mod trends array }; }, @@ -163,8 +196,9 @@ globalOpts.elements.candlestick = { upCandleColor: "rgba(80, 160, 115, 1)", downCandleColor: "rgba(215, 85, 65, 1)", - outlineCandleColor: "rgba(90, 90, 90, 1)", - outlineCandleWidth: 1, + outlineCandleColor: "rgba(0, 0, 0, 1)", + volumeColor: "rgb(91, 118, 163,.7)", //j mod + outlineCandleWidth: .4, }; function isVertical(bar) { @@ -187,7 +221,6 @@ y1 = vm.candle.h; y2 = vm.candle.l; - return { left: x1, top: y1, @@ -210,6 +243,11 @@ var l = vm.candle.l; var c = vm.candle.c; +//j mod + var vol = vm.candle.v; + var trends_v = vm.candle.trends_v; +// + ctx.strokeStyle = helpers.getValueOrDefault(vm.outlineCandleColor, globalOpts.elements.candlestick.outlineCandleColor); ctx.lineWidth = helpers.getValueOrDefault(vm.outlineCandleWidth, globalOpts.elements.candlestick.outlineCandleWidth); if (c < o) { @@ -224,9 +262,46 @@ ctx.moveTo(x, h); ctx.lineTo(x, l); ctx.stroke(); - ctx.fillRect(x - vm.width / 2, c, vm.width, o - c); - ctx.strokeRect(x - vm.width / 2, c, vm.width, o - c); + +// j mod updates: reductions + var xl = x - vm.width / 2; + ctx.fillRect(xl, c, vm.width, o - c); + ctx.strokeRect(xl, c, vm.width, o - c); ctx.closePath(); + +// j mod to add trends + var trendsColors=[];//todo + ctx.strokeStyle = "rgba(0,0,0,.3)"; + ctx.fillStyle = "rgba(0,0,0,.3)"; + //ctx.lineWidth = 1; + if(typeof trends_v === 'object' && trends_v.length) { + trends_v.forEach(function(ele) { + ctx.beginPath(); + ctx.arc(xl,ele,2,0,2*Math.PI); + ctx.fill(); + // console.log(" [trends_v] x="+xl+" ele="+ele); + ctx.stroke(); + }); + } + +//j update to add volume + + ctx.strokeStyle = "rgba(0,0,200,1)"; //helpers.getValueOrDefault(vm.volumeColor, globalOpts.elements.candlestick.volumeColor); + ctx.lineWidth = 1; + + ctx.beginPath(); + + ctx.fillStyle = "rgba(0,80,200,.5)"; + +// 3nov17: this is not right given volume data, perhaps scale is not adapted and too large? + + ctx.fillRect( xl, vm.obase-(vm.vheight*vol), vm.width, vm.vheight*vol ); // 0=ymax(top) of graph obase=height at bottom + +// console.log(" [draw] x="+x+" volume=",vol); + ctx.closePath(); + +// + }, height: function() { var vm = this._view; @@ -359,6 +434,10 @@ me.min = null; me.max = null; +// j mod + me.vmax = null; + var useVol=false; +// // Regular charts use x, y values // For the financial chart we have rawValue.h (hi) and rawValue.l (low) for each point helpers.each(datasets, function(dataset, datasetIndex) { @@ -367,13 +446,18 @@ helpers.each(dataset.data, function(rawValue, index) { var high = rawValue.h; var low = rawValue.l; - +//j mod + if(useVol===false && typeof rawValue.v !== 'undefined') { useVol=true; } +// if (me.min === null) { me.min = low; } else if (low < me.min) { me.min = low; } +//j mod + if(useVol===true && (me.vmax === null || rawValue.v>me.vmax)) me.vmax=rawValue.v; +// if (me.max === null) { me.max = high; } else if (high > me.max) {