Problem 3

Using the provided R script as a starting point, implement the binomial tree option pricing algorithm for European options.

binomPut <- function(K, u = 1.01, delta = 0, d = 100/101, r = 0.03, T=1, 
                     S0 = 100, n = 15) 
{
  h <- T/n; disc <- exp(-r*T) 
  q <- (exp( (r-delta)*h )-d)/(u-d)
  Sbin <- S0*d^n*(u/d)^(0:n)
  qbin <- dbinom(0:n,n,q) 
  Payoff <- pmax(K - Sbin, 0)
  return(disc*sum(qbin*Payoff))
}
PutPrices <- vector(length = 50)
KStrikes <- vector(length = 50)
for(i in 0:50) {
  K <- 85 + 0.5*i
  PutPrices[i+1] <- binomPut(K)
  KStrikes[i+1] <- K
}
df2 <- data.frame(KStrikes,PutPrices)
plot(df2$KStrikes,df2$PutPrices, main = 'European Put Premiums v.s. Strikes ',
       xlab = 'Strikes',ylab = 'Euro Put Premiums')

  1. Also compute the corresponding Delta. Hand-in annotated plots of Put premium and Delta as a function of K (be sure to label axes, etc.).
# Binomial tree recursively
binTreePut <- function(K, T=1,S=100,N=15,r=0.03, little_delta=0,u=1.01,d=100/101) {
  dt  <- T/N # value of h
  disc <- exp(-r*dt) #discount over 1 period of h
  q <- (exp( (r-little_delta)*dt )-d)/(u-d) # risk-neutral prob.
  V <- array(0, dim=c(N+1,N+1)) # matrix for storing all the option values
  Del <- array(0, dim=c(N+1,N+1)) # store delta values
  Sbin <- S*d^N*(u/d)^(0:N) # store all possible S_T values
  for (i in 0:(N)) {  # terminal payoff
    curS <- S*(u)^i*(d)^(N-i) #S_T value
    V[N+1,i+1] <- max(K-curS, 0) # payoffs at V[16,i]
  }
  for (j in (N):1) {
    for (i in 0:(j-1)) {
      #discounted expected payoff with risk-neutral prob.
      V[j,i+1] <- disc*(q*V[j+1,i+2]+(1-q)*V[j+1,i+1]) 
      Del[j,i+1] = exp(-little_delta*dt)*(V[j+1,i+2]-V[j+1,i+1])/(S*(u)^(i+1)*(d)^(j-1-i)-S*(u)^i*(d)^(j-i));
    }
  }
  Delta <- exp(-little_delta*dt)*(V[2,2]-V[2,1])/(S*(u-d))  # V[2,2] = C_u, V[2,1]=C_d
  return(Del[1,1])
}
Delta <- vector(length = 50)
KStrikes <- vector(length = 50)
for(i in 0:50) {
  K <- 85 + 0.5*i
  Delta[i+1] <- binTreePut(K)
  KStrikes[i+1] <- K
}
df3 <- data.frame(KStrikes,Delta)
plot(df3$KStrikes,df3$Delta, main = 'Delta v.s. Strikes ',
       xlab = 'Strikes',ylab = 'Delta')

  1. In a brief paragraph summarize your findings. Discuss the asymptotes, slopes and convexity of the plots. Relate to the properties we discussed in Chapter 9.

There is a horizontal asymptote at 0 for the P(K) function. This follows from the fact that a Put cannot be priced less than 0. The slope of the Put must be less than e^(-rT) as well which comes from the chain-slope rule. Next the Delta function has two horizontal asymptotes at 0 and 1 with a slope concaving down at first that inflects at or around the in-the-money Strike Price before concaving up. This is intuitive since a high strike price would mean that our replicating portfolio will be more reliant on the amount of a share (the share will be doing more of the heavy lifting of the replicating portfolio). A lower strike means that there will be more payoffs of zero in our tree as well which will result in a 0 or close to 0 value for Delta.

Problem 4

Use the same setting as Problem 3. Modify the binomial tree pricing algorithm to compute prices of an American Put PA with maturity T and strike K. Re-compute PA(K) as a function of strike K, with K = 85,85.5,86,â€Ĥ,110. Comment on the results. In particular, compare to the values of P_E(K) in Problem 3. Hand-in your code, a plot of the difference P_A(K) - P_E(K) and a summary of your findings.

binTree2 <- function(K=85,T=1,S=100,N=15,r=0.03,delta=0) {
  
  d<-(100/101); u<-1.01;dt <- T/N; disc <- exp(-r*dt)
  q <- (exp( (r-delta)*dt)-d)/(u-d)
  strike<-c() #strike values
  premium<-c() #premiums values
  delta <-c() #delta values
  strike2<-c(); premium_2<-c()
  values1 <- array(0, dim=c(N+1,N+1)) # matrix for storing option values
  values2 <- array(0, dim=c(N+1,N+1)) # matrix for storing option values
  values3 <- array(0, dim=c(N+1,N+1)) # matrix for storing option values
  Del <- array(0, dim=c(N+1,N+1))
  while(K<110.5){
    for (i in 0:(N)) { # terminal payoff
      curS <- S*(u)^i*(d)^(N-i)
      values1[N+1,i+1] <- max( K-curS, 0)
    }
    for (j in (N):1) {
      for (i in 0:(j-1)) {
        values1[j,i+1] <- disc*(q*values1[j+1,i+2]+(1-q)*values1[j+1,i+1])
        Del[j,i+1] = exp(-dt)*(values1[j+1,i+2]-
                                 values1[j+1,i+1])/(S*(u)^(i+1)*(d)^(j-1-i)-S*(u)^i*(d)^(j-i));
      }
    }
    while (N>-1) {
      for (i in 0:(N)) { # terminal payoff
        curS <- S*(u)^i*(d)^(N-i)
        values2[N+1,i+1] <- max(K-curS, 0)
        values3[N+1,i+1] <- max(K-curS, 0)
      }
      N=N-1
    }
    N=15
    for (j in (N):1) {
      for (i in 0:(j-1)) {
        values2[j,i+1] <- disc*(q*values2[j+1,i+2]+(1-q)*values2[j+1,i+1])
        if(values3[j,i+1]>values2[j,i+1]){
          values2[j,i+1]<-values3[j,i+1]
        }
        Del[j,i+1] = exp(-dt)*(values2[j+1,i+2]-
                                 values2[j+1,i+1])/(S*(u)^(i+1)*(d)^(j-1-i)-S*(u)^i*(d)^(j-i));
      }
    }
    strike<-c(strike,K)
    premium<-c(premium,values1[1,1])
    strike2<-c(strike2,K)
    premium_2<-c(premium_2,values2[1,1])
    delta<-c(delta,Del[1,1])
    K=K+0.5
  }
  Delta <- exp(-dt)*(values2[2,2]-values2[2,1])/(S*(u-d)) # values2[2,2] = C_u, values2[2,1]=C_d
  table<-
    data.frame(Strike=strike,European=premium,American=premium_2,Difference=(
      premium_2-premium))
  plot(strike,premium_2,main = 'American Put Premiums v.s. Strike Price',xlab =
         'Strikes',
       ylab = 'Put Premiums')
  plot(strike,(premium_2-premium),main = 'Difference b/w American and
       European Put Premiums v.s. Strikes  ',
       xlab = 'Strikes',ylab = 'Difference in Put Premiums')
}
binTree2()

The slope of the American Put must be less than or equal to 1, whereas the slope of the European Put must be less than or equal to e^(-rt). This is why the American Call is notably priced higher than the European at K=110. It is also the case because of the early-exercise clause in the American Option which requires the premia to be greater than the payoff from exercising at t=0.

Problem 5

Let h = T/N be the length of one time-step in the binomial tree model. Set u =exp(sigma(sqrt(h))) d =exp(-sigma(sqrt(h)))

Fix T = 1, sigma = 0.25, S(0) = K = 100 and interest rate of r = 5% yearly, compounded continuously. There are no dividends.

  1. Compute the price C(0,S0) of a European Call with the above parameters using N = 4,8,15,30,60,90,120 (i.e. varying the number of steps, while keeping the maturity fixed and using the particular scaling of u and d above. Note that as N grows, h shrinks.)
binomCall <- function(N, T=1, S0=100, K=100, r=0.05,sigma=0.25) {
  u <- exp(sigma*sqrt(T/N))
  d <- exp(-sigma*sqrt(T/N))
  q <- (exp(r*T/N)-d)/(u-d)
  Sbin <- S0*d^N*(u/d)^(0:N)  # possible values of stock price
  qbin <- dbinom(0:N,N,q)  # corresponding probabilities using q
  Payoff <- pmax(Sbin-K,0)
  disc <- exp(-r*T)
  return(disc*sum(qbin*Payoff))
}

binomCall(4)
## [1] 11.74255
binomCall(8)
## [1] 12.03253
binomCall(15)
## [1] 12.48756
binomCall(30)
## [1] 12.25395
binomCall(60)
## [1] 12.29489
binomCall(90)
## [1] 12.30857
binomCall(120)
## [1] 12.31542