Advertisement
Guest User

Untitled

a guest
Aug 18th, 2019
85
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 5.77 KB | None | 0 0
  1. #!/usr/bin/env python3
  2. """Analysis results:
  3. Turnover: £3,422,065
  4. EV: £132,712
  5. PnL: £147,777
  6. Commission: £72,974
  7. Net PnL: £74,802
  8. RoI: 2.186%
  9. """
  10.  
  11. import csv
  12. import os
  13. import pandas as pd
  14. import random
  15.  
  16. def find_stake_value(row):
  17. pass
  18.  
  19. def calculate_backing_stake_fraction(win_probability, odds):
  20. return ((win_probability * odds) - 1) / (odds - 1)
  21.  
  22. def calculate_laying_stake_fraction(win_probability, odds):
  23. return ((1 - win_probability) - win_probability * (odds - 1)) / (odds - 1)
  24.  
  25. def calculate_side(win_probability, odds):
  26. stake = calculate_backing_stake_fraction(win_probability, odds)
  27. if stake > 0:
  28. return "back"
  29. else:
  30. return "lay"
  31.  
  32. def get_random_side():
  33. if random.randint(0, 1) == 1:
  34. return "back"
  35. else:
  36. return "lay"
  37.  
  38. def print_all_values(turnover, EV, PnL, commission, Net_PnL, RoI):
  39. print("Turnover: " + str(int(turnover)))
  40. print("EV: " + str(int(EV)))
  41. print("PnL: " + str(int(PnL)))
  42. print("Commission: " + str(int(commission)))
  43. print("Net_PnL: " + str(int(Net_PnL)))
  44. print("RoI: " + str(round(RoI, 3)) + "%")
  45.  
  46. def value_calculation(racing_data, bank, minimum_stake, model):
  47.  
  48. #Define all values to be calculated by iterative addition
  49. turnover = 0
  50. EV = 0
  51. PnL = 0
  52. commission = 0
  53.  
  54. for index, row in racing_data.iterrows():
  55.  
  56. if index == 0:
  57. #Define race number and race PnL at beginning of for loop
  58. previous_race_number = 0
  59. race_PnL = 0
  60.  
  61. #After each race, we calculate commission and add race PnL to total PnL.
  62. #We also reset race PnL to prepare for next race. We need to add a
  63. #condition that checks for the last index, since there is no transition
  64. #to another race that we can use in that case.
  65. if (previous_race_number != row["race_number"]) | (index == len(racing_data.index) - 1):
  66. if race_PnL > 0:
  67. commission += race_PnL * 0.05
  68. PnL += race_PnL
  69. race_PnL = 0
  70.  
  71. #Assign data values to variables for easier readability
  72. win_probability = 1 / row["win_fair_price"]
  73. odds = row["win_starting_price"]
  74.  
  75. #We have two different models to check, one based on predictions and
  76. #one which is completely random.
  77. if model == "prediction":
  78. side = calculate_side(win_probability, odds)
  79. if side == "back":
  80. stake = calculate_backing_stake_fraction(win_probability, odds) * bank
  81. else:
  82. stake = calculate_laying_stake_fraction(win_probability, odds) * bank
  83. if stake > minimum_stake:
  84. turnover += stake
  85. #we need to consider 4 scenarios. lay + win, lay + lose, back + win
  86. #and back + lose.
  87. if side == "lay":
  88. EV += stake * (1 - win_probability) - stake * (odds - 1) * win_probability
  89. if row["winner"] == 0:
  90. race_PnL += stake
  91. else:
  92. race_PnL -= stake * (odds - 1)
  93. else:
  94. EV += stake * win_probability * (odds - 1) - stake * (1 - win_probability)
  95. if row["winner"] == 0:
  96. race_PnL -= stake
  97. else:
  98. race_PnL += stake * (odds - 1)
  99. previous_race_number = row["race_number"]
  100.  
  101. elif model == "monte_carlo":
  102. side = get_random_side()
  103.  
  104. if side == "back":
  105. #Stake is a random number between 2 and our bank value.
  106. stake = random.randint(2, bank)
  107. if row["winner"] == 0:
  108. race_PnL -= stake
  109. else:
  110. race_PnL += stake * (odds - 1)
  111. else:
  112. #The maximum stake is determined by stake that gives a liability
  113. #equal to our bank. We then take a random value between 2 amnd
  114. #this number
  115. stake = random.randint(2, round(bank / (odds - 1)))
  116. if row["winner"] == 0:
  117. race_PnL += stake
  118. else:
  119. race_PnL -= stake * (odds -1)
  120.  
  121. turnover += stake
  122. previous_race_number = row["race_number"]
  123. else:
  124. #Simple check to find an input error in the model name.
  125. raise Exception("Input model incorrect. Choose either 'prediction' or 'monte-carlo' as input string")
  126.  
  127. return turnover, EV, PnL, commission, PnL - commission, (PnL - commission) / turnover * 100
  128.  
  129. def main():
  130. #Set working directory so that horses.csv can be accessed without full path.
  131. os.chdir(os.path.dirname(os.path.realpath(__file__)))
  132.  
  133. #Read the CSV file
  134. csv_path = "horses.csv"
  135. racing_data = pd.read_csv(csv_path)
  136.  
  137. #Define starting bank
  138. bank = 10000
  139. minimum_stake = 2
  140.  
  141. #Extract Values based on data and the set values on bank and minimum stake.
  142. turnover, EV, PnL, commission, Net_PnL, RoI = value_calculation(racing_data, bank, minimum_stake, "prediction")
  143.  
  144. #Print the prediction values
  145. print("Values from predictions:")
  146. print_all_values(turnover, EV, PnL, commission, Net_PnL, RoI)
  147.  
  148. #To find the edge of this project, we compare it to a completely random
  149. #punter. We choose to back or lay at random, and then pick a random amount to
  150. #bet. When laying, the amount maximum will correspond to a £10,000 liability.
  151. turnover, EV, PnL, commission, Net_PnL, RoI = value_calculation(racing_data, bank, minimum_stake, "monte_carlo")
  152.  
  153. #Print monte-carlo values.
  154. print("Values from monte-carlo")
  155. print_all_values(turnover, EV, PnL, commission, Net_PnL, RoI)
  156.  
  157. if __name__=="__main__":
  158. main()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement