Accurately predicting healthcare costs is essential in the intricate system of Medicare Advantage (MA) payments. At the heart of this process is the CMS-HCC model to calculate raw risk scores, which provide valuable insights into an enrollee’s health status and expected costs compared to the average beneficiary. By leveraging tools like MScore®, healthcare plans can efficiently generate and adjust risk scores in accordance with CMS guidelines. This article will break down how MA payments are calculated using the MScore® Python Package, offering a clear understanding of the financial structure behind Medicare Advantage.
The MScore® Python Package is a versatile and streamlined tool designed to integrate seamlessly into existing systems. MScore® allows healthcare companies to prioritize quality patient care while ensuring precise risk score calculations, helping to minimize the risk of audits. Before diving into the code, we’ll first cover the prerequisites to set up MScore®, ensuring the system is ready to generate raw risk scores efficiently.
With the MScore® package and Python, a single script can run the 2025 CMS-HCC models (V24 and V28), apply normalization and coding adjustment factors, blend the risk scores, and calculate MA payments—all in one command. The first part of the code will 1) focus on generating raw risk scores using the MScore® Python Package. Next, we’ll 2) apply the normalization factor, coding adjustment factor, and blend the scores from V24 and V28 to produce a single risk score. Finally, we’ll 3) calculate monthly MA payments based on the blended score.
Prerequisites
Before proceeding, ensure you have the following:
- MScore® License Key
- MScore® Python Package
- Python 3.10 to Python 3.11
- Person Data File
- Diagnosis Data File
- Three Steps to Visualizing Your CMS-HCC Risk Scores with MScore® & Python
We suggest starting the payment calculation process by reading, "Three Steps to Visualizing Your CMS-HCC Risk Scores with MScore® & Python," which provides a clear guide on running the CMS-HCC model with MScore® and visualizing the results. The Python script provided below builds upon these topics, offering a method to execute MScore® for both the V24 and V28 models for CY 2025 and save the output as a CSV file in your working directory.
Adjustment Factors and Medicare Payment equations
The equations highlighted in this article focus on the process of calculating risk scores from raw risk scores then blending risk scores across the weighted CMS-HCC V24 and V28 models. The Normalization Factor and Coding Pattern Adjustment Factor adjusts raw risk scores by dividing them by a model-specific normalization factor, and then applying a reduction to account for the Medicare Advantage (MA) coding pattern adjustment factor:
The Blending Risk Score Equation combines the risk scores of V24 and V28 models, weighting them to reflect the phased transition, where the V24 score is weighted at 33% and the V28 score at 67% for CY 2025:
Finally, the MA Payment Equation calculates the monthly payment value by multiplying the blended risk score by the base monthly rate for MA Parts A and B:
Together, these equations ensure a straightforward process to calculate monthly MA payment values.
Generating MA Payments with MScore®
Step 1: Generate V24 and V28 Raw Risk Scores with MScore®
In the first section of the code, person and diagnosis data are loaded from CSV files, and the MScore®Python Package is used to calculate risk scores for the CMS-HCC model versions V24 and V28 for the year 2025. The output consists of two CSV files, one for each model version, and a confirmation message is displayed once each file is saved. The generated filenames will reflect the version, year, and the total number of beneficiaries contained within the datasets.
from mscore import AuthorizeLicense, MScore
import pandas as pd
import numpy as np
from pathlib import Path
# Define the staging key for authorization
staging_key = 'your_license_key_here'
# Validate the authorization using the staging key
auth = AuthorizeLicense(staging_key).validate()
# Define model versions and years
versions_years = [
{'version': 'V24', 'year': '2025'},
{'version': 'V28', 'year': '2025'}
]
# Loop through each version and year
for item in versions_years:
version = item['version']
year = item['year']
# Read person and diagnosis data from CSV files
person_df = pd.read_csv('person.csv')
diag_df = pd.read_csv('diag.csv')
# Initialize the MScore model
model = MScore(
authorizer=auth,
year=year,
version=version,
model='CMS-HCC',
person_data=person_df,
diag_data=diag_df,
columns='all-fields',
rf_output=False,
)
# Calculate the risk scores
scores_data = model.score_mscore()
# Create DataFrames
scores_df = pd.DataFrame(scores_data.risk_scores)
# Get the number of beneficiaries
num_bene = len(scores_df)
# Create filename
filename = f"{version}_{year}_scores_{num_bene}.csv"
# Save DataFrame to CSV
scores_df.to_csv(filename, index=False)
# Print confirmation
print(f"Saved: {filename}")
Using the CNA_SCORE
values from the generated CSV files, the next step involves applying the normalization and coding adjustment factors,
along with blending the two versions (V24 and V28). Beneficiary 1008 from the V28 model will be at the top of the list,
as the absence of any HCC code impacts their arrangement compared to the beneficiary order of V24.
V24 2025
MBI | ... | CNA_SCORE | ... |
---|---|---|---|
1001 | ... | 0.817 | ... |
1002 | ... | 1.380 | ... |
1003 | ... | 0.355 | ... |
V28 2025
MBI | ... | CNA_SCORE | ... |
---|---|---|---|
1001 | ... | 0.812 | ... |
1002 | ... | 0.952 | ... |
1003 | ... | 1.506 | ... |
Step 2: Adjustment Factors and Blending Risk Scores
In this section of the code, risk score data from two CSV files (for the V24 and V28 model versions) is loaded.
The normalization factor and coding adjustment are applied to each model using predefined constants,
and the scores are blended based on specified percentage amounts.
The function generate_factors_and_blending_scores
handles the normalization factor, coding adjustment factor,
and blending of the V24 and V28 scores individually. The final output will be a blended payment_CNA_SCORE
.
score_file_v24 = Path.cwd().joinpath('V24_2025_scores_10.csv')
score_file_v28 = Path.cwd().joinpath('V28_2025_scores_10.csv')
# Load the CSV data
df_24 = pd.read_csv(score_file_v24)
df_28 = pd.read_csv(score_file_v28)
# Ensure both DataFrames are sorted by 'MBI' and aligned
common_mbis = np.intersect1d(df_24['MBI'], df_28['MBI'])
df_24 = df_24[df_24['MBI'].isin(common_mbis)].sort_values(by='MBI', ascending=True).reset_index(drop=True)
df_28 = df_28[df_28['MBI'].isin(common_mbis)].sort_values(by='MBI', ascending=True).reset_index(drop=True)
# Define constants
NORMALIZATION_FACTORS = {
'V24': 1.153,
'V28': 1.045
}
CODING_PATTERN_ADJUSTMENT = round(5.9/100, 3)
BLENDING_FACTORS = {
'V24': round(33/100, 3),
'V28': round(67/100, 3)
}
# Function to generate normalized and blended scores
def generate_payment_scores (df_24, df_28):
# Normalize and apply coding adjustment to both versions
df_24['normalized_CNA_SCORE'] = np.round(
df_24['CNA_SCORE'] / NORMALIZATION_FACTORS['V24'], 3
) * (1 - CODING_PATTERN_ADJUSTMENT)
df_28['normalized_CNA_SCORE'] = np.round(
df_28['CNA_SCORE'] / NORMALIZATION_FACTORS['V28'], 3
) * (1 - CODING_PATTERN_ADJUSTMENT)
# Apply blending factor
df_24['payment_CNA_SCORE'] = round(df_24['normalized_CNA_SCORE'] * BLENDING_FACTORS['V24'], 3)
df_28['payment_CNA_SCORE'] = round(df_28['normalized_CNA_SCORE'] * BLENDING_FACTORS['V28'], 3)
# Combine payment scores into single DataFrame
payment_df = df_24[['MBI', 'payment_CNA_SCORE']].copy()
payment_df['payment_CNA_SCORE'] += df_28['payment_CNA_SCORE']
return payment_df
# Generate blended payment scores
payment_scores = generate_payment_scores(df_24, df_28)
# Round all float columns to three decimal places
payment_scores = payment_scores.round(3)
The table below, Blended Payment Risk Score, presents the results after applying the normalization factor, coding adjustment factor, and blending process. The resulting column, payment_CNA_SCORE
, serves as a key component for calculating Medicare Advantage (MA) payments.
Blended Payment Risk Scores
MBI | payment_CNA_SCORE |
---|---|
1001 | 0.710 |
1002 | 0.946 |
1003 | 1.005 |
1004 | 0.860 |
1005 | 1.068 |
1006 | 2.183 |
1007 | 0.723 |
1008 | 0.553 |
1009 | 0.505 |
1010 | 3.396 |
Step 3: Calculate MA Payments
Finally, the code merges the normalized and blended risk scores from V24 and V28 into a DataFrame,
aggregating the relevant columns. It then introduces a new column, monthly_payment_value
,
calculated by multiplying the payment_CNA_SCORE
by a predefined base monthly rate that varies by county for
Medicare Parts A and B. For simplicity in this example, the base rate is taken as the average across all counties in the United States.
The final results, including the new payment values, are saved to a CSV file called blended_payment.csv
and displayed in the console.
BASE_MONTHLY_RATE_PARTS_A_AND_B = 1133.57
# Create the new column by multiplying payment_CNA_SCORE by the base rate
payment_scores['monthly_payment_value'] = (
payment_scores['payment_CNA_SCORE'] * BASE_MONTHLY_RATE_PARTS_A_AND_B
).round(2) # Round to two decimal places for currency formatting
# Export the DataFrame with the new column to a CSV file
payment_scores.to_csv('blended_payment.csv', index=False)
# View the final DataFrame with the new column
print(payment_scores)
The table below displays the final results of the blended risk scores and monthly payment values for each beneficiary.
MA Payment Values
MBI | payment_CNA_SCORE | monthly_payment_value |
---|---|---|
1001 | 0.710 | 804.83 |
1002 | 0.946 | 1072.36 |
1003 | 1.005 | 1139.24 |
1004 | 0.860 | 974.87 |
1005 | 1.068 | 1210.65 |
1006 | 2.183 | 2474.58 |
1007 | 0.723 | 819.57 |
1008 | 0.553 | 626.86 |
1009 | 0.505 | 572.45 |
1010 | 3.396 | 3849.60 |
Conclusion
The code above provides a simple and efficient way to calculate risk scores for the CMS-HCC model versions V24 and V28 for 2025 using the MScore® Python Package. By applying normalization and coding adjustment factors, and blending the scores, the script generates a single, accurate risk score for each beneficiary. This process helps you quickly calculate monthly Medicare Advantage (MA) payments based on these scores, offering a clear and comprehensive view of payment values. For healthcare providers, this means an easier and more reliable approach to managing MA payments, ensuring accuracy and compliance with CMS guidelines.
Disclaimer: The code examples above are for illustrative purposes and may require proper environment setup, license keys, or additional parameters to work effectively in your specific context. Always refer to MScore® documentation or reach out to support@riskadjustmentmodel.com if you have questions.
[1] Centers for Medicare & Medicaid Services. (2021). *Risk Adjustment Methodology*. CSSC Operations. https://csscoperations.com/internet/csscw3.nsf/RiskAdjustmentMethodologyTranscript.pdf