The Mathematics Behind Valomapped
A comprehensive deep-dive into the mathematical models, algorithms, and statistical methods powering my Valorant competitive analytics platform.
Core Systems
Advanced Analytics
The core of this website is a custom Elo rating system modified from the standard Elo formula made famous in chess. Each team is given an independent rating for each map so the model can represent map-specific strength. That extra detail is a modeling hypothesis, not a proven performance advantage: the published chronological holdout does not establish that the deployed map model predicts better than plain overall-team Elo.
A typical Elo formula first calculates the expected probability of winning the match for each player as follows:
expected_probability = 1 / (1 + 10^((opponent_rating - player_rating) / 400))Then the Elo rating is updated based on the actual outcome of the match.
new_elo_rating = old_elo_rating + k * (actual_outcome - expected_probability)K is a constant used to control the magnitude of the rating change.
Valomapped's Custom Elo Formula
expected_probability = 1 / (1 + 10^((opponent_rating - player_rating) / 1000))
elo_rating = elo_rating + 74 * margin_factor * (actual_outcome - expected_probability)The margin factor is calculated as follows:
margin_factor = ln(5.95 * sqrt(score_difference + 1))Parameters
There are essentially 3 main parameters that can be adjusted to fit the needs of the specific use case.
- 1. Rating Scale
- 2. Margin of Victory Adjustment
- 3. K-Factor
1. Rating Scale
The rating scale acts as the divisor that controls the spread of Elo ratings in the system. Increasing this value widens the Elo gap required to achieve the same win probability. In traditional chess Elo (400-point scale), a 400-point gap yields ~91% win probability (e.g., 1600 vs 1200). In my 1000-point scale, that same 91% probability requires a 1000-point gap (e.g., 1600 vs 600).
The deployed model uses the wider scale as a legacy modeling and presentation choice. The original selection record is not reproducible, so the scale should not be interpreted as independently calibrated or as evidence that displayed rating gaps are more predictive.
Expected Probability = 1 / (1 + 10^((opponent_rating - player_rating) / 1000))Current Parameters and Validation Status
The production model currently uses the legacy parameter set shown below. Earlier exploratory work used a grid search, but the repository did not preserve enough evidence—exact split dates, scores, candidate results, or a data snapshot—to independently reproduce the selection. These values should therefore be treated as an implementation choice, not a validated performance claim. The published retrospective backtest evaluates the fixed configuration but does not establish an improvement over plain overall-team Elo.
Production configuration:
- Initial map rating: 1000
- Rating scale: 1000
- K-factor: 74
- Margin factor: ln(5.95 × √(score difference + 1))
- Hard rating reset at the start of each calendar year
Evidence standard:
The reproducible retrospective evaluation publishes chronological train, validation, and test dates and enforces validation-only selection within each run; it is not described as a preregistered or untouched holdout. It also publishes a plain-Elo baseline, Brier score, log loss, reliability, confidence-band accuracy, sample sizes, and uncertainty intervals. Experimental results will not silently replace the production model.
2. Margin of Victory Adjustment
The margin of victory adjustment adds critical context by incorporating the score differential into the rating calculation. This ensures that dominant victories yield larger rating changes than narrow wins.
margin_factor = ln(5.95 × √(score_difference + 1))The logarithmic scaling grows more slowly than a linear margin multiplier. For example, a 13-5 victory yields a greater reward than a 13-11 victory, but the marginal increase in reward for winning 13-10 vs 13-11 is higher than the increase for 13-5 vs 13-6. That limits growth relative to a linear rule, but it does not make the deployed updates small.
At equal 1000 ratings, the deployed formula moves each team by about 86.3 points after 13-11 and 114.8 points after 13-0. Those aggressive magnitudes are disclosed and compared in the published backtest; the holdout does not establish that they are superior.
3. K-Factor
The K-factor controls the base sensitivity of each update. Because the deployed formula also multiplies by margin of victory, K is not a hard maximum on the point change.
Tuning the K-factor involves finding a balance in how responsive the rating system is to new data.
A higher K-factor will result in more volatile rating changes, while a lower K-factor will result in more stable rating changes.
The deployed legacy configuration uses a K-factor of 74. The repository does not preserve enough evidence to reproduce the earlier parameter search, so this value is not presented as a validated optimum. It is substantially higher than values commonly used in traditional chess-style Elo systems.
The motivating intuition was that a rapidly evolving esport may benefit from faster updates. The holdout results show why that intuition still needs calibration evidence rather than being treated as proof.
Final Formula
expected_probability = 1 / (1 + 10^((opponent_rating - player_rating) / 1000))
new_rating = old_rating + (74 × ln(5.95 × sqrt(score_difference + 1)) × (Actual_Result - Expected_Probability))Alternative Methods
The notes below describe earlier exploratory ideas whose datasets, splits, and scores were not preserved well enough for independent verification. The reproducible comparison on the methodology page supersedes them as the project's public evidence.
Hybrid Global Offset
The hybrid global offset method is a modification of my custom Elo formula that creates a global Elo rating for each team and then adds a map-specific offset to the rating for each map, rather than having completely independent ratings per map. Earlier exploratory work suggested this might help at the beginning of seasons, but that result is not reproducible from the current repository and is not a published performance claim. The deployed implementation retained independent map ratings.
Model K-Factor Updating Confidence
I also experimented with a K-Factor updating confidence approach. This means the model would dynamically adjust the K-Factor based on the amount of time between matches. So the K-factor would start higher at the beginning of the season and gradually shrink as it got more data. The model starts updating more quickly while it has low confidence in the team's skill level and then updates more slowly as it gets more data. The K-Factor would then increase again after long breaks within the season as the teams have time to make changes.
Earlier exploratory notes reported that this version did not perform as well, but the underlying comparison is not reproducible and should be treated as design history rather than evidence.
I was quite surprised by this result, however my best guess as to why is some combination of factors: the data is sparse as is, and decaying the K-Factor was ultimately causing more harm than good. As well as that teams are able to make significant changes to their playstyle and strategy even in the middle of a season and our reduced K-Factor more slowly adjusted to these mid-season changes.
Regional Elo Multiplier
I plan on testing a regional Elo multiplier for each map in the future. This is because teams play so many of their matches regionally that the model is at risk of not fully accounting for differences in skill level between regions.
Differences between regions are currently sorted out between teams competing internationally where teams from stronger regions will win more often and therefore "bring back" the gained Elo to the regional events.
I however am not convinced this is sufficient to calibrate the regional differences fully. A thought I plan on exploring is giving each region a multiplier that is impacted by the result of each international match, weighting the Elos of every team in the region based on the result rather than just relying on individual team Elo gains/losses waterfalling down to the rest of the region. This would also be map-independent, as regions may have better strategies on some maps and not others.
Probability calculations for Best-of-3 and Best-of-5 matches using probability theory.
Single Map Win Probability
P(Team A wins) = 1 / (1 + 10^((Elo_B - Elo_A) / 1000))The probability of a team winning a given map is calculated directly from the win probability implied by our Elo ratings.
Best-of-3 Match Probability
P(BO3 Win) = P₁P₂ + P₁(1-P₂)P₃ + (1-P₁)P₂P₃Where P₁, P₂, P₃ are the win probabilities for each map in the match sequence.
Best-of-5 Match Probability
A team wins a BO5 by winning 3 maps before their opponent does. There are 10 distinct scenarios for achieving this victory:
3-0 Victory (1 scenario):
P₁P₂P₃3-1 Victory (3 scenarios):
P₁P₂(1-P₃)P₄ + P₁(1-P₂)P₃P₄ + (1-P₁)P₂P₃P₄3-2 Victory (6 scenarios):
P₁P₂(1-P₃)(1-P₄)P₅ + P₁(1-P₂)P₃(1-P₄)P₅ + P₁(1-P₂)(1-P₃)P₄P₅ + (1-P₁)P₂P₃(1-P₄)P₅ + (1-P₁)P₂(1-P₃)P₄P₅ + (1-P₁)(1-P₂)P₃P₄P₅Full Formula:
P(BO5 Win) = [sum of all 10 terms above]Where P₁, P₂, P₃, P₄, P₅ are the win probabilities for each map in the match sequence. Each scenario represents a unique path through the match where the team wins exactly 3 maps.
A local map-Elo heuristic used to simulate pick/ban processes in competitive Valorant.
Strategic Assumptions
- The heuristic bans the map with the acting team's lowest modeled win probability
- The heuristic picks the map with the acting team's highest modeled win probability
- Alternating selection order follows standard competitive rules
- The simulation treats current Elo estimates as its complete input and does not observe private strategic information
BO3 Selection Process
1. Team A bans its lowest-probability map
2. Team B bans its lowest-probability map
3. Team A picks its highest-probability map
4. Team B picks its highest-probability map
5. Team A bans its lowest-probability remaining map
6. Team B bans its lowest-probability remaining map
7. Remaining map becomes deciderBO5 Selection Process
1. Team A bans its lowest-probability map
2. Team B bans its lowest-probability map
3. Team A picks its highest-probability map
4. Team B picks its highest-probability map
5. Team A picks its highest-probability remaining map
6. Team B picks its highest-probability remaining map
7. Remaining map becomes decider
Zero-Sum Model Assumption
This algorithm uses a strict zero-sum abstraction. For any given map, Team A's modeled win probability is exactly (1 - Team B's modeled win probability). Within that abstraction, one team's lowest-probability map is the opponent's highest-probability map, and vice versa.
The implementation therefore makes a greedy local recommendation: ban the lowest modeled probability and pick the highest. That recommendation is internally consistent with the current Elo estimates, but it is not proof of the best full-sequence veto strategy. Later veto choices, format constraints, side selection, opponent behavior, roster plans, and private preparation can all matter beyond this model.
Modeling how an opponent may depart from the same greedy rule is beyond the current system; the simulator assumes both teams follow it.
A potential future addition would be to model each team's actual historical map choice patterns and provide an option to use predicted map selection based on past behavior, rather than assuming both teams follow the same greedy recommendation.
With a model for each team's historical choice patterns, we could create a predicted map pool for a matchup and a policy-aware recommendation that responds to likely opponent choices.
Large-scale statistical modeling of tournament outcomes using probabilistic match simulation.
Simulation Process
for i = 1 to N_simulations (default: 10,000):
for each match in tournament:
simulate_match_result(team1, team2, match_type)
record tournament outcomes
calculate final probabilitiesThe (simulate_match_result) function simulates the map selection phase with both teams following the greedy Elo recommendations, then gets the modeled win probabilities for each map using the match probability calculator.
Then all that is left is to design the tournament structure and simulate the tournament using a Monte Carlo simulation approach.
For each iteration, we simulate each match using the given win probabilities from our simulate_match_result function. Using the calculated probabilities, we generate a random outcome from the distribution. We record that result for each match, moving on to the next until we complete the full tournament.
Once we simulate the tournament in its entirety N times (we currently use 10,000), we aggregate the number of times each team made it to each stage of the tournament, giving us the probability of each team making it to each stage of the tournament.
Accurate representation of complex tournament formats including group stages, playoffs, and bracket structures.
Bracket Traversal Algorithm
function simulate_bracket(teams, bracket_structure):
current_round = teams
for each round in bracket_structure:
next_round = []
for each match in current_round:
winner = simulate_match(match)
next_round.append(winner)
current_round = next_round
return current_round[0] # Tournament winnerGroup Stage Modeling
For tournaments with group stages, I simulate round-robin play within each group, then advance teams based on win-loss records and tiebreakers (head-to-head, map differential).
Dynamic Tournament Updates
The daily pipeline incorporates completed match results. Tournament projections can then be rerun on demand against the latest successfully processed map-Elo snapshot; they are not a streaming, real-time feed.
Multiple Tournament Formats
- Single Elimination Brackets
- Double Elimination Brackets
- Swiss System Tournaments
- Round Robin Groups
- Hybrid Group + Bracket Formats
The inspiration for my player rating systems comes as an attempt to create a Valorant version of the NBA's DARKO metric.
The DARKO metric uses a combination of classic statistics and modern machine learning techniques that updates after each game. You can read more about it in the link above.
Specifically I am modeling after the DPM (DARKO Plus Minus) statistic.
Overview: VPM (Valorant Plus Minus)
VPM is a composite player rating metric that combines traditional box score statistics with time-series modeling to estimate a player's true skill level in relation to rounds won or lost for their team compared to an average replacement player.
The system processes every map a player has ever played and outputs a single number that represents their current skill level, normalized to a standard 24-round map. The rating updates after each game, adapting to recent form while maintaining historical context.
Step 1: Statistical Components
The foundation of VPM consists of 7 per-round box-score statistics that capture different aspects of player performance:
- KPR (Kills Per Round): kills / total_rounds
- DPR (Deaths Per Round): deaths / total_rounds
- APR (Assists Per Round): assists / total_rounds
- FK Attempt Rate: (first_kills + first_deaths) / total_rounds
- FK Win Rate: first_kills / (first_kills + first_deaths)
- ADR: average damage per round (already normalized)
- KAST: Kill/Assist/Survive/Trade percentage (0-1 scale)
These components were selected because they correlate strongly with winning rounds while remaining relatively independent from each other, capturing distinct skill dimensions.
Step 2: Exponentially Weighted Moving Average (EMA)
Rather than treating all games equally, the system uses time-decay to emphasize recent performance. Each component maintains its own decay factor (β) tuned to how quickly that skill changes:
EMA_component = (Σ weight_i × value_i) / (Σ weight_i)
weight_i = rounds_played × β^(days_since_game)Step 3: Linear Regression Model
The 7 EMA components are combined using Ridge regression weights trained on historical data. The model predicts team round-winning probability based on player statistics:
VPM_raw = w₁×EMA_kpr + w₂×EMA_dpr + w₃×EMA_apr + w₄×EMA_fk_att_rate +
w₅×EMA_fk_win_rate + w₆×EMA_adr + w₇×EMA_kastRidge regularization (L2 penalty) prevents overfitting and ensures the model generalizes well to unseen matches. The weights are trained to maximize predictive accuracy on out-of-sample data.
Step 4: Kalman Filtering & Smoothing
The raw VPM values are noisy due to small sample sizes and variance in individual game performance. A Kalman filter provides optimal smoothing by modeling player skill as a latent state that evolves over time:
State Evolution:
x_t = a × x_(t-1) + process_noiseObservation Model:
y_t = x_t + measurement_noiseKalman Gain:
K_t = P_prior / (P_prior + R_t)Update:
x_t = x_prior + K_t × (y_t - x_prior)The filter accounts for variable game lengths (longer games provide more information) and time gaps between matches (uncertainty increases during inactivity). The Rauch-Tung-Striebel (RTS) smoother then performs a backward pass to refine historical estimates using future information.
Step 5: Centering & Normalization
The final VPM values are optionally centered by subtracting the league-average on each date. This ensures ratings are comparable across different eras and accounts for meta shifts that affect overall scoring levels. A VPM of +2.0 means the player provides 2 rounds worth of value above average per 24-round map.
Model Parameters
EMA Decay Factors (β):
- KPR, DPR, APR: 0.992
- FK Attempt Rate: 0.990
- FK Win Rate: 0.985 (most volatile)
- ADR: 0.993 (most stable)
- KAST: 0.991
Kalman Filter Parameters:
- a = 1.0 (state transition coefficient)
- q = 0.05 (process noise per day)
- r₀ = 1.0 (base measurement noise)
- use_days = true (time-aware dynamics)
Advantages Over Traditional Metrics
- Temporal Awareness: Recent performance weighted more heavily than old data
- Uncertainty Quantification: Confidence intervals provided for each rating
- Sample Size Adjustment: Smoothing prevents overreaction to small samples
- Multi-dimensional: Captures combat, trading, impact, and consistency
- Predictive: Trained to maximize correlation with team success
- Adaptive: Model can be retrained as the game evolves
Future Improvements
While the current VPM system provides strong predictive performance, several enhancements are planned:
- Map-specific models: Different weights for different maps (Jett better on Icebox, etc.)
- Agent adjustments: Normalize for expected agent performance (duelists vs sentinels)
- Additional Features: Incorporate additional features such as clutch percentage (1vX), Utility Efficiency, and in-game economy data.
Describing how closely historical choices align with a greedy map-Elo recommendation.
Overview
Every competitive Valorant match begins with a pick/ban phase where teams alternately select and eliminate maps. This analysis compares each observed choice with a greedy recommendation derived from map Elo ratings; it does not observe private coaching inputs or the result of an unplayed alternative.
The leakage-safe rebuild uses ratings strictly before the recorded match completion cutoff, excludes ratings produced by that same match, and defaults missing team/map ratings to 1000. Completion time is the proxy because match start is not stored. The resulting model-regret score measures alignment with that heuristic, not proven coaching quality or causal win lift. Ban comparisons are specifically counterfactual because a banned map is never played.
Greedy Pick Recommendation
For a pick, the heuristic recommends the available map with the acting team's largest Elo advantage:
Greedy Pick = argmax(Elo_Team(map) - Elo_Opponent(map))
Elo Advantage = Elo_Team(picked_map) - Elo_Opponent(picked_map)Pick model regret is the Elo-gap difference between the greedy recommendation and the observed pick. It measures departure from the heuristic, not a realized loss.
Greedy Ban Recommendation
For a ban, the heuristic recommends eliminating the available map where the acting team has the smallest Elo advantage (or largest disadvantage):
Greedy Ban = argmin(Elo_Team(map) - Elo_Opponent(map))
Model Regret = Observed_Advantage - Recommended_AdvantageThis is a counterfactual Elo comparison: the banned map has no observed match result. A positive gap means the choice differed from the model's greedy recommendation, not that the veto was a demonstrated strategic error.
Analysis Process
For each completed match:
- Retrieve ratings strictly before the recorded match completion cutoff, excluding rows produced by that same match; use 1000 when a team/map rating is missing
- Replay the pick/ban phase step-by-step in chronological order
- At each step, calculate the greedy Elo recommendation from the available maps
- Compare the observed choice with that recommendation
- Calculate local model regret, with zero for a recommendation-aligned choice
- Accumulate the local Elo-gap differences across the veto phase
- Store analysis results for aggregation and visualization
Cumulative Model Regret
Cumulative model regret sums the local Elo-gap differences throughout the veto phase. A value of zero means every evaluated choice matched the greedy recommendation; a larger value means the sequence departed from it more often or by larger Elo gaps. It does not measure surrendered competitive advantage, realized probability loss, or coaching skill.
Teams can be ranked by their average model regret across analyzed matches, but that ranking describes model alignment only and should not be interpreted as causal evidence of better preparation.