В этом примере показано, как работать с данными о панели потребительского кредита, чтобы создать через цикл (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.