def calc_σ(self, V): try: self.__verify(V) except ValueError: return np.NaN σ = self.__σinit n = 0 σdiff = 1 while σdiff >= self.__tol and n < self.__nmax: bs = BlackScholes(self.__S, self.__K, self.__r, self.__T, σ, self.__t, self.__q) c = bs.call() if self.__type == 'C' else bs.put() if c == V: return σ vega = self.__vega(bs.get_d1()) if vega == 0: return np.NaN increment = (c - V) / vega σ -= increment n += 1 σdiff = abs(increment) return σ
def test_vanilla_call_option(self): ''' Q: (Vanilla option) A European call option, 3 month to expiry, stock price is 60, the strike price is 65, risk free interest rate is 8% per year, volatility is 30% per year A: 2.1334 ''' bsm = BlackScholes('stock_option', 60, 65, 0.08, 0.25, 0.3) self.assertEqual(2.1334, bsm.get_option_price(OptionType.CALL))
def test_options_on_futures(self): ''' Q: (Options on Futures) A European option on futures, 9 month to expiry, future price is 19, the strike price is 19, risk free interest rate is 10% per year, volatility is 28% per year A: c = p = 1.7011 ''' bsm = BlackScholes('futures_option', 19, 19, 0.1, 0.75, 0.28, 0.1) self.assertEqual(1.7011, bsm.get_option_price(OptionType.CALL)) self.assertEqual(1.7011, bsm.get_option_price(OptionType.PUT))
def get_price(self, otype=OptionType.CALL, product='stock_option', spot=60, strike=65, rate=0.08, expiry=0.25, vol=0.3): ''' Q: (Vanilla option) A European call option, 3 month to expiry, stock price is 60, the strike price is 65, risk free interest rate is 8% per year, volatility is 30% per year A: 2.1334 ''' bsm = BlackScholes(product, spot, strike, rate, expiry, vol) return bsm.get_option_price(otype)
def test_compare_binomial_tree(self): ''' European put option, 2 years to expiry, spot price 50, strike price 52, risk free rate 5%, volatility 30% The result from binomial trees with steps == 10 : 6.747 100: 6.7781 500: 6.7569 ''' bsm = BlackScholes('stock_option', 50, 52, 0.05, 2, 0.3) self.assertEqual(6.7601, bsm.get_option_price(OptionType.PUT))
def test_vanilla_option_with_dividend(self): ''' Q: (Vanilla option with yield) A European put option, 6 month to expiry, stock price is 100, the strike price is 95, risk free interest rate is 10% per year, the dividend is 5% per year, volatility is 20% per year A: 2.4648 ''' bsm = BlackScholes('stock_option_with_dividend', 100, 95, 0.1, 0.5, 0.2, 0.05) self.assertEqual(2.4648, bsm.get_option_price(OptionType.PUT))
def test_options_on_FX(self): ''' Q: (Options on FX) A European USD-call/EUR-put option, 6 month to expiry, USD/EUR exchange rate is 1.56, the strike strike rate is 1.6, the domestic risk free interest rate in EUR is 8% per year, the foreign risk-free interest rate in USD is 6%, volatility is 12% per year A: c = 0.0291 ''' bsm1 = BlackScholes('currency_option', 1.56, 1.6, 0.06, 0.5, 0.12, 0.08) self.assertEqual(0.0291, bsm1.get_option_price(OptionType.CALL)) bsm2 = BlackScholes('currency_option', 1/1.56, 1/1.6, 0.08, 0.5, 0.12, 0.06) self.assertEqual(0.0117, bsm2.get_option_price(OptionType.PUT))
def test_bs(self): """ The actual test. Any method which starts with ``test_`` will considered as a test case. """ res = BlackScholes(100, 0.10, 0.5, 1.00) self.assertEqual(round(res, 2), 23.93)
def test_delta_greeks2(self): ''' Q: A commodity option with two years to expiration. The commodity price is 90, the strike price is 40, the risk-free interest rate is 3% per year, the cost-of-carry is 9% per year, and the volatility is 20%. What's the delta of a call option? A: delta_call = 1.1273 This implies that the call option price will increase/decrease 1.1273 USD if the spot price increase/decrease by 1 USD ''' bsg = BlackScholesGreeks(None, 90, 40, 0.03, 2, 0.2, cost_of_carry=0.09) self.assertEqual(1.1273, bsg.get_delta_greeks(OptionType.CALL)) # For every 1 dollar increase/decrease of the spot price, the option price increase/decrease 1.1273 opt_price = BlackScholes(None, 90, 40, 0.03, 2, 0.2, cost_of_carry=0.09).get_option_price( OptionType.CALL) self.assertAlmostEqual( opt_price + 1.1273, BlackScholes(None, 91, 40, 0.03, 2, 0.2, cost_of_carry=0.09).get_option_price(OptionType.CALL), 3) self.assertEqual( round(opt_price - 1.1273, 4), BlackScholes(None, 89, 40, 0.03, 2, 0.2, cost_of_carry=0.09).get_option_price(OptionType.CALL))
def blackScholes(): data = request.json strike = float(data['strike']) stockPrice = float(data['stockPrice']) volatility = float(data['volatility']) / 100 interestRate = float(data['interestRate']) / 100 repoRate = float(data['repoRate']) / 100 optionType = data['optionType'] time = float(data['time']) blackScholes = BlackScholes(S=stockPrice, K=strike, r=interestRate, T=time, σ=volatility, q=repoRate) if (optionType == 'call'): return str(round(blackScholes.call(), 2)) else: return str(round(blackScholes.put(), 2))
def barrier_downandout(self, barrier): sum = 0 bsm = BlackScholes(self.__S, self.__K, self.__r, self.__Δ, self.__σ) for j in range(0, self.__m): sT = self.__S out = False for i in range(0, int(self.__n)): z = np.random.normal() sT *= np.exp((self.__r - 0.5 * self.__σ * self.__σ) * self.__dt + self.__σ * z * np.sqrt(self.__dt)) if sT < barrier: out = True if self.__option_type == 'call': if not out: sum += bsm.call() if self.__option_type == 'put': if not out: sum += bsm.put() return sum / self.__m
def barrier_upandin(self, barrier): sum = 0 np.random.seed(51) bsm = BlackScholes(self.__S, self.__K, self.__r, self.__Δ, self.__σ) for j in range(0, self.__m): sT = self.__S inop = False for i in range(0, int(self.__n)): z = np.random.normal() sT *= np.exp((self.__r - 0.5 * self.__σ * self.__σ) * self.__dt + self.__σ * z * np.sqrt(self.__dt)) if sT > barrier: inop = True if self.__option_type == 'call': if inop == True: sum += bsm.call() if self.__option_type == 'put': if inop == True: sum += bsm.put() return sum / self.__m
def test_options_on_FX(self): ''' Q: (Options on FX) A European USD-call/EUR-put option, 6 month to expiry, USD/EUR exchange rate is 1.56, the strike strike rate is 1.6, the domestic risk free interest rate in EUR is 8% per year, the foreign risk-free interest rate in USD is 6%, volatility is 12% per year A: c = 0.0291 ''' bsm1 = BlackScholes('currency_option', 1.56, 1.6, 0.06, 0.5, 0.12, 0.08) self.assertEqual(0.0291, bsm1.get_option_price(OptionType.CALL)) bsm2 = BlackScholes('currency_option', 1 / 1.56, 1 / 1.6, 0.08, 0.5, 0.12, 0.06) self.assertEqual(0.0117, bsm2.get_option_price(OptionType.PUT))
# neworder.checked(False) # uncomment to disable checks # requires 4 identical sims with perturbations to compute market sensitivities # (a.k.a. Greeks) assert neworder.mpi.size() == 4, "This example requires 4 processes" # initialisation # market data market = { "spot": 100.0, # underlying spot price "rate": 0.02, # risk-free interest rate "divy": 0.01, # (continuous) dividend yield "vol": 0.2 # stock volatility } # (European) option instrument data option = { "callput": "CALL", "strike": 100.0, "expiry": 0.75 # years } # model parameters nsims = 1000000 # number of underlyings to simulate # instantiate model bs_mc = BlackScholes(option, market, nsims) # run model neworder.run(bs_mc)
from option import Binomial from black_scholes import BlackScholes # choose inputs for Binomial or B-S methods bin_option = Binomial( 100, 102, 0.01, 0.5, 200, { 'tk': 'AAPL', 'is_calc': True, 'is_call': True, 'use_garch': True, 'start_date': '2018-01-01', 'end_date': '2018-06-28', 'american': False }) bs_option = BlackScholes( 100, 102, 0.01, 0.5, 10, { 'tk': 'AAPL', 'is_calc': True, 'is_call': True, 'use_garch': True, 'start_date': '2018-01-01', 'end_date': '2018-06-28', 'american': False }) print(bin_option.price()) print(bs_option.black_scholes())
def bs_price_option(strike, stock_price, expiration_date, side): days = datetime_to_days(expiration_date) bsm = BlackScholes(strike, stock_price, volatility, rfir, days) if side: return bsm.calculate_call_option() return bsm.calculate_put_option()