Binomial Trees: Recall

Suppose there is an asset with the initial spot price \(S_0\) and it may go up by \(u\) to \(S_{1}=uS_0\) with probability \(p\) or by \(d\) to \(S_{1}=dS_0\) with probability \(1-p\) during the time interval of \(dt\). Consider the European Call option and the payoffs as \(C_u = [0,uS_0-K]^+\) and \(C_d = [0,dS_0-K]^+\).

We want to form a (replicating, risk-free) portfolio which has the same value regardless of the outcome (i.e. \(u\) or \(d\)). So, we add \(\Delta\) amount of the underlying asset to get the following equality.

\[-C_u + \Delta u S_0 = -C_d + \Delta d S_0\]

\(\Delta\) value can be calculated as \(\Delta = \dfrac{C_u - C_d}{(u-d)S_0}\).

This risk-free portfolio should return risk-free interest rate.

\[-C_u + \Delta u S_0 = e^{r.dt}(-C + \Delta S_0)\]

Substitute \(\Delta\) and rearrange to find \(C\) in the following way.

\[ C = \dfrac{C_u - C_d}{(u-d)S_0}S_0 + e^{-r.dt}(C_u - \dfrac{C_u - C_d}{(u-d)S_0}uS_0) \]

\[ C = \dfrac{C_u - C_d}{(u-d)} + e^{-r.dt}(C_u - \dfrac{C_u - C_d}{(u-d)}u) \]

\[ C = e^{-r.dt}(e^{r.dt}\dfrac{C_u}{(u-d)} - e^{r.dt}\dfrac{C_d}{(u-d)} + \dfrac{uC_u}{u-d} - \dfrac{dC_u}{u-d} - \dfrac{uC_u}{(u-d)} + \dfrac{uC_d}{(u-d)}) \]

\[ C = e^{-r.dt}(e^{r.dt}\dfrac{C_u}{(u-d)} - \dfrac{dC_u}{u-d} + \dfrac{uC_d}{(u-d)} - e^{r.dt}\dfrac{C_d}{(u-d)}) \]

\[ C = e^{-r.dt}(\dfrac{e^{r.dt}-d}{u-d}C_u + \dfrac{u - e^{r.dt}}{(u-d)}C_d) \]

Define \(p = \dfrac{e^{r.dt}-d}{u-d}\) and the value of the option becomes \(C = e^{-r.dt}[pC_u + (1-p)C_d]\). \(p\) can be interpreted as the risk neutral ‘up’ probability1.

An n-step binomial tree is slightly different. At the terminal (maturity) nodes payoff of the option is calculated.

\[C_{n,j} = [0,S_{n,j} - K]^+\]

where \(S_{n,j}\) is the final asset price at the state \(j\). Then each step back is calculated as the discounted expectation value of their next steps.

\[C_{i,j} = e^{-r.dt}(pC_{i+1,j+1} + (1-p)C_{i+1,j})\]

Repeat until the initial node and the initial node gives the price of the European Call option. R code is given below.

binomial_tree_EOPT<-function(S_0,K,r,T_in_days,vol,n,callput="call",return_tree=FALSE){
  #Binomial tree code for the European Call
  #n is the number of steps
  #dt is the step size
  dt <- (T_in_days/252)/n
  #calculate u and d
  u_val <- exp(vol*sqrt(dt))
  d_val <- 1/u_val
  #calculate p_u
  p_star <- (exp(r*dt) - d_val) / (u_val - d_val)
  #Create option value matrix
  V_mat <- matrix(ncol=n+1,nrow=n+1)
  #Calculate payoffs
  if(callput == "call"){
      V_mat[n+1,] <- pmax(S_0*d_val^n * cumprod(c(1,rep(u_val^2,n))) - K,0)
  }else{
      V_mat[n+1,] <- pmax(K - S_0*d_val^n * cumprod(c(1,rep(u_val^2,n))),0)
  }
  #Calculate discounted expectations in recursion
  for(i in n:1){
    V_mat[i,1:i] <- exp(-r*dt)*(p_star*V_mat[i+1,2:(i+1)]+(1-p_star)*V_mat[i+1,-((i+1):(n+1))])
  }

  if(return_tree){
    #Return option value tree if return tree is TRUE
    return(V_mat)
  }else{
    #Return option price if return tree is FALSE
    return(V_mat[1,1])
  }
}
#Price of the European Call
binomial_tree_EOPT(S_0=100,K=100,r=0.06,T_in_days=252,vol=0.166,n=3,callput="call",return_tree=FALSE)
## [1] 10.18245
#Price of the European Put
binomial_tree_EOPT(S_0=100,K=100,r=0.06,T_in_days=252,vol=0.166,n=3,callput="put",return_tree=FALSE)
## [1] 4.358908

American Put

American options are different than European options in a single but significant way: It is also possible to exercise the option and get the payoff anytime before expiration whereas it is possible to exercise only at the expiration for European options. While index options are European, most (if not all) individual stock options are American type options. If the asset is not paying dividends, value of the American Call is equivalent to the value of the European Call. Briefly it is never advisable to exercise early for American Calls. 2. For American Put, it might be.

Payoff function the of put option is for European: \(P_{European} = [0,K-S_T]^+\) where \(T\) is the expiration time. For American Put, the payoff function is \(P_{American} = [0,K-S_t]^+\) where \(0 < t < T\).

Binomial setting for the American Put is slightly different than the European part.

binomial_tree_AP<-function(S_0,K,r,T_in_days,vol,n,return_tree=FALSE){
  #Binomial tree code for the American Put
  #n is the number of steps
  #dt is the step size
  dt <- (T_in_days/252)/n
  #calculate u and d
  u_val <- exp(vol*sqrt(dt))

  d_val <- 1/u_val
  #calculate p_u
  p_star <- (exp(r*dt) - d_val) / (u_val - d_val)
  #Create asset price matrix
  S_mat <- matrix(ncol=n+1,nrow=n+1)
  S_mat[1,1] <- S_0
  #Calculate terminal stock values
  S_mat[n+1,] <- S_0*d_val^n * cumprod(c(1,rep(u_val^2,n)))
  #Create option value matrix
  V_mat <- matrix(ncol=n+1,nrow=n+1)
  #Calculate payoffs
  V_mat[n+1,] <- pmax(K - S_mat[n+1,],0)
  #Calculate discounted expectations in recursion
  for(i in n:1){
    S_mat[i,1:i] <- S_mat[i+1,1:i]*u_val
    V_mat[i,1:i] <- pmax(exp(-r*dt)*(p_star*V_mat[i+1,2:(i+1)]+(1-p_star)*V_mat[i+1,-((i+1):(n+1))]),K-S_mat[i,1:i])
  }

  if(return_tree){
    #Return option value tree if return tree is TRUE
    return(V_mat)
  }else{
    #Return option price if return tree is FALSE
    return(V_mat[1,1])
  }
}
binomial_tree_AP(S_0=100,K=100,r=0.06,T_in_days=252,vol=0.166,n=3,return_tree=FALSE)
## [1] 4.692452

Choice of u, d and p

Values \(u\) and \(d\) can be defined with either Cox-Ross-Rubinstein (CRR) or Jarrow and Rudd (JR) methods.

CRR method

\[u = e^{(r-1/2\sigma^2)\Delta t + \sigma \sqrt{\Delta t}}\] \[d = e^{(r-1/2\sigma^2)\Delta t - \sigma \sqrt{\Delta t}}\] \[p = 1/2\]

JR method

\[u = 1/d = e^{\sigma \sqrt{\Delta t}}\] \[p = 1/2 + \dfrac{r-1/2\sigma^2}{2\sigma}\sqrt{\Delta t }\]

These methods will only work if time step \(dt\) is small. To work on larger step sizes, we need another way.

General Additive Binomial Model

Under Black-Scholes assumptions asset price movement is governed by Geometric Brownian Motion (GBM). GBM process is as follows.

\[dS = rSdt + \sigma S dz\]

Under GBM log of the asset price is normally distributed. Define \(x = ln(S)\) and apply Ito’s formula.

\[dx = \dfrac{1}{S}dS -\dfrac{1}/{S^2}dS^2 \]

Replace \(dS\)

\[dx = \dfrac{1}{S}(rSdt + \sigma S dz) -\dfrac{1}{S^2}(\sigma^2 S^2 dt) \]

\[dx = (r - 1/2\sigma^2)dt + \sigma dz \]

Define \(v = r - 1/2\sigma^2\) and \(dx = v dt + \sigma dx\). Differently from the multiplicative binomial model, at the next stage of \(x\) it can either be \(x + \Delta x_u\) or \(x + \Delta x_d\) where \(x_u\) and \(x_d\) are defined as the up and down step sizes. The mean and variance values of \(\Delta x\) can be calculated as follows.

\[E[\Delta x] = p\Delta x_u + (1-p)\Delta x_d = v\Delta t\] \[E[\Delta x^2] = p\Delta x_u^2 + (1-p)\Delta x_d^2 = \sigma^2\Delta t + v^2\Delta t^2\]

As with CRR and JR methods we can define equal probabilities (\(p=1/2\)) or equal jump sizes (\(\Delta x_u = - \Delta x_d\)). At equal probabilities we get the following.

\[\Delta x_u = \dfrac{1}{2}v\Delta t + \dfrac{1}{2}\sqrt{4\sigma^2 \Delta t - 3v^2 \Delta t^2}\] \[\Delta x_d = \dfrac{1}{2}v\Delta t - \dfrac{1}{2}\sqrt{4\sigma^2 \Delta t - 3v^2 \Delta t^2}\]

At equal jump sizes we get the following.

\[\Delta x = \sqrt{\sigma^2\Delta t + v^2 \Delta t^2}\] \[p = \dfrac{1}{2}(1 + \dfrac{v\Delta t}{\Delta x})\]

Reportedly equal jump sizes for the additive model is more accurate than the other three.3

#Binomial General Additive European Call
additiveBinomialEC<-function(K=100,T=1,S=100,sig=0.2,r=0.06,N=200){
    #Equal jump size version
    dt=T/N
    nu=r-0.5*sig^2
    dxu=sqrt(sig^2*dt+(nu*dt)^2)
    dxd=-dxu
    pu=0.5+0.5*(nu*dt/dxu)
    disc=exp(-r*dt)
    dpu=disc*pu
    dpd=disc*(1-pu)
    edxud=exp(dxu-dxd)
    edxd=exp(dxd)

    St<-S*exp(N*dxd)
    for(j in 2:(N+1)){
        St[j]<-St[j-1]*edxud
    }

    C<-0
    for(j in 1:(N+1)){
        C[j]=max(0,St[j]-K)
    }

    for(i in (N-1):0){
        for(j in 0:i){
            C[j+1]=dpu*C[j+2]+dpd*C[j+1]
            St[j+1]=St[j+1]/edxd
        }
    }
    return(C[1])
}
#Binomial General Additive American Put
additiveBinomialAP<-function(K=100,T=1,S=100,sig=0.2,r=0.06,N=200){
    #Equal jump size version
    dt=T/N
    nu=r-0.5*sig^2
    dxu=sqrt(sig^2*dt+(nu*dt)^2)
    dxd=-dxu
    pu=0.5+0.5*(nu*dt/dxu)
    disc=exp(-r*dt)
    dpu=disc*pu
    dpd=disc*(1-pu)
    edxud=exp(dxu-dxd)
    edxd=exp(dxd)

    St<-S*exp(N*dxd)
    for(j in 2:(N+1)){
        St[j]<-St[j-1]*edxud
    }

    C<-0
    for(j in 1:(N+1)){
        C[j]=max(0,K-St[j])
    }

    for(i in (N-1):0){
        for(j in 0:i){
            C[j+1]=dpu*C[j+2]+dpd*C[j+1]
            St[j+1]=St[j+1]/edxd
            C[j+1]=max(C[j+1],K-St[j+1])
        }
    }
    return(C[1])
}

Hedge Sensitivities

Hedging is as important as calculating the price of options. There are different types of hedges, also called as Greeks. Most common and basic hedge is Delta (\(\Delta\)). Delta hedge is simply the rate of change in the option price with respect to the change in the underlying asset price. Gamma (\(\Gamma\)) is the rate of change in the Delta with respect to the change in the underlying asset price. It is a second order Greek.

\[\Delta = (C_u - C_d)/(S_u-S_d)\] \[\Gamma = (\Delta_u - \Delta_d)/(S_u-S_d)\]

BinomialTreeEOPTDeltaGamma<-function(S_0=100,K=100,r=0.06,T_in_days=252,vol=0.2,n=100,callput="call"){
  #Binomial tree code for the European Call
  #n is the number of steps
  #dt is the step size
  dt <- (T_in_days/252)/n
  #calculate u and d
  u_val <- exp(vol*sqrt(dt))
  d_val <- 1/u_val
  #calculate p_u
  p_star <- (exp(r*dt) - d_val) / (u_val - d_val)
  #Create option value matrix
  S_mat <- matrix(ncol=n+1,nrow=n+1)
  S_mat[1,1] <- S_0
  for(i in 2:(n+1)){
      S_mat[i,1:i] <- S_0*d_val^(i-1) * cumprod(c(1,rep(u_val^2,(i-1))))
  }

  V_mat <- matrix(ncol=n+1,nrow=n+1)
  #Calculate payoffs
  if(callput == "call"){
      V_mat[n+1,] <- pmax(S_mat[n+1,] - K,0)
  }else{
      V_mat[n+1,] <- pmax(K - S_mat[n+1,],0)
  }
  #Calculate discounted expectations in recursion
  for(i in n:1){
    V_mat[i,1:i] <- exp(-r*dt)*(p_star*V_mat[i+1,2:(i+1)]+(1-p_star)*V_mat[i+1,-((i+1):(n+1))])
  }

  #Delta Matrix
  D_mat <- matrix(ncol=n+1,nrow=n+1)
  D_mat[n+1,] <- ifelse(V_mat[n+1,]>0,1,0)
  for(i in 1:n){
      D_mat[i,1:i]<-(V_mat[i+1,2:(i+1)]-V_mat[i+1,1:i])/((S_mat[i+1,2:(i+1)]-S_mat[i+1,1:i]))
  }

  #Calculation of Gamma is different than lecture notes
  G_mat <- matrix(ncol=n+1,nrow=n+1)
  for(i in 1:(n-1)){
    G_mat[i,1:i]<-(D_mat[i+1,2:(i+1)]-D_mat[i+1,1:i])/((S_mat[i+1,2:(i+1)]-S_mat[i+1,1:i]))
  }

  return(list(Price=V_mat[1,1],Delta=D_mat[1,1],Stock_tree=S_mat,Value_tree=V_mat,Delta_tree=D_mat,Gamma_tree=G_mat))
}

Multidimensional Binomial Method

There are options (or contract combinations) which depend on the outcome of two or more different (but correlated) assets. We can use a multidimensional binomial tree to price them.

\[dS_1(t) = (r - \delta_1)S_1(t)dt + \sigma_1S_1(t)dz_1\] \[dS_2(t) = (r - \delta_2)S_2(t)dt + \sigma_2S_2(t)dz_2\]

where the correlation between the asssets is denoted as \(dz_1dz_2=\rho dt\) and \(\delta\) is the continuous dividend yield. Check the lecture notes for the mathematical derivations of the code below.

American Spread Call is a type of option which gives the owner the right to earn the difference between two asset prices above a predefined strike price at any time till the expiration.

americanSpreadCallBinomial<-function(S1=100,S2=100,K=1,T=1,sigma1=0.2,sigma2=0.3,rho=0.5,r=0.06,N=3,div1=0.03,div2=0.04){

    dt <- T/N
    mu1<-r - div1 - 0.5*sigma1^2
    mu2<-r - div2 - 0.5*sigma2^2
    dx1<-sigma1*sqrt(dt)
    dx2<-sigma2*sqrt(dt)
    disc<-exp(-r*dt)
    puu<-(dx1*dx2+(dx2*mu1+dx1*mu2+rho*sigma1*sigma2)*dt)/(4*dx1*dx2)*disc
    pud<-(dx1*dx2+(dx2*mu1-dx1*mu2-rho*sigma1*sigma2)*dt)/(4*dx1*dx2)*disc
    pdu<-(dx1*dx2+(-dx2*mu1+dx1*mu2-rho*sigma1*sigma2)*dt)/(4*dx1*dx2)*disc
    pdd<-(dx1*dx2+(-dx2*mu1-dx1*mu2+rho*sigma1*sigma2)*dt)/(4*dx1*dx2)*disc
    edx1<-exp(dx1)
    edx2<-exp(dx2)

    S1t<-S1*exp(-N*dx1)
    S2t<-S2*exp(-N*dx2)
    for(j in 2:(2*N+1)){
        S1t[j]=S1t[j-1]*edx1
        S2t[j]=S2t[j-1]*edx2
    }

    C<-matrix(0,ncol=2*N+1,nrow=2*N+1)
    for(j in seq(-N,N,by=2)){
        for(k in seq(-N,N,by=2)){
            C[j+N+1,k+N+1] <- max(0,S1t[j+N+1]-S2t[k+N+1] - K)
        }
    }

    for(i in (N-1):0){
        for(j in seq(-i,i,by=2)){
            for(k in seq(-i,i,by=2)){
                C[j+N+1,k+N+1]<-
                    max(pdd*C[j+N,k+N]+pud*C[j+N+2,k+N]+pdu*C[j+N,k+N+2]+puu*C[j+N+2,k+N+2],
                    S1t[j+N+1]- S2t[k+N+1]-K)

            }
        }
    }

    return(C[N+1,N+1])
}

Trinomial Trees and Finite Difference Methods

Binomial trees are both practical and popular. Then, why stop there? Let’s build a trinomial tree.4

Trinomial Trees

In additional to the probabilities of binomial tree (\(p_u,p_d=1-p_u\)), we now have a probability of staying at the same level (\(p_m\)). So, \(p_m + p_u + p_d = 1\). Changes in the equations are as follows. Choice of \(\Delta x\) is recommended to be \(\sigma\sqrt{3\Delta t}\).

\[E[\Delta x] = p_u(\Delta x) + p_m 0 + p_d(-\Delta x) = \nu \Delta t\] \[E[\Delta x^2] = p_u(\Delta x^2) + p_m 0 + p_d(-\Delta x^2) = \sigma^2\Delta t + \nu^2\Delta t^2\]

The system of equations above will result in the following properties.

\[p_u = \dfrac{1}{2}(\dfrac{\sigma^2\Delta t + \nu^2\Delta t^2}{\Delta x^2}+\dfrac{\nu\Delta t}{\Delta x})\] \[p_d = \dfrac{1}{2}(\dfrac{\sigma^2\Delta t + \nu^2\Delta t^2}{\Delta x^2}-\dfrac{\nu\Delta t}{\Delta x})\] \[p_m = 1 - p_u - p_d = \dfrac{\sigma^2\Delta t + \nu^2\Delta t^2}{\Delta x^2}\]

Rest is similar to Binomial pricing method. R code is as follows.

##Trinomial Trees European Call
trinomialEC<-function(S0=100,K=100,T=1,sig=0.2,r=0.06,div=0.03,N=3){

    dt <- T/N
    dx <- sig*sqrt(3*dt)
    nu <- r - div - 0.5*sig^2
    edx <- exp(dx)
    pu <- 0.5*((sig^2*dt+nu^2*dt^2)/(dx^2)+nu*dt/dx)
    pd <- 0.5*((sig^2*dt+nu^2*dt^2)/(dx^2)-nu*dt/dx)
    pm <- 1 - pu - pd
    disc <- exp(-r*dt)

    S_mat <- matrix(ncol=2*N+1,nrow=N+1)
    S_mat[1,N+1]<-S0
    for(i in 1:N){
        S_mat[i+1,(N+1-i):(N+1+i)]<- S0*(exp(((-i:i)*dx)))
    }

    V_mat <- matrix(ncol=2*N+1,nrow=N+1)
    V_mat[N+1,] <- pmax(S_mat[N+1,]-K,0)
    for(i in N:1){
        V_mat[i,(N-i+2):(i+N)]<-disc*(pu*V_mat[i+1,(N-i+3):(i+N+1)] + pm*V_mat[i+1,(N-i+2):(i+N)] + pd*V_mat[i+1,(N-i+1):(i+N-1)])
    }

    return(list(Price=V_mat[1,N+1],V_mat=V_mat,S_mat=S_mat))

}

From Tree to Grid

Binomial and trinomial trees allow for 1 additional state at each time step. For instance, in a 3-step binomial tree there are 4 final states of option prices. Therefore, in order to increase the accuracy of the method there should be more time steps and decreased \(\Delta t\) so we have more states of option prices. If we can free the number of price states from the time steps we can get more granular therefore more accurate results. Suppose number of state jumps are \(N_j\).

But upper and lower boundaries of option values cannot be computed therefore boundary conditions should be defined. For European Call boundary conditions can be defined as follows.

\[\dfrac{\partial C}{\partial S} = 1\] for large \(S\). \[\dfrac{\partial C}{\partial S} = 0\] for small \(S\).

Discretize the values to grid and the result is as follows.

\[\dfrac{C_{i,N_j}-C_{i,N_j-1}}{S_{i,N_j}-S_{i,N_j-1}} = 1\] for large \(S\). \[\dfrac{C_{i,N_j}-C_{i,N_j-1}}{S_{i,N_j}-S_{i,N_j-1}} = 0\] for small \(S\).

Explicit Finite Difference Method (E-FDM)

Main idea behind finite difference methods is to discretize Black-Scholes PDE5.

\[-\dfrac{\partial C}{\partial t} = \dfrac{1}{2}S^2\sigma^2\dfrac{\partial^2 C}{\partial S^2} + (r - \delta)S\dfrac{\partial C}{\partial S} - rC\]

We can simplify it by using \(x = ln(S)\).

\[-\dfrac{\partial C}{\partial t} = \dfrac{1}{2}\sigma^2\dfrac{\partial^2 C}{\partial x^2} + \nu\dfrac{\partial C}{\partial x} - rC\]

This equation can be discretized as follows.

\[-\dfrac{C_{i+1,j}-C_{i,j}}{\Delta t} = \dfrac{1}{2}\sigma^2\dfrac{C_{i+1,j+1}-2C_{i+1,j}+C_{i+1,j-1}}{\Delta x^2} + \nu\dfrac{C_{i+1,j+1}-C_{i+1,j-1}}{2\Delta x}-rC_{i+1,j}\]

which we can rewrite as

\[C_{i,j} = p_uC_{i+1,j+1} + p_mC_{i+1,j} + p_dC_{i+1,j-1}\]

\[p_u = \Delta t (\dfrac{\sigma^2}{2\Delta x^2}+\dfrac{\nu}{2\Delta x})\] \[p_m = 1 - \Delta t \dfrac{\sigma^2}{2\Delta x^2} - r\Delta t\] \[p_d = \Delta t (\dfrac{\sigma^2}{2\Delta x^2}-\dfrac{\nu}{2\Delta x})\]

Hence the discount parameter at \(p_m\).

##Explicit Finite Difference Method European Call
explicitFDM_EC<-function(S0=100,K=100,T=1,sig=0.2,r=0.06,div=0.03,N=3,Nj=3,dx=0){

    if(Nj < N){
        print("Nj cannot be smaller than N. Equating Nj to N.")
        Nj <- N
    }

    dt <- T/N
    if(dx == 0){
        dx <- sig*sqrt(3*dt)
    }
    nu <- r - div - 0.5*sig^2
    edx <- exp(dx)
    pu <- 0.5*dt*(sig^2/dx^2+nu/dx)
    pd <- 0.5*dt*(sig^2/dx^2-nu/dx)
    pm <- 1 - pu - pd - r*dt

    St<-S0*exp((-Nj:Nj)*dx)
    V_mat <- matrix(ncol=2*Nj+1,nrow=N+1)
    V_mat[N+1,] <- pmax(0,St - K)

    for(i in N:1){
        V_mat[i,2:(2*Nj)]<-pu*V_mat[i+1,3:(2*Nj+1)] + pm*V_mat[i+1,2:(2*Nj)] + pd*V_mat[i+1,1:(2*Nj-1)]
        V_mat[i,1]<- V_mat[i,2]
        V_mat[i,(2*Nj+1)]<-V_mat[i,(2*Nj)] + (St[(2*Nj+1)]-St[(2*Nj)])
    }

    return(list(Price=V_mat[1,Nj+1],V_mat=V_mat))

}

Here is the code for American Put.

##Explicit Finite Difference Method American Put
explicitFDM_AP<-function(S0=100,K=100,T=1,sig=0.2,r=0.06,div=0.03,N=3,Nj=3,dx=0){

    dt <- T/N
    if(dx == 0){
        dx <- sig*sqrt(3*dt)
    }

    nu <- r - div - 0.5*sig^2
    edx <- exp(dx)
    pu <- 0.5*dt*(sig^2/dx^2+nu/dx)
    pd <- 0.5*dt*(sig^2/dx^2-nu/dx)
    pm <- 1 - pu - pd - r*dt

    St<-S0*exp((-Nj:Nj)*dx)
    V_mat <- matrix(ncol=2*Nj+1,nrow=N+1)
    V_mat[N+1,] <- pmax(0, K - St)

    for(i in N:1){
        V_mat[i,2:(2*Nj)]<-pu*V_mat[i+1,3:(2*Nj+1)] + pm*V_mat[i+1,2:(2*Nj)] + pd*V_mat[i+1,1:(2*Nj-1)]
        V_mat[i,1]<- V_mat[i,2]
        V_mat[i,(2*Nj+1)]<-V_mat[i,(2*Nj)] + (St[(2*Nj+1)]-St[(2*Nj)])
        V_mat[i,]<-pmax(V_mat[i,],K-St)
    }

    return(list(Price=V_mat[1,Nj+1],V_mat=V_mat))

}

Some notes about the explicit FDM.

  • \(p_u, p_m\) and \(p_d\) should be all positive.
  • Convergence condition \(\Delta x \ge \sigma\sqrt{3\Delta t}\) should be satisfied.
  • If volatility becomes too small with respect to risk free rate \(p_d\) can become negative.
  • If volatility becomes too large with respect to risk free rate \(p_m\) can become negative.
  • Reasonable range for \(\Delta x\) should cover \(\pm 3\sigma\) around the initial spot price. Suppose for \(\sigma=0.25\), adequate number of asset prices is 100. Then \(\Delta x = 6\sigma\sqrt{T}/100 = 0.015\).
  • Then number of time steps is \(N=\dfrac{T}{\Delta t} \ge 3(\dfrac{2N_j+1}{n_{SD}})^2\) where \(n_SD=6\) is the number of standard deviations.
  • It is also recommended that \(\dfrac{2N_j+1}{n_{SD}} > 15\). So at least 675 time steps is adequate.

Implicit Finite Difference Method (I-FDM)

Implicit FDM is the more stable version of the explicit FDM with additional computational complexity. It discretizes Black-Scholes PDE with space derivatives with time step \(i\) instead of \(i+1\).

\[-\dfrac{C_{i+1,j}-C_{i,j}}{\Delta t} = \dfrac{1}{2}\sigma^2\dfrac{C_{i,j+1}-2C_{i,j}+C_{i,j-1}}{\Delta x^2} + \nu\dfrac{C_{i,j+1}-C_{i,j-1}}{2\Delta x}-rC_{i,j}\]

which we can rewrite as

\[C_{i+1,j} = p_uC_{i,j+1} + p_mC_{i,j} + p_dC_{i,j-1}\]

\[p_u = - \Delta t (\dfrac{\sigma^2}{2\Delta x^2}+\dfrac{\nu}{2\Delta x})\] \[p_m = 1 + \Delta t \dfrac{\sigma^2}{2\Delta x^2} + r\Delta t\] \[p_d = - \Delta t (\dfrac{\sigma^2}{2\Delta x^2}-\dfrac{\nu}{2\Delta x})\]

This time option values cannot be calculated independently, therefore should be solved as a system of equations with boundary conditions.

\[C_{i,N_j}-C_{i,N_j-1} = \lambda_U\] for large \(S\). \[C_{i,-N_j+1}-C_{i,-N_j} = \lambda_L\] for small \(S\).

where \(\lambda_U\) and \(\lambda_L\) depends on the type of the function. For the European Call it is \(\lambda_U = S_{i,N_j}-S_{i,N_j-1}\) and \(\lambda_L = 0\).

The set of equations is called tridiagonal.

\[ \begin{vmatrix} 1 & -1 & 0 & \cdots & \cdots & \cdots & 0 \\ p_u & p_m & p_d & 0 & \cdots & \cdots & 0 \\ 0 & p_u & p_m & p_d & 0 & \cdots & 0 \\ \cdots & \cdots & \cdots & \cdots & \cdots & \cdots & \cdots \\ 0 & \cdots & 0 & p_u & p_m & p_d & 0 \\ 0 & \cdots & \cdots & 0 & p_u & p_m & p_d \\ 0 & \cdots & \cdots & \cdots & 0 & 1 & -1 \\ \end{vmatrix} \begin{vmatrix} C_{i,N_j} \\ C_{i,N_{j}-1} \\ C_{i,N_{j}-2} \\ \cdots \\ C_{i,-N_{j}+2} \\ C_{i,-N_{j}+1} \\ C_{i,-N_{j}} \\ \end{vmatrix} = \begin{vmatrix} \lambda_U \\ C_{i+1,N_{j}-1} \\ C_{i+1,N_{j}-2} \\ \cdots \\ C_{i+1,-N_{j}+2} \\ C_{i+1,-N_{j}+1} \\ \lambda_L \\ \end{vmatrix} \]

##Explicit Finite Difference Method American Put
implicitFDM_AP<-function(S0=100,K=100,T=1,sig=0.2,r=0.06,div=0.03,N=3,Nj=3,dx=0.2){

    dt <- T/N
    if(dx == 0){
        dx <- sig*sqrt(3*dt)
    }

    nu <- r - div - 0.5*sig^2
    edx <- exp(dx)
    pu <- -0.5*dt*(sig^2/dx^2+nu/dx)
    pd <- -0.5*dt*(sig^2/dx^2-nu/dx)
    pm <- 1 + dt*(sig^2/dx^2) + r*dt

    St<-S0*exp((-Nj:Nj)*dx)
    V_mat <- matrix(ncol=2*Nj+1,nrow=N+1)
    V_mat[N+1,] <- pmax(0, K - St)

    lambdaL <- -1*(St[2] - St[1])
    lambdaU <- 0

    amat<-matrix(0,ncol=2*Nj+1,nrow=2*Nj+1)
    amat[1,]<-c(1,-1,rep(0,2*Nj-1))
    for(i in 2:(2*Nj)){
        amat[i,]<-c(rep(0,i-2),pu,pm,pd,rep(0,2*Nj-i))
    }
    amat[2*Nj+1,]<-c(rep(0,2*Nj-1),1,-1)

    solve(amat,vmp)

    for(i in N:1){
        vmp<-rev(c(lambdaL,unlist(V_mat[i+1,-c(1,2*Nj+1)]),lambdaU))
        V_mat[i,]<-pmax(rev(solve(amat,vmp)),K-St)
    }

    return(list(Price=V_mat[1,Nj+1],V_mat=V_mat))

}

Greeks for Implicit FDM

For FDM methods on trinomial trees the Delta and Gamma of the option can be approximated as follows.

\[\Delta = \dfrac{\partial C}{\partial S} \approx \dfrac{C_{0,j+1} - C_{0,j-1}}{S_{0,j+1} - S_{0,j-1}}\]

\[\Gamma = \dfrac{\partial^2 C}{\partial S^2} \approx \dfrac{\left(\dfrac{C_{0,j+1} - C_{0,j-1}}{S_{0,j+1} - S_{0,j-1}}\right)-\left(\dfrac{C_{0,j+1} - C_{0,j-1}}{S_{0,j+1} - S_{0,j-1}}\right)}{1/2(S_{0,j+1}-S_{0,j-1})}\]


  1. Risk-free rate \(r\) should be choosen such that \(d < e^{r.dt} < u\) to avoid arbitrage admission.

  2. Check Merton’s ‘Theory of Rational Option Pricing’ for the proof.

  3. See the textbook (Clewlow and Stickland)

  4. For those who are curious about quadrinomial tree; yes there is research about that too. See http://www.tandfonline.com/doi/abs/10.1080/13504860701596745

  5. Partial differential equation.