def M76_error_function_FFT(p0): ''' Error Function for parameter calibration in M76 Model via Carr-Madan (1999) FFT approach. Parameters ========== sigma: float volatility factor in diffusion term lamb: float jump intensity mu: float expected jump size delta: float standard deviation of jump Returns ======= RMSE: float root mean squared error ''' global i, min_RMSE sigma, lamb, mu, delta = p0 if sigma < 0.0 or delta < 0.0 or lamb < 0.0: return 500.0 se = [] for row, option in options.iterrows(): T = (option['Maturity'] - option['Date']).days / 365. model_value = M76_value_call_FFT(S0, option['Strike'], T, r, sigma, lamb, mu, delta) se.append((model_value - option['Call'])**2) RMSE = math.sqrt(sum(se) / len(se)) min_RMSE = min(min_RMSE, RMSE) if i % 50 == 0: print('%4d |' % i, np.array(p0), '| %7.3f | %7.3f' % (RMSE, min_RMSE)) i += 1 return RMSE
def generate_plot(opt, options): # # Calculating Model Prices # sigma, lamb, mu, delta = opt options['Model'] = 0.0 for row, option in options.iterrows(): T = (option['Maturity'] - option['Date']).days / 365. options.loc[row, 'Model'] = M76_value_call_FFT(S0, option['Strike'], T, r, sigma, lamb, mu, delta) # # Plotting # options = options.set_index('Strike') fig, ax = plt.subplots(2, sharex=True, figsize=(8, 7)) options[['Call', 'Model']].plot(style=['b-', 'ro'], title='%s' % str(option['Maturity'])[:10], ax=ax[0]) ax[0].set_ylabel('option values') ax[0].grid(True) xv = options.index.values ax[1] = plt.bar(xv - 5 / 2., options['Model'] - options['Call'], width=5) plt.ylabel('difference') plt.xlim(min(xv) - 10, max(xv) + 10) plt.tight_layout() plt.grid(True)
def generate_plot(opt, options): # # Calculating Model Prices # sigma, lamb, mu, delta = opt options['Model'] = 0.0 for row, option in options.iterrows(): T = (option['Maturity'] - option['Date']).days / 365. options.loc[row, 'Model'] = M76_value_call_FFT(S0, option['Strike'], T, r, sigma, lamb, mu, delta) # # Plotting # mats = sorted(set(options['Maturity'])) options = options.set_index('Strike') for i, mat in enumerate(mats): options[options['Maturity'] == mat][['Call', 'Model']].\ plot(style=['b-', 'ro'], title='%s' % str(mat)[:10], grid=True) plt.ylabel('option value') plt.savefig('../images/08_m76/M76_calibration_3_%s.pdf' % i)
if __name__ == '__main__': # Single Valuation S = M76_generate_paths(S0, T, r, sigma, lamb, mu, delta, M, I) print("Value of Call Option %8.3f" % M76_value_call_MCS(S0)) # Value Comparisons strikes = np.arange(3000, 3601, 50) values = np.zeros((3, len(strikes)), dtype=np.float) z = 0 for k in strikes: print("CALL STRIKE %10.3f" % k) print("----------------------------") values[0, z] = M76_value_call_INT(S0, k, T, r, sigma, lamb, mu, delta) print("Call Value by Int %10.3f" % values[0, z]) values[1, z] = M76_value_call_FFT(S0, k, T, r, sigma, lamb, mu, delta) print("Call Value by FFT %10.3f" % values[1, z]) print("Difference FFT/Int%10.3f" % (values[1, z] - values[0, z])) values[2, z] = M76_value_call_MCS(k) print("Call Value by MCS %10.3f" % values[2, z]) print("Difference MCS/Int%10.3f" % (values[2, z] - values[0, z])) print("----------------------------") z = z + 1 results = pd.DataFrame(values.T, index=strikes, columns=['INT', 'FFT', 'MCS']) results.index.name = 'Strike'