def getstockopts(stockname, save=True): opts = Options(stockname, 'yahoo') expirydates = opts.expiry_dates dateexp = datetime(2017, 12, 15) #manually set to this calldata = opts.get_call_data(expiry=dateexp) putdata = opts.get_put_data(expiry=dateexp) prices = web.DataReader(stockname, 'yahoo', today) call_impt = calldata[['Last', 'Open_Int', 'Underlying_Price']] call_indexed_impt = call_impt.reset_index() put_impt = putdata[['Last', 'Open_Int', 'Underlying_Price']] put_indexed_impt = put_impt.reset_index() datstr = str(today.date()) comb_indexed_impt = pd.concat([call_indexed_impt, put_indexed_impt]) comb_indexed_impt.index = [datstr] * len(comb_indexed_impt.index) prices_indexed = prices.reset_index() prices_indexed.index = [datstr] * len(prices_indexed.index) if save: foldlists = os.listdir(datfold) foldname = stockname + '/' if stockname not in foldlists: os.mkdir(datfold + foldname) os.mkdir(datfold + foldname + 'options/') os.mkdir(datfold + foldname + 'prices/') stockoptlist = os.listdir(datfold + foldname + 'options/') stockpricelist = os.listdir(datfold + foldname + 'prices/') stockoptname = stockname + '-options.csv' stockpricename = stockname + '-prices.csv' if stockoptname not in stockoptlist: comb_indexed_impt.to_csv(datfold + foldname + 'options/' + stockoptname) else: comb_indexed_impt.to_csv(datfold + foldname + 'options/' + stockoptname, mode='a', header=False) if stockpricename not in stockpricelist: prices_indexed.to_csv(datfold + foldname + 'prices/' + stockpricename) else: prices_indexed.to_csv(datfold + foldname + 'prices/' + stockpricename, mode='a', header=False) print('stock : ' + stockname + ' DONE')
Created on Thu Dec 6 23:36:56 2018 @author: dpsugasa """ import pandas as pd from numpy import sqrt,mean,log,diff import QuantLib as ql from pandas_datareader.data import Options import pandas_datareader.data as web import datetime opt = Options('spy', 'google') expiration_dates = [ql.Date(i.day, i.month, i.year) for i in opt.expiry_dates] expiry_index = 14 # choose the contracts expire on 11/17/2017 data = opt.get_call_data(expiry=opt.expiry_dates[expiry_index]) strikes = list(data.index.get_level_values('Strike')) premium = list(data['Last']) day_count = ql.Actual365Fixed() calendar = ql.UnitedStates() calculation_date = ql.Date(opt._quote_time.day,opt._quote_time.month,opt._quote_time.year) # 08/10/2017 spot = opt.underlying_price # spot price is 244.82 ql.Settings.instance().evaluationDate = calculation_date dividend_yield = ql.QuoteHandle(ql.SimpleQuote(0.0)) risk_free_rate = 0.01 dividend_rate = 0.0 flat_ts = ql.YieldTermStructureHandle( ql.FlatForward(calculation_date, risk_free_rate, day_count)) dividend_ts = ql.YieldTermStructureHandle( ql.FlatForward(calculation_date, dividend_rate, day_count)) # dummy parameters
class OptionLib: def __init__(self, symbol='SPY', dataprovider='yahoo', riskfree=0.01, dividendrate=0.01): self.SYMBOL = symbol self.data_provider = dataprovider self.__oldsymbol = symbol self.__olddataprovider = dataprovider self.risk_free_rate = riskfree self.dividend_rate = dividendrate self.opt = None self.IVs = {'c': [], 'p': []} self.__last_quote = None self.__underlying_price = None self.__data = None self.__data_core = None self.data_selection = (0, 'c') self.tickSize = 0.5 self.data_init() ######################################################################################################### # Data Building and Housekeeping # ######################################################################################################### @waitSyncFlag def data_init(self): self.opt = Options(self.SYMBOL, self.data_provider) self.__underlying_price = self.opt.underlying_price self.data_building_core() self.lastGreeks = {'strike': None, 'data': {}, 'S': [], 'T': []} self.IVs = {'c': [], 'p': []} self.data_aggregate_IV() @waitSyncFlag def data_refresh(self): self.__underlying_price = self.opt.underlying_price self.data_building_core() self.lastGreeks = {'strike': None, 'data': {}, 'S': [], 'T': []} self.IVs = {'c': [], 'p': []} self.data_aggregate_IV() @parallelProcess def data_auto_refresh(self): # This should be running in another thread while True: if not (self.SYMBOL == self.__oldsymbol and self.data_provider == self.__olddataprovider): self.__oldsymbol, self.__olddataprovider = self.SYMBOL, self.data_provider self.__last_quote = self.opt.get_call_data( ).iloc[0]['Quote_Time'].to_pydatetime() self.data_init() print('Data Initialization for {} [ COMPLETE ]'.format( self.SYMBOL)) if not (self.opt.get_call_data().iloc[0] ['Quote_Time'].to_pydatetime() == self.__last_quote): self.__last_quote = self.opt.get_call_data( ).iloc[0]['Quote_Time'].to_pydatetime() self.data_refresh() print('Data Refreshing for {} [ COMPLETE ]'.format( self.SYMBOL)) @requireSyncFlag def data_building_core(self): try: assert self.opt df = self.opt.get_all_data() dflen = len(df.index.values) d = {} for i in range(dflen): dfindex = df.index.values[i] row = df.loc[dfindex] exp = dfindex[1].to_pydatetime() curr = row['Quote_Time'].to_pydatetime() toe = float((exp - curr).days) / 365.0 # Days until expiration dte = round(toe * 365) + 1 otype = 'c' if dfindex[2] == 'call' else 'p' # Index will be using expiry_date index expd = exp.date() j = self.opt.expiry_dates.index(expd) bso = Black_Scholes(option_type=otype, price=row['Underlying_Price'], strike=dfindex[0], interest_rate=self.risk_free_rate, dividend_yield=self.dividend_rate, volatility=row['IV'], expiry=toe) # Check if the index exists or not if not (j in d): d[j] = {'matrix': [], 'indexes': []} # [ [ Ask, Bid, Last, Vol, %, sigma, delta, gamma, kappa, theta, rho, dte, symbol] , (...) ] d[j]['matrix'].append([ row['Ask'], row['Bid'], row['Last'], int(row['Vol']), row['PctChg'], round(row['IV'], 2), round(bso.delta, 2), round(bso.gamma, 2), round(bso.kappa, 2), round(bso.theta, 2), round(bso.rho, 2), dte, dfindex[3] ]) # [ ( type, strike), ... ] d[j]['indexes'].append((otype, dfindex[0])) self.__data_core = d except AssertionError: raise DataFormatError( 'No Data from Yahoo, Check Internet Connection') @requireSyncFlag def data_aggregate_IV(self): """ Aggregate Contract's sigma by call and puts then store them in [ Time to Expiration, Strike, Volatility ] format for later plotting """ try: assert self.__data_core d = self.__data_core.copy() for t in d.keys(): matrix = d[t]['matrix'] indexes = d[t]['indexes'] for i in range(len(matrix)): # Format : [ Time to Expiration, Strike, Volatility ] self.IVs[indexes[i][0]].append( [matrix[i][11], indexes[i][1], matrix[i][5]]) except AssertionError: raise DataFormatError('Must input a pandas.DataFrame') def data_IVpT(self, expiry_index=0): """ Compute IV per timestamp :return: calls and puts """ dt = self.__data_core[expiry_index].copy() matrix = dt['matrix'] indexes = dt['indexes'] calls, puts = [], [] # calls = [ [ Strike, IV] , ... ] for i in range(len(matrix)): if indexes[i][0] == 'c': calls.append([indexes[i][1], matrix[i][5]]) else: puts.append([indexes[i][1], matrix[i][5]]) return calls, puts def data_aggregate_greeks(self, strike=None): """ :return: """ try: assert self.__data_core assert strike d = self.__data_core.copy() times = [] sigmas = [] for t in d.keys(): matrix = d[t]['matrix'] indexes = d[t]['indexes'] for i in range(len(matrix)): if indexes[i][0] == 'c' and indexes[i][1] == strike: sigmas.append(matrix[i][5]) times.append(float(matrix[i][11]) / 365.0) # Matrices are n x m # where n : the nb of contract_dates # compute underlyingPrice matrix underlyingPriceMatrix = np.array([ np.arange(0.0, self.__underlying_price * 2, self.tickSize) for i in range(len(sigmas)) ]) MatrixShape = underlyingPriceMatrix.shape sigmaMatrix = np.array([ np.ones(MatrixShape[1]) * sigmas[i] for i in range(MatrixShape[0]) ]).reshape(MatrixShape) expiryMatrix = np.array([ np.ones(MatrixShape[1]) * times[i] for i in range(MatrixShape[0]) ]).reshape(MatrixShape) ccontracts = [] pcontracts = [] for i in range(MatrixShape[0]): for j in range(MatrixShape[1]): cbso = Black_Scholes(option_type='c', strike=strike, price=underlyingPriceMatrix[i][j], interest_rate=self.risk_free_rate, dividend_yield=self.dividend_rate, expiry=expiryMatrix[i][j], volatility=sigmaMatrix[i][j]) pbso = Black_Scholes(option_type='p', strike=strike, price=underlyingPriceMatrix[i][j], interest_rate=self.risk_free_rate, dividend_yield=self.dividend_rate, expiry=expiryMatrix[i][j], volatility=sigmaMatrix[i][j]) #Access elements in matrix[i][j] ccontracts.append(cbso) pcontracts.append(pbso) cdelta = np.array([c.delta for c in ccontracts]).reshape(MatrixShape) cgamma = np.array([c.gamma for c in ccontracts]).reshape(MatrixShape) ctheta = np.array([c.theta for c in ccontracts]).reshape(MatrixShape) ckappa = np.array([c.kappa for c in ccontracts]).reshape(MatrixShape) crho = np.array([c.rho for c in ccontracts]).reshape(MatrixShape) pdelta = np.array([p.delta for p in pcontracts]).reshape(MatrixShape) pgamma = np.array([p.gamma for p in pcontracts]).reshape(MatrixShape) ptheta = np.array([p.theta for p in pcontracts]).reshape(MatrixShape) pkappa = np.array([p.kappa for p in pcontracts]).reshape(MatrixShape) prho = np.array([p.rho for p in pcontracts]).reshape(MatrixShape) greeks = {'c': {}, 'p': {}} greeks['c']['delta'] = cdelta greeks['c']['gamma'] = cgamma greeks['c']['theta'] = ctheta greeks['c']['kappa'] = ckappa greeks['c']['rho'] = crho greeks['p']['delta'] = pdelta greeks['p']['gamma'] = pgamma greeks['p']['theta'] = ptheta greeks['p']['kappa'] = pkappa greeks['p']['rho'] = prho self.lastGreeks['data'] = greeks self.lastGreeks['strike'] = strike self.lastGreeks['S'] = underlyingPriceMatrix self.lastGreeks['T'] = expiryMatrix except AssertionError: pass pass ######################################################################################################### # Client's Methods and Properties # ######################################################################################################### @property def index(self): opt = self.opt d = {'Expiry Dates': opt.expiry_dates} return pd.DataFrame(data=d).transpose() @property def data(self): print('Underlying @ {:.2f} \nLatest Option Quote @: {}\n'.format( self.__underlying_price, self.__last_quote)) print('Current Contracts Expires @ {}\n'.format( self.opt.expiry_dates[self.data_selection[0]])) obj = self.__data_core[self.data_selection[0]] data = np.array(obj['matrix']) indexes = obj['indexes'] filtered_matrix = [] filtered_indexes = [] for i in range(len(data)): if indexes[i][0] == self.data_selection[1]: filtered_matrix.append(data[i]) filtered_indexes.append(indexes[i][1]) columns = [ 'Ask', 'Bid', 'Last', 'Vol', '%', '\u03C3', '\u0394', '\u0393', '\u039A', '\u0398', '\u03A1', 'Days to Expiry', 'Symbol' ] df = pd.DataFrame(data=filtered_matrix, index=filtered_indexes, columns=columns) return df @property def VIEW_SELECTION(self): return 'CURRENTLY SELECTED DATA :: [ INDEX : {} | TYPE : {} | SYMBOL : {} ]'.format( self.data_selection[0], self.data_selection[1], self.SYMBOL) def select( self, INDEX=0, TYPE='c', ): """ Setting the data-selecting tuple """ try: assert TYPE == 'c' or TYPE == 'p' assert INDEX < len(self.opt.expiry_dates) self.data_selection = (INDEX, TYPE) except AssertionError: raise DataFormatError( 'Expiry index and option type ("c" or "p") must be valid') ######################################################################################################### # Plotting # ######################################################################################################### def plot_smile( self, expiry_index=None, ): """ Plot the IV smile for both calls and puts per timestamp """ expiry_index = expiry_index if expiry_index else self.data_selection[0] calls, puts = self.data_IVpT(expiry_index=expiry_index) k_calls, IV_calls = [], [] k_puts, IV_puts = [], [] for el in calls: k_calls.append(el[0]) IV_calls.append(el[1]) for el in puts: k_puts.append(el[0]) IV_puts.append(el[1]) plt.figure(figsize=(16, 7)) e = plt.scatter(k_calls, IV_calls, c='white', label="IV(call options)") f = plt.scatter(k_puts, IV_puts, c='red', label="IV(put options)") plt.xlabel('strike') plt.ylabel('Implied Volatility') plt.legend((e, f), ("IV (call options)", "IV (put options)")) def plot_surface( self, option_type=None, ): try: if option_type: assert option_type == 'c' or option_type == 'p' option_type = option_type if option_type else self.data_selection[1] plotdata = self.IVs[option_type] color = 'red' if option_type == 'p' else 'green' xaxis = [plotdata[i][0] for i in range(len(plotdata))] yaxis = [plotdata[i][1] for i in range(len(plotdata))] zaxis = [plotdata[i][2] for i in range(len(plotdata))] fig1 = plt.figure(figsize=(20, 12)) ax = fig1.add_subplot(111, projection='3d') ax.view_init() ax.scatter(xaxis, yaxis, zaxis, c=color) plt.xlabel("Time to Expiration (days)") plt.ylabel("Strikes") plt.title("Implied Volatility") fig2 = plt.figure(figsize=(20, 12)) ax2 = fig2.add_subplot(111, projection='3d') ax2.view_init() ax2.plot_trisurf(xaxis, yaxis, zaxis, cmap=cm.jet) plt.xlabel("Time to Expiration (days)") plt.ylabel("Strikes") plt.title("Implied Volatility") except AssertionError: print( 'You must specify option type as first argument and/or Invalid option type' ) except Exception as e: print(e) def plot_letter(self, LETTER=None, STRIKE=None, otype='c'): try: assert LETTER in ['delta', 'gamma', 'theta', 'kappa', 'rho'] data = {} S, T = [], [] strike = STRIKE if STRIKE else np.round(self.__underlying_price) if self.lastGreeks['strike'] and self.lastGreeks[ 'strike'] == strike: data, S, T = self.lastGreeks['data'], self.lastGreeks[ 'S'], self.lastGreeks['T'] else: self.data_aggregate_greeks(strike=strike) data, S, T = self.lastGreeks['data'], self.lastGreeks[ 'S'], self.lastGreeks['T'] print('Plotting {} with Strike {} for {} - {}\n'.format( LETTER, strike, self.SYMBOL, otype)) Z = data[otype][LETTER] fig = plt.figure(figsize=(20, 11)) ax = fig.add_subplot(111, projection='3d') ax.view_init(40, 290) ax.plot_wireframe(S, T, Z, rstride=1, cstride=1) ax.plot_surface(S, T, Z, facecolors=cm.jet(Z), linewidth=0.001, rstride=1, cstride=1, alpha=0.75) ax.set_zlim3d(0, Z.max()) ax.set_xlabel('Stock Price') ax.set_ylabel('Time to Expiration') ax.set_zlabel(LETTER) m = cm.ScalarMappable(cmap=cm.jet) m.set_array(Z) cbarDelta = plt.colorbar(m) except AssertionError: raise DataFormatError('Invalid Letter') except ValueError: raise DataFormatError( 'Invalid Calculations for {} :: Something went wrong on our end :$' .format(LETTER))
# op_name = raw_input('Please enter Option Name (European/American): ') # op_type = raw_input('Please enter Option Type (call/put): ') # stock, option, hedge = option_tree(S0, K, N, op_name, op_type) # stock, option, hedge = option_tree(10, 10, 2, 'ameRican', 'Put') # print(stock) # print(option) # print(hedge) ############################################################################################# ##################################### Output the Result ##################################### ############################################################################################# # Get Bid Price, Ask Price for Call and Put Options goog = Options('GOOG', 'yahoo') call_data = goog.get_call_data(6, 2018) bid_call = call_data['Bid'] ask_call = call_data['Ask'] put_data = goog.get_put_data(6, 2018) bid_put = put_data['Bid'] ask_put = put_data['Ask'] # Calculate the Value of Option # value_call_option = [] # Value of Option for Call Option # value_put_option = [] # Value of Option for Put Option # # for i in range(len(bid_call)): # value_call_option.append((bid_call[i] + ask_call[i]) / 2) # value_put_option.append((bid_put[i] + ask_put[i]) / 2) # Get Options' Strike Prices for Call and Put
import pandas_datareader.data as web from pandas_datareader.data import Options import datetime import pandas as pd pd.set_option('display.width', 300) #data = web.DataReader(stock,self.provider, start, end) #data = web.DataReader("AAPL","google", "01/01/2017", "05/05/2017") #print(data) expiry = datetime.date(2017, 2, 2) aapl = Options('aapl','yahoo') data = aapl.get_call_data(expiry=expiry) print(data)