Welcome, guest | Sign In | My Account | Store | Cart

This class can be used to do interest rate calculations much like a financial calculator, and demonstrates the use of Python properties.

Python, 128 lines
 ``` 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 120 121 122 123 124 125 126 127 128``` ```'''\ An experiment with python properties using TVM equations as an example A TVM object works like a financial calculator. Given any four of (n, i, pmt, pv, fv) TVM object can calculate the fifth. This version assumes payments are at end of compounding period. Example: >>> loan=TVM() >>> loan.n=3*12 # set number of payments to 36 >>> loan.pv=6000 # set present value to 6000 >>> loan.i=6/12. # set interest rate to 6% annual >>> loan.fv=0 # set future value to zero >>> loan.pmt # ask for payment amount -182.5316247083343 # payment (note sign) Alternative style: >>> TVM(n=36, pv=6000, pmt=-200, fv=0).i*12 12.2489388032796 ''' from math import log from __future__ import division class TVM (object): '''A Time Value of Money class using properties''' def __init__(self, n=None, i=None, pv=None, pmt=None, fv=None): self.__n=n self.__i=i self.__pv=pv self.__pmt=pmt self.__fv=fv def __repr__(self): return "TVM(n=%s, i=%s, pv=%s, pmt=%s, fv=%s)" % \ (self.__n, self.__i, self.__pv, self.__pmt, self.__fv) def __get_a(self): '''calculate 'a' intermediate value''' return (1+self.__i/100)**self.__n-1 def __get_b(self): '''calculate 'b' intermediate value''' return 100/self.__i def __get_c(self): '''calculate 'c' intermediate value''' return self.__get_b()*self.__pmt def get_n(self): c=self.__get_c() self.__n = log((c-self.__fv)/(c+self.__pv))/log(1+self.__i/100) return self.__n def set_n(self,value): self.__n=value n = property(get_n, set_n, None, 'number of payments') def get_i(self): # need to do an iterative solution - no closed form solution exists # trying Newton's method INTTOL=0.0000001 # tolerance ITERLIMIT=1000 # iteration limit # initial guess for interest if self.__i: i0=self.__i else: i0=1.0 # 10% higher interest rate - to get a slope calculation i1=1.1*i0 def f(tvm,i): '''function used in Newton's method; pmt(i)-pmt''' a = (1+i/100)**self.__n-1 b = 100/i out = -(tvm.__fv+tvm.__pv*(a+1))/(a*b)-tvm.__pmt return out fi0 = f(self,i0) if abs(fi0)ITERLIMIT: print "Failed to converge; exceeded iteration limit" break slope=(fi1-fi0)/(i1-i0) i2=i0-fi0/slope # New 'i1' fi0 = fi1 i0=i1 i1=i2 n+=1 self.__i = i1 return self.__i def set_i(self,value): self.__i=value i = property(get_i, set_i, None, 'interest rate') def get_pv(self): a=self.__get_a() c=self.__get_c() self.__pv = -(self.__fv+a*c)/(a+1) return self.__pv def set_pv(self,value): self.__pv=value pv = property(get_pv, set_pv, None, 'present value') def get_pmt(self): a=self.__get_a() b=self.__get_b() self.__pmt = -(self.__fv+self.__pv*(a+1))/(a*b) return self.__pmt def set_pmt(self,value): self.__pmt=value pmt = property(get_pmt, set_pmt, None, 'payment') def get_fv(self): a=self.__get_a() c=self.__get_c() self.__fv = -(self.__pv+a*(self.__pv+c)) return self.__fv def set_fv(self,value): self.__fv=value fv = property(get_fv, set_fv, None, 'future value') ```

This is a handy tool to have around - and shows how properties can be used to make a nice interface for an certain types of problems. This class presents a uniform face on solving the equation for each of the variables, rather than having a set of five functions which each solve for a particular variable.

#### 1 comment

Facundo Batista 19 years, 7 months ago

Data type. You should really be using Decimal for this kind of math. See PEP 327 for further info.

 Created by David Klaffenbach on Mon, 30 Aug 2004 (PSF)