The input parameters for the simulation.
Annual investment fee rate (e.g. ETF MER or platform/advisor fee) expressed as a decimal (e.g. 0.0025 for 0.25%). Applied monthly to TFSA and stock portfolio balances using a multiplicative model — the fee is charged on the grown balance. The monthly dollar cost is also tracked as tfsaFees and stocksFees under monthlyExpenses and cumulativeExpenses in the output.
Configuration for the buyer scenarios.
The down payment amount. Must meet the minimum required down payment in Canada based on the purchase price.
Whether the buyer is a first-time owner, used to calculate land transfer tax rebates.
The adjustment applied to the posted fixed mortgage rate (added to the posted rate).
The minimum interest rate (posted + adjustment) for mortgages.
Whether the buyer invests any monthly savings (difference between their expenses and the renter's/max expenses) into the stock market. If false, these savings are discarded (simulating lifestyle inflation or other spending).
Fixed fees associated with the purchase (e.g., notary). Do not include land transfer tax here, as it is calculated automatically based on the city.
The purchase price of the home.
The real estate commission rate for selling the home (e.g., 0.05 for 5%).
Fixed fees associated with selling the home (before sales tax).
The initial annual maintenance cost.
The initial annual property tax.
The initial monthly condo fees.
The initial monthly homeowner's insurance.
The adjustment applied to the variable mortgage rate (added to the posted rate).
The city where the home is located, used to calculate land transfer tax and derive the province for sales and income taxes.
Whether to simulate investments and taxes for a couple doubling TFSA contribution room and splitting capital gains in 2. Assumes each per-month value in parameters.values.employmentIncome represents the per-partner income.
The duration of the simulation in years.
Annualized growth rates over the simulation period. Each array should have a length of numberOfYears * 12. These can be historical or projected rates.
Monthly home appreciation rates.
Monthly condo fee increase rates.
Monthly maintenance cost increase rates.
Monthly market return rates.
Monthly homeowner's insurance increase rates.
Monthly property tax increase rates.
Monthly renter's insurance increase rates.
Monthly rent increase rates.
Monthly increase rates for selling fixed fees.
Configuration for the renter scenario.
The initial security deposit.
The initial monthly renter's insurance.
The initial monthly rent payment.
The year the simulation begins.
Whether to prioritize TFSA contributions for investments (tax-free gains).
Shared absolute values over the simulation period. Each array should have a length of numberOfYears * 12.
Annual employment income at each simulated month, used for calculating marginal income tax rates on investment gains.
Monthly 5-year fixed mortgage interest rates.
Monthly 4-year fixed mortgage interest rates.
Monthly 1-year fixed mortgage interest rates.
Monthly 3-year fixed mortgage interest rates.
Monthly 2-year fixed mortgage interest rates.
Monthly variable mortgage interest rates.
Additional simulation options.
OptionaladjustToInflation?: The rate parameter used as a proxy for inflation to express future dollar values in today's constant dollars. When set (e.g. to "sellingFixedFeesIncrease"), point-in-time metrics (like monthlyExpenses, assets, and balance) are discounted by the current month's inflation factor. Cumulative totals (like cumulativeExpenses and cumulativeGains) accumulate real values incrementally — meaning each nominal monthly contribution is discounted before being added to the running sum. One-time upfront costs paid at month 0 (downPayment, purchaseFixedFees, landTransferTax, insurancePremiumTax, securityDeposit) are not discounted because their real value already equals their nominal value. Defaults to undefined (no adjustment).
Optionalgroups?: string[]Internal filter used by simulateRentVsBuyMonteCarlo via details.filterGroups. Restricts which groups are emitted by onRecord and pushed to results.
OptionalonRecord?: (Internal callback used by simulateRentVsBuyMonteCarlo when details.iterations or details.quantiles is enabled. When provided, numeric values are streamed directly to the accumulator instead of being wrapped in result objects, avoiding the per-record heap allocation cost. At the final month, one winner record (the winVariable entry) per category is still pushed to the results array for winner extraction.
OptionalonSnapshotRecord?: (category: string, monthIndex: number, amount: number) => voidOptionalsnapshotMonths?: Set<number>Optionalvariables?: string[]Internal filter used by simulateRentVsBuyMonteCarlo via details.filterVariables. Restricts which individual variables within allowed groups are emitted by onRecord. An empty array is treated as no filter.
OptionalwinVariable?: "balance" | "balanceAfterSelling" | "assets"The variable used to identify the winner when extracting the final record. Use "balanceAfterSelling" for net balance after a simulated sale, "balance" for cumulative balance, or "assets" for total raw assets.
OptionalwinVariableOnly?: booleanIf true, the returned results will only include the final winVariable record for each scenario (one entry per scenario at the final month). Requires winVariable to be set — throws if winVariableOnly is true but winVariable is not provided. Defaults to false.
A detailed array of monthly results for each scenario (renter, buyerFixed, buyerVariable).
If the down payment is less than the minimum required down payment in Canada. Each object in the array represents a specific data point for a given month, categorized by:
monthlyExpenses or cumulativeExpenses:
rent, insurance, securityDeposit (for Renter)mortgageCapital, mortgageInterests, maintenance, propertyTax, condoFees, downPayment, purchaseFixedFees, insurancePremiumTax (for Buyers)tfsaFees, stocksFees (for all scenarios)monthlyGains or cumulativeGains:
tfsaGains, tfsaContribution, stocksGains, newStocks (for all scenarios)homeEquityGains (for Buyers)assets:
tfsa, stocks (for all scenarios)securityDeposit (for Renter)homeEquity (for Buyers)summary: balance (monthly net worth)summaryCumulative: balance (cumulative net worth), balanceAfterSelling (net worth after hypothetical property sale and associated taxes/fees)saleCosts: stockTaxes (includes employmentIncome used for calculation), homeSellingCommission, homeSellingFixedFees, mortgagePenalty, mortgageBalance (hypothetical costs incurred upon selling)saleNetGains: stockSellingGains, tfsaSellingGains, homeSellingGains, securityDeposit (hypothetical gains realized upon selling)monthlyRecurringExpenses: rent, insurance, mortgageCapital, mortgageInterests, maintenance, propertyTax, condoFees, tfsaFees, stocksFees — same values as the corresponding monthlyExpenses variables, restricted to costs that recur every month.monthlyNonRecurringExpenses: downPayment, purchaseFixedFees, landTransferTax, insurancePremiumTax, securityDeposit — same values as the corresponding monthlyExpenses variables, restricted to one-time upfront costs (nonzero only at month 0).totals: monthlyExpenses, cumulativeExpenses, monthlyGains, cumulativeGains, assets, saleCosts, saleNetGains, monthlyRecurringExpenses, monthlyNonRecurringExpenses (sum of all variables in each respective group; always emitted even when zero)const rates = {
marketReturnRate: new Array(120).fill(0.005), // 0.5% monthly
rentIncrease: new Array(120).fill(0.002),
ownerInsuranceIncrease: new Array(120).fill(0.002),
renterInsuranceIncrease: new Array(120).fill(0.002),
maintenanceIncrease: new Array(120).fill(0.002),
propertyTaxIncrease: new Array(120).fill(0.002),
condoFeeIncrease: new Array(120).fill(0.002),
appreciationIncrease: new Array(120).fill(0.003),
sellingFixedFeesIncrease: new Array(120).fill(0.002),
};
const values = {
employmentIncome: new Array(120).fill(75000),
fiveYearInterestRates: new Array(120).fill(0.05),
fourYearInterestRates: new Array(120).fill(0.05),
threeYearInterestRates: new Array(120).fill(0.05),
twoYearInterestRates: new Array(120).fill(0.05),
oneYearInterestRates: new Array(120).fill(0.05),
variableInterestRates: new Array(120).fill(0.06),
};
const results = simulateRentVsBuy({
startingYear: 2024,
numberOfYears: 10,
tfsaContributions: true,
annualInvestmentFeeRate: 0,
couple: false,
city: "Toronto",
renter: {
startingMonthlyRent: 2000,
securityDeposit: 2000,
startingMonthlyInsurance: 30,
},
buyer: {
downPayment: 100000,
purchasePrice: 500000,
fixedRateAdjustment: -0.015,
variableRateAdjustment: -0.005,
firstTimeOwner: true, investsSavings: true,
purchaseFixedFees: 2000,
startingAnnualMaintenanceCost: 2000,
startingAnnualPropertyTax: 3000,
startingMonthlyCondoFees: 300,
startingMonthlyInsurance: 100,
sellingFixedFees: 2000,
sellingCommissionRate: 0.05,
floorRate: 0.01,
investsSavings: true,
},
values,
rates,
}, { winVariableOnly: true, winVariable: "balanceAfterSelling" });
Simulates and compares the financial outcomes of renting versus buying a home over a specified number of years. This comprehensive simulation accounts for various factors including mortgage payments (fixed and variable), property taxes, maintenance costs, condo fees, insurance, rent increases, market returns on savings, and the eventual sale of the property. Tailored for a Canadian context, it includes specific features like tax-free TFSA contributions and standard Canadian mortgage structures.
The simulation tracks three scenarios:
It provides a detailed breakdown of monthly expenses, gains, assets, and a final summary including the net balance after selling the property and paying all associated costs (taxes, legal fees, penalties).