from analytics.index_data import index_returns from statsmodels.distributions.empirical_distribution import ECDF from scipy.stats import norm from scipy.optimize import brentq df = index_returns(index="IG", tenor=["5yr"]) df = df.reset_index(['index', 'tenor'], drop=True) spreads = df.dropna().groupby(['date']).nth(-1)['spread_return'] monthly_returns = spreads.rolling('30D').apply(lambda s: (1 + s).prod() - 1) mu = monthly_returns.median() ecdf = ECDF(monthly_returns) def implied_vol(q): """ computes the equivalent vol such that P(r \leq \mu + \sigma x) = \Phi(x)""" x0, r = brentq(lambda sigma: ecdf(mu + sigma * q) - norm.cdf(q), 0, 2, full_output=True) return x0