The purchaser of the cap, for a fee or premium paid at inception, is protected against increases in a floating interest rate on its floating rate exposure for a certain nominated upper limit for a given time duration. The floating rate historically would have been linked to a well known benchmark like Libor or Euribor. An interest rate cap constitutes a series of call options (or caplets) on a floating interest rate index, usually 3 or 6 month Libor if dollar denominated. These typically would coincide with the rollover dates on the borrower’s floating liabilities. An Interest Rate Cap could be used as a tool to manage interest rate exposures for corporates planning to repay borrowed funds. The cap can be viewed as a maximum interest rate on the variable rate loan. A Cap can thus protect against a rise in interest rates while preserving the opportunity to benefit from a fall in interest rates. This maximum interest rate can be modeled as Strike Rate in an option and thus we can infer the value of a cap or caplet using the standard techniques linked to the Black (1976) model. In exchange for the protection of the Cap, you pay an Option Premium as a one-off up front cost. We use the Black (1976) model to investigate the value of the option or premium excluding transaction costs. The example is taken from John C Hull "Option , Futures and Other Derivatives". See VBA code below and Excel Implementation:
Function Black_Call(F, K, r, sigma, T1, T2)
'
' Inputs are F = Futures
' K = strike price
' r = risk-free rate
' sigma = volatility
' T1 = time to maturity of Option
' T2 = time to payoff
'
Dim d1, d2, N1, N2
d1 = (Log(F / K) + (0.5 * sigma * sigma) * T1) / (sigma * Sqr(T1))
d2 = d1 - sigma * Sqr(T1)
N1 = Application.NormSDist(d1)
N2 = Application.NormSDist(d2)
Black_Call = Exp(-r * T2) * (F * N1 - K * N2)
End Function
Function Black_Put(F, K, r, sigma, T1, T2)
'
' Inputs are F = Futures
' K = strike price
' r = risk-free rate
' sigma = volatility
' T1 = time to maturity of Option
' T2 = time to payoff
'
Dim d1, d2, N1, N2
d1 = (Log(F / K) + (0.5 * sigma * sigma) * T1) / (sigma * Sqr(T1))
d2 = d1 - sigma * Sqr(T1)
NN1 = Application.NormSDist(-d1)
NN2 = Application.NormSDist(-d2)
Black_Put = Exp(-r * T2) * (K * NN2 - F * NN1)
End Function
// Checked results against excel and calculation is correct
// The code here can be used to estimate the value of a caplet or floorlet
#include <iostream>
#include <vector>
#include <cmath>
using namespace std;
// N(0,1) density
double
f (double x)
{
double pi = 4.0 * atan (1.0);
return exp (-x * x * 0.5) / sqrt (2 * pi);
}
// Boole's Rule
double
Boole (double StartPoint, double EndPoint, int n)
{
vector < double >X (n + 1, 0.0);
vector < double >Y (n + 1, 0.0);
double delta_x = (EndPoint - StartPoint) / double (n);
for (int i = 0; i <= n; i++)
{
X[i] = StartPoint + i * delta_x;
Y[i] = f (X[i]);
}
double sum = 0;
for (int t = 0; t <= (n - 1) / 4; t++)
{
int ind = 4 * t;
sum += (1 / 45.0) * (14 * Y[ind] + 64 * Y[ind + 1] + 24 * Y[ind + 2] +
64 * Y[ind + 3] + 14 * Y[ind + 4]) * delta_x;
}
return sum;
}
// N(0,1) cdf by Boole's Rule
double
N (double x)
{
return Boole (-10.0, x, 240);
}
// Black 1976 Cap or Floor
double
BlackCP (double F, double K, double T1, double T2, double r, double v,
char OpType, double L)
{
double d = (log (F / K) + T1 * (0.5 * v * v)) / (v * sqrt (T1));
double call = exp (-r * T2) * (F * N (d) - K * N (d - v * sqrt (T1)));
if (OpType == 'C')
return call * L * (T2 - T1);
else
return (call - (F - K) * exp (-r * T2)) * L * (T2 - T1);
}
int
main ()
{
double F = 0.07; // Risk Free rate (Discrete time)
double K = 0.08; // Strike Price
double T1 = 1; // Option Expiry
double T2 = 1.25; // Loan Expiry
double r = 0.069394; // Risk free interest rate = m * ln(1+F/m)
double v = 0.20; // Yearly volatility
char OpType = 'C'; // 'C'all (Caplet) or 'P'ut (Floorlet)
double L = 10000;
cout << "Black Model " << BlackCP (F, K, T1, T2, r, v, OpType, L) << endl;
// not used in xcode
system ("PAUSE");
};
Below we explain, how to estimate the value of a caplet and flooret using both VBA and Xcode C++ presented above. The Black (1976) model is implemented to estimate the caplet. The floorlet is inferred using put-call parity. We develop this relationship for this specific interest rate product. We use the Xcode compiler to run the C++ code. The second video immediately employs Microsoft Visual Studio
# Black (1976) model for Caplet and Floorlet
# for backward compatability with Python 2.7
from __future__ import division
# import necessary libaries
import math
import numpy as np
from scipy.stats import norm
from scipy.stats import mvn
# Inputs: option_type = "p" or "c", fs = price of underlying, x = strike, t1 = time to expiration,
# r = risk free rate, t2 = time to payoff, b = cost of carry, v = implied volatility
# Outputs: value, delta, gamma, theta, vega, rho
def _gbs(option_type, fs, x, t1, r, b, v, t2, L):
# Create preliminary calculations
t__sqrt = math.sqrt(t1)
d1 = (math.log(fs / x) + (b + (v * v) / 2) * t1) / (v * t__sqrt)
d2 = d1 - v * t__sqrt
if option_type == "c":
# it's a call
# _debug(" Call Option")
value = L * (t2 - t1) * (fs * math.exp((b - r) * t2) * norm.cdf(d1) - x * math.exp(-r * t2) * norm.cdf(d2))
else:
# it's a put
# _debug(" Put Option")
value = L * (t2 - t1) * (x * math.exp(-r * t2) * norm.cdf(-d2) - fs * math.exp((b - r) * t2) * norm.cdf(-d1))
return value
# This is the public interface for European Options
# Each call does a little bit of processing and then calls the calculations located in the _gbs module
# Inputs:
# option_type = "p" or "c"
# fs = floating rate
# x = strike rate
# t1 = time to expiration
# v = implied volatility
# r = risk free rate
# q = dividend payment
# b = cost of carry or (r - q)
# t2 = time to payoff
# L = Principal
# Outputs:
# value = price of the option
# Merton Model: Stocks Index, stocks with a continuous dividend yields
def black_76(option_type, fs, x, t1, r, v, t2, L):
b = 0
return _gbs(option_type, fs, x, t1, r, b, v, t2, L)
p = black_76('p', fs=0.07, x=0.08, t1=1., r=0.069395, v=0.2, t2 = 1.25, L = 10000)
print( p )
c = black_76('c', fs=0.07, x=0.08, t1=1., r=0.069395, v=0.2, t2 = 1.25, L = 10000)
print( c )