def get_sector_split(self) -> pd.DataFrame: """ Get sector distribution of portfolio w/ respect to weights """ query = yq.Ticker(self.summary['ticker'].to_list()) data = pd.DataFrame.from_dict(query.fund_sector_weightings) mult = np.array(data) * np.array(self.summary['weight'].transpose()) return pd.Series(mult.sum(axis=1), index=data.index)
def runMe(tickers, arg=None): if not tickers: output("No arguments passed") return tickers = tickers.split(",") totalPercentage = [] base_out_period = "{shortName} ({symbol}): {startdate:%Y-%m-%d} - {enddate:%Y-%m-%d}: {old_quote:.2f} - {regularMarketPrice} {currency} " base_out = "{shortName} ({symbol}): {regularMarketPrice} {currency} " for ticker in tickers: res = {} fticker, name = getTicker(ticker) if not fticker: fticker = ticker t = yahooquery.Ticker(fticker) res.update(t.summary_detail) price_info = t.price price_info_ticker = price_info.get(fticker) if isinstance(price_info_ticker, str): output(price_info_ticker) continue res.update(price_info_ticker) if arg: out = base_out_period history = t.history(arg, "1d") history_as_dict = history.to_dict() close = history_as_dict.get("close") close_keys = list(close.keys()) start_key = close_keys[0] end_key = close_keys[-1] start_info = close.get(start_key) end_info = close.get(end_key) res["startdate"] = start_key[1] res["enddate"] = end_key[1] res["old_quote"] = start_info percentage = (res.get("regularMarketPrice") - start_info) / start_info else: out = base_out percentage = res["regularMarketChangePercent"] percentage *= 100.0 out += formatPercentage(percentage) out = out.format(**res) output(out)
def get_ticker_info(symbol: str, logger: logging.Logger) -> yahooquery.Ticker: """Returns the ticker info :param symbol: stock ticker :type symbol: str :param logger: Logger object :type logger: logging.Logger :return: Ticker info :rtype: yahooquery.Ticker """ ticker = yahooquery.Ticker(symbol) return ticker
def get_all_ticker_info(tickers: str or list) -> pd.DataFrame: """ Extract fundamental information about assets :param tickers: string or list of strings with asset symbols :return: DataFrame with the assets and the following characteristics: currency, ticker and name """ query = yq.Ticker(tickers) currency = pd.DataFrame.from_dict(query.summary_detail).loc['currency', :] data = pd.DataFrame.from_dict( query.quote_type).loc[['symbol', 'exchange', 'shortName'], :] data = data.append(currency) data.rename(index={'shortName': 'name', 'symbol': 'ticker'}, inplace=True) return data.transpose()
def get_prev_trading_day_from(day=None, adjclose=False): ticker = yq.Ticker(TICKER) # go back in time to find previous trading day day = day - dt.timedelta(days=1) while not is_trading_day(day): day = day - dt.timedelta(days=1) data = ticker.history( start=day, end=day + dt.timedelta(days=1), period='1d') if day else ticker.history( period='5y') data = data['adjclose'].array[0] if adjclose else data return data, "SUCCESSFULLY RETRIEVED DATA FROM YAHOO\n"
def download_from_yahoo(self, symbols: list, chunk_size: int = None): """Get Yahoo fundamental data in batches, if necessary.""" # download stocks data in chunks and concatenate to large table chunk_size = len(symbols) if chunk_size is None else chunk_size df = pd.DataFrame() for i in range(0, len(symbols), chunk_size): symbol_chunk = symbols[i:i + chunk_size] tickers = yq.Ticker(symbols=symbol_chunk, asynchronous=True).all_modules chunk_df = pd.DataFrame(tickers).T df = pd.concat([df, chunk_df]) # unpack the dictionaries """['assetProfile', 'recommendationTrend', 'industryTrend', 'cashflowStatementHistory', 'indexTrend', 'defaultKeyStatistics', 'quoteType', 'fundOwnership', 'incomeStatementHistory', 'summaryDetail', 'insiderHolders', 'calendarEvents', 'upgradeDowngradeHistory', 'price', 'balanceSheetHistory', 'earningsTrend', 'secFilings', 'institutionOwnership', 'majorHoldersBreakdown', 'balanceSheetHistoryQuarterly', 'earningsHistory', 'esgScores', 'summaryProfile', 'netSharePurchaseActivity', 'insiderTransactions', 'sectorTrend', 'fundPerformance', 'incomeStatementHistoryQuarterly', 'financialData', 'cashflowStatementHistoryQuarterly', 'earnings', 'pageViews', 'fundProfile', 'topHoldings']""" packages = ['summaryProfile', 'summaryDetail', 'quoteType'] # packages = df.columns # for unpacking all # adding prefix to avoid duplicated label errors unpacking df = df.add_prefix("_") packages = ["_" + i for i in packages] # unpack dictionaries and concatenate to table df = self.unpack_dictionary_fundamental(df, packages) # deal with duplicates erase = ['maxAge', 'symbol'] try: df.drop(erase, axis='columns', inplace=True, errors='ignore') except AttributeError as e: log.info(f"Dataframe may be empty. {e}") raise log.info("Yahoo fundamentals downloaded") return df
def getAPIData(symbol, exchange): ex = "NS" if exchange == "NSE" else ( "BO" if exchange == "BSE" else "error") if ex == "error": print(f"{symbol}, {exchange}: Incorrect Exchange Provided") return ex print(colored(f"INFO: {symbol}.{exchange} Processing", "yellow")) ticker = yq.Ticker(f"{symbol}.{ex}") data = ticker.all_modules if data[f"{symbol}.{ex}"] == f"Quote not found for ticker symbol: {symbol}.{ex}": print(f"{symbol}, {exchange}: No match found") return data[f"{symbol}.{ex}"] print(colored(f"INFO: Found response", "yellow")) print(colored(f"INFO: Writing to file", "yellow")) with open(f"{self.path}/{symbol}.{ex}.json", "w") as file: file.write(json.dumps(data))
def getQuoteInfo(dataStore, live=False, period="1y", start=None, end=None, interval="1d"): #build ticker object ticker = yahooquery.Ticker([i["ticker"] for i in dataStore], formatted=True, asynchronous=True) # print("created ticker obj:", list(ticker.symbols), "base:", [i["ticker"] for i in dataStore]) # print("test info:", ticker.get_modules(["price", "summaryDetail"])) #get info and history myInfo = extractInfo(ticker, live=live) # print(myInfo) myHist = extractHistory(ticker, period=period, interval=interval, start=start, end=end) #merge info and history into dataStore (is a list) for i in dataStore: tickerName = i["ticker"] # print(myHist[tickerName]) # print(myInfo[tickerName]) i["data"] = { "history": myHist[tickerName], **(myInfo[tickerName]) }
def asset_profile(symb, attribute): """ Summary line. Extended description of function. Parameters: arg1 (int): Description of arg1 Returns: int: Description of return value """ ticker = yq.Ticker(symb) profile = getattr(ticker, attribute) profile = profile[symb] return profile
def __init__(self, ticker): self.ticker = ticker self.tickerData = yq.Ticker(ticker) #Or error (fix for github version) url = "https://query2.finance.yahoo.com/v10/finance/quoteSummary/" + self.ticker + "?modules=financialData&formatted=false&lang=en-US®ion=US&corsDomain=finance.yahoo.com" try: urllib2.urlopen(url, timeout=2) self.current_price = self.tickerData.financial_data[ticker][ "currentPrice"] except HTTPError as err: self.current_price = si.get_live_price(self.ticker) except Exception as e: print("error", e) self.current_price = self.tickerData.financial_data[ticker][ "currentPrice"] if ticker == "^GSPC" or ticker == "vusa.l": self.company_name = "S&P" else: stock_quote_type = self.tickerData.quote_type[ticker] self.company_name = stock_quote_type["longName"] #Get Earnings date url = "https://query2.finance.yahoo.com/v10/finance/quoteSummary/" + self.ticker + "?modules=calendarEvents&formatted=false&lang=en-US®ion=US&corsDomain=finance.yahoo.com" next_earning_date = 0 try: urllib2.urlopen(url, timeout=4) earnings_date_array = self.tickerData.calendar_events[ self.ticker]["earnings"]["earningsDate"] for earnings_date in earnings_date_array: date = dt1.utcfromtimestamp(earnings_date) if date > dt1.today(): next_earning_date = date break except HTTPError as err: print(err) self.next_earning_date = next_earning_date
def query_prices(stocks, periods): """ stocks : list Tickers from stocks to analyze. periods : str period interesting for analysis: 1y, 2y, 5y, 10y, max Returns DataFrame with daily adjusted prices of stocks parsed. """ df = pd.DataFrame() stocks.insert(0, '^BVSP') # market benchmark index for i, stock in enumerate(stocks): singular_stock = yq.Ticker(stock) df_singular = singular_stock.history(period=periods)['adjclose'] df_singular = df_singular.reset_index() df_singular = df_singular.rename(columns={'adjclose': stock}) df_singular = df_singular.drop(columns='symbol') if i == 0: df = df_singular else: df = pd.merge(df, df_singular, on='date') stock_prices = df.set_index('date') return stock_prices
def plot_reddit_occurences_price(stk_symb, search_term): print(f"\n\n\n\n\n\nCounting occurences of {search_term}") # count the occurences of our stock symbol in r/all and load the into dictionaries # {key:value} = {day:frequency} n_sub_title, n_sub_body, n_sub_title_com_body, n_sub_body_com_body, n_any_com_body = count_occurences( search_term) # Let's consolidate these into a big tuple so we can get the earliest mention of a stock symbol concisely all_occurences = (n_sub_title, n_sub_body, n_sub_title_com_body, n_sub_body_com_body, n_any_com_body) start_date = get_start_date(all_occurences) # get the earliest mention end_date = dt.now().date().__str__( ) # max(max(n_sub_body.keys()), max(n_sub_title.keys())) # I like to set the end date to today rather than the last mention so that I can see the longer term behaviour of the price print(start_date) print(end_date) stk = yq.Ticker(stk_symb, status_forcelist=[404, 429, 500, 502, 503, 504]) print("Retrieving Stock History") price_history = stk.history(start=start_date, end=end_date) print(price_history) mean_close = np.mean(price_history['close']) dates = [d for d in daterange(parse(start_date), parse(end_date))] frequency_imputer = lambda occurence_dict, dates: [ 0 if (d.date().__str__() not in occurence_dict.keys()) else occurence_dict[d.date().__str__()] for d in dates ] body_plot = frequency_imputer(n_sub_body, dates) title_plot = frequency_imputer(n_sub_title, dates) title_com_plot = frequency_imputer(n_sub_title_com_body, dates) body_com_plot = frequency_imputer(n_sub_body_com_body, dates) price_imputer = lambda history, dates: [ None if (d.date() not in history.index.get_level_values("date"). to_list()) else history.loc[history.index.get_level_values( 'date') == d.date(), 'close'] for d in dates ] price_history_plot = price_imputer(price_history, dates) plt.figure(figsize=(15, 5)) plt.subplot(2, 1, 1) plt.plot(range(len(dates)), body_plot, label="Occurences in body of submission") plt.plot(range(len(dates)), title_plot, label="Occurences in title of submission") plt.plot(range(len(dates)), body_com_plot, label="Occurences in body of comments if in submission title") plt.plot(range(len(dates)), title_com_plot, label="Occurences in body of comments if in submission body") plt.subplot(2, 1, 2) plt.plot(range(len(dates)), price_history_plot, label="Closing Price") # plt.plot(range(len(dates)),np.ones(len(dates))*mean_close, label="Mean Close") plt.title(f"Frequency of {stk_symb} in r/all") plt.xticks(ticks=range(len(dates)), labels=list(map(lambda x: x.date(), dates)), rotation=70) # plt.grid() plt.legend() plt.show()
def get_data(): t = yq.Ticker('SABR') data = t.history(period='5y') return data['adjclose'].to_numpy()
# # Prove per il plotting scatter con selettori # Importa altair pandas streamlit, pandas_datareader # In[410]: import altair as alt import pandas as pd import streamlit as st import pandas_datareader as pdr import numpy as np import yahooquery as ya stock = ya.Ticker('VTI') # In[411]: from PIL import Image image = Image.open('Market.png') st.sidebar.image(image, use_column_width=True) image2 = Image.open('Striscia.png') st.image(image2, use_column_width=True) # In[412]:
def options_fetch(self, stock_quotes): max_pain = {} for stock in self.stock_tickers: max_pain[stock] = 0 query = yahooquery.Ticker([stock], asynchronous=True) options = query.option_chain expiration_dates = list(options.index.unique(level=1)) connection = sqlite3.connect(f'{self.cwd}\\Databases\\options.db') expiration = expiration_dates[0].to_pydatetime().date() """ Underlying theory behind why this is necessary Options open interest (and subsequently the total dollar value) is important because options are now the predominant driving force behind stock price movements since March of 2020. What I need to do here is calculate the value of options that are out of the money (which subsequently will change the stock price in that direction) and options that are in the money. We want to assume that the market makers who are selling these options will want to "pin" the stock price to the point where they will profit the most. How do I determine this? A large options volume can be a hedge fund trader that is trying to move a stock in the short-term, in which case volume is very important to track throughout the day. However, I will assume that the vast financial resources in institutions is going to eventually push the stock price to the price where the most options contracts will expire. """ call_df = pd.read_sql( f'select * from "{stock} Calls {expiration}"', con=connection).set_index('strike') for index, row in call_df.copy().iterrows(): call_df.at[index, 'max_pain'] = row['openInterest'] * row['lastPrice'] put_df = pd.read_sql(f'select * from "{stock} Puts {expiration}"', con=connection).set_index('strike') for index, row in put_df.copy().iterrows(): put_df.at[index, 'max_pain'] = row['openInterest'] * row['lastPrice'] reduced_df = call_df['max_pain'].add(put_df['max_pain'], fill_value=0) numerator = 0 denominator = 0 for index, row in reduced_df.iteritems(): numerator += row * index denominator += row max_pain_strike = numerator / denominator max_pain[stock] = round(max_pain_strike, 2) # look at options pinning put_df_stddev = put_df['openInterest'].std() call_df_stddev = call_df['openInterest'].std() # pick out the strikes that are actually being actively traded (which should mean a greater chance of an # effect on price movement i.e. if a particular strike is being traded, then there may be an underlying # position that is purchased or short sold based on that options trade) put_df = put_df.loc[put_df['volume'] >= 10] put_df = put_df.loc[put_df['openInterest'] >= put_df_stddev] call_df = call_df.loc[call_df['volume'] >= 10] call_df = call_df.loc[call_df['openInterest'] >= call_df_stddev] put_momentum = put_df.loc[put_df['volume'] >= ( put_df['openInterest'] * .75)] call_momentum = call_df.loc[call_df['volume'] >= ( call_df['openInterest'] * .75)] print(stock, put_momentum) print(stock, call_momentum) # need to process these dataframes further before we return them # work in progress return max_pain
def get_symbol(symbol): getDetails = yahooquery.Ticker(symbol) longName = (getDetails.price.get(symbol).get('longName')) # print(getDetails.price.get(symbol).get('longName')) return longName
def option_analysis(self): connection = sqlite3.connect(f'{self.cwd}\\Databases\\options.db') cursor = connection.cursor() change_in_options_volume = {} for stock in self.stock_tickers: query = yahooquery.Ticker([stock], asynchronous=True) options = query.option_chain expiration_dates = list(options.index.unique(level=1)) cursor.execute(f'select * from timestamp where stock = (?)', (stock, )) timestamps = cursor.fetchall() print(timestamps) # we need to analyze the change in options, do it in about 5 minutes increments because these are expensive # calculations that shouldnt be ran every 30 seconds for example # once we have done this, replace the options chains and timestamps in the existing options.db for element in cursor.fetchall(): time = dt.datetime.strptime(element[1], "%Y-%m-%d %H:%M:%S.%f") if time + dt.timedelta(minutes=5) < dt.datetime.now(): change_in_options_volume[stock] = [] for date in expiration_dates: dictionary_of_options_volume = { 'calls': [], 'puts': [] } expiration = date.to_pydatetime().date() exp_time = dt.datetime.combine(expiration, dt.time(15, 0)) time_diff = exp_time - dt.datetime.now() if time_diff.days < 0: continue days_till_expiration = round( time_diff.total_seconds() / 86400, 2) if days_till_expiration > 60: break options_chain = options.loc[stock, date] # new and updated options chains new_call_table = options_chain.loc['calls'] new_put_table = options_chain.loc['puts'] # old options chain in the database old_call_table = pd.read_sql( f'select * from "{stock} Calls {expiration}"', con=connection).set_index('strike') old_put_table = pd.read_sql( f'select * from "{stock} Puts {expiration}"', con=connection).set_index('strike') for index, row in new_call_table.iterrows(): strike = row['strike'] change_in_volume = row[ 'volume'] - old_call_table.loc[strike]['volume'] change_in_price = row[ 'lastPrice'] - old_call_table.loc[strike][ 'lastPrice'] if change_in_volume != 0: # if volume increase and price goes down, we can assume investors are bailing from # this strike, if volume increase and price goes up, we can assume movement into # the specific strike dictionary_of_options_volume['calls'].append([ strike, change_in_volume, change_in_price ]) for index, row in new_put_table.iterrows(): strike = row['strike'] change_in_volume = row[ 'volume'] - old_put_table.loc[strike]['volume'] change_in_price = row[ 'lastPrice'] - old_put_table.loc[strike][ 'lastPrice'] if change_in_volume != 0: dictionary_of_options_volume['puts'].append([ strike, change_in_volume, change_in_price ]) print(dictionary_of_options_volume) change_in_options_volume[stock].append( dictionary_of_options_volume) # out of the loops # begin analysis of the change in options volume return change_in_options_volume
def performance_analysis(historical_equity_prices, streamlined_equities={}, selection=None, historical_index_prices=None, market_index=None): '''Returns key financial data for a specified stocks/equities. Calculates KPIs including returns, variances/volatilities, betas and makes predictions on future performance via the Capital Asset Pricing Model.''' names = {'^FTSE':'FTSE100 close', '^FTMC':'FTSE250 close', '^FTAI':'FTSEAIM close', '^GSPC':'S&P500 close', '^IXIC':'NASDAQ close', '^GDAXI':'DAX close'} def market_performance(index=None): '''Obtains key financial data for a specified market index including annualised returns and variances.''' try: # Obtain data from pre-defined index dataframe. df = df_indices[names[index]] one_yr_return = logarithmic_returns(df.iloc[-252:]) one_yr_annualised = one_yr_return.mean() * 252 one_yr_var = logarithmic_returns(df.iloc[-252:]).var() * 252 five_yr_return = logarithmic_returns(df.iloc[-1260:]) five_yr_annualised = five_yr_return.mean() * 252 five_yr_var = logarithmic_returns(df.iloc[-1260:]).var() * 252 ten_yr_return = logarithmic_returns(df.iloc[-2520:]) ten_yr_annualised = ten_yr_return.mean() * 252 ten_yr_var = logarithmic_returns(df.iloc[-2520:]).var() * 252 return one_yr_return, one_yr_annualised, one_yr_var, five_yr_return, five_yr_annualised, five_yr_var, ten_yr_return, ten_yr_annualised, ten_yr_var except: pricing = yf.Ticker(index).history(period='max')['Close'] one_yr_return = logarithmic_returns(pricing.iloc[-252:]) one_yr_annualised = one_yr_return.mean() * 250 one_yr_var = logarithmic_returns(pricing.iloc[-252:]).var() * 250 five_yr_return = logarithmic_returns(pricing.iloc[-1260:]) five_yr_annualised = five_yr_return.mean() * 250 five_yr_var = logarithmic_returns(pricing.iloc[-1260:]).var() * 250 ten_yr_return = logarithmic_returns(pricing.iloc[-2520:]) ten_yr_annualised = ten_yr_return.mean() * 250 ten_yr_var = logarithmic_returns(pricing.iloc[-2520:]).var() * 250 return one_yr_return, one_yr_annualised, one_yr_var, five_yr_return, five_yr_annualised, five_yr_var, ten_yr_return, ten_yr_annualised, ten_yr_var index_performance_holder = {'^FTSE':[], '^FTMC':[], '^FTAI':[], '^GSPC':[], '^IXIC':[], '^GDAXI':[], '^CMC200':[]} for key in index_performance_holder: index_performance_holder[key] = list(market_performance(key)) # Will store lists of financial/performance data for each equity. data = [] for key in streamlined_equities: if selection == 'tradeables': print('\nPerforming full historical analysis on tradeables:\n') else: # if selection == 'equities': print('\nPerforming full historical analysis on ' + names[key].split()[0] + ' stocks/securities:\n') # Obtain the appropriate market index data for each index. one_yr_return_market = index_performance_holder[key][0] one_yr_annualised_market = index_performance_holder[key][1] one_yr_var_market = index_performance_holder[key][2] five_yr_return_market = index_performance_holder[key][3] five_yr_annualised_market = index_performance_holder[key][4] five_yr_var_market = index_performance_holder[key][5] ten_yr_return_market = index_performance_holder[key][6] ten_yr_annualised_market = index_performance_holder[key][7] ten_yr_var_market = index_performance_holder[key][8] for equity in tqdm(streamlined_equities[key]): # 1. Obtaining general financial information about the company. # Create a Ticker object using that company's ticker. Using yahooquery as yf cannot provide info for many tickers. stock = yahooquery.Ticker(equity) # Historical price try: hist = historical_equity_prices[key][equity] except: if equity == 'SGLN.L': hist = yf.Ticker(equity).history(period='max')['Close'].apply(gbx_to_gbp) else: hist = yf.Ticker(equity).history(period='max')['Close'] # Ticker ticker = equity if selection == 'equities': try: name = index_components[key][['company', 'ticker']].set_index(['ticker']).to_dict()['company'][equity].upper() except: name = equity # Get names for tradeables. elif selection == 'tradeables': if equity == 'EQQQ.L': name = 'PowerShares EQQQ Nasdaq-100 UCITS ETF'.upper() else: try: name = yf.Ticker(equity).info['longName'].upper() except: name = yf.Ticker(equity).info['shortName'].upper() # Legal type if selection == 'tradeables': # Obtain the quotype of the instrument - ETF, CRYPTOCURRENCY, EQUITY etc. try: legal_type = yf.Ticker(equity).info['quoteType'] except: legal_type = 'MISC' else: legal_type = 'Equity' # Obtain the company sector. try: sector = stock.asset_profile[equity]['sector'] except: sector = 'N/A' # Obtain the latest closing price. try: close = stock.summary_detail[equity]['previousClose'] except: close = np.nan # Obtain the company's market capitalisation. try: market_cap = stock.summary_detail[equity]['marketCap'] except: market_cap = np.nan # Obtain the dividend rate. try: dividend = stock.summary_detail[equity]['dividendRate'] except: dividend = np.nan # Obtain the earnings quarterly growth. try: growth = stock.key_stats[equity]['earningsQuarterlyGrowth'] if growth == {}: growth = np.nan except: growth = np.nan # Obtain the foward price/earnings ratio (some companies do not have this data). try: forwardpe = stock.summary_detail[equity]['forwardPE'] if forwardpe == {}: forwardpe = np.nan except: forwardpe = np.nan # Obtain the trailing price/earnings ratio. try: trailingpe = stock.summary_detail[equity]['trailingPE'] except: trailingpe = np.nan # 2. BETA if legal_type == 'CRYPTOCURRENCY': one_yr_return_equity = logarithmic_returns(hist.iloc[-252:]) five_yr_return_equity = logarithmic_returns(hist.iloc[-1260:]) ten_yr_return_equity = logarithmic_returns(hist.iloc[-2520:]) # Approximate the beta as there is no real arket benchmark to compare the currencies to. beta_1, beta_5, beta_10 = (1, 1, 1) else: # Calculate the returns of the stock/tradeable over the last year. one_yr_return_equity = logarithmic_returns(hist.iloc[-252:]) # Calcualte the Beta of the stock/tradeable by calculating the covariance between the stock and the market, and the variance of the market. cov_with_market_1 = one_yr_return_equity.cov(one_yr_return_market) * 252 beta_1 = cov_with_market_1/one_yr_var_market # Calculate the returns of the stock/tradeable over the last year. five_yr_return_equity = logarithmic_returns(hist.iloc[-1260:]) # Calcualte the Beta of the stock/tradeable by calculating the covariance between the stock and the market, and the variance of the market. cov_with_market_5 = five_yr_return_equity.cov(five_yr_return_market) * 252 beta_5 = cov_with_market_5/five_yr_var_market # Calculate the returns of the stock/tradeable over the last year. ten_yr_return_equity = logarithmic_returns(hist.iloc[-2520:]) # Calcualte the Beta of the stock/tradeable by calculating the covariance between the stock and the market, and the variance of the market. cov_with_market_10 = ten_yr_return_equity.cov(ten_yr_return_market) * 252 beta_10 = cov_with_market_10/ten_yr_var_market # 3. Calculating the volatility of the returns. # Annualised returns and risk one_yr_annualised_equity = one_yr_return_equity.mean() * 252 one_yr_vol_equity = (stock_variance(logarithmic_returns(hist[-252:])) * 252) ** 0.5 five_yr_annualised_equity = five_yr_return_equity.mean() * 252 five_yr_vol_equity = (stock_variance(logarithmic_returns(hist[-1260:])) * 252) ** 0.5 ten_yr_annualised_equity = ten_yr_return_equity.mean() * 252 ten_yr_vol_equity = (stock_variance(logarithmic_returns(hist[-2520:])) * 252) ** 0.5 # 4. Predicting returns using the CAPM model. # CAPM expected returns one_yr_exp_return = 0.0008 + (beta_1 * 0.065) five_yr_exp_return = 0.0016 + (beta_5 * 0.065) ten_yr_exp_return = 0.0033 + (beta_10 * 0.065) # 5. Sharpe ratio. # Calculating Sharpe ratio sharpe_ratio_1 = (one_yr_exp_return - 0.001)/(one_yr_return_equity.std() * 252 ** 0.5) sharpe_ratio_5 = (five_yr_exp_return - 0.0031)/(five_yr_return_equity.std() * 252 ** 0.5) sharpe_ratio_10 = (ten_yr_exp_return - 0.0055)/(ten_yr_return_equity.std() * 252 ** 0.5) # 6. Obtaining final weighted scores for Beta, returns, volatility, expected returns and sharpe ratio. # Define the weights. Want greater bias towards 5yr and 10yr performances. weights = np.array([0.25, 0.375, 0.375]) # Weighted Beta betas = np.array([beta_1, beta_5, beta_10]) weighted_beta = np.dot(betas, weights.T) # Weighted Returns returns = np.array([one_yr_annualised_equity, five_yr_annualised_equity, ten_yr_annualised_equity]) weighted_return = np.dot(returns, weights.T) # Weighted Volatility volatilities = np.array([one_yr_vol_equity, five_yr_vol_equity, ten_yr_vol_equity]) weighted_volatility = np.dot(volatilities, weights.T) # Weighted Exp returns exp_returns = np.array([one_yr_exp_return, five_yr_exp_return, ten_yr_exp_return]) weighted_capm = np.dot(exp_returns, weights.T) # Weighted Sharpe Ratio sharpes = np.array([sharpe_ratio_1, sharpe_ratio_5, sharpe_ratio_10]) weighted_sharpe_ratio = np.dot(sharpes, weights.T) # 7. Collating all info. info = [ticker, name, legal_type, sector, key, close, market_cap, dividend, growth, forwardpe, trailingpe] info.extend([one_yr_annualised_equity, one_yr_vol_equity, beta_1, one_yr_exp_return, sharpe_ratio_1, five_yr_annualised_equity, five_yr_vol_equity, beta_5, five_yr_exp_return, sharpe_ratio_5, ten_yr_annualised_equity, ten_yr_vol_equity, beta_10, ten_yr_exp_return, sharpe_ratio_10, weighted_beta, weighted_return, weighted_volatility, weighted_capm, weighted_sharpe_ratio]) data.append(info) # 8. Collate all the information as a single dataframe. stocks = pd.DataFrame(data) stocks.columns = ['ticker', 'shortName', 'type','sector', 'index', 'close','marketCap','dividendRate', 'earningsQuarterlyGrowth', 'forwardPE', 'trailingPE', '1yr_return', '1yr_volatility', 'beta_1', '1yr_exp_return', 'sharpe_ratio_1', '5yr_return', '5yr_volatility', 'beta_5', '5yr_exp_return', 'sharpe_ratio_5', '10yr_return', '10yr_volatility', 'beta_10', '10yr_exp_return', 'sharpe_ratio_10', 'weighted_beta', 'weighted_annual_return', 'weighted_annual_volatility','weighted_capm', 'weighted_sharpe_ratio'] print("\nSuccessfully analysed the top performing stocks/securities from the indices provided.") time.sleep(3) return stocks
def main(): parser = argparse.ArgumentParser(description='scrap yahoo earning') parser.add_argument('-input_file', type=str, action='append', help='input file') parser.add_argument('-output', type=str, help='output file') parser.add_argument('-output_prefix', type=str, default='../stock_data/raw_daily_yahoo/yahoo_', help='prefix of the output file') parser.add_argument('-date', type=str, default=str(datetime.date.today()), help='Specify the date') args = parser.parse_args() if args.input_file == None: args.input_file = [ 'data_tickers/yahoo_indexes.csv', 'data_tickers/all_stocks.csv', 'data_tickers/all_etfs.csv' ] if args.output is None: filename = args.output_prefix + args.date + '.csv' else: filename = args.output # run input files df_input_list = [] for input_file in args.input_file: df_input_list.append(pd.read_csv(input_file)) df_input = pd.concat(df_input_list) ticker_list = df_input['Ticker'].to_list() columns = { 'price': { 'regularMarketOpen': 'Open', 'regularMarketDayHigh': 'High', 'regularMarketDayLow': 'Low', 'regularMarketPrice': 'Close', 'regularMarketVolume': 'Volume', 'regularMarketChange': 'Change', 'regularMarketChangePercent': 'ChangePercent', 'quoteType': 'Type', }, 'summary_detail': { 'marketCap': 'MarketCap', 'totalAssets': 'TotalAssets', 'navPrice': 'NAV', }, 'key_stats': { 'floatShares': 'SharesFloat', 'sharesOutstanding': 'SharesOutstanding', 'sharesShort': 'SharesShort', 'shortRatio': 'SharesShortRatio', 'shortPercentOfFloat': 'SharesShortPercentOfFloat', 'heldPercentInsiders': 'SharesInsidersPercent', 'heldPercentInstitutions': 'SharesInstitutionsPercent', 'beta': 'Beta' } } ticker_dict_list = [] print('number of tickers:', len(ticker_list)) for count, ticker in enumerate(ticker_list): print('downloading...', ticker, '-', count) try: yticker = yq.Ticker(ticker) ticker_dict = {} for module, module_dict in columns.items(): for ycol, col in module_dict.items(): ymodule = getattr(yticker, module) ticker_dict['Ticker'] = ticker if ycol in ymodule[ticker]: ticker_dict[col] = ymodule[ticker][ycol] ticker_dict_list.append(ticker_dict) except: print('Error, skip') time.sleep(scrap_delay) df = pd.DataFrame(ticker_dict_list) df['Date'] = args.date df.to_csv(filename)
def initial_options(self, stock): handle = ctypes.cdll.LoadLibrary( r"C:\Users\fabio\source\repos\CallPricingDll\CallPricingDll\x64\Release\CallPricingDll.dll" ) handle.CallPricing.argtypes = [ ctypes.c_float, ctypes.c_float, ctypes.c_float, ctypes.c_float, ctypes.c_float ] handle.CallPricing.restype = ctypes.c_double handle.PutPricing.argtypes = [ ctypes.c_float, ctypes.c_float, ctypes.c_float, ctypes.c_float, ctypes.c_float ] handle.PutPricing.restype = ctypes.c_double url = f"{self.cwd}\\Daily Stock Analysis\\Options\\{stock} Options Data {self.today.date()}.xlsx" wb = openpyxl.Workbook() wb.save(url) book = openpyxl.load_workbook(url) writer = pd.ExcelWriter(url, engine='openpyxl') writer.book = book writer.sheets = dict((ws.title, ws) for ws in book.worksheets) try: dividend = self.initial_data[stock][-1]['dividend'] spot = self.quote_data[stock][-1]['current price'] i = 0 query = yahooquery.Ticker([stock], asynchronous=True) options = query.option_chain expiration_dates = list(options.index.unique(level=1)) for date in expiration_dates: exp = date.to_pydatetime().date() # options expire at 3 o'clock CST exp_time = dt.datetime.combine(exp, dt.time(15, 0)) time_diff = exp_time - self.today if time_diff.days < 0: continue days_till_expiration = round(time_diff.total_seconds() / 86400, 2) if days_till_expiration > 90: continue sofr = self.bond_bootstrapper.sofr() ois_rate = self.bond_bootstrapper.overnightindexedswaps( days_till_expiration, sofr) options_chain = options.loc[stock, date] call_table = options_chain.loc['calls'] put_table = options_chain.loc['puts'] call_table = call_table.assign( option_value=0.00).set_index('strike') put_table = put_table.assign( option_value=0.00).set_index('strike') self.option_value[stock].append({ str(exp): { 'overvalued_call_options': 0, 'undervalued_call_options': 0, 'overvalued_put_options': 0, 'undervalued_put_options': 0 } }) ois_rate -= dividend # dividend should be factored in for index, row in call_table.iterrows(): # this means that there have been no trades over the past day if row['change'] == 0: continue sigma = round(float(row['impliedVolatility']), 6) strike = float(index) option_price = handle.CallPricing(spot, strike, ois_rate, days_till_expiration, sigma) call_table.at[index, 'option_value'] = round(option_price, 3) spread = (row['bid'] + row['ask']) / 2 call_table.at[index, 'lastPrice'] = spread if option_price > spread: self.option_value[stock][i][str( exp)]['undervalued_call_options'] += 1 if option_price < spread: self.option_value[stock][i][str( exp)]['overvalued_call_options'] += 1 for index, row in put_table.iterrows(): # this means that there have been no trades over the past day if row['change'] == 0: continue sigma = round(float(row['impliedVolatility']), 6) strike = float(index) option_price = handle.PutPricing(spot, strike, ois_rate, days_till_expiration, sigma) put_table.at[index, 'option_value'] = round(option_price, 3) spread = (row['bid'] + row['ask']) / 2 put_table.at[index, 'lastPrice'] = spread if option_price > spread: self.option_value[stock][i][str( exp)]['undervalued_put_options'] += 1 if option_price < spread: self.option_value[stock][i][str( exp)]['overvalued_put_options'] += 1 i += 1 connection = sqlite3.connect( f'{self.cwd}\\Databases\\options.db') call_table.to_sql(name=f'{stock} Calls {exp}', con=connection, if_exists='replace') put_table.to_sql(name=f'{stock} Puts {exp}', con=connection, if_exists='replace') cursor = connection.cursor() ts = dt.datetime.now() if 60 <= days_till_expiration <= 90: cursor.execute( "INSERT INTO timestamp (stock, time, expiration) VALUES(?, ?, ?)", (stock, ts, exp_time)) connection.commit() connection.close() # check to make sure we get nonzero values, we can get some weirdness after hours and close to expirations if not unique_cols(call_table['option_value']): call_table.to_excel(writer, sheet_name=f'{stock} Calls {exp}') logger.debug( f"Calls for {stock} expiring {exp} successfully outputted to Excel" ) else: logger.debug( f"Calls for {stock} expiring {exp} had no data to price options" ) if not unique_cols(put_table['option_value']): put_table.to_excel(writer, sheet_name=f'{stock} Puts {exp}') logger.debug( f"Puts for {stock} expiring {exp} successfully outputted to Excel" ) else: logger.debug( f"Puts for {stock} expiring {exp} had no data to price options" ) try: sheet = book['Sheet'] book.remove(sheet) except KeyError: pass except Exception as e: logger.debug(f"Exception occurred: {e}") finally: writer.save() writer.close() book.save(url) book.close() ExcelFormatting(file_path=url).formatting()