Last active
April 24, 2023 13:19
-
-
Save abeppu/1074045 to your computer and use it in GitHub Desktop.
candlestick charts using d3
This file contains hidden or 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> | |
<html> | |
<head> | |
<script type="text/javascript" src="http://mbostock.github.com/d3/d3.js?1.25.0"></script> | |
<script type="text/javascript" src="http://mbostock.github.com/d3/d3.time.js?1.25.0"></script> | |
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script> | |
</head> | |
<body> | |
<div id="chart"></div> | |
<script type="text/javascript"> | |
var width = 900; | |
var height = 500; | |
String.prototype.format = function() { | |
var formatted = this; | |
for (var i = 0; i < arguments.length; i++) { | |
var regexp = new RegExp('\\{'+i+'\\}', 'gi'); | |
formatted = formatted.replace(regexp, arguments[i]); | |
} | |
return formatted; | |
}; | |
var dateFormat = d3.time.format("%Y-%m-%d"); | |
var end = new Date(); | |
var start = new Date(end.getTime() - 1000 * 60 * 60 * 24 * 60); | |
var data = []; | |
function min(a, b){ return a < b ? a : b ; } | |
function max(a, b){ return a > b ? a : b; } | |
function buildChart(data){ | |
var margin = 50; | |
var chart = d3.select("#chart") | |
.append("svg:svg") | |
.attr("class", "chart") | |
.attr("width", width) | |
.attr("height", height); | |
var y = d3.scale.linear() | |
.domain([d3.min(data.map(function(x) {return x["Low"];})), d3.max(data.map(function(x){return x["High"];}))]) | |
.range([height-margin, margin]); | |
var x = d3.scale.linear() | |
.domain([d3.min(data.map(function(d){return dateFormat.parse(d.Date).getTime();})), | |
d3.max(data.map(function(d){return dateFormat.parse(d.Date).getTime();}))]) | |
.range([margin,width-margin]); | |
chart.selectAll("line.x") | |
.data(x.ticks(10)) | |
.enter().append("svg:line") | |
.attr("class", "x") | |
.attr("x1", x) | |
.attr("x2", x) | |
.attr("y1", margin) | |
.attr("y2", height - margin) | |
.attr("stroke", "#ccc"); | |
chart.selectAll("line.y") | |
.data(y.ticks(10)) | |
.enter().append("svg:line") | |
.attr("class", "y") | |
.attr("x1", margin) | |
.attr("x2", width - margin) | |
.attr("y1", y) | |
.attr("y2", y) | |
.attr("stroke", "#ccc"); | |
chart.selectAll("text.xrule") | |
.data(x.ticks(10)) | |
.enter().append("svg:text") | |
.attr("class", "xrule") | |
.attr("x", x) | |
.attr("y", height - margin) | |
.attr("dy", 20) | |
.attr("text-anchor", "middle") | |
.text(function(d){ var date = new Date(d * 1000); return (date.getMonth() + 1)+"/"+date.getDate(); }); | |
chart.selectAll("text.yrule") | |
.data(y.ticks(10)) | |
.enter().append("svg:text") | |
.attr("class", "yrule") | |
.attr("x", width - margin) | |
.attr("y", y) | |
.attr("dy", 0) | |
.attr("dx", 20) | |
.attr("text-anchor", "middle") | |
.text(String); | |
chart.selectAll("rect") | |
.data(data) | |
.enter().append("svg:rect") | |
.attr("x", function(d) { return x(dateFormat.parse(d.Date).getTime()); }) | |
.attr("y", function(d) {return y(max(d.Open, d.Close));}) | |
.attr("height", function(d) { return y(min(d.Open, d.Close))-y(max(d.Open, d.Close));}) | |
.attr("width", function(d) { return 0.5 * (width - 2*margin)/data.length; }) | |
.attr("fill",function(d) { return d.Open > d.Close ? "red" : "green" ;}); | |
chart.selectAll("line.stem") | |
.data(data) | |
.enter().append("svg:line") | |
.attr("class", "stem") | |
.attr("x1", function(d) { return x(dateFormat.parse(d.Date).getTime()) + 0.25 * (width - 2 * margin)/ data.length;}) | |
.attr("x2", function(d) { return x(dateFormat.parse(d.Date).getTime()) + 0.25 * (width - 2 * margin)/ data.length;}) | |
.attr("y1", function(d) { return y(d.High);}) | |
.attr("y2", function(d) { return y(d.Low); }) | |
.attr("stroke", function(d){ return d.Open > d.Close ? "red" : "green"; }) | |
} | |
function appendToData(x){ | |
if(data.length > 0){ | |
return; | |
} | |
data = x.query.results.quote; | |
for(var i=0;i<data.length;i++){ | |
data[i].timestamp = (new Date(data[i].date).getTime() / 1000); | |
} | |
data = data.sort(function(x, y){ return dateFormat.parse(x.Date).getTime() - dateFormat.parse(y.Date).getTime(); }); | |
buildChart(data); | |
} | |
function buildQuery(){ | |
var symbol = window.location.hash; | |
if(symbol === ""){ | |
symbol = "AMZN"; | |
} | |
symbol = symbol.replace("#", ""); | |
var base = "select * from yahoo.finance.historicaldata where symbol = \"{0}\" and startDate = \"{1}\" and endDate = \"{2}\""; | |
var getDateString = d3.time.format("%Y-%m-%d"); | |
var query = base.format(symbol, getDateString(start), getDateString(end)); | |
query = encodeURIComponent(query); | |
var url = "http://query.yahooapis.com/v1/public/yql?q={0}&format=json&env=store%3A%2F%2Fdatatables.org%2Falltableswithkeys&callback=appendToData".format(query); | |
return url; | |
} | |
function fetchData(){ | |
url = buildQuery(); | |
scriptElement = document.createElement("SCRIPT"); | |
scriptElement.type = "text/javascript"; | |
// i add to the url the call back function | |
scriptElement.src = url; | |
document.getElementsByTagName("HEAD")[0].appendChild(scriptElement); | |
} | |
$(document).ready(fetchData); | |
</script> | |
</body> | |
</html> | |
really appreciate the example; hope to build on it soon. thanks.
hi abeppu, could you provide the raw query that would work on http://developer.yahoo.com/yql/console/.
I need to see the format of the data Yahoo returns so I can format my data accordingly.
I have tried
and it gives me a 'No definition found for Table yahoo.finance.historicaldata' error
Nice example! For this to work as of today, I had to change this line:
data[i].timestamp = (new Date(data[i].date).getTime() / 1000);
to this
data[i].timestamp = (new Date(data[i]['Date']).getTime() / 1000);
Thank you for the code, how can I make this chart interactive like in this example: http://bl.ocks.org/andredumas/edf630690c10b89be390
Can anyone help please ?
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Hi Mike and Aaron,
Is it possible to remove the weekends from the chart(i.e., continuous candles)?
Thanks,
Tim