# What is the Maximum OPR?

## Background

The inspiration for this post comes from this Chief Delphi thread asking what the maximum possible Offensive Power Rating (OPR) was in 2019. The easy answer is that there is no upper bound on 2019 OPRs because there was no upper bound for the score due to penalties. Oftentimes innocuous questions can lead down very intriguing paths though, and it got me interested enough to do a more detailed analysis of the question of what the maximum unpenalized OPR in 2019 would have been. Since the maximum unpenalized score for a 2019 match was 154, a first pass guess would say the max OPR would also be 154 (assuming a team scores 154 in all their matches and all other scores are 0). However, just like negative OPRs are theoretically possible, so too are OPRs greater than the max score.

## OPR Theory

For a refresher on how OPR is calculated, check out Eugene’s great blog post from a few years ago, I’ll be skimming details here, so if you get lost try referencing back to that post. To summarize, the least squares solution to an overdetermined set of linear equations (or what is commonly called OPR around here) has the following closed form solution:

Where x is OPR, A is the schedule matrix, and b is the score matrix. From here on in, I’m going to refer to this:

As the multiplication matrix, since it multiplies with the score matrix to obtain the OPR matrix.

The schedule A is static, so the multiplication matrix is really just a static function of the schedule. Since all entries of b are bounded above (by the max score) and below (by 0), the logic to maximize an entry of x is simple: For each half-match (column), if the row corresponding to that entry of x in the multiplication matrix is positive, set that half match’s score equal to the max score. Otherwise, set that half-matches score equal to 0. I know that’s a lot to take in all at once, so here’s an example to illustrate.

## Case Study

Let’s take a look at 5511 at the North Carolina State Championship. I’ve copied all of the entries in the row of the multiplication matrix corresponding to 5511 into the below table:

 match blue red 1 0.085 -0.007 2 0.004 -0.010 3 -0.010 -0.002 4 -0.014 -0.005 5 0.004 -0.010 6 0.003 -0.010 7 -0.012 -0.012 8 -0.003 -0.010 9 -0.003 0.004 10 -0.009 -0.013 11 0.085 -0.006 12 0.004 -0.010 13 -0.013 0.083 14 -0.007 -0.011 15 -0.002 0.003 16 -0.011 -0.002 17 0.002 -0.005 18 -0.011 -0.003 19 -0.003 -0.005 20 -0.010 -0.012 21 -0.003 -0.009 22 0.083 -0.003 23 -0.002 -0.013 24 -0.014 0.010 25 -0.010 -0.013 26 0.000 -0.011 27 0.083 -0.003 28 -0.010 -0.002 29 -0.002 -0.002 30 -0.006 -0.007 31 -0.004 -0.001 32 0.081 -0.011 33 -0.003 -0.013 34 -0.010 -0.003 35 -0.011 0.004 36 -0.012 -0.009 37 0.083 0.012 38 -0.013 -0.003 39 -0.002 -0.009 40 0.081 -0.013 41 -0.003 -0.010 42 0.004 -0.005 43 -0.003 -0.014 44 -0.014 -0.003 45 -0.002 -0.010 46 -0.013 -0.003 47 0.003 0.086 48 -0.006 -0.003 49 -0.002 -0.004 50 -0.002 0.084 51 -0.010 -0.006 52 0.006 -0.012 53 -0.014 -0.004 54 -0.009 -0.014 55 -0.009 -0.011 56 0.005 -0.003 57 -0.005 0.003 58 -0.011 0.083 59 -0.005 0.004 60 -0.010 0.082 61 -0.003 -0.012 62 -0.005 -0.002 63 -0.011 -0.004 64 -0.002 -0.012

You can interpret these numbers as the “impact” of each half-match to 5511’s OPR. So you can see that by far the most important half-matches for 5511 are ones like blue 1, blue 11, and red 13, which not coincidentally are the half-matches 5511 is in. These are the obvious first-order effects of this methodology, if you only look at these, it is very similar to just looking at average scores for teams.

You’ll also see that the majority of the remaining half-matches have negative values. This indicates that, generally, it reflects better on 5511 if half-matches they aren’t in have low scores because that means their partners likely weren’t contributing as much when they were partnered with 5511. We’ll call these effects second-order.

What we are most interested in right now though, are the half-matches that don’t contain 5511, but still have slight positive importance to them such as blue 2, blue 5, blue 6, and red 9. These positive values are generally due to third-order effects. Just like it’s a good sign for you if your partners do poorly without you, it’s also a good sign if their partners do well without them.

This pattern continues forever, odd degrees of separation between teams have positive impact to your team, and even degrees of separation have negative impact. But the further out you go, the more watered down these effects are. Interestingly, 538 recently discussed this same effect for their NBA RAPTOR calculation methodology (jump to point 3 in the section titled RAPTOR On-Off) where they choose to stop at the third order effects or two degrees of separation.

Alright, so now that we have that out of the way, let’s use those half-match impacts to get 5511 a stupid-high OPR. Just go through and make the score 154 if it has positive impact for 5511, and 0 if it has negative impact for them. Here are those scores:

 match blue red 1 154 0 2 154 0 3 0 0 4 0 0 5 154 0 6 154 0 7 0 0 8 0 0 9 0 154 10 0 0 11 154 0 12 154 0 13 0 154 14 0 0 15 0 154 16 0 0 17 154 0 18 0 0 19 0 0 20 0 0 21 0 0 22 154 0 23 0 0 24 0 154 25 0 0 26 154 0 27 154 0 28 0 0 29 0 0 30 0 0 31 0 0 32 154 0 33 0 0 34 0 0 35 0 154 36 0 0 37 154 154 38 0 0 39 0 0 40 154 0 41 0 0 42 154 0 43 0 0 44 0 0 45 0 0 46 0 0 47 154 154 48 0 0 49 0 0 50 0 154 51 0 0 52 154 0 53 0 0 54 0 0 55 0 0 56 154 0 57 0 154 58 0 154 59 0 154 60 0 154 61 0 0 62 0 0 63 0 0 64 0 0

Altogether, this gets 5511 up to an OPR of 165.8! That’s astoundingly high, but it isn’t even the highest possible at this event. Since each team’s schedule is slightly different, each team’s max OPR is also slightly different. So the highest possible OPR at NC Champs would actually have been 186.8 for team 7890. We can then find the highest possible OPR of the 2019 season by doing this same analysis at every event. Unfortunately, no sane person would do that much work.

## Full 2019 Results

But at least I did :). Here is the max and min OPRs possible for every in season event along with some other details about those events.

 event matches per team teams matches max OPR min OPR ausp 8 62 83 269.4 -218.0 flor 9 64 96 264.2 -212.9 flwp 9 64 96 260.1 -208.7 scmb 9 64 96 258.3 -207.0 mndu 9 63 95 258.0 -206.7 mnmi 9 63 95 257.6 -206.3 cada 9 59 89 257.1 -205.8 carv 10 68 114 256.4 -205.1 arli 9 58 87 254.8 -203.5 casj 9 59 89 254.6 -203.2 okok 9 62 93 253.9 -202.5 hop 10 68 114 253.7 -202.4 cars 10 68 114 253.5 -202.2 mndu2 9 60 90 252.6 -201.3 dal 10 68 114 251.5 -200.2 lake 9 59 89 250.5 -199.2 roe 10 67 112 250.2 -198.8 ohcl 9 60 90 250.2 -198.8 tes 10 68 114 250.1 -198.8 tur 10 66 110 249.9 -198.5 new 10 67 112 249.6 -198.3 cala 9 56 84 249.4 -198.1 ohmv 9 60 90 249.2 -197.9 mnmi2 9 60 90 248.3 -197.0 arc 10 68 114 248.3 -197.0 gal 10 67 112 248.0 -196.7 dar 10 68 114 247.9 -196.6 cur 10 68 114 247.7 -196.4 ilch 9 53 80 245.7 -194.3 nyny 9 51 77 239.4 -188.1 wila 10 54 90 232.9 -181.6 alhu 10 55 92 230.6 -179.3 azfl 10 53 89 227.0 -175.7 ndgf 10 52 87 226.5 -175.2 wimi 10 54 90 225.8 -174.5 code 10 53 89 225.7 -174.4 pncmp 12 64 128 225.4 -174.1 tnkn 10 51 85 225.3 -174.0 ftcmp 12 64 128 222.1 -170.8 necmp 12 64 128 221.0 -169.7 cafr 10 49 82 220.8 -169.5 mosl 10 48 80 220.4 -169.0 utwv 10 49 82 220.3 -168.9 nyli2 10 48 80 219.9 -168.6 caoc 10 49 82 219.0 -167.6 nysu 10 46 77 218.5 -167.1 nyro 10 48 80 217.8 -166.4 mrcmp 12 60 120 215.8 -164.5 paca 10 45 75 214.7 -163.4 iacf 10 48 80 214.5 -163.2 chcmp 12 58 116 211.6 -160.3 casd 10 47 79 211.3 -160.0 mxmo 10 43 72 210.1 -158.8 iscmp 11 45 83 209.4 -158.1 nvlv 11 44 81 198.9 -147.6 qcmo 11 42 77 197.9 -146.5 casf 11 43 79 196.6 -145.3 abca 10 37 62 196.4 -145.0 gacmp 12 45 90 196.0 -144.7 ilpe 11 40 74 194.5 -143.2 nhgrs 12 36 72 193.6 -142.2 ausc 11 40 74 192.5 -141.2 txpas 12 32 64 191.7 -140.3 txgre 12 42 84 191.5 -140.2 oncmp2 12 40 80 190.8 -139.4 cave 12 42 84 189.7 -138.4 wayak 12 31 62 189.7 -138.4 txdel 12 40 80 189.6 -138.2 misjo 12 40 80 188.9 -137.6 micmp2 12 40 80 188.8 -137.4 azpx 12 42 84 188.2 -136.9 qcqc 11 35 65 188.2 -136.9 milan 12 40 80 188.0 -136.7 mikng 12 40 80 188.0 -136.7 inmis 12 42 84 188.0 -136.7 mishe 12 40 80 187.8 -136.5 mitvc 12 40 80 187.7 -136.3 mifor 12 40 80 187.6 -136.3 mimil 12 40 80 187.4 -136.1 mitry 12 41 82 187.3 -136.0 ctwat 12 41 82 187.2 -135.9 mibel 12 40 80 187.0 -135.6 milsu 12 41 82 186.9 -135.6 nccmp 12 32 64 186.8 -135.4 onosh 12 40 80 186.8 -135.4 misou 12 40 80 186.6 -135.3 micmp4 12 40 80 186.4 -135.0 marea 12 38 76 186.2 -134.9 micen 12 40 80 186.2 -134.9 miken 12 41 82 186.2 -134.9 micmp3 12 40 80 186.2 -134.9 mimar 12 40 80 186.0 -134.7 inwla 12 39 78 186.0 -134.7 milin 12 41 82 186.0 -134.7 milak 12 39 78 185.8 -134.5 mxto 11 36 66 185.8 -134.4 midet 12 39 78 185.8 -134.4 miliv 12 40 80 185.7 -134.4 onlon 12 40 80 185.5 -134.2 onwin 12 40 80 185.4 -134.0 micmp1 12 40 80 185.2 -133.9 mxcm 11 27 50 185.0 -133.6 isde4 11 36 66 184.9 -133.6 onto3 12 32 64 184.9 -133.6 txdls 12 39 78 184.9 -133.5 caln 12 36 72 184.6 -133.3 nhdur 12 40 80 184.6 -133.3 macma 12 39 78 184.6 -133.2 mimus 12 39 78 184.5 -133.2 oncmp1 12 40 80 184.2 -132.9 miwmi 12 39 78 184.2 -132.8 mimid 12 39 78 184.2 -132.8 cthar 12 38 76 184.1 -132.8 bcvi 11 35 65 184.0 -132.7 gagai 12 38 76 184.0 -132.6 vagle 12 37 74 183.9 -132.5 migul 12 38 76 183.8 -132.5 melew 12 32 64 183.7 -132.3 wasno 12 38 76 183.6 -132.3 gafor 12 30 60 183.2 -131.9 mdoxo 12 39 78 182.8 -131.5 mike2 12 39 78 182.8 -131.5 mijac 12 40 80 182.8 -131.4 vahay 12 38 76 182.3 -131.0 mabri 12 38 76 182.3 -130.9 mialp 12 39 78 181.9 -130.6 txaus 12 36 72 181.9 -130.5 gadal 12 38 76 181.8 -130.4 vapor 12 37 74 181.6 -130.3 waamv 12 38 76 181.6 -130.3 mdowi 12 38 76 181.6 -130.2 njfla 12 37 74 181.5 -130.2 tuis 11 34 63 181.5 -130.1 txama 12 29 58 181.3 -129.9 nhsnh 12 37 74 181.2 -129.9 njski 12 37 74 181.0 -129.6 orwil 12 38 76 180.4 -129.1 mawne 12 30 60 180.3 -128.9 isde2 11 34 63 180.2 -128.8 onto1 12 30 60 179.9 -128.6 caav 12 37 74 179.7 -128.3 nyli 12 37 74 179.1 -127.8 onnyo 12 36 72 179.1 -127.8 mdbet 12 36 72 179.0 -127.7 mokc3 12 36 72 179.0 -127.6 mial2 12 36 72 178.5 -127.2 paphi 12 31 62 178.5 -127.2 ksla 12 36 72 178.5 -127.1 txsan 12 36 72 178.5 -127.1 ncwak 12 36 72 178.4 -127.1 mokc 12 36 72 178.3 -127.0 nytr 12 36 72 178.2 -126.9 ncgui 12 36 72 178.2 -126.8 camb 12 36 72 178.2 -126.8 orore 12 36 72 178.2 -126.8 waspo 12 29 58 177.9 -126.6 paben 12 31 62 177.3 -125.9 ncpem 12 36 72 177.2 -125.9 gaalb 12 30 60 177.0 -125.7 isde3 11 31 57 176.7 -125.4 ingre 12 35 70 176.3 -125.0 orlak 12 36 72 176.3 -125.0 tuis2 11 32 59 176.2 -124.9 cadm 12 35 70 175.9 -124.6 migib 12 35 70 175.9 -124.6 miket 12 35 70 175.9 -124.6 mabos 12 28 56 175.6 -124.3 gacol 12 35 70 175.6 -124.3 txpla 12 35 70 175.5 -124.1 njbri 12 35 70 174.9 -123.6 njtab 12 35 70 174.9 -123.5 nyut 13 31 68 174.8 -123.5 pahat 12 35 70 174.6 -123.3 waahs 12 34 68 174.5 -123.2 txcha 12 35 70 174.2 -122.9 wamou 12 34 68 174.0 -122.6 rismi 12 29 58 173.8 -122.5 onham 12 34 68 173.6 -122.3 vabla 12 34 68 173.3 -122.0 hiho 12 34 68 173.0 -121.7 isde1 11 31 57 172.8 -121.5 pawch 12 32 64 172.0 -120.7 incmp 12 32 64 171.4 -120.1 onnob 12 33 66 171.4 -120.0 ncash 12 32 64 171.3 -120.0 onbar 12 26 52 171.0 -119.6 idbo 12 27 54 170.9 -119.5 onwat 12 32 64 169.2 -117.8 txelp 12 25 50 167.0 -115.7

So, I believe the max possible OPR in 2019 was 269.4, which could only have been achieved by 6508 at South Pacific.

Here I’ve graphed Max OPR against all three of matches per team, total matches, and total teams:

## Conclusions

There’s plenty of other interesting info in here. Firstly, all 2019 events had a max OPR greater than 154. This bodes well for my hypothesis that all but a select few schedules will have some team capable of achieving a max OPR greater than the max score (although a proof or counterexample would be needed to rule definitively on this).

Another cool tidbit is that the minimum possible normalized OPR is always 1/3-(normalized max OPR). This means that, since all events have a normalized max OPR greater than or equal to 1.0, all events also must have a normalized min OPR which is less than or equal to -2/3.

Finally, if you want to predict the max OPR without this excessive effort, then it seems the best linear predictor is team count (R^2 = 0.89). As you can see though there is no straightforward formula to determine precisely what it is as there is clear schedule dependence. Here is a rough exponential function that bounds the 2019 data points above:

It’s formula is (max OPR) = (max score) *(1+e^((teams at event – 63)/26)). I think for the future though, providing the scheduler stays the same and we don’t get more than 70 teams at an event, we can comfortably say that there will probably never be an opportunity for a team to achieve an unpenalized OPR greater than 2.5X the max score.