Monday, April 29, 2024

Win-Goal Less Than Loss-Limit

WCMI Win-Goal Less Than Loss-Limit

In sports trading, we face a great deal of risk and uncertainty that we often express initially as a series of questions.

  • What is my target bankroll?
  • How much am I willing to lose?
  • What are my chances of success?
  • Over how many events (session length) should I set this goal?
  • How much should I risk per event?

First, it is essential to clarify what we mean by "Win-Goal" and "Loss-Limit":

  • Win-Goal: Predefined profit target that we aim to achieve within a specific session or over a certain number of events.
  • Loss-Limit: Maximum amount of capital that we are prepared to lose during the same period.

Setting these parameters helps us to manage our bankrolls effectively.

Second, using historical data on win probabilities and win odds, we will run a series of Monte Carlo simulations of thousands of trading sessions.

  • Win-Goal Probability: We calculate the likelihood of achieving various win goals before reaching the loss limit over a predetermined number of events (trading opportunities).
  • Sensitivity Analysis: We assess how different settings of loss limits and stakes affect the probability of achieving the win goal before reaching the loss limit.

Third, let us consider a simple example. We will set the following parameters (Not meant to be either realistic or recommended):

  • Bankroll: 1000
  • Loss-Limit: 25% (bankroll)
  • Win Odds: 2.50
  • Win Probability: 42%
  • Number of Events: 20

We want to know the probability of reaching win goals of 125 and 175 over these 20 events. Using the simulated scenario, we get these results:

  • Probability of reaching a win goal of 125 over 20 events: 30.57%
  • Probability of reaching a win goal of 175 over 20 events: 30.57%

It might seem odd that the probabilities of reaching different win goals (125 and 175) are identical at 30.57%. This could occur due to several reasons:

  • Statistical Anomaly: In some simulation runs, due to the randomness inherent in Monte Carlo methods, outcomes might align by chance.
  • Dominant Loss-Limit Effect: If the loss limit is highly restrictive, it might prevent the bankroll from fluctuating significantly. In such cases, once a certain profit level is achievable, higher profits might also become equally probable if losses are tightly controlled.
  • Stake Size and Market Limits: The fixed stake size and the limited number of events might create scenarios where reaching any profit above a certain threshold (like 125) doesn't significantly change the odds of achieving even higher profits within the constraints of the model.

The Python script below allows us to evaluate trading sessions based on realistic statistical simulations. By adjusting win goals and loss limits according to the simulation results, we can better manage our risk and potentially increase our profitability.

This approach to risk management not only enhances our understanding of the strategy's robustness but also encourages a disciplined approach to trading, essential for long-term success.

# -*- coding: latin-1 -*-

import random

from datetime import date
from functools import reduce
from scipy.stats import beta
from tabulate import tabulate
from argparse import ArgumentParser, ArgumentDefaultsHelpFormatter

__date__ = str(date.today())
__query__ = ''

__title__ = 'Win-Goal Less Than Loss-Limit'
__author__ = 'matekus'
__version__ = 'v1.02'
__copyright__ = '(c) 2024, ' + __author__ + ', All Rights Reserved.'
__address__ = '[ https://vendire-ludorum.blogspot.com/ ]'

def monte_carlo_simulation(bankroll, win_prob, win_odds, loss_limit, win_goals, stake, markets, trials) -> list:
    wins = [0] * len(win_goals)
    for _ in range(trials):
        current_bankroll = bankroll
        for _ in range(markets):
            current_bankroll += stake * (win_odds - 1) if random.random() < win_prob else -stake
            if current_bankroll <= bankroll - loss_limit:
                break
        wins = [wins[i] + 1 if current_bankroll >= bankroll + goal else wins[i] for i, goal in enumerate(win_goals)]
    probabilities = [win / trials for win in wins]
    return probabilities

def print_monte_carlo_results(state) -> dict:
    new_state = state.copy()
    bankroll = new_state['bankroll']
    win_prob = new_state['win_prob']
    win_odds = new_state['win_odds']
    win_goals = new_state['win_goals']
    stakes_percentages = new_state['stakes_percentages']
    loss_limit_percentages = new_state['loss_limit_percentages']
    markets = new_state['markets']
    trials = new_state['trials']

    # Calculate loss limits for each percentage
    loss_limits = [bankroll * llp for llp in loss_limit_percentages]

    print('')
    print(f'Bankroll: {bankroll:.0f}')
    for loss_limit in loss_limits:
        print(f'Drawdown Limit for {loss_limit/bankroll*100:.0f}%: {bankroll - loss_limit:.0f}')
    print('')

    # Run the Monte-Carlo simulation for each stake and loss limit
    for stake_percentage in stakes_percentages:
        stake = stake_percentage * bankroll
        for loss_limit in loss_limits:
            probabilities = monte_carlo_simulation(bankroll, win_prob, win_odds, loss_limit, win_goals, stake, markets, trials)
            print(f'Stake: {stake_percentage*100:.0f}% of bankroll - {stake:.0f}')
            print(f'Loss-Limit: {loss_limit:.0f}')
            for i, goal in enumerate(win_goals):
                print(f'  Probability of reaching a win goal of {goal} over {markets} events: {probabilities[i]:.2%}')
            print('')
    return new_state

def main() -> None:
    print('')
    print(__title__)
    print(__copyright__)
    print(__address__)
    print('')
    print('[', __date__, ']')
    print('')

    parser = ArgumentParser(formatter_class=ArgumentDefaultsHelpFormatter)
    parser.add_argument("-b", "--bankroll", default=1000.0, type=float, help="Initial bankroll.")
    parser.add_argument("-llp", "--loss_limit_percentages", nargs='+', type=float, default=[0.25], help="Loss limit percentages.")
    parser.add_argument("-wo", "--win_odds", default=2.50, type=float, help="Win odds (historic).")
    parser.add_argument("-wp", "--win_prob", default=0.42, type=float, help="Win probability (historic).")
    parser.add_argument("-wg", "--win_goals", default=[125, 175], type=list, help="Win goals.")
    parser.add_argument("-sp", "--stakes_percentages", default=[0.01, 0.02, 0.03], type=list, help="Stakes percentages.")
    parser.add_argument("-m", "--markets", default=20, type=int, help="Number of markets.")
    args = vars(parser.parse_args())

    # Define pipeline with updated steps
    pipeline = [
        print_monte_carlo_results
    ]

    # Define initial state.
    initial_state = {
        'bankroll': args["bankroll"],
        'loss_limit_percentages': args["loss_limit_percentages"],
        'win_odds': args["win_odds"],
        'win_prob': args["win_prob"],
        'win_goals': args["win_goals"],
        'stakes_percentages': args["stakes_percentages"],
        'markets': args["markets"],
        'trials': 10000,
    }
    # Run pipeline.
    _ = reduce(lambda v, f: f(v), pipeline, initial_state)

    print('')
    print('Fini!')
    print('')

if __name__ == '__main__':
    main()

""" 
> python Win-Goal_Less-Than_Loss-Limit.py -b 1500

Win-Goal Less Than Loss-Limit
(c) 2024, matekus, All Rights Reserved.
[ https://vendire-ludorum.blogspot.com/ ]

[ 2024-04-29 ]

Bankroll: 1500
Drawdown Limit for 25%: 1125

Stake: 1% of bankroll - 15
Loss-Limit: 375
  Probability of reaching a win goal of 125 over 20 events: 8.28%
  Probability of reaching a win goal of 175 over 20 events: 2.95%

Stake: 2% of bankroll - 30
Loss-Limit: 375
  Probability of reaching a win goal of 125 over 20 events: 31.15%
  Probability of reaching a win goal of 175 over 20 events: 16.88%

Stake: 3% of bankroll - 45
Loss-Limit: 375
  Probability of reaching a win goal of 125 over 20 events: 30.74%
  Probability of reaching a win goal of 175 over 20 events: 30.74%

Fini!
"""

# EOF.

As ever, the script has little or no "errr0r" handling and is only a starting point for your own explorations. Enjoy!