In [29]:
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
from scipy import stats
In [12]:
#df = pd.read_csv('SwissRe_CatLosses.csv')
df = pd.read_csv(r'SwissRe_CatLosses.csv')
print(df.tail(10))
Year Weather EQ 45 2015 36.83 0.670000 46 2016 50.29 11.680000 47 2017 183.02 2.160000 48 2018 102.15 3.860000 49 2019 65.82 0.225841 50 2020 102.59 0.780000 51 2021 124.73 5.210000 52 2022 134.56 3.720000 53 2023 107.88 7.190000 54 2024 134.63 2.730000
Let's once again recreate the Swiss Re graph to check everything is working as expected.
In [15]:
weather_losses = df.iloc[:, 1]
eq_losses = df.iloc[:, 2]
years = df.iloc[:, 0]
values = df.iloc[:, 1]
plt.figure(figsize=(12, 6))
plt.bar(years, weather_losses, alpha=0.7, label='Weather Related')
plt.bar(years, eq_losses, alpha=0.7, bottom=weather_losses, label='EQ/Tsunami')
plt.xlabel('Year')
plt.ylabel('Insured Losses')
plt.title('Global Natural Catastrophe Insured Losses')
plt.legend()
plt.tight_layout()
plt.show()
In [33]:
total_losses = df.iloc[:, 1] + df.iloc[:, 2]
ln_total = np.log(total_losses)
slope_total = np.polyfit(years, ln_total, 1)[0]
inflation_rate = np.exp(slope_total) - 1
on_leveled = total_losses * (1 + inflation_rate) ** (len(total_losses) - 1 - np.arange(len(total_losses)))
In [35]:
plt.figure(figsize=(12, 6))
plt.bar(years, on_leveled, alpha=0.7)
plt.xlabel('Year')
plt.ylabel('On-Leveled Losses')
plt.title('On-Leveled Global Natural Catastrophe Insured Losses (2024 dollars)')
plt.tight_layout()
plt.show()
In [37]:
cov_5yr = on_leveled.rolling(window=5).std() / on_leveled.rolling(window=5).mean()
cov_10yr = on_leveled.rolling(window=10).std() / on_leveled.rolling(window=10).mean()
plt.figure(figsize=(12, 6))
plt.plot(years, cov_5yr, marker='o', alpha=0.7, label='5-year CoV')
plt.plot(years, cov_10yr, marker='o', alpha=0.7, label='10-year CoV')
plt.xlabel('Year')
plt.ylabel('Coefficient of Variation')
plt.title('Rolling Coefficient of Variation - On-Leveled Losses')
plt.legend()
plt.tight_layout()
plt.show()
In [39]:
mad_5yr = on_leveled.rolling(window=5).apply(lambda x: np.mean(np.abs(x - x.mean())))
mad_10yr = on_leveled.rolling(window=10).apply(lambda x: np.mean(np.abs(x - x.mean())))
plt.figure(figsize=(12, 6))
plt.plot(years, mad_5yr, marker='o', alpha=0.7, label='5-year MAD')
plt.plot(years, mad_10yr, marker='o', alpha=0.7, label='10-year MAD')
plt.xlabel('Year')
plt.ylabel('Mean Absolute Deviation')
plt.title('Rolling Mean Absolute Deviation - On-Leveled Losses')
plt.legend()
plt.tight_layout()
plt.show()
In [41]:
mean_on_leveled = np.mean(on_leveled)
std_on_leveled = np.std(on_leveled)
mu = np.log(mean_on_leveled**2 / np.sqrt(std_on_leveled**2 + mean_on_leveled**2))
sigma = np.sqrt(np.log(1 + (std_on_leveled**2 / mean_on_leveled**2)))
percentiles = stats.lognorm.cdf(on_leveled, s=sigma, scale=np.exp(mu)) * 100
plt.figure(figsize=(12, 6))
plt.plot(years, percentiles, marker='o', alpha=0.7)
plt.axhline(y=50, color='r', linestyle='--', alpha=0.5, label='Median')
plt.axhline(y=10, color='gray', linestyle='--', alpha=0.3)
plt.axhline(y=90, color='gray', linestyle='--', alpha=0.3)
plt.xlabel('Year')
plt.ylabel('Percentile')
plt.title('Percentile Position Over Time - On-Leveled Losses (Lognormal Fit)')
plt.legend()
plt.tight_layout()
plt.show()