Renting vs. owning comparison calculation
up vote
1
down vote
favorite
I have working code that compares rental prices and owning costs, given some parameters. It works, but it surely does not look good. I hadn't worked with time-series before and I wonder how I could improve the code. See it below:
""" Credit: khanacademy.org/downloads/buyrent.xls"""
""" This code compares the cost of renting with the cost of owning a house.
It was orginally thought for the US case. The adjustment of parameteres was made
to fit the case of Brazil. Two alternatives are available the so-called Price table or SAC:
https://pt.wikipedia.org/wiki/Sistema_de_Amortização_Constante"""
import numpy as np
import matplotlib.pyplot as plt
def flow(purchase_p, downpay, inter, yr, prop_tax_rate, yr_maint, yr_cond, yr_ins, appr, inc_tax_rate, inflat,
rent_price, cash, print_ten=120, choice='price'):
if choice == 'price':
fixed_mortgage_payment = (purchase_p - downpay) * (1 - 1/(1 + inter/12)) / (1 - 1/(1 + inter/12) **
(yr * 12 + 1))
else:
fixed_mortgage_payment = (purchase_p - downpay) / (yr * 12)
home_value = np.zeros(yr * 12 + 1)
debt = np.zeros(yr * 12 + 1)
paid_interest = np.zeros(yr * 12 + 1)
insurance = np.zeros(yr * 12 + 1)
cond = np.zeros(yr * 12 + 1)
maint = np.zeros(yr * 12 + 1)
property_tax = np.zeros(yr * 12 + 1)
cash_outflow = np.zeros(yr * 12 + 1)
rent = np.zeros(yr * 12 + 1)
rent_savings = np.zeros(yr * 12 + 1)
paid_principal = np.zeros(yr * 12 + 1)
income_tax = np.zeros(yr * 12 + 1)
home_value[0] = purchase_p
debt[0] = purchase_p - downpay
insurance[0] = yr_ins/12
cond[0] = yr_cond/12
maint[0] = yr_maint/12
rent[0] = rent_price
rent_savings[0] = downpay
for i in range(yr * 12):
paid_interest[i + 1] = debt[i] * inter / 12
if choice == 'price':
paid_principal[i + 1] = fixed_mortgage_payment - paid_interest[i + 1]
debt[i + 1] = debt[i] - paid_principal[i + 1]
else:
paid_principal[i + 1] = fixed_mortgage_payment
debt[i + 1] = debt[i] - fixed_mortgage_payment
home_value[i + 1] = home_value[i] * (1 + appr/12)
insurance[i + 1] = insurance[i] * (1 + inflat/12)
cond[i + 1] = cond[i] * (1 + inflat/12)
maint[i + 1] = maint[i] * (1 + inflat / 12)
property_tax[i + 1] = home_value[i] * (prop_tax_rate/12)
income_tax[i + 1] = (paid_interest[i + 1] + property_tax[i + 1]) * inc_tax_rate
cash_outflow[i + 1] = insurance[i + 1] + cond[i + 1] + maint[i + 1] + property_tax[i + 1] +
paid_interest[i + 1] + paid_principal[i + 1] - income_tax[i + 1]
rent[i + 1] = (1 + appr/12) * rent[i]
rent_savings[i + 1] = rent_savings[i] * (1 + cash/12) + cash_outflow[i + 1] - rent[i + 1]
print('Home value after {:.0f} years: {:,.2f}'.format(print_ten/12, home_value[print_ten]))
print('Debt after {:.0f} years: {:,.2f}'.format(print_ten/12, debt[print_ten]))
print('Equity after {:.0f} years: {:,.2f}'.format(print_ten/12, home_value[print_ten] - debt[print_ten]))
print('Savings if renting after {:.0f} years: {:,.2f}'.format(print_ten/12, rent_savings[print_ten]))
print('Selling cost (6% brokerage rate): {:,.2f}'.format(home_value[print_ten] * .06))
print('Benefit of buying over renting? {:,.2f}'.format(home_value[print_ten] - debt[print_ten]
- rent_savings[print_ten] - home_value[print_ten] * .06))
return {'home_value': home_value, 'debt': debt, 'equity': home_value - debt, 'savings_renting': rent_savings,
'benefit_buying': home_value - debt - rent_savings - (home_value * .06)}
def plotting(data):
plt.plot(data['home_value'], label='Home value')
plt.plot(data['debt'], label='Debt')
plt.plot(data['equity'], label='Equity')
plt.plot(data['savings_renting'], label="Savings when renting")
plt.plot(data['benefit_buying'], label='Benefit of buying')
plt.legend()
plt.annotate('Parms: house price {:,.0f}, ndownpayment {:,.0f}, ninterest annual {:.3f}, years {:.0f}, '
'naluguel {:,.0f}, ncash return annual {:.3f}, ninflation {:.3f},'
'ntabela: {} nhouse appreciation {:.3f}'.format(purchase_price, downpayment, interest, years,
initial_rent, return_cash, inflation, choice,
appreciation),
fontsize=9, xy=(0.43, 0.7), xycoords='axes fraction')
plt.savefig('res1.png')
plt.show()
if __name__ == '__main__':
purchase_price = 800000
downpayment = 0
interest = .08
years = 30
property_tax_rate = 0
yr_maintenance = 0
yr_comdominium = 0
yr_insurance = 0
appreciation = .03 # real appreciation 0%
income_tax_rate = 0 # income deduction on interest and property taxes paid
inflation = .03
initial_rent = purchase_price * .004 # 0.4 % of real values
return_cash = .06 # real return on cash 3%
time = 360
choice = 'SAC'
res = flow(purchase_price, downpayment, interest, years, property_tax_rate, yr_maintenance, yr_comdominium,
yr_insurance, appreciation, income_tax_rate, inflation, initial_rent, return_cash, time, choice)
plotting(res)
python datetime numpy finance
New contributor
add a comment |
up vote
1
down vote
favorite
I have working code that compares rental prices and owning costs, given some parameters. It works, but it surely does not look good. I hadn't worked with time-series before and I wonder how I could improve the code. See it below:
""" Credit: khanacademy.org/downloads/buyrent.xls"""
""" This code compares the cost of renting with the cost of owning a house.
It was orginally thought for the US case. The adjustment of parameteres was made
to fit the case of Brazil. Two alternatives are available the so-called Price table or SAC:
https://pt.wikipedia.org/wiki/Sistema_de_Amortização_Constante"""
import numpy as np
import matplotlib.pyplot as plt
def flow(purchase_p, downpay, inter, yr, prop_tax_rate, yr_maint, yr_cond, yr_ins, appr, inc_tax_rate, inflat,
rent_price, cash, print_ten=120, choice='price'):
if choice == 'price':
fixed_mortgage_payment = (purchase_p - downpay) * (1 - 1/(1 + inter/12)) / (1 - 1/(1 + inter/12) **
(yr * 12 + 1))
else:
fixed_mortgage_payment = (purchase_p - downpay) / (yr * 12)
home_value = np.zeros(yr * 12 + 1)
debt = np.zeros(yr * 12 + 1)
paid_interest = np.zeros(yr * 12 + 1)
insurance = np.zeros(yr * 12 + 1)
cond = np.zeros(yr * 12 + 1)
maint = np.zeros(yr * 12 + 1)
property_tax = np.zeros(yr * 12 + 1)
cash_outflow = np.zeros(yr * 12 + 1)
rent = np.zeros(yr * 12 + 1)
rent_savings = np.zeros(yr * 12 + 1)
paid_principal = np.zeros(yr * 12 + 1)
income_tax = np.zeros(yr * 12 + 1)
home_value[0] = purchase_p
debt[0] = purchase_p - downpay
insurance[0] = yr_ins/12
cond[0] = yr_cond/12
maint[0] = yr_maint/12
rent[0] = rent_price
rent_savings[0] = downpay
for i in range(yr * 12):
paid_interest[i + 1] = debt[i] * inter / 12
if choice == 'price':
paid_principal[i + 1] = fixed_mortgage_payment - paid_interest[i + 1]
debt[i + 1] = debt[i] - paid_principal[i + 1]
else:
paid_principal[i + 1] = fixed_mortgage_payment
debt[i + 1] = debt[i] - fixed_mortgage_payment
home_value[i + 1] = home_value[i] * (1 + appr/12)
insurance[i + 1] = insurance[i] * (1 + inflat/12)
cond[i + 1] = cond[i] * (1 + inflat/12)
maint[i + 1] = maint[i] * (1 + inflat / 12)
property_tax[i + 1] = home_value[i] * (prop_tax_rate/12)
income_tax[i + 1] = (paid_interest[i + 1] + property_tax[i + 1]) * inc_tax_rate
cash_outflow[i + 1] = insurance[i + 1] + cond[i + 1] + maint[i + 1] + property_tax[i + 1] +
paid_interest[i + 1] + paid_principal[i + 1] - income_tax[i + 1]
rent[i + 1] = (1 + appr/12) * rent[i]
rent_savings[i + 1] = rent_savings[i] * (1 + cash/12) + cash_outflow[i + 1] - rent[i + 1]
print('Home value after {:.0f} years: {:,.2f}'.format(print_ten/12, home_value[print_ten]))
print('Debt after {:.0f} years: {:,.2f}'.format(print_ten/12, debt[print_ten]))
print('Equity after {:.0f} years: {:,.2f}'.format(print_ten/12, home_value[print_ten] - debt[print_ten]))
print('Savings if renting after {:.0f} years: {:,.2f}'.format(print_ten/12, rent_savings[print_ten]))
print('Selling cost (6% brokerage rate): {:,.2f}'.format(home_value[print_ten] * .06))
print('Benefit of buying over renting? {:,.2f}'.format(home_value[print_ten] - debt[print_ten]
- rent_savings[print_ten] - home_value[print_ten] * .06))
return {'home_value': home_value, 'debt': debt, 'equity': home_value - debt, 'savings_renting': rent_savings,
'benefit_buying': home_value - debt - rent_savings - (home_value * .06)}
def plotting(data):
plt.plot(data['home_value'], label='Home value')
plt.plot(data['debt'], label='Debt')
plt.plot(data['equity'], label='Equity')
plt.plot(data['savings_renting'], label="Savings when renting")
plt.plot(data['benefit_buying'], label='Benefit of buying')
plt.legend()
plt.annotate('Parms: house price {:,.0f}, ndownpayment {:,.0f}, ninterest annual {:.3f}, years {:.0f}, '
'naluguel {:,.0f}, ncash return annual {:.3f}, ninflation {:.3f},'
'ntabela: {} nhouse appreciation {:.3f}'.format(purchase_price, downpayment, interest, years,
initial_rent, return_cash, inflation, choice,
appreciation),
fontsize=9, xy=(0.43, 0.7), xycoords='axes fraction')
plt.savefig('res1.png')
plt.show()
if __name__ == '__main__':
purchase_price = 800000
downpayment = 0
interest = .08
years = 30
property_tax_rate = 0
yr_maintenance = 0
yr_comdominium = 0
yr_insurance = 0
appreciation = .03 # real appreciation 0%
income_tax_rate = 0 # income deduction on interest and property taxes paid
inflation = .03
initial_rent = purchase_price * .004 # 0.4 % of real values
return_cash = .06 # real return on cash 3%
time = 360
choice = 'SAC'
res = flow(purchase_price, downpayment, interest, years, property_tax_rate, yr_maintenance, yr_comdominium,
yr_insurance, appreciation, income_tax_rate, inflation, initial_rent, return_cash, time, choice)
plotting(res)
python datetime numpy finance
New contributor
add a comment |
up vote
1
down vote
favorite
up vote
1
down vote
favorite
I have working code that compares rental prices and owning costs, given some parameters. It works, but it surely does not look good. I hadn't worked with time-series before and I wonder how I could improve the code. See it below:
""" Credit: khanacademy.org/downloads/buyrent.xls"""
""" This code compares the cost of renting with the cost of owning a house.
It was orginally thought for the US case. The adjustment of parameteres was made
to fit the case of Brazil. Two alternatives are available the so-called Price table or SAC:
https://pt.wikipedia.org/wiki/Sistema_de_Amortização_Constante"""
import numpy as np
import matplotlib.pyplot as plt
def flow(purchase_p, downpay, inter, yr, prop_tax_rate, yr_maint, yr_cond, yr_ins, appr, inc_tax_rate, inflat,
rent_price, cash, print_ten=120, choice='price'):
if choice == 'price':
fixed_mortgage_payment = (purchase_p - downpay) * (1 - 1/(1 + inter/12)) / (1 - 1/(1 + inter/12) **
(yr * 12 + 1))
else:
fixed_mortgage_payment = (purchase_p - downpay) / (yr * 12)
home_value = np.zeros(yr * 12 + 1)
debt = np.zeros(yr * 12 + 1)
paid_interest = np.zeros(yr * 12 + 1)
insurance = np.zeros(yr * 12 + 1)
cond = np.zeros(yr * 12 + 1)
maint = np.zeros(yr * 12 + 1)
property_tax = np.zeros(yr * 12 + 1)
cash_outflow = np.zeros(yr * 12 + 1)
rent = np.zeros(yr * 12 + 1)
rent_savings = np.zeros(yr * 12 + 1)
paid_principal = np.zeros(yr * 12 + 1)
income_tax = np.zeros(yr * 12 + 1)
home_value[0] = purchase_p
debt[0] = purchase_p - downpay
insurance[0] = yr_ins/12
cond[0] = yr_cond/12
maint[0] = yr_maint/12
rent[0] = rent_price
rent_savings[0] = downpay
for i in range(yr * 12):
paid_interest[i + 1] = debt[i] * inter / 12
if choice == 'price':
paid_principal[i + 1] = fixed_mortgage_payment - paid_interest[i + 1]
debt[i + 1] = debt[i] - paid_principal[i + 1]
else:
paid_principal[i + 1] = fixed_mortgage_payment
debt[i + 1] = debt[i] - fixed_mortgage_payment
home_value[i + 1] = home_value[i] * (1 + appr/12)
insurance[i + 1] = insurance[i] * (1 + inflat/12)
cond[i + 1] = cond[i] * (1 + inflat/12)
maint[i + 1] = maint[i] * (1 + inflat / 12)
property_tax[i + 1] = home_value[i] * (prop_tax_rate/12)
income_tax[i + 1] = (paid_interest[i + 1] + property_tax[i + 1]) * inc_tax_rate
cash_outflow[i + 1] = insurance[i + 1] + cond[i + 1] + maint[i + 1] + property_tax[i + 1] +
paid_interest[i + 1] + paid_principal[i + 1] - income_tax[i + 1]
rent[i + 1] = (1 + appr/12) * rent[i]
rent_savings[i + 1] = rent_savings[i] * (1 + cash/12) + cash_outflow[i + 1] - rent[i + 1]
print('Home value after {:.0f} years: {:,.2f}'.format(print_ten/12, home_value[print_ten]))
print('Debt after {:.0f} years: {:,.2f}'.format(print_ten/12, debt[print_ten]))
print('Equity after {:.0f} years: {:,.2f}'.format(print_ten/12, home_value[print_ten] - debt[print_ten]))
print('Savings if renting after {:.0f} years: {:,.2f}'.format(print_ten/12, rent_savings[print_ten]))
print('Selling cost (6% brokerage rate): {:,.2f}'.format(home_value[print_ten] * .06))
print('Benefit of buying over renting? {:,.2f}'.format(home_value[print_ten] - debt[print_ten]
- rent_savings[print_ten] - home_value[print_ten] * .06))
return {'home_value': home_value, 'debt': debt, 'equity': home_value - debt, 'savings_renting': rent_savings,
'benefit_buying': home_value - debt - rent_savings - (home_value * .06)}
def plotting(data):
plt.plot(data['home_value'], label='Home value')
plt.plot(data['debt'], label='Debt')
plt.plot(data['equity'], label='Equity')
plt.plot(data['savings_renting'], label="Savings when renting")
plt.plot(data['benefit_buying'], label='Benefit of buying')
plt.legend()
plt.annotate('Parms: house price {:,.0f}, ndownpayment {:,.0f}, ninterest annual {:.3f}, years {:.0f}, '
'naluguel {:,.0f}, ncash return annual {:.3f}, ninflation {:.3f},'
'ntabela: {} nhouse appreciation {:.3f}'.format(purchase_price, downpayment, interest, years,
initial_rent, return_cash, inflation, choice,
appreciation),
fontsize=9, xy=(0.43, 0.7), xycoords='axes fraction')
plt.savefig('res1.png')
plt.show()
if __name__ == '__main__':
purchase_price = 800000
downpayment = 0
interest = .08
years = 30
property_tax_rate = 0
yr_maintenance = 0
yr_comdominium = 0
yr_insurance = 0
appreciation = .03 # real appreciation 0%
income_tax_rate = 0 # income deduction on interest and property taxes paid
inflation = .03
initial_rent = purchase_price * .004 # 0.4 % of real values
return_cash = .06 # real return on cash 3%
time = 360
choice = 'SAC'
res = flow(purchase_price, downpayment, interest, years, property_tax_rate, yr_maintenance, yr_comdominium,
yr_insurance, appreciation, income_tax_rate, inflation, initial_rent, return_cash, time, choice)
plotting(res)
python datetime numpy finance
New contributor
I have working code that compares rental prices and owning costs, given some parameters. It works, but it surely does not look good. I hadn't worked with time-series before and I wonder how I could improve the code. See it below:
""" Credit: khanacademy.org/downloads/buyrent.xls"""
""" This code compares the cost of renting with the cost of owning a house.
It was orginally thought for the US case. The adjustment of parameteres was made
to fit the case of Brazil. Two alternatives are available the so-called Price table or SAC:
https://pt.wikipedia.org/wiki/Sistema_de_Amortização_Constante"""
import numpy as np
import matplotlib.pyplot as plt
def flow(purchase_p, downpay, inter, yr, prop_tax_rate, yr_maint, yr_cond, yr_ins, appr, inc_tax_rate, inflat,
rent_price, cash, print_ten=120, choice='price'):
if choice == 'price':
fixed_mortgage_payment = (purchase_p - downpay) * (1 - 1/(1 + inter/12)) / (1 - 1/(1 + inter/12) **
(yr * 12 + 1))
else:
fixed_mortgage_payment = (purchase_p - downpay) / (yr * 12)
home_value = np.zeros(yr * 12 + 1)
debt = np.zeros(yr * 12 + 1)
paid_interest = np.zeros(yr * 12 + 1)
insurance = np.zeros(yr * 12 + 1)
cond = np.zeros(yr * 12 + 1)
maint = np.zeros(yr * 12 + 1)
property_tax = np.zeros(yr * 12 + 1)
cash_outflow = np.zeros(yr * 12 + 1)
rent = np.zeros(yr * 12 + 1)
rent_savings = np.zeros(yr * 12 + 1)
paid_principal = np.zeros(yr * 12 + 1)
income_tax = np.zeros(yr * 12 + 1)
home_value[0] = purchase_p
debt[0] = purchase_p - downpay
insurance[0] = yr_ins/12
cond[0] = yr_cond/12
maint[0] = yr_maint/12
rent[0] = rent_price
rent_savings[0] = downpay
for i in range(yr * 12):
paid_interest[i + 1] = debt[i] * inter / 12
if choice == 'price':
paid_principal[i + 1] = fixed_mortgage_payment - paid_interest[i + 1]
debt[i + 1] = debt[i] - paid_principal[i + 1]
else:
paid_principal[i + 1] = fixed_mortgage_payment
debt[i + 1] = debt[i] - fixed_mortgage_payment
home_value[i + 1] = home_value[i] * (1 + appr/12)
insurance[i + 1] = insurance[i] * (1 + inflat/12)
cond[i + 1] = cond[i] * (1 + inflat/12)
maint[i + 1] = maint[i] * (1 + inflat / 12)
property_tax[i + 1] = home_value[i] * (prop_tax_rate/12)
income_tax[i + 1] = (paid_interest[i + 1] + property_tax[i + 1]) * inc_tax_rate
cash_outflow[i + 1] = insurance[i + 1] + cond[i + 1] + maint[i + 1] + property_tax[i + 1] +
paid_interest[i + 1] + paid_principal[i + 1] - income_tax[i + 1]
rent[i + 1] = (1 + appr/12) * rent[i]
rent_savings[i + 1] = rent_savings[i] * (1 + cash/12) + cash_outflow[i + 1] - rent[i + 1]
print('Home value after {:.0f} years: {:,.2f}'.format(print_ten/12, home_value[print_ten]))
print('Debt after {:.0f} years: {:,.2f}'.format(print_ten/12, debt[print_ten]))
print('Equity after {:.0f} years: {:,.2f}'.format(print_ten/12, home_value[print_ten] - debt[print_ten]))
print('Savings if renting after {:.0f} years: {:,.2f}'.format(print_ten/12, rent_savings[print_ten]))
print('Selling cost (6% brokerage rate): {:,.2f}'.format(home_value[print_ten] * .06))
print('Benefit of buying over renting? {:,.2f}'.format(home_value[print_ten] - debt[print_ten]
- rent_savings[print_ten] - home_value[print_ten] * .06))
return {'home_value': home_value, 'debt': debt, 'equity': home_value - debt, 'savings_renting': rent_savings,
'benefit_buying': home_value - debt - rent_savings - (home_value * .06)}
def plotting(data):
plt.plot(data['home_value'], label='Home value')
plt.plot(data['debt'], label='Debt')
plt.plot(data['equity'], label='Equity')
plt.plot(data['savings_renting'], label="Savings when renting")
plt.plot(data['benefit_buying'], label='Benefit of buying')
plt.legend()
plt.annotate('Parms: house price {:,.0f}, ndownpayment {:,.0f}, ninterest annual {:.3f}, years {:.0f}, '
'naluguel {:,.0f}, ncash return annual {:.3f}, ninflation {:.3f},'
'ntabela: {} nhouse appreciation {:.3f}'.format(purchase_price, downpayment, interest, years,
initial_rent, return_cash, inflation, choice,
appreciation),
fontsize=9, xy=(0.43, 0.7), xycoords='axes fraction')
plt.savefig('res1.png')
plt.show()
if __name__ == '__main__':
purchase_price = 800000
downpayment = 0
interest = .08
years = 30
property_tax_rate = 0
yr_maintenance = 0
yr_comdominium = 0
yr_insurance = 0
appreciation = .03 # real appreciation 0%
income_tax_rate = 0 # income deduction on interest and property taxes paid
inflation = .03
initial_rent = purchase_price * .004 # 0.4 % of real values
return_cash = .06 # real return on cash 3%
time = 360
choice = 'SAC'
res = flow(purchase_price, downpayment, interest, years, property_tax_rate, yr_maintenance, yr_comdominium,
yr_insurance, appreciation, income_tax_rate, inflation, initial_rent, return_cash, time, choice)
plotting(res)
python datetime numpy finance
python datetime numpy finance
New contributor
New contributor
edited 2 days ago
New contributor
asked 2 days ago
B Furtado
1086
1086
New contributor
New contributor
add a comment |
add a comment |
1 Answer
1
active
oldest
votes
up vote
1
down vote
accepted
I can't cover everything that can be done to improve the code, so I will start by the most important parts. Once you incorporate these, you can post the updated version as a new question
variable names
the naming of functions, variables etc is more than half of the documentation of your code, so you should be very careful with it. Saving a few characters like maint
instead of yearly_maintenance
is not worth it. It made me go back and forth between the method definition and place where you call the method a few times.
Also make it clear which cost is yearly, and which is monthly.
You can also include some intermediary variable to clarify some things: loaned_amount = purchase_price - downpayment
split calculation with presentation
Your code both calculates the costs and gain, and does a lot of the presentation (for example print('Home value after {:.0f} years: {:,.2f}'.format(print_ten/12, home_value[print_ten]))
) in the same method. Separating these two will make testing the code and algorithm a lot easier. If you want to build a GUI later, you will be able to reuse the calculation, which is rather difficult now due to all the side-effects (print
)
vectorize
The costs which don't change every year, apart from appreciation or inflation, which are all apart from the loan repayments, can be easily vectorized:
months = years * 12
months_array = np.arange(months + 1)
home_value = purchase_price * (1 + appreciation / 12) ** months_array
maintenance = yearly_maintenance / 12 * (1 + inflation / 12) ** months_array
and then later summed.
split of more parts
The calculation of the amount due each month, or the amortization can be easily split of in different function
def monthly_payment(*, loaned_amount, months, monthly_interest_rate):
return (
loaned_amount
* (1 - 1 / (1 + monthly_interest_rate))
/ (1 - 1 / (1 + monthly_interest_rate) ** (months))
)
little exta comments is needed. The method does what it said in the name and variables. The only thing which might need explanation is the algorithm used.
def amortize(*, loaned_amount, yearly_interest_rate, monthly_payment):
monthly_interest_rate = yearly_interest_rate / 12
principal_paid = 0
interest = 0
yield loaned_amount, interest, principal_paid
while loaned_amount * (1+monthly_interest_rate) >= monthly_payment:
interest = loaned_amount * monthly_interest_rate
principal_paid = monthly_payment - interest
loaned_amount = loaned_amount - principal_paid
yield loaned_amount, interest, principal_paid
interest = loaned_amount * monthly_interest_rate
yield 0, interest, loaned_amount
Here, a generator
is more clear than appending items to 3 different lists, and then returning the lists in the end.
For both I used keyword-only arguments, which are a lot clearer after 2 years (no more questions: what argument came first...
)
and they are called like this:
elif system.lower() == "price":
monthly_amount = monthly_payment(
loaned_amount=loaned_amount,
months=months,
monthly_interest_rate=yearly_interest_rate / 12,
)
amortization = np.array(
list(
amortize(
loaned_amount=loaned_amount,
yearly_interest_rate=yearly_interest_rate,
monthly_payment=monthly_amount,
)
)
)
debt, interest_paid, principal_paid = np.split(amortization, 3, axis=1)
line length
Some of your lines were very long, requiring horizontal scrolling. Try to limit the length of the lines of code. I use the black formatter to take care of line lengths etc for me.
the whole thing
A (simplified) version of the flow
method:
def flow(
purchase_price,
downpayment,
yearly_interest_rate,
years,
property_tax_rate,
yearly_maintenance,
yearly_comdominium,
yearly_insurance,
appreciation,
income_tax_rate,
inflation,
initial_rent,
return_cash,
time,
system,
):
months = years * 12
months_array = np.arange(months + 1)
home_value = purchase_price * (1 + appreciation / 12) ** months_array
maintenance = yearly_maintenance / 12 * (1 + inflation / 12) ** months_array
insurance = yearly_insurance / 12 * (1 + inflation / 12) ** months_array
loaned_amount = purchase_price - downpayment
if system.upper() == "SAC":
debt = loaned_amount * (1 - months_array / months)
interest_paid = loaned_amount * yearly_interest_rate / 12
principal_paid = loaned_amount / months * np.ones_like(months_array)
elif system.lower() == "price":
monthly_amount = monthly_payment(
loaned_amount=loaned_amount,
months=months,
monthly_interest_rate=yearly_interest_rate / 12,
)
amortization = np.array(
list(
amortize(
loaned_amount=loaned_amount,
yearly_interest_rate=yearly_interest_rate,
monthly_payment=monthly_amount,
)
)
)
debt, interest_paid, principal_paid = np.split(amortization, 3, axis=1)
property_tax = home_value * property_tax_rate
income_tax = (interest_paid + property_tax) * income_tax_rate
cash_outflow = (
insurance
+ maintenance
+ property_tax
+ interest_paid
+ principal_paid
- income_tax
)
rent = initial_rent * (1 + appreciation / 12) ** months_array
rent_savings = (cash_outflow - rent) * (
1 + return_cash / 12
) ** months_array
return months, debt, rent_savings
the return
statement can be expanded. Instead of all the arrays in a tuple
, I would combine the either in a dict
or a pandas.DataFrame
.
This can be called like:
if __name__ == "__main__":
purchase_price = 800000
downpayment = 0
interest = 0.08
years = 20
property_tax_rate = 0
yearly_maintenance = 100
yearly_comdominium = 0
yearly_insurance = 0
appreciation = 0.03 # real appreciation 0%
income_tax_rate = 0 # income deduction on interest and property taxes paid
inflation = 0.03
initial_rent = purchase_price * 0.004 # 0.4 % of real values
return_cash = 0.06 # real return on cash 3%
time = 240
choice = "sac"
months, debt, rent_savings = flow(
purchase_price,
downpayment,
interest,
years,
property_tax_rate,
yearly_maintenance,
yearly_comdominium,
yearly_insurance,
appreciation,
income_tax_rate,
inflation,
initial_rent,
return_cash,
time,
choice,
)
rent_savings.sum()
add a comment |
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
1
down vote
accepted
I can't cover everything that can be done to improve the code, so I will start by the most important parts. Once you incorporate these, you can post the updated version as a new question
variable names
the naming of functions, variables etc is more than half of the documentation of your code, so you should be very careful with it. Saving a few characters like maint
instead of yearly_maintenance
is not worth it. It made me go back and forth between the method definition and place where you call the method a few times.
Also make it clear which cost is yearly, and which is monthly.
You can also include some intermediary variable to clarify some things: loaned_amount = purchase_price - downpayment
split calculation with presentation
Your code both calculates the costs and gain, and does a lot of the presentation (for example print('Home value after {:.0f} years: {:,.2f}'.format(print_ten/12, home_value[print_ten]))
) in the same method. Separating these two will make testing the code and algorithm a lot easier. If you want to build a GUI later, you will be able to reuse the calculation, which is rather difficult now due to all the side-effects (print
)
vectorize
The costs which don't change every year, apart from appreciation or inflation, which are all apart from the loan repayments, can be easily vectorized:
months = years * 12
months_array = np.arange(months + 1)
home_value = purchase_price * (1 + appreciation / 12) ** months_array
maintenance = yearly_maintenance / 12 * (1 + inflation / 12) ** months_array
and then later summed.
split of more parts
The calculation of the amount due each month, or the amortization can be easily split of in different function
def monthly_payment(*, loaned_amount, months, monthly_interest_rate):
return (
loaned_amount
* (1 - 1 / (1 + monthly_interest_rate))
/ (1 - 1 / (1 + monthly_interest_rate) ** (months))
)
little exta comments is needed. The method does what it said in the name and variables. The only thing which might need explanation is the algorithm used.
def amortize(*, loaned_amount, yearly_interest_rate, monthly_payment):
monthly_interest_rate = yearly_interest_rate / 12
principal_paid = 0
interest = 0
yield loaned_amount, interest, principal_paid
while loaned_amount * (1+monthly_interest_rate) >= monthly_payment:
interest = loaned_amount * monthly_interest_rate
principal_paid = monthly_payment - interest
loaned_amount = loaned_amount - principal_paid
yield loaned_amount, interest, principal_paid
interest = loaned_amount * monthly_interest_rate
yield 0, interest, loaned_amount
Here, a generator
is more clear than appending items to 3 different lists, and then returning the lists in the end.
For both I used keyword-only arguments, which are a lot clearer after 2 years (no more questions: what argument came first...
)
and they are called like this:
elif system.lower() == "price":
monthly_amount = monthly_payment(
loaned_amount=loaned_amount,
months=months,
monthly_interest_rate=yearly_interest_rate / 12,
)
amortization = np.array(
list(
amortize(
loaned_amount=loaned_amount,
yearly_interest_rate=yearly_interest_rate,
monthly_payment=monthly_amount,
)
)
)
debt, interest_paid, principal_paid = np.split(amortization, 3, axis=1)
line length
Some of your lines were very long, requiring horizontal scrolling. Try to limit the length of the lines of code. I use the black formatter to take care of line lengths etc for me.
the whole thing
A (simplified) version of the flow
method:
def flow(
purchase_price,
downpayment,
yearly_interest_rate,
years,
property_tax_rate,
yearly_maintenance,
yearly_comdominium,
yearly_insurance,
appreciation,
income_tax_rate,
inflation,
initial_rent,
return_cash,
time,
system,
):
months = years * 12
months_array = np.arange(months + 1)
home_value = purchase_price * (1 + appreciation / 12) ** months_array
maintenance = yearly_maintenance / 12 * (1 + inflation / 12) ** months_array
insurance = yearly_insurance / 12 * (1 + inflation / 12) ** months_array
loaned_amount = purchase_price - downpayment
if system.upper() == "SAC":
debt = loaned_amount * (1 - months_array / months)
interest_paid = loaned_amount * yearly_interest_rate / 12
principal_paid = loaned_amount / months * np.ones_like(months_array)
elif system.lower() == "price":
monthly_amount = monthly_payment(
loaned_amount=loaned_amount,
months=months,
monthly_interest_rate=yearly_interest_rate / 12,
)
amortization = np.array(
list(
amortize(
loaned_amount=loaned_amount,
yearly_interest_rate=yearly_interest_rate,
monthly_payment=monthly_amount,
)
)
)
debt, interest_paid, principal_paid = np.split(amortization, 3, axis=1)
property_tax = home_value * property_tax_rate
income_tax = (interest_paid + property_tax) * income_tax_rate
cash_outflow = (
insurance
+ maintenance
+ property_tax
+ interest_paid
+ principal_paid
- income_tax
)
rent = initial_rent * (1 + appreciation / 12) ** months_array
rent_savings = (cash_outflow - rent) * (
1 + return_cash / 12
) ** months_array
return months, debt, rent_savings
the return
statement can be expanded. Instead of all the arrays in a tuple
, I would combine the either in a dict
or a pandas.DataFrame
.
This can be called like:
if __name__ == "__main__":
purchase_price = 800000
downpayment = 0
interest = 0.08
years = 20
property_tax_rate = 0
yearly_maintenance = 100
yearly_comdominium = 0
yearly_insurance = 0
appreciation = 0.03 # real appreciation 0%
income_tax_rate = 0 # income deduction on interest and property taxes paid
inflation = 0.03
initial_rent = purchase_price * 0.004 # 0.4 % of real values
return_cash = 0.06 # real return on cash 3%
time = 240
choice = "sac"
months, debt, rent_savings = flow(
purchase_price,
downpayment,
interest,
years,
property_tax_rate,
yearly_maintenance,
yearly_comdominium,
yearly_insurance,
appreciation,
income_tax_rate,
inflation,
initial_rent,
return_cash,
time,
choice,
)
rent_savings.sum()
add a comment |
up vote
1
down vote
accepted
I can't cover everything that can be done to improve the code, so I will start by the most important parts. Once you incorporate these, you can post the updated version as a new question
variable names
the naming of functions, variables etc is more than half of the documentation of your code, so you should be very careful with it. Saving a few characters like maint
instead of yearly_maintenance
is not worth it. It made me go back and forth between the method definition and place where you call the method a few times.
Also make it clear which cost is yearly, and which is monthly.
You can also include some intermediary variable to clarify some things: loaned_amount = purchase_price - downpayment
split calculation with presentation
Your code both calculates the costs and gain, and does a lot of the presentation (for example print('Home value after {:.0f} years: {:,.2f}'.format(print_ten/12, home_value[print_ten]))
) in the same method. Separating these two will make testing the code and algorithm a lot easier. If you want to build a GUI later, you will be able to reuse the calculation, which is rather difficult now due to all the side-effects (print
)
vectorize
The costs which don't change every year, apart from appreciation or inflation, which are all apart from the loan repayments, can be easily vectorized:
months = years * 12
months_array = np.arange(months + 1)
home_value = purchase_price * (1 + appreciation / 12) ** months_array
maintenance = yearly_maintenance / 12 * (1 + inflation / 12) ** months_array
and then later summed.
split of more parts
The calculation of the amount due each month, or the amortization can be easily split of in different function
def monthly_payment(*, loaned_amount, months, monthly_interest_rate):
return (
loaned_amount
* (1 - 1 / (1 + monthly_interest_rate))
/ (1 - 1 / (1 + monthly_interest_rate) ** (months))
)
little exta comments is needed. The method does what it said in the name and variables. The only thing which might need explanation is the algorithm used.
def amortize(*, loaned_amount, yearly_interest_rate, monthly_payment):
monthly_interest_rate = yearly_interest_rate / 12
principal_paid = 0
interest = 0
yield loaned_amount, interest, principal_paid
while loaned_amount * (1+monthly_interest_rate) >= monthly_payment:
interest = loaned_amount * monthly_interest_rate
principal_paid = monthly_payment - interest
loaned_amount = loaned_amount - principal_paid
yield loaned_amount, interest, principal_paid
interest = loaned_amount * monthly_interest_rate
yield 0, interest, loaned_amount
Here, a generator
is more clear than appending items to 3 different lists, and then returning the lists in the end.
For both I used keyword-only arguments, which are a lot clearer after 2 years (no more questions: what argument came first...
)
and they are called like this:
elif system.lower() == "price":
monthly_amount = monthly_payment(
loaned_amount=loaned_amount,
months=months,
monthly_interest_rate=yearly_interest_rate / 12,
)
amortization = np.array(
list(
amortize(
loaned_amount=loaned_amount,
yearly_interest_rate=yearly_interest_rate,
monthly_payment=monthly_amount,
)
)
)
debt, interest_paid, principal_paid = np.split(amortization, 3, axis=1)
line length
Some of your lines were very long, requiring horizontal scrolling. Try to limit the length of the lines of code. I use the black formatter to take care of line lengths etc for me.
the whole thing
A (simplified) version of the flow
method:
def flow(
purchase_price,
downpayment,
yearly_interest_rate,
years,
property_tax_rate,
yearly_maintenance,
yearly_comdominium,
yearly_insurance,
appreciation,
income_tax_rate,
inflation,
initial_rent,
return_cash,
time,
system,
):
months = years * 12
months_array = np.arange(months + 1)
home_value = purchase_price * (1 + appreciation / 12) ** months_array
maintenance = yearly_maintenance / 12 * (1 + inflation / 12) ** months_array
insurance = yearly_insurance / 12 * (1 + inflation / 12) ** months_array
loaned_amount = purchase_price - downpayment
if system.upper() == "SAC":
debt = loaned_amount * (1 - months_array / months)
interest_paid = loaned_amount * yearly_interest_rate / 12
principal_paid = loaned_amount / months * np.ones_like(months_array)
elif system.lower() == "price":
monthly_amount = monthly_payment(
loaned_amount=loaned_amount,
months=months,
monthly_interest_rate=yearly_interest_rate / 12,
)
amortization = np.array(
list(
amortize(
loaned_amount=loaned_amount,
yearly_interest_rate=yearly_interest_rate,
monthly_payment=monthly_amount,
)
)
)
debt, interest_paid, principal_paid = np.split(amortization, 3, axis=1)
property_tax = home_value * property_tax_rate
income_tax = (interest_paid + property_tax) * income_tax_rate
cash_outflow = (
insurance
+ maintenance
+ property_tax
+ interest_paid
+ principal_paid
- income_tax
)
rent = initial_rent * (1 + appreciation / 12) ** months_array
rent_savings = (cash_outflow - rent) * (
1 + return_cash / 12
) ** months_array
return months, debt, rent_savings
the return
statement can be expanded. Instead of all the arrays in a tuple
, I would combine the either in a dict
or a pandas.DataFrame
.
This can be called like:
if __name__ == "__main__":
purchase_price = 800000
downpayment = 0
interest = 0.08
years = 20
property_tax_rate = 0
yearly_maintenance = 100
yearly_comdominium = 0
yearly_insurance = 0
appreciation = 0.03 # real appreciation 0%
income_tax_rate = 0 # income deduction on interest and property taxes paid
inflation = 0.03
initial_rent = purchase_price * 0.004 # 0.4 % of real values
return_cash = 0.06 # real return on cash 3%
time = 240
choice = "sac"
months, debt, rent_savings = flow(
purchase_price,
downpayment,
interest,
years,
property_tax_rate,
yearly_maintenance,
yearly_comdominium,
yearly_insurance,
appreciation,
income_tax_rate,
inflation,
initial_rent,
return_cash,
time,
choice,
)
rent_savings.sum()
add a comment |
up vote
1
down vote
accepted
up vote
1
down vote
accepted
I can't cover everything that can be done to improve the code, so I will start by the most important parts. Once you incorporate these, you can post the updated version as a new question
variable names
the naming of functions, variables etc is more than half of the documentation of your code, so you should be very careful with it. Saving a few characters like maint
instead of yearly_maintenance
is not worth it. It made me go back and forth between the method definition and place where you call the method a few times.
Also make it clear which cost is yearly, and which is monthly.
You can also include some intermediary variable to clarify some things: loaned_amount = purchase_price - downpayment
split calculation with presentation
Your code both calculates the costs and gain, and does a lot of the presentation (for example print('Home value after {:.0f} years: {:,.2f}'.format(print_ten/12, home_value[print_ten]))
) in the same method. Separating these two will make testing the code and algorithm a lot easier. If you want to build a GUI later, you will be able to reuse the calculation, which is rather difficult now due to all the side-effects (print
)
vectorize
The costs which don't change every year, apart from appreciation or inflation, which are all apart from the loan repayments, can be easily vectorized:
months = years * 12
months_array = np.arange(months + 1)
home_value = purchase_price * (1 + appreciation / 12) ** months_array
maintenance = yearly_maintenance / 12 * (1 + inflation / 12) ** months_array
and then later summed.
split of more parts
The calculation of the amount due each month, or the amortization can be easily split of in different function
def monthly_payment(*, loaned_amount, months, monthly_interest_rate):
return (
loaned_amount
* (1 - 1 / (1 + monthly_interest_rate))
/ (1 - 1 / (1 + monthly_interest_rate) ** (months))
)
little exta comments is needed. The method does what it said in the name and variables. The only thing which might need explanation is the algorithm used.
def amortize(*, loaned_amount, yearly_interest_rate, monthly_payment):
monthly_interest_rate = yearly_interest_rate / 12
principal_paid = 0
interest = 0
yield loaned_amount, interest, principal_paid
while loaned_amount * (1+monthly_interest_rate) >= monthly_payment:
interest = loaned_amount * monthly_interest_rate
principal_paid = monthly_payment - interest
loaned_amount = loaned_amount - principal_paid
yield loaned_amount, interest, principal_paid
interest = loaned_amount * monthly_interest_rate
yield 0, interest, loaned_amount
Here, a generator
is more clear than appending items to 3 different lists, and then returning the lists in the end.
For both I used keyword-only arguments, which are a lot clearer after 2 years (no more questions: what argument came first...
)
and they are called like this:
elif system.lower() == "price":
monthly_amount = monthly_payment(
loaned_amount=loaned_amount,
months=months,
monthly_interest_rate=yearly_interest_rate / 12,
)
amortization = np.array(
list(
amortize(
loaned_amount=loaned_amount,
yearly_interest_rate=yearly_interest_rate,
monthly_payment=monthly_amount,
)
)
)
debt, interest_paid, principal_paid = np.split(amortization, 3, axis=1)
line length
Some of your lines were very long, requiring horizontal scrolling. Try to limit the length of the lines of code. I use the black formatter to take care of line lengths etc for me.
the whole thing
A (simplified) version of the flow
method:
def flow(
purchase_price,
downpayment,
yearly_interest_rate,
years,
property_tax_rate,
yearly_maintenance,
yearly_comdominium,
yearly_insurance,
appreciation,
income_tax_rate,
inflation,
initial_rent,
return_cash,
time,
system,
):
months = years * 12
months_array = np.arange(months + 1)
home_value = purchase_price * (1 + appreciation / 12) ** months_array
maintenance = yearly_maintenance / 12 * (1 + inflation / 12) ** months_array
insurance = yearly_insurance / 12 * (1 + inflation / 12) ** months_array
loaned_amount = purchase_price - downpayment
if system.upper() == "SAC":
debt = loaned_amount * (1 - months_array / months)
interest_paid = loaned_amount * yearly_interest_rate / 12
principal_paid = loaned_amount / months * np.ones_like(months_array)
elif system.lower() == "price":
monthly_amount = monthly_payment(
loaned_amount=loaned_amount,
months=months,
monthly_interest_rate=yearly_interest_rate / 12,
)
amortization = np.array(
list(
amortize(
loaned_amount=loaned_amount,
yearly_interest_rate=yearly_interest_rate,
monthly_payment=monthly_amount,
)
)
)
debt, interest_paid, principal_paid = np.split(amortization, 3, axis=1)
property_tax = home_value * property_tax_rate
income_tax = (interest_paid + property_tax) * income_tax_rate
cash_outflow = (
insurance
+ maintenance
+ property_tax
+ interest_paid
+ principal_paid
- income_tax
)
rent = initial_rent * (1 + appreciation / 12) ** months_array
rent_savings = (cash_outflow - rent) * (
1 + return_cash / 12
) ** months_array
return months, debt, rent_savings
the return
statement can be expanded. Instead of all the arrays in a tuple
, I would combine the either in a dict
or a pandas.DataFrame
.
This can be called like:
if __name__ == "__main__":
purchase_price = 800000
downpayment = 0
interest = 0.08
years = 20
property_tax_rate = 0
yearly_maintenance = 100
yearly_comdominium = 0
yearly_insurance = 0
appreciation = 0.03 # real appreciation 0%
income_tax_rate = 0 # income deduction on interest and property taxes paid
inflation = 0.03
initial_rent = purchase_price * 0.004 # 0.4 % of real values
return_cash = 0.06 # real return on cash 3%
time = 240
choice = "sac"
months, debt, rent_savings = flow(
purchase_price,
downpayment,
interest,
years,
property_tax_rate,
yearly_maintenance,
yearly_comdominium,
yearly_insurance,
appreciation,
income_tax_rate,
inflation,
initial_rent,
return_cash,
time,
choice,
)
rent_savings.sum()
I can't cover everything that can be done to improve the code, so I will start by the most important parts. Once you incorporate these, you can post the updated version as a new question
variable names
the naming of functions, variables etc is more than half of the documentation of your code, so you should be very careful with it. Saving a few characters like maint
instead of yearly_maintenance
is not worth it. It made me go back and forth between the method definition and place where you call the method a few times.
Also make it clear which cost is yearly, and which is monthly.
You can also include some intermediary variable to clarify some things: loaned_amount = purchase_price - downpayment
split calculation with presentation
Your code both calculates the costs and gain, and does a lot of the presentation (for example print('Home value after {:.0f} years: {:,.2f}'.format(print_ten/12, home_value[print_ten]))
) in the same method. Separating these two will make testing the code and algorithm a lot easier. If you want to build a GUI later, you will be able to reuse the calculation, which is rather difficult now due to all the side-effects (print
)
vectorize
The costs which don't change every year, apart from appreciation or inflation, which are all apart from the loan repayments, can be easily vectorized:
months = years * 12
months_array = np.arange(months + 1)
home_value = purchase_price * (1 + appreciation / 12) ** months_array
maintenance = yearly_maintenance / 12 * (1 + inflation / 12) ** months_array
and then later summed.
split of more parts
The calculation of the amount due each month, or the amortization can be easily split of in different function
def monthly_payment(*, loaned_amount, months, monthly_interest_rate):
return (
loaned_amount
* (1 - 1 / (1 + monthly_interest_rate))
/ (1 - 1 / (1 + monthly_interest_rate) ** (months))
)
little exta comments is needed. The method does what it said in the name and variables. The only thing which might need explanation is the algorithm used.
def amortize(*, loaned_amount, yearly_interest_rate, monthly_payment):
monthly_interest_rate = yearly_interest_rate / 12
principal_paid = 0
interest = 0
yield loaned_amount, interest, principal_paid
while loaned_amount * (1+monthly_interest_rate) >= monthly_payment:
interest = loaned_amount * monthly_interest_rate
principal_paid = monthly_payment - interest
loaned_amount = loaned_amount - principal_paid
yield loaned_amount, interest, principal_paid
interest = loaned_amount * monthly_interest_rate
yield 0, interest, loaned_amount
Here, a generator
is more clear than appending items to 3 different lists, and then returning the lists in the end.
For both I used keyword-only arguments, which are a lot clearer after 2 years (no more questions: what argument came first...
)
and they are called like this:
elif system.lower() == "price":
monthly_amount = monthly_payment(
loaned_amount=loaned_amount,
months=months,
monthly_interest_rate=yearly_interest_rate / 12,
)
amortization = np.array(
list(
amortize(
loaned_amount=loaned_amount,
yearly_interest_rate=yearly_interest_rate,
monthly_payment=monthly_amount,
)
)
)
debt, interest_paid, principal_paid = np.split(amortization, 3, axis=1)
line length
Some of your lines were very long, requiring horizontal scrolling. Try to limit the length of the lines of code. I use the black formatter to take care of line lengths etc for me.
the whole thing
A (simplified) version of the flow
method:
def flow(
purchase_price,
downpayment,
yearly_interest_rate,
years,
property_tax_rate,
yearly_maintenance,
yearly_comdominium,
yearly_insurance,
appreciation,
income_tax_rate,
inflation,
initial_rent,
return_cash,
time,
system,
):
months = years * 12
months_array = np.arange(months + 1)
home_value = purchase_price * (1 + appreciation / 12) ** months_array
maintenance = yearly_maintenance / 12 * (1 + inflation / 12) ** months_array
insurance = yearly_insurance / 12 * (1 + inflation / 12) ** months_array
loaned_amount = purchase_price - downpayment
if system.upper() == "SAC":
debt = loaned_amount * (1 - months_array / months)
interest_paid = loaned_amount * yearly_interest_rate / 12
principal_paid = loaned_amount / months * np.ones_like(months_array)
elif system.lower() == "price":
monthly_amount = monthly_payment(
loaned_amount=loaned_amount,
months=months,
monthly_interest_rate=yearly_interest_rate / 12,
)
amortization = np.array(
list(
amortize(
loaned_amount=loaned_amount,
yearly_interest_rate=yearly_interest_rate,
monthly_payment=monthly_amount,
)
)
)
debt, interest_paid, principal_paid = np.split(amortization, 3, axis=1)
property_tax = home_value * property_tax_rate
income_tax = (interest_paid + property_tax) * income_tax_rate
cash_outflow = (
insurance
+ maintenance
+ property_tax
+ interest_paid
+ principal_paid
- income_tax
)
rent = initial_rent * (1 + appreciation / 12) ** months_array
rent_savings = (cash_outflow - rent) * (
1 + return_cash / 12
) ** months_array
return months, debt, rent_savings
the return
statement can be expanded. Instead of all the arrays in a tuple
, I would combine the either in a dict
or a pandas.DataFrame
.
This can be called like:
if __name__ == "__main__":
purchase_price = 800000
downpayment = 0
interest = 0.08
years = 20
property_tax_rate = 0
yearly_maintenance = 100
yearly_comdominium = 0
yearly_insurance = 0
appreciation = 0.03 # real appreciation 0%
income_tax_rate = 0 # income deduction on interest and property taxes paid
inflation = 0.03
initial_rent = purchase_price * 0.004 # 0.4 % of real values
return_cash = 0.06 # real return on cash 3%
time = 240
choice = "sac"
months, debt, rent_savings = flow(
purchase_price,
downpayment,
interest,
years,
property_tax_rate,
yearly_maintenance,
yearly_comdominium,
yearly_insurance,
appreciation,
income_tax_rate,
inflation,
initial_rent,
return_cash,
time,
choice,
)
rent_savings.sum()
answered 2 hours ago
Maarten Fabré
4,239417
4,239417
add a comment |
add a comment |
B Furtado is a new contributor. Be nice, and check out our Code of Conduct.
B Furtado is a new contributor. Be nice, and check out our Code of Conduct.
B Furtado is a new contributor. Be nice, and check out our Code of Conduct.
B Furtado is a new contributor. Be nice, and check out our Code of Conduct.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f207586%2frenting-vs-owning-comparison-calculation%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown