Title: | A Monte Carlo Valuation Framework for Variable Annuities |
---|---|
Description: | Implementation of a Monte Carlo simulation engine for valuing synthetic portfolios of variable annuities, which reflect realistic features of common annuity contracts in practice. It aims to facilitate the development and dissemination of research related to the efficient valuation of a portfolio of large variable annuities. The main valuation methodology was proposed by Gan (2017) <doi:10.1515/demo-2017-0021>. |
Authors: | Hengxin Li [aut, cph], Ben Feng [aut, cph], Mingyi Jiang [aut, cph, cre], GuoJun Gan [ctb] |
Maintainer: | Mingyi Jiang <[email protected]> |
License: | GPL-2 |
Version: | 0.2.1 |
Built: | 2025-03-08 03:00:25 UTC |
Source: | https://github.com/cran/vamc |
Age a VA policy specified in inPolicy from currentDate (specified in inPolicy) to targetDate. The againg scenario is given in fundScen. The time step length is specified in dT. Here we input a rather irrelevant parameter df to "hack" for a more flexible user-defined projection function.
ageOnePolicy( inPolicy, mortTable, fundScen, scenDates, dT = 1/12, targetDate, df )
ageOnePolicy( inPolicy, mortTable, fundScen, scenDates, dT = 1/12, targetDate, df )
inPolicy |
A vector containing 45 attributes of a VA policy, usually a row of a VA portfolio dataframe. |
mortTable |
A dataframe with three columns of doubles representing the mortality table. |
fundScen |
A numScen-by-numStep-by-numFund array of doubles of return factors (i.e., exp(mu_t dt)) in each period. |
scenDates |
A vector containing strings in the format of "YYYY-MM-DD" of dates corresponding to each period in fundScen. |
dT |
A double of stepsize in years; dT = 1 / 12 would be monthly. |
targetDate |
A string in the format of "YYYY-MM-DD" of valuation date of the portfolio. |
df |
A vector of doubles of risk-free discount rates of different tenor (not forward rates), should have length being numStep. |
Outputs a vector containing 45 attributes of a VA policy, where currentDate, gbAmt, GMWBbalance, withdrawal, & fundValue could be updated as a result of aging. Usually a row of a VA portfolio dataframe.
Target date MUST be PRIOR to the last date of historical scenario date, Current date MUST be LATER than the first date of historical scenario date.
exPolicy <- VAPort[1, ] targetDate <- "2016-01-01" histFundScen <- genFundScen(fundMap, histIdxScen) ageOnePolicy(exPolicy, mortTable, histFundScen, histDates, dT = 1 / 12, targetDate, cForwardCurve) ## Not run: targetDate <- "2001-01-01" histFundScen <- genFundScen(fundMap, histIdxScen) ageOnePolicy(exPolicy, mortTable, histFundScen, histDates, dT = 1 / 12, targetDate, cForwardCurve) ## End(Not run) ## Not run: exPolicy <- VAPort[1, ] exPolicy[1, c("currentDate", "issueDate")] <- c("2001-01-01", "2001-01-01") histFundScen <- genFundScen(fundMap, histIdxScen) ageOnePolicy(exPolicy, mortTable, histFundScen, histDates, dT = 1 / 12, targetDate, cForwardCurve) ## End(Not run)
exPolicy <- VAPort[1, ] targetDate <- "2016-01-01" histFundScen <- genFundScen(fundMap, histIdxScen) ageOnePolicy(exPolicy, mortTable, histFundScen, histDates, dT = 1 / 12, targetDate, cForwardCurve) ## Not run: targetDate <- "2001-01-01" histFundScen <- genFundScen(fundMap, histIdxScen) ageOnePolicy(exPolicy, mortTable, histFundScen, histDates, dT = 1 / 12, targetDate, cForwardCurve) ## End(Not run) ## Not run: exPolicy <- VAPort[1, ] exPolicy[1, c("currentDate", "issueDate")] <- c("2001-01-01", "2001-01-01") histFundScen <- genFundScen(fundMap, histIdxScen) ageOnePolicy(exPolicy, mortTable, histFundScen, histDates, dT = 1 / 12, targetDate, cForwardCurve) ## End(Not run)
Age a portfolio of VA policies specified in each inPolicy of inPortfolio from currentDate (specified in inPolicy) to targetDate. The againg scenario is given in fundScen. The time step length is specified in dT. Here we input a rather irrelevant parameter df to "hack" for a more flexible user-defined projection function.
agePortfolio( inPortfolio, mortTable, fundScen, scenDates, dT = 1/12, targetDate, df )
agePortfolio( inPortfolio, mortTable, fundScen, scenDates, dT = 1/12, targetDate, df )
inPortfolio |
A dataframe containing numPolicy rows and 45 attributes of each VA policy. |
mortTable |
A dataframe with three columns of doubles representing the mortality table. |
fundScen |
A numScen-by-numStep-by-numFund array of doubles of return factors (i.e., exp(mu_t dt)) in each period. |
scenDates |
A vector containing strings in the format of "YYYY-MM-DD" of dates corresponding to each period in fundScen. |
dT |
A double of stepsize in years; dT = 1 / 12 would be monthly. |
targetDate |
A string in the format of "YYYY-MM-DD" of valuation date of the portfolio. |
df |
A vector of doubles of risk-free discount rates of different tenor (not forward rates), should have length being numStep. |
Outputs a dataframe containing numPolicy rows and 45 attributes of each VA policy, where currentDate, gbAmt, GMWBbalance, withdrawal, & fundValue of each policy could be updated as a result of aging.
Target date MUST be PRIOR to the last date of historical scenario date, Current date MUST be LATER than the first date of historical scenario date.
targetDate <- "2016-01-01" histFundScen <- genFundScen(fundMap, histIdxScen) agePortfolio(VAPort[1:2, ], mortTable, histFundScen, histDates, dT = 1 / 12, targetDate, cForwardCurve) ## Not run: targetDate <- "2001-01-01" histFundScen <- genFundScen(fundMap, histIdxScen) agePortfolio(VAPort, mortTable, histFundScen, histDates, dT = 1 / 12, targetDate, cForwardCurve) ## End(Not run) ## Not run: VAPort[1, c("currentDate", "issueDate")] <- c("2001-01-01", "2001-01-01") histFundScen <- genFundScen(fundMap, histIdxScen) agePortfolio(VAPort, mortTable, histFundScen, histDates, dT = 1 / 12, targetDate, cForwardCurve) ## End(Not run)
targetDate <- "2016-01-01" histFundScen <- genFundScen(fundMap, histIdxScen) agePortfolio(VAPort[1:2, ], mortTable, histFundScen, histDates, dT = 1 / 12, targetDate, cForwardCurve) ## Not run: targetDate <- "2001-01-01" histFundScen <- genFundScen(fundMap, histIdxScen) agePortfolio(VAPort, mortTable, histFundScen, histDates, dT = 1 / 12, targetDate, cForwardCurve) ## End(Not run) ## Not run: VAPort[1, c("currentDate", "issueDate")] <- c("2001-01-01", "2001-01-01") histFundScen <- genFundScen(fundMap, histIdxScen) agePortfolio(VAPort, mortTable, histFundScen, histDates, dT = 1 / 12, targetDate, cForwardCurve) ## End(Not run)
Bootstrap discount factors from a yield curve.
buildCurve( swapRates, tenors, fixFreq = 6, fixDCC = "Thirty360", fltFreq = 6, fltDCC = "Thirty360", calendar = "General", bdc = c("Actual", "Preceding", "Following", "Modified_Prec", "Modified_Foll"), curveDate, numSetDay, yieldCurveDCC = "Thirty360", holidays = NULL )
buildCurve( swapRates, tenors, fixFreq = 6, fixDCC = "Thirty360", fltFreq = 6, fltDCC = "Thirty360", calendar = "General", bdc = c("Actual", "Preceding", "Following", "Modified_Prec", "Modified_Foll"), curveDate, numSetDay, yieldCurveDCC = "Thirty360", holidays = NULL )
swapRates |
A vector of doubles of swap rates. |
tenors |
A vector of integers of corresponding tenors. |
fixFreq |
An integer of fixed leg frequency of payment in months. Default is 6, semi-annual payments. |
fixDCC |
A string of fixed leg day count convention from four options: "Thirty360", "ACT360", "ACT365", or "ACTACT". Default is "Thirty360". |
fltFreq |
An integer of floating leg frequency of payment in months. Default is 6, semi-annual payments. |
fltDCC |
A string of floating leg day count convention from four options: "Thirty360", "ACT360", "ACT365", or "ACTACT". Default is "Thirty360". |
calendar |
A string of the desired calendar convention from two options:
|
bdc |
A string of business day convention from five options:
Default is "Actual". |
curveDate |
A string in the format of "YYYY-MM-DD" of yield curve date. |
numSetDay |
An integer of settlement days from yield curve date. |
yieldCurveDCC |
A string of yield curve day count convention from four options: "Thirty360", "ACT360", "ACT365", or "ACTACT". Default is "Thirty360". |
holidays |
An optional vector dates of user-defined holidays. If provided, within the given holidays range, the calendar provided in the parameter "calendar" will not be applied; If the date is not in the given holidays range, it will follow the calendar provided in the "calendar" parameter |
Outputs a data frame of strings of discount dates and doubles of discount factors.
rate <- c(0.69, 0.77, 0.88, 1.01, 1.14, 1.38, 1.66, 2.15) * 0.01 tenor <- c(1, 2, 3, 4, 5, 7, 10, 30) fixFreq <- 6 fixDCC <- "Thirty360" fltFreq <- 6 fltDCC <- "ACT360" calendar <- "NY" bdc <- "Modified_Foll" curveDate <- "2016-02-08" numSetDay <- 2 yieldCurveDCC <- "Thirty360" holidays <- NULL buildCurve(rate, tenor, fixFreq, fixDCC, fltFreq, fltDCC, calendar, bdc, curveDate, numSetDay, yieldCurveDCC, holidays)
rate <- c(0.69, 0.77, 0.88, 1.01, 1.14, 1.38, 1.66, 2.15) * 0.01 tenor <- c(1, 2, 3, 4, 5, 7, 10, 30) fixFreq <- 6 fixDCC <- "Thirty360" fltFreq <- 6 fltDCC <- "ACT360" calendar <- "NY" bdc <- "Modified_Foll" curveDate <- "2016-02-08" numSetDay <- 2 yieldCurveDCC <- "Thirty360" holidays <- NULL buildCurve(rate, tenor, fixFreq, fixDCC, fltFreq, fltDCC, calendar, bdc, curveDate, numSetDay, yieldCurveDCC, holidays)
Calculates the mortality factors (t - 1)px q(x + t - 1) and tpx required to valuate the inPolicy. Extract gender, age (birth date & current date), valuation date (current date), and maturity date from inPolicy, mortality rates from mortTable.
calcMortFactors(inPolicy, mortTable, dT = 1/12)
calcMortFactors(inPolicy, mortTable, dT = 1/12)
inPolicy |
A vector containing 45 attributes of a VA policy, usually a row of a VA portfolio dataframe. |
mortTable |
A dataframe with three columns of doubles representing the mortality table. |
dT |
A double of stepsize in years; dT = 1 / 12 would be monthly. |
Outputs a two-column data frame of doubles of mortFactors (t - 1)px q(x + t - 1) and tpx.
exPolicy <- VAPort[1, ] calcMortFactors(exPolicy, mortTable, dT = 1 / 12)
exPolicy <- VAPort[1, ] calcMortFactors(exPolicy, mortTable, dT = 1 / 12)
A dataset containing 2 percent continuously compounded annual interest rate for illustration purposes.
cForwardCurve
cForwardCurve
A vector with 360 elements:
discount rate
...
A dataset containing a default mapping from five indices to ten different funds.
fundMap
fundMap
A matrix with 10 rows and 5 columns:
name for each index
proportion of fund allocated to a particular index
...
Calculate numScen-by-numStep-by-numFund fund scenarios based on given index scenarios indexScen and fund map fundMap that maps indices to funds.
genFundScen(fundMap, indexScen)
genFundScen(fundMap, indexScen)
fundMap |
A numFund-by-numIndex matrix of doubles, mapping indices to funds. |
indexScen |
A numScen-by-numStep-by-numIndex array of doubles, index scenarios. |
Outputs a numScen-by-numStep-by-numFund array of doubles of fund scenarios.
genFundScen(fundMap, indexScen)
genFundScen(fundMap, indexScen)
Simulate a 3D array, numScen-by-numStep-by-numIndex, of Black-Scholes return factors for numIndex indices in each of numStep time steps and each of numScen scenarios. Covariances among indices are specified in covMatrix. Stepsize is given is dT and interpolated discount factors are given in vDF. Random seed is optional for reproducibility.
genIndexScen( covMatrix, numScen, numStep, indexNames, dT = 1/12, forwardCurve, seed )
genIndexScen( covMatrix, numScen, numStep, indexNames, dT = 1/12, forwardCurve, seed )
covMatrix |
A numIndex-by-numIndex matrix of doubles of covariances among numIndex indices. |
numScen |
An integer of number of scenario (sample paths) to be simulated. |
numStep |
An integer of number of periods to be simulated. |
indexNames |
A vector of strings containing index names. |
dT |
A double of stepsize in years; dT = 1 / 12 would be monthly. |
forwardCurve |
A vector of doubles of discount rates at each time step. |
seed |
An integer of the deterministic seed for random sampling. |
Outputs a 3D array (numScen-by-numStep-by-numIndex) of index scenarios
genIndexScen(mCov, 100, 360, indexNames, 1 / 12, cForwardCurve, 1)
genIndexScen(mCov, 100, 360, indexNames, 1 / 12, cForwardCurve, 1)
Generate a portfolio of VA contracts at inception based on given attribute ranges and investment fund information.
genPortInception( birthDayRng = c("1950-01-01", "1980-01-01"), issueRng = c("2001-08-01", "2014-01-01"), matRng = c(15, 30), acctValueRng = c(50000, 5e+05), femPct = 0.4, fundFee = c(30, 50, 60, 80, 10, 38, 45, 55, 47, 46), baseFee = 200, prodPct = rep(1/19, 19), prodType = c("DBRP", "DBRU", "DBSU", "ABRP", "ABRU", "ABSU", "IBRP", "IBRU", "IBSU", "MBRP", "MBRU", "MBSU", "WBRP", "WBRU", "WBSU", "DBAB", "DBIB", "DBMB", "DBWB"), riderFee = c(25, 35, 35, 50, 60, 60, 60, 70, 70, 50, 60, 60, 65, 75, 75, 75, 85, 75, 90), rollUpRate = rep(5, 19), withdrawalRate = rep(5, 19), numPolicy = 10 )
genPortInception( birthDayRng = c("1950-01-01", "1980-01-01"), issueRng = c("2001-08-01", "2014-01-01"), matRng = c(15, 30), acctValueRng = c(50000, 5e+05), femPct = 0.4, fundFee = c(30, 50, 60, 80, 10, 38, 45, 55, 47, 46), baseFee = 200, prodPct = rep(1/19, 19), prodType = c("DBRP", "DBRU", "DBSU", "ABRP", "ABRU", "ABSU", "IBRP", "IBRU", "IBSU", "MBRP", "MBRU", "MBSU", "WBRP", "WBRU", "WBSU", "DBAB", "DBIB", "DBMB", "DBWB"), riderFee = c(25, 35, 35, 50, 60, 60, 60, 70, 70, 50, 60, 60, 65, 75, 75, 75, 85, 75, 90), rollUpRate = rep(5, 19), withdrawalRate = rep(5, 19), numPolicy = 10 )
birthDayRng |
A vector of two strings in 'YYYY-MM-DD' of birthday range. |
issueRng |
A vector of two strings in 'YYYY-MM-DD' of issue date range. |
matRng |
A vector of two integers, range of policy maturity. |
acctValueRng |
A vector of two doubles, range of initial account values. |
femPct |
A double, percentage of female policyholders in the portfolio. |
fundFee |
A vector of doubles, fees charged by each fund in bps. |
baseFee |
A double, base fee for all funds in bps. |
prodPct |
A vector of non-negative doubles, proportions of rider types. |
prodType |
A vector of strings, names of different rider types. |
riderFee |
A vector of doubles, rider fees for different riders in bps. |
rollUpRate |
A vector of doubles, roll up rates for different rider types in bps. |
withdrawalRate |
A vector of doubles, withdrawal rates for different rider types in bps. |
numPolicy |
An integer, number of each type of policies to be generated. |
Outputs a data frame of 45 columns of attributes in an annuity contract.
genPortInception(c("1980-01-01", "1990-01-01"), c("2001-08-01", "2014-01-01"), c(15, 30), c(5e4, 5e5), 0.4, c(30, 50, 60, 80, 10, 38, 45, 55, 47, 46), 200, rep(1 / 4, 4), c("WBRP", "WBRU", "WBSU", "DBWB"), riderFee = c(25, 35, 35, 50), rep(5, 4), rep(5, 4), 100) ## Not run: genPortInception() ## End(Not run)
genPortInception(c("1980-01-01", "1990-01-01"), c("2001-08-01", "2014-01-01"), c(15, 30), c(5e4, 5e5), 0.4, c(30, 50, 60, 80, 10, 38, 45, 55, 47, 46), 200, rep(1 / 4, 4), c("WBRP", "WBRU", "WBSU", "DBWB"), riderFee = c(25, 35, 35, 50), rep(5, 4), rep(5, 4), 100) ## Not run: genPortInception() ## End(Not run)
A dataset containing the dates at which historical returns for different indices were observed.
histDates
histDates
A vector with 175 elements:
each observation date of the historical scenarios
...
A dataset containing a matrix, number of indices (5) by number of time steps (175), of observed historical returns for each index in each of time step in the past.
histIdxScen
histIdxScen
A data frame with dimensions 175 rows and 10 columns:
historical return for index "FIXED" in one month
historical return for index "INT" in one month
historical return for index "MONEY" in one month
historical return for index "SMALL" in one month
historical return for index "US" in one month
...
These historical index scenarios were assessed on 2008-09-12
http://www.math.uconn.edu/~gan/software.html
A dataset containing names for each index.
indexNames
indexNames
A vector with 5 elements:
name of the index
...
A dataset containing a 3D array, number of scenarios (10) by number of indices (5) by number of time steps (360), of Black-Scholes return factors for each index in each of time step and each of scenario.
indexScen
indexScen
A 3D array with dimensions 10x360x5:
scenario number
month since valuation date
monthly return for a particular index in one scenario one month
...
A dataset containing the covariance matrix among the returns of five indices.
mCov
mCov
A matrix with 5 rows and 5 columns:
number for each index
...
A dataset containing the mortality rates for male and female from ages 5 to 115 (table IAM 1996 from the Society of Actuaries).
mortTable
mortTable
A data frame with 110 rows and 3 columns:
individual's age
mortality of a male at a particular age ranging from 5 to 115
mortality of a female at a particular age ranging from 5 to 115
...
A dataset containing US swap rates for various maturities.
swapRate
swapRate
A vector with 8 elements:
swap rate
...
These swap rates were assessed on 2016-02-08
Valuate a VA policy specified in inPolicy based on the simulated fund scenarios fundScen. The time step length is specified in dT and the discount rate for each period is specified in df.
valuateOnePolicy(inPolicy, mortTable, fundScen, dT = 1/12, df)
valuateOnePolicy(inPolicy, mortTable, fundScen, dT = 1/12, df)
inPolicy |
A vector containing 45 attributes of a VA policy, usually a row of a VA portfolio dataframe. |
mortTable |
A dataframe with three columns of doubles representing the mortality table. |
fundScen |
A numScen-by-numStep-by-numFund array of doubles of return factors (i.e., exp(mu_t dt)) in each period. |
dT |
A double of stepsize in years; dT = 1 / 12 would be monthly. |
df |
A vector of doubles of risk-free discount rates of different tenor (not forward rates), should have length being numStep. |
Outputs a list of doubles of policyValue, the average discounted payoff of the VA, and riskCharge, the average discounted risk charges.
fundScen <- genFundScen(fundMap, indexScen)[1, , ] exPolicy <- VAPort[1, ] valuateOnePolicy(exPolicy, mortTable, fundScen, 1 / 12, cForwardCurve)
fundScen <- genFundScen(fundMap, indexScen)[1, , ] exPolicy <- VAPort[1, ] valuateOnePolicy(exPolicy, mortTable, fundScen, 1 / 12, cForwardCurve)
Valuate a portfolio VA policies specified in each curPolicy of inPortfolio based on the simulated fund scenarios fundScen. The time step length is specified in dT and the discount rate for each period is specified in df.
valuatePortfolio(inPortfolio, mortTable, fundScen, dT = 1/12, df)
valuatePortfolio(inPortfolio, mortTable, fundScen, dT = 1/12, df)
inPortfolio |
A dataframe containing numPolicy rows and 45 attributes of each VA policy. |
mortTable |
A dataframe with three columns of doubles representing the mortality table. |
fundScen |
A numScen-by-numStep-by-numFund array of doubles of return factors (i.e., exp(mu_t dt)) in each period. |
dT |
A double of stepsize in years; dT = 1 / 12 would be monthly. |
df |
A vector of doubles of risk-free discount rates of different tenor (not forward rates), should have length being numStep. |
Outputs a list of doubles of portVal, the sum of average discounted payoff of the VAs in inPortfolio, portRC, the sum of average discounted risk charges of the VAs in inPortfolio, and vectors of doubles of these average discounted values for each policy.
fundScen <- genFundScen(fundMap, indexScen)[1, , ] valuatePortfolio(VAPort[1:2, ], mortTable, fundScen, 1 / 12, cForwardCurve)
fundScen <- genFundScen(fundMap, indexScen)[1, , ] valuatePortfolio(VAPort[1:2, ], mortTable, fundScen, 1 / 12, cForwardCurve)
The vamc package provides a Monte Carlo engine for valuating a pool of variable annuities. The key steps are: YieldCurveGeneration, ScenarioGeneration, PolicyGenerationl, and MonteCarloValuation.
YieldCurveGeneration generates a forward curve from swap rates. The forward curve is obtained by solving for swap rates that equates values of floating and fixed notes.
ScenarioGeneration generates a random fund scenario under Black-Scholes. After simulating random index scenarios, a fundMap is used to allocate returns of indices to each fund according to proportion of investment.
PolicyGenerationl randomly generates a pool of variable annuities for user-input birthday range, issue-date range, maturity range, account value range, female percentage, fund management fee, fund base fee, product types, rider fee of each type, roll-up-rate for roll-up featured guarantees, withdrawal rate for GMWB, and number of policies to be generated for each type.
MonteCarloValuation discounts cash flow from living and death benefits, as well as risk charges for each policy in the portfolio.
Gan G, Valdez EA (2017). “Valuation of Large Variable Annuity Portfolios: Monte Carlo Simulation and Synthetic Datasets.” Dependence Modeling, 5, 354–374. doi:10.1515/demo-2017-0021.
A dataset containing information of the policy and the policy holder.
VAPort
VAPort
A data frame with 19 row and 45 columns:
Unique identifier of the policy
Positive weighting number
Gender of the policyholder
Product type
Issue date
Maturity date
Birth date of the policyholder
Current date
M&E (Mortality & Expense) fee
Rider fee
Roll-up rate
Guaranteed benefit
GMWB balance
Guaranteed withdrawal rate
Withdrawal so far
Fund number of the 1st investment fund
Fund number of the 2nd investment fund
Fund number of the 3rd investment fund
Fund number of the 4th investment fund
Fund number of the 5th investment fund
Fund number of the 6th investment fund
Fund number of the 7th investment fund
Fund number of the 8th investment fund
Fund number of the 9th investment fund
Fund number of the 10th investment fund
Fund value of the 1st investment fund
Fund value of the 2nd investment fund
Fund value of the 3rd investment fund
Fund value of the 4th investment fund
Fund value of the 5th investment fund
Fund value of the 6th investment fund
Fund value of the 7th investment fund
Fund value of the 8th investment fund
Fund value of the 9th investment fund
Fund value of the 10th investment fund
Fund management fee of the 1st investment fund
Fund management fee of the 2nd investment fund
Fund management fee of the 3rd investment fund
Fund management fee of the 4th investment fund
Fund management fee of the 5th investment fund
Fund management fee of the 6th investment fund
Fund management fee of the 7th investment fund
Fund management fee of the 8th investment fund
Fund management fee of the 9th investment fund
Fund management fee of the 10th investment fund
...