Fantasy PerformanceΒΆ

Fantasy sport has existed for decades, but is relatively new to soccer. It has transitioned for an endeavor by editors to sell newspapers to a serious enterprise with thousands of pounds in prizes on offer.

The English Premier League has its own official fantasy competition that attracts over 3 million players from around the world. In this example we will use the Soccermetrics API to compute fantasy points for a football player in the Premier League and perform some light statistical analysis.

Language

This script is written in Python 2.7 using the official API client for Python. The client simplifies the process of making HTTP requests to the Soccermetrics API and unpacking the responses.

This is a LONG script – close to 500 lines of code. We devoted about 40 lines to a routine that plotted the fantasy point history and distribution, so the Matplotlib package is required.

Concept

In a script as complicated as this one, it’s necessary to divide the tasks into classes and functions. We create one class to handle match time conversion and computation, and a series of functions to calculate fantasy points for various types of offensive and defensive play.

Throughout the script, we call lineups.get() to retrieve the specific match lineup representation and link.get() to make use of the hypertext linked from the lineup and match representations.

Walkthrough

Because of the size of the script, we’re not going to be able to step through every block of code. Instead we will focus on the major functions and classes and invite you to study the example.

We start with the matchTime class that converts match time to an “absolute” time scale. We do this because some halves in a football match run longer than 45 minutes which affects calculations of elapsed time between events that start in one half and end in another. We initialize the class by passing the lengths of each half, and then use the methods total() and absoluteTime() to calculate total playing time and absolute time.

class matchTime:
    PERIODS = [(1, 46), (46, 91)]

    def __init__(self, matchLength=[45, 45]):
        self.matchLength = matchLength

    def total(self):
        return sum(self.matchLength)

    def absoluteTime(self,time):
        if type(time) is int:
            time = (time,0)

        if (time[0] and (time[0] % 45)):
            newtime = (time[0],0)
            time = newtime

        for period,k in zip(matchTime.PERIODS,range(len(matchTime.PERIODS))):
            minSet = set(range(period[0],period[1]))
            if minSet.intersection((time[0],)):
                v = k

        return sum(self.matchLength[0:v]) + sum(time)-matchTime.PERIODS[v][0] + 1

We’ll step through calcMinutesPlayed() because its organization is similar to other functions. As you would guess, this function computes the total minutes played in a match. What makes this problem hard is that we must account for the following events:

  1. Started and played full match.
  2. Started match and was sent off.
  3. Started match and was substituted out.
  4. Entered match and played remainder of match.
  5. Entered match and was sent off.
  6. Entered match and was substituted out.

Results

Results for van Persie here.

Results for Barton here.