def binomialmodels(stockprice, strikeprice, volatility, intrate, calcdate, expdate, divrate, opttype, modelname, steps): day_count = ql.Actual365Fixed() calendar = ql.UnitedStates() calculation_date = ql.Date(calcdate.day, calcdate.month, calcdate.year) if opttype == "p": option_type = ql.Option.Put else: option_type = ql.Option.Call exp_date = ql.Date(expdate.day, expdate.month, expdate.year) ql.Settings.instance().evaluationDate = calculation_date payoff = ql.PlainVanillaPayoff(option_type, strikeprice) exercise = ql.AmericanExercise(calculation_date, exp_date) american_option = ql.VanillaOption(payoff, exercise) spot_handle = ql.QuoteHandle(ql.SimpleQuote(stockprice)) flat_ts = ql.YieldTermStructureHandle( ql.FlatForward(calculation_date, intrate, day_count)) dividend_yield = ql.YieldTermStructureHandle( ql.FlatForward(calculation_date, divrate, 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) binomial_engine = ql.BinomialVanillaEngine(bsm_process, modelname, steps) american_option.setPricingEngine(binomial_engine) return american_option.NPV()
def setUp(self): self.today = ql.Date(21, ql.April, 2019) self.dc = ql.Actual365Fixed() ql.Settings.instance().evaluationDate = self.today self.domesticTS = ql.FlatForward(self.today, 0.025, self.dc) self.foreignTS = ql.FlatForward(self.today, 0.075, self.dc) self.fxVolTS = ql.BlackConstantVol(self.today, ql.TARGET(), 0.15, self.dc) self.quantoHelper = ql.FdmQuantoHelper( self.domesticTS, self.foreignTS, self.fxVolTS, -0.75, 1.0) self.divYieldTS = ql.FlatForward(self.today, 0.03, self.dc) divDate = ql.DateVector() divDate.push_back(self.today + ql.Period(6, ql.Months)) divAmount = ql.DoubleVector() divAmount.push_back(8.0) maturityDate = self.today + ql.Period(9, ql.Months) self.option = ql.DividendVanillaOption( ql.PlainVanillaPayoff(ql.Option.Call, 105), ql.AmericanExercise(self.today, maturityDate), divDate, divAmount)
def option_exercise_type(exercise_type, date, maturity): if exercise_type.upper() == 'AMERICAN': return ql.AmericanExercise(to_ql_date(date), to_ql_date(maturity)) elif exercise_type.upper() == 'EUROPEAN': return ql.EuropeanExercise(to_ql_date(maturity)) else: raise ValueError('Exercise type not supported')
def __init__(self, strike, effectivedt, maturitydt, optionType): self.strike = strike self.maturitydt = maturitydt self.optionType = optionType exercise = ql.AmericanExercise(effectivedt, maturitydt) payoff = ql.PlainVanillaPayoff(optionType, strike) option = ql.VanillaOption(payoff, exercise) self.option_ql = option
def _create_option(self, option_type, strike_price, maturity_yyyy_mm_dd): payoff = ql.PlainVanillaPayoff(option_type, strike_price) (yyyy, mm, dd) = maturity_yyyy_mm_dd maturity_date = ql.Date(dd, mm, yyyy) settlement_date = self._calendar.advance(maturity_date, 0, ql.Days) exercise = ql.AmericanExercise(settlement_date, maturity_date) option = ql.VanillaOption(payoff, exercise) return option
def Set_Process(self, exercise_type): '''定义Payoff''' if self.option_type == 'call': put_or_call = ql.Option.Call elif self.option_type == 'put': put_or_call = ql.Option.Put else: print('unknown option type:', self.option_type) return (-1) payoff = ql.PlainVanillaPayoff( put_or_call, self.strike_price.value()) #根据call/put,产生相应Payoff对象 '''定义Exercise''' #shift expiry date forward by 1 day, so that calculation can be done on the expiry day self.exercise_type = exercise_type expiry_date_1 = self.expiry_date + dt.timedelta(days=1) eDate = ql.Date(expiry_date_1.day, expiry_date_1.month, expiry_date_1.year) self.valuation_date = min(self.expiry_date, self.valuation_date) self.vDate = ql.Date(self.valuation_date.day, self.valuation_date.month, self.valuation_date.year) if self.exercise_type == 'E': exercise = ql.EuropeanExercise(eDate) elif self.exercise_type == 'A': exercise = ql.AmericanExercise(self.vDate, eDate) else: print('unknown option type:', self.exercise_type) return (-1) '''定义Calendar''' #Set the valuation date, by default it will use today's date ql.Settings.instance().evaluationDate = self.vDate calendar = ql.China() day_counter = ql.ActualActual() '''定义Option,输入PayOff与Exercise''' option = ql.VanillaOption(payoff, exercise) '''定义TermStructure(Vol,Dividend,Int)''' #dividend_curve = ql.FlatForward(self.vDate, self.dividend_rate.value(), day_counter) #interest_curve = ql.FlatForward(self.vDate, self.interest_rate.value(), day_counter) #volatility_curve = ql.BlackConstantVol(self.vDate, calendar, self.volatility.value(), day_counter) dividend_curve = ql.FlatForward(0, ql.TARGET(), ql.QuoteHandle(self.dividend_rate), day_counter) interest_curve = ql.FlatForward(0, ql.TARGET(), ql.QuoteHandle(self.interest_rate), day_counter) volatility_curve = ql.BlackConstantVol(0, ql.TARGET(), ql.QuoteHandle(self.volatility), day_counter) u = ql.QuoteHandle(self.underlying_price) d = ql.YieldTermStructureHandle(dividend_curve) r = ql.YieldTermStructureHandle(interest_curve) v = ql.BlackVolTermStructureHandle(volatility_curve) process = ql.BlackScholesMertonProcess(u, d, r, v) return option, process
def __init__(self, stockPrice, strikePrice, evaluationDate, maturityDate, optionType): # 输入参数为期权条款本身 # optionType为ql.Option.Call或ql.Option.Put super().__init__(stockPrice, evaluationDate) self.strikePrice = strikePrice # 敲定价不用ql.SimpleQuote包装,Payoff不支持 self.maturityDate = self.str2date(maturityDate) # 美式期权为到期日 self.optionType = optionType # 构造期权 self.option = ql.VanillaOption(ql.PlainVanillaPayoff(self.optionType, self.strikePrice), ql.AmericanExercise(self.evaluationDate, self.maturityDate))
def get_option_price(code, time, steps, price=-1, volat=-1): #time: 未来时间 #price: 未来期货价格 option_code = code future_code = option_code.split('-')[0] d_day = Future.objects.get(code=future_code).delivery_day maturity_date = ql.Date(d_day.day, d_day.month, d_day.year) calculation_date = ql.Date(time.day, time.month, time.year) if price <= 0: spot_price = FutureTreadingData.objects.get(future=future_code, time=time).close_price else: spot_price = price strike_price = int(option_code.split('-')[-1]) # volatility = history_vol(code=code, day=datetime.datetime(time.year, time.month, time.day)) #to be change volatility = volat if volatility <= 0: volatility = history_vol(option_code) dividend_rate = 0 option_type = ql.Option.Call risk_free_rate = np.log(1.03) day_count = ql.Actual365Fixed() calendar = ql.China() # time1 = tm.clock() ql.Settings.instance().evaluationDate = calculation_date payoff = ql.PlainVanillaPayoff(option_type, strike_price) settlement = calculation_date 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) binomial_engine = ql.BinomialVanillaEngine(bsm_process, "crr", steps) american_option.setPricingEngine(binomial_engine) # print(american_option.NPV()) # # time2 = tm.clock() # print(time2 - time1) return american_option.NPV()
def __init__(self, dt_eval: datetime.date, dt_maturity: datetime.date, option_type: constant.OptionType, option_exercise_type: constant.OptionExerciseType, spot: float, strike: float, vol: float = 0.2, rf: float = 0.03, n: int = 801, dividend_rate: float = 0.0): super().__init__() 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.steps: int = n 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.option_type = ql.Option.Put else: self.option_type = ql.Option.Call payoff = ql.PlainVanillaPayoff(self.option_type, strike) if option_exercise_type == constant.OptionExerciseType.AMERICAN: self.exercise = ql.AmericanExercise(self.settlement, self.maturity_date) self.ql_option = ql.VanillaOption(payoff, self.exercise) else: 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) binomial_engine = ql.BinomialVanillaEngine(self.bsm_process, "crr", self.steps) self.ql_option.setPricingEngine(binomial_engine) ql.BaroneAdesiWhaleyEngine(self.bsm_process)
def _create(self, asof_date): strike_price = self[F.STRIKE] option_type = self[F.OPTION_TYPE] maturity_date = self[F.MATURITY_DATE] start_date = self.get(F.START_DATE, asof_date) payoff_at_expiry = self.get(F.PAYOFF_AT_EXPIRY, False) payoff = ql.PlainVanillaPayoff(option_type, strike_price) exercise = ql.AmericanExercise(start_date, maturity_date, payoff_at_expiry) american_option = ql.VanillaOption(payoff, exercise) return american_option
def quantlibprice(strike_price,optiontype,volatility): # option data maturity_date = ql.Date(15, 11, 2020) spot_price = 311.790009 dividend_rate = 0 if optiontype == "call": option_type = ql.Option.Call elif optiontype == "put": option_type = ql.Option.Put risk_free_rate = 0.0154 day_count = ql.Actual365Fixed() calendar = ql.UnitedStates() calculation_date = ql.Date(15, 11, 2019) ql.Settings.instance().evaluationDate = calculation_date payoff = ql.PlainVanillaPayoff(option_type, strike_price) settlement = calculation_date 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) steps = 200 binomial_engine = ql.BinomialVanillaEngine(bsm_process, "crr", steps) american_option.setPricingEngine(binomial_engine) return american_option.NPV()
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 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 evaluate_american_option(input_dict): tparams = input_dict["tradeParameters"] # Option Construction todaysDate = construct_date(tparams["evaluationDate"]) ql.Settings.instance().evaluationDate = todaysDate exercise = ql.AmericanExercise(todaysDate, construct_date(tparams["exerciseDate"])) payoff = ql.PlainVanillaPayoff(ql.Option.Put, 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), ) if input_dict["engineName"] == "BaroneAdesiWhaleyApproximationEngine": option.setPricingEngine(ql.BaroneAdesiWhaleyApproximationEngine(process)) elif input_dict["engineName"] == "BjerksundStenslandApproximationEngine": option.setPricingEngine(ql.BjerksundStenslandApproximationEngine(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)) else: raise Exception("Unimplemented engineName [{}]".format(input_dict["engineName"])) value = option.NPV() return value
def to_ql_option_exercise_type(exercise_type, earliest_date, maturity): """ Returns the QuantLib object representing the exercise type. :param exercise_type: str The exercise name :param earliest_date: QuantLib.Date The earliest date of exercise :param maturity: QuantLib.Date The maturity / exercise date :return: QuantLib.Exercise """ if exercise_type.upper() == 'AMERICAN': return ql.AmericanExercise(earliest_date, maturity) elif exercise_type.upper() == 'EUROPEAN': return ql.EuropeanExercise(maturity) else: raise ValueError('Exercise type not supported')
def getAmericanOption(valuation_date, expiry_date, put_or_call, strike_price, process): grid_points = 100 exercise = ql.AmericanExercise(valuation_date, expiry_date) payoff = ql.PlainVanillaPayoff(put_or_call, strike_price) #Option Setup option = ql.VanillaOption(payoff, exercise) time_steps = 1000 xGrid = 1000 engine = ql.FdBlackScholesVanillaEngine(process, time_steps, xGrid) option.setPricingEngine(engine) return option
def imp_vol_ql(today, settlement, expiry, underlying, riskfree, dividend_yield, parity, strike, premium): # Dates today = ql.Date(today.day, today.month, today.year) settlement = ql.Date(settlement.day, settlement.month, settlement.year) expiry = ql.Date(expiry.day, expiry.month, expiry.year) ql.Settings.instance().evaluationDate = today # Market data underlying = ql.SimpleQuote(underlying) r = ql.SimpleQuote(riskfree) # risk-free rate q = ql.SimpleQuote(dividend_yield) # dividend yield 0.016 vol = ql.SimpleQuote( 0.20) # only needed for price process, not relevant for implied vol dcc = ql.Actual365Fixed() risk_free_curve = ql.FlatForward(settlement, ql.QuoteHandle(r), dcc) div_yield_curve = ql.FlatForward(settlement, ql.QuoteHandle(q), dcc) vol_curve = ql.BlackConstantVol(today, ql.UnitedStates(ql.UnitedStates.NYSE), ql.QuoteHandle(vol), dcc) res = [] for i in range(len(parity)): # Instantiating the option exercise = ql.AmericanExercise(settlement, expiry) if parity[i] == 1: type = ql.Option.Call elif parity[i] == -1: type = ql.Option.Put payoff = ql.PlainVanillaPayoff(type, strike[i]) option = ql.VanillaOption(payoff, exercise) # Set up price process process = ql.BlackScholesMertonProcess( s0=ql.QuoteHandle(underlying), dividendTS=ql.YieldTermStructureHandle(div_yield_curve), riskFreeTS=ql.YieldTermStructureHandle(risk_free_curve), volTS=ql.BlackVolTermStructureHandle(vol_curve)) res.append(option.impliedVolatility(premium[i], process)) return res
def __init__(self, strike, effectivedt, maturitydt, optionType): self.strike = strike self.maturitydt = maturitydt self.optionType = optionType exercise = ql.AmericanExercise(effectivedt, maturitydt) payoff = ql.PlainVanillaPayoff(optionType, strike) option = ql.VanillaOption(payoff, exercise) #option = ql.EuropeanOption(payoff, exercise) self.option_ql = option # class OptionPlainAsian: # def __init__(self, strike,effectivedt, maturitydt, optionType): # self.strike = strike # self.maturitydt = maturitydt # self.optionType = optionType # exercise = ql.EuropeanExercise(maturitydt) # payoff = ql.PlainVanillaPayoff(optionType, strike) # option = ql.DiscreteAveragingAsianOption(payoff, exercise,) # self.option_ql = option
def calcAmericanOption(self, calculation_date_ql, maturity_date_ql, bsm_process, payoff_ql): # American option settlement = calculation_date_ql am_exercise_ql = ql.AmericanExercise(settlement, maturity_date_ql) steps = self.iterations if len(self.div_sched) == 0: american_option_ql = ql.VanillaOption(payoff_ql, am_exercise_ql) binomial_engine = ql.BinomialVanillaEngine(bsm_process, "crr", steps) american_option_ql.setPricingEngine(binomial_engine) else: div_sched_ql = [ql.Date(d.day, d.month, d.year) for d in self.div_sched] american_option_ql = ql.DividendVanillaOption(payoff_ql, am_exercise_ql, div_sched_ql, self.div_amounts) engine = ql.FDDividendAmericanEngine(bsm_process, steps, steps -1) american_option_ql.setPricingEngine(engine) print "American theoretical price is ", american_option_ql.NPV() print " -->Delta: ", american_option_ql.delta() print " -->Gamma: ", american_option_ql.gamma() return american_option_ql.NPV()
ql.MCEuropeanBasketEngine(process, "pseudorandom", timeStepsPerYear=1, requiredTolerance=0.02, seed=42) ) print(basketoption.NPV()) basketoption = ql.BasketOption(ql.MinBasketPayoff(payoff), exercise) basketoption.setPricingEngine( ql.MCEuropeanBasketEngine(process, "pseudorandom", timeStepsPerYear=1, requiredTolerance=0.02, seed=42) ) print(basketoption.NPV()) basketoption = ql.BasketOption(ql.AverageBasketPayoff(payoff, 2), exercise) basketoption.setPricingEngine( ql.MCEuropeanBasketEngine(process, "pseudorandom", timeStepsPerYear=1, requiredTolerance=0.02, seed=42) ) print(basketoption.NPV()) americanExercise = ql.AmericanExercise(settlementDate, ql.Date(17, ql.May, 1999)) americanbasketoption = ql.BasketOption(ql.MaxBasketPayoff(payoff), americanExercise) americanbasketoption.setPricingEngine( ql.MCAmericanBasketEngine( process, "pseudorandom", timeSteps=10, requiredTolerance=0.02, seed=42, polynomOrder=5, polynomType=ql.LsmBasisSystem.Hermite, ) ) print(americanbasketoption.NPV())
print('Volatility =', '{0:%}'.format(volatility)) print() # show table tab = pt.PrettyTable(['Method', 'European', 'Bermudan', 'American']) exerciseDates = ql.DateVector() for i in range(1, 5): exerciseDates.push_back(settlementDate + ql.Period(3 * i, ql.Months)) # exerciseDates = [settlementDate+ql.Period(3*i,ql.Months) for i in range(1,5)] europeanExercise = ql.EuropeanExercise(maturity) bermudanExercise = ql.BermudanExercise(exerciseDates) americanExercise = ql.AmericanExercise(settlementDate, maturity) underlyingH = ql.QuoteHandle(ql.SimpleQuote(underlying)) # bootstrap the yield/dividend/vol curves flatTermStructure = ql.YieldTermStructureHandle( ql.FlatForward(settlementDate, riskFreeRate, dayCounter)) flatDividendTS = ql.YieldTermStructureHandle( ql.FlatForward(settlementDate, dividendYield, dayCounter)) flatVolTS = ql.BlackVolTermStructureHandle( ql.BlackConstantVol( settlementDate, calendar, volatility, dayCounter)) payoff = ql.PlainVanillaPayoff(optType, strike) bsmProcess = ql.BlackScholesMertonProcess( underlyingH, flatDividendTS, flatTermStructure, flatVolTS) # options
def OptionCalc(options): print(options) spot = ql.SimpleQuote(options["spot"]) strike = options["strike"] volatility = ql.SimpleQuote(options["volatility"]) maturity = options["maturity"] rf = ql.SimpleQuote(options["rf"]) optionType = options["optionType"] pricingEngine = options["pricingEngine"] optionExercise = options["optionExercise"] if not hasattr(ql.Option, optionType): raise Exception("option type not understood") optionType = getattr(ql.Option, optionType) today = ql.Settings.instance().evaluationDate maturity_date = today + int(maturity) divYield = 0. rebate = 0. # process = ql.BlackScholesMertonProcess( # ql.QuoteHandle(spot), # ql.YieldTermStructureHandle(ql.FlatForward(today, divYield, day_count)), # ql.YieldTermStructureHandle(ql.FlatForward(today, ql.QuoteHandle(rf), day_count)), # ql.BlackVolTermStructureHandle(ql.BlackConstantVol(today, calendar, ql.QuoteHandle(volatility), day_count))) process = ql.BlackScholesProcess( ql.QuoteHandle(spot), ql.YieldTermStructureHandle( ql.FlatForward(today, ql.QuoteHandle(rf), day_count)), ql.BlackVolTermStructureHandle( ql.BlackConstantVol(today, calendar, ql.QuoteHandle(volatility), day_count))) if (optionExercise == "European"): optionExercise = ql.EuropeanExercise(maturity_date) elif (optionExercise == "American"): optionExercise = ql.AmericanExercise(today + 1, maturity_date) else: raise Exception("optionExercise not understood") if (pricingEngine == "Analytical"): pricingEngine = ql.AnalyticEuropeanEngine(process) elif (pricingEngine == "AnalyticalBinary"): pricingEngine = ql.AnalyticBinaryBarrierEngine(process) elif (pricingEngine == "FD"): pricingEngine = ql.FdBlackScholesBarrierEngine(process, timeSteps, gridPoints) elif (pricingEngine == "MC"): pricingEngine = ql.MCBarrierEngine(process, 'pseudorandom', timeSteps=1, requiredTolerance=0.02, seed=42) elif (pricingEngine == "Binomial"): pricingEngine = ql.BinomialBarrierEngine(process, 'jr', timeSteps) else: raise Exception("pricingEngine not understood") option = ql.VanillaOption(ql.PlainVanillaPayoff(optionType, strike), optionExercise) option.setPricingEngine(pricingEngine) results = {} for t in ["NPV", "delta", "vega", "theta", "rho", "gamma"]: try: results[t] = getattr(option, t)() except RuntimeError as e: print(t, e) results[t] = float('nan') if math.isnan(results["NPV"]): return results computegreeks(results, option, spot, volatility, rf, today) return results
# %% [markdown] # ### Global parameters # %% todaysDate = ql.Date(15, ql.May, 1998) ql.Settings.instance().evaluationDate = todaysDate # %% interactive = "get_ipython" in globals() # %% [markdown] # ### Option construction # %% exercise = ql.AmericanExercise(todaysDate, ql.Date(17, ql.May, 1999)) payoff = ql.PlainVanillaPayoff(ql.Option.Put, 40.0) # %% option = ql.VanillaOption(payoff, exercise) # %% [markdown] # ### Market data # %% underlying = ql.SimpleQuote(36.0) dividendYield = ql.FlatForward(todaysDate, 0.00, ql.Actual365Fixed()) volatility = ql.BlackConstantVol(todaysDate, ql.TARGET(), 0.20, ql.Actual365Fixed()) riskFreeRate = ql.FlatForward(todaysDate, 0.06, ql.Actual365Fixed()) # %%
def test_step_back(self): dt_eval = datetime.date(2017, 1, 1) dt_maturity = datetime.date(2017, 4, 1) spot_price = 120 strike_price = 120 volatility = 0.3 # the historical vols or implied vols dividend_rate = 0 risk_free_rate = 0.03 steps = self.size american_binomial_tree = BinomialTree(steps, dt_eval, dt_maturity, OptionType.PUT, OptionExerciseType.AMERICAN, spot_price, strike_price, volatility) american_binomial_tree.initialize() american_binomial_tree.step_back(0) print(american_binomial_tree.T) print("american binomial_tree price", american_binomial_tree.NPV()) european_binomial_tree = BinomialTree(steps, dt_eval, dt_maturity, OptionType.PUT, OptionExerciseType.EUROPEAN, spot_price, strike_price, volatility) european_binomial_tree.initialize() european_binomial_tree.step_back(0) print("european binomial_tree price", european_binomial_tree.NPV()) black = BlackCalculator(dt_eval, dt_maturity,strike_price,OptionType.PUT,spot_price,volatility) print("european blackcalculator price", black.NPV()) maturity_date = QuantlibUtil.to_ql_date(dt_maturity) option_type = ql.Option.Put day_count = ql.ActualActual() calendar = ql.NullCalendar() calculation_date = QuantlibUtil.to_ql_date(dt_eval) print(day_count.yearFraction(calculation_date,maturity_date)) ql.Settings.instance().evaluationDate = calculation_date payoff = ql.PlainVanillaPayoff(option_type, strike_price) settlement = calculation_date am_exercise = ql.AmericanExercise(settlement, maturity_date) american_option = ql.VanillaOption(payoff, am_exercise) 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(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) binomial_engine = ql.BinomialVanillaEngine(bsm_process, "crr", steps) black_engine = ql.AnalyticEuropeanEngine(bsm_process) american_option.setPricingEngine(binomial_engine) print("american quantlib price(BinomialVanillaEngine)", american_option.NPV()) european_option.setPricingEngine(binomial_engine) print("european quantlib price(BinomialVanillaEngine)", european_option.NPV()) european_option.setPricingEngine(black_engine) print("european quantlib price(blackcalculator)", european_option.NPV())
import QuantLib as ql # global data t = ql.Date(DD, ql.MM, YYYY) ql.Settings.instance().evaluationDate = t T = ql.Date(DD, ql.MM, YYYY) r = ql.FlatForward(T, 0.014, ql.Actual365Fixed()) # option parameters exercise = ql.AmericanExercise(T, ql.Date(DD, ql.MM, YYYY)) payoff = ql.PlainVanillaPayoff(ql.Option.Put, 40.0) # market data S = ql.SimpleQuote($S) v = ql.BlackConstantVol(t, ql.TARGET(), 0.20, ql.Actual365Fixed()) q = ql.FlatForward(T, 0.00, ql.Actual365Fixed()) # Results table header = "%19s" % "method" + " |" + " |".join(["%17s" % tag for tag in ["value", "estimated error", "actual error"]]) print("") print(header) print("-" * len(header)) refValue = None def report(method, x, dx=None): e = "%.4f" % abs(x - refValue) x = "%.5f" % x if dx: dx = "%.4f" % dx else:
def testAmericanOptionPricing(self): """Testing Black-Scholes and Heston American Option pricing""" xSteps = 100 tSteps = 25 dampingSteps = 0 todaysDate = ql.Date(15, ql.January, 2020) ql.Settings.instance().evaluationDate = todaysDate dc = ql.Actual365Fixed() riskFreeRate = ql.YieldTermStructureHandle( ql.FlatForward(todaysDate, 0.06, dc)) dividendYield = ql.YieldTermStructureHandle( ql.FlatForward(todaysDate, 0.02, dc)) strike = 110.0 payoff = ql.PlainVanillaPayoff(ql.Option.Put, strike) maturityDate = todaysDate + ql.Period(1, ql.Years) maturity = dc.yearFraction(todaysDate, maturityDate) exercise = ql.AmericanExercise(todaysDate, maturityDate) spot = ql.QuoteHandle(ql.SimpleQuote(100.0)) volatility = ql.BlackConstantVol(todaysDate, ql.TARGET(), 0.20, dc) process = ql.BlackScholesMertonProcess( spot, dividendYield, riskFreeRate, ql.BlackVolTermStructureHandle(volatility)) option = ql.VanillaOption(payoff, exercise) option.setPricingEngine( ql.FdBlackScholesVanillaEngine.make(process, xGrid=xSteps, tGrid=tSteps, dampingSteps=dampingSteps)) expected = option.NPV() equityMesher = ql.FdmBlackScholesMesher(xSteps, process, maturity, strike, cPoint=(strike, 0.1)) mesher = ql.FdmMesherComposite(equityMesher) op = ql.FdmBlackScholesOp(mesher, process, strike) innerValueCalculator = ql.FdmLogInnerValue(payoff, mesher, 0) x = [] rhs = [] layout = mesher.layout() opIter = layout.begin() while (opIter.notEqual(layout.end())): x.append(mesher.location(opIter, 0)) rhs.append(innerValueCalculator.avgInnerValue(opIter, maturity)) opIter.increment() rhs = ql.Array(rhs) bcSet = ql.FdmBoundaryConditionSet() stepCondition = ql.FdmStepConditionComposite.vanillaComposite( ql.DividendSchedule(), exercise, mesher, innerValueCalculator, todaysDate, dc) # only to test an Operator defined in python class OperatorProxy: def __init__(self, op): self.op = op def size(self): return self.op.size() def setTime(self, t1, t2): return self.op.setTime(t1, t2) def apply(self, r): return self.op.apply(r) def apply_direction(self, i, r): return self.op.apply_direction(i, r) def solve_splitting(self, i, r, s): return self.op.solve_splitting(i, r, s) proxyOp = ql.FdmLinearOpCompositeProxy(OperatorProxy(op)) solver = ql.FdmBackwardSolver(proxyOp, bcSet, stepCondition, ql.FdmSchemeDesc.Douglas()) solver.rollback(rhs, maturity, 0.0, tSteps, dampingSteps) spline = ql.CubicNaturalSpline(x, rhs) logS = math.log(spot.value()) calculated = spline(logS) self.assertAlmostEqual(calculated, expected, 1) solverDesc = ql.FdmSolverDesc(mesher, bcSet, stepCondition, innerValueCalculator, maturity, tSteps, dampingSteps) calculated = ql.Fdm1DimSolver(solverDesc, ql.FdmSchemeDesc.Douglas(), op).interpolateAt(logS) self.assertAlmostEqual(calculated, expected, 2) v0 = 0.4 * 0.4 kappa = 1.0 theta = v0 sigma = 1e-4 rho = 0.0 hestonProcess = ql.HestonProcess(riskFreeRate, dividendYield, spot, v0, kappa, theta, sigma, rho) leverageFct = ql.LocalVolSurface( ql.BlackVolTermStructureHandle( ql.BlackConstantVol(todaysDate, ql.TARGET(), 0.50, dc)), riskFreeRate, dividendYield, spot.value()) vSteps = 3 vMesher = ql.FdmHestonLocalVolatilityVarianceMesher( vSteps, hestonProcess, leverageFct, maturity) avgVolaEstimate = vMesher.volaEstimate() self.assertAlmostEqual(avgVolaEstimate, 0.2, 5) mesher = ql.FdmMesherComposite(equityMesher, vMesher) innerValueCalculator = ql.FdmLogInnerValue(payoff, mesher, 0) stepCondition = ql.FdmStepConditionComposite.vanillaComposite( ql.DividendSchedule(), exercise, mesher, innerValueCalculator, todaysDate, dc) solverDesc = ql.FdmSolverDesc(mesher, bcSet, stepCondition, innerValueCalculator, maturity, tSteps, dampingSteps) calculated = ql.FdmHestonSolver(hestonProcess, solverDesc, leverageFct=leverageFct).valueAt( spot.value(), 0.16) self.assertAlmostEqual(calculated, expected, 1)
def get_option_greeks(**kwargs): # risk_free_rate and volatility in whole points not percentage points # for example enter 0.02 for 2 percent interest rate # enter 0.25 for 25 percent annual volatility underlying = kwargs['underlying'] strike = kwargs['strike'] risk_free_rate = kwargs['risk_free_rate'] expiration_date = kwargs['expiration_date'] calculation_date = kwargs['calculation_date'] option_type = kwargs['option_type'].upper() exercise_type = kwargs['exercise_type'].upper() dividend_rate = 0 expiration_datetime = cu.convert_doubledate_2datetime(expiration_date) calculation_datetime = cu.convert_doubledate_2datetime(calculation_date) expiration_date_obj = ql.Date(expiration_datetime.day, expiration_datetime.month, expiration_datetime.year) calculation_date_obj = ql.Date(calculation_datetime.day, calculation_datetime.month, calculation_datetime.year) cal_dte = day_count_obj.dayCount(calculation_date_obj, expiration_date_obj) nan_greeks = {'option_price': np.NaN, 'implied_vol': np.NaN, 'delta': np.NaN, 'vega': np.NaN, 'theta': np.NaN, 'cal_dte': cal_dte, 'gamma': np.NaN} if 'option_price' in kwargs.keys(): if option_type == 'C': if kwargs['option_price']+strike-underlying <= 10**(-12): nan_greeks['delta'] = 1 return nan_greeks elif option_type == 'P': if kwargs['option_price']-strike+underlying <= 10**(-12): nan_greeks['delta'] = -1 return nan_greeks if cal_dte == 0: if option_type == 'C': if strike <= underlying: nan_greeks['delta'] = 1 else: nan_greeks['delta'] = 0 elif option_type == 'P': if strike >= underlying: nan_greeks['delta'] = -1 else: nan_greeks['delta'] = 0 return nan_greeks if 'implied_vol' in kwargs.keys(): implied_vol = kwargs['implied_vol'] else: implied_vol = 0.15 if 'engine_name' in kwargs.keys(): engine_name = kwargs['engine_name'] else: engine_name = 'baw' if option_type == 'C': option_type_obj = ql.Option.Call elif option_type == 'P': option_type_obj = ql.Option.Put ql.Settings.instance().evaluationDate = calculation_date_obj if exercise_type == 'E': exercise_obj = ql.EuropeanExercise(expiration_date_obj) elif exercise_type == 'A': exercise_obj = ql.AmericanExercise(calculation_date_obj, expiration_date_obj) #print('years to expitation: ' + str(day_count_obj.yearFraction(calculation_date_obj, expiration_date_obj))) #print('spot: ' + str(underlying/m.exp(day_count_obj.yearFraction(calculation_date_obj, expiration_date_obj)*risk_free_rate))) #underlying_obj = ql.QuoteHandle(ql.SimpleQuote(underlying/m.exp(day_count_obj.yearFraction(calculation_date_obj, expiration_date_obj)*risk_free_rate))) underlying_obj = ql.QuoteHandle(ql.SimpleQuote(underlying)) flat_ts_obj = ql.YieldTermStructureHandle(ql.FlatForward(calculation_date_obj, risk_free_rate, day_count_obj)) dividend_yield_obj = ql.YieldTermStructureHandle(ql.FlatForward(calculation_date_obj, dividend_rate, day_count_obj)) flat_vol_ts_obj = ql.BlackVolTermStructureHandle(ql.BlackConstantVol(calculation_date_obj, calendar_obj, implied_vol, day_count_obj)) #bsm_process = ql.BlackScholesMertonProcess(underlying_obj, dividend_yield_obj, flat_ts_obj, flat_vol_ts_obj) bsm_process = ql.BlackProcess(underlying_obj, flat_ts_obj, flat_vol_ts_obj) payoff = ql.PlainVanillaPayoff(option_type_obj, strike) option_obj = ql.VanillaOption(payoff, exercise_obj) if (engine_name == 'baw')&(exercise_type == 'A'): option_obj.setPricingEngine(ql.BaroneAdesiWhaleyEngine(bsm_process)) elif (engine_name == 'fda')&(exercise_type == 'A'): option_obj.setPricingEngine(ql.FDAmericanEngine(bsm_process, 100, 100)) elif exercise_type == 'E': option_obj.setPricingEngine(ql.AnalyticEuropeanEngine(bsm_process)) option_price = option_obj.NPV() if 'option_price' in kwargs.keys(): try: implied_vol = option_obj.impliedVolatility(targetValue=kwargs['option_price'], process=bsm_process,accuracy=0.00001) flat_vol_ts_obj = ql.BlackVolTermStructureHandle(ql.BlackConstantVol(calculation_date_obj, calendar_obj, implied_vol, day_count_obj)) #bsm_process = ql.BlackScholesMertonProcess(underlying_obj, dividend_yield_obj, flat_ts_obj, flat_vol_ts_obj) bsm_process = ql.BlackProcess(underlying_obj, flat_ts_obj, flat_vol_ts_obj) if (engine_name == 'baw')&(exercise_type == 'A'): option_obj.setPricingEngine(ql.BaroneAdesiWhaleyEngine(bsm_process)) elif (engine_name == 'fda')&(exercise_type == 'A'): option_obj.setPricingEngine(ql.FDAmericanEngine(bsm_process, 100, 100)) elif exercise_type == 'E': option_obj.setPricingEngine(ql.AnalyticEuropeanEngine(bsm_process)) option_price = option_obj.NPV() except Exception: return nan_greeks option_obj = ql.VanillaOption(payoff, ql.EuropeanExercise(expiration_date_obj)) option_obj.setPricingEngine(ql.AnalyticEuropeanEngine(bsm_process)) return {'option_price': option_price, 'implied_vol': implied_vol, 'delta': option_obj.delta(), 'vega': option_obj.vega(), 'theta': option_obj.thetaPerDay(), 'cal_dte': cal_dte, 'gamma': option_obj.gamma()}
spot_price = 127.62 strike_price = 130 volatility = 0.20 # the historical vols or implied vols dividend_rate = 0.0163 option_type = ql.Option.Call risk_free_rate = 0.001 day_count = ql.Actual365Fixed() calendar = ql.UnitedStates() calculation_date = ql.Date(8, 5, 2015) ql.Settings.instance().evaluationDate = calculation_date payoff = ql.PlainVanillaPayoff(option_type, strike_price) settlement = calculation_date am_exercise = ql.AmericanExercise(settlement, maturity_date) american_option = ql.VanillaOption(payoff, am_exercise) 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(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)
dividends.push_back( ql.FixedDividend(1.0, d)) d += ql.Period(6, ql.Months) dayCounter = ql.Actual365Fixed() maturity = dayCounter.yearFraction(settlementDate, exerciseDate) print("option type =", optType) print("Time to maturity =", format(maturity, '.6')) print("Underlying price =", underlying) print("Risk-free interest rate =", format(riskFreeRate, '%')) print("Dividend yield =", format(dividendYield, '%')) print("Volatility =", format(volatility, '%')) exercise = ql.EuropeanExercise(exerciseDate) amExercise = ql.AmericanExercise(settlementDate, exerciseDate) underlyingH = ql.QuoteHandle( ql.SimpleQuote(underlying)) flatTermStructure = ql.YieldTermStructureHandle( ql.FlatForward(settlementDate, riskFreeRate, dayCounter)) flatDividendTS = ql.YieldTermStructureHandle( ql.FlatForward(settlementDate, dividendYield, dayCounter)) flatVolTS = ql.BlackVolTermStructureHandle( ql.BlackConstantVol(settlementDate, calendar, volatility, dayCounter)) stochasticProcess = ql.BlackScholesMertonProcess( underlyingH, flatDividendTS, flatTermStructure, flatVolTS) timeSteps = 801 creditSpread = ql.QuoteHandle(ql.SimpleQuote(spreadRate)) rate = ql.SimpleQuote(riskFreeRate)
maturity_date = ql.Date(18, 1, 2019) spot_price = 155 strike_price = 155 volatility = 0.20 # the historical vols for a year dividend_rate = 0.0 option_type = ql.Option.Call risk_free_rate = 0.02 day_count = ql.Actual365Fixed() calendar = ql.UnitedStates() calculation_date = ql.Date(10, 1, 2019) ql.Settings.instance().evaluationDate = calculation_date payoff = ql.PlainVanillaPayoff(option_type, strike_price) exercise = ql.AmericanExercise(calculation_date, maturity_date) american_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) #european_option.setPricingEngine(ql.AnalyticEuropeanEngine(bsm_process)) #bs_price = european_option.NPV() #print ("The theoretical price is ", bs_price)