MA PAyment

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:

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.

Note:
To run the script, you'll need Person and Diagnosis data files along with a license key, which can be obtained by registering Here

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:

Risk Score = (Raw Risk Score / Normalization Factor) * (1 - 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:

Blended Risk Score = ((0.33 * V24 Risk Score) + (0.67 * V28 Risk Score))

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:

MA Payment = (Base Rate * Blended Risk Score)

Together, these equations ensure a straightforward process to calculate monthly MA payment values.

Generating MA Payments with MScore®

Note:
The entire code section below can be copied into a Python file and executed with a single command to generate Medicare Advantage monthly payments.

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.

import sourcedefender # This package is required at the top
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

Note:
We round the results to a maximum of three decimal places, as required by the CMS-HCC model.

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.

# Load data from the generated CSV files
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 for Parts A and B
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