def __init__(self, btype): # global data self.todaysDate = ql.Date(15, ql.May, 1998) ql.Settings.instance().evaluationDate = self.todaysDate self.settlementDate = ql.Date(17, ql.May, 1998) self.riskFreeQuote = ql.SimpleQuote(0.05) self.riskFreeRate = ql.FlatForward(self.settlementDate, ql.QuoteHandle(self.riskFreeQuote), ql.Actual365Fixed()) # option parameters self.exercise = ql.EuropeanExercise(ql.Date(17, ql.May, 1999)) self.payoff = ql.PlainVanillaPayoff(ql.Option.Call, 8.0) # market data self.underlying1 = ql.SimpleQuote(10.0) self.volatility1 = ql.BlackConstantVol(self.todaysDate, 0.20, ql.Actual365Fixed()) self.dividendYield1 = ql.FlatForward(self.settlementDate, 0.05, ql.Actual365Fixed()) self.underlying2 = ql.SimpleQuote(7.0) self.volatility2 = ql.BlackConstantVol(self.todaysDate, 0.10, ql.Actual365Fixed()) self.dividendYield2 = ql.FlatForward(self.settlementDate, 0.05, ql.Actual365Fixed()) self.process1 = ql.BlackScholesMertonProcess( ql.QuoteHandle(self.underlying1), ql.YieldTermStructureHandle(self.dividendYield1), ql.YieldTermStructureHandle(self.riskFreeRate), ql.BlackVolTermStructureHandle(self.volatility1), ) self.process2 = ql.BlackScholesMertonProcess( ql.QuoteHandle(self.underlying2), ql.YieldTermStructureHandle(self.dividendYield2), ql.YieldTermStructureHandle(self.riskFreeRate), ql.BlackVolTermStructureHandle(self.volatility2), ) self.procs = ql.StochasticProcessVector() self.procs.push_back(self.process1) self.procs.push_back(self.process2) self.matrix = ql.Matrix(2, 2) self.matrix[0][0] = 1.0 self.matrix[1][1] = 1.0 self.matrix[0][1] = 0.25 self.matrix[1][0] = 0.25 self.process = ql.StochasticProcessArray(self.procs, self.matrix) self.engine = ql.MCBasketEngine("lowdiscrepancy", timeStepsPerYear=1, requiredTolerance=0.02, seed=42) if btype == "min": bpayoff = ql.MinBasketPayoff(self.payoff) elif btype == "max": bpayoff = ql.MaxBasketPayoff(self.payoff) else: bpayoff = ql.AverageBasketPayoff(self.payoff, 2) self.option = ql.BasketOption(self.process, bpayoff, self.exercise, self.engine)
process2 = ql.BlackScholesMertonProcess( ql.QuoteHandle(underlying2), ql.YieldTermStructureHandle(dividendYield2), ql.YieldTermStructureHandle(riskFreeRate), ql.BlackVolTermStructureHandle(volatility2), ) matrix = ql.Matrix(2, 2) matrix[0][0] = 1.0 matrix[1][1] = 1.0 matrix[0][1] = 0.5 matrix[1][0] = 0.5 process = ql.StochasticProcessArray([process1, process2], matrix) basketoption = ql.BasketOption(ql.MaxBasketPayoff(payoff), exercise) basketoption.setPricingEngine( 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) )
def valueBasketCall(val_date, settle_date, maturity_days, tmp_stock, tmp_vol, tmp_corr, rf_rate=0.0, strike=100.0, dividend=0.0, basketCallType='Min', randMethod="pseudorandom", _timeStepsPerYear=1, _requiredTolerance=0.02, _seed=42): tic = time.time() # Input Checks no_stock = len(tmp_stock) theo_no_corr = no_stock * (no_stock - 1) /2 if len(tmp_corr) != theo_no_corr: print('Number of stocks (%d) and number of correlations (%d) do not match! Should be %d ' % (no_stock, len(tmp_corr), theo_no_corr)) return 0.0 if basketCallType not in ["Min","Max","Average"]: print('Unsupported basket Call type %s, only ["Min","Max","Average"] are supported.' % basketCallType) return 0.0 # Set dates day_count = ql.Actual365Fixed() py_val_date = datetime.strptime(val_date, '%Y-%m-%d') ql_val_date = ql.Date(py_val_date.day, py_val_date.month, py_val_date.year) py_settle_date = datetime.strptime(settle_date, '%Y-%m-%d') ql_settle_date = ql.Date(py_settle_date.day, py_settle_date.month, py_settle_date.year) py_maturity_date = py_val_date + timedelta(days=int(maturity_days)) ql_maturity_date = ql.Date(py_maturity_date.day, py_maturity_date.month, py_maturity_date.year) # Set QL instance ql.Settings.instance().evaluationDate = ql_val_date # Create exercise object exercise = ql.EuropeanExercise(ql_maturity_date) # Create Payoff Object payoff = ql.PlainVanillaPayoff(ql.Option.Call, strike) # Create risk free rate object riskFreeRate = ql.FlatForward(ql_settle_date, rf_rate, day_count) # Create list of equity parameters ql_underlying_list = [ql.SimpleQuote(i) for i in tmp_stock] ql_vol_list = [ql.BlackConstantVol(ql_val_date, ql.TARGET(), i, day_count) for i in tmp_vol] ql_div_list = [ql.FlatForward(ql_settle_date, dividend, day_count) for i in tmp_stock] # Populate Correlation Matrix matrix = populateCorrMatrix(tmp_corr, no_stock) # Create list of QL processes for equity ql_process_list =[ql.BlackScholesMertonProcess( ql.QuoteHandle(ql_underlying_list[i]), ql.YieldTermStructureHandle(ql_div_list[i]), ql.YieldTermStructureHandle(riskFreeRate), ql.BlackVolTermStructureHandle(ql_vol_list[i]),) for i in range(len(ql_underlying_list))] if no_stock == 1: # Use Black Scholes Formula to calculate European Call #print("Single stock, use BS Formula!") option = ql.VanillaOption(payoff, exercise) bsm_process = ql_process_list[0] option.setPricingEngine(ql.AnalyticEuropeanEngine(bsm_process)) else: # Create QL Multi-variate Stochastic Process process = ql.StochasticProcessArray(ql_process_list, matrix) # Create Basket Option Object if basketCallType == "Min": option = ql.BasketOption(ql.MinBasketPayoff(payoff), exercise) elif basketCallType == "Max": option = ql.BasketOption(ql.MaxBasketPayoff(payoff), exercise) elif basketCallType == "Average": option = ql.BasketOption(ql.AverageBasketPayoff(payoff), exercise) # Set Pricing Engine option.setPricingEngine(ql.MCEuropeanBasketEngine(process, randMethod, timeStepsPerYear=_timeStepsPerYear, requiredTolerance=_requiredTolerance, seed=_seed) ) p = option.NPV() #p=0 toc = time.time() #print(p, maturity_days, toc-tic) return p