Example #1
0
    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)
)
Example #3
0
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