Doing more Monte Carlo Simulations - Kelly Criterion Project

Hi,

Just started out coding. Was doing a project to test out the Kelly Criterion, a betting system that determines what is the best allocation of your portfolio should you stake for an investment, given the odds and payoffs.

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import decimal as d

# Probablility of winning
# Probablity of loss is 1-W
def kelly(Per,P,L):

    Per=d.Decimal(Per).quantize(d.Decimal('1.000'))
    P=d.Decimal(P).quantize(d.Decimal('1.000'))
    L=d.Decimal(L).quantize(d.Decimal('1.000'))
    
    
    opt= (Per/L)-((1-Per)/P)
    return opt

# Per=0.6

# # Profit of event in percentage. 1+P would be the percentage amount won
# P= 0.2

# # Loss during event in percentage. 1-L is the loss for your portfolio
# L=0.2


# Using The Kelly Function

Here is an example on how to use it

a=kelly(0.6,0.2,0.2)

First variable is the % odds of profit. Between 0-1, goes to max 3 dp

Second variable is the profit if the bet is correct. Can be any positive number. Note this is 1-payoff

Third variable is the loss during event in percentage. Can be any positive number. Note this is 1-loss
PercentageOfOdds = 0.6

Profit = 1

Loss = 1


#Betting percentage for the differnet scenarios

a = kelly(PercentageOfOdds,Profit,Loss)

b = a/2 # Half Kelly

c = a*2 # Double Kelly


# Creating the monte carlo simulation with the for statements

Saving all results in a list before changing it to a dataframe

#Starting capital
amtf=d.Decimal('1')
amth=d.Decimal('1')
amtd=d.Decimal('1')


#changing the profit and loss float numbers to decimal
P=d.Decimal(Profit).quantize(d.Decimal('1.000'))
L=d.Decimal(Loss).quantize(d.Decimal('1.000'))

# List to store the simulations
fullk=[]
halfk=[]
doubk=[]

# Simulating the different senarios

for i in range(10000):
    r=np.random.random()

    # if the bet is in your favour

    if(r<PercentageOfOdds):
        amtf = amtf+amtf*P*a
        amth = amth+amth*P*b
        amtd = amtd+amtd*P*c


        fullk.append(amtf)
        halfk.append(amth)
        doubk.append(amtd)


    # If you lose the bet

    else:
        amtf = amtf-amtf*L*a
        amth = amth-amth*L*b
        amtd = amtd-amtd*L*c


        fullk.append(amtf)
        halfk.append(amth)
        doubk.append(amtd)


df1=pd.DataFrame(fullk, columns = ['Full Kelly'], dtype=float)
df2=pd.DataFrame(halfk, columns = ['Half Kelly'], dtype=float)
df3=pd.DataFrame(doubk, columns = ['Double Kelly'], dtype=float)

#Printing the results

results = pd.concat([df1, df2,df3], axis=1)
results


results.plot()
plt.yscale("log")

I’m trying to do a monte carlo simulation in python for half kelly (kelly criterion), full kelly, and 2X kelly.

Seems like I hit a limit of around 10,000 simulations and the amount generated is too large; it becomes infinity. I’m trying to see if it is possible to do 100,000> simulations is a way to do that?

Is there a better way to do mote carlo simulations?

All advice is welcome!

Thanks

I mean, for a start - don’t use Python lists. They take up a ton more memory because they lack strong typing. So you’re better off directly creating a dataframe and adding the values in there.

Oh ok will change that then. The code runs fine in terms of speed so far. Just that the numerical limit is hot when I run 10000 loops.

Can you show us the exact error you’re getting.

I ran your code several times with no errors and 10,000 iterations. Good job!
I do hit a RuntimeWarning upon graphing the results when raising the iterations to 100,000 however (unsurprisingly as many values are getting converted to np.Inf in the dataframe).

You can use sys.float_info.max to get the maximum value for floats.
You might have better luck using integers for large values where decimal precision might not be very important (memory allowing). Since these are profits, let’s consider USD. Is storing 10 cents on $12,000,000.10 valuable in this particular use case? Maybe use decimal precision up till a certain amount then switch to integer precision if you can get away with it?
For instance, this will throw an OverflowError for me: float(1 * 10**309). But this is perfectly acceptable on my system: int(1 * 10**5000).
Alternatively you can store large floats as strings but I don’t think that will solve your issue here.

image

Thanks for looking at my code! Yeah, my issue is with the np.Inf value in the data frame.

I tried to change it to an interger as suggested buy because the probability is in decimal, seems like it will change the integer to decimal after I multiply it together?

So should I just change it back to the integer at the end of the loop before appending it to the list?

Actually it seems like pandas tries to convert large integers into floats anyway. Decimal objects that are larger than a C long fail to be cast into int on my system; they can be cast to float as Inf.

Perhaps the string method is the easiest way to go here.
E.g.

df1 = pd.DataFrame(fullk, columns = ['Full Kelly'], dtype = str)
df1['converted'] = df1['Full Kelly'].apply(d.Decimal)

This allows you to store the data in a DataFrame to work with, but honestly I think you’ll lose a lot functionality this way. I don’t think vector math will work on Decimal objects and plotting will still likely not work.

I think these values might just be too large for working with many Python libraries.

1 Like

Yeah that makes sense. Perpahs doing monte carols like is not the best in python

Thanks for all the help!