Skip to content

Instantly share code, notes, and snippets.

@arssher
Last active January 23, 2026 07:38
Show Gist options
  • Select an option

  • Save arssher/68560ba0d588a20fcdeb23f81db3effc to your computer and use it in GitHub Desktop.

Select an option

Save arssher/68560ba0d588a20fcdeb23f81db3effc to your computer and use it in GitHub Desktop.
vovsu donimaet
ars@nonlibrem ~ $ mortage.py -y 30 --mortage-payment 71946 -i 6 -r 60000 -s 1 --renovation 2000000 --down-payment 3000000 --loan 12000000
30
inflation factor: 0.0600, skip years: 1, loan: 12000000, down_payment: 3000000, renovation: 2000000
year 0: monthly payment_i_a=71946.00, payment_sum_i_a=863352.00, payment_sum=863352.00, debt=11852639.37, debt_i_a=11181735.26, monthly rental=60000.00, rental_sum=0.00, yearly b=-863352.00, b=-863352.00, full_b=-2863352.00, rental profit=0.00, investments=5863352.00, owned_value=3818264.74, assets=3818264.74, CAGR=-34.88%
year 1: monthly payment_i_a=67873.58, payment_sum_i_a=1677835.02, payment_sum=1726704.00, debt=11696189.86, debt_i_a=10409567.34, monthly rental=60000.00, rental_sum=720000.00, yearly b=-94483.02, b=-957835.02, full_b=-2957835.02, rental profit=0.00, investments=5957835.02, owned_value=4590432.66, assets=4590432.66, CAGR=-12.22%
year 2: monthly payment_i_a=64031.68, payment_sum_i_a=2446215.23, payment_sum=2590056.00, debt=11530090.89, debt_i_a=9680886.65, monthly rental=60000.00, rental_sum=1440000.00, yearly b=-48380.21, b=-1006215.23, full_b=-3006215.23, rental profit=0.00, investments=6006215.23, owned_value=5319113.35, assets=5319113.35, CAGR=-3.97%
year 3: monthly payment_i_a=60407.25, payment_sum_i_a=3171102.21, payment_sum=3453408.00, debt=11353747.30, debt_i_a=8993231.29, monthly rental=60000.00, rental_sum=2160000.00, yearly b=-4886.99, b=-1011102.21, full_b=-3011102.21, rental profit=0.00, investments=6011102.21, owned_value=6006768.71, assets=6006768.71, CAGR=-0.02%
year 4: monthly payment_i_a=56987.97, payment_sum_i_a=3854957.86, payment_sum=4316760.00, debt=11166527.22, debt_i_a=8344278.72, monthly rental=60000.00, rental_sum=2880000.00, yearly b=36144.35, b=-974957.86, full_b=-2974957.86, rental profit=36144.35, investments=6011102.21, owned_value=6655721.28, assets=6691865.63, CAGR=2.17%
year 5: monthly payment_i_a=53762.24, payment_sum_i_a=4500104.70, payment_sum=5180112.00, debt=10967759.81, debt_i_a=7731837.88, monthly rental=60000.00, rental_sum=3600000.00, yearly b=74853.16, b=-900104.70, full_b=-2900104.70, rental profit=110997.51, investments=6011102.21, owned_value=7268162.12, assets=7379159.63, CAGR=3.48%
year 6: monthly payment_i_a=50719.09, payment_sum_i_a=5108733.79, payment_sum=6043464.00, debt=10756732.87, debt_i_a=7153841.71, monthly rental=60000.00, rental_sum=4320000.00, yearly b=111370.91, b=-788733.79, full_b=-2788733.79, rental profit=222368.42, investments=6011102.21, owned_value=7846158.29, assets=8068526.71, CAGR=4.29%
year 7: monthly payment_i_a=47848.20, payment_sum_i_a=5682912.18, payment_sum=6906816.00, debt=10532690.24, debt_i_a=6608340.16, monthly rental=60000.00, rental_sum=5040000.00, yearly b=145821.61, b=-642912.18, full_b=-2642912.18, rental profit=368190.03, investments=6011102.21, owned_value=8391659.84, assets=8759849.87, CAGR=4.82%
year 8: monthly payment_i_a=45139.81, payment_sum_i_a=6224589.91, payment_sum=7770168.00, debt=10294829.16, debt_i_a=6093493.56, monthly rental=60000.00, rental_sum=5760000.00, yearly b=178322.27, b=-464589.91, full_b=-2464589.91, rental profit=546512.31, investments=6011102.21, owned_value=8906506.44, assets=9453018.75, CAGR=5.16%
year 9: monthly payment_i_a=42584.73, payment_sum_i_a=6735606.63, payment_sum=8633520.00, debt=10042297.32, debt_i_a=5607566.37, monthly rental=60000.00, rental_sum=6480000.00, yearly b=208983.28, b=-255606.63, full_b=-2255606.63, rental profit=755495.58, investments=6011102.21, owned_value=9392433.63, assets=10147929.21, CAGR=5.38%
year 10: monthly payment_i_a=40174.27, payment_sum_i_a=7217697.88, payment_sum=9496872.00, debt=9774189.88, debt_i_a=5148921.30, monthly rental=60000.00, rental_sum=7200000.00, yearly b=237908.75, b=-17697.88, full_b=-2017697.88, rental profit=993404.34, investments=6011102.21, owned_value=9851078.70, assets=10844483.04, CAGR=5.51%
year 11: monthly payment_i_a=37900.26, payment_sum_i_a=7672500.94, payment_sum=10360224.00, debt=9489546.15, debt_i_a=4716013.71, monthly rental=60000.00, rental_sum=7920000.00, yearly b=265196.94, b=247499.06, full_b=-1752500.94, rental profit=1258601.27, investments=6011102.21, owned_value=10283986.29, assets=11542587.56, CAGR=5.59%
year 12: monthly payment_i_a=35754.96, payment_sum_i_a=8101560.43, payment_sum=11223576.00, debt=9187346.22, debt_i_a=4307386.42, monthly rental=60000.00, rental_sum=8640000.00, yearly b=290940.51, b=538439.57, full_b=-1461560.43, rental profit=1549541.78, investments=6011102.21, owned_value=10692613.58, assets=12242155.36, CAGR=5.62%
year 13: monthly payment_i_a=33731.09, payment_sum_i_a=8506333.54, payment_sum=12086928.00, debt=8866507.26, debt_i_a=3921664.71, monthly rental=60000.00, rental_sum=9360000.00, yearly b=315226.89, b=853666.46, full_b=-1146333.54, rental profit=1864768.67, investments=6011102.21, owned_value=11078335.29, assets=12943103.96, CAGR=5.63%
year 14: monthly payment_i_a=31821.79, payment_sum_i_a=8888194.96, payment_sum=12950280.00, debt=8525879.66, debt_i_a=3557551.69, monthly rental=60000.00, rental_sum=10080000.00, yearly b=338138.58, b=1191805.04, full_b=-808194.96, rental profit=2202907.25, investments=6011102.21, owned_value=11442448.31, assets=13645355.55, CAGR=5.62%
year 15: monthly payment_i_a=30020.55, payment_sum_i_a=9248441.59, payment_sum=13813632.00, debt=8164242.89, debt_i_a=3213823.87, monthly rental=60000.00, rental_sum=10800000.00, yearly b=359753.38, b=1551558.41, full_b=-448441.59, rental profit=2562660.62, investments=6011102.21, owned_value=11786176.13, assets=14348836.75, CAGR=5.59%
year 16: monthly payment_i_a=28321.28, payment_sum_i_a=9588296.89, payment_sum=14676984.00, debt=7780301.16, debt_i_a=2889327.02, monthly rental=60000.00, rental_sum=11520000.00, yearly b=380144.69, b=1931703.11, full_b=-68296.89, rental profit=2942805.32, investments=6011102.21, owned_value=12110672.98, assets=15053478.30, CAGR=5.55%
year 17: monthly payment_i_a=26718.18, payment_sum_i_a=9908915.11, payment_sum=15540336.00, debt=7372678.74, debt_i_a=2582972.22, monthly rental=60000.00, rental_sum=12240000.00, yearly b=399381.79, b=2331084.89, full_b=331084.89, rental profit=3342187.10, investments=6011102.21, owned_value=12417027.78, assets=15759214.88, CAGR=5.50%
year 18: monthly payment_i_a=25205.83, payment_sum_i_a=10211385.12, payment_sum=16403688.00, debt=6939915.06, debt_i_a=2293732.22, monthly rental=60000.00, rental_sum=12960000.00, yearly b=417529.99, b=2748614.88, full_b=748614.88, rental profit=3759717.09, investments=6011102.21, owned_value=12706267.78, assets=16465984.87, CAGR=5.45%
year 19: monthly payment_i_a=23779.09, payment_sum_i_a=10496734.19, payment_sum=17267040.00, debt=6480459.47, debt_i_a=2020637.89, monthly rental=60000.00, rental_sum=13680000.00, yearly b=434650.93, b=3183265.81, full_b=1183265.81, rental profit=4194368.02, investments=6011102.21, owned_value=12979362.11, assets=17173730.13, CAGR=5.39%
year 20: monthly payment_i_a=22433.10, payment_sum_i_a=10765931.42, payment_sum=18130392.00, debt=5992665.66, debt_i_a=1762774.98, monthly rental=60000.00, rental_sum=14400000.00, yearly b=450802.77, b=3634068.58, full_b=1634068.58, rental profit=4645170.79, investments=6011102.21, owned_value=13237225.02, assets=17882395.81, CAGR=5.33%
year 21: monthly payment_i_a=21163.30, payment_sum_i_a=11019891.08, payment_sum=18993744.00, debt=5474785.79, debt_i_a=1519280.96, monthly rental=60000.00, rental_sum=15120000.00, yearly b=466040.34, b=4100108.92, full_b=2100108.92, rental profit=5111211.13, investments=6011102.21, owned_value=13480719.04, assets=18591930.17, CAGR=5.27%
year 22: monthly payment_i_a=19965.38, payment_sum_i_a=11259475.66, payment_sum=19857096.00, debt=4924964.23, debt_i_a=1289342.15, monthly rental=60000.00, rental_sum=15840000.00, yearly b=480415.42, b=4580524.34, full_b=2580524.34, rental profit=5591626.55, investments=6011102.21, owned_value=13710657.85, assets=19302284.41, CAGR=5.20%
year 23: monthly payment_i_a=18835.27, payment_sum_i_a=11485498.85, payment_sum=20720448.00, debt=4341230.87, debt_i_a=1072190.90, monthly rental=60000.00, rental_sum=16560000.00, yearly b=493976.81, b=5074501.15, full_b=3074501.15, rental profit=6085603.36, investments=6011102.21, owned_value=13927809.10, assets=20013412.46, CAGR=5.14%
year 24: monthly payment_i_a=17769.12, payment_sum_i_a=11698728.27, payment_sum=21583800.00, debt=3721494.12, debt_i_a=867103.03, monthly rental=60000.00, rental_sum=17280000.00, yearly b=506770.58, b=5581271.73, full_b=3581271.73, rental profit=6592373.94, investments=6011102.21, owned_value=14132896.97, assets=20725270.91, CAGR=5.08%
year 25: monthly payment_i_a=16763.32, payment_sum_i_a=11899888.11, payment_sum=22447152.00, debt=3063533.37, debt_i_a=673395.36, monthly rental=60000.00, rental_sum=18000000.00, yearly b=518840.17, b=6100111.89, full_b=4100111.89, rental profit=7111214.11, investments=6011102.21, owned_value=14326604.64, assets=21437818.75, CAGR=5.01%
year 26: monthly payment_i_a=15814.45, payment_sum_i_a=12089661.53, payment_sum=23310504.00, debt=2364991.03, debt_i_a=490423.35, monthly rental=60000.00, rental_sum=18720000.00, yearly b=530226.57, b=6630338.47, full_b=4630338.47, rental profit=7641440.68, investments=6011102.21, owned_value=14509576.65, assets=22151017.33, CAGR=4.95%
year 27: monthly payment_i_a=14919.29, payment_sum_i_a=12268693.07, payment_sum=24173856.00, debt=1623364.13, debt_i_a=317578.96, monthly rental=60000.00, rental_sum=19440000.00, yearly b=540968.46, b=7171306.93, full_b=5171306.93, rental profit=8182409.14, investments=6011102.21, owned_value=14682421.04, assets=22864830.18, CAGR=4.89%
year 28: monthly payment_i_a=14074.81, payment_sum_i_a=12437590.75, payment_sum=25037208.00, debt=835995.31, debt_i_a=154288.57, monthly rental=60000.00, rental_sum=20160000.00, yearly b=551102.32, b=7722409.25, full_b=5722409.25, rental profit=8733511.47, investments=6011102.21, owned_value=14845711.43, assets=23579222.90, CAGR=4.83%
year 29: monthly payment_i_a=13278.12, payment_sum_i_a=12596928.17, payment_sum=25900560.00, debt=63.30, debt_i_a=11.02, monthly rental=60000.00, rental_sum=20880000.00, yearly b=560662.57, b=8283071.83, full_b=6283071.83, rental profit=9294174.04, investments=6011102.21, owned_value=14999988.98, assets=24294163.02, CAGR=4.77%
#!/usr/bin/env python3
import argparse
import sys
# Calculate lost of purchasing power of value after 1 year of inflation with rate inflation_f.
def lpp(value, inflation_f):
return value * (1 / (1 + inflation_f))
def lpp_n_years(value, inflation_f, n_years):
return value * (1 / (1 + inflation_f))**n_years
def lpp_test():
v1 = lpp(100, 0.03)
print(f"lpp test: {v1:.2f}")
v2 = lpp_n_years(100, 0.03, 5)
print(f"lpp_n_years test: {v2:.2f}")
# cagrs as a fraction
def CAGR(initial, end, n_years):
# print(f"calculating cagr: initial={initial}, end={end}, n_years={n_years}")
return (end / initial)**(1 / n_years) - 1
def cagr_test():
c1 = CAGR(100, 200, 1)
c2 = CAGR(1000.0, 1980, 6)
print(f"cagr test: {c1:.2%}")
print(f"cagr test: {c2:.2%}")
c3 = CAGR(863352.00, 863352.00 + 720000.00, 1)
print(f"cagr test: {c3:.2%}")
'''
Notes:
- Mortage conf is assumed to be calculated elsewhere, here we just take monthly
payment, years and loan size as input. Defaults are for 12m for 30 years at 6%
interest. We still need rate to calculate payments interest / body parts.
- Inflation is used to calculate mortage payment reduction over time. Default 6% is
conservative I'd say.
- Realty price is assumed to grow exactly with inflation, so we assume no
profit/loss here and so no calculations are done. Which is also conservative.
- Rental is assumed to grow with exactly inflation too, again we don't do anything here.
- Amortization, taxes etc are assumed to be included into rental.
- if you think mortage is a typo, it is not
'''
if __name__ == '__main__':
parser = argparse.ArgumentParser(description="""
calculate some vovsu donimaet
""")
parser.add_argument("-y", help="years", type=int)
parser.add_argument("--mortage-payment", help="monthly mortage payment", type=int, default=71946)
parser.add_argument("--mortage-rate", help="mortage rate", type=float, default=6.0)
parser.add_argument("-r", help="monthly rental", type=int)
parser.add_argument("-i", help="inflation in %", type=float, default=6.0)
parser.add_argument("-s", help="how many years to skip before rental starts", type=int, default=3)
parser.add_argument("-d", "--down-payment", help="down payment", type=int, default=3000000)
parser.add_argument("-l", "--loan", help="loan size", type=int, default=12000000)
parser.add_argument("--renovation", help="renovation cost. 50k per 1m2 seems reasonable. Unlike down payment, not assumed to be returned when sold, which is not clear actually", type=int, default=2000000)
args = parser.parse_args()
print(args.y)
years = args.y
payment = args.mortage_payment
mortage_rate_f = args.mortage_rate / 100.0
rental = args.r
inflation_f = args.i / 100.0
skip_years = args.s
down_payment = args.down_payment
loan = args.loan
price = down_payment + loan
remaining_debt = loan
# initial
renovation = args.renovation
print(f"inflation factor: {inflation_f:.4f}, skip years: {skip_years}, loan: {loan}, down_payment: {down_payment}, renovation: {renovation}")
payment_inf_adjusted = payment
# sum of loan payed out
payment_sum_inf_adjusted = 0
payment_sum = 0
# sum of investments to cover payment while rental is not enough
payment_investments = 0
rental_sum = 0
# part of rental left after covering payments
rental_profit = 0
for i in range(0, years):
for m in range(0, 12):
monthly_bank_interest = remaining_debt * (mortage_rate_f / 12)
monthly_body = payment - monthly_bank_interest
remaining_debt -= monthly_body
# print(f"year {i} month {m}: interest={monthly_bank_interest:.2f}, body={monthly_body:.2f}, remaining_loan={remaining_loan:.2f}")
remaining_debt_inf_adjusted = lpp_n_years(remaining_debt, inflation_f, i + 1)
payment_yearly_inf_adjusted = payment_inf_adjusted * 12
payment_sum_inf_adjusted += payment_yearly_inf_adjusted
payment_sum += payment * 12
# Pure this year rental income not broke up into payment and profit parts
if i >= skip_years:
yearly_rental = rental * 12
else:
yearly_rental = 0
# Pure rental income not broke up into payment and profit parts
rental_sum += yearly_rental
# Break rental into payment and profit because putting it into payment reduces investments.
if yearly_rental <= payment_yearly_inf_adjusted:
# all rental goes to payment + we need investments to cover the rest
payment_investments += payment_yearly_inf_adjusted - yearly_rental
else:
# rental covers payment, the rest is profit
rental_profit += yearly_rental - payment_yearly_inf_adjusted
# Total (cumulative) rental minus payment balance. Note that these
# balances describe what you have on hands while the realty is not sold;
# IOW, they ignore accumulating owned part of the property and thus look
# a bit sad.
balance = rental_sum - payment_sum_inf_adjusted
# current year rental minus payment balance
yearly_balance = yearly_rental - payment_yearly_inf_adjusted
# takes into account renovation but not down payment because the latter is assumed to be returned when selling
full_balance = balance - args.renovation
investments = down_payment + renovation + payment_investments
# note: again, renovation is not included in assets as not assumed to be
# returned when selling
# Models payoff & sell.
owned_value = price - remaining_debt_inf_adjusted
assets = owned_value + rental_profit
# You might want to compare with non existing linear payout model
# owned_value_lm = down_payment + (i + 1) / years * loan + rental_profit
# Note that in this basic model with mortage % == inflation % (free
# loan) and realty price changing exactly with inflation (buying +
# selling gives zero), if you ignore renovation & down payment, profit
# just equals rental_sum.
cagr = CAGR(investments, assets, i + 1)
# Interesting points:
# - when payment_inf_adjusted gets to rental, i.e. thing becomes self sustainable
# - when accumulated the rest of rental - payment_inf_adjusted buys back the initial investments
# - total (mostly initial) investments size
print(f"year {i}: monthly payment_i_a={payment_inf_adjusted:.2f}, payment_sum_i_a={payment_sum_inf_adjusted:.2f}, payment_sum={payment_sum:.2f}, debt={remaining_debt:.2f}, debt_i_a={remaining_debt_inf_adjusted:.2f}, monthly rental={rental:.2f}, rental_sum={rental_sum:.2f}, yearly b={yearly_balance:.2f}, b={balance:.2f}, full_b={full_balance:.2f}, rental profit={rental_profit:.2f}, investments={investments:.2f}, owned_value={owned_value:.2f}, assets={assets:.2f}, CAGR={cagr:.2%}")
payment_inf_adjusted = lpp(payment_inf_adjusted, inflation_f)
# not changing rental assumes it changes with inflation
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment