Never been to DZone Snippets before?

Snippets is a public source code repository. Easily build up your personal collection of code snippets, categorize them with tags / keywords, and share them with the world

« Newer Snippets
Older Snippets »
Showing 1-1 of 1 total  RSS 

financial functions

   1  
   2  REBOL [
   3     Title:   "Financial Library"
   4     Date:    17-Apr-2002
   5     Name:    'fin
   6     Version: 0.0.2
   7     File:    %fin.r
   8     ;Home:    http://www.pointillistic.com/
   9     Author:  "Gregg Irwin"
  10     Email:   gregg@pointillistic.com
  11     ;Owner:   "Pointillistic Software"
  12     ;Rights:  "Copyright © Pointillistic Software 2002. All Rights Reserved."
  13     ;Tabs:    4
  14     ;Need:    0.1.4
  15     ;Language: 'English
  16     ;Charset:  'ANSI
  17     ;Category: [script 1]
  18     Purpose: {Financial module for standard library.}
  19  
  20     Comment: {Prototype stage.}
  21  
  22     History: [
  23        0.0.1 [13-Mar-2002 "First whack" "Gregg"]
  24        0.0.2 [17-Apr-2002 {Added NPV and a functional, if ugly, IRR.
  25        BRACKET-FN supports IRR.} "Gregg"]
  26     ]
  27  
  28     Example: {do %fin.r}
  29  ]
  30  
  31  fin: make lib-kernel [
  32  
  33      ; Future Value
  34      fv: func [
  35          {Computes future value based on present value.}
  36          value   [number! money!] "Present value"
  37          rate    [number!] "Interest Rate"
  38          periods [number!] "Number of time periods"
  39      ][
  40          1 + rate ** periods * value
  41      ]
  42      ;lib/fin/fv 1000 .1 12
  43      ;lib/fin/fv 1000 .1 24
  44      ;lib/fin/fv 1000 .1 36
  45  
  46  
  47      ; Compound Interest
  48      interest: func [
  49          {Computes accumulated compound interest.}
  50          value   [number! money!] "Present value"
  51          rate    [number!] "Interest Rate"
  52          periods [number!] "Number of time periods"
  53      ][
  54          1 + rate ** periods - 1 * value
  55      ]
  56      ;lib/fin/interest 1000 .1 12
  57      ;lib/fin/interest 1000 .1 24
  58      ;lib/fin/interest 1000 .1 36
  59  
  60  
  61      ; Interest Rate
  62      rate: func [
  63          {Computes interest rate for a given future value.}
  64          value        [number! money!] "Present value"
  65          future-value [number! money!] "Future value"
  66          periods      [number!] "Number of time periods"
  67      ][
  68          future-value / value ** (1 / periods) - 1
  69      ]
  70      ;lib/fin/rate 1000 future-value 1000 .1 12 12
  71      ;lib/fin/rate 1000 future-value 1000 .1 24 24
  72      ;lib/fin/rate 1000 future-value 1000 .1 36 36
  73  
  74  
  75      ; Present Value
  76      pv: func [
  77          {Computes present value based on future value.}
  78          value   [number! money!] "Future value"
  79          rate    [number!] "Interest Rate"
  80          periods [number!] "Number of time periods"
  81      ][
  82          1 + rate ** (negate periods) * value
  83          ; - or -
  84          ;value / (1 + rate ** periods)
  85      ]
  86      ;lib/fin/pv future-value 1000 .1 12 .1 12
  87      ;lib/fin/pv future-value 1000 .1 24 .1 24
  88      ;lib/fin/pv future-value 1000 .1 36 .1 36
  89  
  90      npv: func [
  91          {Computes net present value based on future cash flow values
  92          using continuous discounting.}
  93          values  [any-block!] "Cash flow values"
  94          rate    [number!] "Interest Rate"
  95          /local result
  96      ][
  97          result: $0.0
  98          repeat i length? values [
  99              result: result + pv values/:i rate i
 100          ]
 101          result
 102      ]
 103      ;lib/fin/npv [1000 2000 3000] .1
 104      ;lib/fin/npv [-10000, 3000, 4200, 6800] .1
 105  
 106      ;[-$70'000 $12'000 $15'000 $18'000 $21'000 $26'000]
 107  
 108      ; Time Periods
 109      nper: func [
 110          {Computes the number of time periods from the present value
 111          to a given future value.}
 112          value        [number! money!] "Present value"
 113          future-value [number! money!] "Future value"
 114          rate         [number!] "Interest Rate"
 115      ][
 116          ; 2 versions. Both work.
 117          (log-e (future-value / value)) / (log-e (rate + 1))
 118          ;divide log-e divide future-value value  log-e add rate 1
 119      ]
 120      ;lib/fin/nper 1000 future-value 1000 .1 12 .1
 121      ;lib/fin/nper 1000 future-value 1000 .1 24 .1
 122      ;lib/fin/nper 1000 future-value 1000 .1 36 .1
 123  
 124      irr: func [
 125          {Computes the internal rate of return based on future cash flow values.
 126          The internal rate of return of a cash flow is the interest rate that
 127          makes the present value of a cash flow equal to zero. THIS IS A QUICKLY
 128          HACKED VERSION AND NEEDS TO BE CLEANED UP! HERE FOR TESTING.}
 129          values  [any-block!] "Cash flow values"
 130          /guess
 131              guess-val
 132          /local rates rate npv-result result
 133      ][
 134          tries: 50
 135          ACCURACY: $.000001
 136          range: none
 137          rtb: dx: x-mid: 0.0
 138          f-mid: $0
 139  
 140          if not guess [guess-val: .2]
 141  
 142          if range: bracket-fn :npv values 0 guess-val [
 143              either ((npv values range/1) < $0) [
 144                  rtb: range/1
 145                  dx:  range/2 - range/1
 146              ][
 147                  rtb: range/2
 148                  dx:  range/1 - range/2
 149              ]
 150              loop tries [
 151              	dx: dx * 0.5
 152              	x-mid: rtb + dx
 153              	f-mid: npv values x-mid
 154              	if (f-mid <= $0) [rtb: x-mid]
 155              	if any [
 156                      (abs f-mid < ACCURACY)
 157                      (abs dx < second ACCURACY)
 158                  ] [return x-mid]
 159              ]
 160              return none
 161          ]
 162      ]
 163  
 164      bracket-fn: func [
 165          {Adapted from Numerical Recipes. Given a user supplied function and a
 166          given 'guess' range (x1 to x2) it expands the range geometrically until
 167          a root is bracketed by the returned values x1 and x2, in which case
 168          the range is returned as a block of those two values. If it doesn't
 169          succeed after 50 tries, it returns false. This was built to support
 170          IRR so it's designed to call NPV, which takes one arg. It should be
 171          generalized.}
 172          fn arg x1 x2
 173          /local factor tries f1 f2
 174      ][
 175          tries: 50
 176          factor: 1.6
 177          f1: fn arg x1
 178          f2: fn arg x2
 179          loop tries [
 180              ; We have to use SECOND on f2 because it's a money! value
 181              ; and the numeric component is returned by SECOND.
 182              if negative? multiply f1 second f2 [
 183                  return reduce [x1 x2]
 184              ]
 185              either (abs f1) < (abs f2) [
 186                  x1: x1 + (factor * (x1 - x2))
 187                  f1: fn arg x1
 188              ][
 189                  x2: x2 + (factor * (x2 - x1))
 190                  f2: fn arg x2
 191              ]
 192          ]
 193          false
 194      ]
 195      ;bracket-fn get in lib/fin 'npv values 0 .2
 196      ;values: [-$70'000 $12'000 $15'000 $18'000 $21'000 $26'000]
 197      ;lib/fin/irr values
 198      ;lib/fin/irr copy/part values 5
 199      ;lib/fin/irr copy/part values 3
 200      ;lib/fin/irr/guess copy/part values 3 -.1
 201      ;values: [-10 1.8 1.8 1.8 1.8 1.8 1.8 1.8 2.8]
 202      ;lib/fin/irr values
 203      ;values: [0 -1073 -1459 -1364 -1247 -1110 31789]
 204      ;lib/fin/irr values
 205  
 206  ;     irr: func [
 207  ;         {Computes the internal rate of return based on future cash flow values.
 208  ;         The internal rate of return of a cash flow is the interest rate that
 209  ;         makes the present value of a cash flow equal to zero. THIS IS A QUICKLY
 210  ;         HACKED VERSION AND NEEDS TO BE CLEANED UP! HERE FOR TESTING.}
 211  ;         values  [any-block!] "Cash flow values"
 212  ;         /guess
 213  ;             guess-val
 214  ;         /local rates rate npv-result result
 215  ;     ][
 216  ;         ACCURACY: $.000001
 217  ;         tries: 50
 218  ;         range: none
 219  ;         rtb: dx: x-mid: 0.0
 220  ;         f-mid: $0
 221  ;         if not guess [guess-val: .2]
 222  ;         if range: bracket-fn :npv values 0 guess-val [
 223  ;             f: npv values range/1
 224  ;             either (f < $0) [
 225  ;                 rtb: range/1
 226  ;                 dx: range/2 - range/1
 227  ;             ][
 228  ;                 rtb: range/2
 229  ;                 dx: range/1 - range/2
 230  ;             ]
 231  ;             loop tries [
 232  ;             	dx: dx * 0.5
 233  ;             	x-mid: rtb + dx
 234  ;             	f-mid: npv values x-mid
 235  ;             	if (f-mid <= $0) [rtb: x-mid]
 236  ;             	if any [
 237  ;                     ((abs f-mid) < ACCURACY)
 238  ;                     ((abs dx) < (second ACCURACY))
 239  ;                 ] [return x-mid]
 240  ;             ]
 241  ;             return none
 242  ;         ]
 243  ;     ]
 244  ;
 245  ;     bracket-fn: func [
 246  ;         {Adapted from Numerical Recipes. Given a user supplied function and a
 247  ;         given 'guess' range (x1 to x2) it expands the range geometrically until
 248  ;         a root is bracketed by the returned values x1 and x2, in which case
 249  ;         the range is returned as a block of those two values. If it doesn't
 250  ;         succeed after 50 tries, it returns false. This was built to support
 251  ;         IRR so it's designed to call NPV, which takes one arg. It should be
 252  ;         generalized.}
 253  ;         fn arg x1 x2
 254  ;         /local factor tries f1 f2
 255  ;     ][
 256  ;         tries: 50
 257  ;         factor: 1.6
 258  ;         f1: fn arg x1
 259  ;         f2: fn arg x2
 260  ;         loop tries [
 261  ;             ; We have to use SECOND on f2 because it's a money! value
 262  ;             ; and the numeric component is returned by SECOND.
 263  ;             if negative? multiply f1 second f2 [
 264  ;                 return reduce [x1 x2]
 265  ;             ]
 266  ;             either (abs f1) < (abs f2) [
 267  ;                 x1: x1 + (factor * (x1 - x2))
 268  ;                 f1: fn arg x1
 269  ;             ][
 270  ;                 x2: x2 + (factor * (x2 - x1))
 271  ;                 f2: fn arg x2
 272  ;             ]
 273  ;         ]
 274  ;         false
 275  ;     ]
 276  
 277  ]
« Newer Snippets
Older Snippets »
Showing 1-1 of 1 total  RSS