Skip to content

Instantly share code, notes, and snippets.

@timmyshen
Forked from timelyportfolio/Readme.md
Created July 7, 2014 16:30
Show Gist options
  • Save timmyshen/52e51252b34bc83c37e9 to your computer and use it in GitHub Desktop.
Save timmyshen/52e51252b34bc83c37e9 to your computer and use it in GitHub Desktop.

Revisions

  1. @timelyportfolio timelyportfolio revised this gist Jun 4, 2014. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion index.html
    Original file line number Diff line number Diff line change
    @@ -14,7 +14,7 @@
    width: 800px;
    height: 400px;
    }
    .tooltips {opacity:1;}
    .tooltip {opacity:1;}
    </style>

    </head>
  2. @timelyportfolio timelyportfolio revised this gist Jun 4, 2014. 1 changed file with 2 additions and 1 deletion.
    3 changes: 2 additions & 1 deletion index.html
    Original file line number Diff line number Diff line change
    @@ -13,7 +13,8 @@
    margin-right: auto;
    width: 800px;
    height: 400px;
    }
    }
    .tooltips {opacity:1;}
    </style>

    </head>
  3. @timelyportfolio timelyportfolio revised this gist Jun 4, 2014. 1 changed file with 9 additions and 0 deletions.
    9 changes: 9 additions & 0 deletions Readme.md
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,9 @@
    ### Source:
    <blockquote>
    <h4><a href = "http://media.pimco.com/Documents/PIMCO_Quantitative_Research_Active_Share_Tracking_Error_Sapra_Hun.pdf">
    Active Share, Tracking Error, and Manager Style
    </a></h4>
    PIMCO Quantitative Research<br>
    Steve Sapra, Ph.D., CFA and Manny Hunjan, CFA<br>
    October 2013
    </blockquote>
  4. @timelyportfolio timelyportfolio created this gist Jun 4, 2014.
    215 changes: 215 additions & 0 deletions index.html
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,215 @@
    <!doctype HTML>
    <meta charset = 'utf-8'>
    <html>
    <head>

    <script src='http://d3js.org/d3.v3.min.js' type='text/javascript'></script>
    <script src='http://dimplejs.org/dist/dimple.v1.1.5.min.js' type='text/javascript'></script>

    <style>
    .rChart {
    display: block;
    margin-left: auto;
    margin-right: auto;
    width: 800px;
    height: 400px;
    }
    </style>

    </head>
    <body >

    <div id = 'chart2ee063ee4f90' class = 'rChart dimple'></div>
    <script type="text/javascript">
    var opts = {
    "dom": "chart2ee063ee4f90",
    "width": 800,
    "height": 400,
    "xAxis": {
    "type": "addMeasureAxis",
    "showPercent": false
    },
    "yAxis": {
    "type": "addMeasureAxis",
    "showPercent": false,
    "outputFormat": ".2f"
    },
    "zAxis": [],
    "colorAxis": [],
    "defaultColors": [],
    "layers": [],
    "legend": [],
    "x": "ActiveShare",
    "y": "TrkError",
    "groups": [ "ActiveShare", "numStocks" ],
    "type": "line",
    "id": "chart2ee063ee4f90"
    },
    data = [{"numStocks":"25","ActiveShare":"0.1","TrkError":0.018},{"numStocks":"50","ActiveShare":"0.1","TrkError":0.017},{"numStocks":"100","ActiveShare":"0.1","TrkError":0.016},{"numStocks":"500","ActiveShare":"0.1","TrkError":0.015},{"numStocks":"25","ActiveShare":"0.2","TrkError":0.026},{"numStocks":"50","ActiveShare":"0.2","TrkError":0.021},{"numStocks":"100","ActiveShare":"0.2","TrkError":0.018},{"numStocks":"500","ActiveShare":"0.2","TrkError":0.016},{"numStocks":"25","ActiveShare":"0.3","TrkError":0.035},{"numStocks":"50","ActiveShare":"0.3","TrkError":0.027},{"numStocks":"100","ActiveShare":"0.3","TrkError":0.021},{"numStocks":"500","ActiveShare":"0.3","TrkError":0.018},{"numStocks":"25","ActiveShare":"0.4","TrkError":0.045},{"numStocks":"50","ActiveShare":"0.4","TrkError":0.034},{"numStocks":"100","ActiveShare":"0.4","TrkError":0.024},{"numStocks":"500","ActiveShare":"0.4","TrkError":0.02},{"numStocks":"25","ActiveShare":"0.5","TrkError":0.055},{"numStocks":"50","ActiveShare":"0.5","TrkError":0.04},{"numStocks":"100","ActiveShare":"0.5","TrkError":0.028},{"numStocks":"500","ActiveShare":"0.5","TrkError":0.023},{"numStocks":"25","ActiveShare":"0.6","TrkError":0.066},{"numStocks":"50","ActiveShare":"0.6","TrkError":0.048},{"numStocks":"100","ActiveShare":"0.6","TrkError":0.032},{"numStocks":"500","ActiveShare":"0.6","TrkError":0.025},{"numStocks":"25","ActiveShare":"0.7","TrkError":0.076},{"numStocks":"50","ActiveShare":"0.7","TrkError":0.055},{"numStocks":"100","ActiveShare":"0.7","TrkError":0.037},{"numStocks":"500","ActiveShare":"0.7","TrkError":0.028},{"numStocks":"25","ActiveShare":"0.8","TrkError":0.086},{"numStocks":"50","ActiveShare":"0.8","TrkError":0.062},{"numStocks":"100","ActiveShare":"0.8","TrkError":0.041},{"numStocks":"500","ActiveShare":"0.8","TrkError":0.031},{"numStocks":"25","ActiveShare":"0.9","TrkError":0.097},{"numStocks":"50","ActiveShare":"0.9","TrkError":0.069},{"numStocks":"100","ActiveShare":"0.9","TrkError":0.045},{"numStocks":"500","ActiveShare":"0.9","TrkError":0.034},{"numStocks":"25","ActiveShare":"1","TrkError":0.107},{"numStocks":"50","ActiveShare":"1","TrkError":0.077},{"numStocks":"100","ActiveShare":"1","TrkError":0.05},{"numStocks":"500","ActiveShare":"1","TrkError":0.037}];
    var svg = dimple.newSvg("#" + opts.id, opts.width, opts.height);

    //data = dimple.filterData(data, "Owner", ["Aperture", "Black Mesa"])
    var myChart = new dimple.chart(svg, data);
    if (opts.bounds) {
    myChart.setBounds(opts.bounds.x, opts.bounds.y, opts.bounds.width, opts.bounds.height);//myChart.setBounds(80, 30, 480, 330);
    }
    //dimple allows use of custom CSS with noFormats
    if(opts.noFormats) { myChart.noFormats = opts.noFormats; };
    //for markimekko and addAxis also have third parameter measure
    //so need to evaluate if measure provided

    //function to build axes
    function buildAxis(position,layer){
    var axis;
    var axisopts = opts[position+"Axis"];

    if(axisopts.measure) {
    axis = myChart[axisopts.type](position,layer[position],axisopts.measure);
    } else {
    axis = myChart[axisopts.type](position, layer[position]);
    };
    if(!(axisopts.type === "addPctAxis")) axis.showPercent = axisopts.showPercent;
    if (axisopts.orderRule) axis.addOrderRule(axisopts.orderRule);
    if (axisopts.grouporderRule) axis.addGroupOrderRule(axisopts.grouporderRule);
    if (axisopts.overrideMin) axis.overrideMin = axisopts.overrideMin;
    if (axisopts.overrideMax) axis.overrideMax = axisopts.overrideMax;
    if (axisopts.overrideMax) axis.overrideMax = axisopts.overrideMax;
    if (axisopts.inputFormat) axis.dateParseFormat = axisopts.inputFormat;
    if (axisopts.outputFormat) axis.tickFormat = axisopts.outputFormat;
    return axis;
    };

    var c = null;
    if(d3.keys(opts.colorAxis).length > 0) {
    c = myChart[opts.colorAxis.type](opts.colorAxis.colorSeries,opts.colorAxis.palette) ;
    if(opts.colorAxis.outputFormat){
    c.tickFormat = opts.colorAxis.outputFormat;
    }
    }

    //allow manipulation of default colors to use with dimple
    if(opts.defaultColors.length) {
    //opts.defaultColors = opts.defaultColors[0];
    if (typeof(opts.defaultColors) == "function") {
    //assume this is a d3 scale
    //for now loop through first 20 but need a better way to handle
    defaultColorsArray = [];
    for (var n=0;n<20;n++) {
    defaultColorsArray.push(opts.defaultColors(n));
    };
    opts.defaultColors = defaultColorsArray;
    }
    opts.defaultColors.forEach(function(d,i) {
    opts.defaultColors[i] = new dimple.color(d);
    })
    myChart.defaultColors = opts.defaultColors;
    }

    //do series
    //set up a function since same for each
    //as of now we have x,y,groups,data,type in opts for primary layer
    //and other layers reside in opts.layers
    function buildSeries(layer, hidden){
    //inherit from primary layer if not intentionally changed or xAxis, yAxis, zAxis null
    if (!layer.xAxis) layer.xAxis = opts.xAxis;
    if (!layer.yAxis) layer.yAxis = opts.yAxis;
    if (!layer.zAxis) layer.zAxis = opts.zAxis;

    var x = buildAxis("x", layer);
    x.hidden = hidden;

    var y = buildAxis("y", layer);
    y.hidden = hidden;

    //z for bubbles
    var z = null;
    if (!(typeof(layer.zAxis) === 'undefined') && layer.zAxis.type){
    z = buildAxis("z", layer);
    };

    //here think I need to evaluate group and if missing do null
    //as the group argument
    //if provided need to use groups from layer
    var s = new dimple.series(myChart, null, x, y, z, c, dimple.plot[layer.type], dimple.aggregateMethod.avg, dimple.plot[layer.type].stacked);

    //as of v1.1.4 dimple can use different dataset for each series
    if(layer.data){
    //convert to an array of objects
    var tempdata;
    //avoid lodash for now
    datakeys = d3.keys(layer.data)
    tempdata = layer.data[datakeys[1]].map(function(d,i){
    var tempobj = {}
    datakeys.forEach(function(key){
    tempobj[key] = layer.data[key][i]
    })
    return tempobj
    })
    s.data = tempdata;
    }

    if(layer.hasOwnProperty("groups")) {
    s.categoryFields = (typeof layer.groups === "object") ? layer.groups : [layer.groups];
    //series offers an aggregate method that we will also need to check if available
    //options available are avg, count, max, min, sum
    }
    if (!(typeof(layer.aggregate) === 'undefined')) {
    s.aggregate = eval(layer.aggregate);
    }
    if (!(typeof(layer.lineWeight) === 'undefined')) {
    s.lineWeight = eval(layer.lineWeight);
    }
    if (!(typeof(layer.barGap) === 'undefined')) {
    s.barGap = eval(layer.barGap);
    }

    /* if (!(typeof(layer.eventHandler) === 'undefined')) {
    layer.eventHandler = (layer.eventHandler.length === "undefined") ? layer.eventHandler : [layer.eventHandler];
    layer.eventHandler.forEach(function(evt){
    s.addEventHandler(evt.event, eval(evt.handler))
    })
    }*/

    myChart.series.push(s);

    /*placeholder fix domain of primary scale for new series data
    //not working right now but something like this
    //for now just use overrideMin and overrideMax from rCharts
    for( var i = 0; i<2; i++) {
    if (!myChart.axes[i].overrideMin) {
    myChart.series[0]._axisBounds(i==0?"x":"y").min = myChart.series[0]._axisBounds(i==0?"x":"y").min < s._axisBounds(i==0?"x":"y").min ? myChart.series[0]._axisBounds(i==0?"x":"y").min : s._axisBounds(i==0?"x":"y").min;
    }
    if (!myChart.axes[i].overrideMax) {
    myChart.series[0]._axisBounds(i==0?"x":"y")._max = myChart.series[0]._axisBounds(i==0?"x":"y").max > s._axisBounds(i==0?"x":"y").max ? myChart.series[0]._axisBounds(i==0?"x":"y").max : s._axisBounds(i==0?"x":"y").max;
    }
    myChart.axes[i]._update();
    }
    */

    return s;
    };

    buildSeries(opts, false);
    if (opts.layers.length > 0) {
    opts.layers.forEach(function(layer){
    buildSeries(layer, true);
    })
    }
    //unsure if this is best but if legend is provided (not empty) then evaluate
    if(d3.keys(opts.legend).length > 0) {
    var l =myChart.addLegend();
    d3.keys(opts.legend).forEach(function(d){
    l[d] = opts.legend[d];
    });
    }
    //quick way to get this going but need to make this cleaner
    if(opts.storyboard) {
    myChart.setStoryboard(opts.storyboard);
    };
    myChart.draw();

    </script>

    <script></script>
    </body>
    </html>