MRE_APP/apps/MRE/__init__.py
2025-03-14 13:37:08 -06:00

118 lines
3.7 KiB
Python

import numpy as np
import matplotlib.pyplot as plt
from multipolyfit import multipolyfit as mpf
class ConsumerNotEligibleError(Exception):
def __init__(self, reason, *args):
super().__init__(args)
self.reason = reason
def __str__(self):
return f'Consumer is ineligible due to {self.reason}'
def fico_default_risk_modifier_by_lend_percent(credit_score, loan_percent):
# The initial data set is organized as [{credit_score}, {loan_percent}]
initial_data = [[620, 1],
[620, 70],
[620, 85],
[620, 90],
[620, 95],
[660, 1],
[660, 70],
[660, 85],
[660, 90],
[660, 95],
[700, 1],
[700, 70],
[700, 85],
[700, 90],
[700, 95],
[740, 1],
[740, 70],
[740, 85],
[740, 90],
[740, 95]]
# the default rates to use
def_rate_620 = 3.03
def_rate_660 = 2.01
def_rate_700 = 1.50
def_rate_740 = 0.94
# the risk factor multiples to use
risk_factor_620 = [0.20, 0.61, 1.22, 1.48, 1.80]
risk_factor_660 = [0.20, 0.62, 1.22, 1.48, 1.82]
risk_factor_700 = [0.20, 0.62, 1.22, 1.49, 1.83]
risk_factor_740 = [0.20, 0.63, 1.21, 1.47, 1.81]
net_def_risks_620 = np.multiply(def_rate_620, risk_factor_620)
net_def_risks_660 = np.multiply(def_rate_660, risk_factor_660)
net_def_risks_700 = np.multiply(def_rate_700, risk_factor_700)
net_def_risks_740 = np.multiply(def_rate_740, risk_factor_740)
initial_risk_mults = [r for r in net_def_risks_620] + [r for r in net_def_risks_660] + [r for r in net_def_risks_700] + [r for r in net_def_risks_740]
x, y = zip(*initial_data)
ax = plt.axes(projection='3d')
ax.scatter(x, y, initial_risk_mults)
coefficients = mpf(initial_data, initial_risk_mults, 1)
result = np.multiply(coefficients[1], x) + np.multiply(coefficients[2], y) + coefficients[0]
ax.plot3D(x, y, result)
ax.set_title('Credit Score/Loan % Line of Best Fit')
plt.savefig('graph.png')
return coefficients[0] + coefficients[1] * credit_score + coefficients[2] * loan_percent
def get_loss_severity():
return 0.19
def get_recovery_rate():
return 0.9
def get_risk_pool_allocation_percent():
return 0.01
def get_gross_rent_yield():
return 3.686
def compute_mre(home_value, down_payment_percent, consumer_fico):
if not 0 <= down_payment_percent < 100:
raise ValueError('Down payment percent must be contained in [0, 100)')
if consumer_fico < 620:
raise ConsumerNotEligibleError('Credit score too low (must be 620 or Greater)')
monthly_payment = home_value * get_gross_rent_yield()/100/12
income_interruption_home_percentage = 100 * (monthly_payment * 4 / home_value)
risk_pool_percent = get_risk_pool_allocation_percent()
loss_severity = get_loss_severity()
recovery_rate = get_recovery_rate()
default_rate = fico_default_risk_modifier_by_lend_percent(consumer_fico, 100 - down_payment_percent)
at_risk_value = home_value * loss_severity
def_rate_mult = 100/default_rate
risk_pool_allocation = risk_pool_percent * home_value
denom = recovery_rate
num = at_risk_value - (def_rate_mult * risk_pool_allocation)
result = num/denom
mre = result/home_value + income_interruption_home_percentage
mre += income_interruption_home_percentage
return mre
if __name__ == '__main__':
print(compute_mre(742500, 2.5, 680))
# print(fico_default_risk_modifier_by_lend_percent(620, 85))