Contact
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
| Download

📚 The CoCalc Library - books, templates and other resources

Views: 96161
License: OTHER
1
"""This file contains code for use with "Think Bayes",
2
by Allen B. Downey, available from greenteapress.com
3
4
Copyright 2013 Allen B. Downey
5
License: GNU GPLv3 http://www.gnu.org/licenses/gpl.html
6
"""
7
8
import csv
9
import numpy
10
import thinkbayes
11
import thinkplot
12
13
import matplotlib.pyplot as pyplot
14
15
16
FORMATS = ['png', 'pdf', 'eps']
17
18
19
def ReadData(filename='showcases.2011.csv'):
20
"""Reads a CSV file of data.
21
22
Args:
23
filename: string filename
24
25
Returns: sequence of (price1 price2 bid1 bid2 diff1 diff2) tuples
26
"""
27
fp = open(filename)
28
reader = csv.reader(fp)
29
res = []
30
31
for t in reader:
32
_heading = t[0]
33
data = t[1:]
34
try:
35
data = [int(x) for x in data]
36
# print heading, data[0], len(data)
37
res.append(data)
38
except ValueError:
39
pass
40
41
fp.close()
42
return zip(*res)
43
44
45
class Price(thinkbayes.Suite):
46
"""Represents hypotheses about the price of a showcase."""
47
48
def __init__(self, pmf, player, name=''):
49
"""Constructs the suite.
50
51
pmf: prior distribution of price
52
player: Player object
53
name: string
54
"""
55
thinkbayes.Suite.__init__(self, pmf, name=name)
56
self.player = player
57
58
def Likelihood(self, data, hypo):
59
"""Computes the likelihood of the data under the hypothesis.
60
61
hypo: actual price
62
data: the contestant's guess
63
"""
64
price = hypo
65
guess = data
66
67
error = price - guess
68
like = self.player.ErrorDensity(error)
69
70
return like
71
72
73
class GainCalculator(object):
74
"""Encapsulates computation of expected gain."""
75
76
def __init__(self, player, opponent):
77
"""Constructs the calculator.
78
79
player: Player
80
opponent: Player
81
"""
82
self.player = player
83
self.opponent = opponent
84
85
def ExpectedGains(self, low=0, high=75000, n=101):
86
"""Computes expected gains for a range of bids.
87
88
low: low bid
89
high: high bid
90
n: number of bids to evaluates
91
92
returns: tuple (sequence of bids, sequence of gains)
93
94
"""
95
bids = numpy.linspace(low, high, n)
96
97
gains = [self.ExpectedGain(bid) for bid in bids]
98
99
return bids, gains
100
101
def ExpectedGain(self, bid):
102
"""Computes the expected return of a given bid.
103
104
bid: your bid
105
"""
106
suite = self.player.posterior
107
total = 0
108
for price, prob in sorted(suite.Items()):
109
gain = self.Gain(bid, price)
110
total += prob * gain
111
return total
112
113
def Gain(self, bid, price):
114
"""Computes the return of a bid, given the actual price.
115
116
bid: number
117
price: actual price
118
"""
119
# if you overbid, you get nothing
120
if bid > price:
121
return 0
122
123
# otherwise compute the probability of winning
124
diff = price - bid
125
prob = self.ProbWin(diff)
126
127
# if you are within 250 dollars, you win both showcases
128
if diff <= 250:
129
return 2 * price * prob
130
else:
131
return price * prob
132
133
def ProbWin(self, diff):
134
"""Computes the probability of winning for a given diff.
135
136
diff: how much your bid was off by
137
"""
138
prob = (self.opponent.ProbOverbid() +
139
self.opponent.ProbWorseThan(diff))
140
return prob
141
142
143
class Player(object):
144
"""Represents a player on The Price is Right."""
145
146
n = 101
147
price_xs = numpy.linspace(0, 75000, n)
148
149
def __init__(self, prices, bids, diffs):
150
"""Construct the Player.
151
152
prices: sequence of prices
153
bids: sequence of bids
154
diffs: sequence of underness (negative means over)
155
"""
156
self.pdf_price = thinkbayes.EstimatedPdf(prices)
157
self.cdf_diff = thinkbayes.MakeCdfFromList(diffs)
158
159
mu = 0
160
sigma = numpy.std(diffs)
161
self.pdf_error = thinkbayes.GaussianPdf(mu, sigma)
162
163
def ErrorDensity(self, error):
164
"""Density of the given error in the distribution of error.
165
166
error: how much the bid is under the actual price
167
"""
168
return self.pdf_error.Density(error)
169
170
def PmfPrice(self):
171
"""Returns a new Pmf of prices.
172
173
A discrete version of the estimated Pdf.
174
"""
175
return self.pdf_price.MakePmf(self.price_xs)
176
177
def CdfDiff(self):
178
"""Returns a reference to the Cdf of differences (underness).
179
"""
180
return self.cdf_diff
181
182
def ProbOverbid(self):
183
"""Returns the probability this player overbids.
184
"""
185
return self.cdf_diff.Prob(-1)
186
187
def ProbWorseThan(self, diff):
188
"""Probability this player's diff is greater than the given diff.
189
190
diff: how much the oppenent is off by (always positive)
191
"""
192
return 1 - self.cdf_diff.Prob(diff)
193
194
def MakeBeliefs(self, guess):
195
"""Makes a posterior distribution based on estimated price.
196
197
Sets attributes prior and posterior.
198
199
guess: what the player thinks the showcase is worth
200
"""
201
pmf = self.PmfPrice()
202
self.prior = Price(pmf, self, name='prior')
203
self.posterior = self.prior.Copy(name='posterior')
204
self.posterior.Update(guess)
205
206
def OptimalBid(self, guess, opponent):
207
"""Computes the bid that maximizes expected return.
208
209
guess: what the player thinks the showcase is worth
210
opponent: Player
211
212
Returns: (optimal bid, expected gain)
213
"""
214
self.MakeBeliefs(guess)
215
calc = GainCalculator(self, opponent)
216
bids, gains = calc.ExpectedGains()
217
gain, bid = max(zip(gains, bids))
218
return bid, gain
219
220
def PlotBeliefs(self, root):
221
"""Plots prior and posterior beliefs.
222
223
root: string filename root for saved figure
224
"""
225
thinkplot.Clf()
226
thinkplot.PrePlot(num=2)
227
thinkplot.Pmfs([self.prior, self.posterior])
228
thinkplot.Save(root=root,
229
xlabel='price ($)',
230
ylabel='PMF',
231
formats=FORMATS)
232
233
234
def MakePlots(player1, player2):
235
"""Generates two plots.
236
237
price1 shows the priors for the two players
238
price2 shows the distribution of diff for the two players
239
"""
240
241
# plot the prior distribution of price for both players
242
thinkplot.Clf()
243
thinkplot.PrePlot(num=2)
244
pmf1 = player1.PmfPrice()
245
pmf1.name = 'showcase 1'
246
pmf2 = player2.PmfPrice()
247
pmf2.name = 'showcase 2'
248
thinkplot.Pmfs([pmf1, pmf2])
249
thinkplot.Save(root='price1',
250
xlabel='price ($)',
251
ylabel='PDF',
252
formats=FORMATS)
253
254
# plot the historical distribution of underness for both players
255
thinkplot.Clf()
256
thinkplot.PrePlot(num=2)
257
cdf1 = player1.CdfDiff()
258
cdf1.name = 'player 1'
259
cdf2 = player2.CdfDiff()
260
cdf2.name = 'player 2'
261
262
print 'Player median', cdf1.Percentile(50)
263
print 'Player median', cdf2.Percentile(50)
264
265
print 'Player 1 overbids', player1.ProbOverbid()
266
print 'Player 2 overbids', player2.ProbOverbid()
267
268
thinkplot.Cdfs([cdf1, cdf2])
269
thinkplot.Save(root='price2',
270
xlabel='diff ($)',
271
ylabel='CDF',
272
formats=FORMATS)
273
274
275
def MakePlayers():
276
"""Reads data and makes player objects."""
277
data = ReadData(filename='showcases.2011.csv')
278
data += ReadData(filename='showcases.2012.csv')
279
280
cols = zip(*data)
281
price1, price2, bid1, bid2, diff1, diff2 = cols
282
283
# print list(sorted(price1))
284
# print len(price1)
285
286
player1 = Player(price1, bid1, diff1)
287
player2 = Player(price2, bid2, diff2)
288
289
return player1, player2
290
291
292
def PlotExpectedGains(guess1=20000, guess2=40000):
293
"""Plots expected gains as a function of bid.
294
295
guess1: player1's estimate of the price of showcase 1
296
guess2: player2's estimate of the price of showcase 2
297
"""
298
player1, player2 = MakePlayers()
299
MakePlots(player1, player2)
300
301
player1.MakeBeliefs(guess1)
302
player2.MakeBeliefs(guess2)
303
304
print 'Player 1 prior mle', player1.prior.MaximumLikelihood()
305
print 'Player 2 prior mle', player2.prior.MaximumLikelihood()
306
print 'Player 1 mean', player1.posterior.Mean()
307
print 'Player 2 mean', player2.posterior.Mean()
308
print 'Player 1 mle', player1.posterior.MaximumLikelihood()
309
print 'Player 2 mle', player2.posterior.MaximumLikelihood()
310
311
player1.PlotBeliefs('price3')
312
player2.PlotBeliefs('price4')
313
314
calc1 = GainCalculator(player1, player2)
315
calc2 = GainCalculator(player2, player1)
316
317
thinkplot.Clf()
318
thinkplot.PrePlot(num=2)
319
320
bids, gains = calc1.ExpectedGains()
321
thinkplot.Plot(bids, gains, label='Player 1')
322
print 'Player 1 optimal bid', max(zip(gains, bids))
323
324
bids, gains = calc2.ExpectedGains()
325
thinkplot.Plot(bids, gains, label='Player 2')
326
print 'Player 2 optimal bid', max(zip(gains, bids))
327
328
thinkplot.Save(root='price5',
329
xlabel='bid ($)',
330
ylabel='expected gain ($)',
331
formats=FORMATS)
332
333
334
def PlotOptimalBid():
335
"""Plots optimal bid vs estimated price.
336
"""
337
player1, player2 = MakePlayers()
338
guesses = numpy.linspace(15000, 60000, 21)
339
340
res = []
341
for guess in guesses:
342
player1.MakeBeliefs(guess)
343
344
mean = player1.posterior.Mean()
345
mle = player1.posterior.MaximumLikelihood()
346
347
calc = GainCalculator(player1, player2)
348
bids, gains = calc.ExpectedGains()
349
gain, bid = max(zip(gains, bids))
350
351
res.append((guess, mean, mle, gain, bid))
352
353
guesses, means, _mles, gains, bids = zip(*res)
354
355
thinkplot.PrePlot(num=3)
356
pyplot.plot([15000, 60000], [15000, 60000], color='gray')
357
thinkplot.Plot(guesses, means, label='mean')
358
#thinkplot.Plot(guesses, mles, label='MLE')
359
thinkplot.Plot(guesses, bids, label='bid')
360
thinkplot.Plot(guesses, gains, label='gain')
361
thinkplot.Save(root='price6',
362
xlabel='guessed price ($)',
363
formats=FORMATS)
364
365
366
def TestCode(calc):
367
"""Check some intermediate results.
368
369
calc: GainCalculator
370
"""
371
# test ProbWin
372
for diff in [0, 100, 1000, 10000, 20000]:
373
print diff, calc.ProbWin(diff)
374
print
375
376
# test Return
377
price = 20000
378
for bid in [17000, 18000, 19000, 19500, 19800, 20001]:
379
print bid, calc.Gain(bid, price)
380
print
381
382
383
def main():
384
PlotExpectedGains()
385
PlotOptimalBid()
386
387
388
389
if __name__ == '__main__':
390
main()
391
392