def test_get_stocks_data(mocker, recorder): target = "gamestonk_terminal.stocks.sector_industry_analysis.financedatabase_model.yf.utils.get_json" mocker.patch(target=target, return_value=YF_UTILS_GET_DICT) result = financedatabase_model.get_stocks_data( country="Georgia", sector="Industrials", industry="Conglomerates", marketcap="", exclude_exchanges=True, ) recorder.capture(result)
def display_bars_financials( finance_key: str, finance_metric: str, country: str, sector: str, industry: str, marketcap: str = "", exclude_exchanges: bool = True, limit: int = 10, export: str = "", raw: bool = False, already_loaded_stocks_data: Dict = None, ): """Display financials bars comparing sectors, industry, analysis, countries, market cap and excluding exchanges. Parameters ---------- finance_key: str Select finance key from Yahoo Finance(e.g. financialData, defaultKeyStatistics, summaryProfile) finance_metric: str Select finance metric from Yahoo Finance (e.g. operatingCashflow, revenueGrowth, ebitda, freeCashflow) country: str Search by country to find stocks matching the criteria. sector : str Search by sector to find stocks matching the criteria. industry : str Search by industry to find stocks matching the criteria. marketcap : str Select stocks based on the market cap. exclude_exchanges: bool When you wish to include different exchanges use this boolean. limit: int Limit amount of companies displayed export: str Format to export data as raw: bool Output all raw data already_loaded_stocks_data: Dict Dictionary of filtered stocks data that has been loaded before Returns ------- dict Dictionary of filtered stocks data list List of tickers filtered """ if already_loaded_stocks_data: stocks_data = already_loaded_stocks_data else: stocks_data = financedatabase_model.get_stocks_data( country, sector, industry, marketcap, exclude_exchanges) metric_data = {} for symbol in list(stocks_data.keys()): if finance_key in stocks_data[symbol] and "quoteType" in stocks_data[ symbol]: stock_name = stocks_data[symbol]["quoteType"]["longName"] metric = (stocks_data[symbol][finance_key][finance_metric] if stocks_data[symbol][finance_key] is not None and finance_metric in stocks_data[symbol][finance_key] else None) if metric and stock_name: metric_data[stock_name] = (metric, symbol) if len(metric_data) > 1: metric_data = dict( OrderedDict( sorted(metric_data.items(), key=lambda t: t[1][0], reverse=True))) company_names = list() company_metrics = list() company_tickers = list() for name, metric in metric_data.items(): company_names.append(name) company_metrics.append(metric[0]) company_tickers.append(metric[1]) metric_finance_col = ("".join( " " + char if char.isupper() else char.strip() for char in finance_metric).strip().capitalize()) df_all = pd.DataFrame({ "Company": company_names, metric_finance_col: company_metrics }) if len(df_all) > limit: console.print( f"Limiting the amount of companies displayed to {limit}.") company_name = np.array(company_names)[:limit] company_metric = np.array(company_metrics)[:limit] company_ticker = np.array(company_tickers)[:limit] df = df_all.head(limit) if raw: print_rich_table(df, headers=list(df.columns), show_index=False, title="Bars Financials") else: plt.subplots(figsize=plot_autoscale(), dpi=PLOT_DPI) magnitude = 0 while max(company_metric) > 1_000 or abs( min(company_metric)) > 1_000: company_metric = np.divide(company_metric, 1_000) magnitude += 1 # check if the value is a percentage if ((magnitude == 0) and all(company_metric >= 0) and all(company_metric <= 1)): unit = "%" company_metric = company_metric * 100 else: unit = " KMBTP"[magnitude] for name, metric, ticker in zip(company_name[::-1], company_metric[::-1], company_ticker[::-1]): if len(name.split(" ")) > 6 and len(name) > 40: name = f'{" ".join(name.split(" ")[:4])}\n{" ".join(name.split(" ")[4:])}' plt.barh(name, metric, label=ticker) handles, _ = plt.gca().get_legend_handles_labels() plt.legend(reversed(handles), reversed(company_ticker[::-1]), loc="lower right") metric_title = ("".join( " " + char if char.isupper() else char.strip() for char in finance_metric).strip().capitalize()) benchmark = np.median(company_metric) plt.axvline(x=benchmark, lw=3, ls="--", c="k") if unit != " ": units = f" [{unit}] " else: units = " " title = f"{metric_title.capitalize()}{units}with benchmark of {benchmark:.2f} {unit}\n" title += marketcap + " cap companies " if marketcap else "Companies " if industry: title += f"in {industry} industry\n" elif sector: title += f"in {sector} sector\n" if country: title += f"in {country}" title += " " if (industry or sector) else "\n" title += ("(excluding data from international exchanges)" if exclude_exchanges else "(including data from international exchanges)") plt.title(title) if gtff.USE_ION: plt.ion() plt.tight_layout() plt.show() export_data( export, os.path.dirname(os.path.abspath(__file__)), finance_metric, df_all, ) if not export: console.print("") return stocks_data, company_tickers
def display_bars_financials( finance_key: str, finance_metric: str, country: str, sector: str, industry: str, marketcap: str = "", exclude_exchanges: bool = True, limit: int = 10, export: str = "", raw: bool = False, already_loaded_stocks_data: Dict = None, external_axes: Optional[List[plt.Axes]] = None, ): """Display financials bars comparing sectors, industry, analysis, countries, market cap and excluding exchanges. Parameters ---------- finance_key: str Select finance key from Yahoo Finance(e.g. financialData, defaultKeyStatistics, summaryProfile) finance_metric: str Select finance metric from Yahoo Finance (e.g. operatingCashflow, revenueGrowth, ebitda, freeCashflow) country: str Search by country to find stocks matching the criteria. sector : str Search by sector to find stocks matching the criteria. industry : str Search by industry to find stocks matching the criteria. marketcap : str Select stocks based on the market cap. exclude_exchanges: bool When you wish to include different exchanges use this boolean. limit: int Limit amount of companies displayed export: str Format to export data as raw: bool Output all raw data already_loaded_stocks_data: Dict Dictionary of filtered stocks data that has been loaded before external_axes : Optional[List[plt.Axes]], optional External axes (1 axis is expected in the list), by default None Returns ------- dict Dictionary of filtered stocks data list List of tickers filtered """ if already_loaded_stocks_data: stocks_data = already_loaded_stocks_data else: stocks_data = financedatabase_model.get_stocks_data( country, sector, industry, marketcap, exclude_exchanges) metric_data = {} for symbol in list(stocks_data.keys()): if finance_key in stocks_data[symbol] and "quoteType" in stocks_data[ symbol]: stock_name = stocks_data[symbol]["quoteType"]["longName"] metric = (stocks_data[symbol][finance_key][finance_metric] if stocks_data[symbol][finance_key] is not None and finance_metric in stocks_data[symbol][finance_key] else None) if metric and stock_name: metric_data[stock_name] = (metric, symbol) if len(metric_data) > 1: metric_data = dict( OrderedDict( sorted(metric_data.items(), key=lambda t: t[1][0], reverse=True))) company_names = list() company_metrics = list() company_tickers = list() for name, metric in metric_data.items(): company_names.append(name) company_metrics.append(metric[0]) company_tickers.append(metric[1]) metric_finance_col = ("".join( " " + char if char.isupper() else char.strip() for char in finance_metric).strip().capitalize()) df_all = pd.DataFrame({ "Company": company_names, metric_finance_col: company_metrics }) if len(df_all) > limit: console.print( f"Limiting the amount of companies displayed to {limit}.") company_name = np.array(company_names)[:limit] company_metric = np.array(company_metrics)[:limit] company_ticker = np.array(company_tickers)[:limit] df = df_all.head(limit) if raw: print_rich_table(df, headers=list(df.columns), show_index=False, title="Bars Financials") else: # This plot has 1 axis if not external_axes: _, ax = plt.subplots(figsize=plot_autoscale(), dpi=PLOT_DPI) else: if len(external_axes) != 1: logger.error("Expected list of one axis item.") console.print( "[red]Expected list of one axis item./n[/red]") # set returns statement to be compatible with others return dict(), list() (ax, ) = external_axes magnitude = 0 while max(company_metric) > 1_000 or abs( min(company_metric)) > 1_000: company_metric = np.divide(company_metric, 1_000) magnitude += 1 # check if the value is a percentage if ((magnitude == 0) and all(company_metric >= 0) and all(company_metric <= 1)): unit = "%" company_metric = company_metric * 100 else: unit = " KMBTP"[magnitude] if magnitude != 0 else "" colors = iter(theme.get_colors()) for name, metric, ticker in zip(company_name[::-1], company_metric[::-1], company_ticker[::-1]): if len(name.split(" ")) > 6 and len(name) > 40: name = f'{" ".join(name.split(" ")[:4])}\n{" ".join(name.split(" ")[4:])}' ax.barh(f"{name} ({ticker})", metric, label=ticker, color=next(colors)) metric_title = ("".join( " " + char if char.isupper() else char.strip() for char in finance_metric).strip().capitalize()) benchmark = np.median(company_metric) ax.axvline(x=benchmark, lw=3, ls="--", c="grey") title = f"The {metric_title.title()} (benchmark: {benchmark:.2f}{unit}) of " title += marketcap + " cap companies " if marketcap else "Companies " if industry: title += f"in {industry} industry " elif sector: title += f"in {sector} sector " if country: title += f"in {country}" title += " " if (industry or sector) else "" title += ("(excl. data from international exchanges)" if exclude_exchanges else "(incl. data from international exchanges)") ax.set_title(title, wrap=True, fontsize=11) labels = ax.get_xticks().tolist() ax.set_xticks(labels) ax.set_xticklabels([f"{label}{unit}" for label in labels]) theme.style_primary_axis(ax) if not external_axes: theme.visualize_output() export_data( export, os.path.dirname(os.path.abspath(__file__)), finance_metric, df_all, ) return stocks_data, company_tickers
def metric_command( finance_key: str, finance_metric: str, ticker: str = "", ): """Display financials bars comparing sectors, industry, analysis, countries, market cap and excluding exchanges. Parameters ---------- finance_key: str Select finance key from Yahoo Finance(e.g. financialData, defaultKeyStatistics, summaryProfile) finance_metric: str Select finance metric from Yahoo Finance (e.g. operatingCashflow, revenueGrowth, ebitda, freeCashflow) ticker: str Company ticker to use as the basis. """ logger.info("metrics") exclude_exchanges: bool = True limit: int = 10 ticker = ticker.lower() if ticker: data = yfinance.utils.get_json(f"https://finance.yahoo.com/quote/{ticker}") if "summaryProfile" in data: country = data["summaryProfile"]["country"] if country not in financedatabase_model.get_countries(): similar_cmd = difflib.get_close_matches( country, financedatabase_model.get_countries(), n=1, cutoff=0.7, ) if similar_cmd: country = similar_cmd[0] sector = data["summaryProfile"]["sector"] if sector not in financedatabase_model.get_sectors(): similar_cmd = difflib.get_close_matches( sector, financedatabase_model.get_sectors(), n=1, cutoff=0.7, ) if similar_cmd: sector = similar_cmd[0] industry = data["summaryProfile"]["industry"] if industry not in financedatabase_model.get_industries(): similar_cmd = difflib.get_close_matches( industry, financedatabase_model.get_industries(), n=1, cutoff=0.7, ) if similar_cmd: industry = similar_cmd[0] if "price" in data: mktcap = data["price"]["marketCap"] if mktcap < 2_000_000_000: mktcap = "Small" elif mktcap > 10_000_000_000: mktcap = "Large" else: mktcap = "Mid" stocks_data = financedatabase_model.get_stocks_data( country, sector, industry, mktcap, exclude_exchanges ) metric_data = {} for symbol in list(stocks_data.keys()): if finance_key in stocks_data[symbol] and "quoteType" in stocks_data[symbol]: stock_name = stocks_data[symbol]["quoteType"]["longName"] metric = ( stocks_data[symbol][finance_key][finance_metric] if stocks_data[symbol][finance_key] is not None and finance_metric in stocks_data[symbol][finance_key] else None ) if metric and stock_name: metric_data[stock_name] = (metric, symbol) if len(metric_data) > 1: metric_data = dict( OrderedDict( sorted(metric_data.items(), key=lambda t: t[1][0], reverse=True) ) ) company_names = list() company_metrics = list() company_tickers = list() for name, metric in metric_data.items(): company_names.append(name) company_metrics.append(metric[0]) company_tickers.append(metric[1]) company_name = np.array(company_names)[:limit] company_metric = np.array(company_metrics)[:limit] company_ticker = np.array(company_tickers)[:limit] magnitude = 0 while max(company_metric) > 1_000 or abs(min(company_metric)) > 1_000: company_metric = np.divide(company_metric, 1_000) magnitude += 1 # check if the value is a percentage if (magnitude == 0) and all(company_metric >= 0) and all(company_metric <= 1): unit = "%" company_metric = company_metric * 100 else: unit = " KMBTP"[magnitude] colors = [ "#ffed00", "#ef7d00", "#e4003a", "#c13246", "#822661", "#48277c", "#005ca9", "#00aaff", "#9b30d9", "#af005f", "#5f00af", "#af87ff", ] fig = go.Figure() i = 0 for name, metric, tickers in zip( company_name[::-1], company_metric[::-1], company_ticker[::-1] ): if len(name.split(" ")) > 6 and len(name) > 40: name = ( f'{" ".join(name.split(" ")[:4])}\n{" ".join(name.split(" ")[4:])}' ) df_name = [] df_metric = [] df_tickers = [] df_name.append(name) df_metric.append(metric) df_tickers.append(tickers) fig.add_trace( go.Bar( name=tickers, y=[name], x=[metric], orientation="h", marker=dict( color=colors[i], line=dict(color="rgb(248, 248, 249)", width=1), ), ), ) i += 1 metric_title = ( "".join( " " + char if char.isupper() else char.strip() for char in finance_metric ) .strip() .capitalize() ) benchmark = np.median(company_metric) if unit != " ": units = f" [{unit}] " else: units = " " title = f"{metric_title.capitalize()}{units}with benchmark of {benchmark:.2f} {unit}<br>" title += mktcap + " cap companies " if mktcap else "Companies " if industry: title += f"in {industry} industry<br>" elif sector: title += f"in {sector} sector<br>" if country: title += f"in {country}" title += " " if (industry or sector) else "<br>" title += ( "(excl. data from international exchanges)" if exclude_exchanges else "(incl. data from international exchanges)" ) fig.add_vline( x=benchmark, fillcolor="grey", opacity=1, layer="below", line_width=3, line=dict(color="grey", dash="dash"), ) if imps.PLT_WATERMARK: fig.add_layout_image(imps.PLT_WATERMARK) fig.update_layout( margin=dict(l=40, r=0, t=100, b=20), template=imps.PLT_CANDLE_STYLE_TEMPLATE, title=title, colorway=colors, font=imps.PLT_FONT, legend={"traceorder": "reversed"}, ) imagefile = "sia_metrics.png" # Check if interactive settings are enabled plt_link = "" if imps.INTERACTIVE: plt_link = imps.inter_chart(fig, imagefile, callback=False) fig.update_layout( width=800, height=500, ) imagefile = imps.image_border(imagefile, fig=fig) return { "title": "Stocks - Sector and Industry Analysis", "description": plt_link, "imagefile": imagefile, }