Introduction

The goal of this file is to gain a better understanding of the NAIC’s stochastic scenario generator under a variety of interest rate environments, with the hopes that a better understanding of the generator will assist in reducing Stochastic Reserve runtime.

The first step in doing so was to download the scenario generator from the website below: https://www.actuary.org/content/economic-scenario-generators

After downloading the generator and reviewing the FAQ’s, three sets of scenarios were generated (considering adding a 4th with a steeper yield curve). One scenario was under the interest rate environment as of 12/31, one was with rates shocked down 300bps (with a 1 bp floor), and one was with rates shocked up 300 bps. The shocked scenarios also contained shocked mean reversion parameters.

These scenarios were generated. The scenario generator creates 10,000 scenarios, with projected interest rates for 360 months. The generator only creates treasury rates; corporate or other asset spreads must be added by a qualified actuary (I think that’s not quite true for PBR; review reg & model).

PreliMinary analysis was conducted as follows.

Read in Data for 10 year treasury; under current interest rate environment, +300bps, and -300bps.

Preliminary data exploration

summary(Base10YrCST[,3])
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
## 0.00783 0.01933 0.02418 0.02615 0.03063 0.19796
summary(Dn10YrCST[,3])
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
## 0.00010 0.01090 0.01219 0.01299 0.01419 0.08657
summary(Up10YrCST[,3])
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
## 0.00813 0.04053 0.04866 0.05270 0.06028 0.21801
sd(Base10YrCST[,3])
## [1] 0.009711092
sd(Dn10YrCST[,3])
## [1] 0.00326597
sd(Up10YrCST[,3])
## [1] 0.01938166

Data exploration by scenario

This is slightly more complex than the analysis above - I took the average and standard deviation of the 10 year CST rates in each scenarios, then averaged those numbers across all 10,000 scenarios. The goal was to learn how much one scenario varied from another.

## [1] "Base Summary"
##   Avg_IntRate      Standard_Deviation
##  Min.   :0.01339   Min.   :0.001565  
##  1st Qu.:0.02214   1st Qu.:0.004429  
##  Median :0.02533   Median :0.006054  
##  Mean   :0.02615   Mean   :0.006931  
##  3rd Qu.:0.02921   3rd Qu.:0.008440  
##  Max.   :0.06999   Max.   :0.050614
## [1] "Down 300bps Summary"
##   Avg_IntRate      Standard_Deviation
##  Min.   :0.01026   Min.   :0.000849  
##  1st Qu.:0.01174   1st Qu.:0.001618  
##  Median :0.01255   Median :0.002093  
##  Mean   :0.01299   Mean   :0.002428  
##  3rd Qu.:0.01376   3rd Qu.:0.002839  
##  Max.   :0.03111   Max.   :0.021529
## [1] "Up 300bps Summary"
##   Avg_IntRate      Standard_Deviation
##  Min.   :0.02537   Min.   :0.003060  
##  1st Qu.:0.04367   1st Qu.:0.007729  
##  Median :0.05058   Median :0.010453  
##  Mean   :0.05270   Mean   :0.012500  
##  3rd Qu.:0.05907   3rd Qu.:0.014846  
##  Max.   :0.14088   Max.   :0.055564

A few random scenarios

The goal of these plots is to visualize some of the variance (or lack therof) found above. I set the y axis manually to show scale

Map Interest rate curve

First, import data.

Then, create data frame

Finally, visualize Baseline Scenario 1 Months 1 & 360 - curve shape

I find it interesting that the curve is flattening.

Now do the same for + 300; read in data first

Then create data frame

Visualize +300bps Scenario 1 Months 1 & 360 - curve shape

This +300 chart is very interesting; I wasn’t expecting the rate curve to flatten out even more. After seeing this, I decided to analyze the “flatness” of each each scenario. This particular scenario could be a fluke. However, if it was not a fluke and the variance of each +300 scenario is that low, it could tell us not to bother with many scenarios in “up” scenarios of CFT. I should probably come up with a statistical test to tell us it is indeed “flat”…need to think that through.

Avg and standard deviations for each tenor, across all months

summary(Up3mCST[,3])
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
## 0.00010 0.02678 0.03772 0.04250 0.05272 0.29259
summary(Up6mCST[,3])
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
## 0.00010 0.02772 0.03842 0.04315 0.05314 0.28679
summary(Up1YrCST[,3])
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
## 0.00010 0.02940 0.03969 0.04434 0.05393 0.27627
summary(Up2YrCST[,3])
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
## 0.00226 0.03214 0.04180 0.04632 0.05527 0.25886
summary(Up3YrCST[,3])
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
## 0.00395 0.03423 0.04345 0.04785 0.05637 0.24611
summary(Up5YrCST[,3])
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
## 0.00620 0.03712 0.04578 0.05002 0.05803 0.22920
summary(Up7YrCST[,3])
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
## 0.00720 0.03892 0.04728 0.05142 0.05917 0.22237
summary(Up10YrCST[,3])
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
## 0.00813 0.04053 0.04866 0.05270 0.06028 0.21801
summary(Up20YrCST[,3])
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
## 0.00935 0.04262 0.05065 0.05447 0.06185 0.21218
summary(Up30YrCST[,3])
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
## 0.00943 0.04329 0.05124 0.05505 0.06242 0.21184
sd(Up3mCST[,3])
## [1] 0.02412551
sd(Up6mCST[,3])
## [1] 0.02372688
sd(Up1YrCST[,3])
## [1] 0.02302754
sd(Up2YrCST[,3])
## [1] 0.0219464
sd(Up3YrCST[,3])
## [1] 0.02118878
sd(Up5YrCST[,3])
## [1] 0.02026286
sd(Up7YrCST[,3])
## [1] 0.0197639
sd(Up10YrCST[,3])
## [1] 0.01938166
sd(Up20YrCST[,3])
## [1] 0.01897378
sd(Up30YrCST[,3])
## [1] 0.01887676

Mins and Mean’s follow the patterns I expect, and imply the flatness doesn’t persist for all scenarios/projection periods. However, the max’s are wild! They imply there are inverted yield curves in the scenarios. To be sure, let’s look further.

Checking for inversion

Create a new variable - 30yr minus 3m.

UpScenInversion <- Up30YrCST
UpScenInversion$Delta <- Up30YrCST[,3] - Up3mCST[,3]
print("Summary of inversion across all up scenarios, projection months")
## [1] "Summary of inversion across all up scenarios, projection months"
summary(UpScenInversion[,4]) #confirms inversion
##     Min.  1st Qu.   Median     Mean  3rd Qu.     Max. 
## -0.11690  0.00530  0.01285  0.01255  0.02009  0.12067
sd(UpScenInversion[,4])
## [1] 0.01229981
InversionByScen <-Up3mCST[1,]
looper <-c(1:10000)
for (val in looper)(
InversionByScen[val,3] <- Up30YrCST[361*val,3] - Up3mCST[361*val - 360,3])
print("Summary of inversion by end of each scenario")
## [1] "Summary of inversion by end of each scenario"
summary(InversionByScen[,3])
##     Min.  1st Qu.   Median     Mean  3rd Qu.     Max. 
## -0.01683  0.01224  0.02309  0.02770  0.03771  0.15884
print("Count of up scenarios ending with an inverted yield curve")
## [1] "Count of up scenarios ending with an inverted yield curve"
sum(InversionByScen[,3] < 0 )
## [1] 446

The min is negative 11bps, meaning there’s quite a bit of inversion.

Looking at beginning, ending values in each scenario

Create a new variable - month 361 - 1

Taking avg and standard deviation for each

summary(Up3mCSTDeltas[,3])
##      Min.   1st Qu.    Median      Mean   3rd Qu.      Max. 
## -0.030500 -0.003403  0.009790  0.015409  0.027310  0.205150
sd(Up3mCSTDeltas[,3])
## [1] 0.02778782
summary(Up6mCSTDeltas[,3])
##     Min.  1st Qu.   Median     Mean  3rd Qu.     Max. 
## -0.03180 -0.00385  0.00916  0.01475  0.02652  0.20078
sd(Up6mCSTDeltas[,3])
## [1] 0.02739338
summary(Up1YrCSTDeltas[,3])
##      Min.   1st Qu.    Median      Mean   3rd Qu.      Max. 
## -0.033800 -0.004180  0.008355  0.013905  0.025442  0.193230
sd(Up1YrCSTDeltas[,3])
## [1] 0.02670031
summary(Up2YrCSTDeltas[,3])
##      Min.   1st Qu.    Median      Mean   3rd Qu.      Max. 
## -0.033460 -0.004953  0.006950  0.012429  0.023390  0.180640
sd(Up2YrCSTDeltas[,3])
## [1] 0.02563798
summary(Up3YrCSTDeltas[,3])
##      Min.   1st Qu.    Median      Mean   3rd Qu.      Max. 
## -0.033000 -0.005452  0.006185  0.011530  0.022110  0.171070
sd(Up3YrCSTDeltas[,3])
## [1] 0.02490018
summary(Up5YrCSTDeltas[,3])
##      Min.   1st Qu.    Median      Mean   3rd Qu.      Max. 
## -0.032720 -0.005542  0.005650  0.010754  0.021010  0.159220
sd(Up5YrCSTDeltas[,3])
## [1] 0.02400803
summary(Up7YrCSTDeltas[,3])
##     Min.  1st Qu.   Median     Mean  3rd Qu.     Max. 
## -0.03275 -0.00556  0.00532  0.01033  0.02032  0.15398
sd(Up7YrCSTDeltas[,3])
## [1] 0.02353472
summary(Up10YrCSTDeltas[,3])
##     Min.  1st Qu.   Median     Mean  3rd Qu.     Max. 
## -0.03264 -0.00488  0.00596  0.01080  0.02077  0.14999
sd(Up10YrCSTDeltas[,3])
## [1] 0.02317303
summary(Up20YrCSTDeltas[,3])
##      Min.   1st Qu.    Median      Mean   3rd Qu.      Max. 
## -0.035940 -0.007162  0.003645  0.008307  0.018142  0.141520
sd(Up20YrCSTDeltas[,3])
## [1] 0.02281227
summary(Up30YrCSTDeltas[,3])
##      Min.   1st Qu.    Median      Mean   3rd Qu.      Max. 
## -0.035230 -0.006160  0.004690  0.009297  0.019310  0.140440
sd(Up30YrCSTDeltas[,3])
## [1] 0.02272164

There are implications here for our reinvestment assumption.

Next, evaluate something with the subsets….maybe min, max, and std dev etc by subset and tenor. Do subsets chose widest range of scenarios?

Also, it occurs to me I don’t know how the DR scenarios are generated or selected…look into it.