Leveraged ETF – A Simulation

This post is a token of appreciation for Faisal Habib who taught us structured products this summer.

As commonly known among people who are familiar with leveraged ETFs, the tracking error of those products tend to be larger than what we intuitively expected. This phenomenon has been explored and explained by Avellaneda and Zhang (2009). More information can also be found here. In a nutshell, the discrepancy resides in the borrowing cost incurred in a replication portfolio and extra realized variance in a continuous model. The resources linked above have more details, here I think it’ll be interesting just to model it out and take a look at the simulated results.

To do this I simulated four time-series.

  1. An underlying that follows GBM.
  2. An imaginary product that provides perfect leverage simply by multiplying the underlying return by the leverage ratio.
  3. A leveraged product that achieves leveraged return by constructing a static replication portfolio with risk-free rate r.
  4. A leveraged ETF modeled in continuous time, i.e., drift term adjusted using Ito’s lemma.

Here we have the results after running it once with 2x leverage and daily frequency (delta_t = 1/252). I know it strikingly resembles the shape of S&P500 but I swear this is pure coincidence (I thought it’s cool, too).

Rplot

And annualized returns:

underlying_process simple_multiplication static_replication leveraged_etf
12.0% 25.4% 23.6% 22.3%

A quick note. The annualized return of the simple multiplication process (# 2) is way above 2 times of the underlying because of the compounding effect in a raging bull market we just created. The static replication (# 3) underperforms # 2 roughly by the same amount of the annual risk-free rate. The leveraged ETF (# 4) underperforms # 3 by the annual variance of the underlying. These results are consistent with previous studies.

There are a lot of ways to play with this so I’ll post the source code here for anyone who’s interested in trying it out (or let me know if I made any mistakes).

LETF <- function(S_0 = 100,
                 r_f = 0.015,
                 borrow_cost = 0.01,
                 mu = 0.05,
                 sigma = 0.1,
                 end_t = 5,
                 delta_t = 1/252,
                 leverage = 2) {
  # create a vector of the undelrying process
  n <- end_t / delta_t
  underlying_process <- zoo(0, 1:n)
  underlying_process[1] <- S_0      if (leverage > 1) {borrow_cost <- 0}

  # create vectors of simple_multiplication, static replication
  # and leveraged ETF without expense ratio
  simple_multiplication <- underlying_process
  static_replication <- underlying_process
  leveraged_etf <- underlying_process

  for (i in 2:n) {
    # the random component of the GBM model
    rdn <- rnorm(1)

    # model the underlying with GBM
    underlying_process[i] <- coredata(underlying_process[i - 1]) *
      exp((mu - sigma ^ 2 / 2) * delta_t + sigma * sqrt(delta_t) * rdn)
    underlying_log_return <- log(coredata(underlying_process[i]) /
                                   coredata(underlying_process[i - 1]))

    # model a leveraged process by simplely multiplying underlying returns
    simple_multiplication_log_return <- leverage * underlying_log_return
    simple_multiplication[i] <- simple_multiplication[i - 1] *
      exp(simple_multiplication_log_return)

    # model static replication return with equation (1) and (2) in
    # Avellaneda and Zhang (2009)
    static_replication_log_return <- underlying_log_return * leverage -
      ((leverage - 1) * r_f - borrow_cost * leverage) * delta_t
    static_replication[i] <- coredata(static_replication[i - 1]) *
      exp(static_replication_log_return)

    # model leveraged etf return with equation (10) in
    # Avellaneda and Zhang (2009)
    leveraged_etf[i] <- coredata(leveraged_etf[i - 1]) *
      exp(underlying_log_return) ^ leverage *
      exp(-((leverage - 1) * r_f +
              sigma ^ 2 * leverage * (leverage - 1) / 2) * delta_t)
  }
  return(merge(underlying_process, simple_multiplication,
               static_replication, leveraged_etf))
}

 

Roy