def bates_calibration(df_option, ival=None): """ calibrate bates' model """ tmp = make_helpers(df_option) risk_free_ts = tmp['risk_free_rate'] dividend_ts = tmp['dividend_rate'] spot = tmp['spot'] options = tmp['options'] v0 = .02 if ival is None: ival = { 'v0': v0, 'kappa': 3.7, 'theta': v0, 'sigma': 1.0, 'rho': -.6, 'lambda': .1, 'nu': -.5, 'delta': 0.3 } process = BatesProcess(risk_free_ts, dividend_ts, spot, ival['v0'], ival['kappa'], ival['theta'], ival['sigma'], ival['rho'], ival['lambda'], ival['nu'], ival['delta']) model = BatesModel(process) engine = BatesEngine(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('model calibration results:') print('v0: %f kappa: %f theta: %f sigma: %f\nrho: %f lambda: \ %f nu: %f delta: %f' % (model.v0, model.kappa, model.theta, model.sigma, model.rho, model.Lambda, model.nu, model.delta)) 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, 'Bates')
def test_batest_process(self): pb = BatesProcess(self.risk_free_ts, self.dividend_ts, self.s0, self.v0, self.kappa, self.theta, self.sigma, self.rho, self.Lambda, self.nu, self.delta) self.assertIsNotNone(pb) mb = BatesModel(pb) self.assertIsNotNone(mb)
def batesdetjump_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.0, 'rho': -.6, 'lambda': .1, 'nu': -.5, 'delta': 0.3 } process = BatesProcess(risk_free_ts, dividend_ts, spot, ival['v0'], ival['kappa'], ival['theta'], ival['sigma'], ival['rho'], ival['lambda'], ival['nu'], ival['delta']) model = BatesDetJumpModel(process) engine = BatesDetJumpEngine(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('BatesDetJumpModel calibration:') print( 'v0: %f kappa: %f theta: %f sigma: %f\nrho: %f lambda: %f nu: %f \ delta: %f\nkappaLambda: %f thetaLambda: %f' % (model.v0, model.kappa, model.theta, model.sigma, model.rho, model.Lambda, model.nu, model.delta, 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, 'BatesDetJump')
def setUp(self): self.settings = Settings() daycounter = ActualActual() interest_rate = .1 dividend_yield = .04 self.risk_free_ts = flat_rate(interest_rate, daycounter) self.dividend_ts = flat_rate(dividend_yield, daycounter) s0 = SimpleQuote(32.0) # Heston model v0 = 0.05 kappa = 5.0 theta = 0.05 sigma = 1.0e-4 rho = -0.5 self.heston_process = HestonProcess(self.risk_free_ts, self.dividend_ts, s0, v0, kappa, theta, sigma, rho, PartialTruncation) v0 = 0.05 ival = { 'v0': v0, 'kappa': 3.7, 'theta': v0, 'sigma': 1.0, 'rho': -.6, 'lambda': .1, 'nu': -.5, 'delta': 0.3 } spot = SimpleQuote(1200) self.bates_process = BatesProcess(self.risk_free_ts, self.dividend_ts, spot, ival['v0'], ival['kappa'], ival['theta'], ival['sigma'], ival['rho'], ival['lambda'], ival['nu'], ival['delta']) a = 0.376739 sigma = 0.0209 self.hullwhite_process = HullWhiteProcess(self.risk_free_ts, a, sigma)
plot(time, simulations) show() ival = { 'v0': v0, 'kappa': 3.7, 'theta': v0, 'sigma': 1.0, 'rho': -.6, 'lambda': .1, 'nu': -.5, 'delta': 0.3 } spot = SimpleQuote(1200) proc_bates = BatesProcess(risk_free_ts, dividend_ts, spot, ival['v0'], ival['kappa'], ival['theta'], ival['sigma'], ival['rho'], ival['lambda'], ival['nu'], ival['delta']) model_bates = BatesModel(proc_bates) res_bates = simulateBates(model_bates, paths, steps, horizon, seed) time = res_bates[0, :] simulations = res_bates[1:, :].T figure() plot(time, simulations) show()
def test_bates_det_jump(self): # this looks like a bug in QL: # Bates Det Jump model does not have sigma as parameter, yet # changing sigma changes the result! settlement_date = today() self.settings.evaluation_date = settlement_date daycounter = ActualActual() exercise_date = settlement_date + 6 * Months payoff = PlainVanillaPayoff(Put, 1290) exercise = EuropeanExercise(exercise_date) option = VanillaOption(payoff, exercise) risk_free_ts = flat_rate(0.02, daycounter) dividend_ts = flat_rate(0.04, daycounter) spot = 1290 ival = {'delta': 3.6828677022272715e-06, 'kappa': 19.02581428347027, 'kappaLambda': 1.1209758060939223, 'lambda': 0.06524550732595163, 'nu': -1.8968106563601956, 'rho': -0.7480898462264719, 'sigma': 1.0206363887835108, 'theta': 0.01965384459461113, 'thetaLambda': 0.028915397380738218, 'v0': 0.06566800935242285} process = BatesProcess( risk_free_ts, dividend_ts, SimpleQuote(spot), ival['v0'], ival['kappa'], ival['theta'], ival['sigma'], ival['rho'], ival['lambda'], ival['nu'], ival['delta']) model = BatesDetJumpModel(process, ival['kappaLambda'], ival['thetaLambda']) engine = BatesDetJumpEngine(model, 64) option.set_pricing_engine(engine) calc_1 = option.net_present_value ival['sigma'] = 1.e-6 process = BatesProcess( risk_free_ts, dividend_ts, SimpleQuote(spot), ival['v0'], ival['kappa'], ival['theta'], ival['sigma'], ival['rho'], ival['lambda'], ival['nu'], ival['delta']) model = BatesDetJumpModel(process, ival['kappaLambda'], ival['thetaLambda']) engine = BatesDetJumpEngine(model, 64) option.set_pricing_engine(engine) calc_2 = option.net_present_value if(abs(calc_1-calc_2) > 1.e-5): print('calc 1 %f calc 2 %f' % (calc_1, calc_2)) self.assertNotEqual(calc_1, calc_2)