-
Notifications
You must be signed in to change notification settings - Fork 0
/
shovel.py
executable file
路130 lines (102 loc) 路 4.16 KB
/
shovel.py
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
129
130
#!/usr/bin/python
import yaml
from prettytable import PrettyTable
import prettytable
import calendar
class bcolors:
HEADER = '\033[95m'; OKBLUE = '\033[94m'; OKGREEN = '\033[92m'; WARNING = '\033[93m'
FAIL = '\033[91m'; ENDC = '\033[0m'; BOLD = '\033[1m'; UNDERLINE = '\033[4m'
def getInterest(prin, rate):
if period == "Yearly":
return prin*(1+rate)-prin
else: #Monthly
return prin*(1+(rate/12.0))-prin
def calcWeights(loans):
interests, weights = [], []
[ interests.append( getInterest(l['prin'], l['rate']) ) for l in loans ]
total = sum(interests)
[ weights.append( i / total ) for i in interests ]
return weights
def calcPayments(loans, payment):
payments = []
weights = calcWeights(loans)
for i in range(len(loans)):
#we take the minimum of our recommended weighting and the potential accumulation of the next year
#this lets us surge a bit on the last year to tackle any remaining interest
p = min( loans[i]['prin'] + getInterest( loans[i]['prin'],
loans[i]['rate'] ),
weights[i]*payment)
payments.append(p)
return payments
def increment(loans, payment):
payments = calcPayments(loans, payment)
for i in range(len(loans)):
loan = loans[i]
loan['prin'] = loan['prin']+getInterest(loan['prin'], loan['rate']) - payments[i]
if loan['prin'] < 10:
loan['prin'] = 0
return loans, payments
def pNeg(n):
if n == 0: return format(n, ".2f")
else: return bcolors.FAIL + format(n, ".2f") + bcolors.ENDC
def pPos(n):
if n == 0: return format(n, ".2f")
else: return bcolors.OKGREEN + format(n, ".2f") + bcolors.ENDC
def pWarn(n): return bcolors.WARNING+n+bcolors.ENDC
def pOK(n): return bcolors.OKBLUE+n+bcolors.ENDC
def pHeader(n): return bcolors.HEADER+n+bcolors.ENDC
def newLine(n):
return [" " for i in range(n)]
def calcLeft(loans):
return sum([l['prin'] for l in loans])
def schedule(loans):
payment, month = startingPayment, startingMonth
year = 0
t = PrettyTable([""]+[pHeader(l['name']) for l in loans]+[pHeader("Total")], align="r")
#alignments
for l in loans:
t.align[pHeader(l['name'])] = "r"
t.align[""] = "r"
t.align[pHeader("Total")] = "r"
while calcLeft(loans) > 10:
t.add_row(newLine(2+len(loans)))
if period == "Monthly":
yearTitle = "{0} {1}".format(calendar.month_abbr[month], year+startingYear)
periodPaymentTitle = pHeader("Monthly")+" Payment"
else:
yearTitle = "{0}".format(year+startingYear)
periodPaymentTitle = pHeader("Annual")+" Payment"
t.add_row(["{0} Principal".format(pWarn(yearTitle))]
+ [pPos(l['prin']) for l in loans]
+ [format(sum([l['prin'] for l in loans]),".2f")])
t.add_row(["Interest"]
+ ["+{0}".format(format(getInterest(l['prin'], l['rate']),".2f")) for l in loans]
+ [format(sum([getInterest(l['prin'], l['rate']) for l in loans]),".2f")])
loans, recentPayments = increment(loans, payment)
if period == "Yearly":
t.add_row(["Monthly Payment"]
+ ["-{0}".format(format(r/12.0,".2f")) for r in recentPayments]
+ [format(sum([r/12.0 for r in recentPayments]),".2f")])
t.add_row([periodPaymentTitle]
+ ["-{0}".format(pNeg(r)) for r in recentPayments]
+ [pHeader(format(sum([r for r in recentPayments]),".2f"))])
payment = payment * (1 + growth)
if period == "Monthly":
if month == 12:
month = 1; year = year + 1
else:
month = month + 1
else:
year = year + 1
print t
y = yaml.load(open('config.yaml'))
global period, growth, startingYear, startingMonth, startingPayment
period = y['period'] or "Yearly"
growth = float(y['growth'])/100.0 or 0
startingYear = y['startingYear']
startingMonth = y['startingMonth']
startingPayment = float(y['startingPayment']) or 5000
loans = y['loans']
for loan in loans:
loan['rate'] /= 100 #percent to decimal
schedule(loans)