Laying Home Favourites in the Bundesliga

Published on July 22, 2020, 2:13 p.m. - Sports: Football

This betting system focuses on the German football league, Bundesliga, and involves betting against the favourite. There are various sets of rules that can be applied in order to increase profitability. Some of them are selecting home favourites only or excluding certain odds ranges.

The sports investing blog green-all-over.blogspot.com analyses the lay the Bundesliga favourite approach in great detail. The author Cassini refers to this method as "Bundeslayga" and in a recent post he updated his backtesting results.

To be honest, I was surprised when looking at the profit and loss figures of such a simple system. I thought I would give it a try and started to look into the data with the goal to reproduce the backtesting results. For the backtest on historical data, the following rules are used: Bundesliga 1 and 2 matches are selected for a bet when the home team is the favourite with winning odds in the range of 40% - 89%. Pinnacle closing prices are used as baseline, odds taken from football-data.co.uk.

Backtest on historical data

I use a short Python script along with the Pandas package to download the historical odds into a Pandas dataframe. The dataframe contains all the matches for the seasons from 2012/13 up to 2018/19 for 1. and 2. Bundesliga.

import pandas as pd
from typing import Tuple

def get_df(
        seasons: Tuple[str] = ("1213", "1314", "1415", "1516", "1617", "1718", "1819"),
        leagues: Tuple[str] = ("D1", "D2")
) -> pd.DataFrame:
    results = pd.DataFrame()
    for season in seasons:
        for league in leagues:
            df = pd.read_csv(
                f"http://www.football-data.co.uk/mmz4281/{season}/{league}.csv",
                usecols=["HomeTeam", "AwayTeam", "FTHG", "FTAG", "PSCH", "PSCD", "PSCA"],
            )
            df["Season"] = season
            df["League"] = league
            results = pd.concat([results, df], ignore_index=True)
    return results

df = get_df()

An output of the dataframe (df)  should list the matches along with the full time home / away goals and Pinnacle's closing prices for home, draw and away:

  HomeTeam AwayTeam FTHG FTAG PSCH PSCD PSCA Season League
0 Dortmund Werder Bremen 2 1 1.29 6.37 11.20 1213 D1
1 Augsburg Fortuna Dusseldorf 0 2 2.08 3.45 4.01 1213 D1
2 Ein Frankfurt Leverkusen 2 1 2.99 3.54 2.48 1213 D1
3 Freiburg Mainz 1 1 2.78 3.45 2.71 1213 D1
4 Greuther Furth Bayern Munich 0 3 8.65 4.76 1.44 1213 D1

Next, I will calculate the hypothetical lay odds for the favourite. Since laying is not possible on Pinnacle, I use a combination of back draw and back underdog to resemble a lay bet. Deriving the lay odds with this method results in higher odds compared to the back favourite odds in the dataframe due to market overround. One point flat staking is used which results in a loss of 1 point in case the favourites does win. Otherwise the profit is is one over lay_odds minus one.

def get_profit(x):
    if  0.4 <= 1 / x["LayH"] <= 0.89:
        if x["FTHG"] <= x["FTAG"]:
            return round(1/(x["LayH"]-1), 2)
        else:
            return -1
    return 0.0


df["LayH"] = 1 / (1 - 1 / df["PSCD"] - 1 / df["PSCA"])
df["Profit"] = df.apply(lambda x: get_profit(x), axis=1)

With the additional "LayH" and "Profit" columns, the dataframe should now look like:

  HomeTeam AwayTeam FTHG FTAG PSCH PSCD PSCA Season League LayH Profit
0 Dortmund Werder Bremen 2 1 1.29 6.37 11.20 1213 D1 1.326738 -1.00
1 Augsburg Fortuna Dusseldorf 0 2 2.08 3.45 4.01 1213 D1 2.170288 0.85
2 Ein Frankfurt Leverkusen 2 1 2.99 3.54 2.48 1213 D1 3.181792 0.00
3 Freiburg Mainz 1 1 2.78 3.45 2.71 1213 D1 2.931337 0.00
4 Greuther Furth Bayern Munich 0 3 8.65 4.76 1.44 1213 D1 10.474328 0.00

Next, I will calculate profit and loss for each match and group by division and season:

df = df[df["Profit"] != 0]
df["Sels"] = 1
df.groupby(["League", "Season"]).agg({
    "Sels": "count",
    "Profit": "sum",
})

In the end I obtain the following number selections and P/L figures:

    Sels Profit
League Season    
D1 1213 178 11.10
1314 175 -15.73
1415 174 1.87
1516 168 2.43
1617 164 -2.33
1718 172 -0.44
1819 158 2.70
D2 1213 179 1.68
1314 185 22.79
1415 163 12.18
1516 154 5.44
1617 161 -29.40
1718 158 4.15
1819 143 1.35

Unfortunately, there is some deviation from the results reported on Cassini's blog and I am not sure yet where it originates from. I will try to clarify and update shortly.

Do you like our content? Please share with your friends!

Share on Facebook Share on Twitter

Comments

No comments published yet.

Please log in to leave a comment.

Similar Strategies
See all Strategies!
Learn more About This Strategy

If you would like to learn more about this strategy, please do not hesitate to contact us.

Contact Us!