Skip to content

Monte Carlo Inflation Rates Simulation in Croatia for 2024-2030

I have conducted a Monte Carlo simulation to generate multiple inflation scenarios for the years 2024-2030 in Croatia. The simulation is based on an initial inflation rate of 6.7% for the year 2023. It incorporates dynamic volatility over the years, which is adjusted based on predefined rates ranges for different time periods.

Simulation Results

The simulation results are stored in a dataframe called results. It has the following columns:

  • Projected Rates: This column contains the mean inflation rate for each scenario.
  • Q1: This column contains the first quartile (25th percentile) inflation rate for each scenario.
  • Q3: This column contains the third quartile (75th percentile) inflation rate for each scenario.

Control calculation

  • In order to identify if the data in the first simulation is affected by very high or very low inflation rates, I excluded the outliers and re-plotted the chart. The data showed minimal deviations between the simulated rates.

*Please note that these results are based on the Monte Carlo simulation and should be interpreted as possible inflation scenarios rather than definitive predictions.

# Import libraries
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

# Set the initial parameters
inflation_2023 = 6.7  
start_year = 2023 
end_year = 2030
num_scenarios = 1500 

# Define a function to calculate dynamic volatility
def dynamic_volatility(year):
    # Adjust the volatility based on the year
    if year <= start_year + 2:
        return (-6.5, 1.5)  # range for the first 2 years
    elif year <= start_year + 4:
        return (-2.5, 3)  # inflation rates range for 2025-26
    else:
        return (-5, 5.2)  # inflation rates range for 2027 and beyond

# Generate random scenarios for each year
np.random.seed()  # for reproducibility
inflation_scenarios = []

for scenario in range(num_scenarios):
    years = np.arange(start_year, end_year + 1)
    inflation_rates = [inflation_2023]  

    for year in range(start_year + 1, end_year + 1):
        yearly_increase_range = dynamic_volatility(year)
        yearly_increase = np.random.uniform(*yearly_increase_range)
        inflation_rate = inflation_rates[-1] + yearly_increase
        inflation_rates.append(inflation_rate)

    inflation_scenarios.append(inflation_rates)

# Identify the scenario with the closest inflation rates to the mean
closest_scenario_idx = np.argmin(np.abs(inflation_scenarios - np.mean(inflation_scenarios, axis=0)), axis=0)

# Plot the scenarios
plt.figure(figsize=(10, 6))
for scenario in inflation_scenarios:
    plt.plot(years[1:], scenario[1:], alpha=0.1, color='blue')  # Exclude the first year

# Highlight the mean scenario in red
mean_scenario = np.mean(inflation_scenarios, axis=0)
plt.plot(years[1:], mean_scenario[1:], '-', markersize=3, label='Mean rate', color="crimson")  # Exclude the first year

# Calculate quartiles for each year
quartiles = np.percentile(inflation_scenarios, [25, 75], axis=0)

# Plot quartiles
plt.plot(years[1:], quartiles[0][1:], '--', label='Q1 (25th Percentile)', color="yellow")  # Exclude the first year
plt.plot(years[1:], quartiles[1][1:], '--', label='Q3 (75th Percentile)', color="yellow")  # Exclude the first year

plt.xlabel('Year')
plt.ylabel('Inflation Rate')
plt.title('Monte Carlo Simulation of Inflation rates (2024-2030)')
plt.legend()
plt.grid(True)
plt.savefig('Monte Carlo Simulation of Inflation rates (2024-2030).jpg')
plt.show()

# List the mean scenario inflation rates for each year
mean_scenario_rates = [inflation_scenarios[closest_scenario_idx[idx]][idx] for idx in range(len(years))]
mean_scenario_rates = np.round(mean_scenario_rates[1:], 2)  # Exclude the first year

# Optional: Print mean inflation rates
""""print("Mean Scenario Inflation Rates:")
for year, rate in zip(years[1:], mean_scenario_rates):
    print(f"Year {year}: {rate}%")
print()"""

quartiles = np.round(quartiles[:, 1:], 2)  # Exclude the first year

# Optional: Print the percentiles
"""for year, (q1, q3) in zip(years[1:], zip(quartiles[0], quartiles[1])):
    print(f"Year {year}: Q1={q1}%, Q3={q3}%")"""

# Create a DataFrame to store the results
results = pd.DataFrame({'Projected rate': mean_scenario_rates, 'Q1': quartiles[0], 'Q3': quartiles[1]}, index=years[1:])
results = results.rename_axis("Year")
print(results)
  • To test the model, in the next step I've excluded the outliers, the lower and upper 5% of the rates simulated and ploted a chart again.
# Calculate the lower and upper percentiles to exclude
lower_percentile = 5
upper_percentile = 95

# Calculate the number of scenarios to trim
num_scenarios = len(inflation_scenarios)
trim_size = int(num_scenarios * lower_percentile / 100)

# Sort the inflation scenarios
sorted_scenarios = np.sort(inflation_scenarios, axis=0)

# Exclude the lower and upper percentiles
trimmed_scenarios = sorted_scenarios[trim_size:-trim_size]

# Plot the trimmed scenarios
plt.figure(figsize=(10, 6))
for scenario in trimmed_scenarios:
    plt.plot(years[1:], scenario[1:], alpha=0.1, color='royalblue')  # Exclude 2023 year

# Calculate quartiles for each year
quartiles = np.percentile(trimmed_scenarios, [25, 75], axis=0)
quartiles=np.round(quartiles,2)

# Plot quartiles
plt.plot(years[1:], quartiles[0][1:], '--', label='Q1 (25th Percentile)', color="yellow")  # Exclude 2023 year
plt.plot(years[1:], quartiles[1][1:], '--', label='Q3 (75th Percentile)', color="yellow")  # Exclude 2023 year

# Calculate trimmed mean
trimmed_mean_scenario = np.mean(trimmed_scenarios, axis=0)
plt.plot(years[1:], trimmed_mean_scenario[1:], '--', label='Trimmed Mean', color="red")  # Exclude 2023 year

plt.xlabel('Year')
plt.ylabel('Inflation Rate')
plt.title('Monte Carlo Simulation of Inflation rates with Dynamic Volatility (2024-2030) [Trimmed]')
plt.legend()
plt.grid(True)
plt.show()

# List the trimmed mean scenario inflation rates for each year
trimmed_mean_scenario_rates = np.round(trimmed_mean_scenario[1:], 2)  # Exclude 2023 year

# Create a DataFrame to store the results
results = pd.DataFrame({'Projected rates[trimmed]': trimmed_mean_scenario_rates, 'Q1': quartiles[0][1:], 'Q3': quartiles[1][1:]}, index=years[1:])  # Exclude 2023 year
results_trimmed = results.rename_axis("Year")
print(results_trimmed)
# Calculate the difference between the trimmed mean scenario rates and the mean scenario rates
difference = np.round(trimmed_mean_scenario_rates, 2) - np.round(mean_scenario_rates[:7], 2)

# Return the difference
difference
  • Excluding the lower and upper 5% of simulated rates had an insignificant impact on the projected data.

1 hidden cell