Main Content

Create Custom Lifetime PD Model for Credit Scorecard Model with Function Handle

This example shows how to use customLifetimePDModel to create a lifetime model for the probability of default. Using a retail credit data in panel format, you can create a credit scorecard model and then use a function handle with customLifetimePDModel to create a lifetime PD model.

Fit Credit Scorecard Model

Load the data set.

load RetailCreditPanelData.mat
data = join(data,dataMacro);

nIDs = max(data.ID);
uniqueIDs = unique(data.ID);

rng('default'); % for reproducibility
c = cvpartition(nIDs,'HoldOut',0.4);

TrainIDInd = training(c);
TestIDInd = test(c);

TrainDataInd = ismember(data.ID,uniqueIDs(TrainIDInd));
TestDataInd = ismember(data.ID,uniqueIDs(TestIDInd));

Use creditscorecard to create a creditscorecard object and then use autobinning to bin the data. Alternatively, you can bin the data using the Binning Explorer. You can fit the model using fitmodel.

sc = creditscorecard(data(TrainDataInd,:),'IDVar','ID','PredictorVars',{'ScoreGroup' 'YOB' 'GDP' 'Market'},'ResponseVar','Default')
sc = 
  creditscorecard with properties:

                GoodLabel: 0
              ResponseVar: 'Default'
               WeightsVar: ''
                 VarNames: {'ID'  'ScoreGroup'  'YOB'  'Default'  'Year'  'GDP'  'Market'}
        NumericPredictors: {'YOB'  'GDP'  'Market'}
    CategoricalPredictors: {'ScoreGroup'}
           BinMissingData: 0
                    IDVar: 'ID'
            PredictorVars: {'ScoreGroup'  'YOB'  'GDP'  'Market'}
                     Data: [388097x7 table]

sc = autobinning(sc);
sc = autobinning(sc,'YOB','Algorithm','Split');
sc = fitmodel(sc);
1. Adding ScoreGroup, Deviance = 42417.8562, Chi2Stat = 986.130141, PValue = 1.85820778e-216
2. Adding YOB, Deviance = 41644.7594, Chi2Stat = 773.096796, PValue = 3.81440566e-170
3. Adding Market, Deviance = 41616.8646, Chi2Stat = 27.8948108, PValue = 1.28092837e-07
4. Adding GDP, Deviance = 41612.2361, Chi2Stat = 4.62852205, PValue = 0.0314446396

Generalized linear regression model:
    logit(Default) ~ 1 + ScoreGroup + YOB + GDP + Market
    Distribution = Binomial

Estimated Coefficients:
                   Estimate       SE       tStat       pValue   
                   ________    ________    ______    ___________

    (Intercept)     4.6006     0.017273    266.35              0
    ScoreGroup     0.98953     0.033117     29.88    3.5837e-196
    YOB             1.0439      0.04216     24.76    2.4054e-135
    GDP             4.5496       2.1012    2.1652        0.03037
    Market          1.6892      0.44761    3.7738     0.00016076


388097 observations, 388092 error degrees of freedom
Dispersion: 1
Chi^2-statistic vs. constant model: 1.79e+03, p-value = 0
displaypoints(sc)
ans=16×3 table
      Predictors            Bin          Points 
    ______________    _______________    _______

    {'ScoreGroup'}    {'High Risk'  }    0.61946
    {'ScoreGroup'}    {'Medium Risk'}     1.3073
    {'ScoreGroup'}    {'Low Risk'   }     1.8816
    {'ScoreGroup'}    {'<missing>'  }        NaN
    {'YOB'       }    {'[-Inf,2)'   }    0.56097
    {'YOB'       }    {'[2,5)'      }     1.0021
    {'YOB'       }    {'[5,7)'      }     1.4673
    {'YOB'       }    {'[7,Inf]'    }     2.4996
    {'YOB'       }    {'<missing>'  }        NaN
    {'GDP'       }    {'[-Inf,0.63)'}      1.051
    {'GDP'       }    {'[0.63,Inf]' }     1.1664
    {'GDP'       }    {'<missing>'  }        NaN
    {'Market'    }    {'[-Inf,2.78)'}     1.0661
    {'Market'    }    {'[2.78,9.48)'}     1.1262
    {'Market'    }    {'[9.48,Inf]' }     1.2358
    {'Market'    }    {'<missing>'  }        NaN

Validate the creditscorecard model using validatemodel.

figure;
s = validatemodel(sc,data(TestDataInd,:),'Plot','roc');

Figure contains an axes object. The axes object with title Receiver Operating Characteristic (ROC) Curve, xlabel Fraction of Nondefaulters, ylabel Fraction of Defaulters contains 3 objects of type patch, line, text.

disp(s)
            Measure              Value 
    ________________________    _______

    {'Accuracy Ratio'      }    0.39124
    {'Area under ROC curve'}    0.69562
    {'KS statistic'        }    0.28409
    {'KS score'            }     4.6019

Wrap Credit Scorecard Model as Lifetime PD Model

Create a function handle for the probdefault function of the creditscorecard object. The only variable in the function handle (predictFcnHandle) is the data. The creditscorecard object (sc) is a fixed parameter of the probdefault function.

Use customLifetimePDModel to create an instance of a custom lifetime PD model using the function handle predictFcnHandle. Also, set up variable names for the model. The base class LifetimePDModel uses those variable names for different validations and computations.

predictFcnHandle = @(data)probdefault(sc,data);
pdModel = customLifetimePDModel(predictFcnHandle,'ModelID','MyScorecardModel','IDVar','ID','AgeVar','YOB','LoanVars','ScoreGroup','MacroVars',{'GDP','Market'},'ResponseVar','Default')
pdModel = 
  CustomLifetimePD with properties:

            ModelID: "MyScorecardModel"
        Description: ""
    UnderlyingModel: @(data)probdefault(sc,data)
              IDVar: "ID"
             AgeVar: "YOB"
           LoanVars: "ScoreGroup"
          MacroVars: ["GDP"    "Market"]
        ResponseVar: "Default"
         WeightsVar: ""
       TimeInterval: []

pdModel.UnderlyingModel
ans = function_handle with value:
    @(data)probdefault(sc,data)

Predict and Validate Scores Using Custom Lifetime PD Model

You can use pdModel like any other lifetime PD model. The training and test data sets are in panel data format and can be passed to either predict or predictLifetime. The predict function returns the conditional PD, the same prediction as the probdefault function for the credit scorecard. The predictLifetime function returns the cumulative probability of default for each ID. Here, the first ID in the test data set spans the first eight rows. The conditional PD can go up or down, but the cumulative PD always increases from one period to the next.

CondPD = predict(pdModel,data(TestDataInd,:));
LifetimePD = predictLifetime(pdModel,data(TestDataInd,:));
disp([CondPD(1:8) LifetimePD(1:8)])
    0.0154    0.0154
    0.0089    0.0241
    0.0089    0.0328
    0.0099    0.0424
    0.0066    0.0488
    0.0075    0.0559
    0.0022    0.0580
    0.0020    0.0599

By wrapping the credit scorecard as a lifetime PD model object (pdModel), you can use all the validation capabilities of lifetime PD models are available. Use modelCalibrationPlot to plot observed default rates compared to the predicted PDs on grouped data.

figure;
modelCalibrationPlot(pdModel,data(TestDataInd,:),'YOB')

Figure contains an axes object. The axes object with title Scatter Grouped by YOB MyScorecardModel, RMSE = 0.0014741, xlabel YOB, ylabel PD contains 2 objects of type line. One or more of the lines displays its values using only markers These objects represent Observed, MyScorecardModel.

Use modelDiscriminationPlot to plot the ROC curve.

figure;
modelDiscriminationPlot(pdModel,data(TestDataInd,:))

Figure contains an axes object. The axes object with title ROC MyScorecardModel, AUROC = 0.69562, xlabel Fraction of Non-Defaulters, ylabel Fraction of Defaulters contains an object of type line. This object represents MyScorecardModel.

Use modelDiscriminationPlot to plot the ROC curve and segment the data by ScoreGroup.

figure;
modelDiscriminationPlot(pdModel,data(TestDataInd,:),'SegmentBy','ScoreGroup')

Figure contains an axes object. The axes object with title ROC Segmented by ScoreGroup, xlabel Fraction of Non-Defaulters, ylabel Fraction of Defaulters contains 3 objects of type line. These objects represent MyScorecardModel, High Risk, AUROC = 0.62838, MyScorecardModel, Medium Risk, AUROC = 0.60867, MyScorecardModel, Low Risk, AUROC = 0.62568.

See Also

| | | | | | |

Related Examples

More About

External Websites