Allsvenskan 2018 Summer update 2

Last time, I took a look at how the teams in Allsvenskan have performed this first part of the 2018 season leading up to the World Cup break. As I promised then, I will now look closer at individual player performances. Before we begin though, it is important to underline that Stratagem’s data is a bit different than other sources, so please read the beginning of this post to be able to better understand the stuff I’m about to show.

Note: In some of the scatter plots below I’ve excluded what I deem to be outliers due to the small sample size.

Goalscoring

01.png

Scoring 4 goals against Sirius in the last match before the break, Djurgården’s Tino Kadewere tops the league in non-penalty goals at 8, overperforming his second place xG of 5.5. He has also gotten into most chances so far, showing some great form.

Another strong performance comes from Hammarby’s Pa Dibba, the speedy forward being one of the main reasons behind their attacking success. He leads the league in xG at almost 6 to go with his 7 non-penalty goals, but what really makes him stand out is his time-weighted performance, dominating with over 1 goal and 0.92 xG per 90 minutes played.

Nikola Đurđić has been the other focal point in Hammarby’s attack and the Serbian has been just what Hammarby needed. Besides goals, he has also brought grit and a mentality which has maybe been missing in Hammarby.

Romain Gall has impressed with 5 goals for Sundsvall, and will likely be on the radar of the bigger clubs for the upcoming transfer window. Interestingly, IFK Göteborg’s Giorgi Kharaishvili leads the league in Chances per 90 minutes.

02.png

Plotting goals and xG we see just how good Dibba has been so far, and also that compared to last season, a lot of players are running really hot and overperforming their xG numbers. There’s a sample size problem here of course, as we’ve only seen 10-12 matches per team but it will be interesting to see if it continues the same way after the summer break.

03.png

Looking at Player Attacking Styles we see how Dibba has been combining a lot of chances with a high average quality. Moberg-Karlsson, Paulinho and Kharaishvili have similiar chances per 90, but of considerably lower quality and hence have scored less goals. Inversely, Alhassan Kamara, Dino Islamovic, Carlos Strandberg and Đurđić have ended up in chances of roughly equal quality as Dibba, but less often, again having scored less goals. From the previous plot we see that Kamara and Strandberg also have efficiency problems compared to their xG but if they can keep their high average chance quality they should get the goalscoring running again soon, as they’re both usually very strong in front of goal.

Chance Creation

04.png

The creators behind the chances then? Well, Örebro’s Nahir Besara is as usual up there when it comes to assists, as is Ken Sema of Östersund. Hammarby’s Jiloan Hamad has had a strong season so far as well, being one of the main driving forces behind Hammarby’s attack. Tino Kadewere shows his versatility by producing 5 assists to add to his goals, though it is worth mentioning that two of these are rebounded shots. Another attacker showing some creativity is Đurđić who’ve created over 3 xA so far.

Adjusted for minutes played we see that old boy Tobias Hysén is still important to IFK Göteborg’s chance creation, and that Östersund’s Hosam Aiesh has created most xA per 90 at about 0.5. The small sample size sees Brommapojkarna’s Marko Nikolic make the list with his 2 assists from 340 minutes played.

Häcken’s Daleho Irandust is one of the most frequent creators, leading the league in Chances Created per 90, ahead of Arnor Traustason and Alexander Jakobsen of Malmö and Norrköping, respectively.

05.png

Plotting actual and expected assists, we again see a lot of overperformance which is of course linked to what we saw with the goals earlier. Malmö’s Markus Rosenberg has been one of the most notorious under-performers against xG in my models for years, but here he interestingly shows up underperforming xA instead. This of course has a lot to do with the sample size, but also indicating that he has switched role in Malmö’s attack a bit, and that his teammates haven’t been that clinical when he’s set them up with chances.

06.png

Looking at how the players create chances, we see how some like Irandust, Jakobsen and Traustason focus on volume, while Đurđić, Kalmar’s Måns Söderqvist and Nahir Bahoui of AIK create chances less often, but of a higher quality. As with goals, the strongest producers like Besara, Hamad, Kadewere and Sema manage to combine both aspects when setting up their teammates. AIK’s Rasmus Lindkvist and IFK Göteborg’s Emil Salomonsson are the only defenders showing up here, both operating as wing backs in front of a 3-back line.

Attacking Production

07.png

Tino Kadewere dominates when it comes to raw numbers, leading the league in G+A, xG+A and Chance Production, but drops a bit when taking playing time into consideration as Djurgården’s lack of options up front has seen him play a lot of minutes.

Dibba and Đurđić again show up as strong producers, and Sundsvall’s Linus Hallenius also deserves a mention being third in G+A per 90 and fifth in xG+A per 90. Norrköping’s young icelander Arnór Sigurdsson has also impressed with over 0.6 xG+A per 90, as has AIK’s Anton Salétros, whose fine performance and 0.84 G+A per 90 earned him a move to Rostov in the Russian league.

08.png

Naturally we see a lot of overperformance when combining goals and assists as well, and we should expect to see some of these players’ output to normalize over the season. Who that will be is of course a lot down to chance itself.

09.png

Plotting xG and xA we can get a glimpse of the production style of players. Dibba is of course the typical striker with a lot of xG but little xA created, while Aiesh seem to be the direct opposite. A strong group of players lead by Đurđić combine both execution and creation.

The small sample size is of course a problem and could be one of the reasons we see no real one-sided ‘role players’ besides Aiesh and Dibba yet. Sema, Traustason, Irandust and others should all belong to the more creative group but have for various reasons failed to create enough xA for it to show yet. On the other side of the scale, we know that Kamara, Strandberg and Kalle Holmberg are all strong strikers heavily focused on being at the business end of chances just like Dibba, but they’ve struggled a bit so far. It will be interesting to see how things develop over the season.

Player Profiles

T. Kadewere_chanceT. Kadewere_creation

I mentioned Tino Kadewere back in 2016, at the very end of this post. Since then, he’s missed much of 2017 to injuries and when fit struggled to get back to form. One of the reason for this is him having to adopt to a new role as the sole striker up front as goalscorer after goalscorer have left Djurgården. His display has been sometimes puzzling this season as he at least early on mixed insane misses and poor touches with equally jaw-dropping dribbles and smart play. As time has progressed though he’s looked better and better, being instrumental in Djurgården’s Swedish Cup win with 4 goals in 7 matches, to add to his 8 in Allsvenskan. Previously used as more of a creative support attacker he has now evolved into a centre forward with impressive hold up play and a presence in the box, which is evident from his very good chance locations. Add his creative side and it’s no wonder he’s rumoured to be on the radar of clubs abroad.

P. Dibba_chance.png

Pa Dibba has impressed as well, and though usually applauded for his speed and counter-attacking skills adding a dimension to Hammarby’s attack, he has some very useful skills poaching in front of goals on crosses and set pieces as well, as can be seen from the 3 high-quality chances close to goal.

N. Đurđić_chanceN. Đurđić_creation

Nikola Đurđić’s return to Allsvenskan (10 goals in 11 matches for Helsingborg in 2012 and 5 in 12 for Malmö in 2015) is another reason for Hammarby’s success so far. Overperforming his xG a bit, he has still gotten into some very good chances and brings a lot of overall quality as well, creating high quality chances for his teammates. As mentioned he has also brought in a kind of grit and mentality that I think has been missing in Hammarby for quite some time.

R. Gall_chance

Sundsvall’s Romain Gall has been one of the most in-form players so far and could be on his way to a bigger club soon. As can be seen from the above plot though, his 5 goals is a bit flattering compared to his xG, but if he can get the right coaching and learn to be a bit more selective when it comes to chance locations, I think he could grow into a very strong winger.

N. Besara_chanceN. Besara_creation

Just like last season, Nahir Besara has been the driving force behind Örebro’s attack. Possibly limited a bit by Axel Kjäll’s more cautious approach, he has still had an impressive spring. Combining some good quality chances inside the box with efficient long-range shoot and strong passing foot, it’s tempting to think about what he could do at a bigger club.

D. Irandust_creation

Daleho Irandust is Allsvenskan’s most frequent creator, third in raw quantity and leading the league in chances created per 90, but what good does that do when his teammates simply refuse to score? Not super high average chance quality though but given time and his undeniable talent, assist will come.

J. Hamad_chanceJ. Hamad_creation

Jiloan Hamad is the main creator in Hammarby’s midfield, being the driving force behind much of their attack. He can score as well and his strong season so far saw him involved in the discussions for Sweden’s World Cup squad, though he was eventually left out.

K. Sema_creation

Another strong creator who was in contention for the Swedish squad is Ken Sema. Though not yet as impressive as last season, he has been creating chances for Östersund  this spring and his strong performance in the Europa League could very well earn him a move abroad soon as quite a few players could be leaving the club after Graham Potter’s departure.

C. Strandberg_chance

Arguably one of the best strikers in the league, Carlos Strandberg has, just like all of Malmö, struggled so far. Still getting into great chances and scoring goals, he is lacking a bit in volume though and will need to get up to speed and improve a lot if Malmö are to climb the table after the summer break. He has a great left foot and should shoot more, in my opinion.

R. Lindkvist_creation

Left wing-back Rasmus Lindkvist has been a big part of AIK’s attack with his 4 assists and 12 chances created so far. Interestingly, he doesn’t use his wide position to whip in crosses, instead using his good pace and passing foot to combine his way into the box where he sets up his teammates in front of goal, which seems to work out quite well for him.

If you want to see any more Player Chance/Creation Maps, just let me know on Twitter.

This article was written with the aid of StrataData, which is property of Stratagem Technologies. StrataData powers the StrataBet Sports Trading Platform, in addition to StrataBet Premium Recommendations.

Advertisements
Allsvenskan 2018 Summer update 2

Allsvenskan 2018 Summer update

Allsvenskan is on a break waiting for the World Cup, and so am I – so why not write a quick recap of the action so far? Well I hadn’t planned on it, but with this first part of the season being far more interesting than what we’ve seen in a long time, I simply couldn’t resist.

01

The number of matches played are a bit unevenly distributed so far, with Malmö, AIK and Djurgården all having played one extra match each to give room for the European qualifiers later this summer, while Sirius‘ season opener against Sundsvall was postponed due to poor pitch conditions.

The main (and I mean MAIN) narratives so far have been Malmö’s fall from grace and Hammarby‘s surprisingly flying start to the season. A mini narrative this season is also Östersund with their poor start, criminal investigations into chairman Kindberg‘s business and manager of the year for the last two seasons, Graham Potter, leaving to take over Swansea in the Championship.

Title defenders Malmö very disappointingly sit in 10th and are nowhere near their usual standard which has seen them claim the top spot 4 times in the last 5 seasons. Magnus Pehrsson was under a lot of pressure early on and after failing to bounce back after the 3-0 defeat to Djurgården in the Swedish Cup final, he was soon fired.

Hammarby on the other hand got off to a great start, winning 8 and drawing once before finishing with their first defeat of the season (against rivals AIK) and another draw. For a team that finished 9th last season, looked quite poor, sacked their manager and promoted his assistant in a move that looked like a huge gamble, this is surprising even for Allsvenskan. Fair play to Hammarby and Stefan Billborn though, they have undeniably been the best team so far, playing a very entertaining attacking football.

That said, let’s get on with some scatterplots:

02

Looking at chances we can see that Hammarby spend a lot of time attacking, while at the same time limiting their opponents. Häcken does a good job as well, and Malmö actually don’t look too bad quantity-wise. AIK is a curious case with Rikard Norling as usual having his side focus more on game control than chance dominance, limiting their attack even more than last season. A bottom quartet of Dalkurd, Trelleborg, Sirius and Brommapojkarna can be easily distinguished here, with especially promoted BP looking really poor when it comes to raw chance numbers, facing a whopping 17 chances per match.

03

Hammarby have been effective in front of goal, which when combined with their many chances of course is a big part of their impressive run so far. Malmö and Häcken on the other hand have seen their good numbers spoiled by some ineffective finishing, while AIK’s effectiveness has compensated for their low quantity and allows them to aim for the top. Brommapojkarna’s performance is dismal here as well, and we can also note that IFK Göteborg worryingly combine low chance quantity with ineffective scoring.

04

Looking at defensive effectiveness we see how Hammarby are actually quite poor, proving the point that their success is mostly down to their impressive attack. Malmö and Östersund look surprisingly bad as well, on par with bottom teams Sirius and Dalkurd. Had they defended better they would have gone into the summer break with far more confidence of a top 3 finish, and I don’t even want to think about how Hammarby would look if they get their defense in shape.

AIK is of course the master defenders, handling the few chances faced very effectively, as is Norling’s trademark. As we’ve seen though, they’ve done so by giving up some attacking ambition, relying more on effectiveness in front of goal. There could be a fine line between success and utter failure with this approach but I suspect AIK to be in the race for the title up until November.

Bottom placed Sirius look really poor defensively and as usual they are plagued by injuries as well. They’ve also had to start with their goalkeeping coach a few matches as their only fit goalkeeper was suspended after a cocaine-related offense, which certainly didn’t make things easier. Brommapojkarna’s defensive effectiveness look OK but they still face way too many chances to avoid being involved in the relegation battle.

Lastly, Örebro have dramatically improved their defense under new manager Axel Kjäll, going from around 7.5 chances faced per goal conceded last season, to almost 12 so far. They still face a lot of chances but defend these well, looking very much to have a deliberate strategy to defend the box and let the opposition bomb away from poorer chance locations.

05.png

Looking at the Expected goals scatter we see just how different Hammarby and AIK’s approaches are. Interestingly, this fits very well with the traditional values of the clubs with AIK focusing a lot on a solid defense looking for a controlled 1-0 win while Hammarby attack head on carefree, not minding conceding a goal or two as they can always score more if needed.

Besides the top 2 teams, there seems to be some clustering going on xG-wise. A group of 5 clubs including Malmö and Djurgården look to be in contention for a top 3 spot with average or better defenses and strong attacking, while a roughly average quartet are lead by Örebro. Lastly, we see how the bottom quartet is actually a quintet with Sundsvall also showing poor underlying performances in both ends of the pitch.

06

The clustering shows up when looking at Expected Goals Difference as well, also showing that Häcken is actually on par with AIK and that Östersund is slightly worse than the other top 3 contenders. Sirius are just bad.

How about a prediction then – will the main narratives continue or will Malmö regain their form and will Hammarby drop back to their former mediocrity? Who will be relegated? Well, even if I wanted to make a prediction, we’ve seen just a bit more than one third of the season so far and there’s still a lot to come, including a very interesting transfer window which could see most clubs look very different come mid August. The only thing I can say is that the remainder of the season could very well get even more interesting than what we’ve seen so far.

That’s it for now, but I will hopefully be back soon with an update on individual player performances.

This article was written with the aid of StrataData, which is property of Stratagem Technologies. StrataData powers the StrataBet Sports Trading Platform, in addition to StrataBet Premium Recommendations.

Allsvenskan 2018 Summer update

Allsvenskan 2017 Summary Part 2

Alright, after my last post discussing team performance for the 2017 season it’s now time to dig deeper into Stratagem‘s great dataset and have a look at individual players.

As usual, it’s important to remember that Stratagem collects chances, not shots and also this: only one chance per attacking play is recorded. So for example if a team forces a goalkeeper to a series of saves in a single attack, only the highest rated chance (or a goal if it was scored) is recorded – this of course makes much sense as you can only score a maximum of one goal per attack.

Another difference from most data collectors is that whenever a blocked or saved shot rebounds and leads to a new chance, Stratagem credits the original shooter with an assist for his part in ‘creating’ this new chance. It’s important to note though that this only happens if the rebound chance happens to be of a higher quality than the original chance or end up as a goal, due to the above rule of only one chance per attack.

Lastly, when it comes to minutes played I’ve taken some time to try to calculate it as correctly as possible to get a better look at players ‘true’ performance. Sites like Soccerway seems to set their maximum playing time per match to 90 minutes which is of course wrong as there’s usually a lot of injury time to consider, sometimes even in the first half. So for this post with injury time in both halves taken into consideration you’ll see players which have played more than 30 units of 90 minutes and this also means that most players will see their per90 stats slightly diminished.

All data is open play chances, i.e. penalties are excluded for this post.

But enough of that, let’s get to it and have a look at some numbers. As usual I’ll just throw some plots at you together with my spontane thoughts:

Goalscoring

01Though sharing honors as the league top scorer at 14 with Magnus Eriksson, the moral winner is Norrköping’s Kalle Holmberg with 13 open play goals while 5 of Eriksson’s goals came from penalties. Eriksson’s 9 open play goals is still very impressive though, seeing him finish joint second together with a group of strong goalscorers, all forwards – while Eriksson has mainly been used in midfield in Özcan Melkemichel’s Djurgården.

Another impressive performance comes from AIK’s Nicolas Stefanelli who managed to reach 9 open play goals despite only arriving during the summer, resulting in him topping the league when it comes to goals scored per 90 minutes. Versatile Bjørn Paulsen‘s 8 goals are equally impressive as he’s been used in both central midfield and defence alongside his starts up front for Hammarby.

Tobias Hysén shows that he’s still to be reckoned with, producing the highest total xG in the league at age 35. I’ve been waiting for his performance to drop for some years now, will he surprise me again next season?

The lack of any real xG per 90 Wizard this season (besides Stefanelli, maybe) sees some surprising names break into the immediate top. Johan Bertilsson, Skhodran Maholli (though he enjoyed an initial strong start to his arrival at Sirius) and Linus Hallenius comes to mind. Impressive of course, but it should be noted that this Allsvenskan season has been lacking the strong goalscoring box-player poacher type like pasts seasons’ Kjartansson, Owoeri and Kujovic. Kalle Holmberg could’ve been that player but IFK Norrköping’s weak end to the season has certainly limited his output to more normal levels.

Eflsborg’s Issam Jebali was the end point of most chances for the season, but when playing time is taken into consideration, AIK’s Nicolas Stefanelli once again reigns supreme.

02Comparing goals and xG we see that Stefanelli’s output isn’t that much better than expected, he could very well be the real deal. Another interesting point is that Malmö’s captain Markus Rosenberg continues to underperform against xG.

03.pngLooking at how many chances players create and the average quality of those chances should give us at least some sense of their preferred attacking styles. We see here how most strong attacking players tend to cluster around an area of compromise between quality and quantity. In this group, Viktor Prodell, Johan Bertilsson, Henok Goitom and Mohamed Buya Turay tend to rely more on high quality chances (all above 0.20 xG per chance), while David Moberg-Karlsson and Stefanelli prefer to just rack up chance after chance, the latter with some respectable xG per chance as well.

Moses Ogbu is an extreme outlier with over 0.30 xG per chance, explained in part by the fact that he only took part in Sirius’ very strong first half of the season before getting injured. Still a very interesting player, his numbers would likely have dropped a bit had he been fit to play when Sirius struggled (including 7 straight losses) in the second half of the season.

Chance Creation

04.pngElfsborg’s Simon Lundevall provided most assist overall but taking playing time into account, IFK Norrköping’s Niclas Eliasson was Allsvenskan’s main creator this season. Racking up 11 assists in the first half of the season before leaving for Bristol City in the Championship, his departure effectively ended Norrköping’s top 3 ambitions.

Magnus Eriksson, Tobias Hysén and Nahir Besara‘s appearance in the Assists Top 10 really shows their versatility and huge importance to their teams’ overall attack.

Just like seen with goals above, some interesting and perhaps surprising names appear when we account for playing time. I certainly didn’t expected to see Sirius’ Elias Andersson or AFC Eskilstuna’s Andrew Fox here, but there you go.

Ken Sema‘s strong finish to the season saw him (besides earning a call-up to ‘Party-‘ Janne Andersson’s national team which beat Italy to advance to the World Cup) top the Expected Assists table at roughly 11, though 3 less than his actual output. Sema has also been performing well in Östersund’s Europa League campagin and is one of many players they’ll have to work hard to keep over the winter transfer window.

Nostalgic as I am, it’s certainly nice to see my boyhood hero Kim Källström racking up some strong numbers placing him in the Top 10 Assists and xA tables, as well as creating most chances in the league overall and 4th most when taking playing time into consideration.

05.pngComparing assists and xA we see how Niclas Eliasson has been outperforming his expected output (likely thanks to some effective scoring from Kalle Homberg) while Ken Sema has been underperforming. Lundevall is closer to his expected output.

06.pngJust like with the Attacking Styles, Player Chance Creation Styles are mostly clustered with a lot of creative players combining reasonable quality with quantity. Ken Sema, Elias Andersson and Yoshimar Yotún (who left Malmö for the MLS in the summer) are the extremes when it comes to creation volume, while Andreas Vindheim has created some very good chances for Malmö.

Attacking Production

07.pngBy combining goals and assists into Attacking Production we see that Besara was the most productive player when it comes to raw numbers, but when factoring in playing time, Stefanelli once again tops the table in both expected and actual output. Prodell has done well considering his playing time, as well as Malmö’s Alexander Jeremejeff who’s second behind Stefanelli in xG+A per 90 minutes.

Djurgården’s both wingers break into the Total Chance Production table, with Othman El Kabir joining Eriksson just below the top trio. Paulinho was the most productive attacking player though, creating over 5 chances per 90 minutes for Häcken.

08.pngLooking at actual and expected output, we see how most strong attacking players like Besara, Jebali, Homberg, Eriksson, Hysén and Stefanelli tend to perform close to what we can expected. Eliasson is again overperforming while Rosenberg is doing the opposite. Eric Larsson is worth a special mention here as he has produced some fine numbers for a fullback, with his underperformance coming largely from his teammates in Sundsvall underperforming on the chances he created for them.

09.pngSeperating Expected Goals and Expected Assists let us see how the attacking players specialise. Once again we see how this season has really lacked many strong specialist, with only Stefanelli and Sema really standing out on their ends. Most players tend to cluster somewhat here as well, combining creativity with being at the end of chances as well.

Player Profiles

As I now work with StrataData, I’d thought I’d do a total revamp of the popular player maps. The style is more or less shamelessly stolen from a range of other analysts, no names mentioned, and now also include Chance Creation Maps:

K. Holmberg_chanceAs mentioned earlier, Kalle Holmberg was this season’s strongest goalscorer, and from his Chance Map it’s easy to see why: he usually gets into some very good positions just in front of goal, with an average xG of 0.19 per chance. 13 open play goals is strong, but as I’ve also mentioned I think he could’ve done even better had IFK Norrköping’s performance not dropped (and Niclas Eliasson not left).

M. Eriksson_chanceM. Eriksson_creationOperating from Djurgården’s right wing, Magnus Eriksson was another strong goalscorer this season, though a bit more versatile as he also provided a lot of assists for his team. Mostly crosses from the right flank but also two shot rebounds. His Chance Map is a bit different from Holmberg’s with more chances outside the box, which is only natural as he’s after all a midfielder. Though attacking is certainly his main quality, Djurgården will also miss his work ethic, grit and competitiveness now that he’s left for the MLS.

T. Hysén_chanceT. Hysén_creationVeteran Tobias Hysén continues to be extremely important to IFK Göteborg’s attack. His Chance Map combines a lot of good chances inside the box with some poorer outside, some of them direct free kick. When it comes to Chance Creation he’s provided some crucial passing inside and into the box, as well as some corners and free kicks.

N. Besara_chanceN. Besara_creationÖrebro’s Nahir Besara was also extremely important to his team’s attack, combining some chances inside the box with a lot of shooting from outside, including one goal from a direct free kick. His creation numbers are boosted by three rebounds who turned into goals, otherwise it’s mostly corners and crosses into the box.

N. Stefanelli_chanceNicolás Stefanelli arrived at AIK at a crucial time this summer, with the team’s attack struggling during the first half of the season. The Argentinian took some time to adopt but slowly turned into to a real strong presence up front, scoring 9 goals from 14 starts. It will be very interesting indeed to see if he can continue his fine performance come the new season. As a Djurgården supporter, I sure hope not.

L. Hallenius_chanceLinus Hallenius is an interesting case that’s flown under at least my radar this season. With 7 goals and nearly 10 xG he’s done well for a struggling Sundsvall side that just barely managed to stay up. Most of his chances have been created by Eric Larsson, so it’ll be very interesting to see if Hallenius can continue his fine performance next season with the right back having left for champions Malmö.

S. Lundevall_creationElfsborg’s Simon Lundevall was the assist king this season at 12, with 4 of them coming from corners, curiously with some rather high xA values – 3 of them are above 0.30 xA. Maybe Elfsborg have some corner strong routine going on? Lundevall has also provided some long range passes on the left half of the pitch, which I guess is related to counter-attacking.

N. Eliasson_creationNiclas Eliasson’s strong first half of a season earned him a move abroad, and as mentioned earlier IFK Norrköping never really looked the same after that. Overperfoming, sure, but he did create some really good chances for his team with his precise crossing from both flanks.

K. Sema_creationKen Sema was another creation monster, racking up some really good chances with an average xA per chance of 0.18. It’s clear to see why, as most of his passes was either directly inside the box, or ending up in it – a direct consequence of Östersund’s heavily passing-oriented style of attack.

K. Källström_creationThough it stopped at just one season before he chose to end his career, Kim Källström’s long-awaited return to Djurgården was (despite some very inconsistent perfomances) instrumental in returning the team he once won the league with in two consecutive seasons at the start of the millenium, back to the top 3. When he was at his best this season, sitting back in his deep-lying playmaker role he dictated much of Djurgården’s attack with his quarter-back ‘Hail Mary’ style of long passing. Interestingly though, all his assists came from set pieces where he got more time to use his precise left foot.

E. Larsson_creationI mentioned Eric Larsson before and looking at his Chance Creation Map we see clearly how strong a player he is. From his right back position at struggling Sundsvall he produced 52 chances and well over 6 xA – more than most midfielders. Though his teammates only managed to score twice on these chances, with his move to Malmö I expect him to get a lot more assists next season.

That’s it, thank you for reading the whole piece. If you want to see any more Player Chance/Creation Maps, just let me know on Twitter.

This article was written with the aid of StrataData, which is property of Stratagem Technologies. StrataData powers the StrataBet Sports Trading Platform, in addition to StrataBet Premium Recommendations.

Allsvenskan 2017 Summary Part 2

Allsvenskan 2017 Summary

With the end of the Swedish football season I’m now on vacation, and thus have time to do some writing. I haven’t written anything for a while and have especially avoided football since I’m biased with my work involving taking bets on the Swedish leagues. If I say Team X is underrated and should have a good chance of picking up some points in the future, why would you believe me, when I profit from your losses? Once the new season starts I’ll likely crawl back under my rock again, but for now, let’s get to it: Allsvenskan 2017 Summary!

Before we start though, I’d like to point out two things: a) most of the graphics shown below are very much inspired by (or more or less copied from) the great Ben Mayhew at Experimental 361, and b) the data used is from my good friends at Stratagem, for which I used to cover Norwegian Eliteserien and collect stats watching matches. You’ll find more information about Stratagem and their products at the bottom of this piece.

So, Allsvenskan 2017 it is then. First let’s have a look at the final table, once again topped by Malmö who managed to defend their title from last season, making it their 5th since 2010.

01

To my own personal joy, Djurgården finally returned to the top 3 for the first time since 2007, grabbing the last European qualifier spot in the process. Much hyped Östersund also managed to climb from last season’s 8th place, at the same time adding a very impressive run in the Europa League. Häcken have also improved (with new manager Stahre now leaving for the MLS), while Norrköping, IFK Göteborg and Elfsborg have all dropped somewhat. Of the three newcomers, only Sirius managed to stay up, reaching an impressive 7th place after a strong spring and a weaker autumn. Besides Halmstad and AFC Eskilstuna, Jönköpings Södra were also relegated via play-off against the 3rd placed team in Superettan, Trelleborg.

Let’s dig deeper by looking at some scatterplots (note: as I now use data from Stratagem, shots have turned into chances as this is what they collect. For more info, read this blog by Dave Willoughby).

02

Right away we can see part of why Malmö have dominated the season, as they create far more chances than the rest while at the same time keeping a tidy defense and facing fewest chances in the league. There’s quite some distance to the other top teams and interestingly IFK Göteborg seems to have done better chance-wise than the table suggests.

At the other end of things, AFC Eskilstuna stands out as a really poor team with the lowest number of chances created coupled with the highest number of chances faced per match. Jönköpings Södra also stand out a bit, with quite low numbers on both scales indicating some very boring matches (which I can confirm).

03

Looking at attacking effectiveness  we see how the top teams were efficient with their many chances created, while bottom teams like Sundsvall and relegated Halmstad both struggled to create and to capitalise on their chances. A curious case is Elfsborg who were the most efficient scorers, needing less than 7 chances per goal, while at the same time failing to create enough chance volume to compete with the top teams.

04.png

When it comes to defensive effectiveness, AIK and Häcken really stands out with around 13 chances faced per goal conceded, compared to the league average just under 9. Followers of Allsvenskan won’t be surprised to see AIK in the top here as a tight defense has been a cornerstone of the club for a long time. Häcken though, have really been transformed from a care-free attacking-minded side under Peter Gerhardsson, to a more cynic and well-structured defensive side under departing (and former AIK manager) Mikael Stahre. It will be very interesting to see who replaces him and what direction the club will take in the future.

Another interesting point to make is that as affective as they are on the attack, Elfsborg are equally ineffective when defending. With the third most goals scored and most conceded, the Borås side have certainly been entertaining to watch this season.

05

When it comes to Expected Goals, champions Malmö are closely followed by AIK, with Östersund and Djurgården some distance away. AFC Eskilstuna and Elfsborg were the two poorest defenders with around 2 xG conceded per match. I wonder how Elfsborg would have done without their effective scoring?

06

Rating the teams by Expected Goal Difference sees really how close AIK were to Malmö, whose ability to win close matches seems to be a big factor in their title win this season. At the bottom AFC Eskilstuna clearly deserved to be relegated with the worst xG difference, as did Halmstad while Jönköpings Södra maybe deserved a better fate than to be relegated via play-off.

That’s it for now, next up I’m hoping to have a look at individual player’s performance.

This article was written with the aid of StrataData, which is property of Stratagem Technologies. StrataData powers the StrataBet Sports Trading Platform, in addition to StrataBet Premium Recommendations.

Allsvenskan 2017 Summary

Stake sizing, Part 1

In the last post we used Python code to take a look at a classic gambling situation, the coin flip, to make a point about the importance of choosing the highest odds available to bet at. Today, we’ll again use the coin flipping example to investigate another fundamental principal of successful gambling: stake sizing.

Now, imagine we’re one of the lucky punters from the last post who were allowed to bet on a fair coin flip at odds of 2.03. As I stated then, this is pretty much like a license to print money – but how much of your bankroll should you bet on each flip of the coin? Knowing that the coin was indeed fair and you would be getting the best of it, a natural instinct could be to bet as much as you could possibly cough up, steal and borrow in order to maximize your profit. This is a poor strategy though, as we’ll soon come to see.

The reason for this is that even if we do have come across a profitable proposition, our edge when betting at a (I’ll empasize it again: fair) coin flip at 2.03 odds is only 1.5% – meaning that for each 1 unit bet we are expected to net 0.015 units on average. This conclusion should be absolute basics for anyone interested in serious gambling, but to make sure we’re all on the same page I’ll throw some maths at you:

The Expected Value, or EV, of any bet is, simply put, the sum of all outcomes multiplied by their respective probabilities – indicating the punter’s average profit or loss on each bet. So with our coin flip, we’ll win a net of 1.03 units 50% of the time and lose 1 unit 50% of the time; our EV is therefore 1.03 * 0.5 + (-1 * 0.5) = 0.015, for a positive edge of 1.5% and an average profit of 0.015 units per bet. For these simple types of bets though, an easier way to calculate EV is to divide the given odds by the true odds and subtract 1: 2.03 / 2.0 – 1 = 0.015.

An edge of only 1.5% is nothing to scoff at though, empires has been built on less, so we’ll definitely want to bet something – but how much?

Stake sizing is much down to personal preferences about risk aversion and tolerance of the variance innately involved in gambling, but with some Python code we can at least have a look at some different strategies before we set out to chase riches and glory flipping coins. Just like in the last post I’ll just give you the code with some comments in it, which will hopefully guide you along what’s happening  before I briefly explain it.

Here we go:

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns

def coin_flips(n=10000,odds=1.97,bankroll=100,stake=1,bankrupt=False):
    '''
    Simulates 10000 coinflips for a single punter, betting at 1.97 odds,
    also calculates net winnings

    NEW: default bankroll and stake set at 100 and 1, respectively
    now also calculates if player went bankrupt or not
    '''

    # create a pandas dataframe for storing coin flip results
    # and calculate net winnings
    df = pd.DataFrame()
    # insert n number of coinflips, 0=loss, 1=win
    df['result'] = np.random.randint(2,size=n)
    # calculate net winnings
    df['net'] = np.where(df['result']==1,stake*odds-stake,-stake)
    # calculate cumulative net winnings
    df['cum_net'] = df['net'].cumsum()

    # calculate total bankroll
    df['bankroll'] = df['cum_net'] + bankroll

    # if bankroll goes below the default stake, punter will stop betting
    # count times bankroll < stake
    df['bankrupt'] = np.where(df['bankroll']<stake,1,0)
    # count cumulative bankruptcies, with column shifted one step down
    df['bankruptcies'] = df['bankrupt'].cumsum().shift(1)
    # in case first flip is a loss, bankruptcies will be NaN, replace with 0
    df.fillna(0,inplace=True)
    # drop all flips after first bankruptcy
    if bankrupt:
        df = df[df['bankruptcies']==0]

    return df

First off, we’ll modify our original coin_flips function to take our punter’s bankroll and stake size into consideration, setting the bankrupt threshold at the point where a default sized bet can no longer be made. By default, our punter will have an endless stream of 100 unit bankrolls, but if we set the parameter bankrupt to True, the function will cut away any coin flips after his first bankruptcy.

def many_coin_flips(punters=100,n=10000,odds=1.97,bankroll=100,stake=1,color='r',plot=False,bankrupt=False):
    '''
    Simulates 10000 coinflips for 100 different punters,
    all betting at 1.97 odds,
    also calculates and plots net winnings for each punter

    NEW: now also saves punter bankruptcies
    '''

    # create pandas dataframe for storing punter results
    punter_df = pd.DataFrame()
    # loop through all punters
    for i in np.arange(punters):
        # simulate coin flips
        df = coin_flips(n,odds,bankroll,stake,bankrupt)
        # calculate net
        net = df['net'].sum()
        # check for bankruptcy
        bankruptcy = df['bankrupt'].sum()

        # append to our punter dataframe
        punter_df = punter_df.append({'odds':odds,
                                      'net':net,
                                      'bankrupt':bankruptcy},ignore_index=True)

        if plot:
            # plot the cumulative winnings over time
            df['cum_net'].plot(color=color,alpha=0.1)

    # check if punters ended up in profit
    punter_df['winning'] = np.where(punter_df['net']>0,1,0)

    return punter_df

We also want to modify the many_coin_flips function so that it’ll also take bankroll and stake size into consideration, counting up how many of our punters went bankrupt.

We won’t use the compare_odds function here, instead we’ll write a new one to compare stake sizing – but if we ever want to use it again sometime in the future a few minor changes will be needed here as well:

def compare_odds(punters=100,n=10000,odds=[1.97,2.00,2.03]):
    '''
    Simulates and compare coin flip net winnings
    after 10000 flips for 3 groups of punters,
    betting at odds of 1.97, 2.00 and 2.03, respectively.
    Also plots every punters net winnings
    '''

    # create figure and ax objects to plot on
    fig, ax = plt.subplots()

    # set y coordinates for annotating text for each group of punters
    ys = [0.25,0.5,0.75]
    # assign colors to each group of punters
    cs = ['r','y','g']

    # loop through the groups of punters, with their respective odds,
    # chosen color and y for annotating text
    for odd, color, y in zip(odds,cs,ys):
        # run coin flip simulation with given odds, plot with chosen color
        df = many_coin_flips(punters,n,odd,color=color,plot=True)
        # calculate how many punters in the group ended up in profit
        winning_punters = df['winning'].mean()
        # set a text to annotate
        win_text = '%.2f: %.0f%%' %(odd,winning_punters * 100)
        # annotate odds and chance of profit for each group of punters
        ax.annotate(win_text,xy=(1.02,y),
                    xycoords='axes fraction', color=color,va='center')

    # set title
    ax.set_title('Chances of ending up in profit after %s coin flips' %n)
    # set x and y axis labels
    ax.set_xlabel('Number of flips')
    ax.set_ylabel('Net profit')
    # add annotation 'legend'
    ax.annotate('odds: chance',xy=(1.02,1.0),
                xycoords=('axes fraction'),fontsize=10,va='center')
    # add horizontal line at breakeven point
    plt.axhline(color='k',alpha=0.5)
    # set y axis range at some nice number
    ax.set_ylim(-450,450)

    # show plot
    plt.show()

Now, with all our previous coin flip functions taking bankroll and stake size into consideration, we can go ahead and evaluate a few stake sizing strategies with a new function:

def compare_stakes(punters=200,n=10000,odds=2.03,stakes=[100,50,25,10,5,2,1,0.5],bankroll=100):
    '''
    Similar to compare_odds, but here we instead want to compare different
    staking sizes for our coin flips betting at 2.03 odds

    Increased number of punters in each group, from 100 to 200

    Also prints out the results
    '''

    # pandas df to store results
    results_df = pd.DataFrame(columns=['stake','win','lose','bankrupt'])

    # colors to use in plot later, green=1=win, yellow=4=lost, red=2=bankrupt
    colors = [sns.color_palette()[i] for i in (1,4,2)]

    # loop through the groups of punters, with their respective odds
    for stake in stakes:
        # run coin flip simulation with given stake
        df = many_coin_flips(punters,n,odds,stake=stake,bankrupt=True)
        # calculate how many punters in the group ended up in profit
        winning_punters = df['winning'].mean()
        # ...and how many went bankrupt
        bankrupt_punters = df['bankrupt'].mean()
        # lost money but not bankrupt
        lose = 1 - winning_punters - bankrupt_punters

        # append to dataframe
        results_df = results_df.append({'stake':stake,
                                        'win':winning_punters,
                                        'lose':lose,
                                        'bankrupt':bankrupt_punters},ignore_index=True)

    # set stake as index
    results_df.set_index('stake',inplace=True)

    # plot
    fig = plt.figure()
    # create ax object
    ax = results_df.plot(kind='bar',stacked=True,color=colors,alpha=0.8)
    # fix title, axis labels etc
    ax.set_title('Simulation results: betting %s coin flips at %s odds, starting bankroll %s' %(n,odds,bankroll))
    ax.set_ylabel('%')
    # set legend outside plot
    ax.legend(bbox_to_anchor=(1.2,0.5))

    # add percentage annotation for both win and bankrupt
    for x, w, l, b in zip(np.arange(len(results_df)),results_df['win'],results_df['lose'],results_df['bankrupt']):
        # calculate y coordinates
        win_y = w/2
        lost_y = w + l/2
        bankr_y = w + l + b/2

        # annotate win, lose and bankrupt %, only if >=2%
        if w >= 0.04:
            ax.annotate('%.0f%%' %(w * 100),xy=(x,win_y),va='center',ha='center')
        if l >= 0.04:
            ax.annotate('%.0f%%' %(l * 100),xy=(x,lost_y),va='center',ha='center')
        if b >= 0.04:
            ax.annotate('%.0f%%' %(b * 100),xy=(x,bankr_y),va='center',ha='center')

    plt.show()

By default, our new compare_stakes function creates a number of punter groups, all betting on fair coin flips at 2.03 odds with a starting bankroll of a 100 units. For each group and their different staking plan, the function takes note of how many ended up in profit, how many lost and how many went bankrupt.

As we can see on the plot below, the results differ substantially:

01

Just like last time, I want to remind you that any numbers here are only rough estimates, and increasing the size of each punter group as well as the number of coin flips will get us closer to the true values.

So what can we learn from the above plot? Well, the main lesson is that even if you have a theoretically profitable bet, your edge will account for nearly nothing if you are too bold with your staking. Putting your whole bankroll at risk will see you go bankrupt around 96% of the time, and even if you bet as small as 2 units, you’ll still face a considerable risk of screwing up a lucrative proposition. The truth is that with such a small edge, keeping your bet small as well is the way to go if you want to make it in the long run.

But what if some fool offered us even higher odds, let’s say 2.20? First off, we would have to check if the person was A: mentally stable, and B: rich enough to pay us if (or rather, when) we win, before we go ahead and bet. Here our edge would be 10% (2.2 / 2.0 – 1), nearly 10 times as large as in the 2.03 situation, so we’ll likely be able to bet more – but how much? Well, the functions are written with this in mind, enabling us to play around with different situations and strategies. Specifying the odds parameter of our new function as 2.20, here’s what betting at a fair coin flip at 2.20 odds would look like:

02

As can be seen from the new plot, with a larger edge we can go ahead and raise our stake size considerably, hopefully boosting our winnings as well. So the main take-away from this small exercise is that even if you have an edge, if you want to make it in the long run you’ll have to be careful with your staking to avoid blowing up your bankroll – but also that the larger your edge, the larger you can afford to bet.

That’s it for now, but I’ll hopefully be back soon with a Part 2 about stake sizing, looking at a staking plan that actually takes your (perceived) edge into account when calculating the optimal stake size: The Kelly Criterion.

Stake sizing, Part 1

Flipping coins, and the importance of betting at the highest odds

As I stated in the previous post, this blog will now focus more on gambling, using Python code to investigate whatever comes to my mind around the subject.

Today I’ll have a look at a classic gambling example – the flip of a coin – but before I go ahead and talk you through the code I want to state a few things that I know some of you will be wondering. Though R seems to be the language preferred by most in the football analytics scene, I have chosen Python simply because I feel it is so much more intuitive and easier to learn. RStudio seems to be the tool of choice for the R folks, but I don’t know of any real dominant counterpart for Python. I use Spyder, available through downloading Anaconda, mainly because it’s easy to use and comes with a lot of useful stuff pre-installed. If you’re thinking about testing it out yourself, I would suggest switching the color scheme of the editor to Zenburn for that dark and cool programming look that really make your code look super important, and run your scripts in the included IPython console.

One final, very important thing: I am not in any way an expert programmer, statistician, mathematician or anything like that. I am simply a gambler looking to use these fields to get an edge. It’s totally OK to simply copy and paste any code I publish here to use yourself and play around with it however you may wish. If you notice any mistakes or if something doesn’t add up, please comment. I’m happy to learn new stuff.

Flipping coins, and the importance of betting at the highest odds

The inspiration for this post came the other day when I noticed that a few hours prior to kick-off in this year’s Super Bowl, the bookmaker Pinnacle offered 1.97 odds on the opening coin flip. A sucker bet, I thought to myself, knowing the true odds of a fair coin to be 2.00. The coin flip is a very popular Super Bowl prop bet though and as it was pointed out to me on Twitter, a few books actually offered the fair odds of 2.00. Choosing the highest odds available is crucial if you want to make money gambling in the long run, so I decided to write up a nice little Python script to visualise my point.

The layout of these blog posts will be that I simply throw a piece of code at you, before explaining it. The comments in the code itself should also help you out, and for those of you who already know Python much will be simple basics, while those who’s completely new to coding or Python will hopefully learn a few things.

Here we go:

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns

def coin_flips(n=10000,odds=1.97):
    '''
    Simulates 10000 coinflips for a single punter,
    betting at 1.97 odds,
    also calculates net winnings
    '''

    # create a pandas dataframe for storing coin flip results
    # and calculate net winnings
    df = pd.DataFrame()
    # insert n number of coinflips, 0=loss, 1=win
    df['result'] = np.random.randint(2,size=n)
    # calculate net winnings
    df['net'] = np.where(df['result']==1,odds-1,-1)
    # calculate cumulative net winnings
    df['cum_net'] = df['net'].cumsum()

    return df

Allright, so after importing all the needed modules for this piece, we go ahead and define our first function, coin_flips, which will be used to simulate the coin flips and calculate the net winnings of a single punter. I’ve chosen 10,000 flips and Pinnacle’s odds of 1.97 as our default values here.

Creating a pandas dataframe, we can easily store the result of each coin flip. Now, as we assume that the coin is fair, there’s no need to even consider which side our punter would call each time, instead we can simply go ahead and use numpy to simulate a series of ones and zeros, representing either a win or a loss. Calculating the net result of each flip is also very straightforward as when he wins, our punter will pocket the net end of the offered odds, 0.97, while losing will see his pocket lightened by 1 unit. Calculating the cumulative net winnings is also very easy using pandas’ built-in cumsum function.

For coding reasons, the function is set to return the dataframe so calling it will simply make a lot of numbers pop up, but running the coin_flips()[‘cum_net’].plot() command in the IPython console will let you simulate a punter’s coin flips, and also plot his cumulative net winnings like this:

01

Every time you run the command another simulation will run with a new, different result. Doing this a couple of times, you’ll likely understand why I described this as a sucker bet. Sure, you can get lucky and win, even a couple of times in a row – but betting with the odds against you, you’ll find it very hard to make a profit long term.

But that single punter flipping coins 10,000 times actually doesn’t say that much, maybe he just got unlucky? To dig deeper we want to know just how likely you are to end up with a profit after 10,000 coin flips. So we write another function, using the previous one to simulate the results of many more punters betting on 10,000 coin flips. How many do you think will end up in profit?

def many_coin_flips(punters=100,n=10000,odds=1.97,color='r'):
    '''
    Simulates 10000 coinflips for 100 different punters,
    all betting at 1.97 odds,
    also calculates and plots net winnings for each punter
    '''

    # create pandas dataframe for storing punter results
    punter_df = pd.DataFrame()
    # loop through all punters
    for i in np.arange(punters):
        # simulate coin flips
        df = coin_flips(n,odds)
        # calculate net
        net = df['net'].sum()
        # append to our punter dataframe
        punter_df = punter_df.append({'odds':odds,
                                      'net':net},ignore_index=True)

        # plot the cumulative winnings over time
        df['cum_net'].plot(color=color,alpha=0.1)

    # check if punters ended up in profit
    punter_df['winning'] = np.where(punter_df['net']>0,1,0)

    return punter_df

The slightly more complicated many_coin_flips function uses the earlier coin_flips to loop through a group of punters, 100 by default, and save their results into a new pandas dataframe, punter_df, where we’ll assign a 1 to all punters who ended up in profit while all the losers get a 0. We also plot each punters cumulative net winnings with a nice red color to symbolise their (very) likely bankruptcy.

This function also returns a dataframe so running it will again make a lot of numbers pop up in the console, but it also plots out the financial fate of each punter, like this:

02.png

As we can see, there actually are a few of our 100 punters who got lucky enough to end up winning after 10,000 coin flips. But most of them ended up way below the break-even point, losing a lof of money. If this was a real group of punters we can only hope that even if they were stupid enough to set out betting on 10,000 coin flips at these odds, they’ll at least at some point realise their mistake and quit.

But how about if we change the offered odds? As I mentioned earlier, some books actually put up the fair odds of 2.00. How would 100 punters do after 10,000 coin flips betting at those odds? Well, we’ll have to write a new function for that. Also, just for fun (or to make a point) I’ve included an additional group of 100 punters lucky enough to be allowed to bet on the coin flips at odds of 2.03 – literally a license to print money.

def compare_odds(punters=100,n=10000,odds=[1.97,2.00,2.03]):
    '''
    Simulates and compare coin flip net winnings
    after 10000 flips for 3 groups of punters,
    betting at odds of 1.97, 2.00 and 2.03, respectively.
    Also plots every punters net winnings
    '''

    # create figure and ax objects to plot on
    fig, ax = plt.subplots()

    # set y coordinates for annotating text for each group of punters
    ys = [0.25,0.5,0.75]
    # assign colors to each group of punters
    cs = ['r','y','g']

    # loop through the groups of punters, with their respective odds,
    # chosen color and y for annotating text
    for odd, color, y in zip(odds,cs,ys):
        # run coin flip simulation with given odds, plot with chosen color
        df = many_coin_flips(punters,n,odd,color)
        # calculate how many punters in the group ended up in profit
        winning_punters = df['winning'].mean()
        # set a text to annotate
        win_text = '%.2f: %.0f%%' %(odd,winning_punters * 100)
        # annotate odds and chance of profit for each group of punters
        ax.annotate(win_text,xy=(1.02,y),
                    xycoords='axes fraction', color=color,va='center')

    # set title
    ax.set_title('Chances of ending up in profit after %s coin flips' %n)
    # set x and y axis labels
    ax.set_xlabel('Number of flips')
    ax.set_ylabel('Net profit')
    # add annotation 'legend'
    ax.annotate('odds: chance',xy=(1.02,1.0),
                xycoords=('axes fraction'),fontsize=10,va='center')
    # add horizontal line at breakeven point
    plt.axhline(color='k',alpha=0.5)
    # set y axis range at some nice number
    ax.set_ylim(-450,450)

    # show plot
    plt.show()

This last function makes use of the two previous ones to simulate the coin flips of our three groups of punters, plotting their total net winnings all on the same ax object, which we later make use of to add a title and some nice labels to the axes. We also add a horizontal line to be able to better compare the punters’ winnings with the break-even point, as well as some text annotation to explain the colors of the three groups.

Now, running the compare_odds() function in the IPython console will hopefully result in something like this:

03

Here we clearly see just how important betting at the highest odds really is. Have in mind though that the numbers to the right are only rough estimates. As you can see, the yellow group of punters who bet at the fair odds of 2.00 did not win exactly 50% of the time, but close enough. I actually had to re-run the function a few times to get this close. But it’s only natural since we only had 100 punters, a very small number in this context, in each of our groups. The more punters and coin flips we use in our simulations, the closer we’ll come to the real win percentages – but here speed is more important than super accuracy.

So as we clearly see in the above plot, betting on the coin flip at Pinnacle’s 1.97 odds really is a sucker bet, albeit an entertaining one if you were planning to watch the Super Bowl. But if you hope to make a profit from your betting, finding the highest available odds to bet on is crucial, as is shown by the green group of punters who were allowed to bet at odds of 2.03. It’s only a difference of 0.06, but it makes all the difference in the long run. The margins in betting are tiny, but they add up over time.

The lessons learned here can easily be transferred to sports betting in general and football betting in particular, were the Asian Handicaps and Over/Under markets focus on odds around even money. The coin flip example is special though as we knew the true odds of the bet beforehand, something you’ll never be able to know betting on football. But as shown in the last plot, by consistently betting at the highest available odds, you at least give yourself a much better chance of ending up in profit.

Flipping coins, and the importance of betting at the highest odds

With a new season approaching, the blog changes course: Gambling, probability and programming!

As you may have noticed, I haven’t written anything in months. There’s two reasons for this, one being of course that the Swedish football season I’ve primarily focused on ended in November, but it’s also because I’ve taken on a new job. Working full time for the first time in my life has simply left me with little time to do any writing. (Yes, I did use the word time three times in that short sentence.)

But now, having settled in at the new job I’m anxious to get back to writing again. There’s one thing though: as I now work with compiling odds on Swedish football I wouldn’t feel comfortable publishing football analytics about Allsvenskan, telling you which teams are underrated and who’ll win the league title. And knowing I set the odds, and potentially profit from your mistakes, why would you believe anything I said?

So this blog will take on a slightly new focus: gambling. I originally set up the blog intending to write about this topic as well as football analytics, using maths, statistics, probability and psychology to discuss interesting things related to gambling, but the football part soon took over completely.

As I’ve published my football work on the blog I’ve now and then gotten some questions about programming, so I’ve taken the decision to include Python code whenever applicable. Learning to code has made a huge difference for me both in my gambling and football analytics endeavours, and though the blog won’t turn into a Python tutorial per se, if any of you who are new to programming should learn a new thing or two through my writing, I’d be glad.

I’m still hoping to write the occasional football analytics piece though, and if I do it’ll likely be for StrataBet, using their data as I did when I had a look at headers in Allsvenskan and Norway’s Tippeligaen.

That’s it for now, but I already have a new post in the works, coming up very shortly!

With a new season approaching, the blog changes course: Gambling, probability and programming!