def batesdoubleexpdetjump_calibration(df_option, dtTrade=None, df_rates=None, ival=None): # array of option helpers hh = heston_helpers(df_option, dtTrade, df_rates, ival) options = hh['options'] spot = hh['spot'] risk_free_ts = df_to_zero_curve(df_rates['R'], dtTrade) dividend_ts = df_to_zero_curve(df_rates['D'], dtTrade) v0 = .02 if ival is None: ival = { 'v0': v0, 'kappa': 3.7, 'theta': v0, 'sigma': .1, 'rho': -.6, 'lambda': .1, 'nu': -.5, 'delta': 0.3 } process = HestonProcess(risk_free_ts, dividend_ts, spot, ival['v0'], ival['kappa'], ival['theta'], ival['sigma'], ival['rho']) model = BatesDoubleExpDetJumpModel(process, 1.0) engine = BatesDoubleExpDetJumpEngine(model, 64) for option in options: option.set_pricing_engine(engine) om = LevenbergMarquardt() model.calibrate(options, om, EndCriteria(400, 40, 1.0e-8, 1.0e-8, 1.0e-8)) print('BatesDoubleExpDetJumpModel calibration:') print( 'v0: %f kappa: %f theta: %f sigma: %f\nrho: %f lambda: %f \ nuUp: %f nuDown: %f\np: %f\nkappaLambda: %f thetaLambda: %f' % (model.v0, model.kappa, model.theta, model.sigma, model.rho, model.Lambda, model.nuUp, model.nuDown, model.p, model.kappaLambda, model.thetaLambda)) calib_error = (1.0 / len(options)) * sum( [pow(o.calibration_error(), 2) for o in options]) print('SSE: %f' % calib_error) return merge_df(df_option, options, 'BatesDoubleExpDetJump')
def batesdoubleexpdetjump_calibration(df_option, dtTrade=None, df_rates=None, ival=None): # array of option helpers hh = heston_helpers(df_option, dtTrade, df_rates, ival) options = hh['options'] spot = hh['spot'] risk_free_ts = df_to_zero_curve(df_rates['R'], dtTrade) dividend_ts = df_to_zero_curve(df_rates['D'], dtTrade) v0 = .02 if ival is None: ival = {'v0': v0, 'kappa': 3.7, 'theta': v0, 'sigma': .1, 'rho': -.6, 'lambda': .1, 'nu': -.5, 'delta': 0.3} process = HestonProcess( risk_free_ts, dividend_ts, spot, ival['v0'], ival['kappa'], ival['theta'], ival['sigma'], ival['rho']) model = BatesDoubleExpDetJumpModel(process, 1.0) engine = BatesDoubleExpDetJumpEngine(model, 64) for option in options: option.set_pricing_engine(engine) om = LevenbergMarquardt() model.calibrate( options, om, EndCriteria(400, 40, 1.0e-8, 1.0e-8, 1.0e-8) ) print('BatesDoubleExpDetJumpModel calibration:') print('v0: %f kappa: %f theta: %f sigma: %f\nrho: %f lambda: %f \ nuUp: %f nuDown: %f\np: %f\nkappaLambda: %f thetaLambda: %f' % (model.v0, model.kappa, model.theta, model.sigma, model.rho, model.Lambda, model.nuUp, model.nuDown, model.p, model.kappaLambda, model.thetaLambda)) calib_error = (1.0 / len(options)) * sum( [pow(o.calibration_error(), 2) for o in options]) print('SSE: %f' % calib_error) return merge_df(df_option, options, 'BatesDoubleExpDetJump')
def heston_calibration(df_option, dtTrade=None, df_rates=None, ival=None): """ calibrate heston model """ # array of option helpers print df_option, df_rates, ival hh = heston_helpers(df_option, dtTrade, df_rates, ival) options = hh['options'] spot = hh['spot'] risk_free_ts = df_to_zero_curve(df_rates['R'], dtTrade) dividend_ts = df_to_zero_curve(df_rates['D'], dtTrade) if ival is None: ival = { 'v0': 0.1, 'kappa': 1.0, 'theta': 0.1, 'sigma': 0.5, 'rho': -.5 } process = HestonProcess(risk_free_ts, dividend_ts, spot, ival['v0'], ival['kappa'], ival['theta'], ival['sigma'], ival['rho']) model = HestonModel(process) engine = AnalyticHestonEngine(model, 64) for option in options: option.set_pricing_engine(engine) om = LevenbergMarquardt(1e-8, 1e-8, 1e-8) model.calibrate(options, om, EndCriteria(400, 40, 1.0e-8, 1.0e-8, 1.0e-8)) print('model calibration results:') print('v0: %f kappa: %f theta: %f sigma: %f rho: %f' % (model.v0, model.kappa, model.theta, model.sigma, model.rho)) calib_error = (1.0 / len(options)) * sum( [pow(o.calibration_error() * 100.0, 2) for o in options]) print('SSE: %f' % calib_error) return merge_df(df_option, options, 'Heston')
def heston_pricer(trade_date, options, params, rates, spot): """ Price a list of European options with heston model. """ spot = SimpleQuote(spot) risk_free_ts = df_to_zero_curve(rates[nm.INTEREST_RATE], trade_date) dividend_ts = df_to_zero_curve(rates[nm.DIVIDEND_YIELD], trade_date) process = HestonProcess(risk_free_ts, dividend_ts, spot, **params) model = HestonModel(process) engine = AnalyticHestonEngine(model, 64) settlement_date = pydate_to_qldate(trade_date) settings = Settings() settings.evaluation_date = settlement_date modeled_values = np.zeros(len(options)) for index, row in options.T.iteritems(): expiry_date = row[nm.EXPIRY_DATE] strike = row[nm.STRIKE] option_type = Call if row[nm.OPTION_TYPE] == nm.CALL_OPTION else Put payoff = PlainVanillaPayoff(option_type, strike) expiry_qldate = pydate_to_qldate(expiry_date) exercise = EuropeanExercise(expiry_qldate) option = VanillaOption(payoff, exercise) option.set_pricing_engine(engine) modeled_values[index] = option.net_present_value prices = options.filter( items=[nm.EXPIRY_DATE, nm.STRIKE, nm.OPTION_TYPE, nm.SPOT]) prices[nm.PRICE] = modeled_values prices[nm.TRADE_DATE] = trade_date return prices
def heston_pricer(trade_date, options, params, rates, spot): """ Price a list of European options with heston model. """ spot = SimpleQuote(spot) risk_free_ts = df_to_zero_curve(rates[nm.INTEREST_RATE], trade_date) dividend_ts = df_to_zero_curve(rates[nm.DIVIDEND_YIELD], trade_date) process = HestonProcess(risk_free_ts, dividend_ts, spot, **params) model = HestonModel(process) engine = AnalyticHestonEngine(model, 64) settlement_date = pydate_to_qldate(trade_date) settings = Settings() settings.evaluation_date = settlement_date modeled_values = np.zeros(len(options)) for index, row in options.T.iteritems(): expiry_date = row[nm.EXPIRY_DATE] strike = row[nm.STRIKE] option_type = Call if row[nm.OPTION_TYPE] == nm.CALL_OPTION else Put payoff = PlainVanillaPayoff(option_type, strike) expiry_qldate = pydate_to_qldate(expiry_date) exercise = EuropeanExercise(expiry_qldate) option = VanillaOption(payoff, exercise) option.set_pricing_engine(engine) modeled_values[index] = option.net_present_value prices = options.filter(items=[nm.EXPIRY_DATE, nm.STRIKE, nm.OPTION_TYPE, nm.SPOT]) prices[nm.PRICE] = modeled_values prices[nm.TRADE_DATE] = trade_date return prices
def heston_calibration(df_option, dtTrade=None, df_rates=None, ival=None): """ calibrate heston model """ # array of option helpers print df_option, df_rates, ival hh = heston_helpers(df_option, dtTrade, df_rates, ival) options = hh['options'] spot = hh['spot'] risk_free_ts = df_to_zero_curve(df_rates['R'], dtTrade) dividend_ts = df_to_zero_curve(df_rates['D'], dtTrade) if ival is None: ival = {'v0': 0.1, 'kappa': 1.0, 'theta': 0.1, 'sigma': 0.5, 'rho': -.5} process = HestonProcess( risk_free_ts, dividend_ts, spot, ival['v0'], ival['kappa'], ival['theta'], ival['sigma'], ival['rho']) model = HestonModel(process) engine = AnalyticHestonEngine(model, 64) for option in options: option.set_pricing_engine(engine) om = LevenbergMarquardt(1e-8, 1e-8, 1e-8) model.calibrate( options, om, EndCriteria(400, 40, 1.0e-8, 1.0e-8, 1.0e-8) ) print('model calibration results:') print('v0: %f kappa: %f theta: %f sigma: %f rho: %f' % (model.v0, model.kappa, model.theta, model.sigma, model.rho)) calib_error = (1.0 / len(options)) * sum( [pow(o.calibration_error() * 100.0, 2) for o in options]) print('SSE: %f' % calib_error) return merge_df(df_option, options, 'Heston')
def heston_helpers(df_option, dtTrade=None, df_rates=None, ival=None): """ Create array of heston options helpers """ if dtTrade is None: dtTrade = df_option['dtTrade'][0] DtSettlement = pydate_to_qldate(dtTrade) settings = Settings() settings.evaluation_date = DtSettlement calendar = TARGET() if df_rates is None: df_tmp = DataFrame.filter(df_option, items=['dtExpiry', 'IR', 'IDIV']) grouped = df_tmp.groupby('dtExpiry') df_rates = grouped.agg(lambda x: x[0]) # convert data frame (date/value) into zero curve # expect the index to be a date, and 1 column of values risk_free_ts = df_to_zero_curve(df_rates['R'], dtTrade) dividend_ts = df_to_zero_curve(df_rates['D'], dtTrade) # back out the spot from any forward iRate = df_option['R'][0] iDiv = df_option['D'][0] TTM = df_option['T'][0] Fwd = df_option['F'][0] spot = SimpleQuote(Fwd * np.exp(-(iRate - iDiv) * TTM)) print('Spot: %f risk-free rate: %f div. yield: %f' % \ (spot.value, iRate, iDiv)) # loop through rows in option data frame, construct # helpers for bid/ask oneDay = datetime.timedelta(days=1) dtExpiry = [dtTrade + int(t * 365) * oneDay for t in df_option['T']] df_option['dtExpiry'] = dtExpiry options = [] for index, row in df_option.T.iteritems(): strike = row['K'] if (strike / spot.value > 1.3) | (strike / spot.value < .7): continue days = int(365 * row['T']) maturity = Period(days, Days) options.append( HestonModelHelper(maturity, calendar, spot.value, strike, SimpleQuote(row['VB']), risk_free_ts, dividend_ts, ImpliedVolError)) options.append( HestonModelHelper(maturity, calendar, spot.value, strike, SimpleQuote(row['VA']), risk_free_ts, dividend_ts, ImpliedVolError)) return {'options': options, 'spot': spot}
def heston_helpers(df_option, dtTrade=None, df_rates=None, ival=None): """ Create array of heston options helpers """ if dtTrade is None: dtTrade = df_option['dtTrade'][0] DtSettlement = pydate_to_qldate(dtTrade) settings = Settings() settings.evaluation_date = DtSettlement calendar = TARGET() if df_rates is None: df_tmp = DataFrame.filter(df_option, items=['dtExpiry', 'IR', 'IDIV']) grouped = df_tmp.groupby('dtExpiry') df_rates = grouped.agg(lambda x: x[0]) # convert data frame (date/value) into zero curve # expect the index to be a date, and 1 column of values risk_free_ts = df_to_zero_curve(df_rates['R'], dtTrade) dividend_ts = df_to_zero_curve(df_rates['D'], dtTrade) # back out the spot from any forward iRate = df_option['R'][0] iDiv = df_option['D'][0] TTM = df_option['T'][0] Fwd = df_option['F'][0] spot = SimpleQuote(Fwd * np.exp(-(iRate - iDiv) * TTM)) print('Spot: %f risk-free rate: %f div. yield: %f' % \ (spot.value, iRate, iDiv)) # loop through rows in option data frame, construct # helpers for bid/ask oneDay = datetime.timedelta(days=1) dtExpiry = [dtTrade + int(t * 365) * oneDay for t in df_option['T']] df_option['dtExpiry'] = dtExpiry options = [] for index, row in df_option.T.iteritems(): strike = row['K'] if (strike / spot.value > 1.3) | (strike / spot.value < .7): continue days = int(365 * row['T']) maturity = Period(days, Days) options.append( HestonModelHelper( maturity, calendar, spot.value, strike, SimpleQuote(row['VB']), risk_free_ts, dividend_ts, ImpliedVolError)) options.append( HestonModelHelper( maturity, calendar, spot.value, strike, SimpleQuote(row['VA']), risk_free_ts, dividend_ts, ImpliedVolError)) return {'options': options, 'spot': spot}