Files
workspace/tools/re-breakeven.py

111 lines
4.5 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env python3
"""Find break-even scenarios for rental property cash flow Day 1"""
# Fixed assumptions
MONTHLY_RENT = 2000
VACANCY = 0.05
EFFECTIVE_MONTHLY = MONTHLY_RENT * (1 - VACANCY) # $1,900
PROPERTY_TAX_RATE = 0.007 # ~$2400 on $345K
INSURANCE_RATE = 0.004 # ~$1400 on $345K
MAINTENANCE_RATE = 0.006 # ~$2000 on $345K
DOWN_PAYMENT_PCT = 0.20
print("=" * 70)
print("BREAK-EVEN ANALYSIS: What price + rate = Day 1 cash flow positive?")
print("=" * 70)
print(f"\nFixed: Rent $2,000/mo | Vacancy 5% | Effective income: ${EFFECTIVE_MONTHLY:,.0f}/mo")
print(f"Down payment: 20% | 30-year fixed\n")
# Calculate monthly mortgage payment
def monthly_payment(principal, annual_rate, years=30):
r = annual_rate / 12
n = years * 12
if r == 0:
return principal / n
return principal * (r * (1 + r)**n) / ((1 + r)**n - 1)
print(f"{'Price':>10} {'Rate':>6} {'Down':>10} {'Loan':>10} {'P&I':>8} {'Tax/Ins':>8} {'Maint':>7} {'Total':>8} {'Cash Flow':>10} {'Rent/Price':>10}")
print("-" * 100)
results = []
for price in range(200000, 360000, 10000):
for rate_bps in range(300, 700, 25):
rate = rate_bps / 10000
down = price * DOWN_PAYMENT_PCT
loan = price * (1 - DOWN_PAYMENT_PCT)
pi = monthly_payment(loan, rate)
tax_ins = (price * PROPERTY_TAX_RATE + price * INSURANCE_RATE) / 12
maint = (price * MAINTENANCE_RATE) / 12
total_monthly = pi + tax_ins + maint
cash_flow = EFFECTIVE_MONTHLY - total_monthly
rent_to_price = (MONTHLY_RENT / price) * 100
results.append((price, rate, down, loan, pi, tax_ins, maint, total_monthly, cash_flow, rent_to_price))
# Show scenarios that are cash flow positive or near break-even
print("\n📗 CASH FLOW POSITIVE SCENARIOS (Day 1):")
print("-" * 100)
positive = [r for r in results if r[8] >= 0]
for r in sorted(positive, key=lambda x: -x[8])[:20]:
price, rate, down, loan, pi, tax_ins, maint, total, cf, rtp = r
print(f"${price:>9,} {rate:>5.2%} ${down:>9,} ${loan:>9,} ${pi:>7,.0f} ${tax_ins:>7,.0f} ${maint:>6,.0f} ${total:>7,.0f} ${cf:>+8,.0f} {rtp:.2f}%")
print(f"\n\n📕 YOUR CURRENT DEAL ($345K @ 6.25%):")
price, rate = 345000, 0.0625
down = price * DOWN_PAYMENT_PCT
loan = price * (1 - DOWN_PAYMENT_PCT)
pi = monthly_payment(loan, rate)
tax_ins = (price * PROPERTY_TAX_RATE + price * INSURANCE_RATE) / 12
maint = (price * MAINTENANCE_RATE) / 12
total = pi + tax_ins + maint
cf = EFFECTIVE_MONTHLY - total
print(f"${price:>9,} {rate:>5.2%} ${down:>9,} ${loan:>9,} ${pi:>7,.0f} ${tax_ins:>7,.0f} ${maint:>6,.0f} ${total:>7,.0f} ${cf:>+8,.0f} {(MONTHLY_RENT/price)*100:.2f}%")
# Find exact break-even rate at different price points
print(f"\n\n📊 BREAK-EVEN INTEREST RATE BY PRICE POINT:")
print("-" * 50)
for price in [200000, 220000, 240000, 260000, 280000, 300000, 320000, 345000]:
for rate_bps in range(100, 1000, 1):
rate = rate_bps / 10000
loan = price * (1 - DOWN_PAYMENT_PCT)
pi = monthly_payment(loan, rate)
tax_ins = (price * PROPERTY_TAX_RATE + price * INSURANCE_RATE) / 12
maint = (price * MAINTENANCE_RATE) / 12
total = pi + tax_ins + maint
cf = EFFECTIVE_MONTHLY - total
if cf <= 0:
# Previous rate was break-even
be_rate = (rate_bps - 1) / 10000
print(f" ${price:>9,} → break-even at {be_rate:.2%} or lower")
break
else:
print(f" ${price:>9,} → cash flows positive even at 10%+")
# Find exact break-even price at different rates
print(f"\n\n📊 BREAK-EVEN PRICE BY INTEREST RATE:")
print("-" * 50)
for rate_pct in [3.0, 3.5, 4.0, 4.5, 5.0, 5.5, 6.0, 6.25]:
rate = rate_pct / 100
for price in range(400000, 100000, -1000):
loan = price * (1 - DOWN_PAYMENT_PCT)
pi = monthly_payment(loan, rate)
tax_ins = (price * PROPERTY_TAX_RATE + price * INSURANCE_RATE) / 12
maint = (price * MAINTENANCE_RATE) / 12
total = pi + tax_ins + maint
cf = EFFECTIVE_MONTHLY - total
if cf >= 0:
print(f" {rate_pct:.2f}% → max price ${price:>9,} (rent/price: {(MONTHLY_RENT/price)*100:.2f}%)")
break
else:
print(f" {rate_pct:.2f}% → no viable price found")
# The 1% rule check
print(f"\n\n📊 1% RULE CHECK:")
print(f" $2,000 rent × 100 = $200,000 max purchase price")
print(f" Your deal: $345,000 = {(2000/345000)*100:.2f}% (needs to be ≥1.0%)")
print(f" To hit 1% at $345K, rent needs to be: ${345000*0.01:,.0f}/mo")
print(f" To hit 0.8% at $345K, rent needs to be: ${345000*0.008:,.0f}/mo")