blob: b124061ccba3f36be824a0e6965707d458171f32 (
plain) (
blame)
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
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
|
;;; finance.el --- Functions to help me organize my finances -*- lexical-binding: t -*-
;; Author: William Carroll <wpcarro@gmail.com>
;;; Commentary:
;; Using functions to organize my financial thinking.
;;; Code:
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Dependencies
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(require 'prelude)
(require 'math)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Library
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defvar finance/enable-tests? t
"When t, run the tests defined herein.")
;; TODO: Support printing an org-table of these amount in a similar format to:
;; https://keisan.casio.com/exec/system/1234231998
(cl-defun finance/future-value (amt
&key
num-years
(frequency 'monthly)
(interest-rate 0.06)
(payment-due-at 'beg)
(present-value 0))
"Compute the Future Value of AMT.
This function assumes that the interest rate is applied annually and not
monthly.
This function will attempt to provide the following defaults:
- frequency: 'monthly
- interest-rate: 6%
- payment-due-at: 'beg
- present-value: 0.00"
(prelude/assert (set/contains? payment-due-at (set/new 'beg 'end)))
(prelude/assert (set/contains? frequency (set/new 'annually
'semiannually
'quarterly
'monthly)))
(let ((pmt amt)
(k (alist/get frequency '((annually . 1)
(semiannually . 2)
(quarterly . 4)
(monthly . 12))))
(r interest-rate)
(n num-years)
(pv present-value))
(if (= 0 r)
(+ pv (* pmt n k))
(if (equal 'beg payment-due-at)
(+ (* pv (math/exp (+ 1 (/ r k)) (* n k)))
(* pmt
(/ (- (math/exp (+ 1 (/ r k)) (* n k)) 1)
(/ r k))
(+ 1 (/ r k))))
(+ (* pv (math/exp (+ 1 (/ r k)) (* n k)))
(* pmt
(/ (- (math/exp (+ 1 (/ r k)) (* n k)) 1)
(/ r k))))))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Tests
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(when finance/enable-tests?
(prelude/assert
(equal "1551.27"
(string/format "%0.2f"
(finance/future-value
9.99
:interest-rate 0.05
:num-years 10
:frequency 'monthly
:payment-due-at 'end
:present-value 0))))
(prelude/assert
(equal "14318.34"
(string/format "%0.2f"
(finance/future-value 10.0 :num-years 35))))
(prelude/assert
(equal "4200.00"
(string/format "%0.2f"
(finance/future-value
10.0
:interest-rate 0.0
:num-years 35
:frequency 'monthly
:payment-due-at 'beg
:present-value 0))))
(prelude/assert
(equal "14318.34"
(string/format "%0.2f"
(finance/future-value
10.0
:interest-rate 0.06
:num-years 35
:frequency 'monthly
:payment-due-at 'beg
:present-value 0))))
(prelude/assert
(equal "38282.77"
(string/format "%0.2f"
(finance/future-value
10.0
:interest-rate 0.1
:num-years 35
:frequency 'monthly
:payment-due-at 'beg
:present-value 0)))))
(provide 'finance)
;;; finance.el ends here
|