def SABR_vega(f, t, k, alpha, beta, rho, volvol): b_s = BlackScholes(f, 0, 0, t) atm_vol = ATM_vol(f, t, alpha, beta, rho, volvol) strike_vol = 100 * lognormal_vol(k, f, t, alpha, beta, rho, volvol) bs_vega = b_s.BS_vega(k, strike_vol) vega = bs_vega * strike_vol / atm_vol return vega
def calculate_price(underlying, mtr, ATM_vol, K, K1, K2, K3, mkt_price_K1, mkt_price_K3): weight_list = calculate_weight(underlying, mtr, ATM_vol, K, K1, K2, K3) b_s = BlackScholes(underlying, 0, 0, mtr) BS_price_K = b_s.BS_call(K, ATM_vol) BS_price_K1 = b_s.BS_call(K1, ATM_vol) BS_price_K3 = b_s.BS_call(K3, ATM_vol) price = BS_price_K + weight_list[0] * (mkt_price_K1 - BS_price_K1) + weight_list[2] * (mkt_price_K3 - BS_price_K3) return price
def SABR_delta_2(f, t, k, CallPut, alpha, beta, rho, volvol): f2 = f * 1.01 b_s = BlackScholes(f, 0, 0, t) SABR_vol = lognormal_vol(k, f, t, alpha, beta, rho, volvol) * 100 SABR_vol_shift = lognormal_vol(k, f2, t, alpha, beta, rho, volvol) * 100 bs_delta = b_s.BS_delta(k, SABR_vol, CallPut) bs_vega = b_s.BS_vega(k, SABR_vol) delta = bs_delta + bs_vega * (SABR_vol_shift - SABR_vol) / (f2 - f) return delta
def warrants(app, tickers, warrants_out): if tickers is None: print('Error: Must provide ticker for warrant valuation') return if warrants_out is None: print('Number of warrants outstanding was not provided. Will not calculate with share dilution.') # Take user input for vol? vols = [.2, .3, .35, .4, .5, .6] data = {'Volatility': vols} ticker_data, issue_tickers = getPriceData(app, tickers) fund_ticker_data, data_issue_tickers = getFundamentalData(app, tickers) for key, val in ticker_data.items(): # Find the warrant contract_details = app.getContractDetails( key, "WAR", exchange='SMART', currency='USD') underlying_price = float(val) # Get dividend yield contract = app.createContract(key, "STK", "USD", "SMART", "ISLAND") div = app.getYield(contract) # Find share count from financials qtr1 = app.parseFinancials(fund_ticker_data[key], quarterly=True)[0] shares_out = qtr1['total_common_shares_outstanding'] for c in contract_details: contract = c.contract strike = contract.strike # right = contract.right warrants_per_share = (1/float(contract.multiplier)) expiry = datetime.datetime.strptime( contract.lastTradeDateOrContractMonth, '%Y%m%d').strftime('%m-%d-%Y') # TODO: Get this from t-bill near expiry date? risk = .03 prices = [] for vol in vols: bs = BlackScholes(strike, underlying_price, risk, vol, expiry, div, shares_out, warrants_out, warrants_per_share) prices.append('$' + str(round(bs.price_euro_call(), 5))) header = ('%s %s' % (str(strike), expiry)) data[header] = prices df = pandas.DataFrame(data=data) print(df) print('Tickers missing price data: (%s)' % len(issue_tickers)) print(issue_tickers) print('Tickers missing fundamental data: (%s)' % len(data_issue_tickers)) print(data_issue_tickers)
def calculate_weight(underlying, mtr, ATM_vol, K, K1, K2, K3): b_s = BlackScholes(underlying, 0, 0, mtr) vega_K = b_s.BS_vega(K, ATM_vol) vega_K_1 = b_s.BS_vega(K1, ATM_vol) vega_K_2 = b_s.BS_vega(K2, ATM_vol) vega_K_3 = b_s.BS_vega(K3, ATM_vol) weight_1 = (vega_K * np.log(K2 / K) * np.log(K3 / K)) / (vega_K_1 * np.log(K2 / K1) * np.log(K3 / K1)) weight_2 = (vega_K * np.log(K / K1) * np.log(K3 / K)) / (vega_K_2 * np.log(K2 / K1) * np.log(K3 / K2)) weight_3 = (vega_K * np.log(K / K1) * np.log(K / K2)) / (vega_K_3 * np.log(K3 / K1) * np.log(K3 / K2)) return [weight_1, weight_2, weight_3]
def BS_max_gamma(underlying, underlying_change, mtr, strike, vol): if underlying_change < 0: underlying_list = np.arange(underlying + underlying_change, underlying + 1, 1) else: underlying_list = np.arange(underlying, underlying + underlying_change + 1, 1) max_result = 0 for st in underlying_list: b_s = BlackScholes(st, 0, 0, mtr) deri = b_s.BS_gamma_deri(strike, vol) if abs(deri) > max_result: max_result = abs(deri) return max_result
def get_iv(row, bidorask): b_s = BlackScholes(row['underlying_price'], interest_rate, dividend, ttm) if bidorask == 'bid': iv = b_s.BS_impliedVol(row['Strike'], row['m_bid'] * row['underlying_price'], row['CallPut']) elif bidorask == 'ask': iv = b_s.BS_impliedVol(row['Strike'], row['m_ask'] * row['underlying_price'], row['CallPut']) else: iv = b_s.BS_impliedVol(row['Strike'], row['m_mid'] * row['underlying_price'], row['CallPut']) return iv
def SABR_delta_3(f, t, k, CallPut, alpha, beta, rho, volvol): f2 = f * 1.01 b_s = BlackScholes(f, 0, 0, t) SABR_vol = lognormal_vol(k, f, t, alpha, beta, rho, volvol) * 100 SABR_vol_shift = lognormal_vol(k, f2, t, alpha, beta, rho, volvol) * 100 bs_delta = b_s.BS_delta(k, SABR_vol, CallPut) bs_vega = b_s.BS_vega(k, SABR_vol) SABR_vol_alpha_shift = lognormal_vol(k, f, t, alpha * 1.01, beta, rho, volvol) * 100 alpha_deri = (SABR_vol - SABR_vol_alpha_shift) / (alpha - 1.01 * alpha) delta = bs_delta + bs_vega * ((SABR_vol_shift - SABR_vol) / (f2 - f) + alpha_deri * (rho * volvol / (f**beta))) return delta
def get_greeks(row, greek): b_s = BlackScholes(row['underlying_price'], 0, 0, row['mtr']) if greek == 'gamma': result = b_s.BS_gamma(row['Strike'], row['m_mid_vol']) elif greek == 'theta': result = b_s.BS_theta(row['Strike'], row['m_mid_vol'], row['CallPut']) elif greek == 'vega': result = b_s.BS_vega(row['Strike'], row['m_mid_vol']) elif greek == 'delta': result = b_s.BS_delta(row['Strike'], row['m_mid_vol'], row['CallPut']) elif greek == 'vanna': result = b_s.BS_vanna(row['Strike'], row['m_mid_vol']) elif greek == 'volga': result = b_s.BS_volga(row['Strike'], row['m_mid_vol']) elif greek == 'gamma_deri': result = b_s.BS_gamma_deri(row['Strike'], row['m_mid_vol']) return result
def SABR_beta_d(f, t, k, CallPut, alpha, beta, rho, volvol): vol_1 = lognormal_vol(k, f, t, alpha, beta, rho, volvol) * 100 vol_2 = lognormal_vol(k, f, t, alpha, beta + 0.01, rho, volvol) * 100 b_s = BlackScholes(f, 0, 0, t) if CallPut == 'C': vanna = (b_s.BS_call(k, vol_2) - b_s.BS_call(k, vol_1)) / (0.01 * rho) else: vanna = (b_s.BS_put(k, vol_2) - b_s.BS_put(k, vol_1)) / (0.01 * rho) return vanna
def SABR_delta(f, t, k, CallPut, alpha, beta, rho, volvol): f2 = f * 1.01 b_s = BlackScholes(f * 1.01, 0, 0, t) b_s_2 = BlackScholes(f * 0.99, 0, 0, t) if CallPut == 'C': delta_i = (b_s.BS_call( k, 100 * lognormal_vol(k, f * 1.01, t, alpha, beta, rho, volvol)) - b_s_2.BS_call( k, 100 * lognormal_vol(k, f * 0.99, t, alpha, beta, rho, volvol))) / (0.02 * f) else: delta_i = (b_s.BS_put( k, 100 * lognormal_vol(k, f * 1.01, t, alpha, beta, rho, volvol)) - b_s_2.BS_put( k, 100 * lognormal_vol(k, f * 0.99, t, alpha, beta, rho, volvol))) / (0.02 * f) return delta_i
def SABR_theta(f, t, k, CallPut, alpha, beta, rho, volvol): t2 = t * 1.01 b_s = BlackScholes(f, 0, 0, t) b_s_2 = BlackScholes(f, 0, 0, t2) if CallPut == 'C': theta = -(b_s.BS_call( k, 100 * lognormal_vol(k, f, t, alpha, beta, rho, volvol) ) - b_s_2.BS_call( k, 100 * lognormal_vol(k, f, t2, alpha, beta, rho, volvol))) / (t - t2) else: theta = -(b_s.BS_put( k, 100 * lognormal_vol(k, f, t, alpha, beta, rho, volvol) ) - b_s_2.BS_put( k, 100 * lognormal_vol(k, f, t2, alpha, beta, rho, volvol))) / (t - t2) return theta
def SABR_alpha_deri(f, t, k, CallPut, alpha, beta, rho, volvol): vol_1 = lognormal_vol(k, f, t, alpha * 0.99, beta, rho, volvol) * 100 vol_2 = lognormal_vol(k, f, t, alpha * 1.01, beta, rho, volvol) * 100 b_s = BlackScholes(f, 0, 0, t) if CallPut == 'C': volga = (b_s.BS_call(k, vol_2) - b_s.BS_call(k, vol_1)) / (0.02 * alpha) else: volga = (b_s.BS_put(k, vol_2) - b_s.BS_put(k, vol_1)) / (0.02 * alpha) return volga
def fit_beta(f, f_new, t, t2, k, v_sln_t1, C_t1, C_t2, C_P_list, v_sln_atm_t1, v_sln_atm_t2): beta_list = np.arange(0, 11, 1) / 10 f_diff = f_new - f C_diff = C_t2 - C_t1 min_hedge_error = 1e10 best_beta = beta_list[0] hedge_error_list = [] for beta in beta_list: hedge_error = 0 param = fit(f, t, beta, k, v_sln_t1) alpha_t1 = alpha(v_sln_atm_t1 / 100, f, t, beta, param[1], param[2]) alpha_t2 = alpha(v_sln_atm_t2 / 100, f_new, t2, beta, param[1], param[2]) f2 = f * 1.01 b_s = BlackScholes(f, 0, 0, t) b_s_2 = BlackScholes(f2, 0, 0, t) delta_list = [] vega_list = [] for num in range(len(k)): s_k = k[num] c_p = C_P_list[num] if c_p == 'C': delta_i = (b_s.BS_call( s_k, 100 * lognormal_vol(s_k, f, t, param[0], beta, param[1], param[2])) - b_s_2.BS_call( s_k, 100 * lognormal_vol(s_k, f2, t, param[0], beta, param[1], param[2]))) / (f - f2) vega_i = (b_s.BS_call(s_k, 100*lognormal_vol(s_k, f, t, alpha_t1, beta, param[1], param[2])) - b_s.BS_call(s_k, 100*lognormal_vol(s_k, f, t, alpha_t1 *1.01, beta, param[1], param[2]))) /\ (alpha_t1 - 1.01 * alpha_t1) else: delta_i = (b_s.BS_put( s_k, 100 * lognormal_vol(s_k, f, t, param[0], beta, param[1], param[2])) - b_s_2.BS_put( s_k, 100 * lognormal_vol(s_k, f2, t, param[0], beta, param[1], param[2]))) / (f - f2) vega_i = (b_s.BS_put( s_k, 100 * lognormal_vol(s_k, f, t, alpha_t1, beta, param[1], param[2])) - b_s.BS_put( s_k, 100 * lognormal_vol( s_k, f, t, alpha_t1 * 1.01, beta, param[1], param[2]))) / (alpha_t1 - 1.01 * alpha_t1) delta_list.append(delta_i) vega_list.append(vega_i) for i in range(len(C_diff)): #sig = (C_diff[i] - delta_list[i] * f_diff ) / C_t2[i] sig = (C_diff[i] - delta_list[i] * f_diff - vega_list[i] * (alpha_t2 - alpha_t1)) / C_t2[i] hedge_error += sig**2 hedge_error_list.append(hedge_error) if hedge_error < min_hedge_error: min_hedge_error = hedge_error best_beta = beta return best_beta
def get_delta(row): b_s = BlackScholes(row['underlying_price'], interest_rate, dividend, ttm) delta = b_s.BS_delta(row['Strike'], row['m_mid_vol'], row['CallPut']) return delta
def get_gamma(row): b_s = BlackScholes(row['underlying_price'], interest_rate, dividend, ttm) gamma = b_s.BS_gamma(row['Strike'], row['m_mid_vol']) return gamma
def SABR_bs_delta(f, t, k, CallPut, alpha, beta, rho, volvol): b_s = BlackScholes(f, 0, 0, t) SABR_vol = lognormal_vol(k, f, t, alpha, beta, rho, volvol) * 100 bs_delta = b_s.BS_delta(k, SABR_vol, CallPut) return bs_delta
k = np.array(asset_call_df['Strike']) strike_list = list(asset_call_df['Strike']) vv_vol_list = [] for K in strike_list: t = np.mean(asset_call_df['mtr']) f = np.mean(asset_call_df['underlying_price']) ATM_vol = delta25_call_df.loc[1, 'm_mid_vol'] K1, K2, K3 = delta25_call_df.loc[0, 'Strike'], delta25_call_df.loc[1, 'Strike'], delta25_call_df.loc[2, 'Strike'] mkt_price_K1 = delta25_call_df.loc[0, 'm_mid'] * delta25_call_df.loc[0, 'underlying_price'] mkt_price_K3 = delta25_call_df.loc[2, 'm_mid'] * delta25_call_df.loc[0, 'underlying_price'] weight_list = calculate_weight(f, t, ATM_vol, K, K1, K2, K3) price = calculate_price(f,t, ATM_vol, K, K1, K2, K3, mkt_price_K1, mkt_price_K3) delta = vanna_volga_delta(f, t, ATM_vol, K, K1, K2, K3, mkt_price_K1, mkt_price_K3) b_s = BlackScholes(f,0,0,t) vv_vol = b_s.BS_impliedVol(K, price, 'C') vv_vol_list.append(vv_vol) asset_call_df['VV_vol'] = vv_vol_list result_df = result_df.append(asset_call_df) result_df.to_csv('D:\\SABR model/vol_data/SABR_VV_model_param.csv') vol_fit = [SABR.lognormal_vol(k_, f, t, param[0], 1, param[1], param[2]) * 100 for k_ in strike_list] #vol_surface_df.loc[t, strike_list] = vol_fit plt.figure(figsize=(6, 6)) fig = plt.figure(1) ax1 = plt.subplot(111)