Skip to content

Instantly share code, notes, and snippets.

@jfreels
Last active October 31, 2019 06:55
Show Gist options
  • Save jfreels/6904504 to your computer and use it in GitHub Desktop.
Save jfreels/6904504 to your computer and use it in GitHub Desktop.
d3js: Dynamic Scatter plot based on Select input using JSON.

d3js: Dynamic Scatter plot based on Select input using JSON.

Need to figure out how to dynamically change axis labels from percent to number based on select input.

{
"keys" : [
"variable",
"Annualized Return",
"Annualized Standard Deviation",
"Cumulative Return",
"Sharpe Ratio",
"Maximum Drawdown",
"Average Drawdown",
"Pain Ratio",
"Calmar Ratio",
"Current Drought",
"Maximum Drought",
"Omega Ratio",
"Best Month",
"Worst Month",
"Average Positive Month",
"Average Negative Month",
"Percent of Positive Months",
"Percent of Negative Months"
],
"values" : [
{
"variable" : "Convertible Arbitrage",
"Annualized Return" : 0.07702,
"Annualized Standard Deviation" : 0.069446,
"Cumulative Return" : 1.5596,
"Sharpe Ratio" : 1.1091,
"Maximum Drawdown" : -0.29269,
"Average Drawdown" : -0.024537,
"Pain Ratio" : 3.139,
"Calmar Ratio" : 0.26315,
"Current Drought" : 27,
"Maximum Drought" : 84,
"Omega Ratio" : 2.6021,
"Best Month" : 0.0611,
"Worst Month" : -0.1237,
"Average Positive Month" : 0.013639,
"Average Negative Month" : -0.017371,
"Percent of Positive Months" : 0.76316,
"Percent of Negative Months" : 0.23026
},
{
"variable" : "CTA Global",
"Annualized Return" : 0.076711,
"Annualized Standard Deviation" : 0.087056,
"Cumulative Return" : 1.5503,
"Sharpe Ratio" : 0.88117,
"Maximum Drawdown" : -0.11677,
"Average Drawdown" : -0.02375,
"Pain Ratio" : 3.2299,
"Calmar Ratio" : 0.65695,
"Current Drought" : 14,
"Maximum Drought" : 32,
"Omega Ratio" : 1.9368,
"Best Month" : 0.0691,
"Worst Month" : -0.0543,
"Average Positive Month" : 0.024277,
"Average Negative Month" : -0.015715,
"Percent of Positive Months" : 0.55263,
"Percent of Negative Months" : 0.44079
},
{
"variable" : "Distressed Securities",
"Annualized Return" : 0.09751,
"Annualized Standard Deviation" : 0.063559,
"Cumulative Return" : 2.2497,
"Sharpe Ratio" : 1.5342,
"Maximum Drawdown" : -0.22923,
"Average Drawdown" : -0.023339,
"Pain Ratio" : 4.178,
"Calmar Ratio" : 0.42537,
"Current Drought" : 32,
"Maximum Drought" : 42,
"Omega Ratio" : 3.2304,
"Best Month" : 0.0504,
"Worst Month" : -0.0836,
"Average Positive Month" : 0.015359,
"Average Negative Month" : -0.014263,
"Percent of Positive Months" : 0.75,
"Percent of Negative Months" : 0.25
},
{
"variable" : "Emerging Markets",
"Annualized Return" : 0.093612,
"Annualized Standard Deviation" : 0.13362,
"Cumulative Return" : 2.1065,
"Sharpe Ratio" : 0.70061,
"Maximum Drawdown" : -0.35979,
"Average Drawdown" : -0.077723,
"Pain Ratio" : 1.2044,
"Calmar Ratio" : 0.26019,
"Current Drought" : 32,
"Maximum Drought" : 51,
"Omega Ratio" : 1.7654,
"Best Month" : 0.123,
"Worst Month" : -0.1922,
"Average Positive Month" : 0.027532,
"Average Negative Month" : -0.03484,
"Percent of Positive Months" : 0.69079,
"Percent of Negative Months" : 0.30921
},
{
"variable" : "Equity Market Neutral",
"Annualized Return" : 0.073936,
"Annualized Standard Deviation" : 0.031197,
"Cumulative Return" : 1.4683,
"Sharpe Ratio" : 2.37,
"Maximum Drawdown" : -0.11082,
"Average Drawdown" : -0.0079162,
"Pain Ratio" : 9.3398,
"Calmar Ratio" : 0.66715,
"Current Drought" : 28,
"Maximum Drought" : 28,
"Omega Ratio" : 6.2137,
"Best Month" : 0.0253,
"Worst Month" : -0.0587,
"Average Positive Month" : 0.0082379,
"Average Negative Month" : -0.00875,
"Percent of Positive Months" : 0.86842,
"Percent of Negative Months" : 0.13158
},
{
"variable" : "Event Driven",
"Annualized Return" : 0.09319,
"Annualized Standard Deviation" : 0.063568,
"Cumulative Return" : 2.0913,
"Sharpe Ratio" : 1.466,
"Maximum Drawdown" : -0.20082,
"Average Drawdown" : -0.02194,
"Pain Ratio" : 4.2474,
"Calmar Ratio" : 0.46406,
"Current Drought" : 29,
"Maximum Drought" : 36,
"Omega Ratio" : 2.9997,
"Best Month" : 0.0442,
"Worst Month" : -0.0886,
"Average Positive Month" : 0.015246,
"Average Negative Month" : -0.015247,
"Percent of Positive Months" : 0.75,
"Percent of Negative Months" : 0.25
},
{
"variable" : "Fixed Income Arbitrage",
"Annualized Return" : 0.050675,
"Annualized Standard Deviation" : 0.049091,
"Cumulative Return" : 0.8704,
"Sharpe Ratio" : 1.0323,
"Maximum Drawdown" : -0.17879,
"Average Drawdown" : -0.017742,
"Pain Ratio" : 2.8562,
"Calmar Ratio" : 0.28343,
"Current Drought" : 30,
"Maximum Drought" : 50,
"Omega Ratio" : 2.5859,
"Best Month" : 0.0365,
"Worst Month" : -0.0867,
"Average Positive Month" : 0.0084565,
"Average Negative Month" : -0.014482,
"Percent of Positive Months" : 0.81579,
"Percent of Negative Months" : 0.18421
},
{
"variable" : "Global Macro",
"Annualized Return" : 0.094208,
"Annualized Standard Deviation" : 0.058958,
"Cumulative Return" : 2.128,
"Sharpe Ratio" : 1.5979,
"Maximum Drawdown" : -0.079229,
"Average Drawdown" : -0.010367,
"Pain Ratio" : 9.0869,
"Calmar Ratio" : 1.1891,
"Current Drought" : 15,
"Maximum Drought" : 18,
"Omega Ratio" : 3.5166,
"Best Month" : 0.0738,
"Worst Month" : -0.0313,
"Average Positive Month" : 0.015821,
"Average Negative Month" : -0.0094571,
"Percent of Positive Months" : 0.67763,
"Percent of Negative Months" : 0.32237
},
{
"variable" : "Long Short Equity",
"Annualized Return" : 0.094015,
"Annualized Standard Deviation" : 0.076812,
"Cumulative Return" : 2.121,
"Sharpe Ratio" : 1.224,
"Maximum Drawdown" : -0.2182,
"Average Drawdown" : -0.030571,
"Pain Ratio" : 3.0753,
"Calmar Ratio" : 0.43087,
"Current Drought" : 29,
"Maximum Drought" : 38,
"Omega Ratio" : 2.4381,
"Best Month" : 0.0745,
"Worst Month" : -0.0675,
"Average Positive Month" : 0.019415,
"Average Negative Month" : -0.016739,
"Percent of Positive Months" : 0.67763,
"Percent of Negative Months" : 0.32237
},
{
"variable" : "Merger Arbitrage",
"Annualized Return" : 0.083721,
"Annualized Standard Deviation" : 0.038688,
"Cumulative Return" : 1.7688,
"Sharpe Ratio" : 2.164,
"Maximum Drawdown" : -0.056342,
"Average Drawdown" : -0.0069996,
"Pain Ratio" : 11.961,
"Calmar Ratio" : 1.4859,
"Current Drought" : null,
"Maximum Drought" : 22,
"Omega Ratio" : 4.5959,
"Best Month" : 0.0272,
"Worst Month" : -0.0544,
"Average Positive Month" : 0.01063,
"Average Negative Month" : -0.011472,
"Percent of Positive Months" : 0.81579,
"Percent of Negative Months" : 0.16447
},
{
"variable" : "Relative Value",
"Annualized Return" : 0.082317,
"Annualized Standard Deviation" : 0.045708,
"Cumulative Return" : 1.7237,
"Sharpe Ratio" : 1.8009,
"Maximum Drawdown" : -0.15941,
"Average Drawdown" : -0.012373,
"Pain Ratio" : 6.6528,
"Calmar Ratio" : 0.51639,
"Current Drought" : 26,
"Maximum Drought" : 34,
"Omega Ratio" : 3.8154,
"Best Month" : 0.0392,
"Worst Month" : -0.0692,
"Average Positive Month" : 0.011223,
"Average Negative Month" : -0.012476,
"Percent of Positive Months" : 0.80921,
"Percent of Negative Months" : 0.19079
},
{
"variable" : "Short Selling",
"Annualized Return" : 0.032654,
"Annualized Standard Deviation" : 0.19087,
"Cumulative Return" : 0.50232,
"Sharpe Ratio" : 0.17108,
"Maximum Drawdown" : -0.49562,
"Average Drawdown" : -0.21152,
"Pain Ratio" : 0.15438,
"Calmar Ratio" : 0.065886,
"Current Drought" : 132,
"Maximum Drought" : 132,
"Omega Ratio" : 1.2288,
"Best Month" : 0.2463,
"Worst Month" : -0.134,
"Average Positive Month" : 0.044699,
"Average Negative Month" : -0.036376,
"Percent of Positive Months" : 0.5,
"Percent of Negative Months" : 0.5
},
{
"variable" : "Funds of Funds",
"Annualized Return" : 0.07127,
"Annualized Standard Deviation" : 0.063088,
"Cumulative Return" : 1.3918,
"Sharpe Ratio" : 1.1297,
"Maximum Drawdown" : -0.20591,
"Average Drawdown" : -0.023008,
"Pain Ratio" : 3.0976,
"Calmar Ratio" : 0.34612,
"Current Drought" : 40,
"Maximum Drought" : 41,
"Omega Ratio" : 2.4602,
"Best Month" : 0.0666,
"Worst Month" : -0.0618,
"Average Positive Month" : 0.014716,
"Average Negative Month" : -0.012573,
"Percent of Positive Months" : 0.67763,
"Percent of Negative Months" : 0.32237
}
]
}
## require(devtools); install_github('r_jfreels','jfreels')
require(jfreels)
require(PerformanceAnalytics)
data(edhec)
e<-data.table(melt(data.frame(date=index(edhec),coredata(edhec)),id.vars='date'))
e<-dt.dates.filter(e)
e$variable<-gsub('[.]',' ',e$variable)
e_table<-e[,list('Annualized Return'=aror(value),
'Annualized Standard Deviation'=asd(value),
'Cumulative Return'=cror(value),
'Sharpe Ratio'=sharpe(value),
'Maximum Drawdown'=maxdd(value),
'Average Drawdown'=mean(dd(value)),
'Pain Ratio'=pain(value),
'Calmar Ratio'=calmar(value),
'Current Drought'=drought.current(value),
'Maximum Drought'=drought.max(value),
'Omega Ratio'=omega(value),
'Best Month'=max(value),
'Worst Month'=min(value),
'Average Positive Month'=mean(value[value>0]),
'Average Negative Month'=mean(value[value<0]),
'Percent of Positive Months'=percentUp(value),
'Percent of Negative Months'=percentDown(value)
),by=list(variable)]
json(e_table,sink='data.json')
<!DOCTYPE html>
<meta charset='utf-8'>
<html>
<head>
<script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script>
<link rel='stylesheet' href='style.css'>
</head>
<body>
<script type='text/javascript' src='script.js'></script>
</body>
</html>
d3.select('head').append('title').text('Scatterplot')
d3.json('data.json',function (data) {
// CSV section
data.keys.shift() // remove the variable value
var body = d3.select('body')
// Select X-axis Variable
var span = body.append('span')
.text('Select X-Axis variable: ')
var yInput = body.append('select')
.attr('id','xSelect')
.on('change',xChange)
.selectAll('option')
.data(data.keys)
.enter()
.append('option')
.attr('value', function (d) { return d })
.text(function (d) { return d ;})
body.append('br')
// Select Y-axis Variable
var span = body.append('span')
.text('Select Y-Axis variable: ')
var yInput = body.append('select')
.attr('id','ySelect')
.on('change',yChange)
.selectAll('option')
.data(data.keys)
.enter()
.append('option')
.attr('value', function (d) { return d })
.text(function (d) { return d ;})
body.append('br')
// Variables
var body = d3.select('body')
var margin = { top: 50, right: 50, bottom: 50, left: 50 }
var h = 500 - margin.top - margin.bottom
var w = 500 - margin.left - margin.right
var formatPercent = d3.format('.2%')
// Scales
var colorScale = d3.scale.category20()
var xScale = d3.scale.linear()
.domain([
d3.min([0,d3.min(data.values,function (d) { return d['Annualized Return'] })]),
d3.max([0,d3.max(data.values,function (d) { return d['Annualized Return'] })])
])
.range([0,w])
var yScale = d3.scale.linear()
.domain([
d3.min([0,d3.min(data.values,function (d) { return d['Annualized Return'] })]),
d3.max([0,d3.max(data.values,function (d) { return d['Annualized Return'] })])
])
.range([h,0])
// SVG
var svg = body.append('svg')
.attr('height',h + margin.top + margin.bottom)
.attr('width',w + margin.left + margin.right)
.append('g')
.attr('transform','translate(' + margin.left + ',' + margin.top + ')')
// X-axis
var xAxis = d3.svg.axis()
.scale(xScale)
.tickFormat(formatPercent)
.ticks(5)
.orient('bottom')
// Y-axis
var yAxis = d3.svg.axis()
.scale(yScale)
.tickFormat(formatPercent)
.ticks(5)
.orient('left')
// Circles
var circles = svg.selectAll('circle')
.data(data.values)
.enter()
.append('circle')
.attr('cx',function (d) { return xScale(d['Annualized Return']) })
.attr('cy',function (d) { return yScale(d['Annualized Return']) })
.attr('r','10')
.attr('stroke','black')
.attr('stroke-width',1)
.attr('fill',function (d,i) { return colorScale(i) })
.on('mouseover', function () {
d3.select(this)
.transition()
.duration(500)
.attr('r',20)
.attr('stroke-width',3)
})
.on('mouseout', function () {
d3.select(this)
.transition()
.duration(500)
.attr('r',10)
.attr('stroke-width',1)
})
.append('title') // Tooltip
.text(function (d) { return d.variable })
// X-axis
svg.append('g')
.attr('class','axis')
.attr('id','xAxis')
.attr('transform', 'translate(0,' + h + ')')
.call(xAxis)
.append('text') // X-axis Label
.attr('id','xAxisLabel')
.attr('y',-10)
.attr('x',w)
.attr('dy','.71em')
.style('text-anchor','end')
.text('Annualized Return')
// Y-axis
svg.append('g')
.attr('class','axis')
.attr('id','yAxis')
.call(yAxis)
.append('text') // y-axis Label
.attr('id', 'yAxisLabel')
.attr('transform','rotate(-90)')
.attr('x',0)
.attr('y',5)
.attr('dy','.71em')
.style('text-anchor','end')
.text('Annualized Return')
function yChange() {
var value = this.value // get the new y value
yScale // change the yScale
.domain([
d3.min([0,d3.min(data.values,function (d) { return d[value] })]),
d3.max([0,d3.max(data.values,function (d) { return d[value] })])
])
yAxis.scale(yScale) // change the yScale
d3.select('#yAxis') // redraw the yAxis
.transition().duration(1000)
.call(yAxis)
d3.select('#yAxisLabel') // change the yAxisLabel
.text(value)
d3.selectAll('circle') // move the circles
.transition().duration(1000)
.delay(function (d,i) { return i*100})
.attr('cy',function (d) { return yScale(d[value]) })
}
function xChange() {
var value = this.value // get the new x value
xScale // change the xScale
.domain([
d3.min([0,d3.min(data.values,function (d) { return d[value] })]),
d3.max([0,d3.max(data.values,function (d) { return d[value] })])
])
xAxis.scale(xScale) // change the xScale
d3.select('#xAxis') // redraw the xAxis
.transition().duration(1000)
.call(xAxis)
d3.select('#xAxisLabel') // change the xAxisLabel
.transition().duration(1000)
.text(value)
d3.selectAll('circle') // move the circles
.transition().duration(1000)
.delay(function (d,i) { return i*100})
.attr('cx',function (d) { return xScale(d[value]) })
}
})
body {
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
position: relative;
width: 960px;
}
.axis text {
font: 10px sans-serif;
}
.axis path,
.axis line {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
.bar {
fill: steelblue;
fill-opacity: .9;
}
.bar:hover {
fill: orange;
}
label {
position: absolute;
top: 10px;
right: 10px;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment