Option Pricing Functions

Differences to the American Options Function built in Mathematica 8

What sets the two functions in JavaTools apart from the American options function in Mathematica version 8 are:
- both functions AmericanOption[] and AmericanPut[] fully harness a thread-pool of ready-to-execute "worker" threads in Java when the computations are not required for just one value of time to expiration or strike, but for A WHOLE LIST of them. This makes optimal use of multi-core hardware while eliminating any thread creation and destruction overhead.
- the AmericanOption[] function uses a super-symmetric scheme with moment-matching.
- third-order grids using the Douglas scheme (fourth-order accuracy using second-order inputs) are used for AmericanOption[], instead of the binomial method used in Mathematica version 8.
- AmericanPut[] (see below) returns all computation results for ALL values of the underlying stock, not just for one! This is in stark contrast to traditional option pricing trees which return one option price for one spot price. AmericanPut[] is written to exploit the results for the entire interval with the SAME computational effort.

AmericanOption[]

The JavaTools function AmericanOption[] computes the true value (also referred to as TV, fair value, fair price, or option price), delta, gamma, and theta of an American option ("plain vanilla option") with discrete dividends. The method uses the trinomial Douglas scheme, which is among the best third-order finite difference schemes for 100% explicit methods as it provides for fourth-order accuracy using only second-order inputs. Delta, gamma, and theta are sometimes referred to as "standard Greeks", as they can be extracted directly from the grid structure of a properly constructed grid without requiring any recomputations. They are not "shape-defining Greeks", whereas vega and rho are. To compute vega and rho it is necessary to (re)submit the tree computation again with slightly modified inputs as vega and rho are shape-defining Greeks. This can be done with the well-known finite difference formulas for first derivatives, the simplest being

"americanoptions_1.gif"

also called the "secant rule".

The following computes the true value, delta, gamma, and theta of an American call option with a current price of $60, a strike price of $55, a time to expiration of one year, a volatility of 40%, an interest rate of 2%, a dividend yield (in general: asset yield) of 0%, and no discrete dividends, using 150 steps for the grid construction:

"americanoptions_2.gif"

"americanoptions_3.gif"

The following computes fair value, delta, gamma, and theta for the corresponding put using the same inputs

"americanoptions_4.gif"

"americanoptions_5.gif"

This function is very fast and precise, as the underlying grid structure is super-symmetric, moment-matching, and uses the explicit Douglas scheme.

On multi-core systems the performance can even be increased significantly because the function AmericanOption[] allows the user to specify a list of times to expirations, instead of just one value for the time to expiration, and then AmericanOption[] threads the computations over the cores. The following computes true value, delta, gamma, and theta for monthly expirations, ranging from 1/12 of year (one month) to 1 year in steps of 1/12 of a year (one month). We also use the JavaTools function JTable[] to provide for a nicer display of tabular data:

In[20]:=

"americanoptions_6.gif"

Out[20]=

"americanoptions_7.gif"

The time it takes to perform the above computations is very low on a multi-threaded system (47 milliseconds, using 6 cores, with 150 steps in the tree):

"americanoptions_8.gif"

"americanoptions_9.gif"

Oftentimes a practitioner does not need the option prices (and associated Greeks) computed for several times to expiration, but for several strikes in the same expiration. AmericanOption[] supports this as well. This example computes true value, delta, gamma, and theta for a fixed expiration of one year, but for strikes ranging from $50 to $60 in steps of $1:

In[21]:=

"americanoptions_10.gif"

Out[21]=

"americanoptions_11.gif"

Again, the computation time is very low on a multi-core system as AmericanOption[] threads all computations for the different strikes over the cores in several threads (6 cores, 150 steps in the tree):

"americanoptions_12.gif"

"americanoptions_13.gif"

And oftentimes the option prices (and associated Greeks) are needed for multiple values of the underlying instrument. AmericanOption[] supports this as well. The next example computes true value, delta, gamma, and theta for stock prices ranging from $50 to $60 in steps of $1:

In[24]:=

"americanoptions_14.gif"

Out[24]=

"americanoptions_15.gif"

Again, the computation time is very low on a multi-core system as AmericanOption[] threads all computations for the different stock prices over the cores in several threads (6 cores, 150 steps):

"americanoptions_16.gif"

"americanoptions_17.gif"

And oftentimes the option prices (and associated Greeks) are needed for multiple values of volatility. AmericanOption[] supports this as well. The next example computes true value, delta, gamma, and theta for volatilities ranging from 10% to 90% in steps of 5%:

In[25]:=

"americanoptions_18.gif"

Out[25]=

"americanoptions_19.gif"

Again, the computation time is very low on a multi-core system as AmericanOption[] threads all computations for the different volatilities over the cores in several threads (6 cores, 150 steps):

"americanoptions_20.gif"

"americanoptions_21.gif"

JavaTools also contains single-threaded versions of AmericanOption[] because the additional memory requirements of the executor class of Java's concurrency framework are not always needed. For example, when computing an implied volatility, it is necessary to compute ONE option price for given inputs, not a whole list of option prices. Of course, multiple option prices have to be computed in a root search, but each is computed using a different value for volatility, therefore only one option price would ever be used in a root search, making the use of the executor class a bad choice. For this reason, JavaTools contains the functions AmericanOptionST[], which are single-threaded ("ST" stands for "single-threaded").

The following example computes the implied volatility given an option price of $12.11 using Mathematica's FindRoot[] function with a starting "guess" value of 80%:

In[49]:=

"americanoptions_22.gif"

Out[49]=

"americanoptions_23.gif"

Notice that the method correctly computes the put value as intrinsic value plus dividend amount for puts that have an underlying price of roughly strike plus dividend, or less, when the dividend date ("ex-dividend date") is exactly on the expiration days. The convergence is from above. In this example, the lower limit of the interval is $45, and the option price is $14.0002, which is $55-$45=$10 for intrinsic value, plus the dividend of $4, plus time value for one day:

"americanoptions_24.gif"

"americanoptions_25.gif"

The same is not true for calls, as the value of the option instantly decreases by the dividend amount at the time the dividend "goes ex", at which time the call option holder could exercise the option, get the stock, and thus the dividend, which makes up for the loss in the call price of the same amount.

"americanoptions_26.gif"

"americanoptions_27.gif"

This also explains why "call delta minus put delta" is NOT 1 (but larger than 1) for dividend stocks, although this is practically only noticeable when the dividend goes ex at the time of expiration, and then only for underlying prices between strike and strike+dividend amount:

"americanoptions_28.gif"

"americanoptions_29.gif"

The reason for this is the higher put delta (the call delta is the same as for a non-dividend stock), because the entire put price function is basically "shifted to the right" by the dividend amount, and given hat a put has a positive gamma, this results in a higher delta due to the dividend amount.

AmericanPut[]

The function AmericanPut[] computes American put values (no Greeks) for ALL stock prices (up to a certain upper limit used in the internal interpolation). The method is also a third order grid method, like in AmericanOption[], but unlike AmericanOption[] the function AmericanPut[]
- does not handle dividends
- does not output any Greeks
- returns put prices for ALL stock prices from 0 to the upper limit of the internal interpolation.
- returns its results as InterpolatingFunction objects

Like AmericanOption[], the method AmericanPut[] can be used with lists instead of only atomic values in the inputs, exploiting multi-core hardware in an optimal manner by using Java's thread-pool from the concurrency framework. AmericanPut[] accepts lists for time to expiration, strike prices, and rates, to take full advantage of multi-threading. The method is a 100% explicit method on a trinomial scheme. It returns an InterpolatingFunction object that can then be used to read off the value for particular prices of the underlying, making it extremely easy and fact to create tables or plots with AmericanPut[]. Instead of a parameter for the number of steps AmericanPut[] requires two parameters, one for the "length" of the spatial interval, and one for the number of spatial subdivisions. The number of time steps is optimally computed internally to provide for a value of α (the ratio between spatial and temporal step sizes) that is as close as possible to 1/2, but not greater than 1/2, as α = 1/2 is the upper stability limit for all 100% explicit methods. Higher values for a and N increase the precision, but the computations take longer, as finer grids are constructed. In an optional last argument the interpolation order can be set, the default value of 3 is used if omitted.

In[26]:=

"americanoptions_30.gif"

Out[26]=

"americanoptions_31.gif"

This method is extremely fast, especially on multi-core hardware, DESPITE the fact that the put prices for ALL prices of the underlying are computed, EVEN when larger numbers for a and N are chosen. The following computes the InterpolatingFunction objects for ALL stock prices for 12 expirations using 13 for the space interval a and 1340 subdivisions in the spatial dimension in just half a second (6 cores):

"americanoptions_32.gif"

"americanoptions_33.gif"

For the 1-year expiration:

In[27]:=

"americanoptions_34.gif"

Out[28]=

"americanoptions_35.gif"

For all expirations:

"americanoptions_36.gif"

"americanoptions_37.gif"

With AmericanPut[] we can also compute the InterpolatingFunction objects for multiple strikes for one expiration, as we did with AmericanOption[];

In[30]:=

"americanoptions_38.gif"

Out[30]=

"americanoptions_39.gif"

For all strikes from $50 to $60, using 1 month to expiration, and stock prices from 45 to 70:

"americanoptions_40.gif"

"americanoptions_41.gif"

With AmericanPut[] we can also compute the InterpolatingFunction objects for multiple rates, as we did with AmericanOption[];

In[36]:=

"americanoptions_42.gif"

Out[36]=

"americanoptions_43.gif"

For all rates from 1% to 31% in steps of 2%, using 1 month to expiration, and stock prices from 45 to 70:

In[37]:=

"americanoptions_44.gif"

Out[37]=

"americanoptions_45.gif"

No function AmericanCall[] was implemented as a dividend-free American call has the same price (and hence, Greeks) as a dividend-free European call, and a European call is easy to compute.

Internally AmericanOption[] and AmericanPut[] use the concurrency framework of Java, using the executor class to dispatch the threads. That means a thread pool is used, in which, instead of launching a new thread when one is needed, and taking it down when it has finished, there is already a set of so-called "worker threads" ready and waiting to be dispatched with "work" to do. That means there is absolutely no delay at all for thread creation and thread destruction. The memory consumption for this is SLIGHTLY higher, as the worker threads have to be launched and kept running, but this is irrelevant compared to the massive speed gains afforded by the thread-pool of the executor class. If the functions are called with atomic parameters (no lists for time to expiration or strikes), the thread-pool/executor class is not used at all.

For more information and detailed descriptions of the mathematics involved in the AmericanPut[] method, see www.lauschkeconsulting.net:49050/webMathematica/LC/explicit.jsp, which includes an interactive "americanoptions_46.gif" demonstration that shows how smooth the method is when α is <= 1/2 and that it wreaks havoc if α is > 1/2. This method was also contributed to the book "Mathematica Cookbook" by Sal Mangano, published in the O'Reilly series in May 2010. However, the method implemented in JavaTools makes use of multi-threading through the thread-pool of the executor class in Java, and the number of time steps is computed optimally to use a value for α that is as close as possible (but never greater than) to 1/2, which is the optimal α, but also the stability limit of the method. The optimal value for the number of time steps is, based on a and the number of spatial steps N:

"americanoptions_47.gif"

Spikey Created with Wolfram Mathematica 7.0