Highstock/Highchart substep maximum? - javascript

example
I want my maximum step count to cap at a dynamic integer. In this case it's 4. I went through the documentation but can't find anything that suits my needs. Does someone have an idea about this?
Ideally; I want the white space shown in red gone.
xAxis: {
min: 1.1,
ordinal: false,
max: 2,
labels: {
formatter: function () {
return 'Lap ' + this.value;
},
},
},
http://jsfiddle.net/d54uae3s/4/

You can use breaks from the broken-axis Highcharts module:
function createBreaks() {
var breaks = [];
for (var i = 1; i < 8; i++) {
breaks.push({
from: i + 0.4,
to: i + 1.1,
breakSize: 0.1
})
}
return breaks;
}
var chart = Highcharts.chart({
...,
xAxis: {
...
breaks: createBreaks()
}
});
Live demo: http://jsfiddle.net/BlackLabel/sjLdfegp/
API Reference: https://api.highcharts.com/highstock/xAxis.breaks

Related

Can i use crosshairs with OHLC/candlestick charts using ChartJS

I have installed the crosshair plugin and am using chartJS 3.0 to take advantage of the candlestick charts but the crosshair does not appear. are these things compatible together? my data appear no problem but the crosshair never appears. how do i use these two things together? are there any working examples?
the tags i am using
<script src="https://cdn.jsdelivr.net/npm/luxon#1.24.1"></script>
<script src="https://cdn.jsdelivr.net/npm/chart.js#3.0.0-beta.9/dist/chart.js"></script>
<script src="https://cdn.jsdelivr.net/npm/chartjs-adapter-luxon#0.2.1"></script>
<script src="https://dd7tel2830j4w.cloudfront.net/f1614793727236x392906938665549250/chartjs-chart-financial.js"></script>
<script scr="https://cdn.jsdelivr.net/npm/chartjs-plugin-crosshair"></script>
and the chart code which also works
var divID = "chartContainer" + properties.chartid
var chartID = "myChart" + properties.chartid
instance.canvas.append('<div id="' + divID + '"></div>')
document.getElementById(divID).innerHTML = ' ';
document.getElementById(divID).innerHTML = '<canvas id=' + chartID + ' width="' + properties.bubble.width() + '" height="' + properties.bubble.height() + '"></canvas>';
var ctx = document.getElementById(chartID).getContext('2d');
var chart = new Chart(ctx, {
type: 'candlestick',
data: {
datasets: [{
label: 'CHRT - Chart.js Corporation',
data: getData()
}]
},
options: {
scales: {
y: {
min: 0,
max: 500
}
},
tooltips: {
mode: "interpolate",
intersect: false
},
plugins: {
crosshair: {
line: {
color: '#F66', // crosshair line color
width: 3, // crosshair line width
dashPattern: [5, 5] // crosshair line dash pattern
},
sync: {
enabled: true, // enable trace line syncing with other charts
group: 1, // chart group
suppressTooltips: false // suppress tooltips when showing a synced tracer
},
zoom: {
enabled: true, // enable zooming
zoomboxBackgroundColor: 'rgba(66,133,244,0.2)', // background color of zoom box
zoomboxBorderColor: '#48F', // border color of zoom box
zoomButtonText: 'Reset Zoom', // reset zoom button text
zoomButtonClass: 'reset-zoom', // reset zoom button class
},
callbacks: {
beforeZoom: function(start, end) { // called before zoom, return false to prevent zoom
return true;
},
afterZoom: function(start, end) { // called after zoom
}
}
}
}
}
});
function getData() {
var dates = properties.time.get(0, properties.time.length())
var opens = properties.open.get(0, properties.open.length())
var highs = properties.high.get(0, properties.high.length())
var lows = properties.low.get(0, properties.low.length())
var closes = properties.close.get(0, properties.close.length())
let data = []
for (i = 0; i < dates.length; i++) {
data.push({
t: dates[i].valueOf(),
o: opens[i],
h: highs[i],
l: lows[i],
c: closes[i]
})
}
console.log(data)
return data
}
chart.update()
The crosair plugin is not yet compatible with the new beta of version 3. They have a pr to be up to date with beta 11 but after that there have been breaking changes again. So you will have to update the plugin yourself or wait till it has been updated to support v3

How to draw a line on a highcharts graph from an AJAX call?

I have in my html page a highcharts graph that I want to update dynamically. I have some input boxes that once they get updated by the user, trigger an AJAX post request. The request does some calculations and I want the output to be used to re-draw the line of my chart's second serie . That line represents a simple y = x function, the 'x' variable being calculated during the AJAX call.
Here is my html/JS code for the chart:
<script type="text/javascript">
$(function () {
$(document).ready(function () {
Highcharts.setOptions({
global: {
useUTC: false
}
});
var chart;
$('#container').highcharts({
chart: {
type: 'line',
animation: Highcharts.svg,
marginRight: 10,
},
title: {
text: 'Strategy Payoff'
},
xAxis: {
//type: 'datetime',
tickPixelInterval: 150
},
yAxis: {
title: {
text: 'Value'
},
plotLines: [{
value: 0,
width: 1,
color: '#808080'
}]
},
legend: {
enabled: false
},
exporting: {
enabled: false
},
series: [{
name: 'PnL',
data: (function () {
var data = [],
time = (new Date()).getTime(),
i;
var V = document.getElementById('V').value;
var Q = document.getElementById('Q').value;
var S = document.getElementById('S').value;
var K = document.getElementById('K').value;
var Type = document.getElementById('Type').value;
if (Type == 'Call') {
direction = 1;
} else {
direction = -1;
}
if (S >= 5000) {
stepSize = 500;
} else if (S >= 500) {
stepSize = 50;
} else {
stepSize = 1;
}
for (i = 0; i <= S * 2; i+=stepSize) { // i+=stepSize
data.push({
x: i,
y: Math.max(-V * Q, -V * Q + Q * direction * (i-K))
});
}
return data;
})()
}, {
name: 'Current Option Strategy PnL',
data: (function pnl(value=10) {
var data2 = [],
time2 = (new Date()).getTime(),
i;
var S = document.getElementById('S').value;
if (S >= 5000) {
stepSize = 500;
} else if (S >= 500) {
stepSize = 50;
} else {
stepSize = 1;
}
for (i = 0; i <= S * 2; i+=stepSize) {
data2.push({
x: i,
y: value
});
}
return data2;
})()
}]
});
});
});
</script>
Here are the input boxes that trigger the AJAX request when updated by the user:
<div class="chart" id="container"></div>
<div class="slider-wrapper">
<span>Option 1 Imp. Vol.</span>
<input class="toChange" id="rangeInput" name="rangeInput" type="range" value="{{Sigma}}" min="0.1" max="150" lang="en_EN" step="0.1" oninput="amount.value=rangeInput.value" />
<input class="toChange" id="amount" type="number" value="{{Sigma}}" min="0.1" max="150" lang="en_EN" step="0.1"oninput="rangeInput.value=amount.value" />
</div>
Finally, here is the AJAX request itself:
<script type="text/javascript">
function inputChange () {
var Sigma = document.getElementById("rangeInput").value;
var Type = document.getElementById('Type').value;
var S = document.getElementById('S').value;
var K = document.getElementById('K').value;
var t = document.getElementById('t').value;
var r = document.getElementById('r').value;
var V = document.getElementById('V').value;
var Q = document.getElementById('Q').value;
$.ajax({
url: '/optionstrategies/',
type: 'POST',
data: {
'Type': Type,
'S': S,
'K': K,
'r': r,
't': t,
'Sigma': Sigma,
},
success: function(optionVal) {
alert((optionVal - V) * Q);
document.getElementById("oPrice").innerHTML = optionVal;
document.getElementById("PnL").innerHTML = (optionVal - V) * Q;
// pnl(12);
}
});
}
$(".toChange").change(inputChange);
</script>
The AJAX call works well as the alert shows the expected value. I now need to use that value to update my chart. So for instance, if the value is equal to 12, I need the second serie of my chart to draw a line representing the y = 12 function.
I've named the function dealing with my second serie 'pnl' as you can see. I've been trying to call that function in the 'success' part of my AJAX request by writing something like 'pnl(12);', but it didn't do anything. Could anybody please help?
Use the series.update feature inside the success call and set the new data on it. Please check the available demos under below link.
API: https://api.highcharts.com/class-reference/Highcharts.Series#update
If this clue wouldn't help, please reproduce a simplified version of your code on some online editor which I could work on.

Highcharts sparklines from ajax-inserted data

You have a html table and you want to show sparkline charts from your data, exactly as in this example (from highcharts demos):
https://codepen.io/_dario/pen/rNBOGVR
Highcharts suggested code follows:
/**
* Create a constructor for sparklines that takes some sensible defaults and merges in the individual
* chart options. This function is also available from the jQuery plugin as $(element).highcharts('SparkLine').
*/
Highcharts.SparkLine = function(a, b, c) {
var hasRenderToArg = typeof a === 'string' || a.nodeName,
options = arguments[hasRenderToArg ? 1 : 0],
defaultOptions = {
chart: {
renderTo: (options.chart && options.chart.renderTo) || this,
backgroundColor: null,
borderWidth: 0,
type: 'area',
margin: [2, 0, 2, 0],
width: 120,
height: 20,
style: {
overflow: 'visible'
},
// small optimalization, saves 1-2 ms each sparkline
skipClone: true
},
title: {
text: ''
},
credits: {
enabled: false
},
xAxis: {
labels: {
enabled: false
},
title: {
text: null
},
startOnTick: false,
endOnTick: false,
tickPositions: []
},
yAxis: {
endOnTick: false,
startOnTick: false,
labels: {
enabled: false
},
title: {
text: null
},
tickPositions: [0]
},
legend: {
enabled: false
},
tooltip: {
hideDelay: 0,
outside: true,
shared: true
},
plotOptions: {
series: {
animation: false,
lineWidth: 1,
shadow: false,
states: {
hover: {
lineWidth: 1
}
},
marker: {
radius: 1,
states: {
hover: {
radius: 2
}
}
},
fillOpacity: 0.25
},
column: {
negativeColor: '#910000',
borderColor: 'silver'
}
}
};
options = Highcharts.merge(defaultOptions, options);
return hasRenderToArg ?
new Highcharts.Chart(a, options, c) :
new Highcharts.Chart(options, b);
};
var start = +new Date(),
$tds = $('td[data-sparkline]'),
fullLen = $tds.length,
n = 0;
// Creating 153 sparkline charts is quite fast in modern browsers, but IE8 and mobile
// can take some seconds, so we split the input into chunks and apply them in timeouts
// in order avoid locking up the browser process and allow interaction.
function doChunk() {
var time = +new Date(),
i,
len = $tds.length,
$td,
stringdata,
arr,
data,
chart;
for (i = 0; i < len; i += 1) {
$td = $($tds[i]);
stringdata = $td.data('sparkline');
arr = stringdata.split('; ');
data = $.map(arr[0].split(', '), parseFloat);
chart = {};
if (arr[1]) {
chart.type = arr[1];
}
$td.highcharts('SparkLine', {
series: [{
data: data,
pointStart: 1
}],
tooltip: {
headerFormat: '<span style="font-size: 10px">' + $td.parent().find('th').html() + ', Q{point.x}:</span><br/>',
pointFormat: '<b>{point.y}.000</b> USD'
},
chart: chart
});
n += 1;
// If the process takes too much time, run a timeout to allow interaction with the browser
if (new Date() - time > 500) {
$tds.splice(0, i + 1);
setTimeout(doChunk, 0);
break;
}
// Print a feedback on the performance
if (n === fullLen) {
$('#result').html('Generated ' + fullLen + ' sparklines in ' + (new Date() - start) + ' ms');
}
}
}
doChunk();
However, in my use case, the data in the table (and the data-sparkline attribute) are not hard-coded like in the example, but loaded and displayed via an AJAX call, similar to below.
//here a table row gets compiled
var tableRow = '<tr id="row_' + word.id + '">';
//this is where the sparkline data go
tableRow += '<td class="has-sparkline"></td></tr>';
//the row gets appended to tbody
$('#wordstable tbody').append(tableRow);
//finally the sparkline data are attached
//data are a simple string such as "1,2,3,4,5"
var rowId = '#row_'+word.id;
var rowIdTd = rowId + ' td.has-sparkline';
$(rowIdTd).data('sparkline',word.sparkline);
This breaks the example logic and I can't have Highcharts "see" the data.
No particular error is returned (as the data, as far as Highcharts is concerned, just isn't there, so there's nothing to do).
The doChunk bit just does all the processing in advance, and when you add your row it is no longer processing. One way of dealing with this is pulling out the part that creates a single chart into a separate function (makeChart) and when you are doing your processing you use that part directly to create your sparkline.
For example, doChunk with split out makeChart:
function makeChart(td) {
$td = td;
stringdata = $td.data('sparkline');
arr = stringdata.split('; ');
data = $.map(arr[0].split(', '), parseFloat);
chart = {};
if (arr[1]) {
chart.type = arr[1];
}
$td.highcharts('SparkLine', {
series: [{
data: data,
pointStart: 1
}],
tooltip: {
headerFormat: '<span style="font-size: 10px">' + $td.parent().find('th').html() + ', Q{point.x}:</span><br/>',
pointFormat: '<b>{point.y}.000</b> USD'
},
chart: chart
});
}
// Creating 153 sparkline charts is quite fast in modern browsers, but IE8 and mobile
// can take some seconds, so we split the input into chunks and apply them in timeouts
// in order avoid locking up the browser process and allow interaction.
function doChunk() {
var time = +new Date(),
i,
len = $tds.length,
$td,
stringdata,
arr,
data,
chart;
for (i = 0; i < len; i += 1) {
makeChart($($tds[i]));
n += 1;
// If the process takes too much time, run a timeout to allow interaction with the browser
if (new Date() - time > 500) {
$tds.splice(0, i + 1);
setTimeout(doChunk, 0);
break;
}
// Print a feedback on the performance
if (n === fullLen) {
$('#result').html('Generated ' + fullLen + ' sparklines in ' + (new Date() - start) + ' ms');
}
}
}
And then a basic example of your ajax-code:
function ajaxIsh() {
var word = {
name: 'Bird', // is the word
id: 'bird',
sparkline: '1, 2, 3, 4, 5'
};
//here a table row gets compiled
var tableRow = '<tr id="row_' + word.id + '">';
//this is where the sparkline data go
tableRow += '<th>'+word.name+'</th><td class="has-sparkline"></td></tr>';
//the row gets appended to tbody
$('#table-sparkline tbody').append(tableRow);
//finally the sparkline data are attached
//data are a simple string such as "1,2,3,4,5"
var rowId = '#row_'+word.id;
var rowIdTd = rowId + ' td.has-sparkline';
$(rowIdTd).data('sparkline',word.sparkline);
makeChart($(rowIdTd));
}
See this JSFiddle demonstration of it in action.

ChartJS - legends and tooltips options

This is the first time I'm using ChartJS v2.
I creating a simple line chart with several datasets.
I have 3 problems:
1 - It has the correct data shown, but I have a problem with the legends, as they appear left aligned with the color box out of the canvas, and one per line like in the image bellow (https://i.stack.imgur.com/c9qBe.png).
I want the legends like float: left; in css.
2 - Other problem is the tooltips, they're very big.. like shown in the image bellow. (https://i.stack.imgur.com/txXCF.png)
I tried to find the options to achieve this but it hard for me to make it work.
3 - I want the interval in the y-axis to be 1 not 0.1.
Bellow is the JS code used to create the chart:
var scripts = $(".sending-data");
var datasets = [];
var days = [];
var counter = 0;
scripts.each(function (index, script){
var json = JSON.parse(script.innerHTML);
var data = [];
for (var i = 0; i<json.DATA.length; i++) {
data.push(json.DATA[i][2]);
if (counter === 0)
days.push(json.DATA[i][1].substr(8, 2));
}
var r = Math.floor((Math.random() * 255) + 1);
var g = Math.floor((Math.random() * 255) + 1);
var b = Math.floor((Math.random() * 255) + 1);
var rgbStr = r+ ", " +g + ", " + b;
console.log(rgbStr);
datasets.push({
label: "## " + $(script).attr("data-send-id"),
backgroundColor: 'rgba('+rgbStr+', 0.2)',
borderColor: 'rgba('+rgbStr+', 1)',
borderWidth: 2,
lineTension: 0.1,
data: data,
fill: false
});
counter++;
});
var config ={
type: 'line',
data: {
labels: days,
datasets: datasets
},
options: {
title: {
display: true,
text: 'Custom Chart Title'
},
responsive : true,
legend: {
fullWidth: false,
boxWidth: 50,
padding: 40,
position: "top",
display: true
},
scales: {
yAxes: [{
ticks: {
beginAtZero:true,
stepSize: 1
}
}]
}
}
};
var ctx = document.querySelector("##canvas-chart").getContext("2d");
console.log(document.querySelector("##canvas-chart"));
var myLine = new Chart(ctx, config);
Dont mind the '##' selector, I'm using CFusion.
Any help from you guys?
--DISCLAIMER--
I managed to set the stepSize: 1 so the interval is 1. But still have the problem (1) and (2)
Thanks in advance!
Happy Programming!
So the problem is this - I'm dumb..
hahaha
The dataset labels had a lot of whitespace... so I just replaced all " " by "" and it showed correctly..
Thanks to all of you.
Cheers and happy programming!

DataLabels on series with many points

I often have to show serieses with many points and I want to set dataLabels for some points. This works fine, but when the series has too many points, the dataLabel is not visible in the beginning. When I zoom into the series, I can see that it is displayed correctly.
So my question: Is there a way to show the dataLabel always for such a series?
Here is my JSFiddle: http://jsfiddle.net/Charissima/9aB6B/
dataLabel at 51.
$(function() {
var myData = [];
for (var i = 0; i < 50; i++) {
myData.push(i + Math.random() * 3);
}
myData.push(51);
for (var i = 52; i < 400; i++) {
myData.push(i + Math.random() * 3);
}
chart = $('#container').highcharts('StockChart', {
chart : {
zoomType: 'x',
events : {
load : function() {
myChart = this;
mySeries = this.series[1];
},
}
},
plotOptions: {
series: {
dataLabels: {
enabled: true,
formatter: setDataLabels
}
}
},
series: [
{
name: 'Label51',
id : 'dataseries',
color: 'blue',
data: myData
}
]
});
function setDataLabels() {
if (this.y == 51) {
return this.y;
} else {
return null;
}
}
});
This is caused by dataGoruping - disable it and will work fine.

Categories

Resources