Sunteți pe pagina 1din 13

SundaramDas:

Derivatives: Principles and


Practice

Chapter

VI. Computation

37. Using Octave

The McGrawHill
Companies, 2011

37
Using Octave
We present a very brief introduction to the open-source, free mathematical language known
as Octave. Octave replicates many of the features of the commercial package Matlab. We
decided to use it in this book because it is free and has many functions that can be accessed
from the web. Almost all the syntax of Octave corresponds to that of Matlab, so students
may eventually migrate to Matlab if they so wish (or go from Matlab to Octave as well).
One of the advantages of Octave is that it runs on the Windows, Macintosh, and
Linux platforms. The binary program may be downloaded from http://www.gnu.org/
software/octave/. The index of functions may be accessed at http://www.gnu.org/
software/octave/doc/interpreter/Function-Index.html#Function - Index.
Installation is easy. Plotting in Octave is undertaken using GnuPlot, another free, opensource, and widely used graphics package. GnuPlot is automatically installed when you
install Octave.
We hope that the reader will install Octave and then use the program code provided in
the book and answer keys to try out the derivatives models under study. This is the best way
to learn and retain the ideas of the hundreds of pricing models we present. Here are some
simple commands that are useful to get you started using Octave.

37.1

Some Simple Commands


To change to the directory in which your les are, type in the following command:
>> cd <directory name>
You can also read in data directly from an ASCII le where the data has been listed in
columns, separated by spaces. Suppose you have a data le called mydata.txt. To load
in this data le, you give the following command at the prompt:
load mydaya.txt
This will create a matrix in memory with the name mydata. The le extension is dropped
when creating the variable in memory. To see the dimensions of the matrix, type in size
mydata.
To see all the variables resident in memory, type in who.
When you start the program, you will get a window with the command prompt. You can
run Octave in two ways. One is from the command line by typing in one command after
another. This makes your use of the program similar to that of a sophisticated calculator.
Second, you can write lengthy (or short) programs into a separate le and then call that
program le from the command line. The system will then execute all the commands in
945

SundaramDas:
Derivatives: Principles and
Practice

VI. Computation

37. Using Octave

The McGrawHill
Companies, 2011

946 Part Six Computation

the program le. Usually, the convention for naming program les is that they end in .m,
so for example, you may have a program le called prog.m.
So, you can call the program code in prog.m by using the following command:
>> prog
The system will automatically assume the .m le extension.

For Loops
Writing loops uses the [for ... end] wrapper. Here is a loop that computes the factorial of
the number n.
octave:1> n=6; fact=1; for j=1:n; fact = fact*j; end; fact
fact = 720
Briey, this is what we programmed. We initialized n = 6. Then we initialized the factorial
fact to be unity. The loop ran over index j from 1 to n, each time multiplying the previous
value of fact by the next value of j. When the loop was nished, we just typed fact without
a semicolon at the end to get the result. When you type a statement with the semicolon, it
suppresses displaying the result.
We could also have done the same less economically as follows:
octave:2> n=6;
octave:3> fact=1;
octave:4> for j=1:n; fact = fact * j; end;
octave:5> fact
fact = 720

While Loops
Loops may also be implemented using the [while ... end] statements. Here is the same
example as above, implemented differently:
octave:10> n=6; fact=1; j=n; while j>0; fact=fact*j; j=j-1; end; fact
fact = 720

Example 37.1 Factorials


As is well known, we may also compute factorials using a recursion. In order to implement
a recursion, we need to dene a function, which then calls itself. First we create a function
called fact.m:
function u = fact(n);
if n==0 || n==1;
u = 1;
else
u = n * fact(n-1);
end;
You can see that the function calls itself on the fth line. We store this function in a separate
le called fact.m, noting the sufx is standard in the programming language. The rst line
of the function is also standard and describes how functions are specied in Octave. The
remaining lines also demonstrate how the [if ... else ... end] statement is used. The
second line shows how a conditional if statement is specied. Note that the statement n==0

SundaramDas:
Derivatives: Principles and
Practice

VI. Computation

The McGrawHill
Companies, 2011

37. Using Octave

Chapter 37 Using Octave

947

uses a double equal-to sign, not just one. The recursive function call is in line 5. Save this
function le in the working directory, and then call the program as follows:
octave:3> fact(6)
ans = 720

Example 37.2 Binomial Trees


In the chapter on pricing options with binomial trees, we learned to use a double loop (over
both time and stock price) to implement the Cox, Ross, and Rubinstien (1979) model. We
will not go into the details of this model here. However, we will implement the same model
recursively, replacing the double loop with a single recursion.
First, we write a function (program) to price the option recursively. This is as follows:
function u = crr_rec(s,X,T,sigma,rf,pc,N);
if N==0;
if pc==1; optval=max(0,s-X); end;
if pc==0; optval=max(0,X-s); end;
else
h = T/N;
u = exp(sigma*sqrt(h));
d = exp(-sigma*sqrt(h));
R = exp(rf*h);
q = (R-d)/(u-d);
optval = (q*crr_rec(s*u,X,T-h,sigma,rf,pc,N-1)+ ...
(1-q)*crr_rec(s*d,X,T-h,sigma,rf,pc,N-1))/R;
end;
u = optval;
The function requires many inputs, not just one as in the previous example. We need to
pass into the function the stock price (s), the strike price (X), time to maturity (T), volatility (sigma), risk-free rate (rf), put or call ag (pc), where the value 1 indicates a call and
value 0 indicates a put. Finally, we also stipulate how many steps we want in the binomial
tree, i.e., N.
The recursion builds out a tree by spawning a new pair of nodes (recall that the tree
is binomial) from each current node. We can see the function call itself on the two succeeding nodes in the function lines 11 and 12. At each function call, the next nodes are
instantiated by calling the function at both succeeding nodes; note that all the parameters
need to be passed along each time such a call is made. Lines 25 contain the condition
at which the recursion is terminated, i.e., when the last time period in the tree is reached.
At this point, the terminal value of the option is generated, and then the recursion begins
to unwind itself.
Lets price a six-period option. We price both the call and the put. We then also compute
put-call parity to check our model. Here are the function calls:
octave:6> call = crr_rec(100,101,0.5,0.3,0.05,1,6)
call = 8.9539
octave:7> put = crr_rec(100,101,0.5,0.3,0.05,0,6)
put = 7.4602
octave:8> call - put
ans = 1.4937
octave:9> 100 - 101*exp(-0.05*0.5)
ans = 1.4937
We can see that the put-call parity condition (C P = S P V (K )) is satised as well.

SundaramDas:
Derivatives: Principles and
Practice

VI. Computation

The McGrawHill
Companies, 2011

37. Using Octave

948 Part Six Computation

37.2

Regression and Integration


Whereas Octave is primarily a matrix language, it contains many statistical tools as well.
Here we create some data and then run a regression to demonstrate how it works. To create
the data, we also demonstrate the random number generators that are available.
We can generate uniform random numbers using the rand function call. Lets create a
column of 200 such numbers:
octave:12> u = rand(200,1);
From this we will create a column of data to mimic our dependent variable
octave:13> y = u * 5;
We also create the independent variable by multiplying the original variable by 10 and then
adding a random normal number using the function call randn (note this has the same call
as before but the function name has an extra n at the end).
octave:14> x = u * 10 + randn(200,1);
It is useful to see the power of a matrix language here. Even though the statements above
make it look like we are operating on a single variable, we are indeed computing the entire
vector of 200 values at one time. We are now ready to run the regression of y on x using
ordinary least squares. The regression line will be
y =a+b x +e
where a, b are the coefcients in the regression and e is the residual or error term. In order
to do this regression, we also need to create a column of data for the intercept term a. Hence,
we enhance the dependent variable to include a column of ones. This is how to do it:
octave:18> x = [ones(200,1)

x];

The function ones(m,n) creates a matrix of ones of dimension m rows and n columns.
Finally, we run the regression as follows:
octave:19> ols(y,x)
ans =
0.25025
0.44932
This returns the required values from the regression, which are a=0.25025 and b=0.44932.

Help
All canned functions in Octave come with a help function. For example, if we wanted to
know how to specify the regression syntax, we could have typed
help ols
and we would have obtained the following:
octave:20> help ols
ols is the user-defined function from the file
/sw/share/octave/2.1.53/m/statistics/base/ols.m
-- Function File: [BETA, SIGMA, R] = ols (Y, X)

SundaramDas:
Derivatives: Principles and
Practice

VI. Computation

37. Using Octave

The McGrawHill
Companies, 2011

Chapter 37 Using Octave

949

Ordinary least squares estimation for the multivariate model


y = x b + e with mean (e) = 0 and cov (vec (e)) = kron (s, I).
where y is a t by p matrix, x is a t by k matrix, b is a k by
p matrix, and e is a t by p matrix.
Each row of Y and X is an observation and each column a variable.
The return values BETA, SIGMA, and R are defined as follows.
BETA
The OLS estimator for B, BETA = pinv (X) * Y, where pinv
(X) denotes the pseudoinverse of X.
SIGMA
The OLS estimator for the matrix S,
SIGMA = (Y-X*BETA)
* (Y-X*BETA)
/ (T-rank(X))
R
The matrix of OLS residuals, R = Y - X * BETA.
Additional help for built-in functions, operators, and variables
is available in the on-line version of the manual. Use the command
help -i <topic> to search the manual index.
Help and information about Octave is also available on the WWW
at http://www.octave.org and via the help-octave@bevo.che.wisc.edu
mailing list.

Integration
There are standard numerical integration routines in Octave. The most common one is the
function quad, which uses a quadrature approach. As an example, we will integrate the
normal probability density function over the range (a, +a) as follows:
octave:25> a =
ans = 0.68269
octave:26> a =
ans = 0.95450
octave:27> a =
ans = 0.99730
octave:28> a =
ans = 0.99994
octave:30> a =
ans = 1.00000
octave:31> a =
ans = 1.00000

1; quad(normal_pdf(x),-a,a)
2; quad(normal_pdf(x),-a,a)
3; quad(normal_pdf(x),-a,a)
4; quad(normal_pdf(x),-a,a)
5; quad(normal_pdf(x),-a,a)
6; quad(normal_pdf(x),-a,a)

Hence, we have done the integration many times, going from 1-sigma to 6-sigma, and we
can see that the area under the normal curve increased until we reached unity.

SundaramDas:
Derivatives: Principles and
Practice

VI. Computation

The McGrawHill
Companies, 2011

37. Using Octave

950 Part Six Computation

Suppose instead that we wanted to do the same integration mechanically without using
the canned quadrature routine. In other words, we want to approximate the integral by a
discrete sum, i.e.,
 a
a

(x) d x
(x) x
a

x=a

For example, say we want to do this over the range from (3, +3). First, we create a discrete
small step size, say x = 0.01.
octave:32> dx = 0.01;
Next, we create a vector of discrete values over the entire support, at intervals of x. This
is done as follows:
octave:33> x = [-3:dx:3];
This creates a vector of values {3, 2.99, 2.98, . . . , 2.99, 3}. Finally, we implement the
discrete sum, using the sum function, as follows:
octave:34> sum(normal_pdf(x) * dx)
ans = 0.99734
Note that when we call the normal probability density function and pass to it an entire
vector of values, it returns back a vector of function values. As we can see, the result is
quite accurate and is almost the same as what was obtained using the quadrature function.
In order to increase accuracy, we may take x = 0.001 instead. Here is the result using the
new value:
octave:35> dx = 0.001;
octave:36> x = [-3:dx:3];
octave:37> sum(normal_pdf(x) * dx)
ans = 0.99730
Now we get exactly the same answer as with the quadrature routine.

37.3

Reading in Data, Sorting, and Finding


Suppose we have a data le with two columns of data stored in a plain text le. Lets call
the le mydata.txt. Here is the le:
%

X1
1.75552
2.48603
4.28121
4.72918
3.16090
0.31241
1.79625
0.77824
1.14772
2.97055

X2
1.43763
3.30246
4.08831
3.91513
1.32696
0.79171
5.44980
9.00096
8.05371
4.22001

Note that in Octave, you can have only numeric values in a le. We will load the data into
a matrix as follows:

SundaramDas:
Derivatives: Principles and
Practice

VI. Computation

The McGrawHill
Companies, 2011

37. Using Octave

Chapter 37 Using Octave

951

octave:41> load mydata.txt


octave:42> mydata
mydata =
1.75552
2.48603
4.28121
4.72918
3.16090
0.31241
1.79625
0.77824
1.14772
2.97055

1.43763
3.30246
4.08831
3.91513
1.32696
0.79171
5.44980
9.00096
8.05371
4.22001

The load function stores the data in a matrix that has the name of the input le without
its sufx. Hence, the data matrix in memory is called mydata. The program only reads in
lines that do not have a % sign in front of them. Hence, when creating the data le, you can
have a header line but comment it out so that it is not read in. The load function will also
not work with non-numeric data.
If we want to store the variables separately, we can always slice pieces off the main
data matrix as follows:
octave:43> x1 = mydata(:,1)
x1 =
1.75552
2.48603
4.28121
4.72918
3.16090
0.31241
1.79625
0.77824
1.14772
2.97055
The slice took all rows and the rst column of mydata and stored it in a vector x1. If we
wanted rows 35 and columns 12, we would do the following:
octave:44> mydata(3:5,1:2)
ans =
4.2812
4.7292
3.1609

4.0883
3.9151
1.3270

The same could also be achieved with the following command:


octave:45> mydata(3:5,:)
ans =
4.2812

4.0883

SundaramDas:
Derivatives: Principles and
Practice

VI. Computation

37. Using Octave

The McGrawHill
Companies, 2011

952 Part Six Computation

4.7292
3.1609

3.9151
1.3270

This is because we want all columns.

Sorting
Say we want to sort the mydata matrix in the order of the rst column. This is done using
the sort function as follows:
octave:47> x = mydata(:,1)
x =
1.75552
2.48603
4.28121
4.72918
3.16090
0.31241
1.79625
0.77824
1.14772
2.97055
octave:48> [S,I] = sort(x)
S =
0.31241
0.77824
1.14772
1.75552
1.79625
2.48603
2.97055
3.16090
4.28121
4.72918
I =
6
8
9
1
7
2
10
5
3
4
We began by extracting the rst column of the data and storing it in a variable x. Next we
called the sort function, which returns two columns of data: S, which is the sorted column
of data, and I the index of the sort. The index returns the positions of the elements of

SundaramDas:
Derivatives: Principles and
Practice

VI. Computation

37. Using Octave

The McGrawHill
Companies, 2011

Chapter 37 Using Octave

953

the sorted column instead of the sorted values. Since the sixth element is the smallest, it
appears rst in the vector I. Likewise, the fourth element is the largest and appears last.
We now use the index vector to obtain the sorted list of the second column of data as
follows:
octave:49> x2 = mydata(:,2)
x2 =
1.43763
3.30246
4.08831
3.91513
1.32696
0.79171
5.44980
9.00096
8.05371
4.22001
octave:50> x2(I)
ans =
0.79171
9.00096
8.05371
1.43763
5.44980
3.30246
4.22001
1.32696
4.08831
3.91513
Note that we wanted the second column of data in the sort order based on the rst column
of data. Hence, we used the statement x2(I), which means to return the elements of x2
indexed by I. Hence, the sixth element of x2 appears rst, and the fourth element appears
last.

Finding
The find command is very useful to extract slices of data based on some criterion. This is
best illustrated with an example. We use the same mydata from above. Suppose we wanted
to collect all values of x2 (the second column of data) when the value of x1 (the rst column
of data) is greater than 3. First lets print out mydata one more time:
octave:51> mydata
mydata =
1.75552
2.48603
4.28121
4.72918
3.16090

1.43763
3.30246
4.08831
3.91513
1.32696

SundaramDas:
Derivatives: Principles and
Practice

VI. Computation

37. Using Octave

The McGrawHill
Companies, 2011

954 Part Six Computation

0.31241
1.79625
0.77824
1.14772
2.97055

0.79171
5.44980
9.00096
8.05371
4.22001

We can see that there are only three cases in which the values in the rst column are greater
than 3, i.e., the elements 3, 4, and 5. We use the following commands to obtain the index
set of these elements:
octave:52> x1 = mydata(:,1);
octave:53> I = find(x1>3);
octave:54> I
I =
3
4
5
The function find contains a mathematical condition (x1>3) and returns an index vector
containing the element numbers that satisfy the criterion. Next we use this index vector just
as we had done in the previous section to obtain these specic elements of x2.
octave:55> x2(I)
ans =
4.0883
3.9151
1.3270
We obtain the desired subvector based on the index set. If we want to know how many
elements there are, we simply use the function length:
octave:56> length(I)
ans = 3
What if we run the find command on the entire matrix?
octave:57> find(mydata>3)
ans =
3
4
5
12
13
14
17
18
19
20
The result is self-explanatory. However, note that the numbering (indexing) is column by
column.

SundaramDas:
Derivatives: Principles and
Practice

VI. Computation

37. Using Octave

The McGrawHill
Companies, 2011

Chapter 37 Using Octave

37.4

955

Equation Solving
Equation solving is a useful tool. In many cases in nance, we need to nd roots of equations
in parts of our numerical analyses. The following example demonstrates how easy it is to
undertake this in Octave:
octave:59> fsolve(2*x^2-12*x+3,1)
ans = 0.26139
We solved the equation 2x 2 12x + 3 = 0 and passed the starting value of 1. What if we
used a different starting value?
octave:59> fsolve(2*x^2-12*x+3,6)
ans = 5.7386
We get a different answer, which is not surprising, since the equation is a quadratic and there
are two solutions. The example highlights the care required in numerical work because one
needs to make sure that the root we obtain is the one we require.

37.5

Screenshots
Figure 37.1 is a screen shot demonstrating how to call the normal distribution probability
density function and plot it with a background grid. The gure also shows the commands
needed to generate the plot.

FIGURE 37.1
Generating a Normal
Probability Density
Plot

SundaramDas:
Derivatives: Principles and
Practice

VI. Computation

37. Using Octave

The McGrawHill
Companies, 2011

956 Part Six Computation

Figure 37.2 is a screen shot showing how to program nested loops and then plot a 3-D
graph.
Figure 37.3 is a screen shot showing the use of various statistical functions.
Figure 37.4 is a screen shot showing how to solve a system of simultaneous equations
using matrix algebra. This solves the matrix equation AX = B. Check the result yourself
by typing: A*X.

FIGURE 37.2
Nested Loops and 3-D
Plots

FIGURE 37.3
Basic Statistical
Functions

SundaramDas:
Derivatives: Principles and
Practice

VI. Computation

37. Using Octave

The McGrawHill
Companies, 2011

Chapter 37 Using Octave

FIGURE 37.4
Solving a System of
Equations

957

S-ar putea să vă placă și