{
"nbformat": 4,
"nbformat_minor": 0,
"metadata": {
"colab": {
"provenance": [],
"authorship_tag": "ABX9TyNHrbOlQwbl+NDlyCWef9lE",
"include_colab_link": true
},
"kernelspec": {
"name": "python3",
"display_name": "Python 3"
},
"language_info": {
"name": "python"
}
},
"cells": [
{
"cell_type": "markdown",
"metadata": {
"id": "view-in-github",
"colab_type": "text"
},
"source": [
""
]
},
{
"cell_type": "markdown",
"source": [
"# Monte Carlo Retirement Simulator\n",
"\n",
"A **Monte Carlo simulation** is used to model the potential outcomes of a retirement portfolio, starting with an initial withdrawal rate and running calculations on a **monthly basis**. The simulation uses historical data from **Robert Shiller**, including the **S&P 500 index**, dividends, **Consumer Price Index (CPI)**, and **10-year Treasury bond interest rates (GS10)** between the years of 1871 and 2023. The portfolio consists of two asset classes: the S&P 500 to represent equities and an **intermediate-term bond fund based on 7-year-duration** approximations using GS10 data for fixed income. A target allocation can be specified (e.g., **70% stocks, 30% bonds**), and the portfolio is periodically **rebalanced** to maintain this allocation.\n",
"\n",
"To maintain realism, all calculations are performed in an **inflation-adjusted** manner using the CPI to account for changes in purchasing power over time. The simulation applies a **block bootstrap** approach, where blocks of consecutive months are resampled from historical data to preserve patterns of autocorrelation, providing a realistic range of outcomes that consider the historical relationship between stocks and bonds. **Transaction costs** are included during the rebalancing process, but it is assumed that the funds are held in **tax-advantaged accounts**, so no taxes on capital gains or dividends are considered.\n",
"\n",
"The simulation now includes two withdrawal strategies:\n",
"\n",
"- **Constant Withdrawal Strategy:** Withdraws a fixed inflation-adjusted amount annually based on the initial withdrawal rate (e.g., 4%). This amount remains constant throughout the simulation, providing predictable income but not adjusting for changes in portfolio performance.\n",
"\n",
"- **Dynamic Withdrawal Strategy (akin to Vanguard's Dynamic Spending Rule):** Implements an optional dynamic withdrawal strategy inspired by Vanguard's dynamic spending rule. In this approach, the annual withdrawal amount is adjusted each year based on the portfolio's performance, within specified **ceiling** and **floor** limits to prevent drastic changes in spending. Specifically, the withdrawal amount is recalculated annually as a fixed percentage (e.g., 4%) of the current portfolio value. The year-over-year change in the withdrawal amount is then constrained by the ceiling (maximum increase) and floor (maximum decrease). This strategy aims to balance the need for stable income with the sustainability of the portfolio, potentially reducing the likelihood of depleting funds during retirement.\n",
"\n",
"If we set the block size equal to the full length of the simulation (e.g., 30 years), the approach essentially turns into *backtesting* rather than a Monte Carlo simulation, which one may prefer to do. For example, with a block size equal to the full simulation, each \"block\" would cover an entire historical sequence of returns and inflation from the dataset instead of resampling shorter blocks and stitching them together to create new sequences.\n",
"\n",
"## Some Caveats of the Simulation Approach\n",
"\n",
"- **Assumption of Stationarity:** The simulation assumes that the historical returns, correlations, volatilities, and inflation are representative of future conditions (stationarity).\n",
"\n",
"- **Only S&P 500 Equity:** No small-cap stocks, international stocks, or real estate diversification included.\n",
"\n",
"- **Independence of Simulated Blocks:** Even though block bootstrapping is used to preserve autocorrelation, it still treats different resampled blocks as independent. This approach may not fully account for long-term trends or extended periods of poor market performance.\n",
"\n",
"- **Ignoring Tax Implications:** The simulation does not consider taxes on capital gains, dividends, or interest income. This is reasonable assuming that the funds are in tax-advantaged accounts like 401(k)s and IRAs (i.e., rebalancing doesn't generate taxable events).\n",
"\n",
"- **Transaction Cost Simplifications:** The model applies fixed and percentage-based transaction costs during rebalancing but does not account for other potential costs, such as bid-ask spreads or market-impact costs, which can be significant for large portfolios.\n",
"\n",
"- **Withdrawal Strategy Considerations:** While the simulation now includes both constant and dynamic withdrawal strategies, it does not account for more complex spending needs or changes in personal circumstances that may affect withdrawal amounts.\n",
"\n",
"- **No Modeling of Sequence of Returns Risk Beyond Block Size:** Although block bootstrapping helps preserve some patterns of returns, it may not fully capture the impact of sequence of returns risk, where the timing of poor market performance (especially early in retirement) can have a disproportionate effect on the outcome. The dynamic withdrawal strategy may help mitigate this risk by adjusting spending in response to portfolio performance.\n",
"\n",
"- **Assumption of Constant Asset Allocation:** The model assumes a fixed target allocation between stocks and bonds, which may not be realistic over a long time horizon. Investors may choose to adjust their asset allocation as they age or in response to market conditions.\n",
"\n",
"- **No Incorporation of Cash Flows Outside Withdrawals:** The simulation does not account for additional contributions or withdrawals, such as Social Security benefits, pensions, or large expenses, which can impact the portfolio's longevity.\n",
"\n",
"- **Simplified Rebalancing:** Rebalancing is done at fixed intervals (e.g., every three months). In reality, investors may rebalance based on market conditions or when the asset allocation drifts beyond certain thresholds.\n",
"\n",
"\n",
"# License Information\n",
"\n",
"## Code License: BSD 3-Clause License\n",
"\n",
"Copyright © 2024, Hari Bharadwaj.\n",
"All rights reserved.\n",
"\n",
"Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n",
"\n",
"1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer.\n",
"\n",
"2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution.\n",
"\n",
"3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\n",
"\n",
"**Disclaimer**: THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n",
"\n",
"\n",
"## Text/Images License: CC-BY-NC-SA 4.0\n",
"\n",
"Any accompanying text and images, including plots, are licensed under the [Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License (CC-BY-NC-SA 4.0)](https://creativecommons.org/licenses/by-nc-sa/4.0/).\n",
"\n",
"![Creative Commons License](https://mirrors.creativecommons.org/presskit/buttons/88x31/svg/by-nc-sa.svg)\n",
"\n"
],
"metadata": {
"id": "IxAXJEvno_eT"
}
},
{
"cell_type": "markdown",
"source": [
"# Download and prepare historical data\n",
"First, download CSV file from Dropbox and load it into a pandas DataFrame. The CSV file was generated by downloading Shiller's data from [his official link](http://www.econ.yale.edu/~shiller/data.htm) and selecting a subset of columns. The selected columns include the S&P 500 price, dividends, Consumer Price Index (CPI), and the 10-year Treasury bond interest rate (GS10). We'll calculate the historical monthly returns for stocks (S&P 500) and an intermediate-term bond fund (i.e., assuming GS10 rates and a 7 year duration). We'll also calculate monthly changes in the CPI for inflation adjustments. All simulations will be done with inflation adjusted historical data (i.e., \"real\" returns). As a sanity check, histograms of (inflation-adjusted) stock and bond returns, and a histogram of inflation is plotted and annotated with annualized returns and volatility."
],
"metadata": {
"id": "yAzr8dOpPLdq"
}
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/",
"height": 657
},
"cellView": "form",
"id": "ONFG7Ul-J39O",
"outputId": "f03c865f-3f20-4709-920f-099d92ab48d8"
},
"outputs": [
{
"output_type": "display_data",
"data": {
"text/plain": [
"