Skip to content

Instantly share code, notes, and snippets.

@westurner
Last active July 13, 2023 23:15
Show Gist options
  • Save westurner/c4f75b4983e716d73cbff78626ad4713 to your computer and use it in GitHub Desktop.
Save westurner/c4f75b4983e716d73cbff78626ad4713 to your computer and use it in GitHub Desktop.
savings_interest_and_future_value.ipynb
Display the source blob
Display the rendered blob
Raw
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Savings, Interest, and Future Value\n",
"- `fv()` https://numpy.org/doc/1.17/reference/generated/numpy.fv.html#numpy.fv\n",
"- `FV()` https://support.google.com/docs/answer/3093224?hl=en\n",
"- `FV()` https://support.office.com/en-us/article/fv-function-2eef9f44-a084-4c61-bdd8-4fe4bb1b71b3\n",
"- `FV()` https://wiki.openoffice.org/wiki/Documentation/How_Tos/Calc:_FV_function"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"#!pip install numpy_financial pandas\n",
"#import numpy as npf\n",
"import numpy_financial as npf\n",
"import pandas as pd"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [],
"source": [
"def annual_interest_to_daily_simple(rate):\n",
" return rate / 365\n",
"\n",
"def annual_interest_to_daily_compounding(rate):\n",
" return (((1+rate) ** (1/365)) - 1)"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"'$ 1.7660088312053745e+18 after 200 years at 10.0 % APR'"
]
},
"execution_count": 3,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"savings_target = 145_000_000_000\n",
"\n",
"interest_rate_annual = 0.10\n",
"n_years = 200\n",
"\n",
"interest_rate_daily = annual_interest_to_daily_simple(interest_rate_annual)\n",
"rate = interest_rate_daily\n",
"nper = 365 * n_years\n",
"pmt = pmt_ = -1_000_000\n",
"pv = 0\n",
"\n",
"fv = npf.fv(rate, nper, pmt, pv)\n",
"f'$ {fv:,} after {n_years} years at {interest_rate_annual*100} % APR'"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"array([-0.00000000e+00, 1.00000000e+06, 2.00027397e+06, ...,\n",
" 1.76455811e+18, 1.76504155e+18, 1.76552513e+18])"
]
},
"execution_count": 4,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"fv_array = npf.fv(rate, range(0, nper), pmt, pv)\n",
"#f'{fv:,}'\n",
"fv_array"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>value</th>\n",
" </tr>\n",
" <tr>\n",
" <th>days</th>\n",
" <th></th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>-0.000000e+00</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>1.000000e+06</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>2.000274e+06</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>3.000822e+06</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>4.001644e+06</td>\n",
" </tr>\n",
" <tr>\n",
" <th>...</th>\n",
" <td>...</td>\n",
" </tr>\n",
" <tr>\n",
" <th>72995</th>\n",
" <td>1.763592e+18</td>\n",
" </tr>\n",
" <tr>\n",
" <th>72996</th>\n",
" <td>1.764075e+18</td>\n",
" </tr>\n",
" <tr>\n",
" <th>72997</th>\n",
" <td>1.764558e+18</td>\n",
" </tr>\n",
" <tr>\n",
" <th>72998</th>\n",
" <td>1.765042e+18</td>\n",
" </tr>\n",
" <tr>\n",
" <th>72999</th>\n",
" <td>1.765525e+18</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"<p>73000 rows × 1 columns</p>\n",
"</div>"
],
"text/plain": [
" value\n",
"days \n",
"0 -0.000000e+00\n",
"1 1.000000e+06\n",
"2 2.000274e+06\n",
"3 3.000822e+06\n",
"4 4.001644e+06\n",
"... ...\n",
"72995 1.763592e+18\n",
"72996 1.764075e+18\n",
"72997 1.764558e+18\n",
"72998 1.765042e+18\n",
"72999 1.765525e+18\n",
"\n",
"[73000 rows x 1 columns]"
]
},
"execution_count": 5,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"df = pd.DataFrame.from_records(\n",
" enumerate(fv_array),\n",
" index='days',\n",
" columns=['days', 'value'])\n",
"df"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"<matplotlib.axes._subplots.AxesSubplot at 0x7f8be8c8dc10>"
]
},
"execution_count": 6,
"metadata": {},
"output_type": "execute_result"
},
{
"data": {
"image/png": "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\n",
"text/plain": [
"<Figure size 432x288 with 1 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
}
],
"source": [
"df.plot(title=f'at {interest_rate_annual*100} % APR')"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"0.02\n",
"0.05\n",
"0.1\n",
"0.2\n"
]
},
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>0.02</th>\n",
" <th>0.05</th>\n",
" <th>0.1</th>\n",
" <th>0.2</th>\n",
" </tr>\n",
" <tr>\n",
" <th>days</th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>-0.000000e+00</td>\n",
" <td>-0.000000e+00</td>\n",
" <td>-0.000000e+00</td>\n",
" <td>-0.000000e+00</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>1.000000e+06</td>\n",
" <td>1.000000e+06</td>\n",
" <td>1.000000e+06</td>\n",
" <td>1.000000e+06</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>2.000055e+06</td>\n",
" <td>2.000137e+06</td>\n",
" <td>2.000274e+06</td>\n",
" <td>2.000548e+06</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>3.000164e+06</td>\n",
" <td>3.000411e+06</td>\n",
" <td>3.000822e+06</td>\n",
" <td>3.001644e+06</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>4.000329e+06</td>\n",
" <td>4.000822e+06</td>\n",
" <td>4.001644e+06</td>\n",
" <td>4.003289e+06</td>\n",
" </tr>\n",
" <tr>\n",
" <th>...</th>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" </tr>\n",
" <tr>\n",
" <th>72995</th>\n",
" <td>9.777841e+11</td>\n",
" <td>1.605658e+14</td>\n",
" <td>1.763592e+18</td>\n",
" <td>4.237356e+26</td>\n",
" </tr>\n",
" <tr>\n",
" <th>72996</th>\n",
" <td>9.778387e+11</td>\n",
" <td>1.605878e+14</td>\n",
" <td>1.764075e+18</td>\n",
" <td>4.239678e+26</td>\n",
" </tr>\n",
" <tr>\n",
" <th>72997</th>\n",
" <td>9.778933e+11</td>\n",
" <td>1.606098e+14</td>\n",
" <td>1.764558e+18</td>\n",
" <td>4.242001e+26</td>\n",
" </tr>\n",
" <tr>\n",
" <th>72998</th>\n",
" <td>9.779479e+11</td>\n",
" <td>1.606318e+14</td>\n",
" <td>1.765042e+18</td>\n",
" <td>4.244325e+26</td>\n",
" </tr>\n",
" <tr>\n",
" <th>72999</th>\n",
" <td>9.780025e+11</td>\n",
" <td>1.606538e+14</td>\n",
" <td>1.765525e+18</td>\n",
" <td>4.246651e+26</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"<p>73000 rows × 4 columns</p>\n",
"</div>"
],
"text/plain": [
" 0.02 0.05 0.1 0.2\n",
"days \n",
"0 -0.000000e+00 -0.000000e+00 -0.000000e+00 -0.000000e+00\n",
"1 1.000000e+06 1.000000e+06 1.000000e+06 1.000000e+06\n",
"2 2.000055e+06 2.000137e+06 2.000274e+06 2.000548e+06\n",
"3 3.000164e+06 3.000411e+06 3.000822e+06 3.001644e+06\n",
"4 4.000329e+06 4.000822e+06 4.001644e+06 4.003289e+06\n",
"... ... ... ... ...\n",
"72995 9.777841e+11 1.605658e+14 1.763592e+18 4.237356e+26\n",
"72996 9.778387e+11 1.605878e+14 1.764075e+18 4.239678e+26\n",
"72997 9.778933e+11 1.606098e+14 1.764558e+18 4.242001e+26\n",
"72998 9.779479e+11 1.606318e+14 1.765042e+18 4.244325e+26\n",
"72999 9.780025e+11 1.606538e+14 1.765525e+18 4.246651e+26\n",
"\n",
"[73000 rows x 4 columns]"
]
},
"execution_count": 7,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"data = {}\n",
"for rate in [0.02, 0.05, 0.1, 0.2]:\n",
" print(rate)\n",
" rate_daily = annual_interest_to_daily_simple(rate)\n",
" data[str(rate)] = npf.fv(rate_daily, range(0, nper), pmt, pv)\n",
"df = pd.DataFrame.from_records(data)\n",
"df.index.name = 'days'\n",
"df"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"<matplotlib.axes._subplots.AxesSubplot at 0x7f8be688cfd0>"
]
},
"execution_count": 8,
"metadata": {},
"output_type": "execute_result"
},
{
"data": {
"image/png": "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\n",
"text/plain": [
"<Figure size 432x288 with 1 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
}
],
"source": [
"df[f'savings_target={savings_target:,}'] = savings_target\n",
"df.plot(xlim=(0, nper), ylim=(0, savings_target*1.1), title=f'days until ${savings_target:,}')"
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th>interest rate</th>\n",
" <th>days</th>\n",
" <th>years</th>\n",
" <th>value</th>\n",
" <th>value_without_interest</th>\n",
" <th>diff</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0.02</th>\n",
" <td>39,989.00</td>\n",
" <td>109.56</td>\n",
" <td>145,000,059,420.29</td>\n",
" <td>39,989,000,000.00</td>\n",
" <td>105,011,059,420.29</td>\n",
" </tr>\n",
" <tr>\n",
" <th>0.05</th>\n",
" <td>22,179.00</td>\n",
" <td>60.76</td>\n",
" <td>145,005,054,636.52</td>\n",
" <td>22,179,000,000.00</td>\n",
" <td>122,826,054,636.52</td>\n",
" </tr>\n",
" <tr>\n",
" <th>0.1</th>\n",
" <td>13,532.00</td>\n",
" <td>37.07</td>\n",
" <td>145,003,286,468.73</td>\n",
" <td>13,532,000,000.00</td>\n",
" <td>131,471,286,468.73</td>\n",
" </tr>\n",
" <tr>\n",
" <th>0.2</th>\n",
" <td>8,010.00</td>\n",
" <td>21.95</td>\n",
" <td>145,026,084,836.17</td>\n",
" <td>8,010,000,000.00</td>\n",
" <td>137,016,084,836.17</td>\n",
" </tr>\n",
" <tr>\n",
" <th>savings_target=145,000,000,000</th>\n",
" <td>None</td>\n",
" <td>None</td>\n",
" <td>None</td>\n",
" <td>None</td>\n",
" <td>None</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
"interest rate days years value \\\n",
"0.02 39,989.00 109.56 145,000,059,420.29 \n",
"0.05 22,179.00 60.76 145,005,054,636.52 \n",
"0.1 13,532.00 37.07 145,003,286,468.73 \n",
"0.2 8,010.00 21.95 145,026,084,836.17 \n",
"savings_target=145,000,000,000 None None None \n",
"\n",
"interest rate value_without_interest diff \n",
"0.02 39,989,000,000.00 105,011,059,420.29 \n",
"0.05 22,179,000,000.00 122,826,054,636.52 \n",
"0.1 13,532,000,000.00 131,471,286,468.73 \n",
"0.2 8,010,000,000.00 137,016,084,836.17 \n",
"savings_target=145,000,000,000 None None "
]
},
"execution_count": 9,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"summary_str = f\"If you saved ${pmt*-1:,} a day, you'd have ${savings_target:,} after\"\n",
"\n",
"years_until = {}\n",
"for column in df:\n",
" col = df[column]\n",
" output = col[col > savings_target].head(1)\n",
" # print([column, output])\n",
" if output.empty:\n",
" days = None\n",
" years = None\n",
" value = None\n",
" value_without_interest = None\n",
" else:\n",
" days = output.index[0]\n",
" years = output.index[0] / 365\n",
" value = output.values[0]\n",
" value_without_interest = pmt * days * -1\n",
"\n",
" years_until[column] = {'days': days, 'years': years, 'value': value,\n",
" 'value_without_interest': value_without_interest,\n",
" 'diff': value - value_without_interest if value else None}\n",
" if \".\" in column:\n",
" summary_str += f\" {years:.1f} years at {float(column)*100}% APR,\"\n",
"\n",
"#print(years_until)\n",
"\n",
"pd.options.display.float_format = '{:,.2f}'.format\n",
"df_years_until = pd.DataFrame(years_until)\n",
"df_years_until.index.name = 'interest rate'\n",
"df_years_until.T"
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"If you saved $1,000,000 a day, you'd have $145,000,000,000 after 109.6 years at 2.0% APR, 60.8 years at 5.0% APR, 37.1 years at 10.0% APR, 21.9 years at 20.0% APR.\n"
]
}
],
"source": [
"print(f\"{summary_str.rstrip(',')}.\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"https://numpy.org/doc/1.17/reference/generated/numpy.fv.html#numpy.fv"
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"\u001b[0;31mSignature:\u001b[0m \u001b[0mnpf\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mfv\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mrate\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mnper\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mpmt\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mpv\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mwhen\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;34m'end'\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
"\u001b[0;31mDocstring:\u001b[0m\n",
"Compute the future value.\n",
"\n",
"Given:\n",
" * a present value, `pv`\n",
" * an interest `rate` compounded once per period, of which\n",
" there are\n",
" * `nper` total\n",
" * a (fixed) payment, `pmt`, paid either\n",
" * at the beginning (`when` = {'begin', 1}) or the end\n",
" (`when` = {'end', 0}) of each period\n",
"\n",
"Return:\n",
" the value at the end of the `nper` periods\n",
"\n",
"Parameters\n",
"----------\n",
"rate : scalar or array_like of shape(M, )\n",
" Rate of interest as decimal (not per cent) per period\n",
"nper : scalar or array_like of shape(M, )\n",
" Number of compounding periods\n",
"pmt : scalar or array_like of shape(M, )\n",
" Payment\n",
"pv : scalar or array_like of shape(M, )\n",
" Present value\n",
"when : {{'begin', 1}, {'end', 0}}, {string, int}, optional\n",
" When payments are due ('begin' (1) or 'end' (0)).\n",
" Defaults to {'end', 0}.\n",
"\n",
"Returns\n",
"-------\n",
"out : ndarray\n",
" Future values. If all input is scalar, returns a scalar float. If\n",
" any input is array_like, returns future values for each input element.\n",
" If multiple inputs are array_like, they all must have the same shape.\n",
"\n",
"Notes\n",
"-----\n",
"The future value is computed by solving the equation::\n",
"\n",
" fv +\n",
" pv*(1+rate)**nper +\n",
" pmt*(1 + rate*when)/rate*((1 + rate)**nper - 1) == 0\n",
"\n",
"or, when ``rate == 0``::\n",
"\n",
" fv + pv + pmt * nper == 0\n",
"\n",
"References\n",
"----------\n",
".. [WRW] Wheeler, D. A., E. Rathke, and R. Weir (Eds.) (2009, May).\n",
" Open Document Format for Office Applications (OpenDocument)v1.2,\n",
" Part 2: Recalculated Formula (OpenFormula) Format - Annotated Version,\n",
" Pre-Draft 12. Organization for the Advancement of Structured Information\n",
" Standards (OASIS). Billerica, MA, USA. [ODT Document].\n",
" Available:\n",
" http://www.oasis-open.org/committees/documents.php?wg_abbrev=office-formula\n",
" OpenDocument-formula-20090508.odt\n",
"\n",
"Examples\n",
"--------\n",
">>> import numpy as np\n",
">>> import numpy_financial as npf\n",
"\n",
"What is the future value after 10 years of saving $100 now, with\n",
"an additional monthly savings of $100. Assume the interest rate is\n",
"5% (annually) compounded monthly?\n",
"\n",
">>> npf.fv(0.05/12, 10*12, -100, -100)\n",
"15692.928894335748\n",
"\n",
"By convention, the negative sign represents cash flow out (i.e. money not\n",
"available today). Thus, saving $100 a month at 5% annual interest leads\n",
"to $15,692.93 available to spend in 10 years.\n",
"\n",
"If any input is array_like, returns an array of equal shape. Let's\n",
"compare different interest rates from the example above.\n",
"\n",
">>> a = np.array((0.05, 0.06, 0.07))/12\n",
">>> npf.fv(a, 10*12, -100, -100)\n",
"array([ 15692.92889434, 16569.87435405, 17509.44688102]) # may vary\n",
"\u001b[0;31mFile:\u001b[0m ~/-wrk/-ce37/math/lib/python3.7/site-packages/numpy_financial/_financial.py\n",
"\u001b[0;31mType:\u001b[0m function\n"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"npf.fv?\n",
"# help(npf.fv)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## A symbolic solution (with SymPy)"
]
},
{
"cell_type": "code",
"execution_count": 12,
"metadata": {},
"outputs": [
{
"data": {
"text/latex": [
"$\\displaystyle fv + \\frac{pmt \\left(rate when + 1\\right) \\left(\\left(rate + 1\\right)^{nper} - 1\\right)}{rate} + pv \\left(rate + 1\\right)^{nper} = 0$"
],
"text/plain": [
"Eq(fv + pmt*(rate*when + 1)*((rate + 1)**nper - 1)/rate + pv*(rate + 1)**nper, 0)"
]
},
"execution_count": 12,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"import sympy as sy\n",
"fv, pv, pmt, rate, when, nper = sy.var('fv pv pmt rate when nper')\n",
"fveq = sy.Eq(fv + pv*(1+rate)**nper + pmt*(1 + rate*when)/rate*((1 + rate)**nper - 1), 0)\n",
"fveq"
]
},
{
"cell_type": "code",
"execution_count": 13,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Eq(fv + pmt*(rate*when + 1)*((rate + 1)**nper - 1)/rate + pv*(rate + 1)**nper, 0)\n",
"[(log((-fv*rate + pmt*rate*when + pmt)/(pmt*rate*when + pmt + pv*rate))/log(rate + 1), rate)]\n",
"log((-fv*rate + pmt*rate*when + pmt)/(pmt*rate*when + pmt + pv*rate))/log(rate + 1)\n"
]
}
],
"source": [
"# Solve in terms of nper, rate\n",
"fveq__nper_rate = sy.solve(fveq, [nper, rate])\n",
"print(fveq)\n",
"print(fveq__nper_rate)\n",
"if tuple(int(x) for x in sy.__version__.split('.')) < (1,5,1): # ? colab has 1.1.1\n",
" fveq__nper_rate = fveq__nper_rate[0][nper]\n",
"else:\n",
" fveq__nper_rate = fveq__nper_rate[0][0]\n",
"print(fveq__nper_rate)"
]
},
{
"cell_type": "code",
"execution_count": 14,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"{fv: 145000000000, pv: 0, pmt: -1000000, when: 0}\n",
"{0.02: 109.558885909925, 0.05: 60.7637197535231, 0.1: 37.0737514871950, 0.2: 21.9443170182029}\n"
]
}
],
"source": [
"BEGIN, END = 1, 0\n",
"vals = {fv: savings_target, pv: 0, pmt: pmt_, when: END}\n",
"print(vals)\n",
"\n",
"data = {}\n",
"for annual_interest_rate in [0.02, 0.05, 0.1, 0.2]:\n",
" data[annual_interest_rate] = (fveq__nper_rate\n",
" .subs(vals)\n",
" .subs({rate: annual_interest_to_daily_simple(annual_interest_rate)}) / 365)\n",
"print(data)"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.7.6"
}
},
"nbformat": 4,
"nbformat_minor": 4
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment