def putPercentChange(ticker, strike): putChart = options.get_puts(ticker) csv = putChart.to_csv(ticker + '.csv') tickerDf = pd.read_csv(ticker + '.csv') oneRowDataframe = tickerDf.loc[tickerDf['Strike'] == strike] percentChange = oneRowDataframe.iloc[0]['% Change'] return percentChange
def getDetailedQuote(stock, ax1 = None): ''' # get the detailded bid/ask quote data for charting # input : stock - stock ticker of the option of interest ax1 - matplotlib axis , if desired to specify # for use with bestPick frame: # bestPick['Stock'] would be the input # output is a matplotlib AxesSubplot object ''' # find the current price of the stock in question currentPrice=stock_info.get_live_price(stock) stockOptionVals=options.get_puts(stock, date='05/15/20') asksExist = stockOptionVals['Ask'] != '-' bidsExist = stockOptionVals['Bid'] != '-' stockOptionVals = stockOptionVals[bidsExist & asksExist] stockOptions = stockOptionVals.plot(x='Strike',y=['Bid','Ask'], xlim=[.25*currentPrice,1.75*currentPrice], title='Bid and Ask Prices for {} Options Contracts'.format(stock), ax = ax1) # plot the current stock price as a vertical line in green stockOptions.axvline(currentPrice, color='green', ls='--') stockOptions.set_xlabel('Strike Price ($)') stockOptions.set_ylabel('Contract Price ($)') return stockOptions
def calculateStopLoss(ticker, strike, optionType): if optionType == 'Call' or optionType == 'call': callChart = options.get_calls(ticker) cdf = pd.DataFrame(callChart) oneRowDataframe = cdf.loc[cdf['Strike'] == strike] ask = oneRowDataframe.iloc[0]['Ask'] bid = oneRowDataframe.iloc[0]['Bid'] currPrice = oneRowDataframe.iloc[0]['Last Price'] limitPriceUpper = (currPrice - (currPrice * .2)) - (ask - bid) limitPriceLower = (currPrice - (currPrice * .15)) - (ask - bid) if limitPriceLower < 0 or limitPriceUpper < 0: print("No need to set stop loss! This option premium is too low for a stop loss!") elif limitPriceUpper != limitPriceLower: print("Set Stop Loss Between: $", limitPriceUpper, "and $", limitPriceLower) if optionType == 'Put' or optionType == 'Put': putChart = options.get_puts(ticker) pdf = pd.DataFrame(putChart) oneRowDataframe = pdf.loc[pdf['Strike'] == strike] ask = oneRowDataframe.iloc[0]['Ask'] bid = oneRowDataframe.iloc[0]['Bid'] currPrice = oneRowDataframe.iloc[0]['Last Price'] limitPriceUpper = (currPrice - (currPrice * .2)) - (ask - bid) limitPriceLower = (currPrice - (currPrice * .15)) - (ask - bid) if limitPriceLower < 0 or limitPriceUpper < 0: print("No need to set stop loss! This option premium is too low for a stop loss!") elif limitPriceUpper != limitPriceLower: print("Set Stop Loss Between: $", limitPriceUpper, "and $", limitPriceLower)
def putVolatility(ticker, strike): putChart = options.get_puts(ticker) csv = putChart.to_csv(ticker + '.csv') tickerDf = pd.read_csv(ticker + '.csv') oneRowDataframe = tickerDf.loc[tickerDf['Strike'] == strike] volatility = oneRowDataframe.iloc[0]['Implied Volatility'] return volatility
def update_options_list(self, option_type, strike, date): empty = { 'Last Trade Date': '', 'Strike': '', 'Last Price': '', 'Bid': '', 'Ask': '', 'Change': '', '% Change': '', 'Volume': '', 'Open Interest': '', 'Implied Volatility': '' } contract_name = option_naming(self.ticker, strike, date, option_type) orig_date = date if contract_name not in self.observed_options: #breakdown date string """ month_int = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November','December'] month_today = month_int.index(date[0:date.index(' ')])+1 date = date[date.index(' ')+1:] day_today = int(date[0:date.index(',')]) year_today = int(date[-4:]) strike_date_datetime = datetime.date(year_today, month_today, day_today) tod = datetime.date(year = datetime.datetime.today().year, month = datetime.datetime.today().month, day = datetime.datetime.today().day) years_to_maturity = (strike_date_datetime-tod).days/365 """ years_to_maturity = years_to_maturity_calc(date) #get implied volatility if option_type.lower() == 'call': df = options.get_calls(self.ticker, orig_date) else: df = options.get_puts(self.ticker, orig_date) iv = float(df.loc[df['Strike'] == strike]['Implied Volatility']. to_list()[0][0:-1].replace(',', '')) / 100 #calculate greeks grks = option_greeks(self.prices_today[-1], strike, years_to_maturity, iv, self.risk_free_rate)[option_type.lower()] #calculate prices price = round( option_price(self.prices_today[-1], strike, years_to_maturity, iv, self.risk_free_rate)[option_type.lower()], 2) opt = { 'Expir Date': orig_date, 'Strike Price': '${}'.format(strike) } opt['Value'] = '${}'.format(price) opt['Type'] = option_type opt['Implied Vol'] = '{}%'.format(np.round(iv * 100, 4)) opt.update(grks) self.observed_options[contract_name] = opt return self.observed_options
def find_spreads(ticker, date, spread_type, rr=None, pop=None): try: curr_price = math.floor(si.get_live_price(ticker)) if spread_type == 'cs': data = [] puts = options.get_puts(ticker, date) puts_filtered = puts[puts['Strike'] <= curr_price] for i in range(0, len(puts_filtered) - 1): for j in range(i + 1, len(puts_filtered)): calculate(spread_type, data, puts_filtered.iloc[i], puts_filtered.iloc[j]) df = pd.DataFrame(data, columns=[ 'Strike 1\n(LONG)', 'Strike 2\n(SHORT)', 'S1 Spread\nDiff', 'S2 Spread\nDiff', 'Net\nCredit', 'Max\nLoss', 'Max\nGain', 'Risk/Reward\nRatio', 'PoP\n(%)' ]) pd.set_option('display.max_rows', df.shape[0] + 1) if rr != None: df = df.loc[(df['Risk/Reward\nRatio'] >= float(rr))] if pop != None: df = df.loc[(df['PoP\n(%)'] >= float(pop))] # if rr == None and pop == None: # df = df.loc[(df['Risk/Reward Ratio'] >= .25) & (df['PoP (%)'] <= 99.99)] return 'No good credit spreads found. The optional filters (R/R & PoP) may be too strict' if df.empty else df # .sort_values(by='Risk/Reward', ascending=False) elif spread_type == 'ds': data = [] calls = options.get_calls(ticker, date) calls_filtered = calls[calls['Strike'] >= curr_price] for i in range(0, len(calls_filtered) - 1): for j in range(i + 1, len(calls_filtered)): calculate(spread_type, data, calls_filtered.iloc[i], calls_filtered.iloc[j]) df = pd.DataFrame(data, columns=[ 'Strike 1\n(LONG)', 'Strike 2\n(SHORT)', 'S1 Spread\nDiff', 'S2 Spread\nDiff', 'Net\nDebit', 'Max\nLoss', 'Max\nGain', 'Risk/Reward\nRatio', 'PoP\n(%)' ]) pd.set_option('display.max_rows', df.shape[0] + 1) if rr != None: df = df.loc[(df['Risk/Reward\nRatio'] >= float(rr))] if pop != None: df = df.loc[(df['PoP\n(%)'] >= float(pop))] # if rr == None and pop == None: # df = df.loc[(df['Risk/Reward Ratio'] >= 2) & (df['PoP (%)'] >= 20)] return 'No good debit spreads found. The optional filters (R/R & PoP) may be too strict' if df.empty else df # .sort_values(by='Risk/Reward', ascending=False) else: return 'Not a valid spread type' except AssertionError: return 'Not a valid ticker symbol' except ValueError: return 'Not a valid contract expiration date'
def puts_chain(ticka): puts = pd.DataFrame() stock_expiry_cache[ticka] = friday() while (puts.empty): try: puts = opt.get_puts(ticka, stock_expiry_cache[ticka]) except: stock_expiry_cache[ticka] = stock_expiry_cache[ticka] + \ dt.timedelta(days=7) puts['profit'] = puts['Last Price'] / puts['Strike'] return puts
def get_chain(ticker, date=None, c_p='Call'): ''' Gets option chain from Yahoo Finance API Inputs: ticker: (str) Stock or ETF ticker symbol date: (str) Indicates maturity date for option (e.g: "2019-12-06") c_p: (str) Indicates call or put option Returns: Pandas DataFrame of option chain ''' cols = {'Implied Volatility': 'IV'} if c_p == 'Call': df = options.get_calls(ticker, date).rename(columns=cols) return df.set_index("Strike") if c_p == 'Put': df = options.get_puts(ticker, date).rename(columns=cols) return df.set_index("Strike")
def find_em(ticker, exp_date): sd = .6827 curr_price = round(si.get_live_price(ticker), 2) low = curr_price - (curr_price * (1 - sd)) high = curr_price + (curr_price * (1 - sd)) calls = options.get_calls(ticker, exp_date) calls = calls.loc[(calls['Strike'] >= low) & (calls['Strike'] <= high)] new_calls = calls['Implied Volatility'].str.replace(r'%', r'').astype('float') puts = options.get_puts(ticker, exp_date) puts = puts.loc[(puts['Strike'] >= low) & (puts['Strike'] <= high)] new_puts = puts['Implied Volatility'].str.replace(r'%', r'').astype('float') volatility = round((new_calls.mean() + new_puts.mean()) / 2, 2) d1 = datetime.today() d2 = datetime.strptime(exp_date, '%m/%d/%y') days_left = abs(d1 - d2).days + 1 em = round( si.get_live_price(ticker) * (volatility / 100) * math.sqrt(days_left / 365), 2) return 'Volatility: {}, Expected movement: -/+{}'.format(volatility, em)
def get_iv(symbol): price = si.get_live_price(symbol) df = options.get_puts(symbol) index_value = (df["Strike"] - price).apply(abs).idxmin() df_iv = df.loc[index_value, :] return df_iv["Implied Volatility"]
print('\n') pd.set_option('display.max_columns', None) # View all columns chain = options.get_options_chain( stock, 'August 20, 2021') # Give all options that expire before a particular date #print(chain) # All Options #print('\n') print('CALL Options: \n') print(chain['calls']) # CALL Options print('\n') print('PUT Options: \n') print(chain['puts']) # PUT Options print('\n') # Another way to get call and put options directly chain = options.get_calls(stock, 'August 20, 2021') #print(chain) # Strike value depends on Stock's price, so modify as per requirement. print('CALL Options: Strike <=150 \n') print(chain[chain['Strike'] <= 150] ) # Get all rows where strike price is less than 150 print('\n') chain = options.get_puts(stock, 'August 20, 2021') #print(chain) print('PUT Options: Strike <=150 \n') print(chain[chain['Strike'] <= 150] ) # Get all rows where strike price is less than 150 print('\n')
def getOptionsData(personalRiskTolerance, budget, printOutput = 'True'): ''' get the up to date stock options pareto. Currently hardcoded for the DOW stocks inputs: personalRiskTolerance - risk level - number between 0 and 0.9 budget - Number - larger than 2000 printOutput - bool to determine whether print statements show outputs: stockPareto DataFrame (all options within the budget) bestPick DataFrame (highest value return within risk tolerance) hardcoded: options date - 5/15/2020 stocks to pick from: All DOW stocks ''' # date selection today = datetime.today() optionsDate = datetime(2020,5,15) t = ((optionsDate - today).days + ((optionsDate - today).seconds/86400))/365 daysLeft = (optionsDate - today).days hoursLeft = int((optionsDate - today).seconds/3600) if printOutput: print('\nOptions will expire in approximately {} days and {} hours'.format(daysLeft,hoursLeft)) stockPareto = pd.DataFrame() if printOutput: print('Pulling stock data...\n') # initial data capture and processing for stock in stock_info.tickers_dow(): # checks if there is an option during the particular week. try: individualOptionsData = options.get_puts(stock,date=optionsDate) # capture stock, current price for each stock individualOptionsData['Stock Name'] = stock individualOptionsData['Current Price'] = stock_info.get_live_price(stock) # IV formatting to a number individualOptionsData['IV']= individualOptionsData['Implied Volatility'].str.slice_replace(-1,repl='').astype(float)/100 # if not, skip the ticker except: if printOutput: print('No data from {}'.format(stock)) continue # if successful at obtaining options data, fill DataFrame stockPareto with the values stockPareto = stockPareto.append(individualOptionsData) if printOutput: print('Data from {} collected'.format(stock)) if printOutput: print('Data Capture Complete!') # bool logic to make sure options are worth investing in beingTraded = stockPareto['Volume'] != '-' asksExist = stockPareto['Ask'] != '-' bidsExist = stockPareto['Bid'] != '-' # filtering by bool logic stockPareto = stockPareto[beingTraded & asksExist & bidsExist] #################################################### ### formatting of key variables in the DataFrame ### #################################################### # POP derived from Black-Scholes model stockPareto['POP'] = 100*stats.norm.cdf((np.log(stockPareto['Current Price'] / stockPareto['Strike'] ) + ( (stockPareto['IV']**2) /2)*t) / (stockPareto['IV']*np.sqrt(t))) stockPareto['Strike'] = stockPareto['Strike'].astype(float) stockPareto['Bid'] = stockPareto['Bid'].astype(float) stockPareto['Ask'] = stockPareto['Ask'].astype(float) # determine number of each contract that is in budget # potential gain is the average contract selling price ~ (bid / ask) * 100 # potential gain multiple contracts - potential gain * number of contracts that can be sold within budget stockPareto['contractsInBudget'] = np.floor(budget/(stockPareto['Strike']*100)) stockPareto['Potential Gain'] = ((stockPareto['Ask'] + stockPareto['Bid'])/2) * 100 stockPareto['Potential Gain Multiple Contracts'] = stockPareto['Potential Gain'] * stockPareto['contractsInBudget'] ########################### ### plotting the pareto ### ########################### inBudget = stockPareto['contractsInBudget'] > 0 isInteresting = stockPareto['Bid'] != 0 stockPareto = stockPareto[inBudget & isInteresting] stockPareto = stockPareto.set_index('Contract Name') # this is the field which will show in the interactive plot stockPareto['printString'] = ('Stock: ' + stockPareto['Stock Name']+'\n' 'Strike Price = $'+ round(stockPareto['Strike'],2).astype(str)+'\n'+ 'Current Price = $' + round(stockPareto['Current Price'],2).astype(str) + '\n' + 'Potential Gain = $'+ round(stockPareto['Potential Gain Multiple Contracts'],2).astype(str)+'\n' + 'ROI = ' + round(((stockPareto['Potential Gain Multiple Contracts']/budget) * 100),2).astype(str) + '%\n' + 'Probability of Profit = ' + round(stockPareto['POP'],2).astype(str)) #################### ## Best Fit Logic ## #################### notBelowRisk = stockPareto['POP'] > (personalRiskTolerance*100) bestPick = stockPareto[notBelowRisk].sort_values(by='Potential Gain Multiple Contracts',ascending = False) bestPick = bestPick.loc[bestPick['Potential Gain Multiple Contracts'].idxmax()] if printOutput: print('The best OPTION is:') print(bestPick) return stockPareto, bestPick
async def on_message(message): print(message.content) if message.content.find("!") != -1: content = message.content.strip('!').lower().split() print(content) print(content[0]) if content[0] == "day": if content[1] == "gain": await message.channel.send( si.get_day_gainers().head(10).iloc[:, :3]) await message.channel.send( "-------------------------------------------") await message.channel.send( si.get_day_gainers().head(10).iloc[:, 4:7]) elif content[1] == "lose": await message.channel.send( si.get_day_losers().head(10).iloc[:, :3]) await message.channel.send( "-------------------------------------------") await message.channel.send( si.get_day_losers().head(10).iloc[:, 4:7]) elif content[1] == "active": await message.channel.send( si.get_day_most_active().head(10).iloc[:, :3]) await message.channel.send( "-------------------------------------------") await message.channel.send( si.get_day_most_active().head(10).iloc[:, 4:7]) elif content[0] == "crypto": await message.channel.send(si.get_top_crypto().head(10).iloc[:, :3] ) await message.channel.send( "-------------------------------------------") await message.channel.send(si.get_top_crypto().head(10).iloc[:, 4:5]) elif content[0] == "help": embedVar = discord.Embed(title="List of functioning commands", description="", colour=0x00ff00) embedVar.add_field(name="\u200b", value="!tsla\n!day gain\n!day loss", inline=True) embedVar.add_field( name="\u200b", value="!calls tlsa 03/19/2021\n!puts tlsa 03/19/2021", inline=True) await message.channel.send(embed=embedVar) elif content[0] == "calls": await message.channel.send( op.get_calls(content[1], content[2]).iloc[:, 2:8]) elif content[0] == "puts": await message.channel.send( op.get_puts(content[1], content[2]).iloc[:, 2:8]) else: temp = si.get_quote_table(content[0]) change = round(temp["Quote Price"] - temp["Previous Close"], 2) percentage = round(change / temp["Previous Close"] * 100, 2) displayQuote = str(round(temp["Quote Price"], 2)) displayChange = str(change) displayPercentage = str(percentage) displayTicker = content[0].upper() displayClose = str(round(temp["Previous Close"], 2)) dayRange = temp["Day's Range"].replace('-', '').split() dayLow = dayRange[0] dayHigh = dayRange[1] open = temp["Open"] close = temp["Previous Close"] volume = str(round(temp["Volume"] / 1000000, 2)) volume = volume + "M" avgVolume = str(round(temp["Avg. Volume"] / 1000000, 2)) avgVolume = avgVolume + "M" bid = temp["Bid"] ask = temp["Ask"] if change >= 0: rgb = 0x00ff00 displayChange = "+" + displayChange displayPercentage = "+" + displayPercentage else: rgb = 0xff0000 embedVar = discord.Embed( title= f"${displayTicker}\n${displayQuote} {displayChange} ({displayPercentage}%)", description="", colour=rgb) embedVar.add_field( name="\u200b", value= f"High: {dayHigh}\nLow: {dayLow}\n\nAsk: {ask}\nBid: {bid}", inline=True) embedVar.add_field(name="\u200b", value=f"Open: {open}\nPrev.: {close}", inline=True) embedVar.add_field( name="\u200b", value=f"Volume: {volume}\nAvg. Vol.: {avgVolume}", inline=True) await message.channel.send(embed=embedVar)
# randomly select calls or puts random_option_type = random.choice(["Call", "Put"]) if (random_option_type == "Call"): # random OTM call strike price random_strike_price = round( random.uniform(current_price, current_price * 3)) + (random.randrange(0, 51, 50) / 100) try: option_chain = options.get_calls(random_ticker, date=random_date) except: pass else: #random OTM put strike price random_strike_price = round(random.uniform( 0, current_price)) + (random.randrange(0, 51, 50) / 100) try: option_chain = options.get_puts(random_ticker, date=random_date) except: pass # make number a multiple of 5 if it's not # print(str(random.randrange(0,round(si.get_live_price(random_ticker)/3)+1,1) + random.randrange(0, 96, 5)/10)) print("Ticker: {0}\n{1}: ${2} {3}, literally can't go t**s up".format( random_ticker, random_date, str(round(random_strike_price, 2)), random_option_type)) print("--- %s seconds ---" % (time.time() - start_time)) #print(option_chain) #for line in option_chain: #print(line)