Lots of tweaks to historicalStockChart, still more to come

master-patched
Bob Monteverde 12 years ago
parent 3abf806d4f
commit 0de3da0485

@ -114,9 +114,10 @@ function getHistoricalStockData(symbol, startDate, endDate, frequency) {
{
"key": "Volume",
"bar": true,
"values": data.map(function(d) {
"values": data.map(function(d,i) {
return {
'x': Date.parse(d.Date),
'dx': i,
'y': d.Volume / 1000 //TODO: figure out why y domain was maxing out at 9933800
}
})
@ -124,9 +125,10 @@ function getHistoricalStockData(symbol, startDate, endDate, frequency) {
{
"key": "Price",
"bar": false,
"values": data.map(function(d) {
"values": data.map(function(d,i) {
return {
'x': Date.parse(d.Date),
'dx': i,
'y': d.Close,
'open': d.Open,
'close': d.Close,
@ -145,7 +147,7 @@ function getHistoricalStockData(symbol, startDate, endDate, frequency) {
nv.addGraph(function() {
var chart = nv.models.historicalStockChart()
//.margin({top: 30, right: 70, bottom: 50, left: 55})
.x(function(d,i) { return i })
.x(function(d,i) { return d.dx })
.color(d3.scale.category10().range());
// Use if we are removing weekends/holidays
@ -153,6 +155,7 @@ function getHistoricalStockData(symbol, startDate, endDate, frequency) {
//.tickPadding(7)
.tickFormat(function(d) {
return '';
d = parseInt(d);
var dx = lineData[0].values[d] && lineData[0].values[d].x || 0;
return d3.time.format('%x')(new Date(dx))
});
@ -160,6 +163,7 @@ function getHistoricalStockData(symbol, startDate, endDate, frequency) {
chart.xAxis2
.tickPadding(7)
.tickFormat(function(d) {
d = parseInt(d);
var dx = lineData[0].values[d] && lineData[0].values[d].x || 0;
return d3.time.format('%x')(new Date(dx))
});
@ -167,7 +171,7 @@ function getHistoricalStockData(symbol, startDate, endDate, frequency) {
chart.xAxis3
.tickPadding(7)
.tickFormat(function(d) {
var dx = lineData[0].values[d] && lineData[0].values[d].x || 0;
var dx = lineData[0].values[d] && lineData[0].values[parseInt(d)].x || 0;
return d3.time.format('%x')(new Date(dx))
});

@ -21,7 +21,8 @@ nv.models.historicalStockChart = function() {
var stocks = nv.models.ohlcBar(),
bars = nv.models.historicalBar(),
lines = nv.models.line().interactive(false),
x = d3.scale.linear(), // needs to be both line and historicalBar x Axis
//x = d3.scale.linear(), // needs to be both line and historicalBar x Axis
x = stocks.xScale(),
x3 = lines.xScale(),
y1 = bars.yScale(),
y2 = stocks.yScale(),
@ -33,7 +34,8 @@ nv.models.historicalStockChart = function() {
yAxis2 = nv.models.axis().scale(y2).orient('left'),
yAxis3 = nv.models.axis().scale(y3).orient('left'),
legend = nv.models.legend().height(30),
dispatch = d3.dispatch('tooltipShow', 'tooltipHide');
dispatch = d3.dispatch('tooltipShow', 'tooltipHide'),
brush = d3.svg.brush().x(x3);
var showTooltip = function(e, offsetElement) {
var left = e.pos[0] + ( offsetElement.offsetLeft || 0 ),
@ -60,6 +62,9 @@ nv.models.historicalStockChart = function() {
availableHeight3 = height3 - margin3.top - margin3.bottom;
brush.on('brush', onBrush);
var dataBars = data.filter(function(d) { return !d.disabled && d.bar });
var dataStocks = data.filter(function(d) { return !d.disabled && !d.bar });
@ -68,6 +73,9 @@ nv.models.historicalStockChart = function() {
//TODO: try to remove x scale computation from this layer
/*
var series1 = data.filter(function(d) { return !d.disabled && d.bar })
.map(function(d) {
return d.values.map(function(d,i) {
@ -87,7 +95,6 @@ nv.models.historicalStockChart = function() {
/*
x .domain(d3.extent(d3.merge(data.map(function(d) { return d.values })), getX ))
.range([0, availableWidth]);
@ -113,6 +120,7 @@ nv.models.historicalStockChart = function() {
gEnter.append('g').attr('class', 'stocksWrap');
gEnter.append('g').attr('class', 'linesWrap');
gEnter.append('g').attr('class', 'legendWrap');
gEnter.append('g').attr('class', 'x brush');
@ -182,6 +190,16 @@ nv.models.historicalStockChart = function() {
d3.transition(linesWrap).call(lines);
gBrush = g.select('.x.brush')
.attr('transform', 'translate(0,' + (availableHeight + margin.bottom + height2) + ')')
.call(brush);
gBrush.selectAll('rect')
//.attr('y', -5)
.attr('height', availableHeight3);
gBrush.selectAll(".resize").append("path").attr("d", resizePath);
g.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');
@ -282,6 +300,94 @@ nv.models.historicalStockChart = function() {
chart.update = function() { selection.transition().call(chart) };
chart.container = this; // I need a reference to the container in order to have outside code check if the chart is visible or not
// Taken from crossfilter (http://square.github.com/crossfilter/)
function resizePath(d) {
var e = +(d == "e"),
x = e ? 1 : -1,
y = availableHeight3 / 3;
return "M" + (.5 * x) + "," + y
+ "A6,6 0 0 " + e + " " + (6.5 * x) + "," + (y + 6)
+ "V" + (2 * y - 6)
+ "A6,6 0 0 " + e + " " + (.5 * x) + "," + (2 * y)
+ "Z"
+ "M" + (2.5 * x) + "," + (y + 8)
+ "V" + (2 * y - 8)
+ "M" + (4.5 * x) + "," + (y + 8)
+ "V" + (2 * y - 8);
}
function onBrush() {
updateFocus();
//linesWrap.call(lines)
//var focusLinesWrap = g.select('.focus .linesWrap')
//g.select('.x.axis').call(xAxis);
//g.select('.y.axis').call(yAxis1);
}
function updateFocus() {
//nv.log(brush.empty(), brush.extent(), x3(brush.extent()[0]), x3(brush.extent()[1]));
var extent = brush.empty() ? x3.domain() : brush.extent();
var stocksWrap = g.select('.stocksWrap')
.datum(
[{
key: dataStocks[0].key,
values: dataStocks[0].values.filter(function(d,i) {
return getX(d,i) > extent[0] && getX(d,i) < extent[1];
})
}]
);
var barsWrap = g.select('.barsWrap')
.attr('transform', 'translate(0,' + (availableHeight + margin.bottom) + ')')
.datum(
[{
key: dataBars[0].key,
values: dataBars[0].values.filter(function(d,i) {
return getX(d,i) > extent[0] && getX(d,i) < extent[1];
})
}]
);
d3.transition(barsWrap).call(bars);
d3.transition(stocksWrap).call(stocks);
d3.transition(g.select('.x.axis'))
.call(xAxis);
d3.transition(g.select('.x2.axis'))
.call(xAxis2);
d3.transition(g.select('.y1.axis'))
.call(yAxis1);
d3.transition(g.select('.y2.axis'))
.call(yAxis2);
/*
var yDomain = brush.empty() ? y3.domain() : d3.extent(d3.merge(dataStocks.map(function(d) { return d.values })).filter(function(d) {
return lines.x()(d) >= brush.extent()[0] && lines.x()(d) <= brush.extent()[1];
}), lines.y()); //This doesn't account for the 1 point before and the 1 point after the domain. Would fix, but likely need to change entire methodology here
if (typeof yDomain[0] == 'undefined') yDomain = y3.domain(); //incase the brush doesn't cover a single point
x.domain(brush.empty() ? x3.domain() : brush.extent());
y1.domain(yDomain);
*/
//lines.xDomain(x.domain());
//lines.yDomain(y1.domain());
}
});
return chart;

@ -100,11 +100,6 @@ nv.models.ohlcBar = function() {
//.attr('x', 0 )
//.attr('y', function(d,i) { return y(Math.max(0, getY(d,i))) })
//.attr('height', function(d,i) { return Math.abs(y(getY(d,i)) - y(0)) })
.attr('d', function(d,i) {
var w = (availableWidth / data[0].values.length) * .9;
//nv.log(this, getOpen(d,i), getClose(d,i), y(getOpen(d,i)), y(getClose(d,i)));
return 'm0,0l0,' + (y(getOpen(d,i)) - y(getHigh(d,i))) + 'l' + (-w/2) + ',0l' + (w/2) + ',0l0,' + (y(getLow(d,i)) - y(getOpen(d,i))) +'l0,'+ (y(getClose(d,i)) - y(getLow(d,i))) +',l' + (w/2) + ',0l' + (-w/2) + ',0z';
})
.on('mouseover', function(d,i) {
d3.select(this).classed('hover', true);
dispatch.elementMouseover({
@ -155,6 +150,11 @@ nv.models.ohlcBar = function() {
ticks
.attr('class', function(d,i) { return getOpen(d,i) > getClose(d,i) ? 'tick negative' : 'tick positive'})
.attr('transform', function(d,i) { return 'translate(' + x(getX(d,i)) + ',' + y(getHigh(d,i)) + ')'; })
.attr('d', function(d,i) {
var w = (availableWidth / data[0].values.length) * .9;
//nv.log(this, getOpen(d,i), getClose(d,i), y(getOpen(d,i)), y(getClose(d,i)));
return 'm0,0l0,' + (y(getOpen(d,i)) - y(getHigh(d,i))) + 'l' + (-w/2) + ',0l' + (w/2) + ',0l0,' + (y(getLow(d,i)) - y(getOpen(d,i))) +'l0,'+ (y(getClose(d,i)) - y(getLow(d,i))) +',l' + (w/2) + ',0l' + (-w/2) + ',0z';
})
//.attr('width', (availableWidth / data[0].values.length) * .9 )

Loading…
Cancel
Save