Implement a panel-aware blocked time-series cross-validation splitter with an embargo. Input: DataFrame columns [loan_id, msa, month]. Requirements: (1) K=5 expanding-window folds with cutoffs t1<...<t5; for fold k, train on months <= tk−embargo and test on (tk−embargo, tk+1]; embargo = 90 days prevents any loan_id from appearing in both sets within the window. (2) Support grouped blocking so that in at least one fold, an entire MSA's months are held out as test while preserving temporal order within each MSA. (3) Ensure determinism and stability under shuffled input. (4) Output precise algorithm steps or pseudocode plus time complexity in N rows, G MSAs, and K folds; discuss memory characteristics. (5) Describe unit tests for adversarial cases: duplicate timestamps, missing months, loan migration across MSAs, and highly imbalanced MSAs.