Rent vs. Buy Calculator
rent_vs_buyCalculation, not advice. Verify with a professional before acting. Deterministic rent-vs-buy decision model. Given a home price, monthly rent, and mortgage rate, computes the breakeven month (when BUY net worth first equals or exceeds RENT net worth), per-horizon net-worth comparison (years 5, 10, 30 + user horizon), and the full year-by-year cost/wealth series for both paths. Includes carrying costs (property tax, insurance, maintenance, PMI, HOA) on the BUY path and opportunity-cost investing on the RENT path. Optional federal tax benefit model (Tier-3: apply_tax_benefit=true) with TY2025/TY2026 SALT caps, mortgage interest deduction, PMI deductibility, and marginal-excess formula. All assumptions cite primary sources (FHFA, BLS, Harvard JCHS, IRS Pub 936, OBBBA Pub. L. 119-21) and can be overridden. HEAVY tool: use output='summary' (default) for scalar headline or output='inline' for chart series. output='capture' writes the full payload to a file on this server's local disk for the chart-render pipeline; available on the local stdio transport only, and rejected with a structured error on the hosted HTTP transport.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| toolArguments | Yes | JSON object with parameters: TIER 0 - REQUIRED (the instant answer renders from these three): home_price: decimal > 0 monthly_rent: decimal >= 0 (0 is valid for free-housing baseline) mortgage_rate_pct: decimal in (0, 100]; e.g. 6.75 for 6.75%. Never cached; provide current rate. TIER 1 - PRE-FILLED (defaults are cited; omit to use the default): down_payment_pct: decimal [0, 100] (default: 20%). 0 is valid (zero-down programs). loan_term_months: int > 0 (default: 360 = 30-year fixed) horizon_years: int [1, 40] (default: returns snapshots at years 5, 10, 30) hoa_monthly: decimal >= 0 (default: 0) TIER 2 - SOFT OVERRIDES (defaults from cited national sources; override for your market): home_appreciation_pct: decimal. Annual home price appreciation % (default: 4.25%, FHFA HPI). rent_growth_pct: decimal. Annual rent escalation % (default: 3.4%, BLS CPI ROPR). maintenance_pct: decimal. Annual maintenance as % of home value (default: 1.5%, Harvard JCHS). sell_side_pct: decimal. Sell-side transaction cost % of sale price (default: 7.5%, Redfin post-NAR). property_tax_pct: decimal. Annual property tax as % of home value (default: 0.88%). home_insurance_pct: decimal. Annual insurance as % of home value (default: 0.65%). pmi_pct: decimal. Annual PMI rate as % of loan (default: 0.5%). Removal threshold is set by pmi_removal_ltv_pct (below). pmi_removal_ltv_pct: decimal 50-100 (optional). Sets the loan-balance trigger for PMI removal: omitted, it is the 78% HPA automatic-termination threshold; provided (e.g. 80), it is whichever of 78% or your value is reached first. Either way PMI also stops at the statutory amortization midpoint of the original term (12 U.S.C. §4901(7), §4902(c)), which this value cannot postpone. investment_return_pct: decimal. RENT path annual return %, an EFFECTIVE ANNUAL rate; the monthly compounding step is (1+pct/100)^(1/12)-1 (default: 10.0%). inflation_pct: decimal. Inflation % for real-terms toggle (default: 2.5%). real_terms: bool. Deflate the output series for real-terms view (default: false). basis_capitalizable_pct_override: decimal [0, 100]. Fraction of the buy-side closing cost that is capitalizable into the §121 adjusted basis (IRS Pub 523 split: abstract fees, title search, recording fees, survey fees, transfer taxes, owner's title insurance). Default: 50% (Senaro deterministic midpoint). Supply your actual HUD-1 split when available. 0 = HomePrice-only basis; 100 = full closing cost in basis. TIER 3 - TAX REFINEMENT (only used when apply_tax_benefit = true): apply_tax_benefit: bool (default: false). The §121 home-sale gain exclusion applies only at sale points 24 months or more after purchase (IRC §121(a) 2-of-5-year test); year 1 of yearly_series, months 1-23 in monthly_series, and any horizon under 24 months use no exclusion. Separately, IRC §1222(3) makes a holding period of 12 months or less short-term, taxed at ordinary rates instead of the long-term rates otherwise applied, on the home-sale gain and the renter's portfolio gain alike (24 months vs. 12 months are two different thresholds); this tool applies that split exactly to the home-sale gain, and to the renter's portfolio at annual grain: prior years' contributions are compounded together as one long-term lot rather than aged individually, so months inside a year understate short-term gain. filing_status: 'Single' | 'MFJ' | 'MFS' | 'HoH' (REQUIRED when apply_tax_benefit = true) tax_year: 2025 | 2026 (REQUIRED when apply_tax_benefit = true) annual_gross_income: decimal >= 0 (REQUIRED when apply_tax_benefit = true; MAGI proxy for bracket/SALT) state_local_tax: decimal >= 0 (optional, default 0; SALT for the SALT cap, state income or sales tax paid) charitable: decimal >= 0 (optional, default 0; charitable contributions. TY2026+: 0.5%-AGI floor per OBBBA §70111) other_itemizable: decimal >= 0 (optional, default 0; medical above 7.5% AGI, casualty losses, etc.) age_65_plus_count: int 0 to 2 (optional; adds additional standard deduction per qualifying filer) blind_count: int 0 to 2 (optional; adds additional standard deduction per qualifying blind filer) loan_origination_date: string YYYY-MM-DD (optional; pre-12/15/2017 gets $1M cap, post gets $750k) pmi_annual: decimal >= 0 (optional; if omitted, derived from pmi_pct x average loan balance) purchase_year_points: decimal >= 0 (optional; discount points at origination, % of loan; paid in cash at closing and deducted in year 1) ENVELOPE: output: 'summary' (default) | 'inline' | 'capture' summary: headline scalars + per-horizon snapshots; heavy series stripped (chart-friendly) inline: full payload including yearly_series[] + monthly_series[] (for chart rendering) capture: full payload written to ~/.senaro/captures/; capture_ref URI returned. Available on the local stdio transport only; the hosted HTTP transport rejects 'capture' with a structured error naming 'summary' and 'inline' as the valid alternatives. chart_title: string (optional) override for the chart title. Must not contain em-dashes or en-dashes. Max 120 characters. |