We are going to deal with a simple but common situation in finance - if I have a contract where I am going to receive $100 dollars in 3 years time what is that 'contract' worth to me now. How much would I pay to obtain that contract? In order to calculate the worth we need to consider what else I would do with the money and the most obvious action is to deposit it into a bank account that attracts interest.

The question is reposed then as: if I put x into a bank account then what is x if the final amount after 3 years is $100. This is easy if the interest is fixed, not so easy if it varies.

This blogpiece will provide a fragment of the implementation of HWFC that answers the above.

As this is literate Haskell some preliminaries:

> module Main where

>

> import Probability

HWFC introduces the concept of a value process which is a function from time to a random variable. We shall equate a random variable with a probability distribution and a definition of a value process is:

> type PR a = Int -> Dist a

For our interest rate model let us say that from year to the next the interest rate can either stay the same, increase by 1% or decrease by 1% all with equal likelihood. We can express this as:

> interest :: Floating a => a -> PR a

> interest i n = (n *. one) i where one start = uniform [start+1/100,start,start-1/100]

The *. function allows us to repeat a random process n times. The process here is to start with an interest rate and to move to the next years rate.

If this year the rate is 10%, after a couple of years the distribution looks like:

interest 10 2

10.0 33.3%

9.99 22.2%

10.01 22.2%

9.98 11.1%

10.02 11.1%

Let us put that to one side and look at the contracts side of things. I will short circuit the approach in the paper and dive directly into the valuation

> data Obs a = O { evalObs :: PR a }

>

> konst k = O (\t -> certainly k)

> lift f (O pr) = O (\t -> fmap f (pr t))

> lift2 f (O pr1) (O pr2) = O (\t -> joinWith f (pr1 t) (pr2 t))

> date = O (\t -> certainly t)

>

> data Contract = C { evalContract :: PR Float }

> cconst k = C $ \ _ -> certainly k

> when o c = C $ disc (evalObs o) (evalContract c)

>

>

> at t = lift2 (==) date (konst t)

> zcb t x = when (at t) x

>

> whenFirstTrue :: PR Bool -> Int

> whenFirstTrue prb = f 0 where f i = if prb i == certainly True then i else f (i+1)

>

> baseRate = 10

This is a value process such that if when the first argument is true, return the second otherwise calculated the discounted value of the first argument.

> disc :: PR Bool -> PR Float -> PR Float

> disc prb prd t = if prb t == certainly True then prd t else let s = prd t

> t' = whenFirstTrue prb

> in discount baseRate s (t'-t)

>

> discount :: Floating a => a -> Dist a -> PR a

> discount int final time = let intspread = interest int time

> in joinWith (\i s -> s / (1+i/100)) intspread final

>

Lets start with a trivial example to make sure that things are working as planned

> ex1 = cconst 100

The value of this contract, as a random variable, is:

evalContract ex1 0

100.0 100.0

> ex2 = zcb 3 (cconst 100)

The value of this contact is:

evalContract ex2 0

90.90909 25.9%

90.900826 22.2%

90.91736 22.2%

90.89256 11.1%

90.92562 11.1%

90.88431 3.7%

90.93389 3.7%

The PFP library has a function to provide the expected value which can be ask of a distribution. The expected value of our contract is:

expected $ evalContract ex2 0

90.9091