Skip to content

Instantly share code, notes, and snippets.

@kent37
Last active August 29, 2015 14:19
Show Gist options
  • Select an option

  • Save kent37/c67f0fd4d104034acb13 to your computer and use it in GitHub Desktop.

Select an option

Save kent37/c67f0fd4d104034acb13 to your computer and use it in GitHub Desktop.
Expense ratio vs yield
Symbol Name ExpenseRatio Y1 Y3 Y5 Y10
VASGX Vanguard LifeStrategy Growth Fund 0.17 7.8 11.36 10.34 6.63
VSMGX Vanguard LifeStrategy Moderate Growth Fund 0.16 7.47 9.38 9.01 6.31
VMMXX Vanguard Prime Money Market Fund 0.16 0.01 0.02 0.03 1.58
VPMCX Vanguard PRIMECAP Fund Investor Shares 0.44 15.58 21 15.91 10.78
VGSLX Vanguard REIT Index Fund Admiral Shares 0.1 24.09 14.11 15.84 9.87
VTTVX Vanguard Target Retirement 2025 Fund 0.17 7.65 10.35 9.78 6.58
VBTLX Vanguard Total Bond Market Index Fund Admiral Shares 0.08 5.62 3.04 4.35 4.9
VTIAX Vanguard Total International Stock Index Fund Admiral Shares 0.14 -1.05 6.62 NA NA
VTSAX Vanguard Total Stock Market Index Fund Admiral Shares 0.05 12.3 16.39 14.76 8.55
VWENX Vanguard Wellington Fund Admiral Shares 0.18 8.27 11.61 10.72 8.22
BAICX BlackRock Multi-Asset Income Portfolio Investor A Shares 0.99 -1.15 5.85 7.22 NA
CMNIX Calamos Market Neutral Income Fund Institutional Class 0.97 2.28 3.65 4.26 3.85
EIFAX Eaton Vance Floating-Rate Advantage Fund Class I 1.02 2.6 5.11 5.93 NA
SGIIX First Eagle Global Fund Class I 0.83 2.61 8.25 9.28 9
FRIAX Franklin Income Series Class Advisor 0.46 0.9 9.16 9.05 6.91
FMISX Franklin Massachusetts Tax-Free Income Fund Class A 0.66 3.46 2.23 3.57 3.67
NEZYX Loomis Sayles Strategic Income Fund Class Y 0.69 2.05 7.66 8.39 7.92
FLAAX Nuveen All-American Municipal Bond Fund Class A 0.72 4.81 4.03 5.91 4.96
TGBAX Templeton Global Bond Fund Advisor Class 0.66 1.29 4.24 4.74 7.88
LTMIX Thornburg Limited Term Municipal Fund Class I 0.4 2.74 2.2 3.34 3.78
EMGYX Wells Fargo Advantage Emerging Markets Equity Fund Administrator Class 1.49 -3.67 -1.62 1.43 10.09
VWO VANGUARD FTSE EMERGING MARKETS ETF 0.15 3.35 0.6 1.79 8.17
VHT VANGUARD HEALTH CARE ETF 0.12 27.88 27.67 20.75 12.15
VYM VANGUARD HIGH DIVIDEND YIELD ETF 0.1 11.04 15.48 14.89 NA
VOO VANGUARD S&P 500 INDEX ETF NEW 0.05 12.71 16.08 NA NA
VOX VANGUARD TELECOM SERVICES ETF 0.12 4.4 13.69 12.56 8.42
VTI VANGUARD TOTAL STOCK MARKET ETF 0.05 12.34 16.4 14.76 8.57
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Expense Ratio vs Yield</title>
<script type="text/javascript" src="http://d3js.org/d3.v3.js"></script>
<style type="text/css">
body {
background-color: white;
font-family: Helvetica, Arial, sans-serif;
}
h1 {
font-size: 24px;
margin: 0;
}
p {
font-size: 14px;
margin: 10px 0 0 0;
}
button {
background-color: orange;
}
svg {
background-color: white;
}
circle:hover {
fill: orange;
}
.axis path,
.axis line {
fill: none;
stroke: black;
shape-rendering: crispEdges;
}
.axis text {
font-family: sans-serif;
font-size: 11px;
}
</style>
</head>
<body>
<h1>Expense Ratio vs Yield</h1>
<p>Expense Ratio vs Yield for a selection of mutual funds and ETFs.</p>
<p id='legend'>Showing one-year yield.</p>
<script type="text/javascript">
var w = 700;
var h = 600;
var padding = [ 20, 10, 50, 50 ]; //Top, right, bottom, left
var xScale = d3.scale.linear()
.range([ padding[3], w - padding[1] - padding[3] ]);
var yScale = d3.scale.linear()
.range([ padding[0], h - padding[2] ]);
var colorScale = d3.scale.category10();
var xAxis = d3.svg.axis()
.scale(xScale)
.orient("bottom");
var yAxis = d3.svg.axis()
.scale(yScale)
.orient("left");
var svg = d3.select("body")
.append("svg")
.attr("width", w)
.attr("height", h);
d3.csv("ExpenseVsYield.csv", function(data) {
xScale.domain([
d3.min(data, function(d) {
return +d.ExpenseRatio;
}),
d3.max(data, function(d) {
return +d.ExpenseRatio;
})
]);
// The domain of yScale has to be the max of all the yields
yScale.domain([
d3.max(data, function(d) {
return d3.max([+d.Y1, +d.Y3, +d.Y5, +d.Y10]);
}),
d3.min(data, function(d) {
return d3.min([+d.Y1, +d.Y3, +d.Y5, +d.Y10]);
})
]);
colorScale.domain([0, data.length-1]);
// Make a group for each stock
var groups = svg.selectAll("g")
.data(data)
.enter()
.append("g");
// A function to create a translation string for a stock
var translation = function(d, year) {
return "translate(" + xScale(d.ExpenseRatio) + "," + yScale(d[year]) + ")";
}
// A function to format title text
var titleText = function(d, year, text)
{
return d.Name + "'s expense ratio is " + d.ExpenseRatio + ", and " + text + " yield is " + d[year] + "";
}
// Locate the group
groups.attr("transform", function(d) { return translation(d, 'Y1');})
.append("title")
.text(function(d) { return titleText(d, 'Y1', 'one-year'); });
// Add a circle and a text legend for each group
groups.append('circle')
.attr("cx", 0)
.attr("cy", 0)
.attr("r", 5)
.attr("fill", function(d, i) { return colorScale(i%10); });
groups.append('text')
.attr({
x: 8,
y: 4,
class: 'label',
'font-size': '10px',
fill: function(d, i) { return colorScale(i%10); }
})
.text(function (d) {
return d.Symbol;
});
// Add the axes
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + (h - padding[2] + 10) + ")")
.call(xAxis);
svg.append("g")
.attr("class", "y axis")
.attr("transform", "translate(" + (padding[3] - 10) + ",0)")
.call(yAxis);
// Add event handlers for the controls
// This is the function that will be called
yield = function(year, text)
{
// Reset text label positions
svg.selectAll('.label').attr({x: 8, y: 4});
groups.select('title')
.text(function(d) { return titleText(d, year, text); });
groups.transition(1500)
.attr("transform", function(d) { return translation(d, year);})
.attr('visibility', function(d) { return d[year]=='NA' ? 'hidden' : 'visible';})
.each('end', arrangeLabels(year));
d3.select('p#legend')
.transition(750).style('color', 'white')
.transition(750).style('color', 'black')
.text('Showing ' + text + ' yield.');
}
d3.select('button#y1').on('click', function () { yield('Y1', 'one-year'); });
d3.select('button#y3').on('click', function () { yield('Y3', 'three-year'); });
d3.select('button#y5').on('click', function () { yield('Y5', 'five-year'); });
d3.select('button#y10').on('click', function () { yield('Y10', 'ten-year'); });
// Set the initial positions
arrangeLabels('Y1');
});
// Test for intersection of two rectangles
var intersectRect = function(r1, r2) {
return !(r2.left > r1.right ||
r2.right < r1.left ||
r2.top > r1.bottom ||
r2.bottom < r1.top);
};
// Arrange the labels so they don't overlap
// From http://bl.ocks.org/larskotthoff/11406992
// and https://blog.safaribooksonline.com/2014/03/11/solving-d3-label-placement-constraint-relaxing/
function arrangeLabels(year) {
var alpha = 0.5;
// First reset them all
var textLabels = svg.selectAll('.label');
//textLabels.attr({x: 8, y: 4});
var again = false;
textLabels.each(function() {
if (this.__data__[year] == 'NaN') return;
var that = this, thatRect = this.getBoundingClientRect();
textLabels.each(function() {
if (this == that || this.__data__[year]=='NaN') return;
var thisRect = this.getBoundingClientRect();
if (!intersectRect(thisRect, thatRect)) return;
var deltaY = thatRect.top - thisRect.top;
// If the labels collide, we'll push each
// of the two labels up and down a little bit.
again = true;
var sign = deltaY > 0 ? 1 : -1;
var adjust = sign * alpha;
var dthat = d3.select(that);
dthat.attr("y", +dthat.attr('y') + adjust);
var dthis = d3.select(this);
dthis.attr("y", +dthis.attr('y') - adjust);
});
});
if(again) {
setTimeout(function() { arrangeLabels(year); },20);
}
}
</script>
<p>Click the buttons to change the displayed yield.</p>
<button class='click' id='y1'>1-Year</button> <button class='click' id='y3'>3-Year</button>
<button class='click' id='y5'>5-Year</button> <button class='click' id='y10'>10-Year</button>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment