Skip to main content

fee-delta-and-impact-simulation

Solve dabstep Fee_Delta_and_Impact_Simulation questions: computing fee deltas when a fee's rate changes, identifying which merchants are affected by fee rule changes, and computing fee deltas when a merchant's MCC changes. Use when asked about fee impact, delta payments, rate changes, MCC code changes, or which merchants would be affected by modifying a fee rule.

Source facts

Repository
zjunlp/DataMind
Last source activity
July 5, 2026 at 09:13
Detected SKILL.md language
English
Stars
149
Forks
13

Install options

The review-first prompt is selected by default. You can switch to a direct command or download a local copy.

Review the source files

Read SKILL.md and any companion files shown by SkillsMP before deciding whether to install.

Showing SKILL.md

SKILL.md
Source instructions · Read-only preview
name
Fee_Delta_and_Impact_Simulation
description
Solve dabstep Fee_Delta_and_Impact_Simulation questions: computing fee deltas when a fee's rate changes, identifying which merchants are affected by fee rule changes, and computing fee deltas when a merchant's MCC changes. Use when asked about fee impact, delta payments, rate changes, MCC code changes, or which merchants would be affected by modifying a fee rule.
# Fee Delta and Impact Simulation This skill covers three question types: 1. **Rate-change delta**: How much more/less would a merchant pay if a specific fee's rate changed? 2. **Affected-merchant identification**: Which merchants would be impacted if a fee rule's applicability changed? 3. **MCC-change delta**: How much more/less would a merchant pay if its MCC code changed? ## CRITICAL: Submit Immediately After Computing **Do NOT spend extra turns verifying individual transactions or investigating unmatched transactions.** Once you have the computed delta, print it and submit. It is completely normal for 40–70% of transactions to have no matching fee rule — this is expected behavior, not a bug. ## Data Files | File | Purpose | |------|---------| | `fees.json` | 1000 fee rules with matching criteria and rates | | `payments.csv` | 138,236 transactions (all year 2023) | | `merchant_data.json` | 30 merchants with account_type, MCC, capture_delay, acquirers | | `acquirer_countries.csv` | Maps acquirer names → country codes (rarely needed) | | `manual.md` | Domain definitions (read first) | ## Key Domain Rules ### Fee Formula ``` fee = fixed_amount + rate * transaction_value / 10000 ``` **"Relative fee"** = the `rate` field. When a question says "relative fee changed to X", it means the `rate` changes from its current value to X. ### Fee Rule Matching A transaction/merchant matches a fee rule when ALL conditions hold: | Fee field | Condition | |-----------|-----------| | `card_scheme` | Exact match with transaction's card_scheme | | `account_type` | `[]` (empty list) = applies to all; else merchant's account_type must be in the list | | `merchant_category_code` | `[]` (empty list) = applies to all; else merchant's MCC must be in the list | | `capture_delay` | `null` = applies to all; else see mapping below | | `monthly_fraud_level` | `null` = applies to all; else see calculation below | | `monthly_volume` | `null` = applies to all; else see calculation below | | `is_credit` | `null` = applies to all; else must equal transaction's is_credit | | `aci` | `[]` (empty list) or `null` = applies to all; else transaction's aci must be in the list | | `intracountry` | `null` = applies to all; `1.0` = issuing_country == acquirer_country; `0.0` = issuing_country != acquirer_country | **Critical**: Empty list `[]` for `account_type`, `merchant_category_code`, and `aci` means "applies to all values". **When multiple fees match a transaction**: Use the **first matching fee** — iterate fees.json in order (fees are sorted by ascending ID) and return the FIRST fee that satisfies ALL criteria. Do NOT pick the most-specific one or sum them all. ### Capture Delay Mapping Merchant `capture_delay` values must be mapped to fee rule categories: ```python def capture_delay_matches(merchant_val, fee_val): if fee_val is None: return True if merchant_val in ('immediate', 'manual'): return merchant_val == fee_val n = int(merchant_val) if fee_val == '<3': return n < 3 if fee_val == '3-5': return 3 <= n <= 5 if fee_val == '>5': return n > 5 return False ``` ### Monthly Fraud Level Calculation Compute per merchant per natural calendar month (using day_of_year): ```python fraud_volume = sum(eur_amount where has_fraudulent_dispute == True) total_volume = sum(eur_amount) fraud_ratio = fraud_volume / total_volume * 100 # as percentage # Map to fee rule category: # '<7.2%' : ratio < 7.2 # '7.2%-7.7%': 7.2 <= ratio <= 7.7 # '7.7%-8.3%': 7.7 <= ratio <= 8.3 # '>8.3%' : ratio > 8.3 ``` ### Monthly Volume Calculation Compute per merchant per natural calendar month: ```python monthly_total = sum(eur_amount) # in euros # Map to fee rule category: # '<100k' : total < 100,000 # '100k-1m': 100,000 <= total <= 1,000,000 # '1m-5m' : 1,000,000 < total <= 5,000,000 # '>5m' : total > 5,000,000 ``` ### Month → day_of_year (2023, non-leap year) | Month | day_of_year range | |-------|-------------------| | January | 1–31 | | February | 32–59 | | March | 60–90 | | April | 91–120 | | May | 121–151 | | June | 152–181 | | July | 182–212 | | August | 213–243 | | September | 244–273 | | October | 274–304 | | November | 305–334 | | December | 335–365 | ### Intracountry Use `acquirer_country` directly from `payments.csv` (already resolved). Compare with `issuing_country`: ```python is_intracountry = (row['issuing_country'] == row['acquirer_country']) ``` --- ## Question Type 1: Rate-Change Delta **Question pattern**: "In [period] what delta would [merchant] pay if the relative fee of the fee with ID=[X] changed to [Y]?" ### CRITICAL: Do NOT Check First-Match for Rate-Change For Q1, **do NOT verify whether fee X is the first matching fee** for each transaction. The question asks for the direct impact of changing fee X's rate. Simply filter all transactions that match fee X's criteria (card_scheme, account_type, MCC, capture_delay, is_credit, aci, intracountry) and compute the delta. This is intentional — you are computing the delta on all transactions to which fee X's criteria apply. ### Step-by-step Algorithm ```python import json, pandas as pd # 1. Load fee rule with open('fees.json') as f: fees = json.load(f) fee = next(f for f in fees if f['ID'] == X) old_rate = fee['rate'] new_rate = Y # from question # 2. Load merchant properties with open('merchant_data.json') as f: merchants = json.load(f) merchant = next(m for m in merchants if m['merchant'] == MERCHANT_NAME) # 3. Load payments and filter by merchant + time period payments = pd.read_csv('payments.csv') mask = (payments['merchant'] == MERCHANT_NAME) # For a specific month: also filter day_of_year range # For a full year: no day_of_year filter needed # 4. Check merchant-level criteria (checked once, not per transaction) if fee['account_type'] and merchant['account_type'] not in fee['account_type']: print("Delta = 0 (merchant does not match fee's account_type)") elif fee['merchant_category_code'] and merchant['merchant_category_code'] not in fee['merchant_category_code']: print("Delta = 0 (merchant does not match fee's MCC)") elif fee['capture_delay'] is not None and not capture_delay_matches(merchant['capture_delay'], fee['capture_delay']): print("Delta = 0 (merchant does not match fee's capture_delay)") else: # 5. Filter transactions by fee's transaction-level criteria mask &= (payments['card_scheme'] == fee['card_scheme']) if fee['is_credit'] is not None: mask &= (payments['is_credit'] == fee['is_credit']) if fee['aci']: # non-empty list mask &= payments['aci'].isin(fee['aci']) if fee['intracountry'] is not None: if fee['intracountry'] == 1.0: mask &= (payments['issuing_country'] == payments['acquirer_country']) else: mask &= (payments['issuing_country'] != payments['acquirer_country']) # 6. Handle monthly conditions (if fee has monthly_fraud_level or monthly_volume) # If both are null: just sum all matching transactions # If either is non-null: must filter month by month matching = payments[mask] total_amount = matching['eur_amount'].sum() delta = (new_rate - old_rate) * total_amount / 10000 print(f"{delta:.14f}") ``` ### Important: Monthly Conditions for Rate-Change When the fee has `monthly_fraud_level` or `monthly_volume` != null, these are **merchant-level, month-level** conditions. For a single-month query, calculate for that month. For a full-year query, the fee may apply in some months but not others — filter transactions month-by-month. --- ## Question Type 2: Affected Merchants (Account Type Change) **Question pattern**: "During 2023, imagine if the Fee with ID [X] was only applied to account type [T], which merchants would have been affected by this change?" ### Interpretation "Affected" = merchants whose fee X application STATUS CHANGES: - Currently: if `account_type = []` (applies to all), ALL matching merchants use fee X - After change: only account_type T merchants use fee X - Affected = merchants whose current status ≠ new status AND who have transactions matched by other fee criteria ### Step-by-step Algorithm ```python # 1. Load fee rule fee = next(f for f in fees if f['ID'] == X) # 2. For each merchant, check if fee status changes affected = [] for m in merchants: # Check merchant-level criteria (MCC, capture_delay) - excluding account_type if fee['merchant_category_code'] and m['merchant_category_code'] not in fee['merchant_category_code']: continue if fee['capture_delay'] is not None and not capture_delay_matches(m['capture_delay'], fee['capture_delay']): continue # Check if merchant has any matching transactions (transaction-level filters) m_payments = payments[payments['merchant'] == m['merchant']] mask = (m_payments['card_scheme'] == fee['card_scheme']) if fee['is_credit'] is not None: mask &= (m_payments['is_credit'] == fee['is_credit']) if fee['aci']: mask &= m_payments['aci'].isin(fee['aci']) if fee['intracountry'] is not None: if fee['intracountry'] == 1.0: mask &= (m_payments['issuing_country'] == m_payments['acquirer_country']) else: mask &= (m_payments['issuing_country'] != m_payments['acquirer_country']) if mask.sum() == 0: continue # No matching transactions # Check if account_type status changes currently_applies = not fee['account_type'] or m['account_type'] in fee['account_type'] would_apply = (m['account_type'] == T) # after the change if currently_applies != would_apply: affected.append(m['merchant']) print(', '.join(sorted(affected))) ``` --- ## Question Type 3: MCC-Change Delta **Question pattern**: "Imagine the merchant [M] had changed its MCC code to [NEW_MCC] before 2023 started, what amount delta will it have to pay in fees for the year 2023?" ### Algorithm For each transaction, find the first matching fee under the OLD MCC and NEW MCC separately. Delta = total_fees(new_mcc) - total_fees(old_mcc). **Write this as a single complete script — do not split into multiple exploration steps to avoid hitting turn limits.** ```python import json import pandas as pd # Load data with open('fees.json') as f: fees = json.load(f) with open('merchant_data.json') as f: merchants = json.load(f) payments = pd.read_csv('payments.csv') # Merchant info merchant = next(m for m in merchants if m['merchant'] == MERCHANT_NAME) old_mcc = merchant['merchant_category_code'] new_mcc = NEW_MCC # from question acct_type = merchant['account_type'] cap_delay = str(merchant['capture_delay']) # Filter transactions for this merchant df = payments[payments['merchant'] == MERCHANT_NAME].copy() MONTH_RANGES = { 1:(1,31), 2:(32,59), 3:(60,90), 4:(91,120), 5:(121,151), 6:(152,181), 7:(182,212), 8:(213,243), 9:(244,273), 10:(274,304), 11:(305,334), 12:(335,365) } def day_to_month(day): for m, (s, e) in MONTH_RANGES.items(): if s <= day <= e: return m return 12 df['month'] = df['day_of_year'].apply(day_to_month) # Precompute monthly fraud and volume categories def get_fraud_cat(ratio): if ratio < 7.2: return '<7.2%' if ratio <= 7.7: return '7.2%-7.7%' if ratio <= 8.3: return '7.7%-8.3%' return '>8.3%' def get_vol_cat(vol): if vol < 100000: return '<100k' if vol <= 1000000: return '100k-1m' if vol <= 5000000: return '1m-5m' return '>5m' monthly_cats = {} for month in range(1, 13): md = df[df['month'] == month]
View on GitHub
This SKILL.md is very large, so SkillsMP previews the first section here. View on GitHub