This is the modified file, built on the ohlc module, that I have used.
I didn't make the modifications myself, I used it as is from what I think are leftout's modifications.
Code: Select all
/* ohlc.src.js */
/**
* @license Highcharts JS v2.1.4 (2011-03-02)
* Candlestick/OHLC series module, Beta
*
* (c) 2010 Torstein H├©nsi
*
* License: http://www.highcharts.com/license
*/
(function(){ // encapsulate
// create shortcuts
var HC = Highcharts,
addEvent = HC.addEvent,
defaultOptions = HC.getOptions(),
defaultPlotOptions = defaultOptions.plotOptions,
seriesTypes = HC.seriesTypes,
extend = HC.extend,
each = HC.each,
map = HC.map,
merge = HC.merge,
math = Math,
mathRound = math.round;
/*****************************************************************************
* Start OHLC series code *
*****************************************************************************/
// 1 - Set default options
defaultPlotOptions.OHLC = merge(defaultPlotOptions.column, {
animation: false,
lineWidth: 1,
states: {
hover: {
//brightness: 0.1,
lineWidth: 3
}
}
});
// 2- Create the OHLCPoint object
var OHLCPoint = Highcharts.extendClass(Highcharts.Point, {
/**
* Apply the options containing the x and OHLC data and possible some extra properties.
* This is called on point init or from point.update. Extends base Point by adding
* multiple y-like values.
*
* @param {Object} options
*/
applyOptions: function(options) {
var point = this,
series = point.series,
n,
i = 0;
// object input for example:
// { x: Date(2010, 0, 1), open: 7.88, high: 7.99, low: 7.02, close: 7.65 }
if (typeof options == 'object' && typeof options.length != 'number') {
// copy options directly to point
extend(point, options);
point.options = options;
}
// array
else if (options.length) {
// with leading x value
if (options.length == 5) {
if (typeof options[0] == 'string') {
point.name = options[0];
} else if (typeof options[0] == 'number') {
point.x = options[0];
}
i++;
}
point.open = options[i++];
point.high = options[i++];
point.low = options[i++];
point.close = options[i++];
}
/*
* If no x is set by now, get auto incremented value. All points must have an
* x value, however the y value can be null to create a gap in the series
*/
point.y = point.high;
if (point.x === undefined) {
point.x = series.autoIncrement();
}
},
/**
* A specific OHLC tooltip formatter
*/
tooltipFormatter: function(useHeader) {
var point = this,
series = point.series;
return ['<span style="color:'+ series.color +';font-weight:bold">', (point.name || series.name), '</span><br/> ',
'Open: ', point.open, '<br/>',
'High: ', point.y, '<br/>',
'Low: ', point.low, '<br/>',
'Close: ', point.close].join('');
}
});
// 3 - Create the OHLCSeries object
var OHLCSeries = Highcharts.extendClass(seriesTypes.column, {
type: 'OHLC',
pointClass: OHLCPoint,
pointAttrToOptions: { // mapping between SVG attributes and the corresponding options
stroke: 'color',
'stroke-width': 'lineWidth'
},
/**
* Translate data points from raw values x and y to plotX and plotY
*/
translate: function() {
var chart = this.chart,
series = this,
categories = series.xAxis.categories,
yAxis = series.yAxis,
stack = yAxis.stacks[series.type];
seriesTypes.column.prototype.translate.apply(series);
// do the translation
each(this.data, function(point) {
// the graphics
point.plotOpen = yAxis.translate(point.open, 0, 1);
point.plotClose = yAxis.translate(point.close, 0, 1);
});
},
/**
* Draw the data points
*/
drawPoints: function() {
var series = this, //state = series.state,
//layer = series.stateLayers[state],
seriesOptions = series.options,
seriesStateAttr = series.stateAttr,
data = series.data,
chart = series.chart,
pointAttr,
pointOpen,
pointClose,
crispCorr,
halfWidth,
path,
graphic,
crispX;
each(data, function(point) {
graphic = point.graphic;
if (point.plotY !== undefined &&
point.plotX >= 0 && point.plotX <= chart.plotSizeX &&
point.plotY >= 0 && point.plotY <= chart.plotSizeY) {
pointAttr = point.pointAttr[point.selected ? 'selected' : ''];
// crisp vector coordinates
crispCorr = (pointAttr['stroke-width'] % 2) / 2;
crispX = mathRound(point.plotX) + crispCorr;
plotOpen = mathRound(point.plotOpen) + crispCorr;
plotClose = mathRound(point.plotClose) + crispCorr;
halfWidth = mathRound(point.barW / 2);
path = [
'M',
crispX, mathRound(point.yBottom),
'L',
crispX, mathRound(point.plotY),
'M',
crispX, plotOpen,
'L',
crispX - halfWidth, plotOpen,
'M',
crispX, plotClose,
'L',
crispX + halfWidth, plotClose,
'Z'
];
if (graphic) {
graphic.animate({
d: path
});
} else {
point.graphic = chart.renderer.path(path)
.attr(pointAttr)
.add(series.group);
}
} else if (graphic) {
point.graphic = graphic.destroy();
}
});
}
});
seriesTypes.OHLC = OHLCSeries;
/*****************************************************************************
* End OHLC series code *
*****************************************************************************/
/*****************************************************************************
* Start Candlestick series code *
*****************************************************************************/
// 1 - set default options
defaultPlotOptions.candlestick = merge(defaultPlotOptions.column, {
animation: false,
lineColor: 'black',
lineWidth: 2,
upColor: 'white',
states: {
hover: {
lineWidth: 3
}
}
});
// 3 - Create the CandlestickSeries object
var CandlestickSeries = Highcharts.extendClass(OHLCSeries, {
type: 'candlestick',
/**
* One-to-one mapping from options to SVG attributes
*/
pointAttrToOptions: { // mapping between SVG attributes and the corresponding options
fill: 'color',
stroke: 'lineColor',
'stroke-width': 'lineWidth'
},
/**
* Postprocess mapping between options and SVG attributes
*/
getAttribs: function() {
OHLCSeries.prototype.getAttribs.apply(this, arguments);
var series = this,
options = series.options,
stateOptions = options.states,
upColor = options.upColor,
seriesDownPointAttr = merge(series.pointAttr);
seriesDownPointAttr[''].fill = upColor;
seriesDownPointAttr.hover.fill = stateOptions.hover.upColor || upColor;
seriesDownPointAttr.select.fill = stateOptions.select.upColor || upColor;
each(series.data, function(point) {
if (point.open < point.close) {
point.pointAttr = seriesDownPointAttr;
}
});
},
/**
* Draw the data points
*/
drawPoints: function() {
var series = this, //state = series.state,
//layer = series.stateLayers[state],
seriesOptions = series.options,
seriesStateAttr = series.stateAttr,
data = series.data,
chart = series.chart,
pointAttr,
pointOpen,
pointClose,
topBox,
bottomBox,
crispCorr,
crispX,
graphic,
path,
halfWidth;
each(data, function(point) {
graphic = point.graphic;
if (point.plotY !== undefined &&
point.plotX >= 0 && point.plotX <= chart.plotSizeX &&
point.plotY >= 0 && point.plotY <= chart.plotSizeY) {
pointAttr = point.pointAttr[point.selected ? 'selected' : ''];
// crisp vector coordinates
crispCorr = (pointAttr['stroke-width'] % 2) / 2;
crispX = mathRound(point.plotX) + crispCorr;
plotOpen = mathRound(point.plotOpen) + crispCorr;
plotClose = mathRound(point.plotClose) + crispCorr;
topBox = math.min(plotOpen, plotClose);
bottomBox = math.max(plotOpen, plotClose);
halfWidth = mathRound(point.barW / 2);
// create the path
path = [
'M',
crispX - halfWidth, bottomBox,
'L',
crispX - halfWidth, topBox,
'L',
crispX + halfWidth, topBox,
'L',
crispX + halfWidth, bottomBox,
'L',
crispX - halfWidth, bottomBox,
'M',
crispX, bottomBox,
'L',
crispX, mathRound(point.yBottom),
'M',
crispX, topBox,
'L',
crispX, mathRound(point.plotY),
'Z'
];
if (graphic) {
graphic.animate({
d: path
});
} else {
point.graphic = chart.renderer.path(path)
.attr(pointAttr)
.add(series.group);
}
} else if (graphic) {
point.graphic = graphic.destroy();
}
});
}
});
seriesTypes.candlestick = CandlestickSeries;
/*****************************************************************************
* End Candlestick series code *
*****************************************************************************/
/*****************************************************************************
* Start BoxPlot series code *
*****************************************************************************/
// 1 - Set default options
defaultPlotOptions.boxplot = merge(defaultPlotOptions.column, {
animation: false,
borderWidth: 2,
states: {
hover: {
//brightness: 0.1,
borderWidth: 3
}
}
});
// 2- Create the OHLCPoint object
var BoxplotPoint = Highcharts.extendClass(Highcharts.Point, {
/**
* Apply the options containing the x and OHLC data and possible some extra properties.
* This is called on point init or from point.update. Extends base Point by adding
* multiple y-like values.
*
* @param {Object} options
*/
applyOptions: function(options) {
var point = this,
series = point.series,
n,
i = 0;
// object input for example:
// { x: Date(2010, 0, 1), open: 7.88, high: 7.99, low: 7.02, close: 7.65 }
if (typeof options == 'object' && typeof options.length != 'number') {
// copy options directly to point
extend(point, options);
point.options = options;
}
// array
else if (options.length) {
// with leading x value
if (options.length == 6) {
if (typeof options[0] == 'string') {
point.name = options[0];
} else if (typeof options[0] == 'number') {
point.x = options[0];
}
i++;
}
point.lowXtrm = options[i++];
point.Q1 = options[i++];
point.median = options[i++];
point.Q3 = options[i++];
point.uppXtrm = options[i++]
}
/*
* If no x is set by now, get auto incremented value. All points must have an
* x value, however the y value can be null to create a gap in the series
*/
point.low = point.lowXtrm;
point.y = point.uppXtrm;
if (point.x === undefined) {
point.x = series.autoIncrement();
}
},
/**
* A specific OHLC tooltip formatter
*/
tooltipFormatter: function(useHeader) {
var point = this,
series = point.series;
return ['<span style="color:'+ series.color +';font-weight:bold">', (point.name || series.name), '</span><br/> ',
'Upper Extreme: ', point.uppXtrm, '<br/>',
'Q3: ', point.Q3, '<br/>',
'Median: ', point.median, '<br/>',
'Q1: ', point.Q1, '<br/>',
'Lower Extreme: ', point.lowXtrm].join('');
}
});
// 3 - Create the OHLCSeries object
var BoxplotSeries = Highcharts.extendClass(seriesTypes.column, {
type: 'boxplot',
pointClass: BoxplotPoint,
pointAttrToOptions: { // mapping between SVG attributes and the corresponding options
// fill: 'color',
// stroke: 'lineColor',
// 'stroke-width': 'lineWidth'
stroke: 'color',
'stroke-width': 'borderWidth',
fill: 'borderColor',
r: 'borderRadius'
},
/**
* Translate data points from raw values x and y to plotX and plotY
*/
translate: function() {
var chart = this.chart,
series = this,
categories = series.xAxis.categories,
yAxis = series.yAxis,
stack = yAxis.stacks[series.type];
seriesTypes.column.prototype.translate.apply(series);
// do the translation
each(this.data, function(point) {
// the graphics
point.plotQ1 = yAxis.translate(point.Q1, 0, 1);
point.plotQ3 = yAxis.translate(point.Q3, 0, 1);
point.plotMedian = yAxis.translate(point.median, 0, 1);
});
},
/**
* Draw the data points
*/
drawPoints: function() {
var series = this, //state = series.state,
//layer = series.stateLayers[state],
seriesOptions = series.options,
seriesStateAttr = series.stateAttr,
data = series.data,
chart = series.chart,
pointAttr,
pointQ1,
pointQ3,
crispCorr,
halfWidth,
path,
graphic,
crispX;
each(data, function(point) {
graphic = point.graphic;
if (point.plotY !== undefined &&
point.plotX >= 0 && point.plotX <= chart.plotSizeX &&
point.plotY >= 0 && point.plotY <= chart.plotSizeY) {
pointAttr = point.pointAttr[point.selected ? 'selected' : ''];
// crisp vector coordinates
crispCorr = (pointAttr['stroke-width'] % 2) / 2;
crispX = mathRound(point.plotX) + crispCorr;
plotQ1 = mathRound(point.plotQ1) + crispCorr;
plotQ3 = mathRound(point.plotQ3) + crispCorr;
plotMedian = mathRound(point.plotMedian) + crispCorr;
halfWidth = mathRound(point.barW / 2);
quarterWidth = mathRound(point.barW / 4);
path = [
'M',
crispX - halfWidth, plotQ1,
'L',
crispX - halfWidth, plotQ3,
'L',
crispX + halfWidth, plotQ3,
'L',
crispX + halfWidth, plotQ1,
'L',
crispX - halfWidth, plotQ1,
'M',
crispX, plotQ1,
'L',
crispX, mathRound(point.yBottom),
'M',
crispX - quarterWidth, mathRound(point.yBottom),
'L',
crispX + quarterWidth, mathRound(point.yBottom),
'M',
crispX, plotQ3,
'L',
crispX, mathRound(point.plotY),
'M',
crispX - quarterWidth, mathRound(point.plotY),
'L',
crispX + quarterWidth, mathRound(point.plotY),
'M',
crispX - halfWidth, plotMedian,
'L',
crispX + halfWidth, plotMedian,
'Z'
];
if (graphic) {
graphic.animate({
d: path
});
} else {
point.graphic = chart.renderer.path(path)
.attr(pointAttr)
.add(series.group);
}
} else if (graphic) {
point.graphic = graphic.destroy();
}
});
}
});
seriesTypes.boxplot = BoxplotSeries;
})();