| 1. | Introduction |
| 2. | Binomial model |
| 3. | Options |
| 4. | American puts |
| 5. | Systems of equations |
| 6. | Matrix operations |
| 7. | Matrix inverse |
Option Pricing with C++ Tables
Once we fix an underlying asset (such as a stock), we can build derived assets whose payoffs depend on the behavior of the underlying asset. The simplest among them are European call options.
1. Introduction to European call options
European call option is a derived security that has the following parameters:
- Underlying asset. Usually a specific stock is the underlying asset for a European call.
- Expiration time. A time in the future is fixed. In real world, the expiration time is quoted as a specific date in the future. In our notes, the expiration time \(T\) will be the length of time that needs to pass from the present until the expiration of the option. Thus, if we write \(T=0.25\), this would mean that the option expires in \(0.25\) years. If we write \(T=2\), we will mean that the option expires in \(2\) years.
- Strike price. The strike price will be denoted by \(K\).
If the buyer decides to buy one share of the underlying asset from the seller, the seller is not allowed to refuse. Thus, if at the expiration, the price of the underlying asset is higher than the strike \(K\), the buyer will choose to exercise the option and get the underlying asset. The buyer will be paying the cheaper price \(K\), instead of the regular price \(S_T\) for the underlying asset.
Exercising the option is equivalent to the seller giving money \((S_T-K)^+\) to the buyer. The quantity \((S_T-K)^+\) is called the payoff of the option.
2. Option prices in binomial model
If the price of the stock is assumed to follow the binomial model with parameters \(n\), \(S\), \(u\), and \(d\), and if the simple interest rate \(r\) over one period satisfies \(u> 1+r> d\), then the price of the derived security with expiration \(n\) satisfies \begin{eqnarray*}\mbox{Price}&=& \frac1{(1+r)^n}\cdot \mathbb E_*\left[\mbox{Payoff}(S_n)\right], \end{eqnarray*} where \(\mathbb E_*\) is the expectation under the risk-neutral probability.
The risk-neutral probability \(p_*\) that in each period stock price gets multiplied by \(u\) is \begin{eqnarray*}p_*&=&\mathbb P_*\left(S_{i+1}=S_i\cdot u\right)=\frac{1+r-d}{u-d}. \end{eqnarray*} Consequenlty, the risk neutral probability \(q_*\) of the event \(\{S_{i+1}=S_i\cdot d\}\) satisfies \(q_*=1-p_*=\frac{u-1-r}{u-d}\).
3. Example
Let us analyze a European call option with expiration \(n=2\) and strike \(K=\$180\) whose underlying security is the stock from the example we made in the section Binomial model. The parameters in the example were \(n=2\), \(S_0=S=\$200\), \(u=1.25\), \(d=0.75\). The stock price tree was
\begin{eqnarray*} \begin{array}{ccccc} \quad & \quad & \quad & \quad & \$312.5\\ & & & \nearrow & \quad\\ & & \$250& &\\ &\nearrow & &\searrow&\\ \$200& &&& \$187.5\\ &\searrow & & \nearrow&\\ & & \$150& &\\ & & & \searrow & \\ & & & & \$112.5 \end{array} \end{eqnarray*}We will assume that the interest rate over each period is \(r=10\%=0.1\).
Our goal is to determine the price \(C_0\) of the European call option with expiration \(n=2\) and strike \(K=\$180\).
There are \(3\) possible prices that the stock can take at the expiration \(n=2\). They are \(312.5\), \(187.5\), and \(112.5\). The possible payoffs the European call option are \begin{eqnarray*}C_{u^2}&=&\mbox{Payoff}(312.5)=(312.5-180)^+=132.5, \\C_{ud}&=&\mbox{Payoff}(187.5)=(187.5-180)^+=7.5,\quad\mbox{and}\\ C_{d^2}&=&\mbox{Payoff}(112.5)=(112.5-180)^+=0.\end{eqnarray*} We completed our first step in constructing the option price tree. The result is not a complete tree. We only have the last column.
\begin{eqnarray*} \begin{array}{ccccc} \quad & \quad & \quad & \quad & \$132.5\\ & & & \nearrow & \quad\\ & &C_u& &\\ &\nearrow & &\searrow&\\ C_0& &&& \$7.5\\ &\searrow & & \nearrow&\\ & & C_d& &\\ & & & \searrow & \\ & & & & \$0 \end{array} \end{eqnarray*}The numbers \(C_0\), \(C_u\), and \(C_d\) are unknown at the moment. We will calculate them soon. The number \(C_u\) is the price of the option in the binomial model with one period in which the possible payoffs are \(C_{u^2}=132.5\) and \(C_{ud}=7.5\). According to the Theorem 1, the price \(C_u\) satisfies \begin{eqnarray*} C_u&=&\frac1{1+r}\mathbb E_*\left[\mbox{Payoff}\right]\\ &=&\frac1{1+r}\cdot\left(C_{u^2}\cdot p_*+C_{ud}\cdot q_*\right),\quad \mbox{where }\\ p_*&=&\frac{1+r-d}{u-d}=0.7\quad \mbox{ and }\\ q_*&=&1-p_*=0.3. \end{eqnarray*} The price \(C_u\) is \(C_u=86.363636\).
In a very similar way we obtain \begin{eqnarray*}C_d &=& \frac1{1+r}\cdot \left(C_{ud}\cdot p_*+C_{d^2}\cdot q_*\right)\\ &=& \frac1{1.1}\cdot \left(7.5\cdot 0.7+0\cdot 0.3\right)\\ &=&4.772727.\end{eqnarray*} The tree after the second step is \begin{eqnarray*} \begin{array}{ccccc} \quad & \quad & \quad & \quad & \$132.5\\ & & & \nearrow & \quad\\ & &86.363636& &\\ &\nearrow & &\searrow&\\ C_0& &&& \$7.5\\ &\searrow & & \nearrow&\\ & & 4.772727& &\\ & & & \searrow & \\ & & & & \$0 \end{array} \end{eqnarray*} Finally, \begin{eqnarray*}C_0 &=& \frac1{1+r}\cdot \left(C_{u}\cdot p_*+C_{d}\cdot q_*\right)=56.26033.\end{eqnarray*} The final tree is \begin{eqnarray*} \begin{array}{ccccc} \quad & \quad & \quad & \quad & \$132.5\\ & & & \nearrow & \quad\\ & &86.363636& &\\ &\nearrow & &\searrow&\\ 56.26033& &&& \$7.5\\ &\searrow & & \nearrow&\\ & & 4.772727& &\\ & & & \searrow & \\ & & & & \$0 \end{array} \end{eqnarray*}
4. Option price tree with C++ tables
In the section Binomial model we made a program that creates the stock price tree. We will need that program now. We will extend it to calculate prices of European call options.
4.1. Input variables
The two additional variables that we need are the interest rate \(r\) and the strike \(K\). We will read them from A[0][4] and A[0][5].
double r,K; r=A[0][4]; K=A[0][5];
4.2. Data structure for option tree
The option price tree has the same format as the stock price tree. We need a vector of \(n+1\) vectors whose lengths are \(1\), \(2\), \(\dots\), \(n+1\). Instead of manually resizing the vectors, we can just copy the data structure stock_tree. Eventually, we will re-write each of its entries. This copying is done merely as a convenient way to allocate memory of correct shape.
std::vector<std::vector<double> > option_tree=stock_tree;
4.3. Calculations of option prices
The option tree is constructed backwards. The last column is the payoff column. Its entries are the payoffs of the options at the expiration time \(n\). There are \(n+1\) elements in the payoff column because there are \(n+1\) possible prices for the stock at the expiration time \(n\). Each price of the stock determines the payoff uniquely.
i=0;
while(i<=n){
if(stock_tree[n][i]>K){
option_tree[n][i]=stock_tree[n][i]-K;
}
else{
option_tree[n][i]=0;
}
i=i+1;
}
The remaining columns are treated differently than the last column \(n\). For fixed \(i\) that satisfies \(i< n\) and for fixed \(j\) that satisfies \(0\leq j\leq i\), we will use the entries option_tree[i+1][j] and
option_tree[i+1][j+1] to evaluate option_tree[i][j] using the formula
\[\mbox{option_tree}[i][j]=\frac1{1+r}\left(p_*\cdot \mbox{option_tree}[i+1][j]+q_*\cdot \mbox{option_tree}[i+1][j+1]\right).\]
double pStar,qStar;
pStar=(1.0+r-d)/(u-d); qStar=1.0-pStar;
i=n-1;
while(i>=0){
j=0;
while(j<=i){
option_tree[i][j]=(1.0/(1.0+r)) * (pStar*option_tree[i+1][j]+qStar*option_tree[i+1][j+1]);
j=j+1;
}
i=i-1;
}
4.4. Preparation of output
In the section Binomial model
we made a transfer from stock_tree to B. Here we will do an analogous operation. We'll just use option_tree instead of stock_tree.
i=0;
while(i<=n){
j=i;
while(j<=n){
B[i][j]=option_tree[j][i];
j=j+1;
}
i=i+1;
}
4.5. Final code
double S, u, d;
S=A[0][1]; u=A[0][2]; d=A[0][3];
int n;
n=A[0][0];
std::vector<std::vector<double> > stockTree;
stockTree.resize(n+1);
int i;
i=0;
while(i<=n){
stockTree[i].resize(i+1);
i=i+1;
}
stockTree[0][0]=S;
int j;
i=1;
while(i<=n){
stockTree[i][0]=stockTree[i-1][0]*u;
j=1;
while(j<=i){
stockTree[i][j]=stockTree[i-1][j-1]*d;
j=j+1;
}
i=i+1;
}
double r,K;
r=A[0][4]; K=A[0][5];
std::vector<std::vector<double> > optionTree=stockTree;
i=0;
while(i<=n){
if(stockTree[n][i]>K){
optionTree[n][i]=stockTree[n][i]-K;
}
else{
optionTree[n][i]=0;
}
i=i+1;
}
double pStar,qStar;
pStar=(1.0+r-d)/(u-d); qStar=1.0-pStar;
i=n-1;
while(i>=0){
j=0;
while(j<=i){
optionTree[i][j]=(1.0/(1.0+r))
* (pStar*optionTree[i+1][j]
+ qStar*optionTree[i+1][j+1]);
j=j+1;
}
i=i-1;
}
i=0;
while(i<=n){
j=i;
while(j<=n){
B[i][j]=optionTree[j][i];
j=j+1;
}
i=i+1;
}