Option Pricing using the Binomial Tree Model in C#
Introduction
I would like to put forth a simple class that calculates the present value of an American option using the binomial tree model.
Background
Calculation of a European option is typically performed using the closed form solution that Fischer Black and Myron Scholes developed in 1973. While the BlackScholes formula is wellknown as the equation that triggered huge growth in the options markets, what are perhaps less wellknown are some of the alternative models for pricing options, particularly for Americanstyle options. In 1979, a few gentlemen by the names of Cox, Ross, and Rubenstein came up with what is known as the binomial tree or binomial lattice method. This is the standard method used for calculating the value of an American option. Unlike the BlackScholes model, the binomial tree model is not a closed form equation, but rather is a computationally intensive numerical method.
Because of putcall parity, the behavior that two products with the same payoff must have the same value, we can create a synthetic option by valuing a replicating portfolio of assets that have the same payoff. The model uses a lattice made up of discrete time steps, and each node in the lattice represents a possible price at a particular (discrete) point in time. We start at the final time step (maturity) and work backwards, valuing each node along the way until we reach the current time.
Pricing American Options
For an American option, we calculate the value of each binomial node as the maximum of either the Strike minus the Exercise price or zero (for a call), or the maximum of the Exercise price minus the Strike or zero (for a put). The reason we must calculate this payoff at every node is because the owner of the option has the 'option' to exercise at every discrete time step.
Implementing the Binomial Tree
In this example, my approach was to be as clear as possible in the code. If I was to include this code in a largescale pricing system, I would of course not include basic financial math functions such as present value or n factorial in the binomial tree class. But for the sake of expediency, these small functions are included within the class.
An enumeration, EPutCall, is used to represent whether the option is a call or a put.
The user of this class may either pass all the arguments in the constructor, or if instance reuse is required, can set properties. The arguments required are the current AssetPrice, Strike, TimeStep, Volatility, EPutCall, EOptionStyle, RiskFreeRate, and Steps, which is the number of discrete time steps the user designates the binomial tree to contain.
The core calculation of the binomial tree model is the value of each node on the tree. You may have noticed that this code only supports options on assets that do not pay dividends. To modify the code for dividendpaying assets, simply subtract the dividend from the risk free rate such that:
private double BinomialNodeValue(int m, int n, double p)
{
return BinomialCoefficient(m, n) * Math.Pow(p,
(double)m) * Math.Pow(1.0  p, (double)(n  m));
}
The binomial coefficient is a part of the formula used in calculating the value of an individual binomial node.
private double BinomialCoefficient(int m, int n)
{
return Factorial(n) / (Factorial(m) * Factorial(n  m));
}
While intuitively we think of calculating the nodes on a binomial tree backwards, you will notice that my for loop is counting up. This is because my counter, j, is being used to calculate the current step number by subtracting j from the number of total steps (step  j).
public double OptionValue()
{
double totalValue = 0.0;
double u = OptionUp(timeStep, volatility, steps);
double d = OptionDown(timeStep, volatility, steps);
double p = Probability(timeStep, volatility, steps, riskFreeRate);
double nodeValue = 0.0;
double payoffValue= 0.0;
for (int j = 0; j <= steps; j++)
{
payoffValue = Payoff(AssetPrice * Math.Pow(u,
(double)j) * Math.Pow(d,
(double)(steps  j)), strike, putCall);
nodeValue = BinomialNodeValue(j, steps, p);
totalValue += nodeValue * payoffValue;
}
return PresentValue(totalValue, riskFreeRate, timeStep);
}
For an American option, we must calculate the expected payoff at each node of the tree. The payoff is always the greater of the intrinsic value or zero, as intrinsic value cannot be less than zero.
private double Payoff(double S, double X, EPutCall PutCall)
{
switch (PutCall)
{
case EPutCall.Call:
return Call(S, X);
case EPutCall.Put:
return Put(S, X);
default:
return 0.0;
}
}
private double Call(double S, double X)
{
return Math.Max(0.0, S  X);
}
private double Put(double S, double X)
{
return Math.Max(0.0, X  S);
}
To use our little C# binomial tree class, we can simply pass all our arguments into the constructor and retrieve the OptionValue property. In this case, we are pricing a put option where the current price of the asset is 100, the strike is set at 95, the time to maturity is 0.5 years, annualized volatility is 30%, the risk free rate is 8%, and we are constructing a binomial tree of 5 discrete time steps.
BinomialTree tree =
new BinomialTree(100,95,0.5,0.3,0.08,EPutCall.Put,5);
double presentValue = tree.OptionValue();
Finally, let's compare our results with the final result of a 100,000 step Monte Carlo simulation. After all, we don't want to rely on a model that hasn't been thoroughly tested!
Points of Interest
In addition to the binomial tree, American options may be modeled using a trinomial tree. This model assumes an asset may move up, down, or remain flat. Another model is the jump diffusion model where asset price changes are assumed to not only vary in direction but also in magnitude. These models are, of course, more complex than the simple binomial tree but are typically closer to real world option pricing.
Further Reading
About AndrewPeters
Andrew Peters is a systems developer interested in nontrivial trading systems and financial systems architecture. He is currently focused on realtime, high performance multithreaded applications running on the server and the desktop.
After a 4 year stint in China learning Mandarin and Tibetan, Andrew returned to the US to learn more about enterprise development and financial markets. While in China, he translated meetings between demure Communist officials and angry American businessmen, served coffee and fetid tofu in his 'BaiSuiFang' Coffee Shop, started Fabrefactum Software and was generally laughed at for his stupid jokes in Chinese.
He currently helps the pricing/analytics team hack on code at Chatham Financial, an interest rate and foreign exchange derivative consulting company.
