{"id":2332,"date":"2026-07-05T13:44:16","date_gmt":"2026-07-05T17:44:16","guid":{"rendered":"https:\/\/www.cricmetric.com\/blog\/?p=2332"},"modified":"2026-07-05T13:44:16","modified_gmt":"2026-07-05T17:44:16","slug":"beyond-the-average-ranking-cricket-players-using-markov-chains","status":"publish","type":"post","link":"https:\/\/www.cricmetric.com\/blog\/2026\/07\/beyond-the-average-ranking-cricket-players-using-markov-chains\/","title":{"rendered":"Beyond the Average: Ranking Cricket Players Using Markov Chains"},"content":{"rendered":"<p><a href=\"https:\/\/github.com\/mshashi11\/CricketAI\/tree\/main\/PlayerRanking\">GitHub link<\/a><\/p>\n<p>Traditional cricket statistics\u2014like batting and bowling averages\u2014are simple, familiar, and deeply embedded in the sport&#8217;s history. But they have a fundamental flaw: they treat all matchups equally. Scoring 20 runs off Jasprit Bumrah is treated the same as scoring 20 runs off a part-time spinner. Taking the wicket of Virat Kohli is valued the same as dismissing a tailender. Moreover, because that statistics we use to quantify batters and bowlers are different from each other, there is no way to measure the performance of batters\/bowlers\/all rounders using a common metric.<\/p>\n<p>To solve this, we built a <strong>PageRank-style Markov Chain Player Ranking Model<\/strong> (also known as the <strong>EigenFactor Score<\/strong> or <strong>EFscore<\/strong> model). By analyzing ball-by-ball pairwise matchups, the model dynamically adjusts player rankings based on the strength of their opponents. Thus, it captures not just the quality of the opponent when measuring a player&#8217;s performance, it also allows us to measure both batting and bowling performance on a common pedestal.<\/p>\n<p>Below, we break this model down in two ways: first, a layman-friendly overview for general cricket enthusiasts, and second, a rigorous mathematical deep-dive for data scientists and analysts.<\/p>\n<hr \/>\n<h3>Part 1: The Layman&#8217;s Guide to Cricket Player Rankings<\/h3>\n<p>If you&#8217;ve ever used Google, you\u2019ve interacted with the <strong>PageRank<\/strong> algorithm. PageRank determines the importance of a website based on who links to it. If a highly-ranked website (like Wikipedia) links to your blog, your blog&#8217;s rank goes up. If a low-ranked site links to you, it helps, but only a little.<\/p>\n<p>We can apply this exact logic to cricket matchups:<\/p>\n<ul>\n<li><strong>The Network:<\/strong> Think of bowlers and batsmen as a web of interactions. Every time a bowler bowls to a batsman, they are in a &#8220;tug-of-war.&#8221;<\/li>\n<li><strong>Tug-of-War Outcomes:<\/strong> On every ball, we compare what happened to the overall average across the entire tournament.\n<ul>\n<li>If a bowler bowls a <strong>dot ball<\/strong> or gets a <strong>wicket (out)<\/strong>, they &#8220;defeat&#8221; the batsman.<\/li>\n<li>If a batsman scores a boundary (<strong>four<\/strong> or <strong>six<\/strong>), they &#8220;defeat&#8221; the bowler.<\/li>\n<li>For singles and doubles, we look at the average runs-per-ball. If a batsman scores a single on a ball where the average expectation is higher, the bowler gets a partial victory. If the batsman scores runs above the average expectation, the batsman gets a partial victory.<\/li>\n<\/ul>\n<\/li>\n<li><strong>The Flow of Rank:<\/strong> When a batsman dominates a top-tier bowler, they &#8220;steal&#8221; a large amount of ranking credit from that bowler. Conversely, if a bowler dismisses a world-class batsman, they gain a massive boost in their ranking.<\/li>\n<\/ul>\n<p>By accumulating these matchups across an entire series (like IPL 2026), we run a simulation where rank &#8220;flows&#8221; between players until it stabilizes. The final result is the <strong>EigenFactor Score (EFscore)<\/strong>.<\/p>\n<h4>Visualizing the Player Matchup Network<\/h4>\n<p>Here is an illustration of how the player performance network is structured. Players are represented as nodes, and the arrows represent matchup interactions (runs scored and wickets taken) that transfer ranking credit between them (Arrows point from loser to winner, Blue indicates a batsman win, Red indicates a bowler win):<\/p>\n<p style=\"text-align: center;\"><a href=\"https:\/\/www.cricmetric.com\/blog\/2026\/07\/beyond-the-average-ranking-cricket-players-using-markov-chains\/ipl_2026_matchups\/\" rel=\"attachment wp-att-2335\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-2335\" src=\"https:\/\/www.cricmetric.com\/blog\/wp-content\/uploads\/2026\/07\/ipl_2026_matchups-scaled.png\" alt=\"\" width=\"2560\" height=\"1979\" srcset=\"https:\/\/www.cricmetric.com\/blog\/wp-content\/uploads\/2026\/07\/ipl_2026_matchups-scaled.png 2560w, https:\/\/www.cricmetric.com\/blog\/wp-content\/uploads\/2026\/07\/ipl_2026_matchups-300x232.png 300w, https:\/\/www.cricmetric.com\/blog\/wp-content\/uploads\/2026\/07\/ipl_2026_matchups-1024x792.png 1024w, https:\/\/www.cricmetric.com\/blog\/wp-content\/uploads\/2026\/07\/ipl_2026_matchups-150x116.png 150w, https:\/\/www.cricmetric.com\/blog\/wp-content\/uploads\/2026\/07\/ipl_2026_matchups-768x594.png 768w, https:\/\/www.cricmetric.com\/blog\/wp-content\/uploads\/2026\/07\/ipl_2026_matchups-1536x1187.png 1536w, https:\/\/www.cricmetric.com\/blog\/wp-content\/uploads\/2026\/07\/ipl_2026_matchups-2048x1583.png 2048w\" sizes=\"auto, (max-width: 2560px) 100vw, 2560px\" \/><\/a><br \/>\n<em>IPL 2026: Player Matchup Network<\/em><\/p>\n<p>Because the model evaluates the quality of opponents, a player who performs consistently well against tough opposition will rank higher than a player who inflates their stats against weaker teams.<\/p>\n<hr \/>\n<h3>Part 2: The Technical Deep Dive: Markov Chains &amp; EigenFactor Scores<\/h3>\n<p>For those interested in the underlying mathematics, the player ranking model is structured as a finite, discrete-time Markov Chain. Below is the formal step-by-step mathematical formulation of the model using standard WordPress LaTeX shortcodes.<\/p>\n<h4>1. State Space and Matchup Outcomes<\/h4>\n<p>Let \\(\\mathbf{S} = \\{p_1, p_2, \\dots, p_N\\}\\) be the state space representing the set of \\(N\\) unique players (batsmen and bowlers) in the tournament.<\/p>\n<p>For every pairwise batsman \\(i\\) and bowler \\(j\\) interaction, we extract the aggregate statistics:<\/p>\n<ul>\n<li>\\(B_{i,j}\\): Total balls faced by batsman \\(i\\) against bowler \\(j\\).<\/li>\n<li>\\(O_{i,j}\\): Total outs (wickets credited to the bowler).<\/li>\n<li>\\(D_{i,j}, S^{(1)}_{i,j}, S^{(2)}_{i,j}, S^{(3)}_{i,j}, S^{(4)}_{i,j}, S^{(6)}_{i,j}\\): Total dot balls, singles, doubles, triples, fours, and sixes, respectively.<\/li>\n<\/ul>\n<h4>2. Defining Global Baselines<\/h4>\n<p>To determine dominance, we calculate global tournament baselines:<\/p>\n<ul>\n<li><strong>Runs per Ball (\\(r_{avg}\\)):<\/strong>\n<p style=\"text-align: center;\">\\(r_{avg} = \\frac{\\sum_{i,j} \\left( S^{(1)}_{i,j} + 2 S^{(2)}_{i,j} + 3 S^{(3)}_{i,j} + 4 S^{(4)}_{i,j} + 6 S^{(6)}_{i,j} \\right)}{\\sum_{i,j} B_{i,j}}\\)<\/p>\n<\/li>\n<li><strong>Batting Average (\\(a_{avg}\\)):<\/strong>\n<p style=\"text-align: center;\">\\(a_{avg} = \\frac{\\sum_{i,j} \\left( S^{(1)}_{i,j} + 2 S^{(2)}_{i,j} + 3 S^{(3)}_{i,j} + 4 S^{(4)}_{i,j} + 6 S^{(6)}_{i,j} \\right)}{\\sum_{i,j} O_{i,j}}\\)<\/p>\n<\/li>\n<\/ul>\n<h4>3. Pairwise Score Adjustments<\/h4>\n<p>For each matchup, we compute the net contribution of wickets and runs:<\/p>\n<ol>\n<li><strong>Wicket Score:<\/strong> A wicket is valued in runs by the global tournament batting average:\n<p style=\"text-align: center;\">\\(S^{wicket}_{i,j} = B_{i,j} \\cdot r_{avg} &#8211; O_{i,j} \\cdot a_{avg}\\)<\/p>\n<ul>\n<li>If \\(S^{wicket}_{i,j} &lt; 0\\), it contributes to the bowler&#8217;s dominance:\n<p style=\"text-align: center;\">\\(S^{bowler}_{i,j} \\leftarrow S^{bowler}_{i,j} &#8211; S^{wicket}_{i,j}\\)<\/p>\n<\/li>\n<li>If \\(S^{wicket}_{i,j} &gt; 0\\), it contributes to the batsman&#8217;s dominance:\n<p style=\"text-align: center;\">\\(S^{batsman}_{i,j} \\leftarrow S^{batsman}_{i,j} + S^{wicket}_{i,j}\\)<\/p>\n<\/li>\n<\/ul>\n<\/li>\n<li><strong>Run Scoring Adjustments:<\/strong> We evaluate runs relative to the average expectation \\(r_{avg}\\):\n<ul>\n<li><strong>Dots:<\/strong> Bowler receives credit: \\(S^{bowler}_{i,j} \\leftarrow S^{bowler}_{i,j} + r_{avg} \\cdot D_{i,j}\\)<\/li>\n<li><strong>Singles:<\/strong>\n<ul>\n<li>If \\(r_{avg} &lt; 1\\): Batsman receives credit: \\(S^{batsman}_{i,j} \\leftarrow S^{batsman}_{i,j} + (1 &#8211; r_{avg}) \\cdot S^{(1)}_{i,j}\\)<\/li>\n<li>If \\(r_{avg} \\ge 1\\): Bowler receives credit: \\(S^{bowler}_{i,j} \\leftarrow S^{bowler}_{i,j} + (r_{avg} &#8211; 1) \\cdot S^{(1)}_{i,j}\\)<\/li>\n<\/ul>\n<\/li>\n<li><strong>Boundaries\/Multi-runs (\\(R \\in \\{2, 3, 4, 6\\}\\)):<\/strong> Batsman receives credit:\n<p style=\"text-align: center;\">\\(S^{batsman}_{i,j} \\leftarrow S^{batsman}_{i,j} + (R &#8211; r_{avg}) \\cdot S^{(R)}_{i,j}\\)<\/p>\n<\/li>\n<\/ul>\n<\/li>\n<\/ol>\n<h4>4. Constructing the Transition Matrix<\/h4>\n<p>We populate a pairwise win-loss matrix \\(V \\in \\mathbb{R}^{N \\times N}\\). The entry \\(V_{x, y}\\) represents the degree to which player \\(y\\) defeats player \\(x\\):<\/p>\n<ul>\n<li>If \\(x\\) is batsman \\(i\\) and \\(y\\) is bowler \\(j\\): \\(V_{i, j} = S^{bowler}_{i,j}\\)<\/li>\n<li>If \\(x\\) is bowler \\(j\\) and \\(y\\) is batsman \\(i\\): \\(V_{j, i} = S^{batsman}_{i,j}\\)<\/li>\n<\/ul>\n<p>To make the Markov Chain recurrent (fully connected and preventing absorbing states), we add a tiny regularization factor \\(\\epsilon = 0.001\\):<\/p>\n<p style=\"text-align: center;\">\\(T = V + \\epsilon\\)<\/p>\n<p>We set the diagonal entries to reflect the total wins of the player:<\/p>\n<p style=\"text-align: center;\">\\(T_{x, x} = \\sum_{k=1}^N T_{k, x}\\)<\/p>\n<p>We then normalize each row of \\(T\\) to obtain the row-stochastic transition matrix \\(P \\in \\mathbb{R}^{N \\times N}\\):<\/p>\n<p style=\"text-align: center;\">\\(P_{x, y} = \\frac{T_{x, y}}{\\sum_{k=1}^N T_{x, k}}\\)<\/p>\n<h4>5. Solving for the Steady-State Distribution<\/h4>\n<p>The <strong>EigenFactor Score (EFscore)<\/strong> of player \\(x\\) is given by the stationary distribution vector \\(\\pi \\in \\mathbb{R}^N\\), which satisfies:<\/p>\n<p style=\"text-align: center;\">\\(\\pi P = \\pi\\)<\/p>\n<p>Subject to the normalization constraint \\(\\sum_{x=1}^N \\pi_x = 1\\).<\/p>\n<p>Computationally, \\(\\pi^T\\) is the principal eigenvector corresponding to the dominant eigenvalue \\(\\lambda = 1\\) of the transpose matrix \\(P^T\\):<\/p>\n<p style=\"text-align: center;\">\\(P^T \\pi^T = \\pi^T\\)<\/p>\n<h4>6. Derived Performance Metrics<\/h4>\n<p>Once the stationary distribution \\(\\pi\\) (EFscore) is solved, we compute:<\/p>\n<ul>\n<li><strong>Runs Above Average (RAA):<\/strong>\n<p style=\"text-align: center;\">\\(RAA_x = \\text{Wins}_x &#8211; \\text{Losses}_x\\)<\/p>\n<p>where \\(\\text{Wins}_x = \\sum_{k=1}^N V_{k, x}\\) and \\(\\text{Losses}_x = \\sum_{k=1}^N V_{x, k}\\).<\/li>\n<li><strong>Wins Contributed:<\/strong>\n<p style=\"text-align: center;\">\\(\\text{Wins Contributed}_x = \\frac{RAA_x}{10 \\cdot a_{avg}}\\)<\/p>\n<\/li>\n<\/ul>\n<p>This gives a robust, opponent-adjusted rating that translates network-based dominance back into easily interpretable cricket currency.<\/p>\n<hr \/>\n<p>Cricmetric provides the player ranks for all IPL seasons on the <a href=\"https:\/\/www.cricmetric.com\/ipl\/ranks\/\">IPL ranks page<\/a>. However, this is a very general way of ranking entities where &#8220;pairwise contest&#8221; results are known. For example, <a href=\"https:\/\/www.cricmetric.com\/rankings.py\">teams can be ranked<\/a> using the same methodology. And we even provide <a href=\"https:\/\/www.cricmetric.com\/captainranks.py\">all-time captain ranks<\/a> for all the formats using the same methodology as well.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>GitHub link Traditional cricket statistics\u2014like batting and bowling averages\u2014are simple, familiar, and deeply embedded in the sport&#8217;s history. But they have a fundamental flaw: they treat all matchups equally. Scoring 20 runs off Jasprit Bumrah is treated the same as scoring 20 runs off a part-time spinner. Taking the wicket of Virat Kohli is valued&hellip;&nbsp;<a href=\"https:\/\/www.cricmetric.com\/blog\/2026\/07\/beyond-the-average-ranking-cricket-players-using-markov-chains\/\" rel=\"bookmark\">Read More &raquo;<span class=\"screen-reader-text\">Beyond the Average: Ranking Cricket Players Using Markov Chains<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"neve_meta_sidebar":"","neve_meta_container":"","neve_meta_enable_content_width":"off","neve_meta_content_width":70,"neve_meta_title_alignment":"","neve_meta_author_avatar":"","neve_post_elements_order":"[\"title\",\"meta\",\"thumbnail\",\"content\",\"tags\",\"comments\"]","neve_meta_disable_header":"","neve_meta_disable_footer":"","neve_meta_disable_title":"","footnotes":""},"categories":[46],"tags":[],"class_list":["post-2332","post","type-post","status-publish","format-standard","hentry","category-technical"],"_links":{"self":[{"href":"https:\/\/www.cricmetric.com\/blog\/wp-json\/wp\/v2\/posts\/2332","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.cricmetric.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.cricmetric.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.cricmetric.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.cricmetric.com\/blog\/wp-json\/wp\/v2\/comments?post=2332"}],"version-history":[{"count":10,"href":"https:\/\/www.cricmetric.com\/blog\/wp-json\/wp\/v2\/posts\/2332\/revisions"}],"predecessor-version":[{"id":2343,"href":"https:\/\/www.cricmetric.com\/blog\/wp-json\/wp\/v2\/posts\/2332\/revisions\/2343"}],"wp:attachment":[{"href":"https:\/\/www.cricmetric.com\/blog\/wp-json\/wp\/v2\/media?parent=2332"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.cricmetric.com\/blog\/wp-json\/wp\/v2\/categories?post=2332"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.cricmetric.com\/blog\/wp-json\/wp\/v2\/tags?post=2332"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}