Last active
November 4, 2020 16:05
-
-
Save JamesTheAwesomeDude/3b2e0ae241cfce193440b5cb256fa066 to your computer and use it in GitHub Desktop.
Histogram: 2020 Electoral College victory-margin odds
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python3 | |
import json,re,math,sys | |
import statistics | |
import matplotlib.pyplot as plt | |
# python3 6653.py < 6653.json | |
#or | |
# curl https://www.predictit.org/api/marketdata/markets/6653 | python3 6653.py | |
data = json.load(sys.stdin) | |
assert data['url'] == 'https://www.predictit.org/markets/detail/6653/What-will-be-the-Electoral-College-margin-in-the-2020-presidential-election' | |
rName = re.compile(r'(GOP|Dems) by (\d+)(?: - (\d+)|\+)') | |
def normalize_cents(s,invert=False): | |
f = float(s) if s is not None else 1 | |
i = round(100 * f) | |
if invert: | |
i = 100 - i | |
return i | |
## MUNGE DATA | |
munged = {} | |
for contract in sorted(data['contracts'],key=lambda c: c['displayOrder'],reverse=True): | |
party, a, b = re.match(rName,contract['name']).groups() | |
if b is None: b = 538 | |
if party == 'GOP': | |
l = int(a) | |
r = int(b)+1 | |
elif party == 'Dems': | |
l = -int(b) | |
r = -int(a)+1 | |
prices = [] | |
prices.append(normalize_cents(contract['lastTradePrice']))#https://www.reddit.com/r/predictit/comments/aaohko/how_do_you_tell_what_side_of_the_contract_that/ecu1xno/ | |
prices.append(normalize_cents(contract['bestBuyYesCost'])) | |
prices.append(normalize_cents(contract['bestBuyNoCost'],True)) | |
prices.append(normalize_cents(contract['bestSellYesCost'])) | |
prices.append(normalize_cents(contract['bestSellNoCost'],True)) | |
munged[(l,r)] = prices | |
## PLOT DATA | |
plotparams = {} | |
#Left-edge | |
plotparams['x'] = [lr[0] for lr in munged] | |
plotparams['align'] = 'edge' | |
#Histogram-style; area ~ probability | |
plotparams['width'] = [lr[1]-lr[0] for lr in munged] | |
# f(datapoints), divided by the width, is proportional to the probability of that total bin | |
# not the best but should be eminently serviceable | |
plotparams['height'] = [statistics.median(munged[lr])/w for lr,w in zip(munged,plotparams['width'])] | |
#Party Colors (GOP is positive values due to being on the right-side of the graph) | |
plotparams['color'] = [('red' if sum(lr)>0 else 'blue') for lr in munged] | |
#plotparams['yerr'] = [statistics.stdev(munged[lr])/w for lr,w in zip(munged,plotparams['width'])] | |
#Graph It | |
plt.figure(dpi=150) | |
plt.bar(**plotparams) | |
plt.xlim((-538,538)) | |
plt.title(f"Predicted Electoral College victory margin\n{data['timeStamp']}") | |
plt.xlabel("Victory margin") | |
plt.ylabel("Percent-chance of victory margin being *exactly* this amount\n(Averaged per-bin)") | |
plt.figtext(0.5,0.01,data['url'],fontsize=6,ha='center',wrap=True) | |
#plt.savefig("test.png") | |
plt.show() | |
print(munged) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment