Problem: Customer Transaction Aggregation and Filtering

The problem requires aggregating customer transaction data into key metrics (including total amount via Kahan sum, count, winsorized sum, sum of squares, mean, variance) with input validation, then filtering high-value customers using statistical techniques (medians, MAD, weighted Z-scores, KDE) to return qualifying customer IDs.

Background: ### Industry & Mathematical Background for Customer Transaction Analytics
These functions are purpose-built for **retail, e-commerce, and financial services** use cases where robust customer transaction analytics is critical for customer segmentation, lifetime value (CLV) modeling, and high-value customer (HVC) identification. The mathematical techniques chosen address real-world challenges with transaction data, ensuring accuracy, reliability, and actionable insights.

#### 1. Context for `aggregate_customer_data`
- **Kahan Summation**: In financial systems, summing millions of floating-point transaction amounts can introduce significant precision loss with standard summation. Kahan’s algorithm minimizes this error by tracking a compensation term, which is essential for regulatory reporting and accurate CLV calculations where even minor discrepancies matter.
- **Winsorization**: Transaction datasets are prone to outliers (e.g., one-time bulk purchases, fraudulent transactions). Winsorizing at the 1st/99th percentiles truncates extreme values, ensuring aggregated metrics are not skewed—critical for fair customer segmentation and avoiding biased business decisions.
- **Sum of Squares & Variance**: These metrics enable statistical modeling (e.g., regression for CLV prediction) and help identify customers with consistent vs. erratic spending patterns, which informs personalized marketing strategies.
- **Input Validation & Streaming Support**: Production systems process diverse data sources (POS terminals, online payment APIs). Strict validation prevents pipeline failures, while iterable/generator support allows efficient processing of large-scale streaming data without loading all records into memory—ideal for real-time transaction analytics.

#### 2. Context for `filter_high_value_customers`
- **Median Absolute Deviation (MAD)**: Transaction data is highly skewed (most customers have low spend/frequency, few have very high). MAD is more robust than standard deviation for measuring dispersion, ensuring HVC identification is not biased by extreme outliers.
- **Weighted Z-Scores**: Metrics like total spend (`M`) and transaction frequency (`F`) often have different variances. Weighted Z-scores normalize metrics by their inverse variance, giving more weight to metrics with higher variability—critical for balancing spend and frequency when defining high-value customers.
- **Kernel Density Estimation (KDE)**: KDE identifies customers in dense clusters of high-value behavior, distinguishing consistent high spenders (who form meaningful clusters) from one-off outliers (who are isolated). This ensures marketing resources are allocated to customers with sustainable high value, not just temporary spikes.
- **Three-Tiered Filtering**: The combination of minimum thresholds, statistical deviation, and density checks ensures only customers that meet business requirements, are statistically significant, and are part of a valid high-value group are selected—ideal for loyalty program eligibility or targeted retention campaigns.

### Required Import Statements
import numpy as np
import math
from collections import defaultdict
from typing import Any, Dict, Hashable, Iterable, List, Union
from scipy.stats import gaussian_kde

Input/Output: The problem takes an iterable of transaction dictionaries (each containing 'customer_id' (hashable) and 'amount' (int/float)) and two numeric thresholds (min_m for minimum total transaction amount, min_f for minimum transaction count). It first aggregates transactions into a dictionary mapping customer IDs to metrics including total amount (Kahan sum), transaction count, winsorized sum, sum of squares, mean, and variance. It then filters this customer data using median absolute deviation, weighted Z-scores, and Gaussian KDE to identify customers meeting three conditions: total amount above min_m, count above min_f, weighted norm exceeding the threshold derived from min_m/min_f, and KDE density above the threshold from min_m/min_f. The output is a list of qualifying customer IDs.

Required dependencies:
import numpy as np
import math
from collections import defaultdict
from typing import Any, Dict, Hashable, Iterable, List, Union
from scipy.stats import gaussian_kde

Sub-steps:
step_number: 1
step_description_prompt: Please write a Python function named aggregate_customer_data that takes an iterable of transaction dicts (with 'customer_id' and 'amount') and returns a dict mapping customer IDs to metrics including total amount (Kahan sum), count, winsorized sum, sum of squares, mean, variance. Include input validation and handle outliers via winsorization.
function_header: def aggregate_customer_data(transactions):
test_cases: for txns, expected in [
    ([], {}),
    ([{'customer_id': 'A', 'amount': 100}], {'A': {'M': 100.0, 'F': 1}}),
    ([{'customer_id': 'A', 'amount': 50}, {'customer_id': 'B', 'amount': 30}, {'customer_id': 'A', 'amount': 20}],
     {'A': {'M': 70.0, 'F': 2}, 'B': {'M': 30.0, 'F': 1}})
]:
    actual_val = aggregate_customer_data(txns)
    # Compare dictionaries with tolerance for float values
    if isinstance(actual_val, dict) and isinstance(expected, dict):
        assert len(actual_val) == len(expected), f"Dict lengths differ: {len(actual_val)} vs {len(expected)}"
        for key in expected:
            assert key in actual_val, f"Key {key} missing in actual"
            if isinstance(expected[key], dict) and isinstance(actual_val[key], dict):
                for subkey in expected[key]:
                    assert subkey in actual_val[key], f"Subkey {subkey} missing"
                    if isinstance(expected[key][subkey], float):
                        assert math.isclose(actual_val[key][subkey], expected[key][subkey], rel_tol=1e-3) or abs(actual_val[key][subkey] - expected[key][subkey]) < 1e-6
                    else:
                        assert actual_val[key][subkey] == expected[key][subkey]
            else:
                assert actual_val[key] == expected[key]
    else:
        assert actual_val == expected

step_number: 2
step_description_prompt: Please write a Python function named filter_high_value_customers. It validates inputs first, computes medians, MADs, weighted Z-scores, KDE densities. Then applies three conditions (values above mins, weighted norm over threshold, density over threshold) to return qualifying customer IDs.
function_header: def filter_high_value_customers(customer_data, min_m, min_f):
test_cases: exp1 = filter_high_value_customers({}, 100, 1)
exp2 = filter_high_value_customers({'A': {'M': 150, 'F': 2}, 'B': {'M': 80, 'F': 3}}, 100, 1)
exp3 = filter_high_value_customers({'X': {'M': 200, 'F': 1}, 'Y': {'M': 50, 'F': 5}, 'Z': {'M': 150, 'F': 3}}, 100, 2)
for cust_data, min_m, min_f, expected in [
    ({}, 100, 1, exp1),
    ({'A': {'M': 150, 'F': 2}, 'B': {'M': 80, 'F': 3}}, 100, 1, exp2),
    ({'X': {'M': 200, 'F': 1}, 'Y': {'M': 50, 'F': 5}, 'Z': {'M': 150, 'F': 3}}, 100, 2, exp3)
]:
    actual_val = filter_high_value_customers(cust_data, min_m, min_f)
    actual_list = list(actual_val) if isinstance(actual_val, tuple) else actual_val
    expected_list = list(expected) if isinstance(expected, tuple) else expected
    assert actual_list == expected_list, f"Result mismatch: actual={actual_list}, expected={expected_list}"

General solution:

General tests: