В этом примере показано, как работать с данными о панели потребительского кредита, чтобы создать через цикл (TTC) и модели момента времени (PIT) и сравнить их соответствующие вероятности значения по умолчанию (PD).
PD должника является основным параметром риска в анализе кредитного риска. PD должника зависит от факторов риска для конкретного заказчика, а также макроэкономических факторов риска. Поскольку они включают макроэкономические условия по-другому, модели TTC и PIT производят различные оценки PD.
Мера по кредитному риску TTC, в основном, отражает тренд кредитного риска клиента за длительный срок. Сглаживаются переходные, краткосрочные изменения в кредитном риске, которые, вероятно, будут обращены с течением времени. Преобладающими функциями мер по кредитному риску TTC является своя высокая степень устойчивости по циклу кредита и гладкости изменения в зависимости от времени.
Мера по кредитному риску в области ЯМЫ использует всю доступную и уместную информацию с данной даты, чтобы оценить PD клиента за данный период времени. Информационный набор включает не только ожидания о тренде кредитного риска клиента за длительный срок, но также и географический, макроэкономический, и трендах макрокредита.
Ранее согласно Базелю II правил, регуляторы призвали к использованию ФУНТОВ TTC, потери, данные значение по умолчанию (LGDs) и воздействия в значении по умолчанию (ИДЗ). Однако с к новому IFRS9 и предложенным стандартам бухгалтерского учета CECL, регуляторы теперь требуют, чтобы учреждения использовали проекции PIT ФУНТОВ, LGDs и ИДЗА. Путем составления текущего состояния цикла кредита меры PIT тесно отслеживают изменения значения по умолчанию и уровней потерь в зависимости от времени.
Основной набор данных в этом примере (data) содержит следующие переменные:
ID — Идентификатор ссуды.
ScoreGroup — Кредитный рейтинг в начале ссуды, дискретизированной в три группы: High Risk, Medium Risk, и Low Risk.
YOB — Годы на книгах.
Default — Индикатор по умолчанию. Это - переменная отклика.
Year — Календарный год.
Данные также включают небольшой набор данных (dataMacro) с макроэкономическими данными в течение соответствующих календарных лет:
Year — Календарный год.
GDP — Рост валового внутреннего продукта (год за год).
Market — Рынок возвращается (год за год).
Переменные YOBгод, GDP, и Market наблюдаются в конце соответствующего календарного года. ScoreGroup дискретизация исходного кредитного рейтинга когда запущенная ссуда. Значение 1 для Default средние значения, что ссуда приняла значение по умолчанию в соответствующий календарный год.
Этот пример использует симулированные данные, но можно применить тот же подход к действительным наборам данных.
Загрузите данные и просмотрите первые 10 строк таблицы. Данные о панели сложены, и наблюдения для того же ID хранятся в непрерывных строках, составляя высокую, тонкую таблицу. Панель является несбалансированной, потому что не все идентификаторы имеют то же количество наблюдений.
load RetailCreditPanelData.mat
disp(head(data,10)); ID ScoreGroup YOB Default Year
__ ___________ ___ _______ ____
1 Low Risk 1 0 1997
1 Low Risk 2 0 1998
1 Low Risk 3 0 1999
1 Low Risk 4 0 2000
1 Low Risk 5 0 2001
1 Low Risk 6 0 2002
1 Low Risk 7 0 2003
1 Low Risk 8 0 2004
2 Medium Risk 1 0 1997
2 Medium Risk 2 0 1998
nRows = height(data);
UniqueIDs = unique(data.ID);
nIDs = length(UniqueIDs);
fprintf('Total number of IDs: %d\n',nIDs)Total number of IDs: 96820
fprintf('Total number of rows: %d\n',nRows)Total number of rows: 646724
Используйте Year как сгруппированная переменная, чтобы вычислить наблюдаемый уровень по умолчанию в течение каждого года. Используйте groupsummary функция, чтобы вычислить среднее значение Default переменная, группирующаяся Year переменная. Постройте результаты на графике рассеивания, который показывает, что уровень по умолчанию понижается, когда годы увеличиваются.
DefaultPerYear = groupsummary(data,'Year','mean','Default'); NumYears = height(DefaultPerYear); disp(DefaultPerYear)
Year GroupCount mean_Default
____ __________ ____________
1997 35214 0.018629
1998 66716 0.013355
1999 94639 0.012733
2000 92891 0.011379
2001 91140 0.010742
2002 89847 0.010295
2003 88449 0.0056417
2004 87828 0.0032905
subplot(2,1,1) scatter(DefaultPerYear.Year, DefaultPerYear.mean_Default*100,'*'); grid on xlabel('Year') ylabel('Default Rate (%)') title('Default Rate per Year') % Get IDs of the 1997, 1998, and 1999 cohorts IDs1997 = data.ID(data.YOB==1&data.Year==1997); IDs1998 = data.ID(data.YOB==1&data.Year==1998); IDs1999 = data.ID(data.YOB==1&data.Year==1999); % Get default rates for each cohort separately ObsDefRate1997 = groupsummary(data(ismember(data.ID,IDs1997),:),... 'YOB','mean','Default'); ObsDefRate1998 = groupsummary(data(ismember(data.ID,IDs1998),:),... 'YOB','mean','Default'); ObsDefRate1999 = groupsummary(data(ismember(data.ID,IDs1999),:),... 'YOB','mean','Default'); % Plot against the calendar year Year = unique(data.Year); subplot(2,1,2) plot(Year,ObsDefRate1997.mean_Default*100,'-*') hold on plot(Year(2:end),ObsDefRate1998.mean_Default*100,'-*') plot(Year(3:end),ObsDefRate1999.mean_Default*100,'-*') hold off title('Default Rate vs. Calendar Year') xlabel('Calendar Year') ylabel('Default Rate (%)') legend('Cohort 97','Cohort 98','Cohort 99') grid on

График показывает, что уровень по умолчанию уменьшается в зависимости от времени. Заметьте в графике что кредиты, запускающиеся в годах 1997, 1998, и 1 999 форм три когорты. Никакая ссуда в данных о панели не запускается после 1999. Это изображено более подробно в разделе "Years on Books Versus Calendar Years" примера на Стресс-тестировании Вероятностей Значения по умолчанию Потребительского кредита Используя Данные о Панели. Уменьшающийся тренд в этом графике объяснен тем, что существует только три когорты в данных и что шаблон для каждой когорты уменьшается.
ScoreGroup и годы на книгахМодели TTC в основном незатронуты экономическими условиями. Первая модель TTC в этом примере использует только ScoreGroup и YOB как предикторы уровня по умолчанию.
Сгенерируйте обучение и тестирующий наборы данных путем разделения существующих данных в обучение и тестирования наборов данных, которые используются для создания модели и валидации, соответственно.
NumTraining = floor(0.6*nIDs);
rng('default');
TrainIDInd = randsample(nIDs,NumTraining);
TrainDataInd = ismember(data.ID,UniqueIDs(TrainIDInd));
TestDataInd = ~TrainDataInd;Используйте fitglm функция, чтобы подбирать логистическую модель.
TTCModel = fitglm(data(TrainDataInd,:),... 'Default ~ 1 + ScoreGroup + YOB',... 'Distribution','binomial'); disp(TTCModel)
Generalized linear regression model:
logit(Default) ~ 1 + ScoreGroup + YOB
Distribution = Binomial
Estimated Coefficients:
Estimate SE tStat pValue
________ ________ _______ ___________
(Intercept) -3.2453 0.033768 -96.106 0
ScoreGroup_Medium Risk -0.7058 0.037103 -19.023 1.1014e-80
ScoreGroup_Low Risk -1.2893 0.045635 -28.253 1.3076e-175
YOB -0.22693 0.008437 -26.897 2.3578e-159
388018 observations, 388014 error degrees of freedom
Dispersion: 1
Chi^2-statistic vs. constant model: 1.83e+03, p-value = 0
Предскажите PD для обучения и тестирующий наборы данных с помощью predict.
data.TTCPD = zeros(height(data),1); % Predict in-sample data.TTCPD(TrainDataInd) = predict(TTCModel,data(TrainDataInd,:)); % Predict out-of-sample data.TTCPD(TestDataInd) = predict(TTCModel,data(TestDataInd,:));
Визуализируйте подходящую и подгонку из выборки в выборке.
PredTTCPDTrainYear = groupsummary(data(TrainDataInd,:),'Year','mean',... {'Default','TTCPD'}); f = figure; subplot(2,1,1) scatter(PredTTCPDTrainYear.Year,PredTTCPDTrainYear.mean_Default*100,'*'); hold on plot(PredTTCPDTrainYear.Year,PredTTCPDTrainYear.mean_TTCPD*100); hold off xlabel('Year') ylabel('Default Rate (%)') legend('Observed','Predicted') title('Model Fit (Training Data)') grid on PredTTCPDTestYear = groupsummary(data(TestDataInd,:),'Year','mean',... {'Default','TTCPD'}); subplot(2,1,2) scatter(PredTTCPDTestYear.Year,PredTTCPDTestYear.mean_Default*100,'*'); hold on plot(PredTTCPDTestYear.Year,PredTTCPDTestYear.mean_TTCPD*100); hold off xlabel('Year') ylabel('Default Rate (%)') legend('Observed','Predicted') title('Model Fit (Testing Data)') grid on

ScoreGroup, Годы на книгах, GDP и рынке возвращаютсяМодели PIT меняются в зависимости от экономического цикла. Модель PIT в этом примере использует ScoreGroup, YOB, GDP, и Market как предикторы уровня по умолчанию. Используйте fitglm функция, чтобы подбирать логистическую модель.
% Add the GDP and Market returns columns to the original data
data = join(data, dataMacro);
disp(head(data,10)) ID ScoreGroup YOB Default Year TTCPD GDP Market
__ ___________ ___ _______ ____ _________ _____ ______
1 Low Risk 1 0 1997 0.0084797 2.72 7.61
1 Low Risk 2 0 1998 0.0067697 3.57 26.24
1 Low Risk 3 0 1999 0.0054027 2.86 18.1
1 Low Risk 4 0 2000 0.0043105 2.43 3.19
1 Low Risk 5 0 2001 0.0034384 1.26 -10.51
1 Low Risk 6 0 2002 0.0027422 -0.59 -22.95
1 Low Risk 7 0 2003 0.0021867 0.63 2.78
1 Low Risk 8 0 2004 0.0017435 1.85 9.48
2 Medium Risk 1 0 1997 0.015097 2.72 7.61
2 Medium Risk 2 0 1998 0.012069 3.57 26.24
PITModel = fitglm(data(TrainDataInd,:),... 'Default ~ 1 + ScoreGroup + YOB + GDP + Market',... 'Distribution','binomial'); disp(PITModel)
Generalized linear regression model:
logit(Default) ~ 1 + ScoreGroup + YOB + GDP + Market
Distribution = Binomial
Estimated Coefficients:
Estimate SE tStat pValue
__________ _________ _______ ___________
(Intercept) -2.667 0.10146 -26.287 2.6919e-152
ScoreGroup_Medium Risk -0.70751 0.037108 -19.066 4.8223e-81
ScoreGroup_Low Risk -1.2895 0.045639 -28.253 1.2892e-175
YOB -0.32082 0.013636 -23.528 2.0867e-122
GDP -0.12295 0.039725 -3.095 0.0019681
Market -0.0071812 0.0028298 -2.5377 0.011159
388018 observations, 388012 error degrees of freedom
Dispersion: 1
Chi^2-statistic vs. constant model: 1.97e+03, p-value = 0
Предскажите PD для обучения и тестирующий наборы данных с помощью predict.
data.PITPD = zeros(height(data),1); % Predict in-sample data.PITPD(TrainDataInd) = predict(PITModel,data(TrainDataInd,:)); % Predict out-of-sample data.PITPD(TestDataInd) = predict(PITModel,data(TestDataInd,:));
Визуализируйте подходящую и подгонку из выборки в выборке.
PredPITPDTrainYear = groupsummary(data(TrainDataInd,:),'Year','mean',... {'Default','PITPD'}); figure; subplot(2,1,1) scatter(PredPITPDTrainYear.Year,PredPITPDTrainYear.mean_Default*100,'*'); hold on plot(PredPITPDTrainYear.Year,PredPITPDTrainYear.mean_PITPD*100); hold off xlabel('Year') ylabel('Default Rate (%)') legend('Observed','Predicted') title('Model Fit (Training Data)') grid on PredPITPDTestYear = groupsummary(data(TestDataInd,:),'Year','mean',... {'Default','PITPD'}); subplot(2,1,2) scatter(PredPITPDTestYear.Year,PredPITPDTestYear.mean_Default*100,'*'); hold on plot(PredPITPDTestYear.Year,PredPITPDTestYear.mean_PITPD*100); hold off xlabel('Year') ylabel('Default Rate (%)') legend('Observed','Predicted') title('Model Fit (Testing Data)') grid on

В модели PIT, как ожидалось, предсказания совпадают с наблюдаемыми уровнями по умолчанию более тесно, чем в модели TTC. Несмотря на то, что этот пример использует симулированные данные, качественно, тот же тип улучшения модели ожидается при перемещении от TTC до моделей PIT для данных о реальном мире, несмотря на то, что полная ошибка может быть больше, чем в этом примере. Подгонка модели PIT обычно лучше, чем подгонка модели TTC и предсказания обычно совпадают с наблюдаемыми уровнями.
Другой подход для вычисления ФУНТОВ TTC должен использовать модель PIT и затем заменить GDP и Market возвращается с соответствующими средними значениями. В этом подходе вы используете средние значения по целому экономическому циклу (или еще более длинный период) так, чтобы только базовые экономические условия влияли на модель, и любая изменчивость в уровнях по умолчанию происходит из-за других факторов риска. Можно также ввести предсказанные базовые значения для экономики, которые отличаются от среднего значения, наблюдаемого для нового экономического цикла. Например, использование медианы вместо среднего значения уменьшает ошибку.
Можно также использовать этот подход вычисления ФУНТОВ TTC при помощи модели PIT как инструмент для анализа сценариев, однако; это не может быть сделано в первой версии модели TTC. Добавленное преимущество этого подхода состоит в том, что можно использовать одну модель и для TTC и для предсказаний PIT. Это означает, что необходимо подтвердить и обеспечить только одну модель.
% Modify the data to replace the GDP and Market returns with the corresponding average values
data.GDP(:) = median(data.GDP);
data.Market = repmat(mean(data.Market), height(data), 1);
disp(head(data,10)); ID ScoreGroup YOB Default Year TTCPD GDP Market PITPD
__ ___________ ___ _______ ____ _________ ____ ______ _________
1 Low Risk 1 0 1997 0.0084797 1.85 3.2263 0.0093187
1 Low Risk 2 0 1998 0.0067697 1.85 3.2263 0.005349
1 Low Risk 3 0 1999 0.0054027 1.85 3.2263 0.0044938
1 Low Risk 4 0 2000 0.0043105 1.85 3.2263 0.0038285
1 Low Risk 5 0 2001 0.0034384 1.85 3.2263 0.0035402
1 Low Risk 6 0 2002 0.0027422 1.85 3.2263 0.0035259
1 Low Risk 7 0 2003 0.0021867 1.85 3.2263 0.0018336
1 Low Risk 8 0 2004 0.0017435 1.85 3.2263 0.0010921
2 Medium Risk 1 0 1997 0.015097 1.85 3.2263 0.016554
2 Medium Risk 2 0 1998 0.012069 1.85 3.2263 0.0095319
Предскажите PD для обучения и тестирующий наборы данных с помощью predict.
data.TTCPD2 = zeros(height(data),1); % Predict in-sample data.TTCPD2(TrainDataInd) = predict(PITModel,data(TrainDataInd,:)); % Predict out-of-sample data.TTCPD2(TestDataInd) = predict(PITModel,data(TestDataInd,:));
Визуализируйте подходящую и подгонку из выборки в выборке.
PredTTCPD2TrainYear = groupsummary(data(TrainDataInd,:),'Year','mean',... {'Default','TTCPD2'}); figure; subplot(2,1,1) scatter(PredTTCPD2TrainYear.Year,PredTTCPD2TrainYear.mean_Default*100,'*'); hold on plot(PredTTCPD2TrainYear.Year,PredTTCPD2TrainYear.mean_TTCPD2*100); hold off xlabel('Year') ylabel('Default Rate (%)') legend('Observed','Predicted') title('Model Fit (Training Data)') grid on PredTTCPD2TestYear = groupsummary(data(TestDataInd,:),'Year','mean',... {'Default','TTCPD2'}); subplot(2,1,2) scatter(PredTTCPD2TestYear.Year,PredTTCPD2TestYear.mean_Default*100,'*'); hold on plot(PredTTCPD2TestYear.Year,PredTTCPD2TestYear.mean_TTCPD2*100); hold off xlabel('Year') ylabel('Default Rate (%)') legend('Observed','Predicted') title('Model Fit (Testing Data)') grid on

Создайте итоговый график сравнить эти три модели и их ФУНТЫ.
figure scatter(PredPITPDTestYear.Year,PredPITPDTestYear.mean_Default*100, '*') hold on plot(PredTTCPDTestYear.Year,PredTTCPDTestYear.mean_TTCPD*100, 'Marker','o') plot(PredPITPDTestYear.Year,PredPITPDTestYear.mean_PITPD*100, 'Marker','square') plot(PredTTCPD2TestYear.Year,PredTTCPD2TestYear.mean_TTCPD2*100, 'Marker','diamond') hold off xlabel('Year') ylabel('Default Rate (%)') legend('default time','PD TTC','PD PIT','PD TTC 2') title('PIT PDs vs. TTC PDs') grid on

Этот график иллюстрирует, что модель PD PIT имеет лучшую подгонку, модель PD TTC имеет почти лучшую подгонку, и модель PD TTC 2 имеет третью лучшую подгонку.
Как мера качества, сравните среднеквадратическую ошибку ФУНТОВ модели PIT и TTC к наблюдаемым временам по умолчанию.
TTCRMSError = sqrt(mean((PredPITPDTestYear.mean_Default - PredTTCPDTestYear.mean_TTCPD).^2));
PITRMSError = sqrt(mean((PredPITPDTestYear.mean_Default - PredPITPDTestYear.mean_PITPD).^2));
TTC2RMSError = sqrt(mean((PredPITPDTestYear.mean_Default - PredTTCPD2TestYear.mean_TTCPD2).^2));
TTCMaxError = max(abs(PredPITPDTestYear.mean_Default - PredTTCPDTestYear.mean_TTCPD));
PITMaxError = max(abs(PredPITPDTestYear.mean_Default - PredPITPDTestYear.mean_PITPD));
TTC2MaxError = max(abs(PredPITPDTestYear.mean_Default - PredTTCPD2TestYear.mean_TTCPD2));
T = array2table([TTCRMSError, TTCMaxError; PITRMSError, PITMaxError; TTC2RMSError, TTC2MaxError]);
T.Properties.RowNames = {'TTC Model'; 'PIT Model'; 'TTC with PIT Model'};
T.Properties.VariableNames = {'Root Mean Squared Error', 'Maximum Error'};
disp(T); Root Mean Squared Error Maximum Error
_______________________ _____________
TTC Model 0.001964 0.0035249
PIT Model 0.00078292 0.0017776
TTC with PIT Model 0.0036801 0.0066774
Обобщенная линейная документация Моделей: https://www.mathworks.com/help/stats/generalized-linear-regression.html
Baesens, B., Д. Рош и Х. Шеул. Аналитика кредитного риска. Вайли, 2016.