Skip to content

Instantly share code, notes, and snippets.

@d3noob

d3noob/.block

Last active Nov 30, 2019
Embed
What would you like to do?
Dynamic historical stock data with d3.js and YQL
license: mit

This is a chart as used as an example to demonstrate the integration of a YQL query with d3.js and incorperating a degree of control over the query. It is described in the book D3 Tips and Tricks.

You can enter a stock in the form of a ticker symbol (YHOO = Yahoo!, MSFT = Microsoft, KO = Coca-Cola) along with a start and end date (in the format yyyy-mm-dd).

Fair Warning: There is no degree of sanitisation or validation on the inputs. The purpose is to demonstrate the YQL integration with d3.js.

Interesting note: The original version of this example used 'GOOG' as the ticker symbol, but for whatever reason it no longer appears to work.

<!DOCTYPE html>
<meta charset="utf-8">
<style> /* set the CSS */
body { font: 12px Arial;}
path {
stroke: steelblue;
stroke-width: 2;
fill: none;
}
text.shadow {
stroke: white;
stroke-width: 2.5px;
opacity: 0.9;
}
.axis path,
.axis line {
fill: none;
stroke: grey;
stroke-width: 1;
shape-rendering: crispEdges;
}
</style>
<body>
<!-- set inputs for the query -->
<div id="new_input">
&nbsp &nbsp
Stock: <input type="text" name="stock" id="stock" value="YHOO"
style="width: 70px;">
&nbsp &nbsp
Start: <input type="text" name="start" id="start" value="2013-08-10"
style="width: 80px;">
&nbsp &nbsp
End: <input type="text" name="end" id="end" value="2014-03-10"
style="width: 80px;">
&nbsp &nbsp
<input name="updateButton"
type="button"
value="Update"
onclick="updateData()" />
</div>
<!-- load the d3.js library -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.17/d3.min.js"></script>
<script>
// Set the dimensions of the graph
var margin = {top: 30, right: 40, bottom: 30, left: 50},
width = 600 - margin.left - margin.right,
height = 270 - margin.top - margin.bottom;
// Parse the date / time
var parseDate = d3.time.format("%Y-%m-%d").parse;
// Set the ranges
var x = d3.time.scale().range([0, width]);
var y = d3.scale.linear().range([height, 0]);
var xAxis = d3.svg.axis().scale(x)
.orient("bottom").ticks(5);
var yAxis = d3.svg.axis().scale(y)
.orient("left").ticks(5);
var valueline = d3.svg.line()
.x(function(d) { return x(d.date); })
.y(function(d) { return y(d.high); });
var svg = d3.select("body")
.append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate("
+ margin.left
+ "," + margin.top + ")");
var stock = document.getElementById('stock').value;
var start = document.getElementById('start').value;
var end = document.getElementById('end').value;
var inputURL = "http://query.yahooapis.com/v1/public/yql"+
"?q=select%20*%20from%20yahoo.finance.historicaldata%20"+
"where%20symbol%20%3D%20%22"
+stock+"%22%20and%20startDate%20%3D%20%22"
+start+"%22%20and%20endDate%20%3D%20%22"
+end+"%22&format=json&env=store%3A%2F%2F"
+"datatables.org%2Falltableswithkeys";
// Get the data
d3.json(inputURL, function(error, data){
data.query.results.quote.forEach(function(d) {
d.date = parseDate(d.Date);
d.high = +d.High;
d.low = +d.Low;
});
// Scale the range of the data
x.domain(d3.extent(data.query.results.quote, function(d) {
return d.date; }));
y.domain([
d3.min(data.query.results.quote, function(d) { return d.low; }),
d3.max(data.query.results.quote, function(d) { return d.high; })
]);
svg.append("path") // Add the valueline path.
.attr("class", "line")
.attr("d", valueline(data.query.results.quote));
svg.append("g") // Add the X Axis
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
svg.append("g") // Add the Y Axis
.attr("class", "y axis")
.call(yAxis);
svg.append("text") // Add the label
.attr("class", "label")
.attr("transform", "translate(" + (width+3) + ","
+ y(data.query.results.quote[0].high) + ")")
.attr("dy", ".35em")
.attr("text-anchor", "start")
.style("fill", "steelblue")
.text("high");
svg.append("text") // Add the title shadow
.attr("x", (width / 2))
.attr("y", margin.top / 2)
.attr("text-anchor", "middle")
.attr("class", "shadow")
.style("font-size", "16px")
.text(stock);
svg.append("text") // Add the title
.attr("class", "stock")
.attr("x", (width / 2))
.attr("y", margin.top / 2)
.attr("text-anchor", "middle")
.style("font-size", "16px")
.text(stock);
});
// ** Update data section (Called from the onclick)
function updateData() {
var stock = document.getElementById('stock').value;
var start = document.getElementById('start').value;
var end = document.getElementById('end').value;
var inputURL = "http://query.yahooapis.com/v1/public/yql"+
"?q=select%20*%20from%20yahoo.finance.historicaldata%20"+
"where%20symbol%20%3D%20%22"
+stock+"%22%20and%20startDate%20%3D%20%22"
+start+"%22%20and%20endDate%20%3D%20%22"
+end+"%22&format=json&env=store%3A%2F%2F"
+"datatables.org%2Falltableswithkeys";
// Get the data again
d3.json(inputURL, function(error, data){
data.query.results.quote.forEach(function(d) {
d.date = parseDate(d.Date);
d.high = +d.High;
d.low = +d.Low;
});
// Scale the range of the data
x.domain(d3.extent(data.query.results.quote, function(d) {
return d.date; }));
y.domain([
d3.min(data.query.results.quote, function(d) {
return d.low; }),
d3.max(data.query.results.quote, function(d) {
return d.high; })
]);
// Select the section we want to apply our changes to
var svg = d3.select("body").transition();
// Make the changes
svg.select(".line") // change the line
.duration(750)
.attr("d", valueline(data.query.results.quote));
svg.select(".label") // change the label text
.duration(750)
.attr("transform", "translate(" + (width+3) + ","
+ y(data.query.results.quote[0].high) + ")");
svg.select(".shadow") // change the title shadow
.duration(750)
.text(stock);
svg.select(".stock") // change the title
.duration(750)
.text(stock);
svg.select(".x.axis") // change the x axis
.duration(750)
.call(xAxis);
svg.select(".y.axis") // change the y axis
.duration(750)
.call(yAxis);
});
}
</script>
</body>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.