var ƒ = d3.f var width = 960 var height = 500 console.clear() d3.loadData(['ratings-good.csv'], function(err, res){ data = res[0] byState = d3.nestBy(data, ƒ('state')) .filter(d => d.key.length == 2) byState.forEach(function(d){ d.byDate = d3.nestBy(d, ƒ('date')) d.byDate.forEach(function(d, i){ d.kos = +_.find(d, {slug: 'dailykos'}).dem_prob d.fte = +_.find(d, {slug: 'fte'}).dem_prob d.pdw = +_.find(d, {slug: 'predictwise'}).dem_prob d.nyt = +_.find(d, {slug: 'nyt'}).dem_prob d.pec = +_.find(d, {slug: 'pec'}).dem_prob d.huf = +_.find(d, {slug: 'huffpost'}).dem_prob d.m = d.kos // market d.f = d.nyt // forecast //uncomment to invert // var temp = d.m // d.m = d.f // d.f = temp }) scoreState(d) }) byState = byState.filter(function(d){ return d.byDate.every(d => d.m > .005 && d.m < .995) }) maxChange = d3.max(_.flatten(byState.map(ƒ('byDate'))), d => Math.abs(d.logChange)) var sel = d3.select('body').html('') var stateSel = sel.appendMany(byState, 'div') .st({display: 'inline-block', textAlign: 'center', marginBottom: 20}) stateSel.append('div').text(d => d.key.toUpperCase()) stateSel.each(function(d){ var c = d3.conventions({ totalWidth: 150, totalHeight: 150, margin: {top: 0, left: 20, right: 20, bottom: 15}, parentSel: d3.select(this) }) c.xAxis.ticks(3) c.yAxis.ticks(3) c.x.domain([0, d.byDate.length]) c.drawAxis() var line = d3.line() .x((d, i) => c.x(i)) .y(c.y) .curve(d3.curveStep) var color = d3.scaleOrdinal(['orange', 'grey']); c.svg.appendMany(['f', 'm'], 'path') .at({ d: function(e){ return line(d.byDate.map(ƒ(e))) }, fill: 'none', stroke: color, strokeWidth: 1 }) var y = d3.scaleLinear() .domain([-maxChange, maxChange]) .range([c.height, 0]) line.y(ƒ('logChange', y)) // throw 'up' c.svg.append('path') .at({ d: line(d.byDate), stroke: 'black', fill: 'none', strokeWidth: 2 }) }) function scoreState(state){ var dollars = 1000000 var dContracts = 0 var rContracts = 0 state.byDate.forEach(function(d, i){ // d.initNetworth = d.f*dContracts + (1 - d.f)*rContracts + dollars d.initNetworth = d.m*dContracts + (1 - d.m)*rContracts + dollars d.change = d.initNetworth/1000000 d.logChange = Math.log(d.change) d.dollars = dollars d.dContracts = dContracts d.rContracts = rContracts var p = d.f > d.m ? d.f : 1 - d.f var m = d.f > d.m ? d.m : 1 - d.m var q = 1 - p var b = 1/m - 1 d.k = (b*p - q)/b // if (state.key == 'al') throw 'up' if (d.m < d.f){ // forecaster favors clinton more than market //liquidate r contracts dollars = dollars + rContracts*(1 - d.m) rContracts = 0 //adjust ratio of dollars to contracts d.curRatio = dContracts*d.m/d.initNetworth d.dif = d.k - d.curRatio dContracts = dollars*d.dif/d.m + dContracts dollars = dollars*(1 - d.dif) } else{ // forecaster favors trump more than market // liquidate d contracts dollars = dollars + dContracts*d.m dContracts = 0 //adjust ratio of dollars to contracts d.curRatio = rContracts*(1 - d.m)/d.initNetworth d.dif = d.k - d.curRatio rContracts = dollars*d.dif/(1 - d.m) + rContracts dollars = dollars*(1 - d.dif) } }) state.networth = _.last(state.byDate).initNetworth state.change = state.networth/1000000 state.logChange = Math.log(state.change) } })