def set_values(values): try: settlement_date = values["startDate"] days = ql.Actual365Fixed() calendar = ql.Japan() frequency = ql.Annual ql.Settings.instance().evaluationDate = values["startDate"] compounding = ql.Compounded payoff = ql.PlainVanillaPayoff(values["callput"], values["strikeprice"]) eu_exercise = ql.EuropeanExercise(values["expirationdate"]) european_option = ql.VanillaOption(payoff, eu_exercise) spot_handle = ql.QuoteHandle(ql.SimpleQuote(values["spotprice"])) rTS = ql.YieldTermStructureHandle( ql.FlatForward(settlement_date, values["domesticInterestrate"], days, compounding, frequency)) fTS = ql.YieldTermStructureHandle( ql.FlatForward(settlement_date, values["foreignInterestrate"], days, compounding, frequency)) flat_vol_ts = ql.BlackVolTermStructureHandle( ql.BlackConstantVol(settlement_date, calendar, values["volatility"], days)) garman_kohlagen_process = ql.GarmanKohlagenProcess( spot_handle, fTS, rTS, flat_vol_ts) engine = ql.AnalyticEuropeanEngine(garman_kohlagen_process) european_option.setPricingEngine(engine) vol = float( european_option.impliedVolatility(values["premium"], garman_kohlagen_process, 0.000000001, minVol=0.00001, maxVol=5.0) * 100) flat_vol_ts = ql.BlackVolTermStructureHandle( ql.BlackConstantVol(settlement_date, calendar, vol / 100, days)) garman_kohlagen_process = ql.GarmanKohlagenProcess( spot_handle, fTS, rTS, flat_vol_ts) engine = ql.AnalyticEuropeanEngine(garman_kohlagen_process) european_option.setPricingEngine(engine) return round(float(values["premium"]), 3), floatrounding( float(european_option.delta())), floatrounding(vol), None except Exception as e: message = 'Unkown Error Occured' if 'root not bracketed' in repr(e): message = server_responses.root_not_bracketed_error elif 'ValueError' in repr(e): message = server_responses.value_error if 'KeyError' in repr(e): message = server_responses.missing_key_error return None, None, None, message
def calculateImpliedVolatility(self, option_price, spot_price, strike_price, calculation_date, maturity_date, option_type): volatility = 0 calendar = ql.China() 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)) 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) vol = european_option.impliedVolatility(option_price, bsm_process) flat_vol_ts2 = ql.BlackVolTermStructureHandle( ql.BlackConstantVol(calculation_date, calendar, vol, day_count)) bsm_process2 = ql.BlackScholesMertonProcess(spot_handle, dividend_yield, flat_ts, flat_vol_ts2) european_option2 = ql.VanillaOption(payoff, exercise) european_option2.setPricingEngine( ql.AnalyticEuropeanEngine(bsm_process2)) # print european_option2.NPV() - option_price return vol, european_option2.delta()
def __call__(self, vol): flat_vol_ts = ql.BlackVolTermStructureHandle( ql.BlackConstantVol(self._valuation_date, self._calendar, vol, self._day_count)) bsm_process = ql.BlackScholesMertonProcess(self._forward_handle, self._dividend_handle, self._yc_handle, flat_vol_ts) self._european_option.setPricingEngine(ql.AnalyticEuropeanEngine(bsm_process)) return self._european_option.NPV()
def set_values(self,request_form): spot_rate = float(request_form['spotprice']) strike_rate = float(request_form['strikeprice']) domestic_interest_rate = float(request_form['domesticInterestrate']) foreign_interest_rate = float(request_form['foreignInterestrate']) volatility = float(request_form['volatility']) expiration_date = ql.Date(int(request_form['expirationdate'][8:10]),int(request_form['expirationdate'][5:7]),int(request_form['expirationdate'][0:4])) start_date = ql.Date(int(request_form['startdate'][8:10]),int(request_form['startdate'][5:7]),int(request_form['startdate'][0:4])) settlement_date = start_date days = ql.Actual365Fixed() calendar = ql.Japan() frequency = ql.Annual ql.Settings.instance().evaluationDate = start_date if(request_form['callput'] == 'call'): option_type = ql.Option.Call else: option_type = ql.Option.Put compounding = ql.Compounded payoff = ql.PlainVanillaPayoff(option_type, strike_rate) eu_exercise = ql.EuropeanExercise(expiration_date) european_option = ql.VanillaOption(payoff, eu_exercise) spot_handle = ql.QuoteHandle(ql.SimpleQuote(spot_rate)) rTS = ql.YieldTermStructureHandle(ql.FlatForward(settlement_date,domestic_interest_rate, days,compounding, frequency)) fTS = ql.YieldTermStructureHandle(ql.FlatForward(settlement_date,foreign_interest_rate, days,compounding, frequency)) flat_vol_ts = ql.BlackVolTermStructureHandle(ql.BlackConstantVol(settlement_date, calendar, volatility, days)) garman_kohlagen_process = ql.GarmanKohlagenProcess(spot_handle, fTS, rTS, flat_vol_ts) engine = ql.AnalyticEuropeanEngine(garman_kohlagen_process) european_option.setPricingEngine(engine); return float(european_option.NPV()),float(european_option.delta())
def GreeksFunc(self, option, process): try: if self.product.exercise_type == 'E': engine = ql.AnalyticEuropeanEngine(process) option.setPricingEngine(engine) Greeks = pd.DataFrame([option.delta(),option.gamma(),option.vega()/100,option.theta()/365,option.rho()/100], columns = [''], \ index=['Delta','Gamma','Vega(%)','ThetaPerDay','Rho(%)']) elif self.product.exercise_type == 'A': #用BaroneAdesiWhaley离散法计算Greeks engine = ql.BaroneAdesiWhaleyEngine(process) #engine = ql.BinomialVanillaEngine(process, "crr", 100) #BTM option.setPricingEngine(engine) Greeks = self.Numerical_Greeks(option) else: raise ValueError #传入的参数self.product.exercise_type 无效 #缺少解析解时用离散法蒙特卡洛模拟,计算Greeks except: engine = ql.MCDiscreteArithmeticAPEngine( process, self.product.mc_str, self.product.is_bb, self.product.is_av, self.product.is_cv, self.product.n_require, self.product.tolerance, self.product.n_max, self.product.seed) option.setPricingEngine(engine) Greeks = self.Numerical_Greeks(option) # ============================================================================= # #无论亚美还是亚欧都一样 # engine = ql.MCDiscreteArithmeticAPEngine(process, self.product.mc_str, self.product.is_bb, self.product.is_av, self.product.is_cv, self.product.n_require, self.product.tolerance, self.product.n_max, self.product.seed) # option.setPricingEngine(engine) # Greeks = self.Numerical_Greeks(option) #进入离散法计算Greeks # ============================================================================= return Greeks
def plainvanilla(today, s, k, r, q, matDate, vol, flag): ql.Settings.instance().evaluationDate = ql.Date(today.day, today.month, today.year) riskFreeRate = ql.FlatForward(today, r, ql.Actual365Fixed()) # option parameters exercise = ql.EuropeanExercise(matDate) if (flag.lower() == "c" or flag.lower() == "call"): optionType = ql.Option.Call else: optionType = ql.Option.Put payoff = ql.PlainVanillaPayoff(optionType, k) underlying = ql.SimpleQuote(s) volatility = ql.BlackConstantVol(today, ql.SouthKorea(), vol, ql.Actual365Fixed()) dividendYield = ql.FlatForward(today, q, ql.Actual365Fixed()) process = ql.BlackScholesMertonProcess( ql.QuoteHandle(underlying), ql.YieldTermStructureHandle(dividendYield), ql.YieldTermStructureHandle(riskFreeRate), ql.BlackVolTermStructureHandle(volatility)) option = ql.VanillaOption(payoff, exercise) # method: analytic option.setPricingEngine(ql.AnalyticEuropeanEngine(process)) res = { "npv": option.NPV(), "delta": option.delta() * 0.01 * s, "gamma": option.gamma() * ((0.01 * s)**2), "theta": option.theta() } return res
def testQuantoTermStructure(self): """Testing quanto term structure""" today = ql.Date.todaysDate() dividend_ts = ql.YieldTermStructureHandle( ql.FlatForward(today, ql.QuoteHandle(ql.SimpleQuote(0.055)), self.dayCounter)) r_domestic_ts = ql.YieldTermStructureHandle( ql.FlatForward(today, ql.QuoteHandle(ql.SimpleQuote(-0.01)), self.dayCounter)) r_foreign_ts = ql.YieldTermStructureHandle( ql.FlatForward(today, ql.QuoteHandle(ql.SimpleQuote(0.02)), self.dayCounter)) sigma_s = ql.BlackVolTermStructureHandle( ql.BlackConstantVol(today, self.calendar, ql.QuoteHandle(ql.SimpleQuote(0.25)), self.dayCounter)) sigma_fx = ql.BlackVolTermStructureHandle( ql.BlackConstantVol(today, self.calendar, ql.QuoteHandle(ql.SimpleQuote(0.05)), self.dayCounter)) rho = ql.QuoteHandle(ql.SimpleQuote(0.3)) s_0 = ql.QuoteHandle(ql.SimpleQuote(100.0)) exercise = ql.EuropeanExercise( self.calendar.advance(today, 6, ql.Months)) payoff = ql.PlainVanillaPayoff(ql.Option.Call, 95.0) vanilla_option = ql.VanillaOption(payoff, exercise) quanto_ts = ql.YieldTermStructureHandle( ql.QuantoTermStructure(dividend_ts, r_domestic_ts, r_foreign_ts, sigma_s, ql.nullDouble(), sigma_fx, ql.nullDouble(), rho.value())) gbm_quanto = ql.BlackScholesMertonProcess(s_0, quanto_ts, r_domestic_ts, sigma_s) vanilla_engine = ql.AnalyticEuropeanEngine(gbm_quanto) vanilla_option.setPricingEngine(vanilla_engine) quanto_option = ql.QuantoVanillaOption(payoff, exercise) gbm_vanilla = ql.BlackScholesMertonProcess(s_0, dividend_ts, r_domestic_ts, sigma_s) quanto_engine = ql.QuantoEuropeanEngine(gbm_vanilla, r_foreign_ts, sigma_fx, rho) quanto_option.setPricingEngine(quanto_engine) quanto_option_pv = quanto_option.NPV() vanilla_option_pv = vanilla_option.NPV() message = """Failed to reproduce QuantoOption / EuropeanQuantoEngine NPV: {quanto_pv} by using the QuantoTermStructure as the dividend together with VanillaOption / AnalyticEuropeanEngine: {vanilla_pv} """.format(quanto_pv=quanto_option_pv, vanilla_pv=vanilla_option_pv) self.assertAlmostEquals(quanto_option_pv, vanilla_option_pv, delta=1e-12, msg=message)
def GreeksFunc(self, option, process): if self.exercise_type == 'E': engine = ql.AnalyticEuropeanEngine(process) option.setPricingEngine(engine) Greeks = pd.DataFrame([option.delta(),option.gamma(),option.vega()/100,option.theta()/365,option.rho()/100],\ index=['Delta','Gamma','Vega(%)','ThetaPerDay','Rho(%)']) elif self.exercise_type == 'A': #用离散法计算Greeks engine = ql.BaroneAdesiWhaleyEngine(process) #engine = ql.BinomialVanillaEngine(process, "crr", 100) #BTM option.setPricingEngine(engine) #Delta Gamma u0 = self.underlying_price.value() p0 = option.NPV() h = 0.01 #dS self.underlying_price.setValue(u0 + h) p_plus = option.NPV() #print(p_plus) self.underlying_price.setValue(u0 - h) p_minus = option.NPV() self.underlying_price.setValue(u0) delta = (p_plus - p_minus) / (2 * h) gamma = (p_plus - 2 * p0 + p_minus) / (h * h) #Vega v0 = self.volatility.value() h = 0.1 self.volatility.setValue(v0 + h) print(self.volatility.value()) p_plus = option.NPV() print(p_plus) self.volatility.setValue(v0) vega = (p_plus - p0) / h #Theta ql.Settings.instance().evaluationDate = self.vDate + 1 p1 = option.NPV() h = 1 / 365.0 theta = (p1 - p0) / h ql.Settings.instance().evaluationDate = self.vDate #Rho r0 = self.interest_rate.value() h = 0.0001 self.interest_rate.setValue(r0 + h) p_plus = option.NPV() self.interest_rate.setValue(r0) rho = (p_plus - p0) / h Greeks = pd.DataFrame([delta,gamma,vega/100,theta/365,rho/100],\ index=['Delta','Gamma','Vega(%)','ThetaPerDay','Rho(%)']) else: pass return Greeks
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.engine = ql.AnalyticEuropeanEngine(self.process) self.option.setPricingEngine(self.engine) return self.option.NPV()
def reset_vol(self, vol): self.flat_vol_ts = ql.BlackVolTermStructureHandle( ql.BlackConstantVol(self.settlement, self.calendar, vol, self.day_count)) self.bsm_process = ql.BlackScholesMertonProcess( self.spot_handle, self.dividend_yield, self.flat_ts, self.flat_vol_ts) engine = ql.AnalyticEuropeanEngine(self.bsm_process) self.ql_option.setPricingEngine(engine)
def calculate_barrier_price(evaluation, barrier_option, hist_spots, process, engineType): barrier = barrier_option.barrier barrierType = barrier_option.barrierType barrier_ql = barrier_option.option_ql exercise = barrier_option.exercise payoff = barrier_option.payoff # barrier_engine = ql.BinomialBarrierEngine(process, 'crr', 400) # european_engine = ql.BinomialVanillaEngine(process, 'crr', 400) european_engine = ql.AnalyticEuropeanEngine(process) barrier_engine = ql.AnalyticBarrierEngine(process) barrier_ql.setPricingEngine(barrier_engine) option_ql = ql.EuropeanOption(payoff, exercise) option_ql.setPricingEngine(european_engine) # check if hist_spots hit the barrier if len(hist_spots) == 0: option_price = barrier_ql.NPV() # option_delta = barrier_ql.delta() else: if barrierType == ql.Barrier.DownOut: if min(hist_spots) <= barrier: barrier_engine = None european_engine = None return 0.0, 0.0 else: option_price = barrier_ql.NPV() # option_delta = barrier_ql.delta() elif barrierType == ql.Barrier.UpOut: if max(hist_spots) >= barrier: barrier_engine = None european_engine = None return 0.0, 0.0 else: option_price = barrier_ql.NPV() # option_delta = barrier_ql.delta() elif barrierType == ql.Barrier.DownIn: if min(hist_spots) > barrier: option_price = barrier_ql.NPV() # option_delta = barrier_ql.delta() else: option_price = option_ql.NPV() # option_delta = option_ql.delta() else: if max(hist_spots) < barrier: option_price = barrier_ql.NPV() # option_delta = barrier_ql.delta() else: option_price = option_ql.NPV() # option_delta = option_ql.delta() barrier_engine = None european_engine = None barrier_ql = None option_ql = None if math.isnan(option_price): return 0.0 else: return option_price
def bsm_quantlib(): # 1.设置期权的五要素以及分红率和期权类型 # 1.1五要素 maturity_date = ql.Date(31, 7, 2020) spot_price = 9.37 strike_price = 10.00 volatility = 0.20 # the historical vols for a year risk_free_rate = 0.001 # 1.2分红率 dividend_rate = 0.01 # 1.3期权类型 option_type = ql.Option.Call # 1.4设置日期计算方式与使用地区 day_count = ql.Actual365Fixed() calendar = ql.UnitedStates() # 1.5计算期权价格的日期,也就是估值日,我们设为今天 calculation_date = ql.Date(31, 7, 2019) ql.Settings.instance().evaluationDate = calculation_date # 2.利用上的设置配置一个欧式期权 payoff = ql.PlainVanillaPayoff(option_type, strike_price) exercise = ql.EuropeanExercise(maturity_date) # 2.1根据payoff与exercise完成欧式期权的构建 european_option = ql.VanillaOption(payoff, exercise) # 3.构造我们的BSM定价引擎 # 3.1 处理股票当前价格 spot_handle = ql.QuoteHandle(ql.SimpleQuote(spot_price)) # 3.2 根据之前的无风险利率和日期计算方式,构建利率期限结构 flat_ts = ql.YieldTermStructureHandle( ql.FlatForward(calculation_date, risk_free_rate, day_count)) # 3.3 设置分红率期限结构 dividend_yield = ql.YieldTermStructureHandle( ql.FlatForward(calculation_date, dividend_rate, day_count)) # 3.4 设置波动率结构 flat_vol_ts = ql.BlackVolTermStructureHandle( ql.BlackConstantVol(calculation_date, calendar, volatility, day_count)) # 3.5 构造BSM定价引擎 bsm_process = ql.BlackScholesMertonProcess(spot_handle, dividend_yield, flat_ts, flat_vol_ts) # 4使用BSM定价引擎计算 european_option.setPricingEngine(ql.AnalyticEuropeanEngine(bsm_process)) #bs_price = european_option.NPV() #print"The theoretical price is ", bs_price # RESULTS print("Option value =", european_option.NPV()) print("Delta value =", european_option.delta()) print("Theta value =", european_option.theta()) print("Theta perday =", european_option.thetaPerDay()) print("Gamma value =", european_option.gamma()) print("Vega value =", european_option.vega()) print("Rho value =", european_option.rho())
def PricingFunc(self, option, process): '''------------- Set pricing engine, return both option and process -------------''' if self.exercise_type == 'E': engine = ql.AnalyticEuropeanEngine(process) elif self.exercise_type == 'A': engine = ql.BaroneAdesiWhaleyEngine(process) #engine = ql.BinomialVanillaEngine(process, "crr", 100) else: pass option.setPricingEngine(engine) return option.NPV()
def PricingFunc(self, option, process): '''设置定价引擎,返回 option, process''' if self.product.exercise_type == 'E': engine = ql.AnalyticEuropeanEngine(process) elif self.product.exercise_type == 'A': engine = ql.BaroneAdesiWhaleyEngine(process) #engine = ql.BinomialVanillaEngine(process, "crr", 100) else: pass option.setPricingEngine(engine) return option.NPV()
def get_BS_price(self,S=None, sigma = None,risk_free = None, \ dividend = None, K = None, exercise_date = None, calculation_date = None, \ day_count = None, dt = None, evaluation_method = "Numpy"): if evaluation_method is "QuantLib": # For our purpose, assume all inputs are scalar. stochastic_process = BlackScholesProcess(s0 = S, sigma = sigma, \ risk_free = risk_free, dividend = dividend, day_count=day_count) engine = ql.AnalyticEuropeanEngine( stochastic_process.get_process(calculation_date)) ql_payoff = ql.PlainVanillaPayoff(ql.Option.Call, K) exercise_date = ql.EuropeanExercise(exercise_date) instrument = ql.VanillaOption(ql_payoff, exercise_date) if type(self.process).__name__ is "BlackScholesProcess": engine = ql.AnalyticEuropeanEngine( self.process.get_process(calculation_date)) instrument.setPricingEngine(engine) return instrument.NPV() elif evaluation_method is "Numpy": # For our purpose, assume s0 is a NumPy array, other inputs are scalar. T = np.arange(0, (exercise_date - calculation_date + 1)) * dt T = np.repeat(np.flip(T[None, :]), S.shape[0], 0) # Ignore division by 0 warning (expected behaviors as the limits of CDF is defined). with np.errstate(divide='ignore'): d1 = np.divide( np.log(S / K) + (risk_free - dividend + 0.5 * sigma**2) * T, sigma * np.sqrt(T)) d2 = np.divide( np.log(S / K) + (risk_free - dividend - 0.5 * sigma**2) * T, sigma * np.sqrt(T)) return (S * stats.norm.cdf(d1, 0.0, 1.0) - K * np.exp(-risk_free * T) * stats.norm.cdf(d2, 0.0, 1.0))
def euromodel(price, underline, expire, strike, spot_vol, t): exercise = ql.EuropeanExercise(ql.Settings.instance().evaluationDate + expire) payoff = ql.PlainVanillaPayoff(t, strike) option = ql.EuropeanOption(payoff, exercise) underline = ql.QuoteHandle(ql.SimpleQuote(underline)) dividend = ql.YieldTermStructureHandle( ql.FlatForward(0, ql.TARGET(), 0, ql.Actual365Fixed())) risk_free_rate = ql.YieldTermStructureHandle( ql.FlatForward(0, ql.TARGET(), 0.00, ql.Actual365Fixed())) spot_vol = ql.BlackVolTermStructureHandle( ql.BlackConstantVol(0, ql.TARGET(), spot_vol, ql.Actual365Fixed())) process = ql.BlackScholesMertonProcess(underline, dividend, risk_free_rate, spot_vol) option.setPricingEngine(ql.AnalyticEuropeanEngine(process)) try: iv = option.impliedVolatility(price, process) except Exception as e: iv = 0 fiv = ql.BlackVolTermStructureHandle( ql.BlackConstantVol(0, ql.TARGET(), iv, ql.Actual365Fixed())) process = ql.BlackScholesMertonProcess(underline, dividend, risk_free_rate, fiv) option.setPricingEngine(ql.AnalyticEuropeanEngine(process)) delta = option.delta() vega = option.vega() gamma = option.gamma() theta = option.theta() return { "iv": iv, "delta": delta, "vega": vega, "gamma": gamma, "theta": theta }
def get_engine(bsmprocess, engineType): if engineType == 'AnalyticEuropeanEngine': engine = ql.AnalyticEuropeanEngine(bsmprocess) elif engineType == 'BinomialVanillaEngine': engine = ql.BinomialVanillaEngine(bsmprocess, 'crr', 801) elif engineType == 'AnalyticBarrierEngine': engine = ql.AnalyticBarrierEngine(bsmprocess) elif engineType == 'BinomialBarrierEngine': engine = ql.BinomialBarrierEngine(bsmprocess, 'crr', 801) else: engine = None return engine
def calculate_effective_delta_svi2(hedge_date, daycounter, calendar, params_Mi, spot, rf_h_d, strike, maturitydt, optiontype): ql.Settings.instance().evaluationDate = hedge_date step = 0.005 rf = rf_h_d yield_ts = ql.YieldTermStructureHandle( ql.FlatForward(hedge_date, rf, daycounter)) dividend_ts = ql.YieldTermStructureHandle( ql.FlatForward(hedge_date, 0.0, daycounter)) exercise = ql.EuropeanExercise(maturitydt) payoff = ql.PlainVanillaPayoff(optiontype, strike) option = ql.EuropeanOption(payoff, exercise) ttm = daycounter.yearFraction(hedge_date, maturitydt) s_plus = spot + step s_minus = spot - step Ft_plus = s_plus * math.exp(rf * ttm) x_plus = math.log(strike / Ft_plus, math.e) Ft_minus = s_minus * math.exp(rf * ttm) x_minus = math.log(strike / Ft_minus, math.e) iv_plus = implied_vol_function(params_Mi, x_plus) iv_minus = implied_vol_function(params_Mi, x_minus) flat_vol_plus = ql.BlackVolTermStructureHandle( ql.BlackConstantVol(hedge_date, calendar, iv_plus, daycounter)) flat_vol_minus = ql.BlackVolTermStructureHandle( ql.BlackConstantVol(hedge_date, calendar, iv_minus, daycounter)) process_plus = ql.BlackScholesMertonProcess( ql.QuoteHandle(ql.SimpleQuote(s_plus)), dividend_ts, yield_ts, flat_vol_plus) process_minus = ql.BlackScholesMertonProcess( ql.QuoteHandle(ql.SimpleQuote(s_minus)), dividend_ts, yield_ts, flat_vol_minus) option.setPricingEngine(ql.AnalyticEuropeanEngine(process_plus)) npv_plus = option.NPV() option.setPricingEngine(ql.AnalyticEuropeanEngine(process_minus)) npv_minus = option.NPV() delta = (npv_plus - npv_minus) / (s_plus - s_minus) return delta
def calculate_graphLines(values): try: settlement_date = values["startDate"] days = ql.Actual365Fixed() calendar = ql.Japan() frequency = ql.Annual ql.Settings.instance().evaluationDate = values["startDate"] compounding = ql.Compounded payoff = ql.PlainVanillaPayoff(values["callput"], values["strikeprice"]) eu_exercise = ql.EuropeanExercise(values["expirationdate"]) european_option = ql.VanillaOption(payoff, eu_exercise) spot_handle = ql.QuoteHandle(ql.SimpleQuote(values["spotprice"])) rTS = ql.YieldTermStructureHandle( ql.FlatForward(settlement_date, values["domesticInterestrate"], days, compounding, frequency)) fTS = ql.YieldTermStructureHandle( ql.FlatForward(settlement_date, values["foreignInterestrate"], days, compounding, frequency)) flat_vol_ts = ql.BlackVolTermStructureHandle( ql.BlackConstantVol(settlement_date, calendar, values["volatility"], days)) garman_kohlagen_process = ql.GarmanKohlagenProcess( spot_handle, fTS, rTS, flat_vol_ts) engine = ql.AnalyticEuropeanEngine(garman_kohlagen_process) european_option.setPricingEngine(engine) premium = float(european_option.NPV()) x_axis_values, premium_values, intrinsic_values = [], [], [] max_value, min_value = create_range(values) x_axis_values = create_x_axis_values(max_value, min_value, values) premium_values = create_premium_values(x_axis_values, premium, values) intrinsic_values = get_intrinsic_values(x_axis_values, premium, values) return x_axis_values, premium_values, intrinsic_values, None except Exception as e: message = 'Unkown Error Occured' if 'KeyError' in repr(e): message = server_responses.missing_key_error elif 'strike (inf)' in repr(e): message = server_responses.strike_outside_of_domain_curve_error elif 'ValueError' in repr(e): message = server_responses.value_error return None, None, None, message
def calculate_plain_price_vol(evaluation, daycounter, calendar, option, hist_spots, spot, vol, engineType): underlying = ql.SimpleQuote(spot) option_ql = option.option_ql process = evaluation.get_bsmprocess_cnstvol(daycounter, calendar, underlying, vol) if engineType == 'BinomialEngine': engine = ql.BinomialVanillaEngine(process, 'crr', 400) else: engine = ql.AnalyticEuropeanEngine(process) option_ql.setPricingEngine(engine) option_price = option_ql.NPV() option_delta = option_ql.delta() return option_price, option_delta
def create_engine(self): if self.exercise_type == 'european': self.exercise = ql.EuropeanExercise(self.date_expiration) self.engine = ql.AnalyticEuropeanEngine(self.process) elif self.exercise_type == 'american': self.exercise = ql.AmericanExercise(self.date_evaluation, self.date_expiration) self.engine = ql.BinomialVanillaEngine(self.process, 'crr', self.n_steps) else: raise Exception("Received unexpected exercise type " f"'{self.exercise_type}'.") self.option = ql.VanillaOption(self.payoff, self.exercise) self.option.setPricingEngine(self.engine)
def GreeksFunc(self, option, process): if self.product.exercise_type == 'E': engine = ql.AnalyticEuropeanEngine(process) option.setPricingEngine(engine) Greeks = pd.DataFrame([option.delta(),option.gamma(),option.vega()/100,option.theta()/365,option.rho()/100], columns = [''], \ index=['Delta','Gamma','Vega(%)','ThetaPerDay','Rho(%)']) elif self.product.exercise_type == 'A': #用离散法计算Greeks engine = ql.BaroneAdesiWhaleyEngine(process) #engine = ql.BinomialVanillaEngine(process, "crr", 100) #BTM option.setPricingEngine(engine) Greeks = self.Numerical_Greeks(option) #进入离散法计算Greeks else: pass return Greeks
def _gbm_option(val_date=FLAGS.TODAY, maturity_date=FLAGS.MATURITY, spot_price=FLAGS.SPOT, risk_free_rate=FLAGS.RF_RATE, sigma=FLAGS.BS_SIGMA, strike_price=FLAGS.STRIKE): """_gbm_option. Helper to create the option object in QuantLib :param val_date: valuation date :param maturity_date: maturity of the call option :param spot_price: :param risk_free_rate: risk free rate for the BS model :param sigma: volatility of the BS model :param strike_price: strike price of the call option """ option_type = ql.Option.Call day_count = ql.Actual365Fixed() calendar = ql.UnitedStates() payoff = ql.PlainVanillaPayoff(option_type, strike_price) eu_exercise = ql.EuropeanExercise(maturity_date) european_option = ql.VanillaOption(payoff, eu_exercise) spot_handle = ql.QuoteHandle( ql.SimpleQuote(spot_price) ) flat_ts = ql.YieldTermStructureHandle( ql.FlatForward(val_date, risk_free_rate, day_count) ) dividend_rate = 0 dividend_yield = ql.YieldTermStructureHandle( ql.FlatForward(val_date, dividend_rate, day_count) ) flat_vol_ts = ql.BlackVolTermStructureHandle( ql.BlackConstantVol(val_date, calendar, sigma, day_count) ) bsm_process = ql.BlackScholesMertonProcess(spot_handle, dividend_yield, flat_ts, flat_vol_ts) european_option.setPricingEngine(ql.AnalyticEuropeanEngine(bsm_process)) return european_option
def pricing(self, option_type, strike_price, expiry_date, valuation_date, underlying_price, dividend_rate, interest_rate, volatility): # ------------- Option setup ------------- if option_type.lower() in ['c', 'call']: put_or_call = ql.Option.Call elif option_type.lower() in ['p', 'put']: put_or_call = ql.Option.Put else: print('unknown option type:', option_type) return (-1) payoff = ql.PlainVanillaPayoff(put_or_call, strike_price) # shift expiry date forward by 1 day, so that calculation can be done on the expiry day expiry_date_1 = expiry_date + dt.timedelta(days=1) eDate = ql.Date(expiry_date_1.day, expiry_date_1.month, expiry_date_1.year) exercise = ql.EuropeanExercise(eDate) option = ql.VanillaOption(payoff, exercise) # ------------- Process setup ------------- valuation_date = min(expiry_date, valuation_date) vDate = ql.Date(valuation_date.day, valuation_date.month, valuation_date.year) # Set the valuation date, by default it will use today's date ql.Settings.instance().evaluationDate = vDate # Calendar calendar = ql.China() day_counter = ql.ActualActual() # Curve setup dividend_curve = ql.FlatForward(vDate, dividend_rate, day_counter) interest_curve = ql.FlatForward(vDate, interest_rate, day_counter) volatility_curve = ql.BlackConstantVol(vDate, calendar, volatility, day_counter) # Setup Black Scholes Merton Process u = ql.QuoteHandle(ql.SimpleQuote(underlying_price)) d = ql.YieldTermStructureHandle(dividend_curve) r = ql.YieldTermStructureHandle(interest_curve) v = ql.BlackVolTermStructureHandle(volatility_curve) process = ql.BlackScholesMertonProcess(u, d, r, v) # ------------- Set pricing engine, return both option and process ------------- engine = ql.AnalyticEuropeanEngine(process) option.setPricingEngine(engine) return (pd.Series({'option': option, 'process': process}))
def getTheoOptionsPrice(calc_date, spot_price, strike_price, contract_type, days_to_expire, vix): # option data #spot_price = 2970.27 #strike_price = 2900 volatility = vix # the historical vols for a year dividend_rate = 0.0 if contract_type == 'c': option_type = ql.Option.Call else: option_type = ql.Option.Put risk_free_rate = 0.000 day_count = ql.Actual365Fixed() calendar = ql.UnitedStates() calculation_date = ql.Date(calc_date.day, calc_date.month, calc_date.year) (d, m, y) = getMaturityDate(calc_date, days_to_expire) maturity_date = ql.Date(d, m, y) ql.Settings.instance().evaluationDate = calculation_date settlement = calculation_date # construct the European Option payoff = ql.PlainVanillaPayoff(option_type, strike_price) exercise = ql.EuropeanExercise(maturity_date) european_option = ql.VanillaOption(payoff, exercise) am_exercise = ql.AmericanExercise(settlement, maturity_date) american_option = ql.VanillaOption(payoff, am_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)) 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("The theoretical price is ", bs_price) steps = 200 binomial_engine = ql.BinomialVanillaEngine(bsm_process, "crr", steps) american_option.setPricingEngine(binomial_engine) print(american_option.NPV()) return bs_price
def bs_opt(maturity_date,spot_price,strike_price,volatility,dividend_rate,option_type,risk_free_rate,day_count ,calendar,calculation_date): #payoff payoff = ql.PlainVanillaPayoff(option_type, strike_price) exercise = ql.EuropeanExercise(maturity_date) european_option = ql.VanillaOption(payoff, exercise) #process 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)) flat_vol_ts = ql.BlackVolTermStructureHandle(ql.BlackConstantVol(calculation_date, calendar, volatility, day_count)) #price 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() return bs_price
def __init__(self, dt_eval: datetime.date, dt_maturity: datetime.date, option_type: constant.OptionType, spot: float, strike: float, vol: float = 0.0, rf: float = 0.03, dividend_rate: float = 0.0): super().__init__() self.dt_eval = dt_eval self.dt_maturity = dt_maturity self.option_type = option_type self.values: typing.List[typing.List[float]] = [] self.asset_values: typing.List[typing.List[float]] = [] self.exercise_values: typing.List[typing.List[float]] = [] self.strike = strike self.spot = spot self.vol = vol self.rf = rf self.dividend_rate = dividend_rate self.maturity_date = constant.QuantlibUtil.to_ql_date(dt_maturity) self.settlement = constant.QuantlibUtil.to_ql_date(dt_eval) ql.Settings.instance().evaluationDate = self.settlement if option_type == constant.OptionType.PUT: self.ql_option_type = ql.Option.Put else: self.ql_option_type = ql.Option.Call payoff = ql.PlainVanillaPayoff(self.ql_option_type, strike) self.exercise = ql.EuropeanExercise(self.maturity_date) self.ql_option = ql.VanillaOption(payoff, self.exercise) self.day_count = ql.ActualActual() self.calendar = ql.China() self.spot_handle = ql.QuoteHandle(ql.SimpleQuote(spot)) self.flat_ts = ql.YieldTermStructureHandle( ql.FlatForward(self.settlement, rf, self.day_count)) self.dividend_yield = ql.YieldTermStructureHandle( ql.FlatForward(self.settlement, self.dividend_rate, self.day_count)) self.flat_vol_ts = ql.BlackVolTermStructureHandle( ql.BlackConstantVol(self.settlement, self.calendar, self.vol, self.day_count)) self.bsm_process = ql.BlackScholesMertonProcess( self.spot_handle, self.dividend_yield, self.flat_ts, self.flat_vol_ts) engine = ql.AnalyticEuropeanEngine(self.bsm_process) self.ql_option.setPricingEngine(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, maturity: ql.Period() = ql.Period(1, ql.Years), tradeType: TradeType = TradeType.CALL, tradeDirection: TradeDirection = TradeDirection.LONG, underlying: Stock = Stock.ADS, notional: float = 1, strike: float = None): """ Equity Option :param notional: Count of underlying shares :param maturity: Time to maturity of the option (in days). Will be used for both, M and T of paragraph 155 after being divided by 360 :param tradeType: Can be TradeType.CALL or TradeType.PUT :param tradeDirection: Can be TradeDirection.LONG or TradeDirection.SHORT :param strike: Strike of option is no strike is given it default to an at the money option """ self.underlying = underlying self.K = strike if strike != None else EquitySpotQuote[ self.underlying.name].value.value( ) # no K is given it is the current Spot self.currency = underlying.value['Currency'] self.ql_maturity = maturity super(EquityOption, self).__init__(assetClass=AssetClass.EQ, tradeType=tradeType, tradeDirection=tradeDirection, m=convert_period_to_days(maturity) / 360, t=convert_period_to_days(maturity) / 360, notional=notional) vol_handle = EquityVolatility[self.underlying.name].value spot_handle = EquitySpot[self.underlying.name].value self.S = spot_handle.value() discounting_curve = DiscountCurve[self.currency.name].value black_scholes_process = ql.BlackScholesProcess(spot_handle, discounting_curve.value, vol_handle) engine = ql.AnalyticEuropeanEngine(black_scholes_process) if tradeType.name == TradeType.CALL.name: option_type = ql.Option.Call else: option_type = ql.Option.Put payoff = ql.PlainVanillaPayoff(option_type, self.K) maturity_date = today + maturity exercise = ql.EuropeanExercise(maturity_date) self.ql_option = ql.VanillaOption(payoff, exercise) self.ql_option.setPricingEngine(engine)
def create_premium_values(x_axis_values, premium, values): values_array = [] for item in x_axis_values: spot_rate = item settlement_date = values["startDate"] days = ql.Actual365Fixed() calendar = ql.Japan() frequency = ql.Annual ql.Settings.instance().evaluationDate = values["startDate"] compounding = ql.Compounded payoff = ql.PlainVanillaPayoff(values["callput"], values["strikeprice"]) eu_exercise = ql.EuropeanExercise(values["expirationdate"]) european_option = ql.VanillaOption(payoff, eu_exercise) spot_handle = ql.QuoteHandle(ql.SimpleQuote(spot_rate)) rTS = ql.YieldTermStructureHandle( ql.FlatForward(settlement_date, values["domesticInterestrate"], days, compounding, frequency)) fTS = ql.YieldTermStructureHandle( ql.FlatForward(settlement_date, values["foreignInterestrate"], days, compounding, frequency)) flat_vol_ts = ql.BlackVolTermStructureHandle( ql.BlackConstantVol(settlement_date, calendar, values["volatility"], days)) garman_kohlagen_process = ql.GarmanKohlagenProcess( spot_handle, fTS, rTS, flat_vol_ts) engine = ql.AnalyticEuropeanEngine(garman_kohlagen_process) european_option.setPricingEngine(engine) values_array.append(float(european_option.NPV())) if values["callput"] == ql.Option.Call: for i in range(0, len(values_array)): values_array[i] = values_array[i] - premium else: for i in range(0, len(values_array)): values_array[i] = values_array[i] - premium premium_values = values_array return premium_values