MGB Rate Change Thresholds
Question:
MGB would like to perform a ROID-level rate-change analysis between Clear Rates versions. The goal is to get more transparency into why rates are changing. As a part of this analysis, they would like to define ROID-level rate change thresholds to identify significant changes.
Definitions:
What does "significant change" mean? Basically, whatever falls outside of these defined thresholds will proceed to the variance attribution phase.
So "significant change" means that the absolute rate change is too big to be explained by normal contract updates and needs further investigation.
Inclusion Criteria:
There are a few different ways that we can define the data that goes into identifying these thresholds:
- Canonical Rate Score
- use all rates excluding outliers
- only include validated rates
- Rate Change
- use all rate changes
- use only non-zero rate changes
Using (a) all rates excluding outliers or (b) only validated rates should give similar results. If they are different, (b) would give us a better idea of what expected/normal rate changes look like. Although we don't do this anymore in Clear Rates, it's similar to the idea of using the distribution of validated rates to inform our outlier bound selection.
By only looking at non-zero rate changes, we are asking ourselves WHEN rates DO change, what's the expected distribution. This gets rid of all the ZERO rate changes that can make the distribution look tighter than it really is.
Summary of Analysis
| Approach | Rate Inclusion | Change Inclusion | 5th %ile | 25th %ile | 50th %ile | 75th %ile | 95th %ile |
|---|---|---|---|---|---|---|---|
| 1 | All rates (excl. outliers) | All changes | -0.6% | 0.0% | 0.0% | 0.0% | +19.7% |
| 2 | Validated only | All changes | 0.0% | 0.0% | 0.0% | 0.0% | +2.8% |
| 3 | All rates (excl. outliers) | Non-zero only | -54.1% | -2.4% | +4.6% | +35.6% | +662.4% |
| 4 | Validated only | Non-zero only | -7.4% | -0.2% | +2.7% | +5.8% | +38.3% |
Analysis
Approach 1: All Rates Excluding Outliers, All Rate Changes
Looking at all rates excluding outliers, and considering all rate changes (including zero changes), we see that the 5th percentile of rate changes is -0.6%, and the 95th percentile of rate changes is +19.7%.
| pct_change | |
|---|---|
| pct_01 | -0.455 |
| pct_02 | -0.183 |
| pct_03 | -0.067 |
| pct_04 | -0.024 |
| pct_05 | -0.006 |
| pct_25 | 0.000 |
| pct_50 | 0.000 |
| pct_75 | 0.000 |
| pct_90 | 0.013 |
| pct_91 | 0.027 |
| pct_92 | 0.045 |
| pct_93 | 0.069 |
| pct_94 | 0.115 |
| pct_95 | 0.197 |
| pct_99 | 5.154 |
SQL Query
WITH
new AS (
SELECT
roid,
canonical_rate as new_rate
FROM tq_dev.internal_dev_csong_cld_v2_3_0.prod_combined_abridged
WHERE canonical_rate_score > 1
AND provider_type = 'Hospital'
AND provider_id IN (
SELECT DISTINCT provider_id
FROM tq_dev.internal_dev_csong_cld_v2_3_0.tmp_whisper_provider_2025_10
WHERE provider_amc = True
)
AND network_type = 'PPO'
),
old AS (
SELECT
roid,
canonical_rate as old_rate
FROM tq_dev.internal_dev_csong_cld_v2_2_2.prod_combined_abridged
WHERE canonical_rate_score > 1
AND provider_type = 'Hospital'
AND provider_id IN (
SELECT DISTINCT provider_id
FROM tq_dev.internal_dev_csong_cld_v2_2_2.tmp_whisper_provider_2025_09
WHERE provider_amc = True
)
AND network_type = 'PPO'
),
stats AS (
SELECT
roid,
new_rate,
old_rate,
1.0000 * (new_rate - old_rate) / old_rate AS pct_diff
FROM new
JOIN old
USING (roid)
WHERE old_rate > 0
AND new_rate > 0
)
SELECT
APPROX_PERCENTILE(pct_diff, 0.01) AS pct_01,
APPROX_PERCENTILE(pct_diff, 0.02) AS pct_02,
APPROX_PERCENTILE(pct_diff, 0.03) AS pct_03,
APPROX_PERCENTILE(pct_diff, 0.04) AS pct_04,
APPROX_PERCENTILE(pct_diff, 0.05) AS pct_05,
APPROX_PERCENTILE(pct_diff, 0.25) AS pct_25,
APPROX_PERCENTILE(pct_diff, 0.50) AS pct_50,
APPROX_PERCENTILE(pct_diff, 0.75) AS pct_75,
APPROX_PERCENTILE(pct_diff, 0.90) AS pct_90,
APPROX_PERCENTILE(pct_diff, 0.91) AS pct_91,
APPROX_PERCENTILE(pct_diff, 0.92) AS pct_92,
APPROX_PERCENTILE(pct_diff, 0.93) AS pct_93,
APPROX_PERCENTILE(pct_diff, 0.94) AS pct_94,
APPROX_PERCENTILE(pct_diff, 0.95) AS pct_95,
APPROX_PERCENTILE(pct_diff, 0.99) AS pct_99
FROM stats
Approach 2: Only Validated Rates, All Rate Changes
Looking only at validated rates (canonical_rate_score = 5) and considering all rate changes, we see that the 5th percentile of rate changes is 0% and the 95th percentile of rate changes is +2.8%.
| pct_change | |
|---|---|
| pct_01 | -0.036 |
| pct_02 | -0.010 |
| pct_03 | -0.001 |
| pct_04 | -0.000 |
| pct_05 | -0.000 |
| pct_25 | 0.000 |
| pct_50 | 0.000 |
| pct_75 | 0.000 |
| pct_90 | 0.000 |
| pct_91 | 0.000 |
| pct_92 | 0.002 |
| pct_93 | 0.007 |
| pct_94 | 0.016 |
| pct_95 | 0.028 |
| pct_99 | 0.167 |
SQL Query
WITH
new AS (
SELECT
roid,
canonical_rate as new_rate
FROM tq_dev.internal_dev_csong_cld_v2_3_0.prod_combined_abridged
WHERE canonical_rate_score = 5
AND provider_type = 'Hospital'
AND provider_id IN (
SELECT DISTINCT provider_id
FROM tq_dev.internal_dev_csong_cld_v2_3_0.tmp_whisper_provider_2025_10
WHERE provider_amc = True
)
AND network_type = 'PPO'
),
old AS (
SELECT
roid,
canonical_rate as old_rate
FROM tq_dev.internal_dev_csong_cld_v2_2_2.prod_combined_abridged
WHERE canonical_rate_score = 5
AND provider_type = 'Hospital'
AND provider_id IN (
SELECT DISTINCT provider_id
FROM tq_dev.internal_dev_csong_cld_v2_2_2.tmp_whisper_provider_2025_09
WHERE provider_amc = True
)
AND network_type = 'PPO'
),
stats AS (
SELECT
roid,
new_rate,
old_rate,
1.0000 * (new_rate - old_rate) / old_rate AS pct_diff
FROM new
JOIN old
USING (roid)
WHERE old_rate > 0
AND new_rate > 0
)
SELECT
APPROX_PERCENTILE(pct_diff, 0.01) AS pct_01,
APPROX_PERCENTILE(pct_diff, 0.02) AS pct_02,
APPROX_PERCENTILE(pct_diff, 0.03) AS pct_03,
APPROX_PERCENTILE(pct_diff, 0.04) AS pct_04,
APPROX_PERCENTILE(pct_diff, 0.05) AS pct_05,
APPROX_PERCENTILE(pct_diff, 0.25) AS pct_25,
APPROX_PERCENTILE(pct_diff, 0.50) AS pct_50,
APPROX_PERCENTILE(pct_diff, 0.75) AS pct_75,
APPROX_PERCENTILE(pct_diff, 0.90) AS pct_90,
APPROX_PERCENTILE(pct_diff, 0.91) AS pct_91,
APPROX_PERCENTILE(pct_diff, 0.92) AS pct_92,
APPROX_PERCENTILE(pct_diff, 0.93) AS pct_93,
APPROX_PERCENTILE(pct_diff, 0.94) AS pct_94,
APPROX_PERCENTILE(pct_diff, 0.95) AS pct_95,
APPROX_PERCENTILE(pct_diff, 0.99) AS pct_99
FROM stats
Approach 3: All Rates Excluding Outliers, Non-Zero Rate Changes
Looking at all rates excluding outliers, and considering only non-zero rate changes, we see that the 5th percentile of rate changes is -54.1% and the 95th percentile of rate changes is +662.4%.
| pct_change | |
|---|---|
| pct_01 | -0.823 |
| pct_02 | -0.748 |
| pct_03 | -0.675 |
| pct_04 | -0.607 |
| pct_05 | -0.541 |
| pct_25 | -0.024 |
| pct_50 | 0.046 |
| pct_75 | 0.356 |
| pct_90 | 2.848 |
| pct_91 | 3.322 |
| pct_92 | 3.919 |
| pct_93 | 4.625 |
| pct_94 | 5.503 |
| pct_95 | 6.624 |
| pct_99 | 21.691 |
SQL Query
WITH
new AS (
SELECT
roid,
canonical_rate as new_rate
FROM tq_dev.internal_dev_csong_cld_v2_3_0.prod_combined_abridged
WHERE canonical_rate_score > 1
AND provider_type = 'Hospital'
AND provider_id IN (
SELECT DISTINCT provider_id
FROM tq_dev.internal_dev_csong_cld_v2_3_0.tmp_whisper_provider_2025_10
WHERE provider_amc = True
)
AND network_type = 'PPO'
),
old AS (
SELECT
roid,
canonical_rate as old_rate
FROM tq_dev.internal_dev_csong_cld_v2_2_2.prod_combined_abridged
WHERE canonical_rate_score > 1
AND provider_type = 'Hospital'
AND provider_id IN (
SELECT DISTINCT provider_id
FROM tq_dev.internal_dev_csong_cld_v2_2_2.tmp_whisper_provider_2025_09
WHERE provider_amc = True
)
AND network_type = 'PPO'
),
stats AS (
SELECT
roid,
new_rate,
old_rate,
1.0000 * (new_rate - old_rate) / old_rate AS pct_diff
FROM new
JOIN old
USING (roid)
WHERE old_rate > 0
AND new_rate > 0
)
SELECT
APPROX_PERCENTILE(pct_diff, 0.01) AS pct_01,
APPROX_PERCENTILE(pct_diff, 0.02) AS pct_02,
APPROX_PERCENTILE(pct_diff, 0.03) AS pct_03,
APPROX_PERCENTILE(pct_diff, 0.04) AS pct_04,
APPROX_PERCENTILE(pct_diff, 0.05) AS pct_05,
APPROX_PERCENTILE(pct_diff, 0.25) AS pct_25,
APPROX_PERCENTILE(pct_diff, 0.50) AS pct_50,
APPROX_PERCENTILE(pct_diff, 0.75) AS pct_75,
APPROX_PERCENTILE(pct_diff, 0.90) AS pct_90,
APPROX_PERCENTILE(pct_diff, 0.91) AS pct_91,
APPROX_PERCENTILE(pct_diff, 0.92) AS pct_92,
APPROX_PERCENTILE(pct_diff, 0.93) AS pct_93,
APPROX_PERCENTILE(pct_diff, 0.94) AS pct_94,
APPROX_PERCENTILE(pct_diff, 0.95) AS pct_95,
APPROX_PERCENTILE(pct_diff, 0.99) AS pct_99
FROM stats
WHERE pct_diff != 0
Approach 4: Only Validated Rates, Non-Zero Rate Changes
Looking only at validated rates (canonical_rate_score = 5) and considering only non-zero rate changes, we see that the 5th percentile of rate changes is -7.4% and the 95th percentile of rate changes is +38.3%.
| pct_change | |
|---|---|
| pct_01 | -0.288 |
| pct_02 | -0.170 |
| pct_03 | -0.123 |
| pct_04 | -0.093 |
| pct_05 | -0.074 |
| pct_25 | -0.002 |
| pct_50 | 0.027 |
| pct_75 | 0.058 |
| pct_90 | 0.152 |
| pct_91 | 0.185 |
| pct_92 | 0.221 |
| pct_93 | 0.265 |
| pct_94 | 0.313 |
| pct_95 | 0.383 |
| pct_99 | 5.244 |
SQL Query
WITH
new AS (
SELECT
roid,
canonical_rate as new_rate
FROM tq_dev.internal_dev_csong_cld_v2_3_0.prod_combined_abridged
WHERE canonical_rate_score = 5
AND provider_type = 'Hospital'
AND provider_id IN (
SELECT DISTINCT provider_id
FROM tq_dev.internal_dev_csong_cld_v2_3_0.tmp_whisper_provider_2025_10
WHERE provider_amc = True
)
AND network_type = 'PPO'
),
old AS (
SELECT
roid,
canonical_rate as old_rate
FROM tq_dev.internal_dev_csong_cld_v2_2_2.prod_combined_abridged
WHERE canonical_rate_score = 5
AND provider_type = 'Hospital'
AND provider_id IN (
SELECT DISTINCT provider_id
FROM tq_dev.internal_dev_csong_cld_v2_2_2.tmp_whisper_provider_2025_09
WHERE provider_amc = True
)
AND network_type = 'PPO'
),
stats AS (
SELECT
roid,
new_rate,
old_rate,
1.0000 * (new_rate - old_rate) / old_rate AS pct_diff
FROM new
JOIN old
USING (roid)
WHERE old_rate > 0
AND new_rate > 0
)
SELECT
APPROX_PERCENTILE(pct_diff, 0.01) AS pct_01,
APPROX_PERCENTILE(pct_diff, 0.02) AS pct_02,
APPROX_PERCENTILE(pct_diff, 0.03) AS pct_03,
APPROX_PERCENTILE(pct_diff, 0.04) AS pct_04,
APPROX_PERCENTILE(pct_diff, 0.05) AS pct_05,
APPROX_PERCENTILE(pct_diff, 0.25) AS pct_25,
APPROX_PERCENTILE(pct_diff, 0.50) AS pct_50,
APPROX_PERCENTILE(pct_diff, 0.75) AS pct_75,
APPROX_PERCENTILE(pct_diff, 0.90) AS pct_90,
APPROX_PERCENTILE(pct_diff, 0.91) AS pct_91,
APPROX_PERCENTILE(pct_diff, 0.92) AS pct_92,
APPROX_PERCENTILE(pct_diff, 0.93) AS pct_93,
APPROX_PERCENTILE(pct_diff, 0.94) AS pct_94,
APPROX_PERCENTILE(pct_diff, 0.95) AS pct_95,
APPROX_PERCENTILE(pct_diff, 0.99) AS pct_99
FROM stats
WHERE pct_diff != 0