diff options
author | William Carroll <wpcarro@gmail.com> | 2020-01-15T17·20+0000 |
---|---|---|
committer | William Carroll <wpcarro@gmail.com> | 2020-01-17T10·56+0000 |
commit | eba6ea676221e405ce8ecab518df494593cacb8e (patch) | |
tree | 2ef0e6a1202f829c32283405bf0ab63d29f21023 /configs/shared/.emacs.d | |
parent | f5e19abcb341eb54f18526ca2bc3a00ea14a4542 (diff) |
Support finance.el
Create a finance module to help me cheaply calculate things like the future value of a Spotify subscription or Dropbox subscription or Jiu Jitsu membership.
Diffstat (limited to 'configs/shared/.emacs.d')
-rw-r--r-- | configs/shared/.emacs.d/wpc/finance.el | 119 |
1 files changed, 119 insertions, 0 deletions
diff --git a/configs/shared/.emacs.d/wpc/finance.el b/configs/shared/.emacs.d/wpc/finance.el new file mode 100644 index 000000000000..b124061ccba3 --- /dev/null +++ b/configs/shared/.emacs.d/wpc/finance.el @@ -0,0 +1,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 |