Asian Options I

Today I’m going to introduce the first exotic option that I’ve looked at in my blog, the Asian option. There is quite a lot to be said about them so I’ll do it over a few posts. I’ll also be updating the pricers to price these options in a variety of ways.

The simplest form of Asian option has a payoff similar to a vanilla option, but instead of depending on the value of the underlying spot price at expiry, it instead depends on the average the underlying spot price over a series of dates specified in the option contract. That is, the value of the option at expiry C(T) is the payoff

    \[C(T) = \Big( {1\over N}\sum^{N}_{i=0} S_{t_i} - K\Big)^+\]

where K is the strike, N is the number of averaging dates, and S_t is the value of the spot that is realised at each of these dates.

First of all, what does it mean that this is an exotic option? From the market, we will be able to see the prices of vanilla options at or near each of the dates that the contract depends on. As I discussed in my post on Risk-Neutral Valuation, from these prices we can calculate the expected distribution of possible future spot prices at each date – shouldn’t we be able to use this to calculate a unique price of the Asian option consistent with the vanilla prices?

The answer, unfortunately, is no. Although we know the distribution at each time, this doesn’t tell us anything about the correlations between the price at time t_1 and time t_2, which will be critical for the Asian option. To illustrate this, let’s consider a simple Asian that only averages over two dates, t_1 and t_2, and we’ll take t_2 to be the payoff date for ease, and try to calculate its price via risk-neutral valuation. The price at expiry will be

    \[C(t_2) = \Big( {1\over 2}\big(S_{t_1} + S_{t_2}\big) - K\Big)^+\]

To calculate the price at earlier times, we use the martingale property of the discounted price in the risk-neutral measure

    \[C(0) = N(0)\cdot{\mathbb E}^{RN} \Bigl[ \ {C(t_2) \over N(t_2)}\ |\ {\cal F}_0\ \Bigr]\]

and expanding this out as an integral, we have

    \[C(0) = \delta_{0,t_2} \int \int \Big( {1 \over 2} \big( S_{t_1} + S_{t_2} \big) - K \Big)^+\ p(S_{t_1},S_{t_2})\ dS_{t_1} dS_{t_2}\]

where \delta denotes the discount factor to avoid confusion with the pdfs inside the integral. From the market, we know both p(S_{t_1}) and p(S_{t_2}), which are respectively the market-implied probability distributions of the spot price at times t_1 and t_2 calculated from vanilla call prices using the expression we derived before

    \[p(S_{t}) = {1 \over \delta_{0,t}}{\partial^2 C(t) \over \partial K^2}\]

But, we don’t know the JOINT distribution p(S_{t_1},S_{t_2}) which expresses the effect of the dependence of the two distributions. We know from basic statistics that

    \[p(S_{t_2},S_{t_1}) = p(S_{t_2} | S_{t_1}) \cdot p(S_{t_1})\]

and since the spot at the later time depends on the realised value of the spot at the earlier time p(S_{t_2} | S_{t_1}) \neq p(S_{t_2}), so we don’t have enough information to solve the problem from only the market information available from vanilla options.

What is this telling us? It is saying that the market-available information isn’t enough to uniquely determine a model for underlying price movements with time. There are a variety of models that will all re-create the same vanilla prices, but will disagree on the price of anything more exotic, including our simple Asian option. However, observed vanilla prices do allow us to put some bounds on the price of the option. For example, a careful application of the triangle inequality tells us that

    \[\Big( {1\over 2}\big(S_{t_1} + S_{t_2}\big) - K \Big)^+ \leq {1\over 2} \Big( S_{t_1} - K_1 \Big)^+ + {1\over 2} \Big( S_{t_2} - K_2 \Big)^+\]

for any K_1 + K_2 = 2K; the expressions on the right are the payoff at expiry of call options on S_{t_1} and S_{t_2} respectively, and we can see the prices of these on the market, which allow an upper bound on the asian price. This means that, while we can’t uniquely price the option using the market information alone, we CAN be sure that any model consistent with market vanilla prices will produce an asian price that is lower than the limit implied by this inequality.

In order to go further, we need to make a choice of model. Our choice will determine the price that we get for our option, and changing model may well lead to a change in price – analysing this ‘model risk’ is one of a quant’s main jobs. A very simple choice such as Black Scholes [but note that BS might not be able to re-create an arbitrary vanilla option surface, for example if there is a vol smile at some time slices] will allow us to solve the integral above by numerical integration or by Monte Carlo (this option form still doesn’t have a closed form solution even in BS).

In the coming posts I’m going to develop the Monte Carlo pricer on the blog to price asian options in BS, and look at a number of simplifying assumptions that can be made which will allow us to find closed form approximations to the price of Asian options.

 

Finally, a brief note on the naming and usage of Asian options. Opinion seems divided – some people believe they are called Asian options because they’re neither European nor American, while some people say it’s because they were first traded in Japan. They are often traded so that the days on which the averaging is done are the business days of the last month of the option’s life. As the look up period is spread out over a period, they are less susceptible to market manipulation on any particular date, which can be important in less liquid markets, although the theoretical prices of Asian options like this are usually very similar in price to vanilla options at any of the look up dates. More exotic Asians might average over the last day of a month for a year. This average is much less volatile than the underlying over the same period, so Asian options are much cheaper than a portfolio of vanillas, but it’s easy to imagine that they might well match the risk exposure of a company very well, since companies trading in two or more currency areas will probably be happy to hedge their average exchange rate over a period of time rather than the exchange rate at any one particular time.

European vs. American Options

 
All of the options that I’ve discussed so far on this blog have been European options. A European option gives us the right to buy or sell an asset at a fixed price, but only on a particular expiry date. In this post, I’m going to start looking at American options, which give the right to buy or sell at ANY date up until the expiry date.

Surprisingly for the case of vanilla options, despite the apparent extra utility of American options, it turns out that the price of American and European options is almost always the same! Why is this?

The value of a european call option, broken down into its intrinsic and its time component. Volatility is 10%, strike is 100, time to expiry is 1 year and risk free rate is 1%
The value of a european call option, broken down into its intrinsic and its time component. Volatility is 10%, strike is 100, time to expiry is 1 year and risk free rate is 1%

In general, American options are MUCH harder to price than European options, since they depend in detail on the path that the underlying takes on its way to the expiry date, unlike Europeans which just depend on the terminal value, and no closed form solution exists. One thing we can say is that an American option will never be LESS valuable than the corresponding European option, as it gives you extra optionality but doesn’t take anything away. So we can always take the European price to be a lower bound on American prices. Also note that Put-Call Parity no longer holds for Americans, and becomes instead an inequality.

How can we go any further? It is useful in this case to think about the value of an option as made up of two separate parts, an ‘intrinsic value’ and a ‘time value’, which sum to give the true option value. The ‘intrinsic value’ is the value that would be received if the exercise was today – in the case of a vanilla call, this is simply \max(0,S-K). The ‘time value’ is the ‘extra’ value due to time-to-expiry. This is the volatility-dependent part of the price, since we are shielded by the optionality from price swings in the wrong direction, but are still exposed to upside from swings in our favour. As time goes by, the value of the option must approach the ‘intrinsic value’, as the ‘time value’ decays towards expiry.

Consider the graph above, which shows the BS value of a simple European call under typical parameters. Time value is maximal at-the-money, since this is the point where the implicit insurance that the option provides is most useful to us (far in- or out-of-the-money, the option is only useful if there are large price swings, which are unlikely).




What is the extra value that we should assign to an American call relative to a European call due to the extra optionality it gives us? In the case of an American option, at any point before expiry we can exercise and take the intrinsic value there and then. But up until expiry, the value of a European call option is ALWAYS* more than the intrinsic value, as the time value is non-negative. This means that we can sell the option on the market for more than the price that would be received by exercising an American option before expiry – so a rational investor should never do this, and the price of a European and American vanilla call should be identical.

It seems initially as though the same should be true for put options, but actually this turns out not quite to be right. Consider the graph below, showing the same values for a European vanilla put option, under the same parameters.

The value of a european put option under the same parameters as used above, broken down into intrinsic and time components. Unlike the call option, for far in-the-money puts, the time value can be negative, so early exercise can be valuable
The value of a european put option under the same parameters as used above, broken down into intrinsic and time components. Unlike the call option, for far in-the-money puts, the time value can be negative, so early exercise can be valuable

Notice that here, unlike before, when the put is far in-the-money the option value becomes smaller than the intrinsic value – the time value of the option is negative! In this case, if we held an American rather than a European option it might well make sense to exercise at this point, since we would receive the intrinsic value, which is greater than the option value on the market [actually it’s slightly more complicated, because in this scenario the American option price would be higher than the European value shown below, so it would need to be a bit more in the money before it was worth exercising – you can see how this sort of recursive problem rapidly becomes hard to deal with!].

What is it that causes this effect for in-the-money puts? It turns out that it comes down to interest rates. Roughly what is happening is this – if we exercise an in-the-money American put to receive the intrinsic value, we receive (K-S) cash straight away. But if we left the option until expiry, our expected payoff is roughly (K-F), where F is the forward value

    \[F(t,T) = {1\over ZCB(t,T)} S(t)\]

so we can see that leaving the underlying to evolve is likely to harm our option value [this is only true for options deep enough in the money for us to be able to roughly neglect the \max(0,K-S) criterion]

We can put this on a slightly more rigourous footing by thinking about the GREEK for time-dependence, Theta. For vanilla options, this is given by

    \begin{align*} \Theta &= - {\partial V \over \partial \tau} \nonumber \\ &= ZCB(t,T)\cdot\Big\{-{\sigma F(t,T) \phi(d_1)\over 2\sqrt{\tau}} \mp rK\Phi(\pm d_2) \Big\} \nonumber \end{align*}

where F is the forward price from t to T\phi(x) is the standard normal PDF of x and \Phi(x) is its CDF, ZCB is a zero-coupon bond from t to T and the upper of the \mp refers to calls and the lower to puts.

The form for Theta shows exactly what I said in the last paragraph – for both calls and puts there is a negative component coming from the ‘optionality’, which is decreasing with time, and a term coming from the expected change in the spot at expiry due to interest rates which is negative for calls and positive for puts.

The plot below shows Theta for the two options shown in the graphs above, and sure enough where the time value of the European put goes negative, Theta becomes positive – the true option value is increasing with time instead of decreasing as usual, as the true value converges to the intrinsic value from below.

The Theta value for European options. For a European put, this becomes positive when the option value falls below the intrinsic value. The difference between these two Thetas is independent of spot, which can be seen directly from put-call parity.
The Theta value for European options. For a European put, this becomes positive when the option value falls below the intrinsic value. The difference between these two Thetas is independent of spot, which can be seen directly from put-call parity.

*Caveats – I’m assuming a few things here – there are no dividends, rates are positive (negative rates reverses the situation discussed above – so that American CALLS can be more valuable than Europeans), no transaction fees or storage costs, and the other sensibleness and simpleness criteria that we usually assume apply.

In between European and American options lie Bermudan options, a class of options that can be exercised early but only at one of a specific set of times. As I said, it is in general really tough to price more exotic options with early exercise features like these, I’ll look at some methods soon – but this introduction is enough for today!

Excel Monte-Carlo Pricer

I’ve updated the Monte-Carlo pricer to run in excel. Give it a go and the benefits should be obvious – no more messing around with consoles or repeated typing, excel provides a handy interface for running C++ files.

What you’ll need to do is:

  • Download the Excel pricing sheet
  • Download the .xll library (large!) – this is the equivalent of the old .exe file
  • Open the Excel file, and drag-and-drop the .xll file inside the pricing sheet
  • Click on the option to “enable this add-on for this session only”
  • The Option Price function should now re-calculate option price as you make changes to the parameters!

Try using the option pricer function yourself – it now works just like a native excel function, so you can drag it into many cells and it will adjust target cells as usual allowing for easy variation of parameters and plotting of results.

If you’ve successfully set up XLW and Code::Blocks as I described in a previous post, I’ve also made the source code available in a .zip file which you can load in Code::Blocks and fiddle with yourself. I’ll be doing a bit of updating soon to make the code slightly cleaner and allow pricing of more interesting options.

The old console project source code is still available in compiled form and with the source code in a zip file at the bottom of the MC pricers page.

Running C++ in Excel via XLW

Anyone who has downloaded and compiled the console version of my Monte Carlo Pricer will know that it’s not incredibly user-friendly. You have to double-click on an .exe file to run it, and then each time select input parameters which involves a fair amount of typing. The output is given as a single number on a console window, which isn’t very convenient for plotting multiple results or for further data analysis.

In fact, console applications aren’t that commonly used by quants. There are a few solutions used in the industry, and the one I’m going to look at today is an excel wrapper. The idea is that we will write C++ code as normal, then use a programme called XLW to wrap it as a link library and allow it to be called from inside excel. This combines the advantages of excel’s flexibility with C++’s speed and power. This post is going to be a step-by-step guide to getting things up and running (I’ve struggled with it a bit while trying to set things up) with a very simple example function – in future posts I’ll discuss shifting the old pricer over to an excel implementation.

I’m going to go through with screenshots from a clean start, hopefully this should be fairly general but if things change in future it may become outdated and require me to update or re-write these guidelines. I will discuss how to set XLW up using the open source Code::Blocks IDE, it’s a bit more advanced than the Dev-C++ that I’ve been using before and I’m shifting to it from now on for this blog.

Instructions:

  • Download and install Code::Blocks, WITHOUT a built in compiler

Auto-installers are available here, but it’s important that you choose the version WITHOUT the built in compiler, as this is out of date

Choose this download!
Choose this download!

Double-click on the downloaded file to auto-install; agree to the terms and choose default options (by default it should do a full install needing about 60MB and install to directory “C:\Program Files (x86)\CodeBlocks”)

 

  • Download and install the latest version of MinGW compiler

The latest version of the MinGW compiler can be found here, download and double-click on the .exe file to install. Click through the screens, choosing the following option on the third screen: “Use pre-packaged repository catalogues”; by default the compiler will install to “C:\MinGW”. On the ‘select components’ screen, be sure to select “C++ Compiler”! This WASN’T checked for me by default!

Check C++ compiler on this screen
Check C++ compiler on this screen

 

  • Register MinGW with Code::Blocks

In order to register the compiler that we’ve just downloaded, run Code::Blocks (there should now be a shortcut from your start bar).

How to register MinGW with Code::Blocks
How to register MinGW with Code::Blocks

In the toolbar, select Settings->Compiler Settings; and in the window that opens select the “Toolchain Executables” tab. Click on “Auto-detect”, and the IDE should find MinGW successfully.

 

  • Download and install XLW

The latest version of XLW is available via the “Download” link on the front page of the project here. At the time of writing, this is version 5.0 (released Feb’ 2013).

Once again, double-click on the downloaded .exe to install, but pay attention to the screens that pop up as I had to make some modifications to the default choices, as follows:

  1. XLW auto-detected Code::Blocks on the third page (Installed Development Environments) – if you see a blank white box here, you’ve not installed the IDE correctly
  2. On the 4th screen, I had to expand the grey ‘X’s and selected the option shown in the image below
Expand the selections, and check 'Code::Blocks' under 'Source'
Expand the selections, and check ‘Code::Blocks’ under ‘Source’

By default, XLW will install to “C:\Program Files (x86)\XLW\xlw-5.0.0f0”

 

  • Run the XLW template generator

Now we’re getting close. In your start menu, you should now find an XLW option. Go to XLW>xlw-5.0.0f0>xlw>Extract XLW xll template; select “Code::Blocks” on the window that appears, by default the template will be created in the directory “C:\Users\….\Documents\XLL_Project”

Select Code::Blocks in the template extractor options
Select Code::Blocks in the template extractor options

 

  • FIX REQUIRED!!

Unfortunately, there seems to be a bug which has something to do with how XLW and MinGW are talking to one-another. After fiddling with many install configurations without success, I found the same issue discussed here (the second paragraph with a dark background), along with the following fix:

  1. Go to C:\MinGW\bin and locate “mingw32-make.exe”
  2. Copy this to the directory C:\Users\….\Documents\XLL_Project which you created in the previous step (it should contain “RunInterfaceGenerator.mak” among other files)
  3. Rename “mingw32-make.exe” to “make.exe”
  4. Run Code::Blocks, in the toolbar go to Settings->Compiler again, and in the window that pops up select ‘Restore Defaults’. Click ‘OK’ on both of the warning pop-up windows.

 

  • Open the Template project in Code::Blocks

If it isn’t already running from the last step, run Code::Blocks. Go to the directory C:\Users\….\Documents\XLL_Project that was created before, and open the project file “Template.cbp”. If all of the previous steps have been done correctly, you should simply be able to click “Build” (it’s the cog-shaped icon in one of the task bars) and have it compile without problems. Note that after compilation, a file called “Template.xll” appears in the directory C:\Users\….\Documents\XLL_Project\bin\Debug\

To test that everything is working, add an additional function to “source.cpp” and declare it in “cppinterface.h”, such as the example given in the picture below and at the bottom of this post, and check that the project still compiles.

I've added a trivial additional function here to add two doubles - of course, I've also updated the header file with a declaration of the function. XLW will do the rest!
I’ve added a trivial additional function here to add two doubles – of course, I’ve also updated the header file with a declaration of the function. XLW will do the rest!

 

  • Call our functions in Excel!

Open an instance of Excel. In order to load the functions that we’ve created into Excel, find the file “Template.xll” in the directory C:\Users\….\Documents\XLL_Project\bin\Debug\ and drag-and-drop it into the Excel window.

Here we can see the trivial example we made before in action - our function is adding two doubles in different cells together. I will present more advanced examples in future posts.
Here we can see the trivial example we made before in action – our function is adding two doubles in different cells together. I will present more advanced examples in future posts.

You should now find that the additional function you’ve written is available alongside Excel’s in-built functions: congratulations, you’ve made your C++ scripts run with excel as a front end! I’ll be looking at the advantages of this a lot in the near future.

 

Additional example function code

In source.cpp:

double // adds two doubles
AddTwoDoubles( double x, // The first double
               double y  // The second double
              )
{
  return x + y;
}

In cppinterface.h (before the #endif ):

double // adds two doubles
AddTwoDoubles( double x, // The first double
               double y  // The second double
              );

Put-Call Parity

Put-Call parity is a simple result connecting the prices of puts and calls in a model-independent way via the forward price.

Consider the three graphs below, showing independently the payoff at expiry of a vanilla call, a vanilla put, and a forward contract. We can see that the payoff of a long call plus the payoff of a short put will precisely overlap the forward contract payoff (assuming they have the same strike and expiry…).

The combination of a long call and a short put with the same strike and expiry is equivalent to a forward at the same strike and expiry. This is guaranteed by their payoffs at expiry (making the usual assumptions about tradability of the underlying/forward etc.), since the payoff of holding a long call and a short strike can be exactly hedged by holding a forward contract
The combination of a long call and a short put with the same strike and expiry is equivalent to a forward at the same strike and expiry. This is guaranteed by their payoffs at expiry (making the usual assumptions about tradability of the underlying/forward etc.), since the payoff of holding a long call and a short strike can be exactly hedged by holding a forward contract

This can be seen from the algebra as well:

\begin{align*} C_{\rm call}(T) - C_{\rm put}(T)\ & = \big( S(T) - K \big)^+ - \big( K - S(T) \big)^+ \\ & = S(T) - K \\ & = F(T,T) \end{align*}

If two portfolios have the same payoff, it’s a fundamental rule of derivatives pricing that they must have the same price, which gives the fundamental put-call parity relationship

C_{\rm call}(t) - C_{\rm put}(t)\ = Z(t,T)\cdot\Big( F(t,T) - K\Big)

We can take the BS expressions for put and call prices given in a previous post and observe that they obey the relationship [since \inline \Phi(x) + \Phi(-x) = 1], but importantly this result is model independent. As long as there is a forward contract available with the strike and expiry of the options, then this result MUST hold in ANY model.

One implication of this is that if we use a model to determine the price of a call option, put-call parity fixes the price of the put option to be

C_{\rm put}(t) = C_{\rm call}(t) - Z(t,T)\cdot\Big( F(t,T) - K\Big)

We can actually use this to improve our code. Out-of-the-money options typically require more paths to converge in Monte Carlo simulations because they rely on the detailed behaviour of a few paths that travel a long way. However, we can calculate in-the-money prices quickly and due to put-call parity these will lock the price of the matching out-of-the-money options.

Put-call parity is also an important test of the implementation of a model – if the prices that we are getting out don’t obey this relationship then we’ve done something seriously wrong [as long as both prices have converged!]. An equivalent statement is that the implied BS volatility of matching puts and calls should be exactly the same in any model, since the implied vol is the BS vol that would produce the given price for a put/call, and this is locked by put-call parity.

We can get some other similar relationships between put and call prices that I’ll look at in the future. Also note that put-call parity holds for european-style options, but not for many more complicated path-dependent options or those with early exercise features like American options.

Factoryised C++

In two of my most recent posts I’ve talked about Forward Contracts and an implementation of the Normal Quantile function. One strategic reason for this will become apparent from today’s post!

I’m going to be talking here about one of the design patterns used in the Monte Carlo code presented on my blog and discussed recently. It isn’t really my goal for this blog to dwell heavily on programming topics as there are many, many more competent people than me sharing their knowledge on the subject across the web. However, there are some topics that are quite interesting to discuss and make ideal blog topics, and a grounding in Object-Oriented programming (particularly in C++) is vital for the modern Quant.

As I stated before, the goal of the code presented to date in ‘Simple Option Pricer 1.0’ is to choose a fairly simple option payoff, choose a method for generating uniform random numbers, and then choose a method for generating gaussian variates from these (and of course to enter the relevant market parameters like discount factor and volatility). The first thing to do is to download all of the code presented on that page, compile it, and run it a few times to make sure you can get all of it to work. Check the answers correspond to the results you get from the analytical pricers for the same parameters, although don’t forget that there will be some Monte Carlo error on the answers coming for C++, and observe that answers get better (though time taken increases!) as the number of paths is increased.

A very straight-forward way of achieving selectivity would be to use a switch statement:

int option;
SimpleOption* theOptionPointer;

cout << "Select a Contract Type: Call [1], Put [2]";
cin >> option;

switch ( option ) {
 case 1 :
  theOptionPointer = new CallOption( ... );
  break;
 case 2 :
  theOptionPointer = new PutOption( ... );
  break;
 default :
  throw("You must enter [1] or [2]!");
}

where I’ve assumed that we’ve defined some suitable option classes elsewhere that all inherit from an abstract base class SimpleOption (if there is demand for it I might go over inheritance another time, but there are many sources on the web. This IS important for quants, but it’s rather dry to go over!).

The switch statement looks at the user-entered value and assigns the pointer to an option of the relevant type. This is a basic example of polymorphism – we’ve declared theOptionPointer to be a pointer to the abstract base class SimpleOption, but then given it the address of a specific implementation of the base class via a derived class, either CallOption or PutOption. If we were to call any functions of this pointer, they would have to be those functions defined in the base class itself (although they could be abstract and potentially over-loaded in the derived classes) – if, for example, CallOption had a method called getStrike(), there would need to be a [potentially abstract] prototype for this in the base class SimpleOption if we want to have access to it via the SimpleOption pointer..

However, the code isn’t that great as it stands. We’re going to need a switch statement for each of the choices we’re giving the user (currently Option type, RNG type and Gaussian converter type), which will lead to a bloated main(){} function. More annoyingly, every time we want to include a new option in any of these selections, as well as coding up the relevant classes for the new choice we’re going to need to go into the main function and alter the choices and control structures given by the switch statements. As well as being a bother, this will mean the whole project will need to be re-compiled, and for large projects this can be a significant time constraint. You can see roughly how much time this takes by comparing the speed of Build/Compiling your project (which checks to see if changes have been made, and then only rebuilds the files that are affected) with the time taken to Re-Build/Re-Compile your project (which throws away previously compiled files and starts again from the beginning). Give this a try!

I’ve got around this in ‘Simple Option Pricer 1.0’ by coding up a basic Factory for each of the three selections, based on the Factory presented in Chapter 10 of Joshi’s text, C++ Design Patterns and Derivatives Pricing (this is one of my favourite textbooks on the subject – I’ll do some book reviews of other gems in the future). You can see how this works by downloading the following four files:

Drop these into the same folder as the rest of the files in ‘Simple Option Pricer 1.0’, and then right-click on the Project in your development environment and add them to the project one-by-one [Nb. if you’re using Visual Studio, you may need to add

#include "stdafx.h"

to the two .cpp files before this will work – and make sure they’re in the same folder as the rest, this can cause problems!!].

Now, Build/Compile your project. If you’ve done everything correctly, it should happen very swiftly – only the forward.cpp and the gaussianCdfInverter.cpp will need to compile, and the linker will need to run, but the other files won’t need to be recompiled (this is the real strength of the method, by the way!). Now, re-run the programme and you should discover two new options available to you for the option pricer! How have we achieved this sorcery?!

In the files optionFactory.cpp and optionFactory.h (and the corresponding files for the RNG and gaussian converters), we’ve defined the factories for the different types of classes we want to use. I’ve used the Singleton Pattern (for brevity I’m not going to discuss it here, but do have a look at wikipedia) to create and access a single instance of each factory. The important point is that there will be a single instance of each factory, and we can get their addresses in memory using the following method at any point in the code

optionFactory::factoryAddress()

The factories themselves store a two column table (implemented with a map) which links a string (the option name) in the first column with a function that constructs an option of that type and returns a pointer to it in the second column (this will be a base class pointer, using polymorphism as discussed above).

The functions that will create these pointers are implemented using another type of polymorphism – templatisation. In the optionFactoryHelper.h header, I’ve defined a new class which is constructed by calling it with a string. It also has a method which builds a new instance of the <class T>, and returns a pointer to it – which is exactly what we said the factory table needs.

template <class T>
simpleOption* simpleOptionHelper<T>::buildOption(double strike) {
 return new T(strike);
}

The constructer for the helper function registers this method in the factory’s table, along with the string.

template <class T>
simpleOptionHelper<T>::simpleOptionHelper(std::string optionType){
 optionFactory& theFactoryAddress = optionFactory::factoryAddress();
 theFactoryAddress.registerOption(optionType, simpleOptionHelper<T>::buildOption);
}

Options are registered in their .cpp files, the simple code to register the forward is at the top of forward.cpp, creating a new instance of the helper class templatised on the specific instance of the option that we are registering through it. This will call the helper class constructor, which as we just saw contains code to register the corresponding option type with the factory

namespace {
 simpleOptionHelper<forward> registerForward("forward");
}

Since these are done in namespaces, they happen before main(){} starts running – and once registered, we can call the factory at any time in our code using a string and giving it the required parameters and it will create a new instance of the derived class with that name

simpleOption* thisOptionPointer = optionFactory::factoryAddress().createOption( optionType, strike );

I’ll use this pattern again and again in future as more and more options are added to the code. At some point in the future, I’ll look at a way of combining ALL of the factories into a single, templatised factory process using more polymorphism, but the complication will be that since different processes need different arguments for their constructors, I’ll need to build a generic container class first that could contain many different sorts of arguments inside it. The next thing I want to do, however, is look at easier ways of data input and output, as the current console application is very clunky and wouldn’t be suitable for a large amount of data input. I’ll discuss ways of dealing with this in future posts.

Futures

I covered Forward Contracts in a post a week ago, and promised to look at the related Futures Contract soon. These contracts aim to do the same thing – provide a means of ensuring an underlying asset for future delivery at a price determined today – but their dynamics are rather different from those of the Forward Contract.

One of the main criticisms of Forward Contracts is that they are directly written between two parties. This means they are subject to credit risk – if one counterparty goes bankrupt, the contract may not be guaranteed any more. By contrast, a Futures Contract is written via an exchange. This is a central organisation that matches long and short Futures Contract counterparties, and oversees the transaction (and of course, charges a fee for its services). Futures Contracts are standardised in terms of expiry dates and contract terms, which increases liquidity in the market. The counterparty who wants to receive the underlying asset at expiry is said to be the long party, while the one providing it is the short party.

As with a Forward Contract, an underlying asset is specified. Each party must have an account with the exchange in order to enter transactions. Each day, the exchange will quote the current Futures Price, which is the price at which the transaction will happen; but to enter into the contract doesn’t cost either party (beyond the small exchange fee mentioned above). Instead, the counterparties must update their accounts daily to reflect the difference between the initial Futures Price quoted and the current Futures Price quoted. If it is above the initial price, the party who is short the contract must have this difference in their account; and if it is below the initial price, the party who is long must have this difference in their account.

This is probably best demonstrated by a simple example. Let’s say that I want to enter a Futures Contract on Day 0 for delivery of a barrel of oil on Day 5 (realistically this would be a much longer period of months or years, but in order to keep the number of steps in the example down I’m keeping it short here), the current Futures Price quoted for a contract expiring in 5 days is $100. I’m the long party as I want to receive the oil, my counterparty is short as he will be delivering.

Day 1: Futures Price quoted for expiry on Day 5 increases to $101.50. The short party has to deposit $1.50 in his account to cover this increase.

Day 2: Futures Price increases to $103.50. The short party has to deposit another $2 in his account to cover this increase (so it’s now $3.50 total).

Day 3: Futures Price falls to $101. The short party can withdraw $2.50 from his account to leave only $1, which covers the change from day 0.

Day 4: Futures Price for delivery on Day 5 (ie. tomorrow!) crashes to $96. The short party can take all of the money out of his account, and I need to deposit $4 to cover the difference between the current Futures Price and its initial value.

Day 5: Futures Price recovers to $97. I can take $1 out of my account to leave $3 total. Since this is the day the contract expires, we make the transaction today at the initially agreed Futures Price of $100, and the money in my account is returned to me (if the money was in the short party’s account, it would have been returned to him in the same way). Note also that the Futures Price on day 5 for expiry on day 5 must be equal to the spot rate at that time – so this contract obliges me to trade at a price above the current spot rate, just as a Forward Contract at these prices would have done.

There are several points to make. Firstly, I’ve described a Physically Settled Futures Contract here, since I actually took delivery of a barrel of oil. The standardised contracts will specify a grade of oil and a specific delivery location – many exchanges have physical warehouses for these transactions to happen. However, the large majority of Futures Contracts today are Cash Settled: in this case, instead of taking a delivery, I exchange money with the short party to achieve the same financial payoff. In the example above, since we were transacting at $100 while the market price was only $97, I would have to pay $3 to the short party (as we shall see, it’s no coincidence that this was the amount in my account!).

This contract more-or-less eliminates credit risk due to a counterparty defaulting. Consider, for example, that the oil company had defaulted on Day 2. This might seem like bad news for me – at that point, I was expecting to pay $100 for a commodity worth $103.50. The critical point is the account with the exchange. This amount is forfeited if the counterparty wants to leave the transaction or fails to keep topping it up as required, and delivered to the other party. In this case, the short party’s account of $3.50 would have been given to me, and the contract terminated – since the current price was $103.50, I could enter the same contract with a different counterparty without taking any financial loss.

On the other hand, if I’d decided on Day 4 that I no longer wanted to be part of the contract, as it looked like I’d be paying $100 while the contract is only worth $96, I might abscond. However, the exchange still has my $4 on account which it can take and give to the short counterparty, so once again they aren’t hurt by my reneging. The only risk to either party is that there is a large shift in price in a very short time, so that the counterparty is unable to credit a sufficient amount to his account before defaulting.

Although it more-or-less deals with credit risk, this contract does introduce liquidity risk. Considering again Day 2, the company had had to deposit money in their account to cover the position. Even though the contract eventually ends up profitably for the short party, it is conceivable that cash-flow concerns would make them unable to honour their intermediate commitments, in which case they would have to break the contract at that stage and take a loss. For a Forward Contract, as there is no payment until the expiry date this couldn’t happen.

Aside from these issues, this contract seems to be essentially the same as a Forward Contract, since it guaranteed a transaction on Day 5 at $100. However, so far we have ignored interest rates, which turn out to make a subtle difference to the final payoff (and which make the maths interesting!).

I’m going to to another post soon comparing these two contracts in the presence of interest rates, but I’ll tell you the answer right now to whet your appetite: in the presence of deterministic interest rates, the two payoffs are the same. This isn’t surprising – if we know what will happen in the future then we can hedge by replication both of the contracts (Forward Contracts in the way described in the previous post on them; Futures Contracts as I will describe next time – but have a go and try to construct a replication strategy yourself) so that their values are fixed today. However, this is actually quite unrealistic and most real models of interest rates include stochastic interest rates of some type – in this case, the Futures Contract becomes a path-dependent derivative and we can’t construct a static hedge for it at the current time, since we don’t know what the interest rate will look like at each stage! More to come soon.

New Section: Monte Carlo in C++

Good news, this blog has a new section – Monte Carlo pricers! I’m going to experiment to find the most convenient way of making it available for download, and would like it to be available both as a compiled .exe and also as uncompiled source code to allow readers to examine and alter it.

The first iteration can be found online now in the MONTE CARLO section. It is code for a straight-forward Monte Carlo pricer that will price calls and puts, with uniform random variates selected by park-miller and converted into gaussian variates using one of the box-muller processes (for more information on these, refer to the post on Random Numbers).

I’ve used a factory pattern so in principle it should be very straight forward to add new options and also RNG processes to the code, although there are a few more improvements that I will be making in the near future, which will extend the code to basic path-dependent options and allow easier data input by the user. I’ll be going over various aspects of the code in detail in future posts, and also putting together some instructions on how to compile the code yourself using Dev C++ (a free, open-source compiler) and how to add options and processes via the factory.

As always, if you have any problems getting the code to work, please tell me!

Risk Neutral Valuation

There are a few different but equivalent ways of viewing derivatives pricing. The first to be developed was the partial differential equations method, which was how the Black Scholes equation was originally derived. There’s lots of discussion of this on the wikipedia page, and I’ll talk about it at some stage – it’s quite intuitive and a lot of the concepts fall out of it very naturally. However, probably the more powerful method, and the one that I use almost all of the time in work, is the risk-neutral pricing method.

The idea is quite simple, although the actual mechanics can be a little intricate. Since the distribution of the underlying asset at expiry is known, it makes sense that the price of a derivative might be the expected value of the payoff of the option at expiry (eg. (S_t-K)^+ for a call option, where a superscript ‘+’ means “The greater of this value or zero”) over the underlying distribution. In fact, it turns out that this isn’t quite right: due to the risk aversion of investors, this will usually produce an overestimate of the true price. However, in arbitrage-free markets, there exists another probability distribution under which the expectation does give the true price – this is called the risk-neutral distribution of the asset. Further, [as long as the market is complete] any price other than the risk-neutral price allows the possibility of arbitrage. Taken together, these are roughly a statement of the Fundamental Theorem of Asset Pricing. In the case of vanilla call options, a portfolio of the underlying stock and a risk-free bond can be constructed that exactly replicate the option and could be used in such an arbitrage.

In this risk-neutral distribution, all risky assets grow at the risk-free rate, so that the ‘price of risk’ is exactly zero. Let’s say a government bond – which we’ll treat as risk-free – exists, has a price B and pays an interest rate of r, so that

dB = r B dt

Then, the stochastic process for the underlying stock that we looked at before

dS = \mu dt + \sigma dW_t

is modified so that mu becomes r, and the process is

dS = rdt + \sigma dW_t

 so the risk-neutral distribution of the asset is still lognormal, but with mu’s replaced by r’s:

S_t = S_0 e^{(r - {1\over 2}\sigma^2)t + \sigma\sqrt{t}z}

 

I’ve not provided the explicit formula yet, so I’ll demonstrate here how this can be used to price vanilla call options

C(F,K,\sigma,t,\phi) = \delta(t){\mathbb E^{S_t}}[(S_t-K)^+]

= \delta(t)\int^\infty_{0} (S_t - K)^+ p_S(S_t)dS_t

= \delta(t)\int^\infty_{K} (S_t - K) p_S(S_t)dS_t

= {\delta(t) \over \sqrt{2\pi}}\int^\infty_{x_K} (S_0 e^{(r-{1\over 2}\sigma^2)t + \sigma \sqrt{t}x} - K) e^{-{1\over 2}x^2}dx

= {\delta(t) \over \sqrt{2\pi}}\Bigr[S_0 e^{(r-{1\over 2}\sigma^2)t} \int^\infty_{x_K} e^{\sigma \sqrt{t}x -{1\over 2}x^2}dx - \int^\infty_{x_K} K e^{-{1\over 2}x^2} dx \Bigl]

= {\delta(t) \over \sqrt{2\pi}}\Bigr[S_0 e^{(r-{1\over 2}\sigma^2)t} \int^\infty_{x_K} e^{-{1\over 2}(x-\sigma\sqrt{t})^2 + {1\over 2}\sigma^2t}dx - \sqrt{2\pi} K\Phi(-x_K)\Bigl]

= {\delta(t) \over \sqrt{2\pi}}\Bigr[S_0 e^{rt} \int^\infty_{x_K - \sigma \sqrt{t}} e^{-{1\over 2}x^2} dx - \sqrt{2\pi} K \Phi(-x_K)\Bigl]

= \delta(t)\Bigr[S_0 e^{rt} \Phi(-x_K + \sigma \sqrt{t}) - K \Phi(-x_K)\Bigl]

= \delta(t)\Bigr[F \Phi(d_1) - K \Phi(d_2)\Bigl]

which is the celebrated BS formula! In the above, F = forward price = \inline S_0 e^{rt}\inline \Phi(x) is the standard normal cumulative density of x, \inline x_K is the value of x corresponding to strike S=K, ie.

x_K = {\ln{K \over F} + {1\over 2}\sigma^2t \over \sigma \sqrt{t}}

it is typical to use the variables d1 and d2 for the values in the cfds, such that

d_1 = {\ln{F \over K} + {1\over 2}\sigma^2t \over \sigma \sqrt{t}}

d_2 = {\ln{F \over K} - {1\over 2}\sigma^2t \over \sigma \sqrt{t}} = d_1 - \sigma \sqrt{t}

In reality, certain we have made certain assumptions that aren’t justified in reality. Some of these are:

1. No arbitrage – we assume that there is no opportunity for a risk-free profit

2. No transaction costs – we can freely buy and sell the underlying at a single price

3. Can go long/short as we please – we have no funding constraints, and can buy/sell an arbitrarily large amount of stock/options and balance it with an opposite position in bonds

4. Constant vol and r – we assume that vol and r are constant and don’t vary with strike. In fact, it’s an easy extension to allow them to vary with time, I’ll come back to this later

I’ll look at the validity of these and other assumptions in a future post.

If prices of vanillas have non-constant vols that vary with strike, doesn’t that make all of the above useless? Not at all – but we do need to turn it on its head! Instead of using the r-n distribution to find prices, we use prices to find the r-n distribution! Lets assume that we have access to a liquid market of vanilla calls and puts that we can trade in freely. If we look at their prices and apply the Fundamental Theorem of Calculus twice

C(t)= \delta(t) \int^\infty_{K} (S_t - K)p_S(S_t)dS_t

{\partial C \over \partial K} = -\delta(t) \int^\infty_K p_S(S_t)dS_t

{1\over \delta(t)}{\partial^2 C \over \partial K^2} =p_S(K)

 So the curvature of call prices wrt. strike tells us the local risk neutral probability! This means for each expiry time that we can see vanillas option prices, we can calculate the market-implied r-n distribution (which probably won’t be lognormal, telling us that the market doesn’t really believe the BS assumptions as stated above either). Once we know this, we can use it calibrate our choice of market model and to price other, more exotic options.

[Post script: It is worth noting that although this looks like alchemy, we haven’t totally tamed the distribution, because although we know the underlying marginal distribution at each expiry time, we still don’t know anything about the correlations between them. That is, we know the marginal distributions of the underlying at each time, but not the full distribution. For concreteness, consider two times \inline t_1 and \inline t_2. We know \inline P(S_{t_1}) and \inline P(S_{t_2}) but not \inline P(S_{t_1},S_{t_2}). To price an option paying off the average of the spot at these two times, knowing the first two isn’t enough, we need to know the second, as the expectation is \inline \int^\infty_0 \int^\infty_0 {1\over 2}(S_{t_1} + S_{t_2})P(S_{t_1},S_{t_2}) dS_{t_1}dS_{t_2}. To see the difference, from Bayes Theorem we have that \inline P(S_{t_1},S_{t_2}) = \inline P(S_{t_1}).\inline P(S_{t_2}|S_{t_1}). So, although we know how the spot will be distributed at each time, we don’t know how each distribution is conditional on the times before, which we’d need to know to price exactly – our modelling challenge will be to choose some sensible process for this that is consistent with the marginal distributions.]

Price vs. Implied Vol

Something people often comment on when they start out in quantitative finance is that it’s odd that prices tend to be quoted in terms of implied vol instead of… well, price! This seems a bit strange, surely price is both more useful and more meaningful, given that implied vol is based on a model which isn’t really correct?

Briefly, when a vanilla option is priced in the Black-Scholes, its price is given by the following formula

 C(F,K,\sigma,\tau,\delta) = \delta(\tau) \phi \Bigl( F \Phi(\phi \cdot d_1) - K \Phi(\phi \cdot d_2) \Bigr)

d_1 = {\ln{F \over K} + {1 \over 2}\sigma^2 \tau \over \sigma \sqrt{\tau}}

d_2 = d_1 - \sigma \sqrt{\tau}

with \inline \tau the time to expiry, \inline \Phi(x) the standard normal cumulative density of x, \inline \delta(\tau) the discount factor to expiry, \inline \phi +1 for a put and -1 for a call, F the forward to expiry, K the strike, and\inline \sigma the Black-Scholes volatility (there are a few different ways of expressing this formula, I’ll come back to it another time).

Importantly, for both puts and calls there is a 1-to-1 correspondence between price and vol – in both cases, increased vol means increased price, since more vol means a higher chance of greater returns, while our losses are capped at zero. However, the BS price is derived by assuming that vol is a constant parameter (or at least that it only varies with time), but we know that in reality it also varies with strike (this is called the vol smile, and it is a VERY important phenomenon which I’ll talk about LOTS in these posts!). What vol should we put into the equation to get a sensible price?

Actually, we usually think about this in reverse – prices are quoted on the market, and we can invert the BS price to give us instead an implied vol. In fact, usually even the quotes that we receive will be given in terms of implied vol!

There are a few reasons for this. Firstly, a price varys depending on the notional of an option – in physics we’d call it an extrinsic variable, while imp vol is an intrinsic one. But it’s more that price doesn’t really give us as much information about where the option is as vol does. Have a look at the graphs below:

Two graphs of price variation with strike,for options with a flat BS vol (grey) and from a vol smile(red). On the left, their comparative prices are plotted with the forward price for reference. On the right, the corresponding BS implied vols are plotted. In all cases, the forward price is 100, time to expiry is 1 year, the flat vol is a constant 0.1 while the SABR parameters are instant vol = 0.1, vol of vol = 0.5 and rho = -0.2.

These graphs show the price variation with strike for two vol surfaces. Although they come from very different vol surfaces, we really can’t see that from the price graphs. Because the scale is so large, the relatively small price differences are overwhelmed. On one end they look like essentially forwards, while on the other end they are effectively zero.

But when we look at the implied vols instead, we see that they’re in fact very different options. One set has an (unrealistic) constant vol of 10%, while the other set shows higher vols away from the money (ie. at high and low strikes), which is what we typically see in the market. If we didn’t take these into account and priced them using the same vols, we’d be exposing ourselves to significant arbitrage opportunities (incidentally, this vol smile comes from a model commonly used to model and interpolate vol smiles called SABR – we’ll be seeing a lot more of this in the future).

Finally, implied vols give us a feeling for what is happening – since vol is annualised, this is the same order as the percentage change that we would expect in the underlying in a typical year. This gives us an important intuition check on our results that could easily be forgotten in the decimal points or trailing zeroes of a price given in dollars or euros.

As an aside, I’m in the process of upgrading the vanilla pricer to do implied vol calculations as well – so you will be able to either enter a vol and calculate the price of the option, or else enter a price and work out the corresponding vol. Have fun!

[This requires some root-finding (once again, no closed form for the normal cdfs…), and once again I’m taking the path of least resistance for the moment and coding a bisection solver. Since this involves many, many calls to the normal cdf code I used before, I should probably use a quicker method eventually, so I’ll be coding a brent solver soon, which will probably be a post in itself]

-QuantoDrifter