Nathan — Apr 7, 2014, 12:19 PM
rm(list=ls()); cat("\014"); options(warn=-1)
graphics.off(); plotDims=c(2,2); par(mfrow=plotDims)
#### vars ####
A = 0.00022
B = 2.5e-05
c = 1.1
l20 = 1e+05
x = 20
i = 0.05
w = 120
writeToExcel = FALSE
if(writeToExcel==TRUE){tryCatch({library(xlsx);library(rJava)},error=function(e){install.packages("xlsx")})}
#### functions ####
fix <- function(vector, k, truncate) {
decimals <- function(x,k) {
format(round(x,k), nsmall=k)
}
newvector <- numeric(0); vector = as.numeric(vector)
for (j in 1:length(vector)) newvector[j] = decimals(vector[j],k)
newvector = newvector[1:truncate]
return(as.numeric(newvector))
}
display <- function(message, num) {
cat(paste(message, num, sep="")); cat("\n")
}
uxplust <- function(t,...){
age = if(length(list(...))==1) list(...)[[1]] else x
return(A+(B*c^age)*c^t)
}
uxpluss <- function(t,...) {
if(t<0 || t>2) return(uxplust(t,...))
else return(0.9^(2-t)*uxplust(t,...))
}
fxt <- function(t,...) {
return(tpx(t,...)*uxplust(t,...))
}
tpx <- function(t,...) {
age = if(length(list(...))==1) list(...)[[1]] else x
# account for the fact that no one lives beyond age w
if( (age+t)>= w) return(0)
return(exp(-(A*t + B/log(c)*(c^age)*(c^t -1))))
}
tpselectx <- function(t,age=x) {
if( (age+t)>= w) return(0)
if (0<= t & t<=2) {
return(exp(0.9^(2-t)* ((A*(1 - 0.9^t)/log(0.9)) + (B*c^age*(c^t - 0.9^t)/log(0.9/c)))))
} else {
#return(tpx(t,age))
return(tpselectx(2,age)*tpx(t-2,age+2))
}
}
tpselectxplus1 <- function(t,...) {
age = if(length(list(...))==1) list(...)[[1]] else x
# account for the act that no one lives beyond age w
if ( (age+t)>=w) return(0)
if(0<=t & t<=1) {
return(exp(0.9^(1-t)*( (A/log(0.9)*(1-0.9^t)) + (B*c^(age+1)/log(0.9/c)*(c^t - 0.9^t)))))
} else {
return(tpx(t,...))
}
}
tqx <- function(t,...) {
return(1-tpx(t,...))
}
tqselectx <- function(t,...) {
return(1-tpselectx(t,...))
}
tqselectxplus1 <- function(t,...) {
return(1-tpselectxplus1(t,...))
}
kdeferredqx <- function(k,...) {
return(tpx(k,...) - tpx(k+1,...))
}
kdeferredselectqx <- function(k,...) {
return(tpselectx(k,...) - tpselectx(k+1,...))
}
v <- function(i, n, ...) {
moment = if(length(list(...)) == 1) list(...)[[1]] else 1
delta = log(1+i)*moment
return(exp(-delta*n))
}
Ax <- function(x,...) {
total = 0
# w-x-1 since w-x would make A120 non-zero
# sum from k = 0 to w-x-1 of v^k+1 * k|qx
#however, (w-x-1) = (120-20-1) = 99
for (k in (0:(w-x-1))) {
total = total + v(i, (k+1),...)*kdeferredqx(k,x)
}
return(total)
}
Axcolumn <- function(x,w,i,...) {
axcol <- numeric(0); temp = 0
# w-x-1 since w-x would make A120 non-zero
for (k in 0:(w-x)) {
if(k==0) temp = v(i,1,...)
else temp = axcol[k]*tpx(1,(w-k))*v(i,1,...) + v(i,1,...)*tqx(1,(w-k))
axcol = c(axcol, temp)
}
# reverse the vector due to backwards recursion
return(rev(axcol))
}
Aselectx <- function(x,...) {
return(v(i,1,...)*tqselectx(1,x) + v(i,2,...)*tqselectxplus1(1,x)*tpselectx(1,x) +
v(i,2,...)*tpselectx(2,x)*(Ax(x+2,...)))
}
Aselectxcolumn <- function(x,w,i,...) {
aselectxcol <- numeric(0); temp = 0
axplus2col = Axcolumn(x+2, w+2, i, ...)
for (k in 0:(w-x)) {
# temp = Aselectx(k+x,...)
temp = (v(i,1,...)*tqselectx(1,x+k) + v(i, 2, ...)*tqselectxplus1(1,x+k)*tpselectx(1,x+k)
+ v(i,2,...)*tpselectx(2,x+k)*axplus2col[k+1])
aselectxcol = c(aselectxcol, temp)
}
return(aselectxcol)
}
Aselectxplots <- function(i1,i2,i3,xmin,xmax,ymin,ymax,legend) {
temp = i
i <<- i1; plot( Aselectx, xmin, xmax, xlab="Age at Selection",
ylab = expression("A"["[x]"]), col="red",
main = expression(bold(paste("A"["[x]"], " with varying interest rates"))),
ylim=c(ymin,ymax))
i <<- i2; plot( Aselectx, xmin, xmax, col="green", add=TRUE)
i <<- i3; plot( Aselectx, xmin, xmax, col="blue", add=TRUE)
if (legend==TRUE) {
legend(xmin, ymax, c(paste(i1*100,"%"), paste(i2*100,"%"), paste(i3*100,"%")),
lty=c(1,1,1), lwd=c(2,2,2), col=c("red", "green", "blue"), cex=0.7)
}
i <<- temp
}
# use select probabilities
pdfZ <- function(k,x) {
if(0<k & k<(w-1)) return(kdeferredselectqx(k-1,x))
return(0)
}
# x, l[x], l[x]+1, lx+2, x+2
createtable1 <- function(x, w, truncateTable) {
age <- numeric(0)
age_plus_2 <- numeric(0)
l_x <- numeric(0)
l_x_1 <- numeric(0)
lx_2 <- numeric(0)
truncateAt = truncateTable-x+1
for (j in ((x-2):(w-2))) {
lx_2 = c(lx_2, l20*tpx((j-(x-2)),x))
age_plus_2 = c(age_plus_2, (j+2))
# account for blanks in first two rows
if(j<x) { l_x=c(l_x,"-"); l_x_1 = c(l_x_1, "-"); age=c(age,"-") }
else {
l_x = c(l_x, lx_2[(j-(x-3))]/tpselectx(2,j))
l_x_1 = c(l_x_1, lx_2[(j-(x-3))]/tpselectxplus1(1,j))
age = c(age,j)
}
}
lx_2 = fix(lx_2, 2, truncateAt)
age_plus_2 = fix(age_plus_2, 0, truncateAt)
age = fix(age, 0, truncateAt)
l_x = fix(l_x,2, truncateAt)
l_x_1 = fix(l_x_1, 2, truncateAt)
table <- data.frame(age, l_x, l_x_1, lx_2, age_plus_2)
names(table)[names(table)=="age"] = "x"
names(table)[names(table)=="age_plus_2"] = "x+2"
names(table)[names(table)=="l_x"] = "l[x]"
names(table)[names(table)=="l_x_1"] = "l[x]+1"
names(table)[names(table)=="lx_2"] = "lx+2"
return(table)
}
# x, A[x], 2A[x]
createtable2 <- function(x,w, truncateTable) {
age <- numeric(0)
aselectxcol = Aselectxcolumn(x,w,i,1)
aselectx2col = Aselectxcolumn(x,w,i,2)
truncateAt = truncateTable-x+1
for (i in (x:w)) age = c(age,i)
aselectxcol = fix(aselectxcol, 5, truncateAt)
aselectx2col = fix(aselectx2col, 5, truncateAt)
age = fix(age, 0, truncateAt)
table <- data.frame(age, aselectxcol, aselectx2col)
names(table)[names(table)=="age"] = "x"
names(table)[names(table)=="aselectxcol"] = "A[x]"
names(table)[names(table)=="aselectx2col"] = "2A[x]"
return(table)
}
# x, Ax, 2Ax
createtable3 <- function(x,w,truncateTable) {
age <- numeric(0)
axcol = Axcolumn(x,w,i,1)
ax2col = Axcolumn(x,w,i,2)
# if table goes from 20 to 80 then truncate at index (80-20)+1
# this is because in R, array indexices start from 1 not 0
truncateAt = truncateTable-x+1
for (i in (x:w)) age = c(age,i)
axcol = fix(axcol, 5, truncateAt)
ax2col = fix(ax2col, 5, truncateAt)
age = fix(age,0, truncateAt)
table <- data.frame(age, axcol, ax2col)
names(table)[names(table)=="age"] = "x"
names(table)[names(table)=="axcol"] = "Ax"
names(table)[names(table)=="ax2col"] = "2Ax"
return(table)
}
# k, v^k, P(Z=v^k, k|qx
# use select probabilities
# slight error on the last few cdf values due to rounding to 5 decimal places
createtable4 <- function(x,w,truncateTable) {
kdeferredqx_ <- numeric(0)
kx <- numeric(0)
v_k <- numeric(0)
zv_k <- numeric(0)
truncateAt = truncateTable-x+1
for (k in 0:(w-x)) {
kdeferredqx_ = c(kdeferredqx_, kdeferredselectqx(k,x))
kx = c(kx,k)
v_k = c(v_k, v(i,k))
# probability that Z = v(i,k)
zv_k = c(zv_k, pdfZ(k,x))
}
kx = fix(kx, 0, truncateAt)
kdeferredqx_ = fix(kdeferredqx_, 5, truncateAt)
v_k = fix(v_k, 5, truncateAt)
zv_k = fix(zv_k, 5, truncateAt)
cdf_k <- numeric(0); sdf_Z <- numeric(0)
total = 0
# find cdf of k
for (j in 1:(length(kdeferredqx_))) {
total = total+kdeferredqx_[j]
cdf_k = c(cdf_k, total)
sdf_Z = c(sdf_Z, total-kdeferredqx_[j])
}
cdf_k = fix(cdf_k, 5, truncateAt); sdf_Z = fix(sdf_Z, 5, truncateAt)
table = data.frame(kx, kdeferredqx_, cdf_k, v_k, zv_k, sdf_Z)
names(table)[names(table)=="kdeferredqx_"] = "P[K(50)=k]"
names(table)[names(table)=="kx"] = "K(x)"
names(table)[names(table)=="v_k"] = "v^k"
names(table)[names(table)=="zv_k"] = "P[Z=v^k]"
names(table)[names(table)=="cdf_k"] = "P[K(x)<=k]"
names(table)[names(table)=="sdf_Z"] = "P[Z>=v^k]"
theoreticalZ <<- as.numeric(zv_k)
cdfK <<- as.numeric(cdf_k)
sdfZ <<- as.numeric(sdf_Z)
return(table)
}
# draw n observations of K(50)
# x: age, w: limiting age
kNums <- function(n, w,x, cdf) {
# use cdf vector to transform from runif to K(x)
rand <- function(n) return(runif(n,0,1))
nums = rand(n)
transform <- function(num) {
k = 0
if(num>cdf[length(cdf)]) num = runif(1,0,1)
while(num>cdf[k+1] & k<69) k=k+1
return(k)
}
knums <- numeric(0)
for(num in nums) knums = c(knums, transform(num))
return(knums)
}
# draw n observations of Z corresponding to K(50)
zNums <- function(nums,...) {
j = if(length(list(...))==1) list(...)[[1]] else 0.05
newnums <- numeric(0)
for (k in 1:length(nums)) newnums = c(newnums, v(j, nums[k]+1))
return(newnums)
}
# 1 - cdf(Z)
sdf <- function(z, sdfZ) {
k = 0
while(v(i,k+1)>z & k<200) k=k+1
return(sdfZ[k+1])
}
#### output ####
# for the first (3 tables and 2 plots) x = 20, and is 50 otherwise
table1 = createtable1(x,w,w-1) # goes up to 119
table2 = createtable2(x,w,w-3)
table3 = createtable3(x,w,w-1)
table4 = createtable4(50,w,w-1)
Aselectxplots(0.04,0.05,0.06,x,117,0,1,TRUE) # plot goes up to 117
plot(theoreticalZ, main="Theoretical Distribution of Z", ylab="P(Z)=z)", xlab="Z", col="blue")
# n = 50, n = 500
testCases = c(50,500)
MeanZ = Aselectx(50); SdZ = sqrt(Aselectx(50,2) - Aselectx(50,1)^2)
# P(Z>=A[50])
prob = sdf(MeanZ,sdfZ)
cat("\n"); display("P(Z>= A[50]): ", prob); cat("\n")
P(Z>= A[50]): 0.34213
for (j in 1:length(testCases)) {
simKx = kNums(testCases[j],50,w,cdfK)
simZ = zNums(simKx, 0.05)
hist(simZ, main=paste("Histogram of Z (n = ", testCases[j], ")"), xlab ="Z", col="pink")
simMeanZ = mean(simZ); simSdZ = sd(simZ)
display("n is: ", testCases[j])
display("MeanZ: ", MeanZ); display("simMeanZ: ", simMeanZ)
display("SdZ: ", SdZ); display("simSdZ: ", simSdZ)
simCdfZ = ecdf(simZ)
display("P(Z>= A[50]: ~", (1-simCdfZ(MeanZ))); cat("\n")
}
n is: 50
MeanZ: 0.246181759757277
simMeanZ: 0.225124598643679
SdZ: 0.160387268174681
simSdZ: 0.142766170803151
P(Z>= A[50]: ~0.3
n is: 500
MeanZ: 0.246181759757277
simMeanZ: 0.233912423572489
SdZ: 0.160387268174681
simSdZ: 0.162658173920116
P(Z>= A[50]: ~0.294