block by timelyportfolio 11232439

US and Global Factors | rCharts + dimple.js Correlation Plot

Full Screen

index.html

<!doctype HTML>
<meta charset = 'utf-8'>
<html>
  <head>
    
    <script src='//d3js.org/d3.v3.min.js' type='text/javascript'></script>
    <script src='//dimplejs.org/dist/dimple.v1.1.5.min.js' type='text/javascript'></script>
    
    <style>
    .rChart {
      display: block;
      margin-left: auto; 
      margin-right: auto;
      width: 500px;
      height: 350px;
    }  
    </style>
    
  </head>
  <body >
    
    
      <div id = "chart227483a7ecb"></div>
      <script>
      function onHover(e){
      //ugly but it works; if tooltip exists then select otherwise append
      //whole d3 enter, update, exit makes things difficult here
      var custTool = (
        d3.select(e.selectedShape[0][0].parentNode).select("#chartTooltip")[0][0] ? 
        d3.select(e.selectedShape[0][0].parentNode).select("#chartTooltip") :
        d3.select(e.selectedShape[0][0].parentNode).append("text").attr("id","chartTooltip")
      )
      
      custTool
      //reads outputFormat and assumes it exists
      .text(d3.format(opts.colorAxis.outputFormat)(e.selectedShape.data()[0].cValue))
      //turn dispay on with css since none from leave
      .style("display",null)
      .style("pointer-events","none")
      .style("font-size",10)
      //use x and y from selected rectangle to position with transform for center
      .attr("x",e.selectedShape.attr("x"))
      .attr("y",e.selectedShape.attr("y"))
      //move to center
      .attr("transform",
      "translate(" + e.selectedShape.attr("width") / 2 + "," + e.selectedShape.attr("height")/2 + ")"
      )
      .attr("dy",4)
      .style("text-anchor","middle")
      }
      function onLeave(e){
        myChart.svg.select("#chartTooltip")
        .style("display","none");
      }
      </script>
          
    <script type="text/javascript">
  var opts = {
 "dom": "chart227483a7ecb",
"width":    500,
"height":    350,
"xAxis": {
 "type": "addCategoryAxis",
"showPercent": false 
},
"yAxis": {
 "type": "addCategoryAxis",
"showPercent": false 
},
"zAxis": {
 "type": "addMeasureAxis",
"outputFormat": "0.5f",
"overrideMin":     -2,
"overrideMax":      2 
},
"colorAxis": {
 "type": "addColorAxis",
"colorSeries": "CorrelationCoefficient",
"palette": [ "red", "white", "blue" ],
"outputFormat": "0.2f" 
},
"defaultColors": [],
"layers": [],
"legend": [],
"x": "Factor1",
"y": "Factor2",
"z": "CorrelationCoefficient",
"type": "bar",
"bounds": {
 "x":    150,
"y":     50,
"width":    330,
"height":    200 
},
"id": "chart227483a7ecb" 
},
    data = [{"Factor1":"MKT","Factor2":"MKT","CorrelationCoefficient":1},{"Factor1":"SMB","Factor2":"MKT","CorrelationCoefficient":0.200456096933883},{"Factor1":"HML","Factor2":"MKT","CorrelationCoefficient":0.0124127313658237},{"Factor1":"UMD","Factor2":"MKT","CorrelationCoefficient":-0.2049459800431},{"Factor1":"QMJ","Factor2":"MKT","CorrelationCoefficient":-0.602494367474873},{"Factor1":"MKT.Glbl","Factor2":"MKT","CorrelationCoefficient":0.867275406854617},{"Factor1":"SMB.Glbl","Factor2":"MKT","CorrelationCoefficient":0.0624277379524938},{"Factor1":"HML.Glbl","Factor2":"MKT","CorrelationCoefficient":0.0243857546642979},{"Factor1":"UMD.Glbl","Factor2":"MKT","CorrelationCoefficient":-0.263265748740087},{"Factor1":"QMJ.Glbl","Factor2":"MKT","CorrelationCoefficient":-0.615086109994511},{"Factor1":"MKT","Factor2":"SMB","CorrelationCoefficient":0.200456096933883},{"Factor1":"SMB","Factor2":"SMB","CorrelationCoefficient":1},{"Factor1":"HML","Factor2":"SMB","CorrelationCoefficient":-0.0429686192988851},{"Factor1":"UMD","Factor2":"SMB","CorrelationCoefficient":-3.14211648466386e-005},{"Factor1":"QMJ","Factor2":"SMB","CorrelationCoefficient":-0.56518920825219},{"Factor1":"MKT.Glbl","Factor2":"SMB","CorrelationCoefficient":0.186587635125907},{"Factor1":"SMB.Glbl","Factor2":"SMB","CorrelationCoefficient":0.802436265714723},{"Factor1":"HML.Glbl","Factor2":"SMB","CorrelationCoefficient":-0.0661692653665177},{"Factor1":"UMD.Glbl","Factor2":"SMB","CorrelationCoefficient":0.0266919082783937},{"Factor1":"QMJ.Glbl","Factor2":"SMB","CorrelationCoefficient":-0.429164008408081},{"Factor1":"MKT","Factor2":"HML","CorrelationCoefficient":0.0124127313658237},{"Factor1":"SMB","Factor2":"HML","CorrelationCoefficient":-0.0429686192988851},{"Factor1":"HML","Factor2":"HML","CorrelationCoefficient":1},{"Factor1":"UMD","Factor2":"HML","CorrelationCoefficient":-0.694306846426837},{"Factor1":"QMJ","Factor2":"HML","CorrelationCoefficient":-0.160678256883582},{"Factor1":"MKT.Glbl","Factor2":"HML","CorrelationCoefficient":0.0389441274778166},{"Factor1":"SMB.Glbl","Factor2":"HML","CorrelationCoefficient":-0.0185832666501022},{"Factor1":"HML.Glbl","Factor2":"HML","CorrelationCoefficient":0.918471462483014},{"Factor1":"UMD.Glbl","Factor2":"HML","CorrelationCoefficient":-0.635581358136359},{"Factor1":"QMJ.Glbl","Factor2":"HML","CorrelationCoefficient":-0.221405724776633},{"Factor1":"MKT","Factor2":"UMD","CorrelationCoefficient":-0.2049459800431},{"Factor1":"SMB","Factor2":"UMD","CorrelationCoefficient":-3.14211648466386e-005},{"Factor1":"HML","Factor2":"UMD","CorrelationCoefficient":-0.694306846426837},{"Factor1":"UMD","Factor2":"UMD","CorrelationCoefficient":1},{"Factor1":"QMJ","Factor2":"UMD","CorrelationCoefficient":0.290249491031037},{"Factor1":"MKT.Glbl","Factor2":"UMD","CorrelationCoefficient":-0.197088828215587},{"Factor1":"SMB.Glbl","Factor2":"UMD","CorrelationCoefficient":0.0140007604747755},{"Factor1":"HML.Glbl","Factor2":"UMD","CorrelationCoefficient":-0.670907039642455},{"Factor1":"UMD.Glbl","Factor2":"UMD","CorrelationCoefficient":0.917350356790049},{"Factor1":"QMJ.Glbl","Factor2":"UMD","CorrelationCoefficient":0.369324327366696},{"Factor1":"MKT","Factor2":"QMJ","CorrelationCoefficient":-0.602494367474873},{"Factor1":"SMB","Factor2":"QMJ","CorrelationCoefficient":-0.56518920825219},{"Factor1":"HML","Factor2":"QMJ","CorrelationCoefficient":-0.160678256883582},{"Factor1":"UMD","Factor2":"QMJ","CorrelationCoefficient":0.290249491031037},{"Factor1":"QMJ","Factor2":"QMJ","CorrelationCoefficient":1},{"Factor1":"MKT.Glbl","Factor2":"QMJ","CorrelationCoefficient":-0.585164755865734},{"Factor1":"SMB.Glbl","Factor2":"QMJ","CorrelationCoefficient":-0.453498558349998},{"Factor1":"HML.Glbl","Factor2":"QMJ","CorrelationCoefficient":-0.101598782591378},{"Factor1":"UMD.Glbl","Factor2":"QMJ","CorrelationCoefficient":0.292579417975988},{"Factor1":"QMJ.Glbl","Factor2":"QMJ","CorrelationCoefficient":0.888421576866123},{"Factor1":"MKT","Factor2":"MKT.Glbl","CorrelationCoefficient":0.867275406854617},{"Factor1":"SMB","Factor2":"MKT.Glbl","CorrelationCoefficient":0.186587635125907},{"Factor1":"HML","Factor2":"MKT.Glbl","CorrelationCoefficient":0.0389441274778166},{"Factor1":"UMD","Factor2":"MKT.Glbl","CorrelationCoefficient":-0.197088828215587},{"Factor1":"QMJ","Factor2":"MKT.Glbl","CorrelationCoefficient":-0.585164755865734},{"Factor1":"MKT.Glbl","Factor2":"MKT.Glbl","CorrelationCoefficient":1},{"Factor1":"SMB.Glbl","Factor2":"MKT.Glbl","CorrelationCoefficient":0.114312313648855},{"Factor1":"HML.Glbl","Factor2":"MKT.Glbl","CorrelationCoefficient":0.0527835662748547},{"Factor1":"UMD.Glbl","Factor2":"MKT.Glbl","CorrelationCoefficient":-0.271771364714555},{"Factor1":"QMJ.Glbl","Factor2":"MKT.Glbl","CorrelationCoefficient":-0.651821647339809},{"Factor1":"MKT","Factor2":"SMB.Glbl","CorrelationCoefficient":0.0624277379524938},{"Factor1":"SMB","Factor2":"SMB.Glbl","CorrelationCoefficient":0.802436265714723},{"Factor1":"HML","Factor2":"SMB.Glbl","CorrelationCoefficient":-0.0185832666501022},{"Factor1":"UMD","Factor2":"SMB.Glbl","CorrelationCoefficient":0.0140007604747755},{"Factor1":"QMJ","Factor2":"SMB.Glbl","CorrelationCoefficient":-0.453498558349998},{"Factor1":"MKT.Glbl","Factor2":"SMB.Glbl","CorrelationCoefficient":0.114312313648855},{"Factor1":"SMB.Glbl","Factor2":"SMB.Glbl","CorrelationCoefficient":1},{"Factor1":"HML.Glbl","Factor2":"SMB.Glbl","CorrelationCoefficient":-0.0303365805179786},{"Factor1":"UMD.Glbl","Factor2":"SMB.Glbl","CorrelationCoefficient":0.00627511143296203},{"Factor1":"QMJ.Glbl","Factor2":"SMB.Glbl","CorrelationCoefficient":-0.394344952151365},{"Factor1":"MKT","Factor2":"HML.Glbl","CorrelationCoefficient":0.0243857546642979},{"Factor1":"SMB","Factor2":"HML.Glbl","CorrelationCoefficient":-0.0661692653665177},{"Factor1":"HML","Factor2":"HML.Glbl","CorrelationCoefficient":0.918471462483014},{"Factor1":"UMD","Factor2":"HML.Glbl","CorrelationCoefficient":-0.670907039642455},{"Factor1":"QMJ","Factor2":"HML.Glbl","CorrelationCoefficient":-0.101598782591378},{"Factor1":"MKT.Glbl","Factor2":"HML.Glbl","CorrelationCoefficient":0.0527835662748547},{"Factor1":"SMB.Glbl","Factor2":"HML.Glbl","CorrelationCoefficient":-0.0303365805179786},{"Factor1":"HML.Glbl","Factor2":"HML.Glbl","CorrelationCoefficient":1},{"Factor1":"UMD.Glbl","Factor2":"HML.Glbl","CorrelationCoefficient":-0.672862473670752},{"Factor1":"QMJ.Glbl","Factor2":"HML.Glbl","CorrelationCoefficient":-0.220321553036851},{"Factor1":"MKT","Factor2":"UMD.Glbl","CorrelationCoefficient":-0.263265748740087},{"Factor1":"SMB","Factor2":"UMD.Glbl","CorrelationCoefficient":0.0266919082783937},{"Factor1":"HML","Factor2":"UMD.Glbl","CorrelationCoefficient":-0.635581358136359},{"Factor1":"UMD","Factor2":"UMD.Glbl","CorrelationCoefficient":0.917350356790049},{"Factor1":"QMJ","Factor2":"UMD.Glbl","CorrelationCoefficient":0.292579417975988},{"Factor1":"MKT.Glbl","Factor2":"UMD.Glbl","CorrelationCoefficient":-0.271771364714555},{"Factor1":"SMB.Glbl","Factor2":"UMD.Glbl","CorrelationCoefficient":0.00627511143296203},{"Factor1":"HML.Glbl","Factor2":"UMD.Glbl","CorrelationCoefficient":-0.672862473670752},{"Factor1":"UMD.Glbl","Factor2":"UMD.Glbl","CorrelationCoefficient":1},{"Factor1":"QMJ.Glbl","Factor2":"UMD.Glbl","CorrelationCoefficient":0.432016490778744},{"Factor1":"MKT","Factor2":"QMJ.Glbl","CorrelationCoefficient":-0.615086109994511},{"Factor1":"SMB","Factor2":"QMJ.Glbl","CorrelationCoefficient":-0.429164008408081},{"Factor1":"HML","Factor2":"QMJ.Glbl","CorrelationCoefficient":-0.221405724776633},{"Factor1":"UMD","Factor2":"QMJ.Glbl","CorrelationCoefficient":0.369324327366696},{"Factor1":"QMJ","Factor2":"QMJ.Glbl","CorrelationCoefficient":0.888421576866123},{"Factor1":"MKT.Glbl","Factor2":"QMJ.Glbl","CorrelationCoefficient":-0.651821647339809},{"Factor1":"SMB.Glbl","Factor2":"QMJ.Glbl","CorrelationCoefficient":-0.394344952151365},{"Factor1":"HML.Glbl","Factor2":"QMJ.Glbl","CorrelationCoefficient":-0.220321553036851},{"Factor1":"UMD.Glbl","Factor2":"QMJ.Glbl","CorrelationCoefficient":0.432016490778744},{"Factor1":"QMJ.Glbl","Factor2":"QMJ.Glbl","CorrelationCoefficient":1}];
  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();
    }
    */
    // Handle the hover event - overriding the default behaviour
    s.addEventHandler("mouseover", onHover);
    // Handle the leave event - overriding the default behaviour
    s.addEventHandler("mouseleave", onLeave);
    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>
      myChart.svg.append("text")
        .attr("id","charttitle")
        .attr("x", 0)
        .attr("y", 18)
        .text("US and Global Factors Correlations")
        .style("text-anchor","beginning")
        .style("font-size","16px")
        .style("font-family","sans-serif")
        myChart.svg.append("text")
        .attr("id","charttitle")
        .attr("x", 0)
        .attr("y", 34)
        .text("source: Asness, Frazzini, Pedersen | Quality Minus Junk (2013)")
        .style("text-anchor","beginning")
        .style("font-size","14px")
        .style("font-family","sans-serif")
    </script>    
  </body>
</html>

code.R

#full factor set for 1956-2012 from Andrea Frazzini Data
#http://www.econ.yale.edu/~af227/data_library.htm

#direct link to Excel File
#http://www.econ.yale.edu/~af227/data/QMJ%20factors%20-%20Asness,%20Frazzini%20and%20Pedersen.xlsx

#ssrn citation to the paper
#Asness, Clifford S. and Frazzini, Andrea and Pedersen, Lasse Heje
#Quality Minus Junk (October 9, 2013)
#Available at SSRN: http://ssrn.com/abstract=2312432 


require(gdata)
require(PerformanceAnalytics)
require(factorAnalytics)
require(quantmod)
require(reshape2)
require(rCharts)

#read spreadsheet
qmjFactors <- read.xls(
  "http://www.econ.yale.edu/~af227/data/QMJ%20factors%20-%20Asness,%20Frazzini%20and%20Pedersen.xlsx"
  ,pattern = "Caldt"
  ,blank.lines.skip = T
  ,stringsAsFactors = F
)

#convert spreadsheet data to R xts
#remove % with gsub, make numeric, and divide by 100
qmjFactors.xts <- as.xts(
  do.call(cbind,
          lapply(
            qmjFactors[,-(c(1,7))]
            ,function(x){
              df<-data.frame(as.numeric(
                gsub(
                  x=x
                  ,pattern="%"
                  ,replacement=""
                )
              )/100)
              colnames(df) <- colnames(x)
              return(df)
            }
          )
  )  #date is first column; will use in order.by
  ,order.by = as.Date(paste0(qmjFactors[,1],"-01"),format="%Y%m%d")
)

colnames(qmjFactors.xts) <- gsub(
  x = colnames(qmjFactors.xts),
  ,pattern = "\\.1"
  ,replacement = "\\.Glbl"
)

cumul <- melt(
  data.frame(
    date = format(index( na.omit( qmjFactors.xts )))
    , cumprod( 1 + na.omit( qmjFactors.xts ) )
  )
  , id.vars = 1
  , value.name = "cumul"
  , variable.name = "factor"
)

d1 <- dPlot(
  cumul ~ date
  , groups = "factor"
  , data = cumul
  , type = "line"
  , height = 400
  , width = 700
  , bounds = list(x = 80, y = 70, width = 600 , height = 250)  
)
d1$xAxis(
  type = "addTimeAxis"
  , inputFormat = "%Y-%m-%d"
  , outputFormat = "%b %Y"
)
d1$setTemplate(
  afterScript = 
'
<script>
//get fewer ticks on x axis
//this is a dimple issue that might or might not get fixed
myChart.svg.select(".axis").selectAll(".tick")[0].forEach(function(d,i){
  if (!(+d3.time.format("%y")(new Date(+d3.select(d).datum())) % 5 == 0)) {
    d.remove()
  } else {
    var dtext = d3.select(d).selectAll("text");
    dtext
      .text(d3.time.format("%Y")(new Date(dtext.text())))
      .attr("transform","none")
      .attr("y",12)
      .style("text-anchor","middle");
  }
});

//remove x axis label
myChart.axes[0].titleShape.remove()

myChart.svg.append("text")
  .attr("id","charttitle")
  .attr("x", 0)
  .attr("y", 18)
  .text("US and Global Factors")
  .style("text-anchor","beginning")
  .style("font-size","16px")
  .style("font-family","sans-serif")
myChart.svg.append("text")
  .attr("id","charttitle")
  .attr("x", 0)
  .attr("y", 34)
  .text("source: Asness, Frazzini, Pedersen | Quality Minus Junk (2013)")
  .style("text-anchor","beginning")
  .style("font-size","14px")
  .style("font-family","sans-serif")

</script>
'
)
d1



#### now use the correlation plot
#### from rCharts issue #381
corrmatrix<-cor(na.omit(qmjFactors.xts)) #store corr matrix
# The following steps are generic and can all be placed in a function with some tweaks to customize output 
corrdata=as.data.frame(corrmatrix)
corrdata$Factor1=names(corrdata)
corrdatamelt=melt(corrdata,id="Factor1")
names(corrdatamelt)=c("Factor1","Factor2","CorrelationCoefficient")
corrmatplot = dPlot(
  Factor2 ~ Factor1
  ,z = "CorrelationCoefficient"
  ,data = corrdatamelt
  ,type = 'bubble'
  ,height = 350
  ,width = 500
  ,bounds = list( x = 150, y = 50, width = 330, height = 200)
)
corrmatplot$yAxis ( type= "addCategoryAxis" )
corrmatplot$zAxis (
  type= "addMeasureAxis"
  , outputFormat = "0.5f"
  , overrideMin = -2
  , overrideMax = 2
)
corrmatplot$colorAxis(
  type = "addColorAxis"
  ,colorSeries = 'CorrelationCoefficient'
  ,palette = c('red','white','blue')
  ,outputFormat = "0.2f"
)
#corrmatplot


#now do the bar
corrmatplot$set(type = "bar")
#corrmatplot


#with the bar let's play with tooltips
#first tooltip will just be the number in the center of the bar
corrmatplot$templates$script = 
  "http://timelyportfolio.github.io/rCharts_dimple/chart_tooltip_flexible.html"

#this template is designed to let us define onHover and onLeave
#with thought afterScript but does not work since separate <script> block
#so use chartDiv instead
corrmatplot$setTemplate(
  chartDiv = 
    '
  <div id = "{{chartId}}"></div>
  <script>
  function onHover(e){
  //ugly but it works; if tooltip exists then select otherwise append
  //whole d3 enter, update, exit makes things difficult here
  var custTool = (
    d3.select(e.selectedShape[0][0].parentNode).select("#chartTooltip")[0][0] ? 
    d3.select(e.selectedShape[0][0].parentNode).select("#chartTooltip") :
    d3.select(e.selectedShape[0][0].parentNode).append("text").attr("id","chartTooltip")
  )
  
  custTool
  //reads outputFormat and assumes it exists
  .text(d3.format(opts.colorAxis.outputFormat)(e.selectedShape.data()[0].cValue))
  //turn dispay on with css since none from leave
  .style("display",null)
  .style("pointer-events","none")
  .style("font-size",10)
  //use x and y from selected rectangle to position with transform for center
  .attr("x",e.selectedShape.attr("x"))
  .attr("y",e.selectedShape.attr("y"))
  //move to center
  .attr("transform",
  "translate(" + e.selectedShape.attr("width") / 2 + "," + e.selectedShape.attr("height")/2 + ")"
  )
  .attr("dy",4)
  .style("text-anchor","middle")
  }
  function onLeave(e){
    myChart.svg.select("#chartTooltip")
    .style("display","none");
  }
  </script>
  '
,
afterScript = '
<script>
  myChart.svg.append("text")
    .attr("id","charttitle")
    .attr("x", 0)
    .attr("y", 18)
    .text("US and Global Factors Correlations")
    .style("text-anchor","beginning")
    .style("font-size","16px")
    .style("font-family","sans-serif")
  myChart.svg.append("text")
    .attr("id","charttitle")
    .attr("x", 0)
    .attr("y", 34)
    .text("source: Asness, Frazzini, Pedersen | Quality Minus Junk (2013)")
    .style("text-anchor","beginning")
    .style("font-size","14px")
    .style("font-family","sans-serif")
</script>'
)
corrmatplot