Post Season Wrap – 2018

I haven’t posted too much here during the AFL season, mainly, since I had bedded down the updated systems and was able to continue things as normal through the season there wasn’t too much too discuss about the back-end. But now as the season has wrapped up and the dust has settled it is of course time to reappraise and reset priorities.

The Finals

Before I get stuck into the nerdage, it’s worth looking at the how the actual footy turned out through the finals. The lead-up to the grand final were a bit anticlimactic, both preliminary finals being virtually sealed by half-time; Collingwood’s win possibly being more shocking as they were seen as slight underdogs going up against Richmond. That landed us with a grand final between West Coast and Collingwood, two clubs that both have, how shall we say, polarising fandoms.

Without my own team in the fight, I usually tend towards to the team that had gone longer without a flag, although with West Coast last saluting in 2006 with Collingwood doing so in 2010, there wasn’t much of a gap. So basically my view was, with the Melbourne fairytale snuffed out with napalm, after a fairly lacklustre finals series, the best we could hope for was a good close grand final. It delivered on that in spades.

It didn’t look like that early in the first quarter, of course, with the Pies putting on the first five goals, in a performance very reminiscent of both of those prelims, but West Coast eked out two before the first change, and after that it was a contest as the Eagles ground away at Collingwood’s early advantage. Sheed threading that final goal from the flank with Pies supporters hooting at him will go down as one of those great clutch acts that decides a premiership.

Nerdage

Model wise, GRAFT had an OK season, compared with the other models on the Squiggle Models Leaderboard. It was doing pretty well early in the season (particularly in BITS) but fell adrift later on, finishing with 142 tips, a significant gap to the leaders on 147 and 146. With most models hovering around 70% it was a more predictable season than 2017, yet still had a lot of interesting results as there were still up to twelve teams that had chances of making the finals up until the last one or two rounds of the home-and-away.

While GRAFT has essentially remained unchanged in principle even during its single factor days as RAFT, and since I want to keep it’s simplicity, there does come along certain events that make me think about spinning off a hybrid system that can deal with particular instances. That’s right, I’m looking at Geelong bullying away in their last two home-and-away games, stealing top spot in the GRAFT ratings, and then punking out in the Elimination final.

Looking at the ladder it’s easy to figure out what happened – Geelong only got 13 wins, in the 18 team era just sufficient to be considered fringe finalists (as they were) but they did so with a fairly healthy percentage of 131%. That marks a pythagorean anomaly (a what?) of -3 wins. Not as high as Brisbane’s -3.8 (that is, Brisbane won 5 games but on percentage should have had 9 wins) but nevertheless.

On this point it draws attention to GRAFT’s main weakness in that it doesn’t pay any credence towards wins and losses – it only cares about scores, and when a team runs the score up, as Geelong did against Fremantle (by 133) and Gold Coast (by 102), what is the actual difference between thrashing a team by twenty goals instead of ten? Anyway. That will be part of my homework for the off-season – not really an off-season, as I am about to detail.

Offseason Training

As far as the AFL-specific work goes, while the Gamma probability model worked really well, there are computational issues with working out the margins likelihoods – and therefore the win probabilities). This is because the model being based on two curves for each team’s potential score, the equations for those are well-defined, the difference of the two curves, not so much. For each game, I have to run a brute-force run, so for instance to predict the likelihood of a team winning by 30 points, I have to sum the probability of 90-60, 91-61, 92-62, etc.

It works fine once it’s on the front end but it seems to me that I should be able to figure out an actual equation for the difference curve and refer directly to that for the margin probabilities, thereby saving the computer a lot of crank when I update the tables. So basically, getting out my old calculus and statistics texts and trying to relearn everything I didn’t pay sufficient attention to. (Or just getting Wolfram Alpha to do it, although I still have to figure out the principles first).

Along with all of that, showing the actual probability curves on the site is on the list of things to do – a lot of concepts have been completed as to how these will actually look, however I am not satisfied with how they look just yet, particularly as the risk of misinterpretation is real. The current match tables are basically a soup of numbers and I will do my usual overhaul of the website to try and make them more comprehensible.

Also, I don’t have any historical tables up here apart from the archives of the previous seasons’ sites, so this is also on the agenda. I do think it would be good to make that data available and have historical graphs and records so you can compare clubs across seasons. We’ll see how that goes. I am thinking that I will probably use 1987 as the starting point for the public tables as this was when West Coast and Brisbane Bears entered the competition.

Meanwhile, there are also the summer sports to look at. I am in the second year of basic Elo tracking of the A-League and intend to do so for the W-League. I am cutting it fine as the season starts this week in the NBL, which might actually be a good place to start developing that hybrid system, although for now I am just going to stick with Elo tracking for that as well. Obviously the W-League and WNBL as well.

As far as the cricket goes, specifically the Big Bash League, this is something that could happen. I have a month or so to put something in place, which will have to include an analysis of previous results and all that, so it’s maybe a 50/50 chance at this point.

As this will necessarily involve further modularising of the code, so if that is in place, in the new year I can look at certain other competitions that have up to this point escaped notice. News on those further developments to come.

Towards A New Model – Part 3

In previous posts on this matter, I settled on the gamma distribution as the model, as it was a continuous analogue of the poisson curve, and provided a curve that reflected actual real world scores.

The next little challenge was to calibrate it against the “par” scores that GRAFT generates. The par scores typically range from 50 to 120 and are a little narrower than the distribution of actual scores. There were a few more quirks that came in when I was trying to make it all fit. Basically I took 6-point wide slices of each prediction set, and set them against the actual scores against which I would try and fit the gamma curve. Fortunately, at least for the 60 – 120 par range there was a reasonably consistent look to the curves, as I will show. I confined the set of historical scores to start from 1987 to 2017.

(The black curve is the fit against all scores)

A little bit haywire at the extremities, but not too bad for the main spread. I looked at the factors for the distribution, particularly the shape parameter a, to come up with something plausible.

After a bit of eyeballing a sensible function for a, I’ve set the magic function with 7.5 as the scale

def curve(rating):
    a = rating * .1 + 3
    return scipy.stats.gamma(a, 0, 7.5)

(This is Python code of course, you’ll want the scipy library to play with this. I presume, if you use R you’ll be able to figure out how to implement this.)

So in the end we have this bad boy:

And overlaid on the actual result fits…

So that’s not too bad a fit, at least for our purposes.

A few quirks, though; the mean and median of each curve is actually regressed towards the global mean compared with the GRAFT par that was spat out. I have a feeling that this is counteracted by the spread of scores at each GRAFT tick, where a lot of scores come in slightly under average, but this is balanced by the long tail when teams go on the march and score 20 goals or more.

Well, let’s just that I haven’t put too much rigour into it before this season. There’s still a few things to mess around with, like for instance I basically set up curves for each team’s rating against each other completely independently, so there isn’t any covariance taken into account at this stage. What happens when two defense-orientated teams face off, versus two attacking teams? Well, that’s already kind of accounted for at the par setting stage (team.attack – opposition.defense + league_par).

I’ve gotten as far as cooking up some rough examples for the opener on Thursday night:

From the main site, Richmond’s par is 90.8, Carlton’s par is 58.8.

Based on all of the above, Richmond’s likelihood of winning is 76%, with a mean winning margin of 24. Well, that’s our first bit of weirdness there: GRAFT states that Richmond are better by 32 points, so what’s happening there?

The same sort of thing is happening with the base scores: Again, the idea of GRAFT is that each par score represents what each team should score against each other, given past performances, with the weekly adjustments carried out by a factor, calibrated to maximise the amount of correct tips. It’s a little fuzzier on margins even though margins are at the core of the result.

Richmond’s par (rounded off) is 90.8, but the mean of their curve is 90.6 (OK, not too crazy) and the median is 88.1.

As for Carlton, with a par of 58.8, their mean is 66.6 and their median is 64.1.

We’re fine with the median being a little skewiff, it’s not a symmetrical distribution, and the elongated tail is consistent with real scores. (That’s why I picked the gamma distribution, after all, as it was such a good fit for the historical record)

 

Very early drafts of how the graphs might look on the site. I have coded these at a low level in Pillow because I am a masochist. Also because matplotlib plots like the ones earlier in the post look like matplotlib plots.

So obviously there’s regression to the global mean happening each week. Thing is, the weekly ratings are updated according to weekly results based on the actual scores, based on factors which boil down to *Hulk voice* “big better than small”. While I’ve tweaked how the ratings are presented this year (dropping them by a factor of 10 and making them floating numbers) that part has essentially not changed.

What I was dissatisfied with was how the probabilities of individual games and the season as a whole were calculated. That practice of using a normal distribution which would not tail off nicely at zero so these required a horrible fudge of jacking up both teams’ scores. I am glad to be done with that nonsense.

With this new algorithm, I am at the point where I am happy to publish the probabilities, intending to roll them out by Wednesday (boy this blog entry is going to become dated fast), but at the same time they probably need a little more rigour applied, so caution is advised if you’re going to take heed of them for certain activities. Entertainment purposes only!

Another thing that will happen on the site is that I will be producing CSV files for the tips (with lines and likelihoods) and ratings for people to scrape if they like – a little more detail on the the formats and such in the next post.

Rushed, Behind

It has been a couple of months since the last update, and really there’s not that much to say as far as this website is concerned. As anticipated, I’ve been flat-out with other things, in particular moving house, which is always haunt.

Now I’ve settled in enough that I can actually sit down and get back into this stuff. It’s probably a little late to do a decent run for the AFLW, which is already three weeks into its season, which I think is too short anyway. Yes, I think the skills would get better if they got to play more football. That goes for the actual length of the matches too. Anyway, catching up on that is still a priority.

No such plans for the AFLX circus just past; OK, it was probably worth a try just to see what might happen, but having seen what happened, let’s put it back in the box and never speak of it again. Makes you appreciate defensive pressure and the structuring required to get around that.

There’s also isn’t much time to get the revised GRAFT system into place before the season proper commences, but we’ll see how that goes. Having a live comp in the AFLW gives me a chance to rework the design but I think we’ll be a few weeks into the blokes’ turn before I can drop that new prediction model. I should still have tips for the aggregators from the get-go, and I will provide CSVs to make the scraping a little easier.

In the meantime, I’ve done a few basic cosmetic things as I get my head back into this; probably most noticeable is the Eagles going back to the royal blue for their home guernseys, not such a bad move, so the icons for the new season will be updated to suit.

Towards A New Model – Part 1

The past couple of weeks have seen small but significant steps on the development towards the retooling my sim model for AFL.

The first thing I had to do was update my historical data from, the AFL Tables scrapings.

For that I dragged out my old parsing code which still works, but had to deal with the fact that I had stored the goals/behinds with a dot separator. Which is actually not really a good idea if you’re generating a CSV (comma separated value) file, as if you load those straight into Excel the trailing zero may get stripped, so 10 behinds would be come 1 behind.

It’s OK for my purposes since I do most of my stuff in Python, but I decided that I would make my history file public I should at least eliminate that misunderstanding, and so for those fields I’ve changed the sub-separator to the underscore ( _ ).

After all that cleaning up it’s at a point where I can make the history file public, so you can now pick it up on the new Resources section, which may get expanded with other files that I decide to make public.

With that dataset sorted out, I could get stuck into analysing that.

In previous years I’d used the normal distribution (ye olde bell curve) as the basis for the simulation module. There are a few of problems with that, the most annoying to me is that it would generate negative scores.

Anyway, while I was attempting to work up a plausible sim model for “sokkah”, in that case I reasoned that the poisson distribution was most appropriate there as it was an event-based sport, after all.

AFL scoring, too, is a series of events, but with goals and behinds, the waters get muddied a bit as far as the quantum of the data. I guess I still couldn’t get away from the idea of using a continuous distribution, but for that I decided to use the continuous equivalent of the poisson distribution, the gamma curve.

So, I applied that to the set of final scores in the AFL/VFL set, and it worked marvelously.

So that’s what we’ll be using as a basis. I’ve also gotten the suggestion that the log-normal curve might also be worthy as it exhibits similar characteristics, so that might get a look in as I fine-tune things.

I’m now at the point where I’m trying to calibrate forecast results (based on the GRAFT system) against actual results, and that’s actually not looking so great. As far as margins go, what I’ve found is that while there is a good correlation in one sense (bigger predicted margins match up with bigger actual margins), the average of the actual margins for each slice is about 75-76% of the forecast margin. Not that flash. I can generate a pretty good win probability system out of it, but I also want to nail the “line” margins and par scores as well.

In other words, for games where I have “predicted” one team to win by 50 points, they end up winning (on average) by 38 (mean) or 40 (median) points – albeit with a lot of outliers as you’d expect.

There’s a bit of thinking here to do, and I strongly suspect that it’ll lead to a significantly reworking of the GRAFT system to the point where it’ll have to be considered Version 3 – but what that actually entails is still a bit of a mystery. It may be that this will be a whole new system that moves away from the linear arithmetic model, at least in part.

So that’s where we’re up to at this point. How much of this work I can get done before the new season is a little uncertain, because there’s a few other things on my plate over the next few months. But we’ll see how we go.

Hitting the Track

Starting to look at next year’s fixture. No great insights as yet, just basically cleaning up names of stadia and that sort of thing (search and replace Optus Stadium with Perth Stadium, Goombadome with Kardinia Park, that sorta thing)

Also stripping down the website gen code for next year. I haven’t started on the revamped sim routine as mentioned in the previous post because it’s quite a tricky thing to analyse. Obviously once that’s hammered out I can do those spurious season projections again.

I’m trying out few things with the A-League section. The SVG graph is coming up well, so it’s pretty likely I’ll introduce that sort of thing to the AFL pages next year as well. It should also lend itself to some more interactive features as well.

Speaking of interactivity, another thing that I said I would implement this year – but didn’t – is make various tables sortable. It should be pretty easy to do, I’d just never got around to doing it.

Another off-season move is, well, myself sometime in the new year, which will involves a bit of NBN roulette among other things. Let’s just say I’m not optimistic. But I should be all set up by March so we’ll see how much venting on telcos I ended up doing on the Toots.

Changing of the Guard

So, that’s the winter sports all wrapped up for the year – at least in theory.

We saw Richmond triumphant in a game that saw them break down Adelaide’s vaunted attack while keeping up their own end. In particular, Dustin Martin had a fine game to sweep the treble of the Norm Smith, although like many I thought Bachar Houli might been a bit stiff missing out on that as he and Alex Rance did much to blunt the Crows’ path to goal. It was quite telling that when Martin turned up to the post conference he bore only the premiership medallion. Too much bling is gauche.

(As for the conspiracy theory that somehow Adelaide were stiffed by… something to do with umpiring or the higher gravity in Victoria or what, maybe if they hadn’t lost by eight goals, there might be grounds to establish an argument.)

Of course after Footy Christmas came Footy Boxing Day, with the Melbourne Storm just basically crushing the North Qld Cowboys, as seemed to be expected. A bit dull to watch but a nice send off for Cronk, Cam Smith and Slater. Also completing the Swan Street double after the Tigers’ incredible triumph sent that part of Melbourne into raptures – and without any overturned, burned out cars! Good work!

As far as GRAFT goes, I’ve decided to keep myself busy over summer by keeping track of the A-League which kicks off this weekend. The GRAFT system that I use for AFL doesn’t work so well for association football so I’ll be running off everyone’s favourite ranking algorithm as devised by Arpad Elo. I’m unlikely to bring too many enhancements beyond the off-the-shelf formula, although I do want to work out a method to track attacking/defensive alignment along the way. As such, the ratings for this season will be a work in progress as I tune things along the way. So it’ll be in alpha phase for this season.

I also have a bit of homework to do over summer as far as the AFL ratings go, mostly where it comes to projections and that. As I tweeted a while ago, the random algorithm I use for the Monte Carlo sims needs to reflect actual scoring distributions more closely so that’s going on the to-do list.

2017 Grand Final Preview and beyond

According to the main GRAFT ratings, we have Richmond rated as 3 points better than Adelaide, but that is based on a home ground advantage since Richmond are playing at their home ground against the interstate team. If you otherwise consider grand finals to be neutral in general, then you would remove the standard 12 point HGA factor, then it’s Adelaide by 9. That seems more or less right to me – the Crows have objectively been the best side for most of the season (although with a few strange missteps along the way), but the Tigers have also been consistent through the season with some excellent performances of late.

Going by the Season Ratings based on the home-and-away record and not accounting for finals results, there’s a bit more of a gap in perceived quality as it shows Adelaide at 1186 and Richmond at 995, holding Adelaide as the better side by 7 points (or 19 without HGA).

From the gut feeling point of view I would probably put Adelaide ahead as well. They have been one of the more attacking oriented sides of recent seasons, so shutting down those multiple avenues at goal is something Richmond will need to do – and they’re quite capable of that. So what I’m hoping for is basically a close game all the way through – fans of either particular team would probably like their team to work up a decisive advantage early on so they can soak up the rest of the game, but that’s not much fun for the rest of us.

As I’ve mentioned a couple of times on the toots, up to this point Richmond and Adelaide had the two longest current grand final droughts in the league, Richmond not been in a grand final since 1982 (capping off their greatest era) and Adelaide since completing their successful back-to-back campaign in 1998. Prior to this time last year, it was the Western Bulldogs who had that dubious honour which they dispelled in style. After Saturday, though, the honour will pass jointly to North Melbourne and Carlton, who last competed in 1999 – which doesn’t seem that long ago, actually. Maybe I’m getting old…

In that respect, that 16 clubs have managed to play off in the last 20 years has been fairly remarkable, although of course we’ve also seen dynasties from the Brisbane Lions, Geelong and Hawthorn in that time. Only the two newest expansion clubs haven’t made it to the last game of the season, and of course GWS have gotten pretty close the last couple of years so they should be primed to do so next year.

As for premiership droughts, well, Melbourne and St Kilda have still waiting since the 1960s even though they have both played a number of grand finals. Richmond’s wait of 37 years isn’t quite up there but given the vast number of fans, the frustration is palpable, as will the relief if the Tiges actually come through on Saturday. To do that, though, they will have to overcome an Adelaide side that has also suffered its ups-and-downs, such has other clubs nicking off with its best players and tragedies such the passing of Phil Walsh.

It’s going to be an interesting contest between two proud and well-supported clubs who, it has to be said, have underachieved through the years.

Oh, and I prepared a bingo card, of course.