MPI.NET – Distributed Computations with the Message Passing Interface in F# – Part 2

by Call me dave... 17. May 2009 21:17

In a previous post I described that it was possible to calculate PI using Monte Carlo

Using the same technique it is possible to price financial products such as insurance.  Customers pay a premium for heath cover.  If they get sick the insurance company is then obligated to pay any medical costs that “may” occur.  This means that the customer has a fixed “known” upfront cost meanwhile the insurance company’s possible costs range from almost nothing to that of an extremely expensive medical bill resulting from a surgical procedure.  It is possible to run thousands of “What if scenarios” and use the results to estimate the amount of capital that is needed to cover the costs for all of the customers at the organisation.

Another example is pricing an Option which is a simple version of Insurance and is used to lock in the price of a product that the company wants to buy or sell at a future date. 

Buying an option – going Long:

Buyer has no obligation to exercise the Option however the seller of the Option is legally obligated to provide the product at the price indicated in the contract.  Buyer pays a premium to the seller.

  • Call - Buyer assumes the price is going to rise and wants to lock in the price – Airline buys an option to lock in the price of fuel for its fleet as it fears that prices will rise in 6 months. If the price drops in six months the Airline buys Oil from the market at the cheaper price.
  • Put – Buyer assumes that the price is going to fall and wants to lock in the price – Oil manufacturer believes prices will be lower in 6 months as the economy is slowing and fears that oil prices will fall.  If the oil price increases the manufacturer sells the oil at the higher market price.

Selling an option – going Short:

Seller is obligated to provide the product at the price indicated in the contract if the buyer exercises the contract.  An exercised contract is a loss for the seller, in comparison, if the contract is not exercised the Seller makes a profit in the amount of the Premium.

  • Call – Seller assumes the price is going to fall
  • Put – Seller assumes that the price is going to rise

Simulating a European Option

The Financial Numerical Recipes in C++web site includes a number of tutorials using C++ to calculate Bond Prices, Option Prices etc.  I recently have been porting the code snippets to F# to gain more familiarity with the language.

The C++ code to simulate the price of an Option is here

The first part of the simulation is randomly generate what the price will be in the future.  The value has an equal probability of being higher or lower than the starting price.  The inputs to the simulation are:

  • Current Value (S)
  • Interest Rate (r)– Since we are simulating the price in the future we want to convert the price back into todays money
  • Time (time) – Duration to the contract’s exercise date
  • Volatility (sigma) – The magnitude of the random movements, at each point in time, that the price is expected to have – Best guess based on historical data and is the most problematic and difficult part of pricing Options. 
    • A low volatility implies the the final price WILL NOT have diverged far from the current value S
    • A high volatility implies the the final price WILL have diverged far from the current value S
  • Type of Walk – Stock prices are assumed to be “lognormal walk” which means that each price movement is a percentage change
    • S1 = S * 0.1 * randomChoiceOf(1 or –1)
    • S2 = S1 * 0.1 * randomChoiceOf(1 or –1)

The C++ simulation uses a library to generate a random normal distribution which in turn is used to create the lognormal walk.  Meanwhile the System.Random object in .NET provides random numbers where the generated values are equally spread across the range 0 to 1.  A random normal distribution meanwhile generates values that follow a Gaussian distribution with the “mean” being zero and the shape looking like a bell curve.   While it is easy to create a method that will generate a normal distribution the excellent Math.NET Project provides this capability all ready.

let logNormalRandom = new MathNet.Numerics.Distributions.NormalDistribution()
let next = logNormalRandom.NextDouble()

This leads to the following ported code:

   1: let R = (r - (0.5 * Math.Pow(sigma, 2.0))) * time
   2: let SD = sigma * Math.Sqrt(time)
   3: let FuturePrice = S * Math.Exp(R + SD * logNormalRandom.NextDouble())

The code above returns what the future price will be for a particular simulation.  Following the explanation of Options above the buyer only exercises the option if it will make a profit over buying the product directory from the market (In the Money) and programatically is as follows:

   1: let europe_call_payoff price exercise =  Math.Max(0.0, price - exercise)
   2: let europe_put_payoff price exercise =  Math.Max(0.0, exercise - price)

The final code is here

   1: #light
   3: open System
   5: // Financial Numerical Recipes in C
   6: //
   7: let europe_call_payoff price exercise =  Math.Max(0.0, price - exercise)
   8: let europe_put_payoff price exercise =  Math.Max(0.0, exercise - price)
  10: let option_price_call_european S X r sigma time payoff sims =
  11:   let logNormalRandom = new MathNet.Numerics.Distributions.NormalDistribution()
  13:   let R = (r - (0.5 * Math.Pow(sigma, 2.0))) * time
  14:   let SD = sigma * Math.Sqrt(time)
  16:   let option_price_simulation()  =
  17:     let S_T = S * Math.Exp(R + SD * logNormalRandom.NextDouble())
  18:     payoff S_T X
  20:   let rec futureValueIter i value = 
  21:     match i with
  22:     |0 -> value + option_price_simulation()
  23:     |_ -> futureValueIter (i-1) (option_price_simulation() + value)
  25:   let futureValue = futureValueIter sims 0.0
  26:   System.Math.Exp(-r * time) * (futureValue / (double)sims)

And the test

   1: #light
   3: open MbUnit.Framework
   4: open OptionPricingModel
   6: [<Test>]
   7: let simulate_call_option() = 
   8:   let result = option_price_call_european 100.0 100.0 0.1 0.25 1.0 europe_call_payoff 500000
   9:   Assert.AreApproximatelyEqual(14.995, result, 0.03)

Once again the simulation is “close” to the correct value in this case within 3%.  The C++ code shows techniques to improve the accuracy of the simulation which I will do a in a future post and at the same time host the simulation within MPI.NET.


Comments are closed