Chapter 2. Two State Economy

As an empirical domain, finance is aimed at specific answers, such as an appropriate value for a given security, or an optimal number of its shares to hold.

Darrell Duffie (1988)

The notion of arbitrage is crucial to the modern theory of Finance.

Delbaen and Schachermeyer (2006)

The analysis in this chapter is based on the most simple model economy that is still rich enough to introduce many important notions and concepts of finance: an economy with two relevant points in time and two uncertain future states only. It also allows to present some important results in the field, like the Fundamental Theorems of Asset Pricing that are discussed in this chapter.1

The simple model chosen is a means to simplify the formal introduction of the sometimes rather abstract mathematical concepts and financial ideas by avoiding as many technicalities as possible. Once these ideas are fleshed out and well understood, the transfer to more realistic financial models usually proves seamless.

This chapter covers mainly the following central topics from finance, mathematics, and Python programming.

Finance Mathematics Python

time

natural numbers

int, type

money (currency)

real numbers

float

cash flow

tuple

tuple, list

return, interest

real numbers

abs

(net) present value

function

def, return

uncertainty

vector 2

NumPy, ndarray, np.array

financial asset

process

ndarray, tuple

risk

probability, state space, power set, mapping

ndarray

expectation, expected return

dot product

np.dot

volatility

variance, standard deviation

np.sqrt

contingent claims

random variable

np.arange, np.maximum, plt.plot

replication, arbitrage

linear equations, matrix form

ndarray(2d), np.linalg.solve, np.dot

completeness, Arrow-Debreu securities

linear independence, span

np.linalg.solve

martingale pricing

martingale, martingale measure

np.dot

mean-variance

expectation, variance, standard deviation

np.linspace, .std(), [x for y in z]

Economy

The first element of the financial model is the idea of an economy. An economy is an abstract notion which subsumes other elements of the financial model, like assets (real, financial), agents (people, institutions) or currency. Like in the real world, an economy cannot be seen or touched. Nor can it be formally modeled directly — it rather simplifies communication to have such a summary term available. The single model elements together form the economy.

Real Assets

Multiple real assets are available in the economy that can be used for different purposes. A real asset might be a chicken egg or a complex machine to produce other real assets. At this point it is not yet relevant who, for example, produces the real assets or who owns them.

Agents

Agents can be thought of as individual human beings being active in the economy. They might be involved in producing real assets, consuming them or trading them. They accept money during transactions and spend it during others. An agent might also be an institution like a bank that allows other agents to deposit money on which it then pays interest.

Time

Economic activity, like trading real assets, takes place at discrete points in time only. Formally, it holds for a point in time t0,1,2,3,... or t0. In the following, only the two points in time t=0 and t=1 are relevant. They should be best interpreted as today and one year from today, although it is not necessarily the only interpretation of the relevant time interval. In many contexts, one can also think of today and tomorrow. In any case, financial theory speaks of a static economy if only two points in time are relevant.

The Python data type to model the natural numbers is int which stands for integers.2 Typical arithmetic operations are possible on integers like addition, subtraction, multiplication and more.

In [1]: 1 + 3  1
Out[1]: 4

In [2]: 3 * 4  2
Out[2]: 12

In [3]: t = 0  3

In [4]: t  4
Out[4]: 0

In [5]: t = 1  5

In [6]: type(t)  6
Out[6]: int
1

Adds up two integer values.

2

Multiplies two integer values.

3

Assigns a value of 0 to the variable name t.

4

Prints out the value of variable t.

5

Assigns a new value of 1 to t.

6

Looks up and prints the Python type of t.

Money

In the economy, there is money (or currency) in unlimited supply available. Money is also infinitely divisible. Money and currency should be thought of in abstract terms only and not in terms of cash (physical coins or bills).

Money in general serves as the numeraire in the economy in that the value of one unit of money (think USD, EUR, GBP, etc.) is normalized to exactly 1. The prices for all other goods are then expressed in such units and are fractions or multiples of such units. Formally, units of the currency are represented as (positive) real numbers c0.

In Python, float is the standard data type used to represent real numbers . It stands for floating point numbers. Like the int type, it allows, among others, for typical arithmetic operations, like addition and subtraction.

In [7]: 1 + 0.5   1
Out[7]: 1.5

In [8]: 10.5 - 2  2
Out[8]: 8.5

In [9]: c = 2 + 0.75  3

In [10]: c  4
Out[10]: 2.75

In [11]: type(c)  5
Out[11]: float
1

Adding two numbers.

2

Subtracting two numbers.

3

Assigning the result of the addition to the variable name c.

4

Printing the value of the variable c.

5

Looking up and printing out the Python type of the variable c.

Beyond serving as a numeraire, money also allows to buy and sell real assets or to store value over time. These two functions rest on the trust that money has indeed intrinsic value today and also in one year. In general, this translates into trust in people and institutions being willing to accept money both today and later for any kind of transaction. The numeraire function is independent of this trust since it is a numerical operation only.

Cash Flow

Combining time with currency leads to the notion of cash flow. Consider an investment project which requires an investment of, say, 9.5 currency units today and pays back 11.75 currency units after one year. An investment is generally considered to be a cash outflow and one often represents this as a negative real number, c- or more specifically c=-9.5. The payback is a cash inflow and therewith a positive real number, c0 or c=+11.75 in the example.

To indicate the points in time when cash flows happen, a time index is used. In the example, ct=0=-9.5 and ct=1=11.75 or for short c0=-9.5 and c1=11.75.

A pair of cash flows now and one year from now is modeled mathematically as an ordered pair or two-tuple which combines the two relevant cash flows to one object c2 with c=(c0,c1) and c0,c1.

In Python, there are multiple data structures available to model such a mathematical object. The two most basic ones are tuple and list. Objects of type tuple are immutable, i.e. they cannot be changed after instantiation, while those of type list are mutable and can be changed after instantiation. First, an illustration of tuple objects (characterized by parentheses or round brackets).

In [12]: c0 = -9.5  1

In [13]: c1 = 11.75  2

In [14]: c = (c0, c1)  3

In [15]: c  4
Out[15]: (-9.5, 11.75)

In [16]: type(c)  5
Out[16]: tuple

In [17]: c[0]  6
Out[17]: -9.5

In [18]: c[1]  7
Out[18]: 11.75
1

Defines the cash outflow today.

2

Defines the cash inflow one year later.

3

Defines the tuple object c (note the use of parentheses).

4

Prints out the cash flow pair (note the parentheses).

5

Looks up and shows the type of object c.

6

Accesses the first element of object c.

7

Accesses the second element of object c.

Second, an illustration of the list object (characterized by square brackets).

In [19]: c = [c0, c1]  1

In [20]: c  2
Out[20]: [-9.5, 11.75]

In [21]: type(c)  3
Out[21]: list

In [22]: c[0]  4
Out[22]: -9.5

In [23]: c[1]  5
Out[23]: 11.75

In [24]: c[0] = 10  6

In [25]: c  7
Out[25]: [10, 11.75]
1

Defines the list object c (note the use of square brackets).

2

Prints out the cash flow pair (note the square brackets).

3

Looks up and shows the type of object c.

4

Accesses the first element of object c.

5

Accesses the second element of object c.

6

Overwrites the value at the first index position in the object c.

7

Shows the resulting changes.

Return

Consider an investment project with cash flows c=(c0,c1)=(-10,12). The return R of the project is the sum of the cash flows R=c0+c1=-10+12=2. The rate of return r is the return R divided by |c0|, that is by the absolute value of the investment outlay today:

r=R|c0|=-10+1210=210=0.2

In Python, this boils down to simple arithmetic operations.

In [26]: c = (-10, 12)  1

In [27]: R = sum(c)  2

In [28]: R  3
Out[28]: 2

In [29]: r = R / abs(c[0])  4

In [30]: r  5
Out[30]: 0.2
1

Defines the cash flow pair as tuple object.

2

Calculates the return R by taking the sum of all elements of c and …

3

… prints out the result.

4

Calculates the rate of return r with abs(x) giving the absolute value of x and …

5

… prints out the result.

Interest

There is a difference between a cash flow today and a cash flow in one year. The difference results from interest that is being earned on currency units or that has to be paid to borrow currency units. Interest in this context is the price being paid for having control over money that belongs to another agent.

An agent that has currency units that they do not need today can deposit these with a bank or lend them to another agent to earn interest. If the agent needs more currency units than they have currently available, they can borrow them from a bank or other agents and needs to pay interest.

Suppose an agent deposits c0=-10 currency units today with a bank. According to the deposit contract, they receive c1=11 currency units after one year from the bank. The interest I being paid on the deposit is I=c0+c1=-10+11=1. The interest rate i accordingly is i=I|c0|=0.1.

In the following, it is assumed that the relevant interest rate for both lending and borrowing is the same and that it is fixed for the entire economy.

Present Value

Having lending or depositing options available leads to opportunity costs for deploying money in an investment project. A cash flow of, say, c1=12.1 in one year cannot be compared directly in terms of value with a cash flow of c0=12.1 today since interest can be earned on currency units not deployed in a project.

To appropriately compare cash flows in one year with those of today, the present value needs to be calculated. This is accomplished by discounting using the fixed interest rate in the economy. Discounting can be modeled as a function D:,c1D(c1) which maps a real number (cash flow in one year) to another real number (cash flow today). It holds

c0=D(c1)=c11+i=12.11+0.1=11

for an interest rate of i=0.1. This relationship results from the alternative “investment” in deposits with a bank

c1=(1+i)·c0c0=c11+i

Python functions are well suited to represent mathematical functions like the one for discounting.

In [31]: i = 0.1  1

In [32]: def D(c1):  2
             return c1 / (1 + i)  3

In [33]: D(12.1)  4
Out[33]: 10.999999999999998

In [34]: D(11)  5
Out[34]: 10.0
1

Fixes the interest rate i.

2

Function definition with def statement; D is the function name; c1 the parameter name.

3

Returns the present value with the return statement.

4

Calculates the present value of 12.1; note the rounding error due to internal float point number representation issues.

5

Calculates the present value of 11 (“exactly” in this case).

Net Present Value

How shall an agent decide whether to conduct an investment project or not? One criterion is the net present value. The net present value NPV is the sum of the cash outflow today and the present value of the cash inflow in one year, NPV(c)=c0+D(c1). Here, the net present value calculation is a function NPV:2 mapping cash flow tuple to a real number. If the net present value is positive, the project should be conducted; if it is negative, then not --since the alternative of just depositing the money with a bank is more attractive.

Consider an investment project with cash flows cA=(-10.5,12.1). The net present value is NPV(cA)=-10.5+D(12.1)=-10.5+11=0.5. The project should be conducted. Consider an alternative investment project with cB=(-10.5,11). This one has a negative net present value and should not be conducted: NPV(cB)=-10.5+D(11)=-10.5+10=-0.5.

Building on previous definitions, a respective Python function is easily defined.

In [35]: def NPV(c):
             return c[0] + D(c[1])

In [36]: cA = (-10.5, 12.1)  1

In [37]: cB = (-10.5, 11)  2

In [38]: NPV(cA)  1
Out[38]: 0.4999999999999982

In [39]: NPV(cB)  2
Out[39]: -0.5
1

Positive net present value project.

2

Negative net present value project.

Uncertainty

Cash inflows from an investment project one year from now are in general uncertain. They might be influenced by a number of factors in reality (competitive forces, new technologies, growth of the economy, weather, problems during project implementation, etc.). In the model economy, the concept of states of the economy in one year subsumes the influence of all relevant factors.

Assume that in one year the economy might be in one of two different states u and d which might be interpreted as up (“good”) and down (“bad”). The cash flow of a project in one year c1 then becomes a vector c12 with two different values c1u,c1d representing the relevant cash flows per state of the economy. Formally, this is represented as a so-called column vector

c1=c1uc1d

Mathematically, there are multiple operations defined on such vectors, like scalar multiplication and addition, for instance.

α·c1+β=α·c1uc1d+β=α·c1u+βα·c1d+β

Another important operation on vectors are linear combinations of vectors. Consider two different vectors c1,d12. A linear combination is then given by

α·c1+β·d1=α·c1u+β·d1uα·c1d+β·d1d

Here and before, it is assumed that α,β.

The most common way of modeling vectors (and matrices) in Python, is via the NumPy package which is an external package and needs to be installed separately. For the code below, consider an investment project with c0=10 and c1=(20,5)T where the superscript T stands for the transpose of the vector (transforming a row or horizontal vector into a column or vertical vector). The major class used to model vectors is the ndarray class which stands for n-dimensional array.

In [40]: import numpy as np  1

In [41]: c0 = -10  2

In [42]: c1 = np.array((20, 5))  3

In [43]: type(c1)  4
Out[43]: numpy.ndarray

In [44]: c1  5
Out[44]: array([20,  5])

In [45]: c = (c0, c1)  6

In [46]: c  7
Out[46]: (-10, array([20,  5]))

In [47]: 1.5 * c1 + 2  8
Out[47]: array([32. ,  9.5])

In [48]: c1 + 1.5 * np.array((10, 4))  9
Out[48]: array([35., 11.])
1

Imports the numpy package as np.

2

The cash outflow today.

3

The uncertain cash inflow in one year; one-dimensional ndarray objects do not distinguish between row (horizontal) and column (vertical).

4

Looks up and prints the type of c1.

5

Prints the cash flow vector.

6

Combines the cash flows to a tuple object.

7

tuple like list objects can contain other complex data structures.

8

A linear transformation of the vector by scalar multiplication and addition; technically one also speaks of a vectorized numerical operation and of broadcasting.

9

A linear combination of two ndarray objects (vectors).

Financial Assets

Financial assets are financial instruments (“contracts”) that have a fixed price today and an uncertain price in one year. Think of share in the equity of a firm that conducts an investment project. Such a share might be available at a price today of S00. The price of the share in one year depends on the success of the investment project, i.e. whether a high cash inflow is observed in the u state or a low one in the d state. Formally, S1u,S1d with S1u>S1d.

One speaks also of the price process of the financial asset S:×{u,d}0 mapping time and state of the economy to the price of the financial asset. Note that the price today is independent of the state S0u=S0dS0 while the price after one year is not in general. One also writes (St)t{0,1}=(S0,S1) or for short S=(S0,S1).

The NumPy package is again the tool of choice for the modeling.

In [49]: S0 = 10  1

In [50]: S1 = np.array((12.5, 7.5))  2

In [51]: S = (S0, S1)  3

In [52]: S  4
Out[52]: (10, array([12.5,  7.5]))

In [53]: S[0]  5
Out[53]: 10

In [54]: S[1][0]  6
Out[54]: 12.5

In [55]: S[1][1]  7
Out[55]: 7.5
1

The price of the financial asset today.

2

The uncertain price in one year as a vector (ndarray object).

3

The price process as a tuple object.

4

Prints the price process information.

5

Accesses the price today.

6

Accesses the price in one year in the u (first) state.

7

Accesses the price in one year in the d (second) state.

Risk

Often it is implicitly assumed that the two states of the economy are equally likely. What this means in general is that when an experiment in the economy is repeated (infinitely) many times, it is observed that half of the time the u state materializes and that in the other half of all experiments the d state materializes.

This is a frequentist point of view, according to which probabilities for a state to materialize are calculated based on the frequency the state is observed divided by the total number of experiments leading to observations. If state u is observed 30 times out of 50 experiments, the probability p0 with 0p1 is accordingly p=3050=0.6 or 60%.

In a modeling context, the probabilities for all possible states to occur are assumed to be given a priori. One speaks sometimes of objective or physical probabilities.

Probability Measure

The probabilities for events that are physically possible together form a probability measure. Such a probability measure is a function P:({u,d})0 mapping all elements of the power set of {u,d} — with ({u,d})={,{u},{d},{u,d}} — to the positive real line. The power set in this case embodies all events that are physically possible. In this context, the set {u,d} is also called the state space and is symbolized by Ω. The triple (Ω,(Ω),P) together is called a probability space.

A function P representing a probability measure needs to satisfy three conditions:

  1. P()=0

  2. 0P(ω),ωΩ1

  3. P(Ω)=P(u)+P(d)=1

The first condition implies that at least one of the states must materialize. The second implies that the probability for a state to materialize is between 0 and 1. The third one says that all the probabilities add up to 1.

In the simple model economy with two states only, it is convenient to define pP(u) and to accordingly have P(d)=1-p, given the third condition from above. Fixing p then defines the probability measure P.

Having a fully specified probability measure available, the model economy is typically called an economy under risk. A model economy without a fully specified probability measure is often called an economy under ambiguity.

In applications, a probability measure is usually modeled also as a vector and ndarray object, respectively. This is at least possible for a discrete state space with a finite number of elements.

In [56]: p = 0.4

In [57]: 1 - p
Out[57]: 0.6

In [58]: P = np.array((p, 1-p))

In [59]: P
Out[59]: array([0.4, 0.6])

Notions of Uncertainty

Uncertainty in a financial context can take on different forms. Risk in general refers to a situation in which a full probability distribution over future states of the economy is (assumed to be) known. Ambiguity refers to situations in which such a distribution is not known. Traditionally, finance has relied almost exclusively on model economies under risk, although there is a stream of research that deals with finance problems under ambiguity (see Guidolin and Rinaldi (2012) for a survey of the research literature).

Expectation

Based on the probability measure, the expectation of an uncertain quantity, like the price in one year of a financial asset, can be calculated. The expectation can be interpreted as the weighted average where the weights are given by the probabilities. It is an average since the probabilities add up to one.

Consider the financial asset with price process S=S0,S1. The expectation of the uncertain price S1 in one year under the probability measure P is

?P(S1)ωΩP(ω)·S1ω=p·S1u+(1-p)·S1d

with pP(u). If S1=(20,5)T and p=0.4 hold, the expectation value is

?P(S1)=0.4·20+(1-0.4)·5=11

Mathematically, the expectation can be expressed as the dot product (or inner product) of two vectors. If x,y2, the dot product is defined as

(x,y)=i=12xi·yi=x1·y1+x2·y2

Therefore, with P=(p,1-p)T and S1=(S1u,S1d)T the expectation is

?P(S1)=(P,S1)=p1-p,S1uS1d=p·S1u+(1-p)·S1d

Working with ndarray objects in Python, the dot product is defined as a function provided by the NumPy package.

In [60]: P  1
Out[60]: array([0.4, 0.6])

In [61]: S0 = 10  2

In [62]: S1 = np.array((20, 5))  3

In [63]: np.dot(P, S1)  4
Out[63]: 11.0
1

The previously defined probability measure.

2

The price of the financial asset today.

3

The vector of the uncertain price in one year.

4

The dot product of the two vectors calculating the expectation value.

Expected Return

Under uncertainty, the notions of return and rate of return need to be adjusted. In such a case, the expected return of a financial asset is given as the expectation of the price in one year minus the price today. This can be seen by taking the expectation of the uncertain return R=(Ru,Rd)T and rearranging as follows

?P(R)=p1-p,RuRd=p1-p,S1u-S0S1d-S0=p·(S1u-S0)+(1-p)·(S1d-S0)=p·S1u+(1-p)·S1d-S0=?P(S1)-S0

With the assumptions from before, one gets

?P(R)=0.4·(20-10)+(1-0.4)·(5-10)=11-10=1

The expected rate of return then simply is the expected return divided by the price today

?P(r)=?P(R)S0

which can be also derived step-by-step with similar transformations as for the expected return. In what follows, the expected rate of return is symbolized by μ?P(r) for brevity.

The calculation of expected return and rate of return can be modeled in Python by two simple functions.

In [64]: def ER(x0, x1):
             return np.dot(P, x1) - x0  1

In [65]: ER(S0, S1)  2
Out[65]: 1.0

In [66]: def mu(x0, x1):
             return (np.dot(P, x1) - x0) / x0  3

In [67]: mu(S0, S1)  4
Out[67]: 0.1
1

Definition of expected return.

2

The expected return for the previously defined financial asset.

3

Definition of the expected rate of return.

4

The expected rate of return calculate for that asset.

Volatility

In finance, risk and expected return is the dominating pair of concepts. Risk can be measured in many ways, while the volatility measured as the standard deviation of the rates of return is probably the most common measure. In the present context, the variance of the return rates of a financial asset is defined by

σ2(r)=?P(r-μ)2=p1-p,(ru-μ)2(rd-μ)2

with rω(S1ω-S0)/S0,ωΩ. The volatility is defined as the standard deviation of the return rates which is the square root of the variance

σ(r)=σ2(r)

Python functions modeling these two risk measures are given below. Also a helper function to calculate the return rates vector.

In [68]: def r(x0, x1):
             return (x1 - x0) / x0  1

In [69]: r(S0, S1)  2
Out[69]: array([ 1. , -0.5])

In [70]: mu = np.dot(P, r(S0, S1))  3

In [71]: mu  4
Out[71]: 0.10000000000000003

In [72]: def sigma2(P, r, mu):
             return np.dot(P, (r - mu) ** 2)  5

In [73]: sigma2(P, r(S0, S1), mu)  6
Out[73]: 0.54

In [74]: def sigma(P, r, mu):
             return np.sqrt(np.dot(P, (r - mu) ** 2))  7

In [75]: sigma(P, r(S0, S1), mu)  8
Out[75]: 0.7348469228349535
1

Vectorized calculation of the rates of return vector.

2

Applies the function to the financial asset from before.

3

The expected rate of return via the dot product …

4

… printed out.

5

The definition of the variance of the rates of return.

6

The function applied to the rates of return vector.

7

The definition of the volatility.

8

And applied to the rates of return vector.

Vectors, Matrices and NumPy

Finance as an applied mathematical discipline relies heavily on linear algebra and probability theory. In the discrete model economy, both mathematical disciplines and be efficiently handled in Python by using the NumPy package with its powerful ndarray object. This is not only true from a modeling point of view but also from handling, calculation, optimization, visualization and other points of view. Basically all examples to follow in the book will support these claims.

Contingent Claims

Suppose now that a contingent claim is traded in the economy. This is a financial asset — formalized by some contract — that offers a state-contingent payoff one year from now. Such a contingent claim can have an arbitrary state-contingent payoff or one that is derived from the payoff of other financial assets. In the latter case, one generally speaks of derivative assets or derivatives instruments. Formally, a contingent claim is a function C1:Ω0,ωC1(ω) mapping events to (positive) real numbers.

Assume that two financial assets are traded in the economy. A risk-less bond with price process B=(B0,B1) and a risky stock with price process S=S0,(S1u,S1d)T. A call option on the stock has a payoff in one year of C1(S1(ω))=max(S1(ω)-K,0) and ωΩ. K0 is called the strike price of the option.

In probability theory, a contingent claim is usually called a random variable whose defining characteristic is that it maps elements of the state space to real numbers — potentially via other random variables as is the case for derivative assets. In that sense, the price of the stock in one year S1:Ω0,ωS1(ω) is also a random variable.

For the sake of illustration, the Python code below visualizes the payoff of a call option on a segment of the real line. In the economy, there are of course only two states — and therewith two values — of relevance. Figure 2-1 shows the payoff function graphically.

In [76]: S1 = np.arange(20)  1

In [77]: S1[:7]  2
Out[77]: array([0, 1, 2, 3, 4, 5, 6])

In [78]: K = 10  3

In [79]: C1 = np.maximum(S1 - K, 0)  4

In [80]: C1  5
Out[80]: array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9])

In [81]: from pylab import mpl, plt  6
         # plotting configuration
         plt.style.use('seaborn')
         mpl.rcParams['savefig.dpi'] = 300
         mpl.rcParams['font.family'] = 'serif'

In [82]: plt.figure(figsize=(10, 6))
         plt.plot(S1, C1, lw = 3.0, label='$C_1 = max(S_1 - K, 0)$')  7
         plt.legend(loc=0)  8
         plt.xlabel('$S_1$')  9
         plt.ylabel('$C_1$');  10
1

Generates an ndarray object with numbers from 0 to 19.

2

Shows the the first few numbers.

3

Fixes the strike price for the call option.

4

Calculates in vectorized fashion the call option payoff values.

5

Shows these values — many values are 0.

6

Imports the main plotting sub-package from matplotlib.

7

Plots the call option payoff against the stock values; sets the line width to 3 pixels and defines a label as a string object with Latex code.

8

Puts the legend in the optimal location (least overlap with plot elements).

9

Places a label on the x axis …

10

… and on the y axis.

ftwp 0201
Figure 2-1. Payoff of the call option

Replication

When introducing a contingent claim into the economy, an important question that arises is whether the payoff of the contingent claim is redundant or not. Mathematically, one speaks of the payoff vector of the contingent claim being linearly dependent or linearly independent.

The payoff of the call option is said to be linearly dependent — or redundant — when a solution to the following problem exists for

b·B1B1+s·S1uS1d=C1uC1d

with b,s.

This problem can be represented as a system of linear equations

b·B1+s·S1u=C1ub·B1+s·S1d=C1d

With S1uS1d, solutions are given by

s*=C1u-C1dS1u-S1d

and

b*=1B1C1d·S1u-C1u·S1dS1u-S1d

Assume as before that two financial assets are traded, a risk-less bond B=(10,11) and a risky stock S=(10,(20,5)T). Assume further K=15 such that C1=(5,0)T. The optimal numerical solutions then are

s*=5-020-5=13

and

b*=111·0·20-5·520-5=-533

In words, buying one third of the stock and selling 533 of the bond short perfectly replicates the payoff of the call option. Therefore, the payoff of the call option is linearly dependent given the payoff vectors of the bond and the stock.

Technically, short selling implies borrowing the respective number of units of the financial asset today from another agent and immediately selling it in the market. In one year, the borrowing agent buys the exact number of units of the financial asset back in the market to the then current price and transfers them back to the other agent.

The analysis here assumes that all financial assets — like money — are infinitely divisible which might not be the case in practice. It also assumes that short selling of all traded financial assets is possible which might not be too unrealistic given market practice.

As a preparation for the implementation in Python, consider yet another way of formulating the replication problem. To this end, the mathematical concept of a matrix is needed. While a vector is a one-dimensional object, a matrix is a two-dimensional object. For the purposes of this section, consider a square matrix with four elements — implying 2×2 — with

=B1S1uB1S1d

The future payoff vectors of the bond and the stock represent the values in the first and second column of the matrix, respectively. The first row contains the payoff of both financial assets in the state u while the second row contains the payoffs from the d state. With these conventions, the replication problem can be represented in matrix form as

·ϕ=C1

where ϕ2 is the vector containing the bond and stock portfolio positions for replication ϕ(b,s)T. ϕ is usually simply called a portfolio or trading strategy. Therefore

B1S1uB1S1d·bs=C1uC1d

In this context, matrix multiplication is defined by

B1S1uB1S1d·bsB1·b+S1u·sB1·b+S1d·s

which shows the equivalence between this way of representing the replication problem and the one from before.

The ndarray class allows for a modeling of matrices in Python. The NumPy package provides in the sub-package np.linalg a wealth of functions for linear algebra operations among which there is also a function to solve systems of linear equations in matrix form — exactly what is needed here.

In [83]: B = (10, np.array((11, 11)))  1

In [84]: S = (10, np.array((20, 5)))  2

In [85]: M = np.array((B[1], S[1])).T  3

In [86]: M  4
Out[86]: array([[11, 20],
                [11,  5]])

In [87]: K = 15  5

In [88]: C1 = np.maximum(S[1] - K, 0)  6

In [89]: C1  7
Out[89]: array([5, 0])

In [90]: phi = np.linalg.solve(M, C1)  8

In [91]: phi  8
Out[91]: array([-0.15151515,  0.33333333])
1

Defines the price process for the risk-less bond.

2

Defines the price process for the risky stock.

3

Defines a matrix — i.e. a two-dimensional ndarray object — with the future payoff vectors.

4

Shows the matrix with the numerical values.

5

Fixes the strike price for the call option and …

6

… calculates the values for the payoff vector in one year.

7

Shows the numerical values of the payoff vector.

8

Solves the replication problem in matrix form to obtain the optimal portfolio positions.

Arbitrage Pricing

How much does it cost to replicate the payoff of the call option? Once the portfolio to accomplish the replication is derived, this question is easy to answer. Define the value of the replication portfolio today by V0(ϕ). It is given by the dot product

V0(ϕ)bs,B0S0=b·B0+s·S0

or in numbers

V0(ϕ)=b·B0+s·S0=103-5033=1.818181

The uncertain value of the replication portfolio in one year V1(ϕ) can be represented via matrix multiplication as

V1(ϕ)=B1S1uB1S1d·bs=50

Together, one has the value process of the portfolio as V(ϕ)=(V0(ϕ),V1(ϕ)) or V=(V0,V1) for short if there is no ambiguity regarding the portfolio.

Having a portfolio available that perfectly replicates the future payoff of a contingent claim raises the next question: what if the price of the contingent claim today differs from the costs of setting up the replication portfolio? The answer is simple but serious: then there exists an arbitrage or arbitrage opportunity in the economy. An arbitrage is a trading strategy ϕ that creates a risk-less profit out of an investment of zero. Formally, ϕ is an arbitrage if

  • V0(ϕ)=0 and ?PV1(ϕ)>0 or

  • V0(ϕ)>0 and V1(ϕ)=0

Suppose that the price of the call option is C0=2 which is higher than the cost to set up the replication portfolio. A trading strategy that sells the call option in the market for 2 and buys the replication portfolio for 1.81818 yields an immediate profit of the difference. In one year, the payoff of the replication portfolio and of the call option cancel each other out

-C1uC1d+b*B1B1+s*S1uS1d=00

by the definition of the replication portfolio. In the other case, when the price of the call option today is lower than the price of the replication portfolio, say C0=1.5 a trading strategy buying the call option and selling the replication portfolio yields a risk-less profit amounting to the difference between the market price of the call option and the cost to set up the replication portfolio. Of course, the risk-less profits in both cases can be increased by simply multiplying the positions by a positive factor greater than one.

A model for an economy which allows for arbitrage opportunities can be considered not viable. Therefore the only price that is consistent with the absence of arbitrage is C0=1.818181. One calls this price the arbitrage price of the call option. Whenever there is a portfolio ϕ replicating the payoff of a contingent claim V1(ϕ)=C1, then the arbitrage price of the contingent claim is C0=V0(ϕ).

Formally, the arbitrage price is the dot product of the replication portfolio and the price vector of the replicating financial assets

C0V0(ϕ)=ϕ*,B0S0=b*·B0+s*·S0

giving rise to an arbitrage-free price process for the contingent claim of C=(C0,C1).

In Python, this is a single calculation given the previous definitions and calculations.

In [92]: C0 = np.dot(phi, (B[0], S[0]))

In [93]: C0
Out[93]: 1.8181818181818183

In [94]: 10/3 - 50/33
Out[94]: 1.8181818181818183

Market Completeness

Does arbitrage pricing work for every contingent claim? Yes, at least for those that are replicable by portfolios of financial assets that are traded in the economy. The set of attainable contingent claims ? comprises all those contingent claims that are replicable by trading in the financial assets. It is given by the span which is the set of all linear combinations of the future price vectors of the traded financial assets

?=·ϕ,ϕ02

if short-selling is prohibited and

?=·ϕ,ϕ2

if it is allowed in unlimited fashion.

Consider the risk-less bond and the risky stock from before with price processes B=(B0,B1) and S=S0,(S1u,S1d)T, respectively, where B1,S102 and S1uS1d. It is then easy to show that the replication problem

·ϕ=C1

has a unique solution for any C102. The solution is given by

ϕ*=b*a*

and consequently as

ϕ*=C1u-C1dS1u-S1d1B1C1d·S1u-C1u·S1dS1u-S1d

which was derived in the context of the replication of the special call option payoff. The solution carries over to the general case since no special assumptions have been made regarding the payoff other than C102.

Since every contingent claim can be replicated by a portfolio consisting of a position in the risk-less bond and the risky stock, one speaks of a complete market model. Therefore, every contingent claim can be priced by replication and arbitrage. Formally, the only requirement being that the price vectors of the two financial assets in one year be linearly independent. This implies that

B1S1uB1S1d·bs=00

has only the unique solution ϕ*=(0,0)T and no other solution. In fact, all replication problems for arbitrary contingent claims have unique solutions under market completeness. The payoff vectors of the two traded financial assets span the 2 since they form a basis of the vector space 2.

The spanning property can be visualized by the use of Python and the matplotlib package. To this end, 1,000 random portfolio compositions are simulated. The first restriction is that the portfolio positions should be positive and add up to 1. Figure 2-2 shows the result.

In [95]: np.random.seed(100)  1

In [96]: n = 1000  2

In [97]: b = np.random.random(n)  3

In [98]: b[:5]  3
Out[98]: array([0.54340494, 0.27836939, 0.42451759, 0.84477613, 0.00471886])

In [99]: s = (1 - b)  4

In [100]: s[:5]  4
Out[100]: array([0.45659506, 0.72163061, 0.57548241, 0.15522387, 0.99528114])

In [101]: def portfolio(b, s):
              A = [b[i] * B[1] + s[i] * S[1] for i in range(n)]  5
              return np.array(A)  6

In [102]: A = portfolio(b, s)  7

In [103]: A[:3]  7
Out[103]: array([[15.10935552,  8.26042965],
                 [17.49467553,  6.67021631],
                 [16.17934168,  7.54710554]])

In [104]: plt.figure(figsize=(10, 6))
          plt.plot(A[:, 0], A[:, 1], 'r.');  8
1

Fixes the seed for the random number generator.

2

Number of values to be simulated.

3

Simulates the bond position for values between 0 and 1 by the means of a uniform distribution.

4

Derives the stock position as the difference between 1 and the bond position.

5

This calculates the portfolio payoff vectors for all random portfolio compositions and collects them in a list object; this Python idiom is called a list comprehension.

6

The function returns a ndarray version of the results.

7

The calculation is initiated.

8

The results are plotted.

ftwp 0202
Figure 2-2. The random portfolios span a one-dimensional line only

Figure 2-3 shows the graphical results in the case where the portfolio positions do not need to add up to 1.

In [105]: s = np.random.random(n)  1

In [106]: b[:5] + s[:5]
Out[106]: array([0.57113722, 0.66060665, 1.3777685 , 1.06697466, 0.30984498])

In [107]: A = portfolio(b, s)  2

In [108]: plt.figure(figsize=(10, 6))
          plt.plot(A[:, 0], A[:, 1], 'r.');
1

The stock position is freely simulated for values between 0 and 1.

2

The portfolio payoff vectors are calculated.

ftwp 0203
Figure 2-3. The random portfolios span a two-dimensional area (rhomb)

Finally, Figure 2-4 allows for positive as well as negative portfolio positions for both the bond and the stock. The resulting portfolio payoff vectors cover an (elliptic) area around the origin.

In [109]: b = np.random.standard_normal(n)  1

In [110]: s = np.random.standard_normal(n)  1

In [111]: b[:5] + s[:5]  1
Out[111]: array([-0.66775696,  1.60724747,  2.65416419,  1.20646469,
           -0.12829258])

In [112]: A = portfolio(b, s)

In [113]: plt.figure(figsize=(10, 6))
          plt.plot(A[:, 0], A[:, 1], 'r.');
1

Positive and negative portfolio positions are simulated by the means of the standard normal distribution.

ftwp 0204
Figure 2-4. The random portfolios span a two-dimensional area (around the origin)

If b and s are allowed to take on arbitrary values on the real line b,c, the resulting portfolios cover the vector space 2 completely. As pointed out above, the payoff vectors of the traded financial assets span 2 in that case.

Arrow-Debreu Securities

An Arrow-Debreu security is defined by the fact that is pays exactly one unit of currency in a specified future state. In a model economy with two different future states only, there can only be two different such securities. An Arrow-Debreu security is simply a special case of a contingent claim such that the replication argument from before applies. In other words, since the market is complete Arrow-Debreu securities can be replicated by portfolios in the bond and stock. Therefore, both replication problems have (unique) solutions and both securities have unique arbitrage prices. The two replication problems are

·ϕ=10

and

·ϕ=01

Why are these securities important? Mathematically, the two payoff vectors form a standard basis or natural basis for the 2 vector space. This in turn implies that any vector of this space can be uniquely expressed (replicated) as a linear combination of the vectors that form the standard basis. Financially, replacing the original future price vectors of the bond and the stock by Arrow-Debreu securities as a basis for the model economy significantly simplifies the replication problem for all other contingent claims.

The process is to first derive the replication portfolios for the two Arrow-Debreu securities and the resulting arbitrage prices for both. Other contingent claims are then replicated and priced based on the standard basis and the arbitrage prices of the two securities.

Consider the two Arrow-Debreu securities with price processes γu=(γ0u,(1,0)T) and γd=(γ0d,(0,1)T) and define

Mγ=1001

Consider a general contingent claim with future payoff vector

C1=C1uC1d

The replication portfolio ϕγ for the contingent claim then is trivially given by ϕγ=(C1u,C1d)T since

V1(ϕγ)=γ·ϕγ=1001·C1uC1d=C1uC1d

Consequently, the arbitrage price for the contingent claim is

C0=V0(ϕγ)=C1u·γ0u+C1d·γ0d

This illustrates how the introduction of Arrow-Debreu securities simplifies contingent claim replication and arbitrage pricing.

Martingale Pricing

A martingale measure Q:(Ω)0 is a special kind of probability measure. It makes the discounted price process of a financial asset a martingale. For the stock to be a martingale under Q, the following relationship must hold:

S0=11+i·?Q(S1)

If i=B1-B0B0, the relationship is trivially satisfied for the risk-less bond

B0=11+i·?Q(B1)=11+i·B1

One also speaks of the fact that the price processes drift (on average) with the risk-less interest rate under the martingale measure

B0·(1+i)=B1S0·(1+i)=?Q(S1)

Denote qQ(u). One gets

q·S1u+(1-q)·S1d=S0·(1+i)

or after some simple manipulations

q=S0·(1+i)-S1dS1u-S1d

Given previous assumptions, for q to define a valid probability measure S1u>S0·(1+i)>S1d must hold. If so, one gets a new probability space (Ω,(Ω),Q) where Q replaces P.

What if these relationships for S1 do not hold? Then a simple arbitrage is either to buy the risky asset in the case S0S1d or to simply sell it in the other case S0S1u.

If equality holds in these relationships one also speaks of a weak arbitrage since the risk-less profit can only be expected on average and not with certainty.

Assuming the numerical price processes from before, the calculation of q in Python means just an arithmetic operation on floating point numbers.

In [114]: i = (B[1][0] - B[0]) / B[0]

In [115]: i
Out[115]: 0.1

In [116]: q = (S[0] * (1 + i) - S[1][1]) / (S[1][0] - S[1][1])

In [117]: q
Out[117]: 0.4

First Fundamental Theorem of Asset Pricing

The considerations at the end of the previous section hint already towards a relationship between martingale measures on the one hand and arbitrage on the other. A central result in mathematical finance that relates these seemingly unrelated concepts formally is the First Fundamental Theorem of Asset Pricing. Pioneering work in this regard has been published by Cox and Ross (1976), Harrison and Kreps (1979) and Harrison and Pliska (1981).

First Fundamental Theorem of Asset Pricing (1FTAP)

The following statements are equivalent:

  1. A martingale measure exists.

  2. The economy is arbitrage-free.

Given the calculations and the discussion from before, the theorem is easy to prove for the model economy with the risk-less bond and the risky stock.

First, 1. implies 2.: If the martingale measure exists, the price processes do not allow for simple (weak) arbitrages. Since the two future price vectors are linearly independent, every contingent claim can be replicated by trading in the two financial assets implying unique arbitrage prices. Therefore, no arbitrages exist.

Second, 2. implies 1.: If the model economy is arbitrage-free, a martingale measure exists as shown above.

Pricing by Expectation

A corollary of the 1FTAP is that any attainable contingent claim C1? can be priced by taking the expectation of its future payoff and discounting with the risk-less interest rate. The arbitrage price of the call option is known through replication. Assuming the same numerical price processes for the traded financial assets and the same numerical future payoff vector for the call option, the martingale price of the call option is

C0=11+i·?Q(C1)=11+i·(q·C1u+(1-q)·C1d)=11+0.1·(0.4·5+(1-0.4)·0)=1.818181

In other words, the discounted price process of the call option — and any other contingent claim — is a martingale under the martingale measure such that

B0·(1+i)=B1S0·(1+i)=?Q(S1)C0·(1+i)=?Q(C1)

In Python, the martingale pricing boils down to the evaluation of a dot product.

In [118]: Q = (q, 1-q)  1

In [119]: np.dot(Q, C1) / (1 + i)  2
Out[119]: 1.8181818181818181
1

Defines the martingale measure as the tuple Q.

2

Implements the martingale pricing formula.

Second Fundamental Theorem of Asset Pricing

There is another important result, often called the Second Fundamental Theorem of Asset Pricing, which relates the uniqueness of the martingale measure with market completeness.

Second Fundamental Theorem of Asset Pricing (2FTAP)

The following statements are equivalent:

  1. The martingale measure is unique.

  2. The market model is complete.

The result also follows for the simple model economy from previous discussions. A more detailed analysis of market completeness takes place in Chapter 3.

Mean-Variance Portfolios

A major breakthrough in finance has been the formalization and quantification of portfolio investing through the mean-variance portfolio theory (MVP) as pioneered by Markowitz (1952). To some extent this approach can be considered to be the beginning of quantitative finance, initiating a trend that brought more and more mathematics to the financial field.

MVP reduces a financial asset to the first and second moment of its returns, namely the mean as the expected rate of return and the variance of the rates of return or the volatility defined as the standard deviation of the rates of return. Although the approach is generally called “mean-variance” it is often the combination “mean-volatility” that is used.

Consider the risk-less bond and risky stock from before with price processes B=(B0,B1) and S=S0,(S1u,S1d)T and the future price matrix for which the two columns are given by the future price vectors of the two financial assets. What is the expected rate of return and the volatility of a portfolio ϕ that consists of b percent invested in the bond and s percent invested the stock? Note that now a situation is assumed for which b+s=1 with b,s0 holds. This can, of course, be relaxed but simplifies the exposition in this section.

The expected portfolio payoff is

?P(·ϕ)=p·(b·B1+s·S1u)+(1-p)·(b·B1+s·S1d)=p·(b·B1)+(1-p)·(b·B1)+p·(s·S1u)+(1-p)(s·S1d)=b·?P(B1)+s·?P(S1)=b·B1+s·?P(S1)

In words, the expected portfolio payoff is simply b times the bond payoff plus s times the stock payoff.

Defining 2×2 to be the rates of return matrix with

=ir1uir1d

one gets for the expected portfolio rate of return

?P(·ϕ)=b·?P(i)+s·?P(r1)=b·i+s·μ

In words, the expected portfolio rate of return is b times the risk-less interest rate plus s times the expected rate of return of the stock.

The next step is to calculate the portfolio variance

σ2(·ϕ)=?Pr-?P(·ϕ)2=p1-p,(b·i+s·r1u-b·i-s·μ)2(b·i+s·r1d-b·i-s·μ)2=p1-p,(s·r1u-s·μ)2(s·r1d-s·μ)2=s2·σ2(r1)

In words, the portfolio variance is s2 times the stock variance which makes intuitively sense since the bond is risk-less and should not contribute to the portfolio variance. It immediately follows the nice proportionality result for the portfolio volatility

σ(·ϕ)=σ2(·ϕ)=s2·σ2(r1)=s·σ(r1)

The whole analysis is straightforward to implement in Python. First, some preliminaries.

In [120]: B = (10, np.array((11, 11)))

In [121]: S = (10, np.array((20, 5)))

In [122]: M = np.array((B[1], S[1])).T  1

In [123]: M  1
Out[123]: array([[11, 20],
                 [11,  5]])

In [124]: M0 = np.array((B[0], S[0]))  2

In [125]: R = M / M0 - 1  3

In [126]: R  4
Out[126]: array([[ 0.1,  1. ],
                 [ 0.1, -0.5]])

In [127]: P = np.array((0.5, 0.5))  5
1

The matrix with the future prices of the financial assets.

2

The vector with the prices of the financial assets today.

3

Calculates in vectorized fashion the return matrix.

4

Shows the results of the calculation.

5

Defines the probability measure.

With these definitions, expected portfolio return and volatility are calculated as dot products.

In [128]: np.dot(P, R)  1
Out[128]: array([0.1 , 0.25])

In [129]: s = 0.55  2

In [130]: phi = (1-s, s)  3

In [131]: mu = np.dot(phi, np.dot(P, R))  4

In [132]: mu  5
Out[132]: 0.18250000000000005

In [133]: sigma = s * R[:, 1].std()  6

In [134]: sigma  7
Out[134]: 0.41250000000000003
1

The expected returns of the bond and the stock.

2

An example allocation for the stock in percent (decimals).

3

The resulting portfolio with a normalized weight of 1.

4

The expected portfolio return given the allocations.

5

The value lies between the risk-less return and the stock return.

6

The volatility of the portfolio; the Python code here only applies due to p=0.5.

7

Again, the value lies between the volatility of the bond (= 0) and the volatility of the stock (= 0.75).

Varying the weight of the stock in the portfolio leads to different risk-return combinations. Figure 2-5 shows the expected portfolio return and volatility for different values of s between 0 and 1. As the plot illustrates, both the expected portfolio return (from 0.1 to 0.25) and the volatility (from 0.0 to 0.75) increase linearly with increasing allocation s of the stock.

In [135]: values = np.linspace(0, 1, 25)  1

In [136]: mu = [np.dot(((1-s), s), np.dot(P, R))
                for s in values]  2

In [137]: sigma = [s * R[:, 1].std() for s in values]  3

In [138]: plt.figure(figsize=(10, 6))
          plt.plot(values, mu, lw = 3.0, label='$mu_p$')
          plt.plot(values, sigma, lw = 3.0, label='$sigma_p$')
          plt.legend(loc=0)
          plt.xlabel('$s$');
1

Generates an ndarray object with 24 evenly space intervals between 0 and 1.

2

Calculates for every element in values the expected portfolio return and stores them in a list object.

3

Calculates for every element in values the portfolio volatility and stores them in another list object.

ftwp 0205
Figure 2-5. Expected portfolio return and volatility for different allocations

Note that the list comprehension sigma = [s * R[:, 1].std() for s in values] in the code above is short for the following code3:

sigma = list()
for s in values:
    sigma.append(s * R[:, 1].std())

The typical graphic seen in the context of MVP is one that plots expected portfolio return against portfolio volatility. Figure 2-6 shows that an investor can expect a higher return the more risk (volatility) she is willing to bear. The relationship is linear in the special case of this section.

In [139]: plt.figure(figsize=(10, 6))
          plt.plot(sigma, mu, lw = 3.0, label='risk-return')
          plt.legend(loc=0)
          plt.xlabel('$sigma_p$')
          plt.ylabel('$mu_p$');
ftwp 0206
Figure 2-6. Feasible combinations of expected portfolio return and volatility

Conclusions

This chapter introduces to finance, starting with the very basics and illustrating the central mathematical objects and financial notions by simple Python code examples. The beauty is that fundamental ideas of finance — like arbitrage pricing or the risk-return relationship — can be introduced and understood even in a static two state economy. Equipped with this basic understanding and some financial and mathematical intuition, the transition to increasingly more realistic financial models is significantly simplified. The subsequent chapter, for example, adds a third future state to the state space to discuss issues arising in the context of market incompleteness.

Further Resources

Papers cited in this chapter:

  • Cox, John and Stephen Ross (1976): “The Valuation of Options for Alternative Stochastic Processes.” Journal of Financial Economics, Vol. 3, 145-166.

  • Delbaen, Freddy and Walter Schachermayer (2006): The Mathematics of Arbitrage. Springer Verlag, Berlin.

  • Guidolin, Massimo and Francesca Rinaldi (2013): “Ambiguity in Asset Pricing and Portfolio Choice: A Review of the Literature.” Theory and Decision, Vol. 74, 183–217, https://ssrn.com/abstract=1673494.

  • Harrison, Michael and David Kreps (1979): “Martingales and Arbitrage in Multiperiod Securities Markets.” Journal of Economic Theory, Vol. 20, 381–408.

  • Harrison, Michael and Stanley Pliska (1981): “Martingales and Stochastic Integrals in the Theory of Continuous Trading.” Stochastic Processes and their Applications, Vol. 11, 215–260.

  • Markowitz, Harry (1952): “Portfolio Selection.” Journal of Finance, Vol. 7, No. 1, 77-91.

  • Perold, André (2004): “The Capital Asset Pricing Model.” Journal of Economic Perspectives, Vol. 18, No. 3, 3-24.

1 For details on the Fundamental Theorems of Asset pricing, refer to the seminal papers by Harrisson and Kreps (1979) and Harrisson and Pliska (1981).

2 For details on the standard data types in Python, refer to the Built-in Types documentation.

3 Refer to the Data Structures documentation for more on data structures and comprehension idioms in Python.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.129.13.201