Valuation of Financial Options

C F Baum  EC 313  Spring 2000

An option is the right, without the obligation, to take a specific action: for instance, to buy 100 shares of Apple for $75.00 per share within the next 12 months. This would be a call option, in that you have the right to buy at the specified price, prior to option expiration. Options are classified as either call options or put options: put options give you the right to sell at the specified price, prior to option expiration.Many common decisions that consumers and firms face may be considered (and valued) using options pricing theory (e.g. insurance); we will discuss "real options" in a later lecture. At this time let us consider financial options: those which are bought and sold on an organized exchange, for which price quotations exist. 

Since an option grants the buyer a right to act but no obligation to do so, it must sell for a nonnegative price; the option seller (or writer) is giving the buyer the right to act at her discretion. If the buyer acts--and is said to exercise the option--the seller will be financially disadvantaged. Options are a derivative asset--that is, they derive their value from underlying assets--and thus a zero-sum game. Whatever is gained by the one party is lost by the other. The distinction in terms of risk: the buyer pays a fixed sum for the option--the so-called option premium--and can never lose more than that sum. If the option is exercised, it must be "in the money", and whatever gain accrues to the buyer at exercise will be a corresponding loss to the seller. 

We define the exercise price, or strike price, as the price at which the underlying asset may be bought  (sold) in the event that exercise is in the buyer's interest. It is fixed at the time that the option is sold. Likewise, the option contract contains an explicit expiration time, after which the option is no longer valid. If the option can only be exercised at the time of expiration, it is said to be a "European option." If it may be exercised at any time, including at expiration, it is an "American option," and it must be worth at least as much as the equivalent European option.

The theory for valuation of European call options was developed by Fischer Black and Myron Scholes; they shared  the Nobel Prize in Economic Science with Robert Merton for this work. Their fundamental insight is that such an option can be valued in terms of five parameters: the current price of the underlying asset, the strike price of the option, the current volatility of the underlying asset, the risk-free interest rate, and the time to expiration. These parameters are observable except for the volatility, which must be inferred from historical data.

(* :Title: Option Valuation *)

(* :Author: Ross M. Miller *)

(* :Summary:
  Comprehensive set of option valuation analysis for Black-
  Scholes and binomial models.  Includes functions for
  sensitivity analysis (delta, theta, etc.) and for
  constructing and evaluating financial decision trees
  including binomial trees with early exercise 
*)

(* :Context: OptionValue` *)

(* :Package Version: 1.0 mod 0402 cfb for Mma v4 *)

(* :Copyright: Copyright 1990  Addison-Wesley Publishing Company. *)


(* Source:
  Ross M. Miller: "Option Valuation," in 
  Hal Varian, "Economic and Financial Modeling in  Mathematica" 
*)

$RecursionLimit=1024;

BeginPackage["OptionValue`"];

RiskFreeRate::usage = "RiskFreeRate contains the continuously
compounded risk-free rate of return.";

CallPayoff::usage = "CallPayoff[price,strike] gives the
intrinsic value of a call option at a given price for its
underlying stock.";

PutPayoff::usage = "CallPayoff[price,strike] gives the
intrinsic value of a put option at a given price for its
underlying stock.";

AuxBS::usage = "AuxBS[p,k,sd,r,t] is an auxiliary function,
which happens to equal delta, used in the Black-Scholes
model.";

Norm::usage = "Norm[x] gives the cumulative normal distribution
function evaluated at a real-valued x";

BlackScholes::usage = "BlackScholes[p,k,sd,r,t] gives the
Black-Scholes value of a call option.";

Delta::usage = "Delta[p,k,sd,r,t] gives the
Black-Scholes delta of a call option, its sensitivity to
changes in the price of the underlying stock.";

Theta::usage = "Theta[p,k,sd,r,t] gives the
theta of a call option, the sensitivity of its value to changes
in the time until expiration.";

Rho::usage = "Rho[p,k,sd,r,t] gives the rho of a
call option, the sensitivity of its value to changes in the
risk-free rate of return.  Rho returns a numerical value
when all of its arguments are numbers.";

Kappa::usage = "Kappa[p,k,sd,r,t] gives the kappa
of a call option, the sensivity of its value to changes in
its volatility (sd).  (Kappa is also referred to as lambda
or vega.).";

OptionGamma::usage = "OptionGamma[p,k,sd,r,t] gives the
gamma of a call option, the sensitivity of its delta to changes
in the stock price.";

OptionElasticity::usage = "OptionElasticity[p,k,sd,r,t] gives
the elasticity of a call option with respect to its stock
price.";

ImpliedVolatility::usage = "ImpliedVolatility[p,k,r,t,optionprice]
gives the volatility of a call option that is implied by its
price.";

ConsObj::usage = "ConsObj[obj,proplist] is a LISP-like object
constructor that attaches the properties in proplist to the object
symbol obj.  As in LISP, proplist alternatively gives the property
name and then its value.";

(* cfb add defns *)
Type::usage = "Type[option] is set to either call or put.";

Flavor::usage = "Flavor[option] is set to either euro or amer.";

AssetPrice::usage = "AssetPrice[option] gives the price of the
asset that underlies option.";

ExercisePrice::usage = "ExercisePrice[option] gives the strike price of the
option.";

AssetVolatility::usage = "AssetVolatility[option] gives the
volatility of the asset that underlies option.";

ExpirationTime::usage = "ExpirationTime[option] gives the time
to expiration of the option, in years.";

Asset::usage = "Asset[option] gives the asset identifier for the option.";
Price::usage = "Price[asset] gives the price of the underlying asset.";
Volatility::usage = "Volatility[asset] gives the volatility of the underlying asset.";

ExerciseFunction::usage = "ExerciseFunction[option] gives the
exercise function for an option based on its Type property";

MakeAmerTree::usage = "MakeAmerTree[option,n] gives the binomial
financial decision tree for option dividing the time to expiration
into n periods.  MakeAmerTree[option] assumes a default
value of four periods.";

Successors::usage = "Successors[node[symbol,price,left,weight]]
gives a list of successor nodes to a node in an American binomial
option tree.";

TreeValue::usage = "TreeValue[node[symbol,price,left,weight]]
gives the value of the financial decision tree with node as its
root.";

Prob::usage = "Prob[node] gives the probability that a node will
be reached from its parent.";

Expectation::usage = "Expectation[nodelist] gives the mathematical
expectation of the values of the nodes in nodelist.";

Value::usage = "Value[option] gives the value of an option using
the options properties to determine the best valuation method.";


Begin["`Private`"];

RiskFreeRate = 0.04;

CallPayoff[price_,strike_] := Max[0,price-strike]

PutPayoff[price_,strike_] := Max[0,strike-price]

AuxBS[p_,k_,sd_,r_,t_] := (Log[p/k]+r t)/
                        (sd Sqrt[t])+
                         .5 sd Sqrt[t]

BlackScholes[p_,k_,sd_,r_,t_] :=
        p  Norm[AuxBS[p,k,sd,r,t]]- 
        k Exp[-r t] (Norm[AuxBS[p,k,sd,r,t]-sd Sqrt[t]])

Norm[z_?NumberQ]:= N[0.5 + 0.5 Erf[z/Sqrt[2]]]

Norm'[z_] := N[(1/Sqrt[2 Pi])] Exp[-z^2/2]

(* per dab these derivs should be just =, not Delayed   --cfb *)
Delta[p_,k_,sd_,r_,t_] = D[BlackScholes[p,k,sd,r,t],p];

Theta[p_,k_,sd_,r_,t_] = -D[BlackScholes[p,k,sd,r,t],t];

Kappa[p_,k_,sd_,r_,t_] = D[BlackScholes[p,k,sd,r,t],sd];

Rho[p_,k_,sd_,r_,t_] = D[BlackScholes[p,k,sd,r,t],r];

OptionGamma[p_,k_,sd_,r_,t_] = D[Delta[p,k,sd,r,t],p];

OptionElasticity[p_,k_,sd_,r_,t_] :=
                     p Delta[p,k,sd,r,t] / BlackScholes[p,k,sd,r,t]

ImpliedVolatility[p_,k_,r_,t_,optionprice_] :=
            sd /. FindRoot[BlackScholes[p,k,sd,r,t]==
                           optionprice,{sd,0.2}]

ConsObj[obj_,proplist_] := 
        Do[Block[{propname=proplist[[2*i-1]],
                  propval=proplist[[2*i]]},
                  propname[obj]^=propval],
           {i,Length[proplist]/2}]

AssetPrice[option_] := (AssetPrice[option] ^=
                        Price[Asset[option]])
                        
AssetVolatility[option_] := (AssetVolatility[option] ^=
                            Volatility[Asset[option]])
                            
ExerciseFunction[option_] := CallPayoff /;
                             Type[option]=="call"

ExerciseFunction[option_] := PutPayoff /;
                             Type[option]=="put"

MakeAmerTree[option_,n_:4] := 
            Block[{ChanceSymbol = Unique["cnode"],
            DecisionSymbol = Unique["dnode"],
            s = AssetPrice[option],
            k = ExercisePrice[option],
	        ex = ExerciseFunction[option],
	        t = ExpirationTime[option],
            sd= AssetVolatility[option] Sqrt[t/n] // N,
            a = Exp[RiskFreeRate t/n] // N,
            u = Exp[sd],
            d = 1/u},
            ConsObj[Evaluate[ChanceSymbol],
                 {Type,"chance",
                  Dfactor,1/a,
                  Upamt,u,
                  Downamt,d,
                  Upprob,(a-d)/(u-d) // N,
                  ExercisePrice,k,
                  ExerciseFunction,ex,
                  Succsym,DecisionSymbol}];
            ConsObj[Evaluate[DecisionSymbol],
                  {Type,"decision",
                   ExercisePrice,k,
                   ExerciseFunction,ex,
                   Succsym,ChanceSymbol}];
            node[ChanceSymbol,s,n,1]]

Successors[node[symbol_,price_,left_,weight_]] := 
{node[Succsym[symbol],
      Upamt[symbol]*price,left-1,
      Upprob[symbol]],
 node[Succsym[symbol],
      Downamt[symbol]*price,left-1,
      1-Upprob[symbol]]}  /;   Type[symbol]=="chance" ;
      
Successors[node[symbol_,price_,left_,weight_]] := 
{node[Succsym[symbol],
      price,
      left,
      1],
 node[Succsym[symbol],
      price,
      0,
      1]}                 /; Type[symbol]=="decision"

TreeValue[node[symbol_,price_,left_,weight_]] :=
(TreeValue[node[symbol,price,left,weight]]
  = Which[left==0,
      ExerciseFunction[symbol] [price,ExercisePrice[symbol]],
    Type[symbol]=="chance",
      Dfactor[symbol] *
       Expectation[Successors[node[symbol,price,left,weight]]],
    Type[symbol]=="decision",
      Max[TreeValue[Successors[node[symbol,price,left,weight]]]]]);

SetAttributes[TreeValue,Listable]
 
Prob[node_] := node[[4]] ; SetAttributes[Prob,Listable]  

Expectation[nodelist_] := Dot[Prob[nodelist], 
                              TreeValue[nodelist]] 
                               
Value[option_] := BlackScholes[AssetPrice[option],
                               ExercisePrice[option],
                               AssetVolatility[option],
                               RiskFreeRate,
                               ExpirationTime[option]] /;
                           (Type[option]=="call" && Flavor[option]=="euro")
                           
                            
Value[option_] := TreeValue[MakeAmerTree[option,20]] /;
                           (Type[option]=="call" && Flavor[option]=="amer")                                                   


(* euro put via put-call parity  /cfb 0402 *)

Value[option_] :=BlackScholes[AssetPrice[option],
                               ExercisePrice[option],
                               AssetVolatility[option],
                               RiskFreeRate,
                               ExpirationTime[option]] - AssetPrice[option]+
ExercisePrice[option] (1+RiskFreeRate)^ ExpirationTime[option] /;
                               (Type[option]=="put" && Flavor[option]=="euro")
                           
Value[option_] := TreeValue[MakeAmerTree[option,20]] /;
                           (Type[option]=="put" && Flavor[option]=="amer")

End[]

EndPackage[]

Black-Scholes Option Valuation

?BlackScholes

This function,in which the five parameters are provided, gives the Black-Scholes estimate of call option value. The Black-Scholes formula can be viewed by examining the function:

BlackScholes[p, k, sd, r, t]

In this formula, the Norm[] function is the cumulative distribution function of the standard Normal distribution.It arises from the assumption that price changes are normally distributed, so that during the time prior to option expiration, the price may rise (by 1, 2, or 3 σ, for example) or it may fall. But the payoff to the buyer is asymmetric--no matter how far the price falls, the option is still worth $0.00. But depending on how far the price rises, the option may be worth a great deal.

The value of an option at every point in time is the sum of two components: intrinsic value and time value. The intrinsic value, or "moneyness" of the option, is the amount by which the option is currently "in the money", with a minimum of $0.00. An "out-of-the-money" option has zero intrinsic value, but will still have time value--measuring the probability that even though it is worthless today, there is some chance it will become valuable prior to expiration. Since the time value is dependent on how much time remains, all options are "wasting assets"--their time value strictly decreases as time passes and expiration nears. At the moment of expiration, the option is worth exactly its intrinsic value (which could be zero).

cval[p_, k_] := 0
cval[p_, k_] := p - k  /; p ≥ k

pl1 = 
      Plot[cval[i, 20], {i, 0, 40}, AspectRatio -> 0.5, 
        PlotLabel -> "Value of Call Option with k=$20", 
        AxesLabel -> {"Price", ""}]

Illustration of the wasting asset with an at-the-money call option:

TableForm[
      Table[{i, BlackScholes[20, 20, 0.10, RiskFreeRate, i]}, {i, 1, 
          0.1, -0.1}]]

The derivatives of the Black-Scholes function, given Greek names, indicate how sensitive the option price will be to changes in any of the underlying parameters. The most important, δ, is the derivative of the option value with respect to a change in the price of the underlying asset.
It is used to determine an optimal hedging position, where options are combined with a position in the underlying asset to reduce the risk of the composite portfolio. δ may be calculated by differentiating the Black-Scholes formula with respect to p.You might think it is the slope of the option value line above (which is either 0 for out-of-the-money options or 1 for in-the-money options), but that ignores the time value. The option value, given time value, is a smooth curve that lies above the kinked curve displaying intrinsic value.

bslist = 
        Table[{i, BlackScholes[i, 20, 0.5, RiskFreeRate, 1]}, {i, 1, 40, 
            0.5}];
pl2 = 
        ListPlot[bslist, AspectRatio -> 0.5, 
          DisplayFunction -> Identity];
Show[pl1, pl2]

Delta is the slope of the curve given by the dotted line; it will be close to zero for deep out-of-the-money options and close to 1.0 for deep in-the-money options.

Plot[Delta[i, 20, 0.5, RiskFreeRate, 1], {i, 1, 40}, 
      PlotLabel -> "δ of Call Option with k=$20", 
      AxesLabel -> {"Price", ""}]

The other "Greeks" measure the sensitivity of option value to the other parameters in the Black-Scholes formula. Theta measures the sensitivity to the time to expiration (the rate at which the option value "wastes away"):

Plot[Theta[20, 20, 0.5, RiskFreeRate, i/100], {i, 1, 100}, 
      PlotLabel -> "θ of at-the-money Call Option", 
      AxesLabel -> {"Percent of Year", ""}]

Kappa measures the sensitivity of the option's value to changes in the underlying standard deviation of asset returns. Options are more valuable--whether calls or puts--when the underlying asset price is more volatile.

Plot[Kappa[20, 20, i/100, RiskFreeRate, 1], {i, 1, 100}, 
      PlotLabel -> "κ of at-the-money Call Option", 
      AxesLabel -> {"Percent ", ""}]

Rho measures the sensitivity of the option's value to changes in the risk free rate.A call option is an alternative to a "buy-and-hold" strategy, in which you buy the good today and finance carrying it; thus a higher risk free rate increases the value of an alternative strategy, such as buying a call option on the good.

Plot[Rho[20, 20, 0.5, i/100, 1], {i, 3, 7}, 
      PlotLabel -> "ρ of at-the-money Call Option", 
      AxesLabel -> {"Percent ", ""}]

One other "Greek" is often discussed: the second derivative of option value with respect to the underlying asset price, or the derivative of δ with respect to price, often called γ (or, by the classically illiterate, "vega").γ measures how rapidly the hedge ratio will change(curvature of the δ function, equivalent to convexity of a bond valuation formula).

Plot[OptionGamma[i, 20, 0.5, RiskFreeRate, 1], {i, 1, 40}, 
      PlotLabel -> "γ of Call Option with k=$20", 
      AxesLabel -> {"Price", ""}]

Put-Call Parity

All these calculations are done from the Black-Scholes formula for European call option value. How can we evaluate a put? For a European put, we can make use of the Put-Call Parity Theorem, which states that a put and call on the same underlying asset with identical strike prices and time to expiration must obey the relation

Call - Put = P - K/(1+r)^T, 

where Put is the put premium, Call is the call premium, K is the strike price, P is the price of the underlying asset, r is the risk free rate and T is the time to expiration. This can be rewritten as 

Put = Call - P+K/(1+r)^T

or the put premium must equal the call premium minus the price of the underlying asset plus the present value of the strike price.This may be read as "selling a put is equivalent to selling (+) a call, buying (-) the underlying asset and borrowing (+) the present value of the strike price." In the market for traded options, the premia for puts and calls must approximately obey Put-Call Parity, or arbitrage opportunities would arise.

The Put-Call Parity theorem has been added to this package for the evaluation of European put prices. First, let's price an out-of-the-money European call:

AssetPrice[opt] = 20;
ExercisePrice[opt] = 30;
AssetVolatility[opt] = 0.5;
ExpirationTime[opt] = 1;
Type[opt] = "call";
Flavor[opt] = "euro";

callval = Value[opt]

Now, let's price the corresponding put:

Type[opt] = "put";
putval = Value[opt]

Binomial Lattice Option Valuation

There are no closed form solutions (such as Black-Scholes) for American options, nor for other "exotic" options. However, a common valuation technique makes use of trees to generate a binomial lattice.The binomial lattice model assumes that the stock price will move from its current values to one of two outcomes: (1+u)P or (1+d)P, where u>0 and d<0 are the percentage changes that are likely. There is no explicit specification of the probabilities of these two events, which need not be equal. Imagine that K=P and T=1; then at expiration, this at-the-money option will be worth either 0 (in the "down" state: the option expires worthless, since you can buy the stock for less than K) or (1+u)P(t)-K (in the "up" state: the option gives you the right to pay K for something worth more than that). It can be shown that the call option is equivalent to a particular levered portfolio in the underlying asset: C =  δ P + B, where  δ  is the option's  δ , P is the stock price, and B (<0) is the amount to borrow to fund the stock purchase. By working with the payoff from buying this levered stock portfolio, we can derive that

C = ( g C(u) + (1-g) C(d) ) / (1+r),   g = (r-d)/(u-d)

where C(u) and C(d) are the call option values at expiration in the up and down states, and r is the risk free rate. The p here must be the probability of an uptick in a risk-neutral economy. This allows us to evaluate two outcomes next period and determine the price that the option should sell for this period.

Show[
      Graphics[{Point[{0.3, 0.3}], Point[{1.5, 1.7}], 
          Text["C(t)", {0.5, 1}], Text["C(u)", {1, 1.5}], 
          Text["C(d)", {1, 0.5}], Line[{{0.6, 1}, {0.9, 1.4}}], 
          Line[{{0.6, 1}, {0.9, 0.6}}]}]]

For instance, for an at-the-money call, if u=0.20, d=-0.10, r= 0.10, P = $20.00:

r = 0.10;  u = 0.20;  d = -0.10;  
    P = 20;
Pd = P (1 + d)
Cd = 0
Pu = P (1 + u)
Cu = Pu - P
g = (r - d)/(u - d)

Ct = (g Cu  +  (1 - g) Cd)/(1 + r)

The call will be worth either $4.00 or zero at expiration; its price today should be $2.42.

Show[
      Graphics[{Point[{0.3, 0.3}], Point[{1.5, 1.7}], Text[Ct, {0.5, 1}], 
          Text[Cu, {1, 1.5}], Text[Cd, {1, 0.5}], 
          Line[{{0.6, 1}, {0.9, 1.4}}], 
          Line[{{0.6, 1}, {0.9, 0.6}}]}]]

This logic may be extended to a multi-period framework by subdividing the time interval into equal increments, while preserving the price evolution process:

Show[
      Graphics[{Point[{0.3, 0.5}], Point[{3, 3.5}], 
          Text["C(t)", { .5, 2}], Text["C(u,t+1)", {1.5, 2.5}], 
          Text["C(d,t+1)", {1.5, 1.5}], Line[{{0.6, 2}, {1.2, 2.4}}], 
          Line[{{0.6, 2}, {1.2, 1.6}}], Text["C(u,u,t+2)", {2.5, 3}], 
          Text["C(d,d,t+2)", {2.5, 1}], Line[{{1.7, 2.7}, {2.2, 3}}], 
          Line[{{1.7, 2.4}, {2.2, 2}}], Line[{{1.7, 1.4}, {2.2, 1}}], 
          Line[{{1.7, 1.6}, {2.2, 2}}], 
          Text["C(u,d,t+2)", {2.5, 2}]}]]

This "recombining tree" (said to be so since the path (u,d) is the same as the path (d,u)) gives the option value at time t in terms of the two outcomes at time (t+1), which are in turn functions of the three outcomes at time (t+2). For instance, the stock price which increased from $20.00 to $24.00 may now increase to $28.80 or fall to $21.60; likewise if it intially declined to $18.00 it may fall further to $16.20 or rise to $21.60. In this case the $20.00 call will be worth either $8.80, $1.60, or zero in the last period. Applying the same logic to calculate option value at the intermediate nodes, the option will be worth either $5.82 or $0.97 in period 1, and an option with those characteristics will be worth $3.82 today. 
This logic may be extended to evaluate realistic problems in which the number of time steps is greatly increased. It is a natural application of recursive tree structures in terms of programming. This optvalue package has such a tree structure built in for the evaluation of American calls or American puts. For instance:

AssetPrice[opt] = 30;
ExercisePrice[opt] = 30;
AssetVolatility[opt] = 0.2;
ExpirationTime[opt] = 1;
Type[opt] = "call";
Flavor[opt] = "amer";
Value[opt]

AssetPrice[opt] = 30;
ExercisePrice[opt] = 30;
AssetVolatility[opt] = 0.2;
ExpirationTime[opt] = 1;
Type[opt] = "put";
Flavor[opt] = "amer";
Value[opt]

You can examine the structure of the program to see how the author generated the tree structure and "walks" the tree to recursively evaluate the value of the option at each node of the tree. These calculations are done with the depth of the tree set to 8.

Following is experimental code.

Type[decfl]  ^=  "call"
Asset[decfl]  ^=  "dec"
ExercisePrice[decfl] ^= 60
ExpirationTime[decfl] ^= 0.3
Flavor[
        decfl]^="euro"

?decfl

Type[dec] ^= "stock"
Price[dec] ^= 58.5
Volatility[dec] ^= 0.29

?dec

Value[decfl]

Asset[decfl]

Price[Asset[decfl]]

Price[dec]