Click here to Skip to main content
15,897,273 members
Articles / Programming Languages / C#

Option Pricing using the Binomial Tree Model in C#

Rate me:
Please Sign up or sign in to vote.
4.80/5 (16 votes)
4 Apr 20064 min read 118.6K   1.9K   71  
Calculates the present value of an American option using the Cox-Ross-Rubenstein binomial tree model.
using System;

namespace QFramework
{
	/// <summary>
	/// Represents a Cox-Ross-Rubenstein binomial tree option pricing calculator.  May be used for pricing European or American options
	/// </summary>
	public class BinomialTree
	{
		#region "Private Members"

		private double assetPrice = 0.0;
		private double strike = 0.0;
		private double timeStep = 0.0;
		private double volatility = 0.0;
		private EPutCall putCall = EPutCall.Call;
		
		private double riskFreeRate = 0.0;
		private int steps = 0;
		
		#endregion

		#region "Properties'
		public double AssetPrice
		{
			get { return assetPrice;}
			set { assetPrice = value; }
		}

		public double Strike
		{
			get { return strike; }
			set { strike = value; }
		}

		public double TimeStep 
		{
			get { return timeStep; }
			set { timeStep = value; }
		}

		public double Volatility
		{
			get { return volatility; }
			set { volatility = value; }
		}

		public EPutCall PutCall
		{
			get { return putCall; }
			set{ putCall = value; }
		}

		public double RiskFreeRate
		{
			get { return riskFreeRate; }
			set { riskFreeRate = value; }
		}

		public int Steps
		{
			get { return steps; }
			set  { steps = value; }
		}

		#endregion

		#region "Constructors"
		/// <summary>
		/// Empty constructor.  All properties may be set.
		/// </summary>
		public BinomialTree()
		{
		}

		/// <summary>
		/// Constructor that takes all parameters used for calculatin option value using binomial tree
		/// </summary>
		/// <param name="assetPriceParam"></param>
		/// <param name="strikeParam"></param>
		/// <param name="timeStepParam"></param>
		/// <param name="volatilityParam"></param>
		/// <param name="riskFreeRateParam"></param>
		/// <param name="putCallParam"></param>
		/// <param name="optionStyleParam"></param>
		/// <param name="stepsParam"></param>
		public BinomialTree(
			double assetPriceParam, 
			double strikeParam, 
			double timeStepParam, 
			double volatilityParam, 
			double riskFreeRateParam, 
			EPutCall putCallParam, 
			int stepsParam)
		{
			assetPrice = assetPriceParam;
			strike = strikeParam;
			volatility = volatilityParam;
			timeStep = timeStepParam;
			riskFreeRate = riskFreeRateParam;
			putCall = putCallParam;
			steps = stepsParam;
		}
		#endregion

		#region "Binomial Tree"
		/// <summary>
		/// Part of the binomial node value equation, represents the binomial coefficient
		/// </summary>
		/// <param name="m"></param>
		/// <param name="n"></param>
		/// <returns></returns>
		private double BinomialCoefficient(int m, int n)
		{
			return Factorial(n) / (Factorial(m) * Factorial(n - m));
		}

		/// <summary>
		/// Calculates the value of an individual node in the binomial tree
		/// </summary>
		/// <param name="m"></param>
		/// <param name="n"></param>
		/// <param name="p"></param>
		/// <returns></returns>
		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));
		}

		/// <summary>
		/// Returns the present value of the option
		/// </summary>
		/// <returns></returns>
		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);
		}
		#endregion

		#region "Probabilities"
		private double OptionUp(double t, double s, int n)
		{
			return Math.Exp(s * Math.Sqrt(t / n));
		}

		private double OptionDown(double t, double s, int n)
		{
			return Math.Exp(-s * Math.Sqrt(t / n));
		}

		private double Probability(double t, double s, int n, double r)
		{
			double d1 = FutureValue(1.0, r, t / n);
			double d2 = OptionUp(t, s, n);
			double d3 = OptionDown(t, s, n);
			return (d1 - d3) / (d2 - d3);
		}
		#endregion
		
		#region "Payoffs"

		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);
		}
		#endregion

		#region "Financial Math Utility Functions"
		private double Factorial(int n)
		{
			double d = 1.0;
			for (int j = 1; j <= n; j++)
			{
				d *= j;
			}
			return d;
		}

		private double FutureValue(double P, double r, double n)
		{
			return P * Math.Pow(1.0 + r, n);
		}

		private double PresentValue(double F, double r, double n)
		{
			return F / Math.Exp(r * n);
		}
		#endregion
		
	}
} 

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Web Developer
United States United States
Andrew Peters is a systems developer interested in non-trivial trading systems and financial systems architecture. He is currently focused on realtime, high performance multi-threaded 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.

Comments and Discussions