def Pricing_by_QuantLib(v0, S0, K, tau, mu, kappa, theta, sigma, rho, Type): # construct the European Option payoff = ql.PlainVanillaPayoff( Type, K) # (option_type, strike_price) enum Type { Put = -1,. Call = 1. } european_option = ql.VanillaOption(payoff, exercise) ql.Settings.instance().evaluationDate = calculation_date day_count = ql.Actual365Fixed() #dividend_yield = ql.QuoteHandle(ql.SimpleQuote(0.0)) risk_free_rate = 0.0 dividend_rate = 0.0 flat_ts = ql.YieldTermStructureHandle( ql.FlatForward(calculation_date, risk_free_rate, day_count)) dividend_ts = ql.YieldTermStructureHandle( ql.FlatForward(calculation_date, dividend_rate, day_count)) # parameters initialization heston_process = ql.HestonProcess(flat_ts, dividend_ts, ql.QuoteHandle(ql.SimpleQuote(spot)), v0, kappa, theta, sigma, rho) engine = ql.AnalyticHestonEngine( ql.HestonModel(heston_process)) #,0.01, 1000) european_option.setPricingEngine(engine) h_price = european_option.NPV() # print ("The Heston model price is", h_price) # ql.HestonModel(2.3) # HestonProcessPtr const & # iv = european_option.impliedVolatility(6.51, heston_process) # # VanillaOptionPtr::impliedVolatility(Real,GeneralizedBlackScholesProcessPtr const &) # print("iv is ", iv) return h_price
def call_price_exact(kappa, theta, beta, rho, v0, r, T, s0, K): strike_price = 110.0 payoff = ql.PlainVanillaPayoff(ql.Option.Call, strike_price) # option data calculation_date = ql.Date(15, 1, 2011) maturity_date = ql.Date(15, 1, 2011 + T) spot_price = s0 strike_price = K dividend_rate = 0.00 option_type = ql.Option.Call risk_free_rate = r day_count = ql.Actual365Fixed() ql.Settings.instance().evaluationDate = calculation_date # construct the Heston process payoff = ql.PlainVanillaPayoff(option_type, strike_price) exercise = ql.EuropeanExercise(maturity_date) european_option = ql.VanillaOption(payoff, exercise) sigma = beta spot_handle = ql.QuoteHandle(ql.SimpleQuote(spot_price)) flat_ts = ql.YieldTermStructureHandle( ql.FlatForward(calculation_date, risk_free_rate, day_count)) dividend_yield = ql.YieldTermStructureHandle( ql.FlatForward(calculation_date, dividend_rate, day_count)) heston_process = ql.HestonProcess(flat_ts, dividend_yield, spot_handle, v0, kappa, theta, sigma, rho) engine = ql.AnalyticHestonEngine(ql.HestonModel(heston_process), 0.0000001, 100000) european_option.setPricingEngine(engine) h_price = european_option.NPV() return h_price
def get_vanilla_option_price_analytic(self, strike, maturity_period, option_type = ql.Option.Call): self.option = self.vanilla_option_helper( strike, maturity_period, option_type) self.model = ql.HestonModel(self.process) self.engine = ql.AnalyticHestonEngine(self.model) self.option.setPricingEngine(self.engine) return self.option.NPV()
def setup_model(_yield_ts, _dividend_ts, _spot, init_condition=(0.02, 0.2, 0.5, 0.1, 0.01)): theta, kappa, sigma, rho, v0 = init_condition process = ql.HestonProcess(_yield_ts, _dividend_ts, ql.QuoteHandle(ql.SimpleQuote(_spot)), v0, kappa, theta, sigma, rho) model = ql.HestonModel(process) engine = ql.AnalyticHestonEngine(model) return model, engine
def __init__(self, calc_date=calibration_date, option_type=ql.Option.Call): super().__init__() tf.set_random_seed(self.seed) np.random.seed(self.seed) self.spot = self.S0 self.calc_date = calc_date self.spot = ql.SimpleQuote(self.spot) self.s0 = ql.QuoteHandle(self.spot) self.rf = set_rf(calc_date, self.r) self.ir = set_dividend(calc_date, self.q) self.process = ql.HestonProcess(self.rf, self.ir, self.s0, self.v0, self.kappa, self.theta, self.sigma, self.rho) self.engine = ql.AnalyticHestonEngine(ql.HestonModel(self.process)) self.option = EU_option(calc_date, option_type, self.K, self.ttm) self.option.setPricingEngine(self.engine)
def to_ql_option_engine(engine_name=None, process=None, model=None): """ Returns a QuantLib.PricingEngine for Options :param engine_name: str The engine name :param process: QuantLib.StochasticProcess The QuantLib object with the option Stochastic Process. :param model: QuantLib.CalibratedModel :return: QuantLib.PricingEngine """ if engine_name.upper() == 'BINOMIAL_VANILLA': return ql.BinomialVanillaEngine(process, 'LR', 801) elif engine_name.upper() == 'ANALYTIC_HESTON': if model is None: model = ql.HestonModel(process) elif model is not None and process is not None: model = model(process) return ql.AnalyticHestonEngine(model) elif engine_name.upper() == 'ANALYTIC_EUROPEAN': return ql.AnalyticEuropeanEngine(process) elif engine_name.upper() == 'ANALYTIC_EUROPEAN_DIVIDEND': return ql.AnalyticDividendEuropeanEngine(process) elif engine_name.upper() == "FINITE_DIFFERENCES": return ql.FdBlackScholesVanillaEngine(process) elif engine_name.upper() == 'HESTON_FINITE_DIFFERENCES': if model is None: model = ql.HestonModel(process) elif model is not None and process is not None: model = model(process) return ql.FdHestonVanillaEngine(model) elif engine_name.upper() == "BARONE_ADESI_WHALEY": return ql.BaroneAdesiWhaleyEngine(process) elif engine_name.upper() == "BJERKSUND_STENSLAND": return ql.BjerksundStenslandEngine(process) elif engine_name.upper() == "ANALYTIC_GJR_GARCH": if model is None: model = ql.GJRGARCHModel(process) elif model is not None and process is not None: model = model(process) return ql.AnalyticGJRGARCHEngine(model) elif engine_name.upper() == 'MC_GJR_GARCH': return ql.MCEuropeanGJRGARCHEngine(process=process, traits='pseudorandom', timeStepsPerYear=20, requiredTolerance=0.02) else: return None
def __init__(self, vol_data): super().__init__(vol_data) self.process = ql.HestonProcess( self.dom_ts, self.for_ts, ql.QuoteHandle(ql.SimpleQuote(self.spot)), self.v0, self.kappa, self.theta, self.sigma, self.rho) self.model = ql.HestonModel(self.process) self.engine = ql.AnalyticHestonEngine(self.model) self.bl_surface = ql.BlackVarianceSurface( self.calculation_date, self.calendar, self.expiration_dates, self.strikes, self.implied_vols, self.day_count) self.bl_surface.setInterpolation("bicubic") vol_ts = ql.BlackVolTermStructureHandle(self.bl_surface) self.bs_process = BlackScholesMertonProcess( ql.QuoteHandle(ql.SimpleQuote(self.spot)), self.for_ts, self.dom_ts, vol_ts)
def price(S0=100, K=100, r=0.025, T=30, V0=0.04, kappa=1.0, theta=0.04, sigma=0.8, rho=-0.7, type='c'): assert type == 'c' or type == 'p' today = ql.Date(1, ql.December, 2018) ql.Settings.instance().evaluationDate = today riskFreeRate = ql.FlatForward(today, r, ql.Actual365Fixed()) dividendRate = ql.FlatForward(today, 0.0, ql.Actual365Fixed()) # maturity_date = ql.Date(31, ql.December, 2018) maturity_date = today + T payoff = ql.PlainVanillaPayoff( ql.Option.Call if type == 'c' else ql.Option.Put, K) exercise = ql.EuropeanExercise(maturity_date) european_option = ql.VanillaOption(payoff, exercise) heston_process = ql.HestonProcess( ql.YieldTermStructureHandle(riskFreeRate), ql.YieldTermStructureHandle(dividendRate), ql.QuoteHandle(ql.SimpleQuote(S0)), # S0 V0, # v0 kappa, # kappa theta, # theta sigma, # sigma rho, # rho ) engine = ql.AnalyticHestonEngine(ql.HestonModel(heston_process)) european_option.setPricingEngine(engine) h_price = european_option.NPV() return h_price
def HestonModelCalibrator(valuationDate, calendar, spot, curveHandle, dividendHandle, v0, kappa, theta, sigma, rho, expiration_dates, strikes, data, optimizer, bounds): # container for heston calibration helpers helpers = [] # create Heston process, model and pricing engine # use given initial parameters for model process = ql.HestonProcess(curveHandle, dividendHandle, ql.QuoteHandle(ql.SimpleQuote(spot)), v0, kappa, theta, sigma, rho) model = ql.HestonModel(process) engine = ql.AnalyticHestonEngine(model) # nested cost function for model optimization def CostFunction(x): parameters = ql.Array(list(x)) model.setParams(parameters) error = [helper.calibrationError() for helper in helpers] return np.sqrt(np.sum(np.abs(error))) # create Heston calibration helpers, set pricing engines for i in range(len(expiration_dates)): for j in range(len(strikes)): expiration = expiration_dates[i] days = expiration - valuationDate period = ql.Period(days, ql.Days) vol = data[i][j] strike = strikes[j] helper = ql.HestonModelHelper(period, calendar, spot, strike, ql.QuoteHandle(ql.SimpleQuote(vol)), curveHandle, dividendHandle) helper.setPricingEngine(engine) helpers.append(helper) # run optimization, return calibrated model and process optimizer(CostFunction, bounds) return process, model
def heston_sensitivity(volatility, maturity_date, spot_price, strike_price, dividend_rate, option_type, risk_free_rate, calculation_date, hestonparams): day_count = ql.Actual365Fixed() calendar = ql.UnitedStates() ql.Settings.instance().evaluationDate = calculation_date payoff = ql.PlainVanillaPayoff(option_type, strike_price) exercise = ql.EuropeanExercise(maturity_date) european_option = ql.VanillaOption(payoff, exercise) spot_handle = ql.QuoteHandle(ql.SimpleQuote(spot_price)) flat_ts = ql.YieldTermStructureHandle( ql.FlatForward(calculation_date, risk_free_rate, day_count)) dividend_yield = ql.YieldTermStructureHandle( ql.FlatForward(calculation_date, dividend_rate, day_count)) volatility = volatility[0] flat_vol_ts = ql.BlackVolTermStructureHandle( ql.BlackConstantVol(calculation_date, calendar, volatility, day_count)) bsm_process = ql.BlackScholesMertonProcess(spot_handle, dividend_yield, flat_ts, flat_vol_ts) european_option.setPricingEngine(ql.AnalyticEuropeanEngine(bsm_process)) bs_price = european_option.NPV() spot_handle = ql.QuoteHandle(ql.SimpleQuote(spot_price)) flat_ts = ql.YieldTermStructureHandle( ql.FlatForward(calculation_date, risk_free_rate, day_count)) dividend_yield = ql.YieldTermStructureHandle( ql.FlatForward(calculation_date, dividend_rate, day_count)) heston_process = ql.HestonProcess(flat_ts, dividend_yield, spot_handle, hestonparams[0], hestonparams[1], hestonparams[2], hestonparams[3], hestonparams[4]) engine = ql.AnalyticHestonEngine(ql.HestonModel(heston_process), 0.01, 1000) european_option.setPricingEngine(engine) h_price = european_option.NPV() #return h_price,bs_price return h_price
# Analytic formulas: # Black-Scholes for European method = 'Black-Scholes' europeanOption.setPricingEngine( ql.AnalyticEuropeanEngine(bsmProcess)) tab.add_row([method, europeanOption.NPV(), 'N/A', 'N/A']) # semi-analytic Heston for European method = 'Heston semi-analytic' hestonProcess = ql.HestonProcess( flatTermStructure, flatDividendTS, underlyingH, volatility * volatility, 1.0, volatility * volatility, 0.001, 0.0) hestonModel = ql.HestonModel(hestonProcess) europeanOption.setPricingEngine( ql.AnalyticHestonEngine(hestonModel)) tab.add_row([method, europeanOption.NPV(), 'N/A', 'N/A']) # semi-analytic Bates for European method = 'Bates semi-analytic' batesProcess = ql.BatesProcess( flatTermStructure, flatDividendTS, underlyingH, volatility * volatility, 1.0, volatility * volatility, 0.001, 0.0, 1e-14, 1e-14, 1e-14) batesModel = ql.BatesModel(batesProcess) europeanOption.setPricingEngine( ql.BatesEngine(batesModel)) tab.add_row([method, europeanOption.NPV(), 'N/A', 'N/A']) # Barone-Adesi and Whaley approximation for American method = 'Barone-Adesi/Whaley'
ql.Settings.instance().evaluationDate = calculation_date dividend_yield = ql.QuoteHandle(ql.SimpleQuote(0.0)) risk_free_rate = 0.01 dividend_rate = 0.0 flat_ts = ql.YieldTermStructureHandle( ql.FlatForward(calculation_date, risk_free_rate, day_count)) dividend_ts = ql.YieldTermStructureHandle( ql.FlatForward(calculation_date, dividend_rate, day_count)) # dummy parameters initial_var = 0.2; rate_reversion = 0.5; long_term_var = 0.2; corr = -0.75; vol_of_vol = 0.2; # initial_var = 0.2; rate_reversion = 0.15; long_term_var = 0.6; corr = -0.75; vol_of_vol = 0.2; process = ql.HestonProcess(flat_ts, dividend_ts, ql.QuoteHandle(ql.SimpleQuote(spot)), initial_var, rate_reversion, long_term_var, vol_of_vol, corr) model = ql.HestonModel(process) engine = ql.AnalyticHestonEngine(model) heston_helpers = [] date = expiration_dates[expiry_index] for j, s in enumerate(strikes): t = (date - calculation_date) p = ql.Period(t, ql.Days) sigma = premium[j] helper = ql.HestonModelHelper(p, calendar, spot, s, ql.QuoteHandle(ql.SimpleQuote(sigma)), flat_ts, dividend_ts) helper.setPricingEngine(engine) heston_helpers.append(helper) lm = ql.LevenbergMarquardt(1e-8, 1e-8, 1e-8) model.calibrate(heston_helpers, lm, ql.EndCriteria(500, 50, 1.0e-8,1.0e-8, 1.0e-8))
def _QLBuild(self): self._QLFactory = ql.AnalyticHestonEngine( self._HestonModel(), self._params.get('relTolerance'), self._params.get('maxEval'))
# ----------------------------------------------------------- # The Heston process is constructed here. # # The Heston process calculates with changing volatility during the trade # ----------------------------------------------------------- v0 = volatility * volatility # spot variance kappa = 0.1 theta = v0 sigma = 0.1 rho = -0.75 spot_handle = ql.QuoteHandle(ql.SimpleQuote(spot_price)) flat_ts = ql.YieldTermStructureHandle( ql.FlatForward(calculation_date, risk_free_rate, day_count)) dividend_yield = ql.YieldTermStructureHandle( ql.FlatForward(calculation_date, dividend_rate, day_count)) heston_process = ql.HestonProcess(flat_ts, dividend_yield, spot_handle, v0, kappa, theta, sigma, rho) # ------------------------------------------------ # ----------------------------------------------- # Computation - ver. 3 - Heston # ----------------------------------------------- # ----------------------------------------------- pricing_engine = ql.AnalyticHestonEngine(ql.HestonModel(heston_process), 0.01, 1000) european_option.setPricingEngine(pricing_engine) h_price = european_option.NPV() print("The Heston model price is ", h_price)
0.1 * 0.1, 0.0001, 0.0, ) hestonModel = ql.HestonModel(hestonProcess) option = ql.VanillaOption(payoff, exercise) # method: analytic option.setPricingEngine(ql.AnalyticEuropeanEngine(process)) value = option.NPV() refValue = value report("analytic", value) # method: Heston semi-analytic option.setPricingEngine(ql.AnalyticHestonEngine(hestonModel)) report("Heston analytic", option.NPV()) # method: Heston COS method option.setPricingEngine(ql.COSHestonEngine(hestonModel)) report("Heston COS Method", option.NPV()) # method: integral option.setPricingEngine(ql.IntegralEngine(process)) report("integral", option.NPV()) # method: finite differences timeSteps = 801 gridPoints = 800 option.setPricingEngine(ql.FDEuropeanEngine(process, timeSteps, gridPoints))
# HESTON ENGINE v0 = 0.01 kappa = 0.5 theta = 0.01 sigma = 0.0001 rho = -0.5 HestonParams = [theta, kappa, sigma, rho, v0] relTolerance = 0.01 maxEval = 1000 HestonProcess = ql.HestonProcess(ql.YieldTermStructureHandle(r_ts), ql.YieldTermStructureHandle(q_ts), ql.QuoteHandle(s0), v0, kappa, theta, sigma, rho) HestonModel = ql.HestonModel(HestonProcess) HestonEngine = ql.AnalyticHestonEngine(HestonModel, relTolerance, maxEval) for i in range(len(EuropeanOptions)): EuropeanOptions[i].setPricingEngine(HestonEngine) # GENERATE DATAS nRand = 1000 start = time.time() MinParamsValues = [0.1, 0.01, 0.01, -0.999, 0.01] MaxParamsValues = [1.0, 0.50, 0.50, -0.1, 0.50] local_start = 0 local_end = 0 ArrParams = MakeUniformRandParams(MinParamsValues, MaxParamsValues, nRand) intermediary = time.time() #npv = np.zeros(nRand) #iv = np.zeros(nRand)
def evaluate_european_option(input_dict): tparams = input_dict["tradeParameters"] # Option Construction todaysDate = construct_date(tparams["evaluationDate"]) ql.Settings.instance().evaluationDate = todaysDate exercise = ql.EuropeanExercise(construct_date(tparams["exerciseDate"])) payoff = ql.PlainVanillaPayoff(ql.Option.Call, tparams["payoff"]) option = ql.VanillaOption(payoff, exercise) # Market Data underlying = ql.SimpleQuote(tparams["underlying"]) dividendYield = ql.FlatForward(todaysDate, tparams["dividendYield"], ql.Actual365Fixed()) volatility = ql.BlackConstantVol(todaysDate, ql.TARGET(), tparams["volatility"], ql.Actual365Fixed()) riskFreeRate = ql.FlatForward(todaysDate, tparams["riskFreeRate"], ql.Actual365Fixed()) process = ql.BlackScholesMertonProcess( ql.QuoteHandle(underlying), ql.YieldTermStructureHandle(dividendYield), ql.YieldTermStructureHandle(riskFreeRate), ql.BlackVolTermStructureHandle(volatility), ) hestonModel = init_heston_model(input_dict, riskFreeRate, dividendYield, underlying) if input_dict["engineName"] == "AnalyticEuropeanEngine": option.setPricingEngine(ql.AnalyticEuropeanEngine(process)) elif input_dict["engineName"] == "AnalyticHestonEngine": option.setPricingEngine(ql.AnalyticHestonEngine(hestonModel)) elif input_dict["engineName"] == "COSHestonEngine": option.setPricingEngine(ql.COSHestonEngine(hestonModel)) elif input_dict["engineName"] == "IntegralEngine": option.setPricingEngine(ql.IntegralEngine(process)) elif input_dict["engineName"] == "FdBlackScholesVanillaEngine": timeSteps = input_dict["engineParameters"]["timeSteps"] gridPoints = input_dict["engineParameters"]["gridPoints"] option.setPricingEngine( ql.FdBlackScholesVanillaEngine(process, timeSteps, gridPoints)) elif input_dict["engineName"] == "BinomialVanillaEngine": timeSteps = input_dict["engineParameters"]["timeSteps"] # possible tree settings: ["JR", "CRR", "EQP", "Trigeorgis", "Tian", "LR", "Joshi4"] tree = input_dict["engineParameters"]["tree"] option.setPricingEngine( ql.BinomialVanillaEngine(process, tree, timeSteps)) elif input_dict["engineName"] == "MCEuropeanEngine": if input_dict["engineParameters"]["random_source"] == "pseudorandom": option.setPricingEngine( ql.MCEuropeanEngine( process, "pseudorandom", timeSteps=input_dict["engineParameters"]["timeSteps"], requiredTolerance=input_dict["engineParameters"] ["requiredTolerance"], seed=input_dict["engineParameters"]["seed"])) elif input_dict["engineParameters"][ "random_source"] == "lowdiscrepancy": option.setPricingEngine( ql.MCEuropeanEngine( process, "lowdiscrepancy", timeSteps=input_dict["engineParameters"]["timeSteps"], requiredSamples=input_dict["engineParameters"] ["requiredSamples"])) else: raise Exception("Unimplemented engineName [{}]".format( input_dict["engineName"])) else: raise Exception("Unimplemented engineName [{}]".format( input_dict["engineName"])) value = option.NPV() return value
payoff = ql.PlainVanillaPayoff(option_type, strike_price) exercise = ql.EuropeanExercise(maturity_date) european_option = ql.VanillaOption(payoff, exercise) v0 = volatility * volatility kappa = 0.1 theta = v0 sigma = 0.1 rho = -0.75 spot_handle = ql.QuoteHandle(ql.SimpleQuote(spot_price)) flat_ts = ql.YieldTermStructureHandle( ql.FlatForward(calculation_date, risk_free_rate, day_count)) dividend_yield = ql.YieldTermStructureHandle( ql.FlatForward(calculation_date, dividend_rate, day_count)) heston_process = ql.HestonProcess(flat_ts, dividend_yield, spot_handle, v0, kappa, theta, sigma, rho) engine = ql.AnalyticHestonEngine(ql.HestonModel(heston_process)) european_option.setPricingEngine(engine) h_price = european_option.NPV() print(h_price) flat_vol_ts = ql.BlackVolTermStructureHandle( ql.BlackConstantVol(calculation_date, calendar, volatility, day_count)) bsm_process = ql.BlackScholesMertonProcess(spot_handle, dividend_yield, flat_ts, flat_vol_ts) european_option.setPricingEngine(ql.AnalyticEuropeanEngine(bsm_process)) bs_price = european_option.NPV() print(bs_price)
def _QLBuild(self): self._QLFactory = ql.AnalyticHestonEngine(self._HestonModel(), self._RelTolerance, self._MaxEval)