Visualize Transitions Data for `transprob`

This example shows how to visualize credit rating transitions that are used as an input to the `transprob` function. The example also describes how the `transprob` function treats rating transitions when the company data starts after the start date of the analysis, or when the end date of the analysis is after the last transition observed.

Sample Data

Set up fictitious sample data for illustration purposes.

```data = {'ABC','17-Feb-2015','AA'; 'ABC','6-Jul-2017','A'; 'LMN','12-Aug-2014','B'; 'LMN','9-Nov-2015','CCC'; 'LMN','7-Sep-2016','D'; 'XYZ','14-May-2013','BB'; 'XYZ','21-Jun-2016','BBB'}; data = cell2table(data,'VariableNames',{'ID','Date','Rating'}); disp(data)```
``` ID Date Rating _______ _______________ _______ {'ABC'} {'17-Feb-2015'} {'AA' } {'ABC'} {'6-Jul-2017' } {'A' } {'LMN'} {'12-Aug-2014'} {'B' } {'LMN'} {'9-Nov-2015' } {'CCC'} {'LMN'} {'7-Sep-2016' } {'D' } {'XYZ'} {'14-May-2013'} {'BB' } {'XYZ'} {'21-Jun-2016'} {'BBB'} ```

The `transprob` function understands that this panel-data format indicates the dates when a new rating is assigned to a given company. `transprob` assumes that such ratings remain unchanged, unless a subsequent row explicitly indicates a rating change. For example, for company `'ABC'`, `transprob` understands that the `'A'` rating is unchanged for any date after `'6-Jul-2017'` (indefinitely).

Compute Transition Matrix and Transition Counts

The `transprob` function returns a transition probability matrix as the primary output. There are also optional outputs that contain additional information for how many transitions occurred. For more information, see `transprob` for information on the optional outputs for both the `'cohort'` and the `'duration'` methods.

For illustration purposes, this example allows you to pick the `StartYear` (limited to `2014` or `2015` for this example) and the `EndYear` (`2016` or `2017`). This example also uses the `hDisplayTransitions` helper function (see the Local Functions section) to format the transitions information for ease of reading.

```StartYear = 2014; EndYear = 2017; startDate = datetime(StartYear,12,31,'Locale','en_US'); endDate = datetime(EndYear,12,31,'Locale','en_US'); RatingLabels = ["AAA","AA","A","BBB","BB","B","CCC","D"]; [tm,st,it] = transprob(data,'startDate',startDate,'endDate',endDate,'algorithm','cohort','labels',RatingLabels);```

The transition probabilities of the `TransMat` output indicate the probability of migrating between ratings. The probabilities are expressed in %, that is, they are multiplied by 100.

`hDisplayTransitions(tm,RatingLabels,"Transition Matrix")`
```Transition Matrix AAA AA A BBB BB B CCC D ___ __ ___ ___ __ _ ___ ___ AAA 100 0 0 0 0 0 0 0 AA 0 50 50 0 0 0 0 0 A 0 0 100 0 0 0 0 0 BBB 0 0 0 100 0 0 0 0 BB 0 0 0 50 50 0 0 0 B 0 0 0 0 0 0 100 0 CCC 0 0 0 0 0 0 0 100 D 0 0 0 0 0 0 0 100 ```

The transition counts are stored in the `sampleTotals` optional output and indicate how many transitions occurred between ratings for the entire sample (that is, all companies).

`hDisplayTransitions(st.totalsMat,RatingLabels,"Transition counts, all companies")`
```Transition counts, all companies AAA AA A BBB BB B CCC D ___ __ _ ___ __ _ ___ _ AAA 0 0 0 0 0 0 0 0 AA 0 1 1 0 0 0 0 0 A 0 0 0 0 0 0 0 0 BBB 0 0 0 1 0 0 0 0 BB 0 0 0 1 1 0 0 0 B 0 0 0 0 0 0 1 0 CCC 0 0 0 0 0 0 0 1 D 0 0 0 0 0 0 0 1 ```

The third output of `transprob` is `idTotals` that contains information about transitions at an ID level, company by company (in the same order that the companies appear in the input data).

Select a company to display the transition counts and a corresponding visualization of the transitions. The `hPlotTransitions` helper function (see the Local Functions section) shows the transitions history for a company.

```CompanyID = "ABC"; UniqueIDs = unique(data.ID,'stable'); [~,CompanyIndex] = ismember(CompanyID,UniqueIDs); hDisplayTransitions(it(CompanyIndex).totalsMat,RatingLabels,strcat("Transition counts, company ID: ",CompanyID))```
```Transition counts, company ID: ABC AAA AA A BBB BB B CCC D ___ __ _ ___ __ _ ___ _ AAA 0 0 0 0 0 0 0 0 AA 0 1 1 0 0 0 0 0 A 0 0 0 0 0 0 0 0 BBB 0 0 0 0 0 0 0 0 BB 0 0 0 0 0 0 0 0 B 0 0 0 0 0 0 0 0 CCC 0 0 0 0 0 0 0 0 D 0 0 0 0 0 0 0 0 ```
`hPlotTransitions(CompanyID,startDate,endDate,data,RatingLabels)`

To understand how `transprob` handles data when the first observed date is after the start date of the analysis, or whose last observed date occurs before the end date of the analysis, consider the following example. For company `'ABC'` suppose that the analysis has a start date of `31-Dec-2014` and end date of `31-Dec-2017`. There are only two transitions reported for this company for that analysis time window. The first observation for `'ABC'` happened on `17-Feb-2015`. So the `31-Dec-2015` snapshot is the first time the company is observed. By `31-Dec-2016`, the company remained in the original `'AA'` rating. By `31-Dec-2017`, a downgrade to `'A'` is recorded. Consistent with this, the transition counts show one transition from `'AA'` to `'AA'` (from the end of 2015 to the end of 2016), and one transition from `'AA'` to `'A'` (from the end of 2016 to the end of 2017). The plot shows the last rating as a dotted red line to emphasize that the last rating in the data is extrapolated indefinitely into the future. There is no extrapolation into the past; the company's history is ignored until a company rating is known for an entire transition period (`31-Dec-2015` through `31-Dec-2016` in the case of `'ABC'`).

Compute Transition Matrix Containing `NR` (Not Rated) Rating

Consider a different sample data containing only a single company `'DEF'`. The data contains transitions of company `'DEF'` from `'A'` to `'NR'` rating and a subsequent transition from `'NR'` to `'BBB'`.

```dataNR = {'DEF','17-Mar-2011','A'; 'DEF','24-Mar-2014','NR'; 'DEF','26-Sep-2016','BBB'}; dataNR = cell2table(dataNR,'VariableNames',{'ID','Date','Rating'}); disp(dataNR)```
``` ID Date Rating _______ _______________ _______ {'DEF'} {'17-Mar-2011'} {'A' } {'DEF'} {'24-Mar-2014'} {'NR' } {'DEF'} {'26-Sep-2016'} {'BBB'} ```

`transprob` treats `'NR'` as another rating. The transition matrix below shows the estimated probability of transitioning into and out of `'NR'`.

```StartYearNR = 2010; EndYearNR = 2018; startDateNR = datetime(StartYearNR,12,31,'Locale','en_US'); endDateNR = datetime(EndYearNR,12,31,'Locale','en_US'); CompanyID_NR = "DEF"; RatingLabelsNR = ["AAA","AA","A","BBB","BB","B","CCC","D","NR"]; [tmNR,~,itNR] = transprob(dataNR,'startDate',startDateNR,'endDate',endDateNR,'algorithm','cohort','labels',RatingLabelsNR); hDisplayTransitions(tmNR,RatingLabelsNR,"Transition Matrix")```
```Transition Matrix AAA AA A BBB BB B CCC D NR ___ ___ ______ ___ ___ ___ ___ ___ ______ AAA 100 0 0 0 0 0 0 0 0 AA 0 100 0 0 0 0 0 0 0 A 0 0 66.667 0 0 0 0 0 33.333 BBB 0 0 0 100 0 0 0 0 0 BB 0 0 0 0 100 0 0 0 0 B 0 0 0 0 0 100 0 0 0 CCC 0 0 0 0 0 0 100 0 0 D 0 0 0 0 0 0 0 100 0 NR 0 0 0 50 0 0 0 0 50 ```

Display the transition counts and corresponding visualization of the transitions.

`hDisplayTransitions(itNR.totalsMat,RatingLabelsNR,strcat("Transition counts, company ID: ",CompanyID_NR))`
```Transition counts, company ID: DEF AAA AA A BBB BB B CCC D NR ___ __ _ ___ __ _ ___ _ __ AAA 0 0 0 0 0 0 0 0 0 AA 0 0 0 0 0 0 0 0 0 A 0 0 2 0 0 0 0 0 1 BBB 0 0 0 2 0 0 0 0 0 BB 0 0 0 0 0 0 0 0 0 B 0 0 0 0 0 0 0 0 0 CCC 0 0 0 0 0 0 0 0 0 D 0 0 0 0 0 0 0 0 0 NR 0 0 0 1 0 0 0 0 1 ```
`hPlotTransitions(CompanyID_NR,startDateNR,endDateNR,dataNR,RatingLabelsNR)`

To remove the `'NR'` from the transition matrix, use the `'excludeLabels'` name-value input argument in `transprob`. The list of labels to exclude may or may not be specified in the name-value pair argument `labels`. For example, both `RatingLabels` and `RatingLabelsNR` generate the same output from `transprob`.

```[tmNR,stNR,itNR] = transprob(dataNR,'startDate',startDateNR,'endDate',endDateNR,'algorithm','cohort','labels',RatingLabelsNR,'excludeLabels','NR'); hDisplayTransitions(tmNR,RatingLabels,"Transition Matrix")```
```Transition Matrix AAA AA A BBB BB B CCC D ___ ___ ___ ___ ___ ___ ___ ___ AAA 100 0 0 0 0 0 0 0 AA 0 100 0 0 0 0 0 0 A 0 0 100 0 0 0 0 0 BBB 0 0 0 100 0 0 0 0 BB 0 0 0 0 100 0 0 0 B 0 0 0 0 0 100 0 0 CCC 0 0 0 0 0 0 100 0 D 0 0 0 0 0 0 0 100 ```

Display the transition counts and corresponding visualization of the transitions.

`hDisplayTransitions(itNR.totalsMat,RatingLabels,strcat("Transition counts, company ID: ",CompanyID_NR))`
```Transition counts, company ID: DEF AAA AA A BBB BB B CCC D ___ __ _ ___ __ _ ___ _ AAA 0 0 0 0 0 0 0 0 AA 0 0 0 0 0 0 0 0 A 0 0 2 0 0 0 0 0 BBB 0 0 0 2 0 0 0 0 BB 0 0 0 0 0 0 0 0 B 0 0 0 0 0 0 0 0 CCC 0 0 0 0 0 0 0 0 D 0 0 0 0 0 0 0 0 ```
`hPlotTransitions(CompanyID_NR,startDateNR,endDateNR,dataNR,RatingLabels)`

Consistent with the previous plot, the transition counts still show two transitions from `'A'` to `'A'` (from the end of 2012 to the end of 2014), and two transitions from `'BBB'` to `'BBB'` (from the end of 2017 to the end of 2019).

However, different from the previous plot, specifying `'NR'` using the `'excludeLabels'` name-value input argument of `transprob` removes any transitions into and out of the `'NR'` rating.

Local Functions

```function hDisplayTransitions(TransitionsData,RatingLabels,Title) % Helper function to format transition information outputs TransitionsAsTable = array2table(TransitionsData,... 'VariableNames',RatingLabels,'RowNames',RatingLabels); fprintf('\n%s\n\n',Title) disp(TransitionsAsTable) end function hPlotTransitions(CompanyID,startDate,endDate,data,RatingLabels) % Helper function to visualize transitions between ratings Ind = string(data.ID)==CompanyID; DatesOriginal = datetime(data.Date(Ind),'Locale','en_US'); RatingsOriginal = categorical(data.Rating(Ind),flipud(RatingLabels(:)),flipud(RatingLabels(:))); stairs(DatesOriginal,RatingsOriginal,'LineWidth',2) hold on; % Indicate rating extrapolated into the future (arbitrarily select 91 % days after endDate as the last date on the plot) endDateExtrap = endDate+91; if endDateExtrap>DatesOriginal(end) DatesExtrap = [DatesOriginal(end); endDateExtrap]; RatingsExtrap = [RatingsOriginal(end); RatingsOriginal(end)]; stairs(DatesExtrap,RatingsExtrap,'LineWidth',2,'LineStyle',':') end hold off; % Add lines to indicate the snapshot dates % transprob uses 1 as the default for 'snapsPerYear', hardcoded here for simplicity % The call to cfdates generates the exact same snapshot dates that transprob uses snapsPerYear = 1; snapDates = cfdates(startDate-1,endDate,snapsPerYear)'; yLimits = ylim; for ii=1:length(snapDates) line([snapDates(ii) snapDates(ii)],yLimits,'Color','m') end title(strcat("Company ID: ",CompanyID)) end```