# Calculate Compound Interest with Contributions in Python

#### Table of Contents

**Getting Set Up**

` ````
```# import the libraries to eventually compute
# compound interest with monthly contributions
# and then to plot out the results
# need these for data manipulation
import pandas as pd
import numpy as np
# need these for plotting our results
from matplotlib import pyplot as plt
import seaborn as sns
# Format 'money' columns to two decimal places in pandas
pd.options.display.float_format = '{:6.2f}'.format

**Compound Interest Formula and Input Variables**

Next, we will need to define our input variables. Below is the traditional formula for compound interest:

**Results = P * (1 + r/n) ^(n * t)**

**P** is our starting principal, **r** is our annualize rate of return, **n** is the number of months in a year (12), and **t** is the number of years.

The traditional formula is missing one thing necessary to calculate compound interest with contributions… the contributions! To make this change we have to add another term to our formula.

**Results = P(1+r/n)^nt + M((1 +r/n)^nt -1)/(r/n)**

The only additional variable in this new formula is **M**. **M** is the monthly contribution amount. In the next code block I have initialized each one of these variables. Feel free to change these to fit what you are trying to model.

` ````
```# Prepare our input variables in order to compute compound interest
# with monthly contributions
###############################################################
###############################################################
## Change the Below Variables for your investment scenario
P = 10000 # The Starting Principal
r = 0.10 # The Annual Interest Rate to Compound On 10%
n = 12 # The Number of Months in a Year
t = 40 # The Number of Years to Compound
M = 100 # Monthly Contribution Amount
###############################################################
###############################################################

**Compounding Interest with Monthly Contributions**

Let’s start with a simple calculation. In the next code block I have created a DataFrame called ‘**results**‘ that will be used to store the Year and the Account Amount. A *for* loop is called to iteratively calculate the values for each year. Finally, at the end, I print out both the first year and the last year’s results.

` ````
```# Calculate the End of Year Balance for Each Year
# Prepare a DataFrame to store the Year and Final Balance
results = pd.DataFrame(columns = ['Year', 'Amount'])
# Iterate through each year to find the ending balance
# then append it to the results DataFrame
for i in range(1,t+1):
Year = i
Amount = P*np.power((1 + r / n), n * i)+(M)*(np.power((1+ r / n ), n * i)-1)/(r / n)
results = results.append({'Year': Year, 'Amount': Amount}, ignore_index = True)
# Our Year's data type needs to be an integer not a float
results['Year'] = results['Year'].astype('int')
# print out the results
print(results.head(1))
print(results.tail(1))

If you run the code block above, you will see that if we calculate the compounding interest on a principal of $10,000 at a rate of 10% with $100 in reoccurring monthly contributions we arrive at a final balance of **$1,169,414.59**. That’s not too shabby!

When I run the same calculation except with monthly contributions set to $500, the final amount ball0ons to **$3,699,046.42**. By using the code available already, it is easy to quickly change the variables to test various scenarios.

**Plotting our Initial Data**

Now let’s see how the data we calculated looks as a bar chart. Theoretically, with compounding interest we should see a curve that gets steeper as it moves to the right… we should be able to see if that pans out.

To create our plots, we will be using *matplotlib* with seaborn on top. These packages were already imported above. I added some color and changed the default theme to give it some flare but the charts themselves are highly customizable.

` ````
```# Now its time to plot out what we have calculated
sns.set(rc={'figure.figsize':(11,8)}) # Change the size of the plot
sns.set_style('whitegrid') # Change the default background
sns.set_palette('Greens') # Change the color of the bars themeselves
# Plot it Out
sns.barplot(data = results, x ='Year', y = 'Amount').set_title('Compound Interest Plot (10% Return, \$10,000 Principal, \$100 Contribution)')

**Comparing Interest Rates**

Everyone has heard the statement, “*Past Performance Does Not Predict Future Results.*” With this in mind, we need to be open to multiple futures. In other words, we need to understand how various rates of return may impact the compounding of our principal and reoccurring contributions.

To do this I will just throw all the code we initially used to compute our final amount into another *for* loop. This loop will iterate through each of the specified interest rates defined in the variable **interest_rates**.

At the end of the *for* loop I will go ahead and plot out our data but in order to visualize it all on one chart we will need to do it a bit differently. Instead of using a bar plot, I will use a line plot. This will allow us to see each set of data as a line across time. I will set the ‘*hue*‘ of each line to vary based on the interest rate.

` ````
```# Calculate the End of Year Balance for Each Year
# Prepare a DataFrame to store the Year and Final Balance.
# For this next calculation we add the 'Interest' field so
# we can keep track which data is which.
results = pd.DataFrame(columns = ['Year','Interest', 'Amount'])
# identify which interest rates to iterate through
interest_rates = [.06, .07,.08, .09, .10, .11, .12]
# Iterate through each year to find the ending balance
# then append it to the results DataFrame
for j in range(len(interest_rates)):
for i in range(1,t+1):
Year = i
Amount = P*np.power((1 + interest_rates[j] / n), n * i)+(M)*(np.power((1+ interest_rates[j] / n ), n * i)-1)/(interest_rates[j] / n)
results = results.append({'Interest': interest_rates[j], 'Year': Year, 'Amount': Amount}, ignore_index = True)
# Our Year's data type needs to be an integer not a float
results['Year'] = results['Year'].astype('int')
# Now Let's go ahead and plot it out
sns.set(rc={'figure.figsize':(11,8)}) # Change the size of the plot
sns.set_style('whitegrid') # Change the default background
plt.ticklabel_format(style='plain', axis = 'y') # prevent sci notation on y-axis
# now for the actual plot
sns.lineplot(data = results, x ='Year', y = 'Amount',
hue = 'Interest', palette = 'Greens').set_title('Compound Interest Plot (Varying Returns, \$10,000 Principal, \$100 Monthly Contribution)')

Now we are getting somewhere! As you can see from the above chart, it is possible to get a pretty firm grasp of how an expected return over a period of time can drastically change the performance of the compounded principal. An interest rate of 12% looks to be about 8 times more effective at building wealth.

Using this type of chart is a great way to conceptualize your expected progress, or if you are a financial advisor, to show your clients how different investment options may perform.

**Showing the Effect of Varying Contributions**

I have shown how to plot out the performance of various interest rates… now let’s see how varying contributions may affect our performance. I will set up the code in a similar way as before with nested *for* loops, except this time I will be iterating through another variable called ‘**contributions**‘.

Changing the list of values in ‘**contributions**,’ will allow you to change when contributions are computed. As before, I went ahead and plotted the results at the end.

` ````
```# Calculate the End of Year Balance for Each Year
# Prepare a DataFrame to store the Year and Final Balance.
# For this next calculation we add the 'Contribution' field so
# we can keep track which data is which.
results = pd.DataFrame(columns = ['Year','Contribution', 'Amount'])
# identify which monthly contributions to iterate through
contributions = [100, 200, 300, 400, 500, 600, 700, 800, 900, 1000]
# Iterate through each year to find the ending balance
# then append it to the results DataFrame
for j in range(len(contributions)):
for i in range(1,t+1):
Year = i
Amount = P*np.power((1 + r / n), n * i)+(contributions[j])*(np.power((1+ r / n ), n * i)-1)/(r / n)
results = results.append({'Contribution': contributions[j], 'Year': Year, 'Amount': Amount}, ignore_index = True)
# Our Year's data type needs to be an integer not a float
results['Year'] = results['Year'].astype('int')
# Now Let's go ahead and plot it out
sns.set(rc={'figure.figsize':(11,8)}) # Change the size of the plot
sns.set_style('whitegrid') # Change the default background
plt.ticklabel_format(style='plain', axis = 'y') # prevent sci notation on y-axis
# now for the actual plot
sns.lineplot(data = results, x ='Year', y = 'Amount',
hue = 'Contribution').set_title('Compound Interest Plot (Varying Contributions, \$10,000 Principal, 10% Interest)')

Who says you can’t be a millionaire? If you start saving in your 20’s, by the time you are in your 60’s you are virtually guaranteed to be a millionaire if you are saving at least $100 a month. If you are saving $1,000 a month, you would end up with almost 7 million dollars at a rate of 10% interest.

**Compounding Contributions and Interest Rates**

As we see from this chart, the impact of increasing your contributions over time seems to have a linear impact on the final result. Thus, if you save twice as much per month, at retirement you will have twice as much compounded.

Contrast this to when we varied the interest rate where the effect was exponential.

Picking the right long term investment vehicle is much more impactful than how much we save. At the end of the day, use your budget to determine how much you can save… use a financial advisor or research to dig deeply into what you are invested in to make sure that you are invested appropriately.

Keep in mind that you still must save monthly to develop a sizeable nest egg, just realize that the impact of your CHOICES will be much more levered on the investment return side of the equation. Long term bad investment decisions can be detrimental to your overall success.

**Compounding Varying Interest and Monthly Contributions**

Now it’s time to put all the pieces together. Now let’s look at how we can quickly and visually look at the effect of varying interest rates and varying monthly contributions at the same time.

To do this I will use another *for* loop. Working off the last block of code, I will add back in yet another *for* loop that iterates through the interest rates found in the variable ‘**interest_rates**‘ after it has iterated through ‘**contributions**‘ through each year.

` ````
```# Calculate the End of Year Balance for Each Year
# Prepare a DataFrame to store the Year and Final Balance.
# For this next calculation we add the 'Contribution' and 'Interest' fields so
# we can keep track which data is which.
results = pd.DataFrame(columns = ['Year','Contribution', 'Interest' 'Amount'])
# identify which monthly contributions to iterate through
contributions = [100, 200, 300, 400, 500, 600, 700, 800, 900, 1000]
# identify which interest rates to iterate through
interest_rates = [.06, .07,.08, .09, .10, .11, .12]
# Iterate through each year to find the ending balance
# then append it to the results DataFrame
for k in range(len(interest_rates)):
for j in range(len(contributions)):
for i in range(1,t+1):
Year = i
Amount = P*np.power((1 + interest_rates[k] / n), n * i)+(contributions[j])*(np.power((1+ interest_rates[k] / n ), n * i)-1)/(interest_rates[k] / n)
results = results.append({'Contribution': contributions[j],
'Interest': interest_rates[k],
'Year': Year,
'Amount': Amount}, ignore_index = True)
# Our Year's data type needs to be an integer not a float
results['Year'] = results['Year'].astype('int')
# Now Let's go ahead and plot it out
sns.set(rc={'figure.figsize':(11,8)}) # Change the size of the plot
sns.set_style('whitegrid') # Change the default background
plt.ticklabel_format(style='plain', axis = 'y') # prevent sci notation on y-axis
# now for the actual plot
sns.lineplot(data = results, x ='Year', y = 'Amount',
hue = 'Contribution').set_title('Compound Interest Plot (Varying Contributions and Interest, \$10,000 Principal)')

From the graph, it does appear that all the information we calculated is present. The lines represent what appear to be mean amounts for each monthly contribution. A band is created around each line showing the range of values possible with each interest rate. But, this plot is hard to read.

In the next code block, let’s see how splitting out a plot for each interest rate looks. We will use **FacetGrid** to plot it out with the seaborn package.

` ````
```# Now let's use FacetGrid from Seaborn to make our data easier to see
f = sns.FacetGrid(results, col = 'Interest', col_wrap = 2, hue = 'Contribution')
plt.ticklabel_format(style='plain', axis = 'y') # prevent sci notation on y-axis
# these next 2 lines are used to increase the size of the plot
fig = plt.gcf()
fig.set_size_inches(12,16)
# and now map a lineplot to each one of our facets
f = f.map(sns.lineplot, 'Year', 'Amount').add_legend()

As you see above, the result splits out each interest rate and easily shows the varying monthly contributions. Using this method is excellent at giving you a ‘30,000-foot view’ of what is going on. It will allow you to make rough choices about your investment prospects and expected return.

Once you have identified a specific interest rate that matches what you expect to get in the long term based on your investments or professional advice, you can go back and look at one of the larger charts to fine tune your plans.

**Quick Warning and Disclaimer**

Always remember that calculating these types of things should be done with a critical eye. I’ve double checked all my code with other compounding interest calculators, but there may always be a glitch. Double check your code to make sure you’ve typed everything properly. Just because your code executes doesn’t mean that it is giving you the result that you may be interpreting.

Additionally, when it comes to trying to use this type of tool, always remember that automation cannot supersede professional advice. Always do your own research prior to making any real investment decisions.

**Final Thoughts**

I hope you enjoyed this quick how to guide on Compounding Interest with Monthly Contributions using Python. If this type of thing excites you like it does me then you will find other python articles as it relates to Personal Finance here.

If you have any interesting ideas or questions about the code, then feel free to drop me a line down in the comments. I created all of the content from this article using only Google CoLab and the code provided… so if something isn’t working on your end let me know and I’d be glad to help.