F# Net Present Value; List.Fold, Head,Tail Recursion

Today's problem is to calculate the present value of an investment stream.

Suppose you had to pay $1,000 for an investment that returns the following cash flow over its life:

End of Year  1:  $100.00
End of Year  2:  $120.00
End of Year  3:  $125.00
End of Year  4:  $150.00
End of Year  5:  $180.00
End of Year  6:  $200.00
End of Year  7:  $220.00
End of Year  8:  $250.00
End of Year  9:  $290.00
End of Year 10:  $300.00

If we use a discount rate of 10%, what is the present value of the cash flow?

For those unfamiliar with present value, the math behind the calculation is:

PV = -1,000 + 100/(1.1^1) + 120/(1.1^2) + 125/(1.1^3) + 150/(1.1^4) + 180/(1.1^5) + 200/(1.1^6) + 220/(1.1^7) + 250/(1.1^8) + 290/(1.1^9)+ 300/(1.1^10) 

The present value equals the sum of all the flows in each period "discounted" by the interest rate raised to the power n, where n is the number of years from  present.

This is an interesting problem in F# because it let's us explore recursion, the cons operator, and the fold function.

In F#, I find that the approach to solving a problem starts with the littlest details and working back up to the surface.

-------------------------------------------------------

#light
open System
 
let vals = [-1000.0; 100.0; 120.0; 125.0; 150.0; 180.0; 200.0; 220.0; 250.0; 290.0; 300.0]

let pv (i : float) (n : float) =
     1.0 / Math.Pow( (1.0 + i ), n)

let npv v i n =
    v * (pv i n)

-------------------------------------------------------

The vals List is our investment stream

The function pv takes i as the annual interest rate and n as the period and calculates the value of $1.0 discounted back n years.

The function npv takes a value v (say $100) and multiplies it the present value of $1 discounted back to present.

As you can see, the problem now is just to apply the npv function to each item in our vals List and them add them up.

Piece of cake.

The following code snippet is a recursive function that takes our vals list as input and iterates over it to create a new list, where each item in the new list is the item in the vals list discounted by the interest rate over the appropriate number of periods:

let rec valList (aList : List<float>) (ir : float) (n : float) =
    match aList with
    | [] -> []
    | h::t -> npv h ir n :: valList t ir (n+1.0)

The parameters are:
aList : List<float> - Our List of vals
ir : float - the interest rate
n : float - period counter.  Initially pass in with a value of 0.0

The match statement says match the vals list against (1) an empty List (as indicated by []) or (2) ??? what the devil is h::t?

We know that h::t uses the 'cons' operator '::' to prepend a value to the head of a list.  So, the F# compiler sees the pattern h::t which is specifically referred to as the 'Cons' pattern.  Any List will match a 'Cons' pattern because all Lists have a head and a tail.  The interesting thing here is that F# makes the match and then automatically fills your variables for the head (h) and tail (t) with those values from the incoming list.  Bizarre, I know, but that's the language.

Here http://msdn.microsoft.com/en-us/library/dd547125(VS.100).aspx is a really good reference on pattern matching.

So, in our statement:

    | h::t -> npv h ir n :: valList t ir (n+1.0)

The match is made and h and t are filled in with the values for head and tail of our list aList.

We see on the return side of the statement two expressions connected with another cons operator.  Again, this says take the value of left side expression (whatever that is) and prepend it to the List on the right.

The left expression:

npv h ir n

returns the present value (from the function npv) for the first entry in the list (h), using the interest rate ir, for the period n.  Now, for the first item on the list, n will be zero.  Therefore, the first item is not discounted.  In our example, the first entry is negative $1,000, so the npv function just returns -$1,000.

The right expression:

valList t ir (n+1.0)

makes a recursive call to our valList function, passing in the tail (remaining entries) of the current list, the interest rate ir, and the value of n+1 for the number of periods.  Here is where we increment the period counter so that on the second call, the next list value will be discounted one more period.

In our case, the second value is $100.  Thus, the second call to the valList function calculates the value

npv h ir n

as equal to: $100 / (1.1 ^ 1) which equals 90.9090...

We then add it to the return list.  We then call varList again, where the head of the tail is now the third entry in vals and the period n is set to 2.

We keep iterating, until we have reached the end of the list.  Ultimately what we return is a new List, where each entry in our original values List has been discounted by our input interest rate over the relevant number of periods.

The next chore is trivial - just add up the new list.

We could do this:

let aList = valList vals 0.10 0.0

let ret0 = List.fold(+)0.0 aList

First, apply varList to our vals list, using an interest rate of 10%.  And then, use the function 'List.fold' to add up the numbers in the list.

Now a Digression

List.fold is a method of the List module is generally used to reduce a List into a single value.  The big question is how do we reduce a List into a single value?  The simplest method is to add it up, but the reduction could be performed using any rule.

The general format of the List.fold method is:

List.fold(someFunction) initialValue someList 

The expression:

List.fold(+)0.0 aList

is interpreted as such:

1.  Apply the function addition using as input parameters the current (initial) value and the first element on the list.  Return the value into the current value.

2.  Use the new current value and the second element on the list as the new as input parameters.

3.  Continue to the end of the list.

So, if we had the List:

10, 30, 60

List.fold(+)0.0 would produce the sequence:

0 + 10 = 10
10 + 30 = 40
40 + 60 = 100

and 100 would be our result.

The cool thing is though, we don't have to use addition, but any function that takes two inputs and returns a value

So, if we have a function:

let aFunc x y =
    x/100.0+y

We can write:

List.fold(aFunc)0.0

Note: the first argument will always be the current (or initial) value; the second argument will be the next item in the List.

So, the above would yield:

(0/100) + 10 = 10
(10/100) + 30 = 30.1
(30.1/100) + 60 = 60.301

and 60.301 would be our result.

Back to the Show

So we have seen that

let ret0 = List.fold(+)0.0 aList

will add up our list of discounted values and return them in out final result ret0.

But, ultimately what I want is just a function that I can can with a List and a discount rate and return a present value.  Here is what I have come up with:

let presentValue (vals : List<float>) (ir : float) =
    List.fold(+)0.0 <| valList vals ir 0.0

This function just collapses the logic into one function called presentValue.

In the snippet above the '<|' operator passes the result of

valList vals ir 0.0

into the List.fold method, thereby skipping the creation of an intermediate List.

Now, I have what I want.  I can now call my function in an intelligible fashion:

let ret1 = presentValue vals 0.10

I can now get my present value with no hassle (returned in ret1).  The next thing to do is carve out all my code, put it into a math module and stop worrying about the ugly details.

Here the full program:

#light
open System
open System.Collections.Generic
open System.IO

let vals = [-1000.0; 100.0; 120.0; 125.0; 150.0; 180.0; 200.0; 220.0; 250.0; 290.0; 300.0]

let pv (i : float) (n : float) =
     1.0 / Math.Pow( (1.0 + i ), n)

let npv x i n =
    x * (pv i n)

let rec valList aList (ir : float) (n : float) =
    match aList with
    | [] -> []
    | h::t -> npv h ir n :: valList t ir (n+1.0)

let presentValue vals (ir : float) =
    List.fold(+)0.0 <| valList vals ir 0.0

let ret1 = presentValue vals 0.12

 

Print | posted @ Thursday, July 09, 2009 11:54 AM

Comments on this entry:

Gravatar # Your content is really useful
by dress at 7/15/2010 2:25 AM

2010 new styles A-line Wedding Dresses,Beach Wedding Dresses,Evening Dresses,Prom Dresses on sale
evening dresses
Prom dresses
wedding dresses
woman's dresses and dresses on this site
  
Gravatar # re: F# Net Present Value; List.Fold, Head,Tail Recursion
by deexu at 7/16/2010 1:40 AM

great range of Ed Hardy products. Ed Hardy Women's Ellerise Lowrise Sneaker · Ed Hardy Women's
ed hardy jeans, ed hardy hoody, ed hardy shirt, ed hardy clothing, ed hardy cap, ed glasses, ed belts,
women fashion shoes, men's clothes. helping .perhaps you will like
Ed Hardy
Ed Hardy shoes
Ed Hardy shirts
Ed Hardy clothes
Ed Hardy clothing
Ed Hardy shoes
Don Ed Hardy is an American tattoo collector raised in Southern California
Ed Hardy Clothing,Christian Audigier,Ed Hardy Shoes,Ed Hardy Swimwear,Ed Hardy Hat,
ED Hardy Caps
Ed Hardy Sunglasses
Ed Hardy Wallets
EdHardy
Gucci outlet store online, numerous cheap Gucci bags, handbags, wallets, purses, totes, shoes on sale,
cheap prices and authentic qualities
gucci handbags
gucci jewelryRHBTRGBNKIO
  
Gravatar # re: F# Net Present Value; List.Fold, Head,Tail Recursion
by Anhar at 7/16/2010 2:47 AM

just looking at the first calculation I did the following:

let data = [100.0; 120.0; 125.0; 150.0; 180.0; 200.0; 220.0; 250.0; 290.0; 300.0]

let rec pow n x =
match n with
| 0 -> 1.
| n -> x * pow (n - 1) x

let fv = [for i in 1..data.Length do yield pow (i) 1.1 |> (fun x -> data.[i-1]/x) ] |> Seq.sum |> (fun x -> x-1000.0)

let ans = printf "%A" fv

I'm sure this could be easily turned more generic
  
Gravatar # shi
by fiwedding at 7/23/2010 3:13 AM

supply in stock and custom lace front wigs, full lace wigs, lace wigs, human hair wigs,
remy lace front wigs, cheap wigs, cheap, buy, celebrity
full lace wigs
lace wigs
lace wigs sale
lace front wigs
synthetic front lace wigs
A Famous Dresses Shop which sell directly Wedding Dresses, Evening Dress, Bridesmaid Dresses,Prom dresses
cheap wedding dresses
cheap evening dresses
cheap prom dresses
cheap evening dresses
cheap prom dresses
Elegant evening dresses are always associated with the brides and their bridesmaids.Shopping for evening dresses and your wedding dress in stylish bridal ......
  
Gravatar # re: F# Net Present Value; List.Fold, Head,Tail Recursion
by lv handbags at 7/24/2010 7:14 AM

Taiga Leather is a world leading brand name in the fashion industry. louis vuitton wallets for men A Taiga Leather is not only a sign of taste and fashion; it is also a symbol of social status and recognition. At our website the quality of handbag has reached the highest level of perfection and it comes at a very attractive price. Louis Vuitton Handbags are inspired by louis vuitton mens wallets the highly popular designs of their original counterparts.
  
Gravatar # re: F# Net Present Value; List.Fold, Head,Tail Recursion
by ckangelk3 at 7/31/2010 12:23 AM

Tiffany jewelry
mous Tiffany Jewelry Shop which sell directly Tiffany Rings, Earrings, Necklaces, Pendants, Bracelets,
Bangles, Accessories.
Tiffany co jewelry
Tiffany
Tiffany Bracelets
affordable tiffany jewelry, beautiful discount tiffany rings, tiffany necklaces,tiffany Pendants,
tiffany earrings and tiffany Bracelets.
Tiffany Charms
Tiffany Earrings
Tiffany Necklaces
Tiffany Rings
Tiffany Jewelry ,Discount Tiffany & Co Jewelry On Sale,you can buy cheap Tiffany silver.
All jewelry come with Tiffany package
links of london
links london
links of london jewellery

  
Gravatar # re: F# Net Present Value; List.Fold, Head,Tail Recursion
by lily at 8/4/2010 7:33 PM

Adidas is a popular footwear company that manufactures a variety of athletic boots. Adidas City Series designed for hiking, boxing and outdoor winter sports. Mens Adidas Shoes are made of heavy leather, canvas and wool components, along with heavy-duty rubber soles. The fabrics are waterproof, which helps them keep feet warm and dry. Adidas Shoes are very durable and for the most part are resistant to stains and residue, but over time buildup can accumulate on the boots, detracting from their appearance.
  
Gravatar # re: F# Net Present Value; List.Fold, Head,Tail Recursion
by cheap handbag at 8/28/2010 7:27 AM

Adidas is a popular footwear company that manufactures a variety of athletic bootsAdidas is a popular footwear company that manufactures a variety of athletic boots
  
Gravatar # Nike Air Jordan
by Nike Air Jordan at 9/1/2010 6:30 PM

Expect these at retail in June and stick with Sneaker News for updates.
  
Gravatar # timberland shoe company
by timberland for you at 9/1/2010 8:16 PM

On a certain cheap timberland boots day at a certain hour, we will pull into the station. Bands will be playing and flags discount timberland boots waving. Once we get there, so many wonderful timberland winter boots dreams will come true and the pieces of our lives will fit together like a completed jigsaw puzzle. How restlessly we pace the aisles, womens timberland boot the minutes for loitering --waiting, waiting, waiting for the station.But uppermost in our timberland shoes store minds is the final destination. On a certain day at a certain hour, we will pull into the station. Bands will be playing and timberland eye boat flags waving. Tucked away in our timberland for you subconscious is an idyllic vision. We see ourselves on a long trip that timberland 6 inch spans the continent. We are traveling by train. Out timberland hiking boots windows, we drink in the passing scene of cars on nearby highways, of children timberland shoe company waving at a crossing, of cattle grazing on a distant timberland boots hillside, of smoke pouring from a power plant, of row upon row of corn and wheat, of flatlands and timberland wheat shoes valleys, of mountains and rolling classic 3 eye timberland boat hillsides, of city skylines and village halls.But uppermost in our black timberland boots minds is the final destination.
  
Gravatar # re: F# Net Present Value; List.Fold, Head,Tail Recursion
by nannan at 9/3/2010 12:31 AM

MYGRT TVRT Tiffany jewellery
Tiffany
Tiffany & Co
Tiffany Co Bracelets
I came across a story in the WSJ last week (WSJ August 13th) in which some major food companies were warning of a sugar shortage in the US. Excuse me. A sugar shortage? I'm not making this up. Here's the text of the letter
Tiffany Co Charms
Tiffany Co Earrings
Tiffany sale
Tiffany Co Necklaces
Tiffany uk
Tiffany Co Rings
tiffany jewelry
tiffany co
  

Your comment:

Title:
Name:
Email:
Website:
 
Italic Underline Blockquote Hyperlink
 
 
Please add 1 and 3 and type the answer here: