In [2]:
import matplotlib.pylab as pl
%matplotlib inline

Let's assume that we ask the reviewers to bet on the usefullness of an article. The question is "how many articles will use the methods introduced in this article?" The reviewers is then be asked to give a prediction of how many articles within 1 year, 2 year, 3 year x.. with a standard deviation for each prediction. This would effectively create a real time betting curve for each reviewer. Every hour/day, the market would resolve itself and attribute the earnings to all the winning reviewers.

Reviewers can modify their future predictions, but by doing so they have to sell their position back to the market, which might be at a loss or as a gain.


In [3]:
import numpy as np
import math
from scipy.interpolate import interp1d
from scipy.special import erf
import matplotlib.pylab as pl
%matplotlib inline

In [4]:
# illustration of what a predictive market would look like.
guess = np.array([
    # year, n_articles, std
    [ 0.0,  0.,          0.0001 ],
    [ 1.0,  2.,          3. ],
    [ 2.0,  3.,          4. ],
    [ 3.0,  5.,          5. ],
    [ 4.0,  8.,          6. ],
    [ 5.0,  10.,         6. ],
    [ 10.0, 14.,         6. ],
])

with pl.xkcd():
    pl.plot(guess[:,0], guess[:,1])
    pl.fill_between(guess[:,0], guess[:,1]-guess[:,2], guess[:,1]+guess[:,2], alpha=0.2)
    pl.xlabel('Years')
    pl.ylabel('Number of articles')


Definite integral of a normal distribution


In [5]:
normint = lambda a,b,mu,sigma: 0.5 * (erf((b - mu) / (np.sqrt(2.0)*sigma)) - erf((a - mu) / (np.sqrt(2.0)*sigma)))

In [6]:
Y,N = np.meshgrid(np.linspace(0.5, 10, 10), 
                  np.linspace(0, 50, 30))
dn = abs(N[0,0]-N[1,1])
imu = interp1d(guess[:,0],guess[:,1])
isig = interp1d(guess[:,0],guess[:,2])
P = normint(N.flatten(), N.flatten()+dn, imu(Y.flatten()), isig(Y.flatten()))
P = P.reshape(Y.shape)

Lets plot the difference between the predictions and the reported trend


In [7]:
t = 3.5
x = np.linspace(0,t, 100)
scal = 1.4
with pl.xkcd():
    pl.set_cmap('Blues')
    pl.contourf(Y,N+dn/2.,P, 20)
    cb = pl.colorbar()
    pl.errorbar(guess[:,0], guess[:,1], guess[:,2], marker='s', ls='', c='k', label='PREDICTION')
    pl.plot(x, imu(x)*scal, label='REPORTED')
    pl.plot(t, imu(t)*scal,'ro')
    pl.ylabel('N ARTICLES')
    pl.xlabel('N YEARS')
    cb.set_label('PROBABILITY')
    pl.xlim([0.5, 10])
    pl.ylim([1, 30])   
    pl.legend()
    pl.annotate(
    'CURRENT TIME',
    xy=(t,imu(t)*scal+1), arrowprops=dict(arrowstyle='->'), xytext=(1.5, 18))
    #cb.set_clim([0.0,0.3])



In [8]:
pl.errorbar?

In [ ]:

Simulating a predictive market

A naive approach


In [9]:
import pandas as pd

In [10]:
from datetime import datetime

In [11]:
class PredictiveMarket(object):
    def __init__(self, task):
        for k, v in task.items():
            setattr(self, k, v)
        
        self.positions_wannabe = []
        self.positions_players = []        
        #for o in range(len(self.possible_outcomes)):
        #    self.positions_wannabe.append({
        #            'name':'start',
        #            'outcome':o, 
        #            'amount':0.0, 
        #            'buy':1.0/len(self.possible_outcomes), 
        #            'sell':1.0, 
        #            'date':datetime.now()})
        #    self.positions_players.append({
        #            'name':'start',
        #            'outcome':o, 
        #            'amount':0.0, 
        #            'buy':1.0/len(self.possible_outcomes), 
        #            'sell':1.0, 
        #            'date':datetime.now()})
    
    def register_position(self, name, outcome, amount, buy, sell=0.95):
        """Register the position of a scientific bet
        Parameters:
        -----------
        outcome     (int) The index of the possible outcome
        amount      (float, min=0.0) How much money in EUR the user want to buy
        buy         (float, min=0.0, max=1.0) The maximum ratio at before which the user is ready to buy at
        sell        (float, min=0.0, max=1.0) The maximum ratio at after which the user is ready to sell at
        """
        self.positions_wannabe.append({
                'name':name,
                'outcome':outcome, 
                'amount':amount, 
                'buy':buy, 
                'sell':sell, 
                'date':datetime.now()})
        
    def resolve_positions(self):
        pass
        
    @property
    def wannabe(self):
        return pd.DataFrame(self.positions_wannabe)

    @property
    def players(self):
        return pd.DataFrame(self.positions_players)
    
    @property
    def market_value(self):
        if len(self.positions_players) == 0:
            return 0.0
        else:
            return self.players.amount.sum()
    
    def close_market(self):
        pass

Creating a scientific task

Mark is reviewing an article. In this context he is doubting that a result can be reproduced. He therefore creates a scientific task around it.


In [12]:
result1_task1 = {
    'description': 'Attempt to reproduce the result 1 of this article',
    'doi': '10.1051/itmconf/20140201004',
    'reference': 'result 1, p. 4',
    'type': 'scientific task',
    'possible_outcomes': [
        'the result is reproducible',
        'the result is not reproducible'
        ]
}
pm_result1 = PredictiveMarket(result1_task1)

Mark then proceed to bet on the predicitve market that he has just created


In [13]:
pm_result1.register_position('Mark', 1, 50., 0.6, 0.95)
#pm_result1.register_position('Albert', 1, 10., 0.7, 0.95)
pm_result1.wannabe


Out[13]:
amount buy date name outcome sell
0 50 0.6 2015-09-30 20:44:25.493591 Mark 1 0.95

Erik notices that there is a new predictive market that is of interest for him


In [14]:
print('Emergence: There is a new scientific task associated to DOI:%s: "%s"'%(pm_result1.doi, pm_result1.description))
print('Erik: hmmm interesting! I bet it is not goint to be reproducible')


Emergence: There is a new scientific task associated to DOI:10.1051/itmconf/20140201004: "Attempt to reproduce the result 1 of this article"
Erik: hmmm interesting! I bet it is not goint to be reproducible

Erik then proceeds to bet:


In [15]:
pm_result1.register_position('Erik', 0, 10., 0.7, 0.95)
pm_result1.register_position('Soeren', 0, 20., 0.6, 0.95)
pm_result1.wannabe


Out[15]:
amount buy date name outcome sell
0 50 0.6 2015-09-30 20:44:25.493591 Mark 1 0.95
1 10 0.7 2015-09-30 20:44:25.525052 Erik 0 0.95
2 20 0.6 2015-09-30 20:44:25.525104 Soeren 0 0.95

The market booky is going to create the bet odds from there on. He will use the lowest probability as a starting point. Mark is ready to pay 50EUR at a probability of winning of 0.6. That means that if he wins, the booky would need to pay him.


In [16]:
pos_mark = pm_result1.wannabe.query('name == "Mark"')
print("%2.2f EUR"%(pos_mark.amount/pos_mark.buy))


83.33 EUR

We try to maximize the market value, while keeping the probability as high as possible, without going over the constraints


In [17]:
from scipy.optimize import fmin_cobyla
import numpy as np

In [18]:
obj_func = lambda x: -x.sum()

In [19]:
x_init = np.ones(len(pm_result1.wannabe))

Create the constraints functions:

  • $ A_i - x_i > 0$
  • $ B_i - \frac{\Sigma_{i \in O_i}(x_i)}{\Sigma_(x_i)} $

In [20]:
cons = []
amount = pm_result1.wannabe.amount

# The x cannot be more than the specified amount
more_than_amount = lambda i: lambda x: amount[i] - x[i]
# The x cannot be less than 0
less_than_0 = lambda i: lambda x: x[i]
for i in range(len(df)):
    cons.append(more_than_amount(i))
    cons.append(less_than_0(i)) 

# If the outcome o wins, then the sum of all the payments shouldnt be bigger than the total sum of all the 
# money in the market
mv = pm_result1.market_value
ocs = pm_result1.wannabe.outcome.values
buy = df.buy.values
house_never_loses = lambda o: lambda x: mv + x.sum() - sum(x[ocs == o]/buy[ocs == o])

for o in range(len(pm_result1.possible_outcomes)):
    cons.append(house_never_loses(o))


---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
<ipython-input-20-2496034b20e3> in <module>()
      6 # The x cannot be less than 0
      7 less_than_0 = lambda i: lambda x: x[i]
----> 8 for i in range(len(df)):
      9     cons.append(more_than_amount(i))
     10     cons.append(less_than_0(i))

NameError: name 'df' is not defined

Find maxima that maximize the prediction market


In [ ]:
x1 = fmin_cobyla(obj_func, x_init, cons)
print(x1)

In [ ]:
for i in range(len(cons)):
    print(i, cons[i](x1))

In [ ]:
for o in range(len(pm_result1.possible_outcomes)):
    print(o, x1[pm_result1.wannabe.outcome.values == o],
          df.buy.values[pm_result1.wannabe.outcome.values == o],
          x1[pm_result1.wannabe.outcome.values == o]/df.buy.values[pm_result1.wannabe.outcome.values == o],
          sum(x1[pm_result1.wannabe.outcome.values == o]/df.buy.values[pm_result1.wannabe.outcome.values == o]),
          sum(x1))

In [ ]:
def probabilities(x, df):
    for o in set(df.outcome.values):
        print(pm_result1.possible_outcomes[o],':', sum(x[df.outcome.values==o])/sum(x))

In [ ]:
probabilities(x1, pm_result1.wannabe)

In [ ]:
45/(45+10+20)

In [ ]:
60*0.6

In [ ]:
10/0.5 + 33.33

The LS-LMSR model from Augur

Heavily inspired from this blog post: Augur’s Automated Market Maker: The LS-LMSR, By Dr. Abe Othman.

The cost function for the LMSR is given by:

$$ C(\textbf{q}) = b \log \left(\sum_{i=1}^n e^{\frac{q_i}{b}} \right) $$

and the marginal prices on each event are given by the partial derivatives of the cost function: $$ p_j(\textbf{q}) = \frac{e^{\frac{q_j}{b}}}{\sum_{i=1}^n e^{\frac{q_i}{b}}} $$ where $b$, which is defined as a constant in the original LMSR model of Hanson, is here defined as a variable of q $$ b(\textbf{q})=\alpha \sum_{i=1}^n q_i $$

with $\alpha$ defined as

$$ \alpha = \frac{0.1}{n \log{n}} $$

with $n$ being the number of dimensions of $\textbf{q}$


In [329]:
class LS_LMSRMarket(object):
    def __init__(self, task, vig=0.1, init=1.0):
        """
        Parameters
        ----------
        task    dict
                A dictionary describing the task for which the predictive market is created.
                Keys:
                -----
                type:               str 
                                    (e.g. 'scientific task')
                description:        str
                                    description of the task to be performed
                reference:          str
                                    Internal reference (e.g. 'result 1, p. 4')
                doi:                str
                                    DOI of the related publication
                possible_outcomes:  list
                                    List of strings describing the possible outcomes of the task
                                    
        vig     float
                parameter of the `alpha` variable used to calculate the `b` variable.
                Corresponds to the market "vig" value - typically between 5 and 30 percent in real-world markets
                
        init    float
                The initial subsidies of the market, spread equally in this algorithm on all the outcomes.
        
        """
        for k, v in task.items():
            setattr(self, k, v)
        self.init = init
        self.n = len(self.possible_outcomes)
        self._x = [np.ones([self.n])*init/self.n]
        self._book = []
        self.market_value = init
        self._history = []
        self.alpha = vig*self.n/np.log(self.n)
        
    def b(self, x):
        """Calculate the `b` equation: b=\alpha \Sigma x"""
        return self.alpha * x.sum()
        
    @property
    def book(self):
        return pd.DataFrame(self._book)
    
    @property
    def x(self):
        return self._x[-1].copy()
    
    def cost(self, x):
        return self.b(x)*np.log(np.exp(x/self.b(x)).sum())
    
    def _new_x(self, amount, outcome):
        new_x = self.x
        new_x[outcome] += amount        
        return new_x
            
    def price(self, amount, outcome):
        return self._price(self._new_x(amount, outcome))
        
    def _price(self, x):
        return self.cost(x)-self.cost(self.x)
    
    def register_x(self, x):
        self._x.append(x)
    
    def new_bet(self, name, paid, outcome):
        obj_func = lambda a: np.abs(self.price(a, outcome) - paid)
        owed = fmin_cobyla(obj_func, paid, [])
        if owed<paid:
            print('No, sorry the bet would be unfair!')
            return owed
        #price = self.price(amount, outcome)
        self.register_x(self._new_x(owed, outcome))
        self._book.append({'name':name, 'owed':owed, 'outcome':outcome, 'paid':paid})
        self._history.append(self.p)
        self.market_value += paid
        return owed

    @property
    def p(self):
        return np.exp(self.x/self.b(self.x))/np.exp(self.x/self.b(self.x)).sum()
    
    def history(self):
        return np.array(self._history)

In [330]:
np.log(np.exp(1.))


Out[330]:
1.0

In [331]:
result1_task1


Out[331]:
{'description': 'Attempt to reproduce the result 1 of this article',
 'doi': '10.1051/itmconf/20140201004',
 'possible_outcomes': ['the result is reproducible',
  'the result is not reproducible'],
 'reference': 'result 1, p. 4',
 'type': 'scientific task'}

In [332]:
pm = LS_LMSRMarket(result1_task1, init=10., vig=0.1)

In [333]:
pm.new_bet('Mark', 1., 0)
pm.new_bet('Erik', 3., 1)
pm.new_bet('Soeren', 1., 0)
pm.new_bet('Albert', 3., 1)


Out[333]:
array(3.6746164062500006)

In [334]:
pm.market_value


Out[334]:
18.0

In [335]:
pm.book


Out[335]:
name outcome owed paid
0 Mark 0 1.33221953125 1
1 Erik 1 4.0828078125000005 3
2 Soeren 0 1.686667578125 1
3 Albert 1 3.6746164062500006 3

In [336]:
pl.plot(pm.history())
pl.ylim([0.,1.])
pl.legend(['outcome 0', 'outcome 1'])


Out[336]:
<matplotlib.legend.Legend at 0x1166c03c8>

100 Traders example


In [337]:
n = 100
outcome = 0.001
# The amount is assumed to increase linearly with time, as the market increases its liquidity
amount = np.random.random([n]) * 100. #* (1+np.arange(n))/(1.*n)
outcomes = np.zeros([n])
outcomes[np.random.random([n])<outcome] = 1.0

Creating the new task prediction market


In [338]:
pm = LS_LMSRMarket(result1_task1, init=10., vig=0.1)

Performing the bets


In [339]:
for i, a, o in zip(range(n),amount, outcomes):
    pm.new_bet('Trader-%d'%(i), a, int(o))


No, sorry the bet would be unfair!
No, sorry the bet would be unfair!
No, sorry the bet would be unfair!
No, sorry the bet would be unfair!
No, sorry the bet would be unfair!
No, sorry the bet would be unfair!
No, sorry the bet would be unfair!
No, sorry the bet would be unfair!
No, sorry the bet would be unfair!
No, sorry the bet would be unfair!
No, sorry the bet would be unfair!
No, sorry the bet would be unfair!
No, sorry the bet would be unfair!
No, sorry the bet would be unfair!
No, sorry the bet would be unfair!
No, sorry the bet would be unfair!
No, sorry the bet would be unfair!
No, sorry the bet would be unfair!
No, sorry the bet would be unfair!
No, sorry the bet would be unfair!
No, sorry the bet would be unfair!
No, sorry the bet would be unfair!
No, sorry the bet would be unfair!
No, sorry the bet would be unfair!
No, sorry the bet would be unfair!
No, sorry the bet would be unfair!
No, sorry the bet would be unfair!
No, sorry the bet would be unfair!
No, sorry the bet would be unfair!
No, sorry the bet would be unfair!
No, sorry the bet would be unfair!
No, sorry the bet would be unfair!
No, sorry the bet would be unfair!
No, sorry the bet would be unfair!
No, sorry the bet would be unfair!
No, sorry the bet would be unfair!
No, sorry the bet would be unfair!
No, sorry the bet would be unfair!
No, sorry the bet would be unfair!
No, sorry the bet would be unfair!
No, sorry the bet would be unfair!
No, sorry the bet would be unfair!
No, sorry the bet would be unfair!
No, sorry the bet would be unfair!
No, sorry the bet would be unfair!
No, sorry the bet would be unfair!
No, sorry the bet would be unfair!
No, sorry the bet would be unfair!
No, sorry the bet would be unfair!
No, sorry the bet would be unfair!
No, sorry the bet would be unfair!
No, sorry the bet would be unfair!
No, sorry the bet would be unfair!
No, sorry the bet would be unfair!
No, sorry the bet would be unfair!
No, sorry the bet would be unfair!
No, sorry the bet would be unfair!
No, sorry the bet would be unfair!
No, sorry the bet would be unfair!
No, sorry the bet would be unfair!
No, sorry the bet would be unfair!
No, sorry the bet would be unfair!
No, sorry the bet would be unfair!
No, sorry the bet would be unfair!
No, sorry the bet would be unfair!
No, sorry the bet would be unfair!
No, sorry the bet would be unfair!
No, sorry the bet would be unfair!
No, sorry the bet would be unfair!
No, sorry the bet would be unfair!
No, sorry the bet would be unfair!
No, sorry the bet would be unfair!
No, sorry the bet would be unfair!
No, sorry the bet would be unfair!
No, sorry the bet would be unfair!
No, sorry the bet would be unfair!
No, sorry the bet would be unfair!
No, sorry the bet would be unfair!
No, sorry the bet would be unfair!
No, sorry the bet would be unfair!
No, sorry the bet would be unfair!
No, sorry the bet would be unfair!
No, sorry the bet would be unfair!
No, sorry the bet would be unfair!
No, sorry the bet would be unfair!
No, sorry the bet would be unfair!
No, sorry the bet would be unfair!
No, sorry the bet would be unfair!
No, sorry the bet would be unfair!
No, sorry the bet would be unfair!
No, sorry the bet would be unfair!
No, sorry the bet would be unfair!
No, sorry the bet would be unfair!
No, sorry the bet would be unfair!
No, sorry the bet would be unfair!
No, sorry the bet would be unfair!
No, sorry the bet would be unfair!
No, sorry the bet would be unfair!

One company comes along and bet sh*t ton of money


In [340]:
pm.new_bet('EvilMegaCorp', 1.E3, 1)


Out[340]:
array(1013.3293015625)

The total to pay for each outcome


In [341]:
total = pm.book.groupby('outcome').sum()
total['house_wins'] = pm.market_value - total.owed
total


---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-341-d845a9fe9c7f> in <module>()
      1 total = pm.book.groupby('outcome').sum()
----> 2 total['house_wins'] = pm.market_value - total.owed
      3 total

/Users/pire/Projects/FractalFlows/predictive_market/.venv/lib/python3.4/site-packages/pandas/core/generic.py in __getattr__(self, name)
   2148                 return self[name]
   2149             raise AttributeError("'%s' object has no attribute '%s'" %
-> 2150                                  (type(self).__name__, name))
   2151 
   2152     def __setattr__(self, name, value):

AttributeError: 'DataFrame' object has no attribute 'owed'

In [349]:
pm.book.groupby('outcome').sum()


Out[349]:
paid
outcome
0 22.53699
1 1000.00000

Plot the market prediction history


In [327]:
pl.plot(pm.history())
pl.ylim([0.,1.])
pl.legend(['outcome 0', 'outcome 1'])
pl.title('%d Trades, total market value=%2.2f EUR'%(n, pm.market_value))


Out[327]:
<matplotlib.text.Text at 0x11673b2e8>

The book of trades


In [328]:
book = pm.book
book['possible_win'] = pm.book.owed - pm.book.paid
book['p0'] = pm.history()[:,0]
book['p1'] = pm.history()[:,1]
book


Out[328]:
name outcome owed paid possible_win p0 p1
0 Trader-0 0 62.25628687710523 61.283042 0.9732445 0.951942 0.048058
1 Trader-1 0 98.94011925382945 99.767944 -0.827825 0.963148 0.036852
2 Trader-2 0 48.572072226020104 48.996100 -0.4240281 0.964703 0.035297
3 Trader-3 0 58.876211326757485 59.393489 -0.5172781 0.965821 0.034179
4 Trader-4 0 89.68715556260987 90.478759 -0.7916039 0.966806 0.033194
5 Trader-5 0 62.188656095492505 62.738605 -0.5499488 0.967240 0.032760
6 Trader-6 0 8.800520658239893 8.878346 -0.077825 0.967291 0.032709
7 Trader-7 0 90.46583129378851 91.266901 -0.8010695 0.967714 0.032286
8 Trader-8 0 59.07660232034107 59.600240 -0.5236375 0.967919 0.032081
9 Trader-9 0 63.86217600834077 64.428394 -0.566218 0.968097 0.031903
10 Trader-10 0 68.27948534816697 68.884854 -0.6053687 0.968252 0.031748
11 Trader-11 0 50.25892628076068 50.704627 -0.4457008 0.968348 0.031652
12 Trader-12 0 76.88447126047394 77.566400 -0.6819289 0.968473 0.031527
13 Trader-13 0 35.163063330163396 35.474975 -0.3119117 0.968523 0.031477
14 Trader-14 0 54.47142748392926 54.954626 -0.4831984 0.968592 0.031408
15 Trader-15 0 9.965241206626096 10.053720 -0.08847891 0.968604 0.031396
16 Trader-16 0 14.29211450655274 14.419023 -0.126909 0.968620 0.031380
17 Trader-17 0 83.37409442848035 84.114041 -0.7399461 0.968707 0.031293
18 Trader-18 0 79.70989917256541 80.417219 -0.7073195 0.968779 0.031221
19 Trader-19 0 77.96950396579865 78.661598 -0.6920945 0.968839 0.031161
20 Trader-20 0 3.6186684283480917 3.650695 -0.03202656 0.968842 0.031158
21 Trader-21 0 17.886269723118183 18.045161 -0.1588914 0.968854 0.031146
22 Trader-22 0 85.78798761959271 86.549518 -0.7615305 0.968910 0.031090
23 Trader-23 0 80.79308549864831 81.510327 -0.717241 0.968956 0.031044
24 Trader-24 0 11.060352454637881 11.158597 -0.09824453 0.968962 0.031038
25 Trader-25 0 62.4589520029471 63.013495 -0.5545434 0.968994 0.031006
26 Trader-26 0 73.22324360218765 73.873346 -0.6501023 0.969028 0.030972
27 Trader-27 0 36.026451246443244 36.346175 -0.3197242 0.969043 0.030957
28 Trader-28 0 14.862851605450398 14.994888 -0.1320359 0.969049 0.030951
29 Trader-29 0 87.20743693757935 87.981707 -0.7742699 0.969083 0.030917
... ... ... ... ... ... ... ...
71 Trader-71 0 62.9570030656529 63.515885 -0.558882 0.969424 0.030576
72 Trader-72 0 95.92762291411553 96.779385 -0.8517625 0.969431 0.030569
73 Trader-73 0 40.020695502686934 40.375964 -0.3552687 0.969434 0.030566
74 Trader-74 0 53.06598453473234 53.537076 -0.4710914 0.969438 0.030562
75 Trader-75 0 78.43374593276529 79.130235 -0.6964891 0.969443 0.030557
76 Trader-76 0 70.82808500471883 71.456791 -0.6287062 0.969447 0.030553
77 Trader-77 0 90.80709532491268 91.613448 -0.8063523 0.969453 0.030547
78 Trader-78 0 88.4511142810978 89.236571 -0.7854563 0.969458 0.030542
79 Trader-79 0 41.264959991848556 41.631215 -0.3662551 0.969460 0.030540
80 Trader-80 0 5.6957947932450566 5.746276 -0.05048125 0.969460 0.030540
81 Trader-81 0 78.13056425442342 78.824112 -0.6935477 0.969464 0.030536
82 Trader-82 0 43.18197627842462 43.565477 -0.3835008 0.969467 0.030533
83 Trader-83 0 33.47306996290091 33.770133 -0.2970633 0.969468 0.030532
84 Trader-84 0 7.366694373753339 7.432024 -0.06532969 0.969469 0.030531
85 Trader-85 0 4.897935045875853 4.941492 -0.04355703 0.969469 0.030531
86 Trader-86 0 15.856811776544836 15.997737 -0.140925 0.969470 0.030530
87 Trader-87 0 63.75793165469183 64.324150 -0.566218 0.969473 0.030527
88 Trader-88 0 6.8441298007389175 6.904977 -0.06084687 0.969473 0.030527
89 Trader-89 0 49.42374701780073 49.862668 -0.4389207 0.969476 0.030524
90 Trader-90 0 25.940208929426692 26.170634 -0.2304246 0.969477 0.030523
91 Trader-91 0 24.567774221768726 24.785992 -0.2182176 0.969478 0.030522
92 Trader-92 0 25.56333973613601 25.790191 -0.2268508 0.969479 0.030521
93 Trader-93 0 23.591206283843043 23.800579 -0.2093727 0.969480 0.030520
94 Trader-94 0 24.0020147592278 24.215205 -0.2131906 0.969482 0.030518
95 Trader-95 0 41.47420053546037 41.842565 -0.3683641 0.969483 0.030517
96 Trader-96 0 12.601742798868214 12.713759 -0.1120164 0.969484 0.030516
97 Trader-97 0 17.733966474071526 17.891493 -0.1575266 0.969485 0.030515
98 Trader-98 0 57.61405983926817 58.125479 -0.5114187 0.969487 0.030513
99 Trader-99 0 77.57203144013322 78.260852 -0.6888207 0.969491 0.030509
100 EvilMegaCorp 1 1999.0 1000.000000 999 0.812632 0.187368

101 rows × 7 columns


In [237]:
pm.market_value


Out[237]:
1012662.9992755557

In [229]:
pm.p


Out[229]:
array([ 0.03134109,  0.96865891])

In [ ]:


In [ ]:


In [ ]: