<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DZone Snippets: FV code</title>
    <link>http://snippets.dzone.com/posts</link>
    <pubDate>Mon, 08 Sep 2008 03:31:17 GMT</pubDate>
    <description>DZone Snippets: FV code</description>
    <item>
      <title>financial functions</title>
      <link>http://snippets.dzone.com/posts/show/1143</link>
      <description>&lt;code&gt;&lt;br /&gt;REBOL [&lt;br /&gt;   Title:   "Financial Library"&lt;br /&gt;   Date:    17-Apr-2002&lt;br /&gt;   Name:    'fin&lt;br /&gt;   Version: 0.0.2&lt;br /&gt;   File:    %fin.r&lt;br /&gt;   ;Home:    http://www.pointillistic.com/&lt;br /&gt;   Author:  "Gregg Irwin"&lt;br /&gt;   Email:   gregg@pointillistic.com&lt;br /&gt;   ;Owner:   "Pointillistic Software"&lt;br /&gt;   ;Rights:  "Copyright &#169; Pointillistic Software 2002. All Rights Reserved."&lt;br /&gt;   ;Tabs:    4&lt;br /&gt;   ;Need:    0.1.4&lt;br /&gt;   ;Language: 'English&lt;br /&gt;   ;Charset:  'ANSI&lt;br /&gt;   ;Category: [script 1]&lt;br /&gt;   Purpose: {Financial module for standard library.}&lt;br /&gt;&lt;br /&gt;   Comment: {Prototype stage.}&lt;br /&gt;&lt;br /&gt;   History: [&lt;br /&gt;      0.0.1 [13-Mar-2002 "First whack" "Gregg"]&lt;br /&gt;      0.0.2 [17-Apr-2002 {Added NPV and a functional, if ugly, IRR.&lt;br /&gt;      BRACKET-FN supports IRR.} "Gregg"]&lt;br /&gt;   ]&lt;br /&gt;&lt;br /&gt;   Example: {do %fin.r}&lt;br /&gt;]&lt;br /&gt;&lt;br /&gt;fin: make lib-kernel [&lt;br /&gt;&lt;br /&gt;    ; Future Value&lt;br /&gt;    fv: func [&lt;br /&gt;        {Computes future value based on present value.}&lt;br /&gt;        value   [number! money!] "Present value"&lt;br /&gt;        rate    [number!] "Interest Rate"&lt;br /&gt;        periods [number!] "Number of time periods"&lt;br /&gt;    ][&lt;br /&gt;        1 + rate ** periods * value&lt;br /&gt;    ]&lt;br /&gt;    ;lib/fin/fv 1000 .1 12&lt;br /&gt;    ;lib/fin/fv 1000 .1 24&lt;br /&gt;    ;lib/fin/fv 1000 .1 36&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;    ; Compound Interest&lt;br /&gt;    interest: func [&lt;br /&gt;        {Computes accumulated compound interest.}&lt;br /&gt;        value   [number! money!] "Present value"&lt;br /&gt;        rate    [number!] "Interest Rate"&lt;br /&gt;        periods [number!] "Number of time periods"&lt;br /&gt;    ][&lt;br /&gt;        1 + rate ** periods - 1 * value&lt;br /&gt;    ]&lt;br /&gt;    ;lib/fin/interest 1000 .1 12&lt;br /&gt;    ;lib/fin/interest 1000 .1 24&lt;br /&gt;    ;lib/fin/interest 1000 .1 36&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;    ; Interest Rate&lt;br /&gt;    rate: func [&lt;br /&gt;        {Computes interest rate for a given future value.}&lt;br /&gt;        value        [number! money!] "Present value"&lt;br /&gt;        future-value [number! money!] "Future value"&lt;br /&gt;        periods      [number!] "Number of time periods"&lt;br /&gt;    ][&lt;br /&gt;        future-value / value ** (1 / periods) - 1&lt;br /&gt;    ]&lt;br /&gt;    ;lib/fin/rate 1000 future-value 1000 .1 12 12&lt;br /&gt;    ;lib/fin/rate 1000 future-value 1000 .1 24 24&lt;br /&gt;    ;lib/fin/rate 1000 future-value 1000 .1 36 36&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;    ; Present Value&lt;br /&gt;    pv: func [&lt;br /&gt;        {Computes present value based on future value.}&lt;br /&gt;        value   [number! money!] "Future value"&lt;br /&gt;        rate    [number!] "Interest Rate"&lt;br /&gt;        periods [number!] "Number of time periods"&lt;br /&gt;    ][&lt;br /&gt;        1 + rate ** (negate periods) * value&lt;br /&gt;        ; - or -&lt;br /&gt;        ;value / (1 + rate ** periods)&lt;br /&gt;    ]&lt;br /&gt;    ;lib/fin/pv future-value 1000 .1 12 .1 12&lt;br /&gt;    ;lib/fin/pv future-value 1000 .1 24 .1 24&lt;br /&gt;    ;lib/fin/pv future-value 1000 .1 36 .1 36&lt;br /&gt;&lt;br /&gt;    npv: func [&lt;br /&gt;        {Computes net present value based on future cash flow values&lt;br /&gt;        using continuous discounting.}&lt;br /&gt;        values  [any-block!] "Cash flow values"&lt;br /&gt;        rate    [number!] "Interest Rate"&lt;br /&gt;        /local result&lt;br /&gt;    ][&lt;br /&gt;        result: $0.0&lt;br /&gt;        repeat i length? values [&lt;br /&gt;            result: result + pv values/:i rate i&lt;br /&gt;        ]&lt;br /&gt;        result&lt;br /&gt;    ]&lt;br /&gt;    ;lib/fin/npv [1000 2000 3000] .1&lt;br /&gt;    ;lib/fin/npv [-10000, 3000, 4200, 6800] .1&lt;br /&gt;&lt;br /&gt;    ;[-$70'000 $12'000 $15'000 $18'000 $21'000 $26'000]&lt;br /&gt;&lt;br /&gt;    ; Time Periods&lt;br /&gt;    nper: func [&lt;br /&gt;        {Computes the number of time periods from the present value&lt;br /&gt;        to a given future value.}&lt;br /&gt;        value        [number! money!] "Present value"&lt;br /&gt;        future-value [number! money!] "Future value"&lt;br /&gt;        rate         [number!] "Interest Rate"&lt;br /&gt;    ][&lt;br /&gt;        ; 2 versions. Both work.&lt;br /&gt;        (log-e (future-value / value)) / (log-e (rate + 1))&lt;br /&gt;        ;divide log-e divide future-value value  log-e add rate 1&lt;br /&gt;    ]&lt;br /&gt;    ;lib/fin/nper 1000 future-value 1000 .1 12 .1&lt;br /&gt;    ;lib/fin/nper 1000 future-value 1000 .1 24 .1&lt;br /&gt;    ;lib/fin/nper 1000 future-value 1000 .1 36 .1&lt;br /&gt;&lt;br /&gt;    irr: func [&lt;br /&gt;        {Computes the internal rate of return based on future cash flow values.&lt;br /&gt;        The internal rate of return of a cash flow is the interest rate that&lt;br /&gt;        makes the present value of a cash flow equal to zero. THIS IS A QUICKLY&lt;br /&gt;        HACKED VERSION AND NEEDS TO BE CLEANED UP! HERE FOR TESTING.}&lt;br /&gt;        values  [any-block!] "Cash flow values"&lt;br /&gt;        /guess&lt;br /&gt;            guess-val&lt;br /&gt;        /local rates rate npv-result result&lt;br /&gt;    ][&lt;br /&gt;        tries: 50&lt;br /&gt;        ACCURACY: $.000001&lt;br /&gt;        range: none&lt;br /&gt;        rtb: dx: x-mid: 0.0&lt;br /&gt;        f-mid: $0&lt;br /&gt;&lt;br /&gt;        if not guess [guess-val: .2]&lt;br /&gt;&lt;br /&gt;        if range: bracket-fn :npv values 0 guess-val [&lt;br /&gt;            either ((npv values range/1) &lt; $0) [&lt;br /&gt;                rtb: range/1&lt;br /&gt;                dx:  range/2 - range/1&lt;br /&gt;            ][&lt;br /&gt;                rtb: range/2&lt;br /&gt;                dx:  range/1 - range/2&lt;br /&gt;            ]&lt;br /&gt;            loop tries [&lt;br /&gt;            	dx: dx * 0.5&lt;br /&gt;            	x-mid: rtb + dx&lt;br /&gt;            	f-mid: npv values x-mid&lt;br /&gt;            	if (f-mid &lt;= $0) [rtb: x-mid]&lt;br /&gt;            	if any [&lt;br /&gt;                    (abs f-mid &lt; ACCURACY)&lt;br /&gt;                    (abs dx &lt; second ACCURACY)&lt;br /&gt;                ] [return x-mid]&lt;br /&gt;            ]&lt;br /&gt;            return none&lt;br /&gt;        ]&lt;br /&gt;    ]&lt;br /&gt;&lt;br /&gt;    bracket-fn: func [&lt;br /&gt;        {Adapted from Numerical Recipes. Given a user supplied function and a&lt;br /&gt;        given 'guess' range (x1 to x2) it expands the range geometrically until&lt;br /&gt;        a root is bracketed by the returned values x1 and x2, in which case&lt;br /&gt;        the range is returned as a block of those two values. If it doesn't&lt;br /&gt;        succeed after 50 tries, it returns false. This was built to support&lt;br /&gt;        IRR so it's designed to call NPV, which takes one arg. It should be&lt;br /&gt;        generalized.}&lt;br /&gt;        fn arg x1 x2&lt;br /&gt;        /local factor tries f1 f2&lt;br /&gt;    ][&lt;br /&gt;        tries: 50&lt;br /&gt;        factor: 1.6&lt;br /&gt;        f1: fn arg x1&lt;br /&gt;        f2: fn arg x2&lt;br /&gt;        loop tries [&lt;br /&gt;            ; We have to use SECOND on f2 because it's a money! value&lt;br /&gt;            ; and the numeric component is returned by SECOND.&lt;br /&gt;            if negative? multiply f1 second f2 [&lt;br /&gt;                return reduce [x1 x2]&lt;br /&gt;            ]&lt;br /&gt;            either (abs f1) &lt; (abs f2) [&lt;br /&gt;                x1: x1 + (factor * (x1 - x2))&lt;br /&gt;                f1: fn arg x1&lt;br /&gt;            ][&lt;br /&gt;                x2: x2 + (factor * (x2 - x1))&lt;br /&gt;                f2: fn arg x2&lt;br /&gt;            ]&lt;br /&gt;        ]&lt;br /&gt;        false&lt;br /&gt;    ]&lt;br /&gt;    ;bracket-fn get in lib/fin 'npv values 0 .2&lt;br /&gt;    ;values: [-$70'000 $12'000 $15'000 $18'000 $21'000 $26'000]&lt;br /&gt;    ;lib/fin/irr values&lt;br /&gt;    ;lib/fin/irr copy/part values 5&lt;br /&gt;    ;lib/fin/irr copy/part values 3&lt;br /&gt;    ;lib/fin/irr/guess copy/part values 3 -.1&lt;br /&gt;    ;values: [-10 1.8 1.8 1.8 1.8 1.8 1.8 1.8 2.8]&lt;br /&gt;    ;lib/fin/irr values&lt;br /&gt;    ;values: [0 -1073 -1459 -1364 -1247 -1110 31789]&lt;br /&gt;    ;lib/fin/irr values&lt;br /&gt;&lt;br /&gt;;     irr: func [&lt;br /&gt;;         {Computes the internal rate of return based on future cash flow values.&lt;br /&gt;;         The internal rate of return of a cash flow is the interest rate that&lt;br /&gt;;         makes the present value of a cash flow equal to zero. THIS IS A QUICKLY&lt;br /&gt;;         HACKED VERSION AND NEEDS TO BE CLEANED UP! HERE FOR TESTING.}&lt;br /&gt;;         values  [any-block!] "Cash flow values"&lt;br /&gt;;         /guess&lt;br /&gt;;             guess-val&lt;br /&gt;;         /local rates rate npv-result result&lt;br /&gt;;     ][&lt;br /&gt;;         ACCURACY: $.000001&lt;br /&gt;;         tries: 50&lt;br /&gt;;         range: none&lt;br /&gt;;         rtb: dx: x-mid: 0.0&lt;br /&gt;;         f-mid: $0&lt;br /&gt;;         if not guess [guess-val: .2]&lt;br /&gt;;         if range: bracket-fn :npv values 0 guess-val [&lt;br /&gt;;             f: npv values range/1&lt;br /&gt;;             either (f &lt; $0) [&lt;br /&gt;;                 rtb: range/1&lt;br /&gt;;                 dx: range/2 - range/1&lt;br /&gt;;             ][&lt;br /&gt;;                 rtb: range/2&lt;br /&gt;;                 dx: range/1 - range/2&lt;br /&gt;;             ]&lt;br /&gt;;             loop tries [&lt;br /&gt;;             	dx: dx * 0.5&lt;br /&gt;;             	x-mid: rtb + dx&lt;br /&gt;;             	f-mid: npv values x-mid&lt;br /&gt;;             	if (f-mid &lt;= $0) [rtb: x-mid]&lt;br /&gt;;             	if any [&lt;br /&gt;;                     ((abs f-mid) &lt; ACCURACY)&lt;br /&gt;;                     ((abs dx) &lt; (second ACCURACY))&lt;br /&gt;;                 ] [return x-mid]&lt;br /&gt;;             ]&lt;br /&gt;;             return none&lt;br /&gt;;         ]&lt;br /&gt;;     ]&lt;br /&gt;;&lt;br /&gt;;     bracket-fn: func [&lt;br /&gt;;         {Adapted from Numerical Recipes. Given a user supplied function and a&lt;br /&gt;;         given 'guess' range (x1 to x2) it expands the range geometrically until&lt;br /&gt;;         a root is bracketed by the returned values x1 and x2, in which case&lt;br /&gt;;         the range is returned as a block of those two values. If it doesn't&lt;br /&gt;;         succeed after 50 tries, it returns false. This was built to support&lt;br /&gt;;         IRR so it's designed to call NPV, which takes one arg. It should be&lt;br /&gt;;         generalized.}&lt;br /&gt;;         fn arg x1 x2&lt;br /&gt;;         /local factor tries f1 f2&lt;br /&gt;;     ][&lt;br /&gt;;         tries: 50&lt;br /&gt;;         factor: 1.6&lt;br /&gt;;         f1: fn arg x1&lt;br /&gt;;         f2: fn arg x2&lt;br /&gt;;         loop tries [&lt;br /&gt;;             ; We have to use SECOND on f2 because it's a money! value&lt;br /&gt;;             ; and the numeric component is returned by SECOND.&lt;br /&gt;;             if negative? multiply f1 second f2 [&lt;br /&gt;;                 return reduce [x1 x2]&lt;br /&gt;;             ]&lt;br /&gt;;             either (abs f1) &lt; (abs f2) [&lt;br /&gt;;                 x1: x1 + (factor * (x1 - x2))&lt;br /&gt;;                 f1: fn arg x1&lt;br /&gt;;             ][&lt;br /&gt;;                 x2: x2 + (factor * (x2 - x1))&lt;br /&gt;;                 f2: fn arg x2&lt;br /&gt;;             ]&lt;br /&gt;;         ]&lt;br /&gt;;         false&lt;br /&gt;;     ]&lt;br /&gt;&lt;br /&gt;]&lt;br /&gt;&lt;/code&gt;</description>
      <pubDate>Fri, 13 Jan 2006 04:05:22 GMT</pubDate>
      <guid>http://snippets.dzone.com/posts/show/1143</guid>
      <author>gregg.irwin (Gregg Irwin)</author>
    </item>
  </channel>
</rss>
