Created
June 2, 2014 13:36
-
-
Save k-izzo/62571bf97696ac46fb7f to your computer and use it in GitHub Desktop.
candlesticks
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
date | open | high | low | close | vol | |
---|---|---|---|---|---|---|
May 30, 2014 | 560.80 | 561.35 | 555.91 | 559.89 | 1,766,300 | |
May 29, 2014 | 563.35 | 564 | 558.71 | 560.08 | 1,350,400 | |
May 28, 2014 | 564.57 | 567.84 | 561 | 561.68 | 1,647,500 | |
May 27, 2014 | 556 | 566 | 554.35 | 565.95 | 2,098,400 | |
May 23, 2014 | 547.26 | 553.64 | 543.7 | 552.7 | 1,926,900 | |
May 22, 2014 | 541.13 | 547.6 | 540.78 | 545.06 | 1,611,400 | |
May 21, 2014 | 532.9 | 539.18 | 531.91 | 538.94 | 1,193,000 | |
May 20, 2014 | 529.74 | 536.23 | 526.3 | 529.77 | 1,779,900 | |
May 19, 2014 | 519.7 | 529.78 | 517.58 | 528.86 | 1,274,300 | |
May 16, 2014 | 521.39 | 521.8 | 515.44 | 520.63 | 1,481,200 | |
May 15, 2014 | 525.7 | 525.87 | 517.42 | 519.98 | 1,699,700 | |
May 14, 2014 | 533 | 533 | 525.29 | 526.65 | 1,188,500 | |
May 13, 2014 | 530.89 | 536.07 | 529.51 | 533.09 | 1,646,400 | |
May 12, 2014 | 523.51 | 530.19 | 519.01 | 529.92 | 1,907,300 | |
May 9, 2014 | 510.75 | 519.9 | 504.2 | 518.73 | 2,431,800 | |
May 8, 2014 | 508.46 | 517.23 | 506.45 | 511 | 2,015,800 | |
May 7, 2014 | 515.79 | 516.68 | 503.3 | 509.96 | 3,215,500 | |
May 6, 2014 | 525.23 | 526.81 | 515.06 | 515.14 | 1,684,400 | |
May 5, 2014 | 524.82 | 528.9 | 521.32 | 527.81 | 1,021,300 | |
May 2, 2014 | 533.76 | 534 | 525.61 | 527.93 | 1,683,900 | |
May 1, 2014 | 527.11 | 532.93 | 523.88 | 531.35 | 1,900,300 | |
Apr 30, 2014 | 527.6 | 528 | 522.52 | 526.66 | 1,746,400 | |
Apr 29, 2014 | 516.9 | 529.46 | 516.32 | 527.7 | 2,691,700 | |
Apr 28, 2014 | 517.18 | 518.6 | 502.8 | 517.15 | 3,326,400 | |
Apr 25, 2014 | 522.51 | 524.7 | 515.42 | 516.18 | 2,094,600 | |
Apr 24, 2014 | 530.07 | 531.65 | 522.12 | 525.16 | 1,878,000 | |
Apr 23, 2014 | 533.79 | 533.87 | 526.25 | 526.94 | 2,046,700 | |
Apr 22, 2014 | 528.64 | 537.23 | 527.51 | 534.81 | 2,358,900 | |
Apr 21, 2014 | 536.1 | 536.7 | 525.6 | 528.62 | 2,559,700 | |
Apr 17, 2014 | 548.81 | 549.5 | 531.15 | 536.1 | 6,790,900 | |
Apr 16, 2014 | 543 | 557 | 540 | 556.54 | 4,879,900 | |
Apr 15, 2014 | 536.82 | 538.45 | 518.46 | 536.44 | 3,844,500 | |
Apr 14, 2014 | 538.25 | 544.1 | 529.56 | 532.52 | 2,568,000 | |
Apr 11, 2014 | 532.55 | 540 | 526.53 | 530.6 | 3,914,100 | |
Apr 10, 2014 | 565 | 565 | 539.9 | 540.95 | 4,025,800 | |
Apr 9, 2014 | 559.62 | 565.37 | 552.95 | 564.14 | 3,321,700 | |
Apr 8, 2014 | 542.6 | 555 | 541.61 | 554.9 | 3,142,600 | |
Apr 7, 2014 | 540.74 | 548.48 | 527.15 | 538.15 | 4,389,600 | |
Apr 4, 2014 | 574.65 | 577.77 | 543 | 543.14 | 6,351,900 | |
Apr 3, 2014 | 569.85 | 587.28 | 564.13 | 569.74 | 5,085,200 | |
Apr 2, 2014 | 599.99 | 604.83 | 562.19 | 567 | 146,700 | |
Apr 1, 2014 | 558.71 | 568.45 | 558.71 | 567.16 | 7,900 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<meta charset="utf-8"> | |
<head><link rel='stylesheet' type='text/css' href='style.css'></head> | |
<body style='background-color:lightgray'> | |
<div id='container'></div> | |
<script src='http://d3js.org/d3.v3.min.js'></script> | |
<script> | |
var format_date = function (raw) { | |
var formatted = raw; | |
if (raw.length !== 12) { | |
formatted = formatted.slice(0, 4) + '0' + formatted.slice(4); | |
} | |
return formatted; | |
}; | |
var parse_date = d3.time.format("%b %d, %Y"); | |
var scale = 0.85, | |
chart_w = 950 * scale, | |
chart_h = 600 * scale, | |
top_h = chart_h * 0.65, | |
margin = {left: 140 * scale, top: 140 * scale, right: 50 * scale, bottom: 130 * scale, mid: 80 * scale}; | |
d3.select('#container') | |
.style({ | |
'margin-left': -1 * (chart_w + margin.left + margin.right)/2 + 'px', | |
'margin-top': -1 * (chart_h + margin.top + margin.bottom)/2 + 'px', | |
width: (chart_w + margin.left + margin.right) + 'px', | |
height: (chart_h + margin.top + margin.bottom) + 'px' | |
}); | |
var get_global_range = function (objects) { | |
var global_min = objects[0].open, global_max = objects[0].open, | |
local_min, local_max; | |
var get_local_range = function (object) { | |
var min, max, values = []; | |
Object.keys(object).forEach(function (prop) { | |
if (prop !== 'date' && prop !== 'vol') { values.push(object[prop]); } | |
}); | |
values.sort(function (a, b) { return a - b; }); | |
min = values[0]; | |
max = values[values.length - 1]; | |
return [min, max]; | |
}; | |
objects.slice(1).forEach(function (object) { | |
local_min = get_local_range(object)[0]; | |
if (local_min < global_min) { global_min = local_min; } | |
local_max = get_local_range(object)[1]; | |
if (local_max > global_max) { global_max = local_max; } | |
}); | |
return [global_min, global_max]; | |
}; | |
d3.csv('data.csv', function (data) { | |
data.forEach(function (d) { | |
d.date = parse_date.parse(format_date(d.date)); | |
d.open = +d.open; | |
d.close = +d.close; | |
d.low = +d.low; | |
d.high = +d.high; | |
d.vol = +(d.vol.replace(/,/g,'')) / 1000000; | |
}); | |
data.reverse() | |
var xs = d3.scale.ordinal() | |
.domain(d3.range(data.length)) | |
.rangePoints([0, chart_w], 0.05); | |
var price_range = get_global_range(data), | |
price_min = price_range[0], | |
price_max = price_range[1]; | |
var ys = d3.scale.linear() | |
.domain([price_min, price_max]) | |
.range([top_h, 0]); | |
var vol_max = d3.max(data, function (d) { return d.vol; }); | |
var vol_ys = d3.scale.linear() | |
.domain([0, vol_max]) | |
.range([chart_h, top_h + margin.mid]); | |
var area = d3.svg.area() | |
.x(function (d, i) { return xs(i); }) | |
.y0(chart_h) | |
.y1(function (d) { return vol_ys(d.vol); }) | |
.interpolate('cardinal') | |
.tension(0.85); | |
var line = d3.svg.line() | |
.x(function (d, i) { return xs(i); }) | |
.y(function (d) { return vol_ys(d.vol); }) | |
.interpolate('cardinal') | |
.tension(0.85); | |
var yaxis = d3.svg.axis() | |
.scale(ys) | |
.orient('left') | |
.ticks(5); | |
var vol_yaxis = d3.svg.axis() | |
.scale(vol_ys) | |
.orient('left') | |
.ticks(4); | |
var tvals = []; | |
data.forEach(function (d) { | |
var insert = parse_date(d.date).slice(0, 6); | |
if (insert[0] !== 'x') { | |
tvals.push(insert); | |
} else { | |
tvals.push(insert.slice(1)); | |
} | |
}); | |
var xaxis = d3.svg.axis() | |
.scale(xs) | |
.orient('bottom') | |
.tickFormat(''); | |
var vis = d3.select('#container') | |
.append('svg') | |
.attr({ | |
width: chart_w + margin.left + margin.right, | |
height: chart_h + margin.top + margin.bottom | |
}) | |
.append('g') | |
.attr('transform', 'translate(' + [margin.left, margin.top] + ')'); | |
vis.append('path') | |
.classed('area_fill', true) | |
.attr('d', area(data, function (d) { return d.vol; })); | |
vis.append('path') | |
.classed('area_line', true) | |
.attr('d', line(data, function (d) { return d.vol; })); | |
var sticks = vis.selectAll('.stick') | |
.data(data) | |
.enter() | |
.append('g') | |
.classed('stick', true) | |
.attr('transform', function (d, i) { return 'translate(' + [xs(i), 0] + ')'; }); | |
var tops = sticks.append('line') | |
.classed('wick', true) | |
.attr({ | |
x1: 0, | |
y1: function (d) { return ys(d.high) }, | |
x2: 0, | |
y2: function (d) { return ys(Math.max(d.open, d.close)); } | |
}); | |
var bottoms = sticks.append('line') | |
.classed('wick', true) | |
.attr({ | |
x1: 0, | |
y1: function (d) { return ys(Math.min(d.open, d.close)); }, | |
x2: 0, | |
y2: function (d) { return ys(d.low); } | |
}); | |
var mids = sticks.append('rect') | |
.attr({ | |
class: function (d) { return d.close > d.open ? 'pos' : 'neg'; }, | |
x: -7, | |
y: function (d) { return ys(Math.max(d.open, d.close)); }, | |
width: 14, | |
height: function (d) { return ys(Math.min(d.open, d.close)) - ys(Math.max(d.open, d.close)); } | |
}); | |
var verts = sticks.append('rect') | |
.classed('vert', true) | |
.attr({ | |
x: -7, | |
y: 0, | |
width: 14, | |
height: chart_h | |
}) | |
.style('opacity', 0); | |
sticks.on('mouseenter', function () { | |
d3.select(this).select('rect').style('fill-opacity', 1); | |
var tip_group = d3.select(this) | |
.append('g') | |
.classed('tip_group', true) | |
.attr('transform', function (d) { return 'translate(' + [0, ys(d.high) - 71] + ')'; }) | |
.style('opacity', 0); | |
tip_group.append('text') | |
.text(function (d) { return d.date.toString().slice(4,10); }) | |
.attr({ | |
x: 0, | |
y: -4 | |
}) | |
.style('text-anchor', 'middle') | |
.style('font-size', 14); | |
tip_group.append('rect') | |
.attr({ | |
x: -30, | |
y: 0, | |
width: 60, | |
height: 59 | |
}) | |
tip_group.selectAll('.interior_lab') | |
.data(['open:', 'close:', 'high:', 'low:', 'vol:']) | |
.enter() | |
.append('text') | |
.classed('interior_lab', true) | |
.text(function (d) { return d; }) | |
.attr({ | |
x: 1, | |
y: function (d, i) { return 8 + i*11; } | |
}) | |
.style({ | |
'font-size': '12px', | |
'text-anchor': 'end', | |
'alignment-baseline': 'text-after-edge' | |
}); | |
var pts = ['open', 'close', 'high', 'low', 'vol']; | |
pts.forEach(function (x, j) { | |
tip_group.append('text') | |
.text(function (d) { return x === 'vol' ? Math.round(d[x]*10)/10 : Math.round(d[x]); }) | |
.attr({ | |
x: 5, | |
y: 8 + j * 11 | |
}) | |
.style({ | |
'font-size': 12, | |
'alignment-baseline': 'text-after-edge' | |
}); | |
}) | |
tip_group.append('circle') | |
.attr({ | |
cx: function (d, i) { return xs(i); }, | |
cy: function (d) { return 71 - ys(d.high) + vol_ys(d.vol); }, | |
r: 5 | |
}) | |
tip_group.style('opacity', 1) | |
}) | |
.on('mouseout', function () { | |
d3.select(this).select('rect').style('fill-opacity', 0.45); | |
d3.select('.tip_group').remove() | |
}) | |
vis.append('g') | |
.classed('axis', true) | |
.attr('transform', 'translate(' + [-20, 0] + ')') | |
.call(yaxis); | |
vis.append('g') | |
.classed('axis', true) | |
.attr('transform', 'translate(' + [-20, 0] + ')') | |
.call(vol_yaxis); | |
var xaxis_group = vis.append('g') | |
.classed('axis', true) | |
.attr('transform', 'translate(' + [0, chart_h + 30] + ')') | |
.call(xaxis) | |
var x_lab_group = xaxis_group.append('g') | |
.classed('x_labs', true) | |
.attr('transform', 'translate(' + [0, 18] + ')') | |
var x_labs = x_lab_group.selectAll('.x_lab') | |
.data(tvals) | |
.enter() | |
.append('g') | |
.attr('transform', function (d, i) { return 'translate(' + [5 + xs(i), 0] + ')'; }) | |
x_labs.append('text') | |
.text(function (d) { return d; }) | |
.attr({ | |
transform: 'rotate(-50)', | |
}) | |
.style({ | |
'text-anchor': 'end', | |
'font-size': '14px' | |
}) | |
vis.append('text') | |
.text('GOOG Daily Performace') | |
.classed('large_label', true) | |
.attr({ | |
x: chart_w / 2, | |
y: 0 - margin.top / 2 - 25, | |
'text-anchor': 'middle', | |
'alignment-baseline': 'baseline' | |
}); | |
vis.append('text') | |
.text('Apr 1 - May 30, 2014') | |
.classed('small_label', true) | |
.attr({ | |
x: chart_w / 2, | |
y: 0 - margin.top / 2, | |
'text-anchor': 'middle', | |
'alignment-baseline': 'baseline' | |
}); | |
vis.append('text') | |
.text('Price') | |
.classed('large_label', true) | |
.attr({ | |
x: -20, | |
y: -35, | |
'text-anchor': 'end' | |
}); | |
vis.append('text') | |
.text('($/share)') | |
.classed('small_label', true) | |
.attr({ | |
x: -20, | |
y: -15, | |
'text-anchor': 'end' | |
}); | |
vis.append('text') | |
.text('Volume') | |
.classed('large_label', true) | |
.attr({ | |
x: -20, | |
y: top_h + margin.mid - 35, | |
'text-anchor': 'end' | |
}); | |
vis.append('text') | |
.text('(mill. shares)') | |
.classed('small_label', true) | |
.attr({ | |
x: -20, | |
y: top_h + margin.mid - 15, | |
'text-anchor': 'end' | |
}); | |
var key_group = vis.append('g') | |
.attr('transform', 'translate(' + [chart_w - 250, 0 - margin.top/2 - 25] + ')scale(1)') | |
key_group.append('rect') | |
.attr({ | |
x: 0, | |
y: 0, | |
width: 250, | |
height: 110 | |
}) | |
.style('fill', 'rgb(231, 231, 231)') | |
.style('fill-opacity', 1) | |
var symbol_groups = key_group.selectAll('.symbol') | |
.data(d3.range(2)) | |
.enter() | |
.append('g') | |
.attr({ | |
id: function (d, i) { return 'sg' + i; }, | |
'transform': function (d, i) { return 'translate(' + [250/2 - 60 + i * 120, 0] + ')'} | |
}); | |
symbol_groups.append('line') | |
.classed('wick', true) | |
.attr({ | |
x1: 0, | |
y1: 20, | |
x2: 0, | |
y2: 40 | |
}) | |
symbol_groups.append('rect') | |
.classed('pos', true) | |
.attr({ | |
class: function (d, i) { return d === 0 ? 'pos' : 'neg'; }, | |
x: -7, | |
y: 40, | |
width: 14, | |
height: 30 | |
}) | |
symbol_groups.append('line') | |
.classed('wick', true) | |
.attr({ | |
x1: 0, | |
y1: 70, | |
x2: 0, | |
y2: 90 | |
}) | |
key_group.selectAll('.high_low') | |
.data(['daily high', 'daily low']) | |
.enter() | |
.append('text') | |
.classed('key_label', true) | |
.text(function (d) { return d; }) | |
.attr({ | |
x: 250 / 2, | |
y: function (d, i) { return 20 + i * 70; }, | |
'text-anchor': 'middle' | |
}); | |
d3.select('#sg0').selectAll('.close_open') | |
.data(['close', 'open']) | |
.enter() | |
.append('text') | |
.classed('key_label', true) | |
.text(function (d) { return d; }) | |
.attr({ | |
x: -45, | |
y: function (d, i) { return 40 + i * 30; }, | |
'text-anchor': 'middle' | |
}); | |
d3.select('#sg0').selectAll('.arrow_line') | |
.data(d3.range(2)) | |
.enter() | |
.append('line') | |
.attr({ | |
x1: -27, | |
y1: function (d, i) { return 40 + i * 30; }, | |
x2: -12, | |
y2: function (d, i) { return 40 + i * 30; } | |
}); | |
d3.select('#sg1').selectAll('.arrow_line') | |
.data(d3.range(2)) | |
.enter() | |
.append('line') | |
.attr({ | |
x1: 27, | |
y1: function (d, i) { return 40 + i * 30; }, | |
x2: 12, | |
y2: function (d, i) { return 40 + i * 30; } | |
}); | |
key_group.selectAll('.arrow_line') | |
.data(d3.range(2)) | |
.enter() | |
.append('line') | |
.attr({ | |
x1: 250 / 2 - 60 + 5, | |
y1: function (d, i) { return 20 + i * 70; }, | |
x2: 250 / 2 - 60 + 25, | |
y2: function (d, i) { return 20 + i * 70; } | |
}); | |
key_group.selectAll('.arrow_line') | |
.data(d3.range(2)) | |
.enter() | |
.append('line') | |
.attr({ | |
x1: 250 / 2 + 60 - 25, | |
y1: function (d, i) { return 20 + i * 70; }, | |
x2: 250 / 2 + 60 - 5, | |
y2: function (d, i) { return 20 + i * 70; } | |
}); | |
d3.select('#sg1').selectAll('.close_open') | |
.data(['open', 'close']) | |
.enter() | |
.append('text') | |
.classed('key_label', true) | |
.text(function (d) { return d; }) | |
.attr({ | |
x: 45, | |
y: function (d, i) { return 40 + i * 30; }, | |
'text-anchor': 'middle' | |
}); | |
var triangle = d3.svg.line() | |
.x(function (d) { return d.x; }) | |
.y(function (d) { return d.y; }) | |
.interpolate('cardinal-closed') | |
.tension(1); | |
var points_right = [{x: -5, y: -2}, {x: -5, y: 2}, {x: 0, y: 0}], | |
points_left = [{x: 5, y: -2}, {x: 5, y: 2}, {x: 0, y: 0}], | |
arrow_coords = [ | |
{x: 250 / 2 - 60 + 5, y: 20, dir: 'l'}, | |
{x: 250 / 2 - 60 + 5, y: 90, dir: 'l'}, | |
{x: 250 / 2 + 60 - 5, y: 20, dir: 'r'}, | |
{x: 250 / 2 + 60 - 5, y: 90, dir: 'r'}, | |
{x: 250 / 2 - 60 - 12, y: 40, dir: 'r'}, | |
{x: 250 / 2 - 60 - 12, y: 70, dir: 'r'}, | |
{x: 250 / 2 + 60 + 12, y: 40, dir: 'l'}, | |
{x: 250 / 2 + 60 + 12, y: 70, dir: 'l'} | |
]; | |
var ah_groups = key_group.selectAll('.ah_group') | |
.data(arrow_coords) | |
.enter() | |
.append('g') | |
.attr('transform', function (d) { return 'translate(' + [d.x, d.y] + ')'; }) | |
ah_groups.append('path') | |
.attr('d', function (d) { return d.dir === 'l' ? triangle(points_left) : triangle(points_right); }); | |
}); | |
</script> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#container { | |
position: absolute; | |
top: 50%; | |
left: 50%; | |
} | |
svg { | |
background-color: lightgray; | |
} | |
.wick, .area_line { | |
stroke: gray; | |
stroke-width: 2; | |
fill: none; | |
} | |
line { | |
stroke: gray; | |
stroke-width: 1; | |
fill: none; | |
} | |
path { | |
stroke: gray; | |
stroke-width: 0.8; | |
fill: gray; | |
fill-opacity: .8; | |
} | |
.area_fill { | |
stroke: none; | |
fill: darkgray; | |
} | |
rect { | |
stroke: gray; | |
stroke-width: 2; | |
fill: rgb(231, 231, 231); | |
} | |
circle { | |
stroke: none; | |
stroke-width: 2; | |
fill: #525252; | |
} | |
.pos { | |
fill: steelblue; | |
fill-opacity: 0.45; | |
} | |
.neg { | |
fill: red; | |
fill-opacity: 0.45; | |
} | |
text { | |
stroke: none; | |
fill: #525252; | |
} | |
.large_label { | |
font-size: 22px; | |
} | |
.small_label { | |
font-size: 16px; | |
} | |
.key_label { | |
font-size: 14px; | |
alignment-baseline: text-after-edge; | |
} | |
.axis { | |
font-size: 16px; | |
} | |
.axis path { | |
fill: none; | |
stroke: gray; | |
stroke-width: 2; | |
} | |
.axis .tick line { | |
stroke: gray; | |
stroke-width: 2; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment