Skip to content

Instantly share code, notes, and snippets.

@JamesTheAwesomeDude
Last active November 4, 2020 16:05
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save JamesTheAwesomeDude/3b2e0ae241cfce193440b5cb256fa066 to your computer and use it in GitHub Desktop.
Save JamesTheAwesomeDude/3b2e0ae241cfce193440b5cb256fa066 to your computer and use it in GitHub Desktop.
Histogram: 2020 Electoral College victory-margin odds
#!/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