|
<!DOCTYPE html> |
|
<meta charset="utf-8"> |
|
|
|
<link href='http://fonts.googleapis.com/css?family=Istok+Web' rel='stylesheet' type='text/css'> |
|
<link href='http://fonts.googleapis.com/css?family=Lora' rel='stylesheet' type='text/css'> |
|
|
|
<link rel="stylesheet" href="//code.jquery.com/ui/1.11.4/themes/smoothness/jquery-ui.css"> |
|
<script src="//code.jquery.com/jquery-1.10.2.js"></script> |
|
<script src="//code.jquery.com/ui/1.11.4/jquery-ui.js"></script> |
|
|
|
<script> |
|
setTimeout(function(){ |
|
$(function() { |
|
$( "#dialog" ).dialog({ |
|
position: { |
|
my: "left top", |
|
at: "left+270 center-220", |
|
of: window, |
|
collision: "none"}}); |
|
});},35500 ); |
|
</script> |
|
|
|
<style> |
|
body { |
|
font-family: 'Lora', Georgia, serif; /* this sets the font axis labels |
|
all other things from the body |
|
are overridden below*/ |
|
font-weight: 400; |
|
font-size: 12px; |
|
} |
|
|
|
.axis path, |
|
.axis line { |
|
fill: none; |
|
stroke: #000; |
|
shape-rendering: crispEdges; |
|
} |
|
|
|
.line { |
|
fill: none; |
|
stroke: steelblue; |
|
stroke-width: 1.5px; |
|
} |
|
|
|
.grid .tick { |
|
stroke: lightgrey; |
|
opacity: 0.7; |
|
} |
|
.grid path { |
|
stroke-width: 0; |
|
} |
|
|
|
p { |
|
padding-top: 0px; |
|
padding-right: 0px; |
|
padding-bottom: 0px; |
|
padding-left: 50px; |
|
} |
|
|
|
p.abstract { |
|
font-family: 'Lora', Georgia, serif; |
|
font-size: 20px; |
|
font-style: italic; /* this sets the font of |
|
the line under the title */ |
|
} |
|
|
|
.blurb { |
|
font-family: 'Lora', Georgia, serif; /* this sets the font of the blurbs */ |
|
font-weight: 400; |
|
font-size: 20px; |
|
} |
|
|
|
h1 { |
|
font-family: 'Istok Web', Verdana, Helvetica, sans-serif; |
|
font-weight: 600; |
|
font-size: 33px; |
|
padding-left: 110px; |
|
} |
|
|
|
.plotlabels { |
|
font-family: 'Istok Web', Verdana, Helvetica, sans-serif; |
|
font-size: 17px; |
|
font-weight:400; |
|
font-style: italic; |
|
cursor: pointer; |
|
} |
|
|
|
</style> |
|
<body> |
|
<h1>precious metals prices since the year 2000</h1> |
|
<p class="abstract">the four commonly traded precious metals, unfortunately not including <a href="http://seekingalpha.com/article/314890-rhodium-not-a-good-precious-metals-investment" target="_blank">rhodium</a></p> |
|
|
|
<div id="dialog" title="instructions" style="display:none;font-size:1.5em;font-family: 'Istok Web', Verdana, Helvetica, sans-serif; "> |
|
<p>Please click on a label to learn more about the metal price time series. |
|
Click the label a second time to see all the metals.</p> |
|
</div> |
|
|
|
<script src="//d3js.org/d3.v3.min.js"></script> |
|
<script> |
|
|
|
function switchThemAllOff() { |
|
d3.select(sil).style("opacity", 0); |
|
d3.select(gol).style("opacity", 0); |
|
d3.select(pla).style("opacity", 0); |
|
d3.select(pal).style("opacity", 0); |
|
sil["active"] = true |
|
gol["active"] = true |
|
pla["active"] = true |
|
pal["active"] = true |
|
active = true |
|
} |
|
|
|
function appendText(content) { d3.select(bt).append("text").html(content).attr("class", "blurb");} |
|
|
|
function removeText() { d3.select(bt).select("text").remove(); } |
|
|
|
function allOn() { |
|
if ( |
|
(gol["active"] === false) && |
|
(pal["active"] === false) && |
|
(sil["active"] === false) && |
|
(pla["active"] === false) |
|
) {return true ;} else {return false ;} } |
|
|
|
// create a boolean which changes from true to false when animation stops |
|
animationRunning = true; |
|
setTimeout(function(){ animationRunning = false;}, 35000); |
|
|
|
document.addEventListener("DOMContentLoaded", function(event) { |
|
var margin = {top: 20, right: 80, bottom: 30, left: 50}, |
|
width = 910 - margin.left - margin.right, |
|
height = 500 - margin.top - margin.bottom; |
|
|
|
var parseDate = d3.time.format("%Y-%m-%d").parse; |
|
|
|
var x = d3.time.scale() |
|
.range([0, width]); |
|
|
|
var y = d3.scale.linear() |
|
.range([height, 0]); |
|
|
|
var color = d3.scale.category10(); |
|
|
|
function make_x_axis() { |
|
return d3.svg.axis() |
|
.scale(x) |
|
.orient("bottom") |
|
.ticks(5) |
|
} |
|
|
|
function make_y_axis() { |
|
return d3.svg.axis() |
|
.scale(y) |
|
.orient("left") |
|
.ticks(9) |
|
} |
|
|
|
var xAxis = d3.svg.axis() |
|
.scale(x) |
|
.orient("bottom") |
|
|
|
var yAxis = d3.svg.axis() |
|
.scale(y) |
|
.orient("left") |
|
|
|
var xAxis2 = d3.svg.axis() |
|
.scale(x) |
|
.ticks(0) |
|
.orient("top"); |
|
|
|
var line = d3.svg.line() |
|
.x(function(d) { return x(d.date); }) |
|
.y(function(d) { return y(d.temperature); }) |
|
.interpolate("basis"); // basis kind of interpolation ; about five different types.. |
|
|
|
var svg = d3.select("body").append("svg") |
|
.attr("width", width + margin.left + margin.right) |
|
.attr("height", height + margin.top + margin.bottom) |
|
.style("overflow", "visible") // so that the series labels don't get chopped off |
|
.append("g") |
|
.attr("transform", "translate(" + margin.left + "," + margin.top + ")"); |
|
|
|
var bottomtext = d3.select("body").append(function() { return document.createElement("p") }) |
|
.style("width", "820px") |
|
.attr("transform", "translate(" + margin.left + "," + margin.top + ")") |
|
.attr("id", "bt"); |
|
|
|
var t = " target=\"_blank\"" ; |
|
|
|
var link1 = "http://articles.economictimes.indiatimes.com/2011-08-28/news/29935853_1_world-gold-council-love-gold-demand-for-gold-bars/"; |
|
var link2 = "http://business.time.com/2013/04/16/whats-behind-the-crash-in-the-gold-market/" |
|
|
|
var text1 = "The only one of the four metals which is yellow, gold is preferred out of these metals as a store of wealth particularly in times of uncertainty. Apart from jewellery it has fewer industrial applications and so its price is less volatile than the others. It is <a href=" + link1 + t +">held</a> in large reserves by major banks, which the other metals are not. It went up 650% between 2001 and the peak in 2011 but there is <a href=" + link2 + t + ">no one solid explanation</a> for the decline since then."; |
|
// _________________________________________________________________________________________________________________________ |
|
|
|
var link3 = "http://www.outsiderclub.com/the-palladium-bull-cometh-platinum-and-palladium-demand-to-soar-in-2015/1409" |
|
var link4 = "http://www.bulliondesk.com/gold-news/focus-palladium-price-worries-car-makers-but-platinum-rhodium-swap-unlikely-jollie-78916/#" |
|
var link5 = "http://tradingblog.esignal.com/2014/07/23/palladium-could-surge-to-all-time-high-this-year-says-poll/" |
|
|
|
var text2 = "Between 1990 and 2001, the global automobile industry <a href=" + link3 + t + ">favoured</a> palladium over platinum as the main catalyst. The carmakers were able to save themselves money by retooling to use platinum instead with palladium price so high in 2001. The price difference has to be quite significant each time before this happens given the effort of changing, and a shift back to palladium is <a href=" + link4 + t + ">not</a> currently expected although it <a href=" + link5 + t +">reached</a> a 13-year high in July 2014."; |
|
// _________________________________________________________________________________________________________________________ |
|
|
|
var link6 = "https://www.caseyresearch.com/crpmkt/crpSolo.php?id=202"; |
|
var link7 = "http://www.outsiderclub.com/an-easy-silver-double/1766"; |
|
var link8 = "https://www.bullionvault.com/gold-news/silver-2011-042320145" ; |
|
var link9 = "http://on.ft.com/224Gq4u" ; |
|
var link10 = "https://www.silverinstitute.org/site/silver-in-technology/silver-in-medicine/bandages/" ; |
|
|
|
var text3 = "Most sources agree that silver is currently <a href=" + link6 + t + ">underpriced</a>. It has always been cheaper than the other precious metals, and the plot above shows the price for ten ounces of it. Still, it is a relatively rare metal, worth a lot more than the same amount of copper, and an examination of the <a href=" + link7 + t +">ratio</a> of the price per ounce of silver to that of gold also supports the argument that it is currently too cheap. Prices <a href=" + link8 + t + ">peaked</a> in April 2011. Solar panels nowadays <a href=" + link9 + t +">drive</a> the price now rather than photograpic film and paper, 20% of the worth of a panel being in its silver. Another interesting application is as an <a href=" + link10 + t +">antibacterial</a>."; |
|
// _________________________________________________________________________________________________________________________ |
|
|
|
var link11 = "https://en.wikipedia.org/wiki/Platinum#Applications" ; |
|
var link12 = "http://ebullionguide.com/platinum-uses.aspx" ; |
|
var link13 = "http://www.bloomberg.com/news/articles/2013-03-22/biggest-crisis-since-2008-looms-for-south-african-mines-energy" ; |
|
|
|
var text4 = "Most of the time since 2000, platinum has been more expensive than gold per ounce. This was even true after its big crash in 2008. Only in more recent times since 2012 has gold been trading at a higher price. Platinum is a lot rarer than gold but its price is affected more by industrial demand than investor demand. The very high prices just before the crash were probably caused by speculative trading inspired by supply uncertainty following <a href=" + link13 + t + ">power outages</a> at the worlds largest platinum mine in South Africa. Catalytic converters are the biggest industrial use but it is also widely used in jewellery, <a href=" + link11 + t + ">industrially</a> in chemical production and petroleum refining and for <a href=" + link12 + t + ">hard drives</a>."; |
|
|
|
function toggleLine(myVar) { |
|
if (myVar["active"] === true) {var active = false;} else {var active = true;} |
|
if (active === true) {newOpacity = 0;} else {newOpacity = 1;}; |
|
d3.select(myVar).style("opacity", newOpacity); |
|
myVar["active"] = active; |
|
} |
|
|
|
d3.csv("weeklyMetals2000.csv", function(error, data) { |
|
// console.log(JSON.stringify(data, null, "\t")); |
|
if (error) throw error; |
|
|
|
color.domain(d3.keys(data[0]).filter(function(key) { return key !== "date"; })); |
|
|
|
data.forEach(function(d) { |
|
d.date = parseDate(d.date); |
|
}); |
|
|
|
// multiply the much cheaper precious metal, silver by a factor. |
|
|
|
var cities = color.domain().map(function(name) { |
|
return { |
|
name: name, |
|
values: data.map(function(d) { |
|
return {date: d.date, temperature: +d[name]}; |
|
}) |
|
}; |
|
}); |
|
|
|
x.domain(d3.extent(data, function(d) { return d.date; })); |
|
|
|
y.domain([ |
|
d3.min(cities, function(c) { return d3.min(c.values, function(v) { return v.temperature; }); }), |
|
d3.max(cities, function(c) { return d3.max(c.values, function(v) { return v.temperature; }); }) |
|
]); |
|
|
|
svg.append("rect") |
|
.attr("width", 780) |
|
.attr("height", "90%") |
|
.attr("fill", "AliceBlue"); |
|
|
|
svg.append("g") |
|
.attr("class", "grid") |
|
.attr("transform", "translate(0," + height + ")") |
|
.call(make_x_axis() |
|
.tickSize(-height, 0, 0) |
|
.tickFormat("") |
|
) |
|
|
|
svg.append("g") |
|
.attr("class", "grid") |
|
.call(make_y_axis() |
|
.tickSize(-width, 0, 0) |
|
.tickFormat("") |
|
) |
|
|
|
svg.append("g") |
|
.attr("class", "x axis") |
|
.attr("transform", "translate(0," + height + ")") |
|
.call(xAxis); |
|
|
|
svg.append("g") |
|
.classed("axis x", true) |
|
.call(xAxis2); |
|
|
|
svg.append("g") |
|
.attr("class", "y axis") |
|
.call(yAxis) |
|
.append("text") |
|
.attr("transform", "rotate(-90)") |
|
.attr("y", 6) |
|
.attr("x", -100) |
|
.attr("dy", ".71em") |
|
.style("text-anchor", "end") |
|
.text("$US price per ounce* (31.103 grams)"); |
|
|
|
svg.append('text') |
|
.attr("class", "y axis") |
|
.call(yAxis) |
|
.attr("transform", "rotate(-90)") |
|
.attr("y", 12) |
|
.attr("x", -450) |
|
.text("(*silver per 10oz/311g)") |
|
|
|
var city = svg.selectAll(".city") |
|
.data(cities) |
|
.enter().append("g") |
|
.attr("class", "city"); |
|
|
|
city.append("path") |
|
.attr("id", function(d) {return (d.name).slice(0,3);}) // for click fn below. |
|
.style("stroke", function(d) {return color(d.name); }) |
|
.transition() |
|
.delay(function(d) {if (d.name === "gold_price") {return 500} |
|
else if (d.name === "platinum_price") {return 9000} |
|
else if (d.name === "palladium_price") {return 18000} |
|
else if (d.name === "silver_price") {return 27000}}) |
|
.attr("class", "line") |
|
.duration(8000) |
|
.attrTween('d', function(d) {if (d.name === "gold_price") {return getInterpolation(d.values);} |
|
else if (d.name === "platinum_price") {return getInterpolation(d.values);} |
|
else if (d.name === "palladium_price") {return getInterpolation(d.values);} |
|
else if (d.name === "silver_price") { |
|
d.values.forEach(function(f) {f.temperature = (10 * f.temperature);}) |
|
return getInterpolation(d.values);}}) |
|
// (pulled out the silver column and multiply the prices by 10) |
|
|
|
city.append("text") |
|
// note - (pal["active"]) is actually TRUE if the line is switched off (!) |
|
.on("click", function(){ |
|
if(d3.select(this).attr('id') === "gotext" && animationRunning===false) { |
|
if (gol["active"]) {switchThemAllOff(); toggleLine(gol); removeText(); appendText(text1);} |
|
else {toggleLine(pal);toggleLine(pla);toggleLine(sil); removeText(); if (!allOn()) {appendText(text1);}} |
|
} |
|
else if (d3.select(this).attr('id') === "patext" && animationRunning===false) { |
|
if (pal["active"]) {switchThemAllOff(); toggleLine(pal); removeText(); appendText(text2);} |
|
else {toggleLine(gol);toggleLine(pla);toggleLine(sil); removeText(); if (!allOn()) {appendText(text2);}} |
|
} |
|
else if (d3.select(this).attr('id') === "sitext" && animationRunning===false) { |
|
if (sil["active"]) {switchThemAllOff(); toggleLine(sil); removeText(); appendText(text3);} |
|
else {toggleLine(gol);toggleLine(pal);toggleLine(pla); removeText(); if (!allOn()){appendText(text3);}} |
|
} |
|
else if (d3.select(this).attr('id') === "pltext" && animationRunning===false) { |
|
if (pla["active"]) {switchThemAllOff(); toggleLine(pla); removeText(); appendText(text4);} |
|
else {toggleLine(gol);toggleLine(pal);toggleLine(sil); removeText(); if (!allOn()){appendText(text4);}} |
|
} |
|
}) |
|
|
|
// transition terminates the selection chaining - StackOverflow Chat |
|
.attr("id", function(d) {return ((d.name).slice(0,2)+"text");}) |
|
.datum(function(d) { return {name: d.name, value: d.values[d.values.length - 1]}; }) |
|
.style("stroke", function(d) {return color(d.name); }) |
|
.attr("class", "plotlabels") |
|
.transition() |
|
.duration(500) |
|
.attr("transform",function(d) |
|
{if (d.name === "gold_price") {return "translate("+x(d.value.date)+","+y(d.value.temperature)+")";} |
|
else if (d.name === "platinum_price") {return "translate("+x(d.value.date)+","+y(d.value.temperature)+")";} |
|
else if (d.name === "palladium_price") {return "translate("+x(d.value.date)+","+y(d.value.temperature)+")";} |
|
else if (d.name === "silver_price") {return "translate("+x(d.value.date)+","+y(10*d.value.temperature)+")";}}) |
|
.attr("x", 3) |
|
.attr("dy", ".35em") |
|
.text(function(d) { return d.name; }) |
|
.delay(function(d) {if (d.name === "gold_price") {return 500} |
|
else if (d.name === "platinum_price") {return 9000} |
|
else if (d.name === "palladium_price") {return 18000} |
|
else if (d.name === "silver_price") {return 27000}}); |
|
|
|
// These are the ids : |
|
// sil |
|
// (index):187 gol |
|
// (index):187 pla |
|
// (index):187 pal |
|
// (index):210 sitext |
|
// (index):210 gotext |
|
// (index):210 pltext |
|
// (index):210 patext |
|
|
|
|
|
function getInterpolation(indexSeries) { |
|
|
|
var interpolate = d3.scale.quantile() |
|
.domain([0,1]) |
|
.range(d3.range(1, indexSeries.length + 1)); |
|
|
|
return function(t) { |
|
var interpolatedLine = indexSeries.slice(0, interpolate(t)); |
|
return line(interpolatedLine); |
|
return interpolatedLine; |
|
} |
|
} |
|
|
|
// initialise all those variables to false in the correct part of the program (scope) |
|
// so that they are not "undefined" at first which upsets the logic. |
|
pla["active"] = false |
|
gol["active"] = false |
|
sil["active"] = false |
|
pal["active"] = false |
|
|
|
}); |
|
|
|
}); |
|
|
|
</script> |
|
</body> |