-
Notifications
You must be signed in to change notification settings - Fork 1
/
APR.py
117 lines (103 loc) · 4.88 KB
/
APR.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
# -*- coding: utf-8 -*-
"""
Created on Mon Sep 28 06:12:10 2015
@author: Dan
"""
import sqlite3 # This is the SQL engine in use.
import cfg
from StringClean import isNull, fixNull, fixZero, float0, strRound
class APRTable (object):
# Reads, from database, a table of APR by FICO, LTV, and Term
# There is only one member of this class (MyAPR)
# MyAPR is initialized once (at startup), and is then used many times
# Two dictionaries are available: APRGrid and MonthlyGrid
# APRGrid is a dictionary from the 3-tuplet of (FICO, LTV, Term) to APR
# Each of the 3 quantities is on an equispaced grid.
# The class elements LowFico, HighFico, and StepFico define the gridpoints
# (Likewise LowLTV, HighLTV and StepLTV; and LowTerm, HighTerm, StepTerm)
# For example, MyAPR.APRGrid[(690, 0.9, 72)] will provide the APR for
# a 72 months term loan at 90% LTV to a FICO 690 borrower
# Similarly, MonthlyGrid will provide the monthly payment (as a percentage
# of loan amount) for a given FICO-LTV-Term tuplet
# The Methods GetAPR and GetMonthly will return the APR and Monthly,
# respectively, for any numeric FICO and LTV; even if not on the grid.
# (Term must always be on the grid)
# For example: MyAPR.GetAPR(711, 0.92, 60) will provide the APR for a
# 60 months term loan at 90% LTV to a FICO 710 borrower.
# Both methods return 0 for erroneous and unfixable parameters
def __init__(self):
MyDB = sqlite3.connect(cfg.FnameDB)
cur = MyDB.cursor()
MyScript = """SELECT FICO, LTV, Term, APR, Monthly
FROM APR;"""
cur.execute(MyScript)
Results = cur.fetchall()
MyDB.commit()
MyDB.close()
self.APRGrid = {(0, 0, 0): 0}
self.MonthlyGrid = {(0, 0, 0): 0}
self.LowFico = int(Results[0][0])
self.HighFico = self.LowFico
self.StepFico = 1000
self.LowLTV = int(Results[0][1])
self.HighLTV = self.LowLTV
self.StepLTV = 1000
self.LowTerm = int(Results[0][2])
self.HighTerm = self.LowTerm
self.StepTerm = 1000
for row in Results:
Fico = int(row[0])
LTV = int(row[1])
Term = int(row[2])
APR = float(row[3])
Monthly = float(row[4])
self.APRGrid.update({(Fico, LTV, Term): APR})
self.MonthlyGrid.update({(Fico, LTV, Term): Monthly})
self.HighFico = max(self.HighFico, Fico)
self.HighLTV = max(self.HighLTV, LTV)
self.HighTerm = max(self.HighTerm, Term)
if Fico > self.LowFico:
self.StepFico = min(self.StepFico, Fico - self.LowFico)
if LTV > self.LowLTV:
self.StepLTV = min(self.StepLTV, LTV - self.LowLTV)
if Term > self.LowTerm:
self.StepTerm = min(self.StepTerm, Term - self.LowTerm)
def CleanDeal(self, sFICO, pLTV, sTerm):
# This function will clean up the sFICO, pLTV, and sTerm
# parameters, so they can be used to find APR and Monthly payment
# If uncleanable, return 0-0-0; else, return Fico-LTV-Term
# The returned values will correspond to a grid point on the
# tabulated APRGrid and MonthlyGrid dictionaries
try:
if isNull(sFICO):
FICO = self.LowFico
else:
FICO = max(self.LowFico, min(self.HighFico, float(sFICO)))
FICO = int(round((FICO - self.LowFico)/self.StepFico) *
self.StepFico + self.LowFico)
LTV = max(self.LowLTV, min(self.HighLTV, 100.0 * pLTV))
LTV = int(round((LTV - self.LowLTV)/self.StepLTV) *
self.StepLTV + self.LowLTV)
Term = int(fixNull(sTerm, cfg.TermWanted))
if (Term < self.LowTerm) or (Term > self.HighTerm) or \
( (Term - self.LowTerm) % self.StepTerm != 0):
return (0, 0, 0)
return (FICO, LTV, Term)
except ValueError:
return (0, 0, 0)
except:
print "Unexpected error in CleanDeal:"
print "sFICO = " + str(sFICO)
print "pLTV = " + str(pLTV)
print "sTerm = " + str(sTerm)
raise
def GetAPR(self, sFICO, pLTV, sTerm):
# Returns the tabulated APR for a prospective loan
# Will return 0 for error conditions (uncleanable inputs)
return self.APRGrid[self.CleanDeal(sFICO, pLTV, sTerm)]
def GetMonthly(self, sFICO, pLTV, sTerm):
# Returns the tabulated Monthly payment for a prospective loan
# (as a percentage of loan amount)
# Will return 0 for error conditions (uncleanable inputs)
return self.MonthlyGrid[self.CleanDeal(sFICO, pLTV, sTerm)]
MyAPR = APRTable()