Book Image

F# for Quantitative Finance

By : Johan Astborg
Book Image

F# for Quantitative Finance

By: Johan Astborg

Overview of this book

F# is a functional programming language that allows you to write simple code for complex problems. Currently, it is most commonly used in the financial sector. Quantitative finance makes heavy use of mathematics to model various parts of finance in the real world. If you are interested in using F# for your day-to-day work or research in quantitative finance, this book is a must-have.This book will cover everything you need to know about using functional programming for quantitative finance. Using a functional programming language will enable you to concentrate more on the problem itself rather than implementation details. Tutorials and snippets are summarized into an automated trading system throughout the book.This book will introduce you to F#, using Visual Studio, and provide examples with functional programming and finance combined. The book also covers topics such as downloading, visualizing and calculating statistics from data. F# is a first class programming language for the financial domain.
Table of Contents (17 chapters)
F# for Quantitative Finance
Credits
About the Author
About the Reviewers
www.PacktPub.com
Preface
Index

Explaining functions


It's now time to look at functions, the most basic and powerful building block in F#, and any other functional programming language for that matter. Functional programming languages use functions as first class constructs, in contrast to object-oriented programming, where objects and data are first class constructs. This means that in functional programming, functions will produce data based on the input and not based on state. In object-oriented programming, the state is encapsulated into objects and passed around. Functions are declared in the same way as variables were declared previously in the preceding snippets, with let bindings. Have a look at the following code snippet:

let sum (x,y) =
	x + y
> sum (7, 7)

If you try to evaluate the first sum function using Alt + Enter, F# Interactive will respond with a function like the following line of code:

val sum : x:int -> y:int -> int

This means that sum is a function that takes two values of type int and returns a value of type int. The compiler simply knows that it's just the last type that is the return type.

let sum (x:float, y:float) =
	x + y

> sum(7.0, 7.0);;
val it : float = 14.0

Let's look at the following case where parameters of wrong types are passed to the function:

> sum(7, 7);;
...
error FS0001: This expression was expected to have type float
but here has type int

As seen in the modified version of the sum function, the types are explicitly declared as float. This is a way of telling the compiler beforehand that float is the value to be used in the function. The first version of sum used type inference to calculate the types for x and y respectively and found it to be of type int.

Learning about anonymous functions

Since it is common to create small helper functions in F# programming, F# also provides a special syntax for creating anonymous functions. These functions are sometimes called lambdas, or lambda functions. To define an anonymous function, the keyword fun is used. Have a look at the following code snippet:

let square = (fun x → x * x)
> square 2
val it : int = 4

Explaining higher-order functions

Now the square function can be used by itself or as an argument to other functions or higher-order functions. Have a look at the following square function:

let squareByFour f
	f 4
> squareByFour square

Here, the square function is passed as an argument to the function squareByFour. The function squareByFour is a higher-order function; it takes another function as an argument. Higher-order functions can take a function as an argument or return a function, or do both. This is an often used technique in functional programming to be able to construct new functions from existing functions and reuse them.

Currying

Though, currying is sometimes considered to be an advanced feature of programming languages, it makes the most sense on connection to functions and higher-order functions. The idea is not complicated at all, and once you have seen a couple of examples, the concept should be clear.

Let's look at the following sum function:

let sum x y =
	x + y

Let's assume we want to reuse the function, but we may often call it for some fixed value of x. That means we have a fixed x, let's say 2, and we vary the y parameter. Have a look at the following:

sum 2 3
sum 2 4
sum 2 5

Instead of having to write out the x parameter every time, we can make use of the concept of currying. That means we create a new function with the first parameter fixed in this case. Take a look at the following function:

let sumBy2 y = 
	sum 2 y

> sumBy2 3;;
val it : int = 5

> sumBy2 4;;
val it : int = 5

> sumBy2 5;;
val it : int = 5

We have now saved ourselves from rewriting some arguments, but this is not the main reason. It's the ability to control the parameters and reuse functionality. More about currying will be covered in later chapters, but the basics were covered here in connection to higher-order functions.

Investigating lists

Lists in F# are very useful, they are some of the most frequently used building blocks. They are the basic building blocks in functional languages and often replace the need of other types or classes. This is because the support for manipulating and creating lists and also being able to nest lists can be enough to replace custom types. You can think of lists as a sequence of values of the same type.

Lists in F# are the following:

  • A powerful way to store data

  • Immutable linked lists of values of any type

  • Often used as building blocks

  • One of the best ways to store data

This illustrates a list in F#, with a head and a tail, where each element is linked to the next.

Let's consider the following simple list of price information which are represented as floating points:

let prices = [45.0; 45.1; 44.9; 46.0]
> val prices : float list = [45.0; 45.1; 44.9; 46.0]

Suppose you want a list with values between 0 and 100, instead of writing them yourself, F# can do it for you. Take a look at the following lines of code:

let range = [0 .. 100]
val range : int list =
  [0; 1; 2; 3; 4; 5; 6; 7; 8; 9; 10; 11; 12; 13; 14; 15; 16; 17;
  18; 19; 20;21; 22; 23; 24; 25; 26; 27; 28; 29; 30; 31; 32;
  33; 34; 35; 36; 37; 38; 39; 40; 41; 42; 43; 44; 45; 46; 47;
  48; 49; 50; 51; 52; 53; 54; 55; 56; 57; 58; 59; 60; 61; 62;
  63; 64; 65; 66; 67; 68; 69; 70; 71; 72; 73; 74; 75; 76; 77;
  78; 79; 80; 81; 82; 83; 84; 85; 86; 87; 88; 89; 90; 91; 92; 
  93; 94; 95; 96; 97; 98; 99; ...]

This is fine if we just want a simple range with fixed size increments. Sometimes however, you may want to have a smaller increment, let's say 0.1, which is between 1.0 and 10.0. The following code shows how it is done:

let fineRange = [1.0 .. 0.1 .. 10.0]
val fineRange : float list =
[1.0; 1.1; 1.2; 1.3; 1.4; 1.5; 1.6; 1.7; 1.8; 1.9; 2.0; 2.1; 2.2; 2.3; 2.4; 2.5; 2.6; 2.7; 2.8; 2.9; 3.0; 3.1; 3.2; 3.3; 3.4; 3.5; 3.6; 3.7; 3.8; 3.9; 4.0; 4.1; 4.2; 4.3; 4.4; 4.5; 4.6; 4.7; 4.8; 4.9; 5.0; 5.1; 5.2; 5.3; 5.4; 5.5; 5.6; 5.7; 5.8; 5.9; 6.0; 6.1; 6.2; 6.3; 6.4; 6.5; 6.6; 6.7; 6.8; 6.9; 7.0; 7.1; 7.2; 7.3; 7.4; 7.5; 7.6; 7.7; 7.8; 7.9; 8.0; 8.1; 8.2; 8.3; 8.4; 8.5; 8.6; 8.7; 8.8; 8.9; 9.0; 9.1; 9.2; 9.3; 9.4; 9.5; 9.6; 9.7; 9.8; 9.9; 10.0]

Lists can be of any type, and type inference works here as well. Have a look at the following code:

> let myList = ["One"; "Two"; "Three"];;
val myList : string list = ["One"; "Two"; "Three"]

However, if you mix the types in a list, the compiler will get confused about the actual type used:

let myList = ["One"; "Two"; 3.0];; 
...
This expression was expected to have type
string but here has type float 

Tip

Downloading the example code

You can download the example code files for all Packt books you have purchased from your account at http://www.packtpub.com. If you purchased this book elsewhere, you can visit http://www.packtpub.com/support and register to have the files e-mailed directly to you.

Concatenating lists

Concatenating lists is useful when you want to add lists together. This is done using the @ operator. Have a look at the following code where the @ operator is used:

> let myNewList = [1;2;3] @ [4;5;6];;

val myNewList : int list = [1; 2; 3; 4; 5; 6]

> myNewList;;
val it : int list = [1; 2; 3; 4; 5; 6]

Let's have a look at some of the most commonly used functions in the List Module: Length, Head, Tail, map, and filter respectively.

The function Length will simply return the length of the list:

> myNewList.Length;;
val it : int = 6

If you want the first element of a list, use Head:

> myNewList.Head;;
val it : int = 1

The rest of the list, meaning all other elements except the Head, is defined as the Tail:

> myNewList.Tail;;
val it : int list = [2; 3; 4; 5; 6]

You can also do some more interesting things with lists, such as calculating the square of all the elements one by one. Note that it's an entirely new list returned from the map function, since lists are immutable. This is done using higher-order functions, where List.map takes a lambda function defined to return the value of x*x as seen in the following code:

> List.map (fun x -> x * x) myNewList;;
val it : int list = [1; 4; 9; 16; 25; 36]

Another interesting function is the filter function of lists, which will return a new list matching the filter criteria:

> List.filter (fun x -> x < 4) myNewList;;
val it : int list = [1; 2; 3]

Tuples

Tuples are a group of unnamed but ordered values. The values can be of different types, if needed. You can think of them as more flexible versions of the Tuple class in C#.

// Tuple of two floats
(1.0, 2.0)

// Tuple of mixed representations of numbers
(1, 2.0, 3, '4', "four")

// Tuple of expressions
(1.0 + 2.0, 3, 4 + 5)

Let's analyze the type information from the tuples in the REPL. The first tuple has the type information:

> (1.0, 2.0);;
val it : float * float = (1.0, 2.0)

The * symbol is used to separate the type elements for a tuple. It's simply a tuple of two floats. The next one is a bit more complex:

> (1, 2.0, 3, '4', "four");;
val it : int * float * int * char * string = (1, 2.0, 3, '4', "four")

But the type inference figured it out without any doubts. The last one consists of expressions:

> (1.0 + 2.0, 3, 4 + 5);;
val it : float * int * int = (3.0, 3, 9)

As you can see, the expressions are evaluated before the type data is analyzed. It may be useful to extract the values from a tuple, this can be done using simple patterns:

let (a, b) = (1.0, 2.0)
printfn "%f %f" a b

If you are not interested in the first value, use the wildcard character (the underscore) to simply ignore it. The wildcard is used throughout F#, for example, in pattern matching, which will be introduced in the next chapter.

let (_, b) = (1.0, 2.0)
printfn "only b %2.2f" b

The pipe operator

The pipe operator is used a lot and it's defined as a function which takes the values on the left-hand side of the operator and applies them to the function on the right-hand side. There is another version of the pipe operator with various numbers of arguments, and more about them will be covered later.

The pipe-forward operator (|>) is the most common pipe operator:

[0..100]|> List.filter (fun x -> x % 2 = 0)|> List.map (fun x -> x * 2)|> List.sum

This snippet first creates a list from 0 to 100, as illustrated in the section about lists previously. Then, the list is piped to the filter function with a conditional lambda function. Every even value in the list gets passed on to the next function. The map function will execute the lambda function to square every number. Finally, all numbers are summed, with the result of:

val it : int = 5100