Last active
August 17, 2023 16:16
-
-
Save dsetzer/b7c3293ee551f9b559edcb191baf110d to your computer and use it in GitHub Desktop.
Calculating probabilities with coefficients calculated from simulations
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import hmac | |
import hashlib | |
import binascii | |
import math | |
from collections import Counter | |
from scipy.optimize import curve_fit | |
import numpy as np | |
# Number of games to simulate (10 million) | |
num_games_to_simulate = 10_000_000 | |
# Hash to generate from | |
game_hash = 'a1f3e2d4c5b6a7f8d9e0a1f2b3c4d5e6f7a8b9c0d1e2f3a3b5c6d7e8f9a0b1c2' | |
# Target payouts to analyze | |
target_payouts = [1.23, 1.48, 1.75, 2, 2.32, 3.25, 5.24, 7.59, 9.87] | |
# Generate javascript code, if false will just outpit the coefficients | |
generate_javascript_code = False | |
def generate_multipliers(game_hash, num_games): | |
salt = '0000000000000000004d6ec16dafe9d8370958664c1dc422f452892264c59526'.encode() | |
hashobj = hmac.new(salt, binascii.unhexlify(game_hash), hashlib.sha256) | |
results = [] | |
for i in range(num_games): | |
intversion = int(hashobj.hexdigest()[0:int(52/4)], 16) | |
X = 100 / (1 - (intversion / (2 ** 52))) # Math.pow(2,52); | |
number = round(max(1, math.floor(X) / 101), 2) # Round to 2 decimal places | |
results.append(number) | |
game_hash = hashlib.sha256(game_hash.encode()).hexdigest() | |
hashobj = hmac.new(salt, binascii.unhexlify(game_hash), hashlib.sha256) | |
return results | |
def calculate_probability(multipliers, counts, total_games): | |
""" | |
Calculates the probability of a given multiplier occurring in a set of games | |
:param multipliers: A single multiplier or list of multipliers | |
:param counts: A Counter object with counts of each multiplier | |
:param total_games: The total number of games | |
""" | |
if isinstance(multipliers, (int, float)): | |
multipliers = [multipliers] | |
probabilities = [] | |
for multiplier in multipliers: | |
occurrences = counts.get(multiplier, 0) | |
probability = occurrences / total_games | |
probabilities.append(probability) | |
if len(probabilities) == 1: | |
return probabilities[0] | |
return probabilities | |
# Generate multipliers for the given number of games | |
print(f'Generating {num_games_to_simulate} results...') | |
game_results = generate_multipliers(game_hash, num_games_to_simulate) | |
result_count = Counter(game_results) | |
# Calculate probability for exactly 2x multiplier | |
print('Calculating probabilities...') | |
probabilities = calculate_probability(target_payouts, result_count, num_games_to_simulate) | |
# Print the probabilities for each target payout | |
for target_payout, probability in zip(target_payouts, probabilities): | |
print(f'Probability of {target_payout}x: {probability}') | |
# Given data points | |
np_target_payouts = np.array(target_payouts) | |
np_probabilities = np.array(probabilities) | |
# Power-law function | |
def power_law(x, a, b): | |
return a * x ** b | |
# Fit the power-law function to the given data | |
params, _ = curve_fit(power_law, np_target_payouts, np_probabilities) | |
# Coefficients a and b | |
a_coeff, b_coeff = params | |
print(f'Power-law coefficients: a={a_coeff}, b={b_coeff}') | |
# Generate javascript code for the power-law function | |
if not generate_javascript_code: | |
print('Generating coefficients...\n') | |
print(f'const a_coeff = {a_coeff};') | |
print(f'const b_coeff = {b_coeff};') | |
else: | |
print('Generating javascript code...\n') | |
print('function calculateProbability(multiplier) {') | |
print(f' return {a_coeff} * Math.pow(multiplier, {b_coeff});') | |
print('}\n') | |
print('function cumulativeProbabilityForExactPayout(targetPayout, numberOfTrials) {') | |
print(' // Probability for the exact target payout in a single trial') | |
print(f' const singleTrialProbability = {a_coeff} * Math.pow(targetPayout, {b_coeff});') | |
print(' // Cumulative probability after a given number of trials') | |
print(' return Math.pow(1 - singleTrialProbability, numberOfTrials - 1) * singleTrialProbability;') | |
print('}\n') | |
print('// Example usage:') | |
print('const targetPayout = 2.0;') | |
print('const numberOfTrials = 10;') | |
print('console.log(`Probability of exactly ${targetPayout}x occurring is ${calculateProbability(targetPayout)}`);') | |
print('console.log(`Cumulative probability for ${targetPayout}x after ${numberOfTrials} trials: ${cumulativeProbabilityForExactPayout(targetPayout, numberOfTrials)}`);') |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment