Skip to content

Instantly share code, notes, and snippets.

@st1vms
Last active July 10, 2025 17:24
Show Gist options
  • Save st1vms/2c6abb8c17aeab9a42ae5c23ed1a3ae2 to your computer and use it in GitHub Desktop.
Save st1vms/2c6abb8c17aeab9a42ae5c23ed1a3ae2 to your computer and use it in GitHub Desktop.
Fund calculator
# Requirements: pandas matplotlib
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from matplotlib import ticker
# Parameters
MONTHLY_INVESTMENT = 100
MONTHLY_RATES = [0.005] # All the monthly rates to simulate
SIMULATION_YEARS = 10 # Total number of years to simulate future value
# List of (loss_probability, [loss_percentage1, loss_perc2, ...])
LOSS_MAP = [(0.003, [0.08]), (0.02, [0.03]), (0.1, [0.01])]
LOSS_MAP = sorted(LOSS_MAP, key=lambda v: v[0])
def plot_investement(
monthly_investment: float,
monthly_rates: list[float],
simulation_years: int,
loss_map: list[tuple[float, list[float]]],
seed: int = 42,
):
"""
Simulate and plot the future value of monthly investments with probabilistic losses.
Args:
monthly_investment (float): Fixed amount invested each month.
monthly_rates (list of float): List of expected monthly return rates to simulate.
simulation_years (int): Number of years to run the simulation.
loss_map (list of tuples): List of (loss_probability, [loss_percentages]) events.
seed (int, optional): Random seed for reproducibility. Defaults to 42.
Behavior:
For each monthly rate, simulates month-by-month:
- Checks if a loss event occurs based on probabilities.
- Applies loss if event occurs.
- Applies monthly gain and adds new investment.
- Records the future value over time.
Produces a plot comparing investment value and total invested capital.
"""
# Build cumulative loss map
cumulative_loss_map = []
cumulative_prob = 0.0
for prob, losses in loss_map:
cumulative_prob += prob
cumulative_loss_map.append((cumulative_prob, losses))
# Set a seed for reproducibility
np.random.seed(seed)
# Simulate the future values
results = {}
# Simulate each monthly rate
for r in monthly_rates:
fv = []
# We start the first month with a base investment
monthly_fv = monthly_investment
for y in range(simulation_years):
for m in range(12):
# Simulate probability of loss
prob = np.random.rand()
for threshold, loss_list in cumulative_loss_map:
if prob < threshold:
loss = np.random.choice(loss_list)
monthly_fv -= monthly_fv * loss
break
# Monthly win + new investement
monthly_fv += monthly_fv * r + monthly_investment
fv.append(monthly_fv)
results[f"Monthly return, price rate: {int(r * 100)}%"] = fv
tot = []
total_invested = 0
for y in range(simulation_years):
for m in range(12):
total_invested += monthly_investment
tot.append(total_invested)
results["Total Invested"] = tot
pd.options.display.float_format = "{:,.2f}".format
df = pd.DataFrame(results)
df.index.name = "Months"
print(df.round(2))
ax = df.plot()
ax.set_xlabel("Months")
ax.set_ylabel("Monthly Future Value (€)")
ax.set_title(
f"""€{monthly_investment}/Month, Total Invested : {results["Total Invested"][-1]} in {simulation_years} years."""
)
ax.grid(True)
ax.yaxis.set_major_formatter(
ticker.StrMethodFormatter("{x:,.0f}")
) # Adds commas and no decimals
plt.tight_layout()
plt.show()
if __name__ == "__main__":
plot_investement(
MONTHLY_INVESTMENT, MONTHLY_RATES, SIMULATION_YEARS, LOSS_MAP, seed=42
)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment