def test_analytical_vega(self): while self.tdi.has_next(): row = self.tdi.next_row() S, K, t, r, sigma = row['S'], row['K'], row['t'], row['R'], row[ 'v'] self.assertAlmostEqual(analytical.vega('c', S, K, t, r, sigma), row['CV'] * .01, delta=0.000001) self.assertAlmostEqual(analytical.vega('p', S, K, t, r, sigma), row['PV'] * .01, delta=0.000001)
def test_analytical_vega(self): S = 49 K = 50 sigma = .2 r = .05 t = 0.3846 flag = 'p' c_put = c_analytical.vega(flag, S, K, t, r, sigma) py_put = py_analytical.vega(flag, S, K, t, r, sigma) self.assertTrue(almost_equal(c_put, py_put)) flag = 'c' c_call = c_analytical.vega(flag, S, K, t, r, sigma) py_call = py_analytical.vega(flag, S, K, t, r, sigma) self.assertTrue(almost_equal(c_call, py_call))
def test_vega(self): vegas = [ vega(flag, S, K, t, r, sigma) for flag, S, K, t, r, sigma in self.arg_combinations ] nvegas = [ nvega(flag, S, K, t, r, sigma) for flag, S, K, t, r, sigma in self.arg_combinations ] self.assertTrue(self.diff_mean(vegas, nvegas) < self.epsilon)
def Calculate_vega(each_row): if each_row['Implied_Volatility'] == 0: measure= 0 else: try: measure = bs_a.vega(flag=each_row['CallOrPut'], S=each_row['Spot'], K=each_row['Strike_Price'], t=each_row['Days_to_Expiry']/365, r=.1,sigma=each_row['Implied_Volatility']) except: measure = 0 print("Vega", end=" ") return measure
def calc_all(self, b): h = self.all_set(b) if not h: return False if not h.get("sigma"): self.civ(h) if not h.get("sigma"): return False a = (h["flag"], h["F"], h["K"], h["t"], h["r"], h["sigma"]) r = self.rounding h["price"] = round(oprice(*a), r) h["delta"] = round(delta(*a), r) h["gamma"] = round(gamma(*a) * 100, r) h["vega"] = round(vega(*a), r) return h
def vega(self, option_obj, asset_price, timestamp, expiration, call_put_flag): flag = call_put_flag S = asset_price K = option_obj.strike t = self.time_2_expiration(timestamp, expiration) r = self.risk_free_rate sigma = option_obj.sigma vega = vollib_greeks.vega(flag, S, K, t, r, sigma) return vega
def update_vega(self, asset_code): flag = asset_code[0].lower() S = self.mid_dict['IDX#PHX'] if len(asset_code) == 6: K = int(asset_code[1:3]) elif len(asset_code) == 7: K = int(asset_code[1:4]) t = (63 - (time.time() - self.start_time) / (900 / 21)) / 252 #time to expiration in years r = 0 price = self.mid_dict[asset_code] sigma = IV(price, S, K, r, t, flag) * np.sqrt(252) return bsga.vega(flag, S, K, t, r, sigma)
def calculateAllGreeks(ticker, date, type, strike): S = si.get_live_price(ticker) K = strike sigma = calculateAnnualizedVolatility(ticker) t = optionExpiration(date) r = calculateTreasuryYield(date) if type == 'Call' or type == "call" or type == "C" or type == 'c': flag = 'c' else: flag = 'p' dlta = delta(flag, S, K, t, r, sigma) gam = gamma(flag, S, K, t, r, sigma) thta = theta(flag, S, K, t, r, sigma) vga = vega(flag, S, K, t, r, sigma) rh = rho(flag, S, K, t, r, sigma) return ({"delta": dlta, "gamma": gam, "theta": thta, "vega": vga, "rho": rh})
def calculateGreek(ticker, date, type, strike, greek): grk = 0 S = si.get_live_price(ticker) K = strike sigma = calculateAnnualizedVolatility(ticker) t = optionExpiration(date) r = calculateTreasuryYield(date) flag = '' if type == 'Call' or type == "call" or type == "C" or type == 'c': flag = 'c' flag = 'p' if greek == "Delta" or greek == "delta": grk = delta(flag, S, K, t, r, sigma) elif greek == "Gamma" or greek == "gamma": grk = gamma(flag, S, K, t, r, sigma) elif greek == "Theta" or greek == "theta": grk = theta(flag, S, K, t, r, sigma) elif greek == "Vega" or greek == "vega": grk = vega(flag, S, K, t, r, sigma) else: grk = rho(flag, S, K, t, r, sigma) return grk
def precompute(table, computedate, underlying, include_riskfree): db = psycopg2.connect(host="localhost", user=settings.db_username, password=settings.db_password, database="optiondata") cur2 = db.cursor() underlying_fragment = "" if (underlying != "*"): underlying_fragment = "underlying_symbol = '" + underlying + "' AND " date_fragment = "" if (computedate != "*"): date_fragment = "quote_date = '" + str(computedate) + "' AND " query = "SELECT id, quote_date, underlying_mid_1545, mid_1545, expiration, strike, option_type FROM " + \ table + " WHERE " + underlying_fragment + date_fragment + "iv IS NULL" cur2.execute(query) result = cur2.fetchall() print( str(computedate) + " " + str(underlying) + ": " + str(len(result)) + " results") bulkrows = [] if (len(result) > 0): for row in result: rowid = row[0] quote_date = row[1] underlying_mid_1545 = float(row[2]) mid_1545 = float(row[3]) expiration = row[4] strike = float(row[5]) option_type = row[6] expiration_time = datetime.datetime.combine( expiration, datetime.time(16, 0)) remaining_time_in_years = util.remaining_time( quote_date, expiration_time) rf = util.interest if include_riskfree: rf = util.get_riskfree_libor(quote_date, remaining_time_in_years) try: iv = implied_volatility.implied_volatility( mid_1545, underlying_mid_1545, int(strike), remaining_time_in_years, rf, option_type) except: iv = 0.001 try: bs_price_bid_ask = black_scholes(option_type, underlying_mid_1545, strike, remaining_time_in_years, rf, iv) except: bs_price_bid_ask = 0.001 try: delta = analytical.delta(option_type, underlying_mid_1545, strike, remaining_time_in_years, rf, iv) * 100 except: delta = 0.001 try: theta = analytical.theta(option_type, underlying_mid_1545, strike, remaining_time_in_years, rf, iv) * 100 except: theta = 0.001 try: vega = analytical.vega(option_type, underlying_mid_1545, strike, remaining_time_in_years, rf, iv) * 100 except: vega = 0.001 bulkrows.append({ 'iv': iv, 'bs_price_bid_ask': bs_price_bid_ask, 'delta': delta, 'theta': theta, 'vega': vega, 'rowid': rowid }) psycopg2.extras.execute_batch( cur2, """UPDATE """ + table + """ SET iv=%(iv)s, bs_price_bid_ask=%(bs_price_bid_ask)s, delta=%(delta)s, theta=%(theta)s, vega=%(vega)s WHERE id=%(rowid)s""", bulkrows, page_size=100) db.commit() db.close()
def weighted_iv(cls, options, term, flag='c'): if flag == 'c': # Call fields bid = 'CallBid' ask = 'CallAsk' last_sale = 'CallLastSale' else: # Put fields bid = 'PutBid' ask = 'PutAsk' last_sale = 'PutLastSale' option_iv = pd.Series(pd.np.zeros(len(options.data.index)), index=options.data.index, name='OptionImpliedVolatility') for i in options.data.index: t = options.data.Expiration[i] / 365.0 price = (options.data[bid][i] + options.data[ask][i]) / 2.0 option_iv[i] = cls.calculate(options.underlying_price, options.data.Strike[i], t, price, flag=flag) data = options.data.join(option_iv) def _find_expiration_dates(df, term): """ Find two expiration dates closest to given number of days, front and back month. """ expirations = df[['Expiration' ]].drop_duplicates().reset_index(drop=True) back_expirations = expirations[(expirations.Expiration > term)].copy() front_expirations = expirations[(expirations.Expiration < term)].copy() if back_expirations.size > 0 and front_expirations.size > 0: front_back_values = [] for frame in [ front_expirations, back_expirations, ]: frame['Difference'] = frame['Expiration'].apply( lambda value: abs(value - term)) front_back_values.append( frame.sort_values( by=['Difference']).head(1)['Expiration'].values[0]) return front_back_values return None, None front, back = _find_expiration_dates(data, term) if not front or not back: return 0.0 def _find_closest_strikes(df, front, back, underlying_price, number_of_strikes=4): """ We take 4 (number_of_strikes) options contracts with strikes nearest to current stock price. We'll use this list to calculate IV Index for the front and back months. """ strike_expiration_df = df[(df.Expiration == front) | (df.Expiration == back)][[ 'Strike', 'Expiration' ]].drop_duplicates().reset_index( drop=True) front_back_lists = [] for value in ( front, back, ): s1 = strike_expiration_df[( strike_expiration_df.Expiration == value)]['Strike'].apply( lambda item: abs(item - underlying_price)).reset_index( drop=True) s2 = df[(df.Expiration == value )]['Strike'].drop_duplicates().reset_index(drop=True) front_back_lists.append( pd.DataFrame({ 'Difference': s1, 'Strike': s2 }).reset_index(drop=True).sort_values(by='Difference'). head(number_of_strikes)['Strike'].values) return front_back_lists front_strikes, back_strikes = _find_closest_strikes( data, front, back, options.underlying_price) # data = data[(data.OptionImpliedVolatility > .01) & (data.OptionImpliedVolatility < 1) & # TODO: Removed IV < 1 filter. IV can be greater than 100%. Looking at you AyyMD ;) data = data[(data.OptionImpliedVolatility > .01) & (( (data.Expiration == front) & (data.Strike.isin(front_strikes))) | ( (data.Expiration == back) & (data.Strike.isin(back_strikes)))) & ((data[bid] > 0) | (data[ask] > 0))] # ) & (data[last_sale] > 0) & (data[bid] > 0) & (data[ask] > 0)] # TODO: Do we care about filtering out options that are not active (last_sale == 0). For example, # if we keep only last_sale > 0 strikes we may end up without options to process. This will # cause vega weights calculations to fail. # TODO: Sometimes bid or ask are 0, so make sure average is calculated correctly. df = pd.DataFrame() for index, items in data[[ 'Strike', 'Expiration' ]].drop_duplicates().reset_index(drop=True).iterrows(): values = data[(data.Strike == items['Strike']) & (data.Expiration == items['Expiration'])][[ 'OptionImpliedVolatility', ask, bid ]].mean() values['Strike'] = items['Strike'] values['Expiration'] = items['Expiration'] values['Price'] = ( values[bid] + values[ask] ) / 2.0 if values[ask] > 0 and values[bid] > 0 else max( values[ask], values[bid]) values['Vega'] = vega(flag, options.underlying_price, items['Strike'], items['Expiration'] / 365.0, RISK_FREE_INTEREST_RATE, values['OptionImpliedVolatility']) df = df.append(values, ignore_index=True) # Liquidity considerations in estimating implied volatility (Rohini Grover and Susan Thomas) # # Interpolation scheme: # # vix = 100 * [ weight_t1 * ( (Nc2 - 30) / (Nc2 - Nc1) ) + weight_t2 * ( (30 - Nc1) / (Nc2 - Nc1) ) ] # # Where weight_ti are implied volatilities and Nci is the number of calendar days to # expiration. Here, i = 1, 2 for the near and next month respectively. def _front_vega_weights(df, front, back, term): """ This function will calculate weighted average for the front month, where weighting is done by Vega (option price sensitivity to a change in Implied Volatility). """ vegas_ivs = 0.0 vegas = 0.0 for index, items in df[(df.Expiration == front)].iterrows(): vegas_ivs += items['Vega'] * items['OptionImpliedVolatility'] vegas += items['Vega'] vw = vegas_ivs / vegas expiry_sqrt = (math.sqrt(back) - math.sqrt(term)) / ( math.sqrt(back) - math.sqrt(front)) return vw, expiry_sqrt def _back_vega_weights(df, front, back, term): """ This function will calculate weighted average for the back month, where weighting is done by Vega (option price sensitivity to a change in Implied Volatility). """ vegas_ivs = 0.0 vegas = 0.0 for index, items in df[(df.Expiration == back)].iterrows(): vegas_ivs += items['Vega'] * items['OptionImpliedVolatility'] vegas += items['Vega'] vw = vegas_ivs / vegas expiry_sqrt = (math.sqrt(term) - math.sqrt(front)) / ( math.sqrt(back) - math.sqrt(front)) return vw, expiry_sqrt vw1, i1 = _front_vega_weights(df, front, back, term) vw2, i2 = _back_vega_weights(df, front, back, term) return i1 * vw1 + i2 * vw2
def precompute(underlying, include_riskfree): done = False bulksize = 100000 counter = 0 print("precompute: " + str(underlying)) print() while not done: db = psycopg2.connect(host="localhost", user=settings.db_username, password=settings.db_password, database="optiondata") cur2 = db.cursor() print("Query for next " + str(bulksize) + " items to precompute ") query = "SELECT id, quote_date, underlying_mid_1545, mid_1545, expiration, strike, option_type FROM optiondata WHERE underlying_symbol = '" + underlying + "' AND iv IS NULL LIMIT " + str( bulksize) cur2.execute(query) result = cur2.fetchall() print(str(len(result)) + " items to precompute") if len(result) == 0: done = True print("Done precomputing") print() bulkrows = [] for row in result: rowid = row[0] quote_date = row[1] underlying_mid_1545 = float(row[2]) mid_1545 = float(row[3]) expiration = row[4] strike = float(row[5]) option_type = row[6] expiration_time = datetime.datetime.combine( expiration, datetime.time(16, 0)) remaining_time_in_years = util.remaining_time( quote_date, expiration_time) rf = util.interest if include_riskfree: rf = util.get_riskfree_libor(quote_date, remaining_time_in_years) try: iv = implied_volatility.implied_volatility( mid_1545, underlying_mid_1545, int(strike), remaining_time_in_years, rf, option_type) delta = analytical.delta(option_type, underlying_mid_1545, strike, remaining_time_in_years, rf, iv) * 100 theta = analytical.theta(option_type, underlying_mid_1545, strike, remaining_time_in_years, rf, iv) * 100 vega = analytical.vega(option_type, underlying_mid_1545, strike, remaining_time_in_years, rf, iv) * 100 except: iv = 0.001 delta = 0.001 theta = 0.001 vega = 0.001 bulkrows.append({ 'iv': iv, 'delta': delta, 'theta': theta, 'vega': vega, 'rowid': rowid }) counter += 1 if (((counter % 1000) == 0) or ((len(result) < bulksize) and (counter == len(result)))): try: cur2.executemany( """UPDATE optiondata SET iv=%(iv)s, delta=%(delta)s, theta=%(theta)s, vega=%(vega)s WHERE id=%(rowid)s""", bulkrows) db.commit() print("inserted: " + str(counter)) bulkrows = [] time.sleep(1) except Exception as e: print("an exception occurred") print(e) if (len(result) < bulksize) and (counter == len(result)): done = True print("Done precomputing") print() db.close()
def precompute(underlying): print("precompute: " + str(underlying)) print db = pgdb.connect(host="localhost", user=settings.db_username, password=settings.db_password, database="optiondata") cur2 = db.cursor() query = "SELECT id, quote_date, underlying_bid_1545, underlying_ask_1545, bid_1545, ask_1545, expiration, strike, option_type FROM optiondata WHERE underlying_symbol = '" + underlying + "' AND iv IS NULL ORDER BY id asc" cur2.execute(query) result = cur2.fetchall() print(str(len(result)) + " items to precompute") for row in result: rowid = row[0] quote_date = row[1] underlying_bid_1545 = row[2] underlying_ask_1545 = row[3] bid_1545 = row[4] ask_1545 = row[5] expiration = row[6] strike = float(row[7]) option_type = row[8].lower() current_quote = float((underlying_bid_1545 + underlying_ask_1545) / 2) midprice = float((bid_1545 + ask_1545) / 2) expiration_time = datetime.combine(expiration, time(16, 0)) remaining_time_in_years = util.remaining_time(quote_date, expiration_time) iv = 0.001 delta = 0.001 theta = 0.001 vega = 0.001 if remaining_time_in_years > 0: try: iv = implied_volatility.implied_volatility( midprice, current_quote, int(strike), remaining_time_in_years, util.interest, option_type) except: iv = 0.001 delta = analytical.delta(option_type, current_quote, strike, remaining_time_in_years, util.interest, iv) * 100 theta = analytical.theta(option_type, current_quote, strike, remaining_time_in_years, util.interest, iv) * 100 vega = analytical.vega(option_type, current_quote, strike, remaining_time_in_years, util.interest, iv) * 100 updateQuery = "UPDATE optiondata SET iv=%s, delta=%s, theta=%s, vega=%s WHERE id=%s" % ( iv, delta, theta, vega, rowid) try: cur2.execute(updateQuery) db.commit() except: print("Except") print(rowid) print(current_quote) print(midprice) print(iv) print(delta) print(theta) print(vega) print(updateQuery) db.close()