def test_get_companies_per_sector_in_country(recorder): result = financedatabase_model.get_companies_per_sector_in_country( country="Georgia", mktcap="Small Cap", exclude_exchanges=True, ) recorder.capture(result)
def display_companies_per_sector_in_country( country: str, mktcap: str = "", exclude_exchanges: bool = True, export: str = "", raw: bool = False, max_sectors_to_display: int = 15, min_pct_to_display_sector: float = 0.015, ): """Display number of companies per sector in a specific country (and market cap). [Source: Finance Database] Parameters ---------- country: str Select country to get number of companies by each sector mktcap: str Select market cap of companies to consider from Small, Mid and Large exclude_exchanges : bool Exclude international exchanges export: str Format to export data as raw: bool Output all raw data max_sectors_to_display: int Maximum number of sectors to display min_pct_to_display_sector: float Minimum percentage to display sector """ companies_per_sector = financedatabase_model.get_companies_per_sector_in_country( country, mktcap, exclude_exchanges) companies_per_sector = dict( OrderedDict( sorted(companies_per_sector.items(), key=lambda t: t[1], reverse=True))) for key, value in companies_per_sector.copy().items(): if value == 0: del companies_per_sector[key] if not companies_per_sector: console.print("No companies found with these parameters!\n") return df = pd.DataFrame.from_dict(companies_per_sector, orient="index") df.index.name = "Sector" df.columns = ["Number of companies"] df["Number of companies"] = df["Number of companies"].astype(int) title = mktcap + " cap companies " if mktcap else "Companies " title += f"per sector in {country}" title += " excluding exchanges" if exclude_exchanges else " including exchanges" if raw: print_rich_table(df, headers=list(df.columns), show_index=True, title=title) else: colors = [ "b", "g", "r", "c", "m", "y", "k", "tab:blue", "tab:orange", "tab:gray", "lightcoral", "yellow", "saddlebrown", "lightblue", "olive", ] if len(companies_per_sector) > 1: total_num_companies = sum(companies_per_sector.values()) min_companies_to_represent = round(min_pct_to_display_sector * total_num_companies) filter_sectors_to_display = (np.array( list(companies_per_sector.values())) > min_companies_to_represent) if any(filter_sectors_to_display): if not all(filter_sectors_to_display): num_sectors_to_display = np.where( ~filter_sectors_to_display)[0][0] if num_sectors_to_display < max_sectors_to_display: max_sectors_to_display = num_sectors_to_display else: console.print( "The minimum threshold percentage specified is too high, thus it will be ignored." ) if len(companies_per_sector) > max_sectors_to_display: companies_per_sector_sliced = dict( list( companies_per_sector.items())[:max_sectors_to_display - 1]) companies_per_sector_sliced["Others"] = sum( dict( list(companies_per_sector.items()) [max_sectors_to_display - 1:]).values()) legend, values = zip(*companies_per_sector_sliced.items()) else: legend, values = zip(*companies_per_sector.items()) plt.subplots(figsize=plot_autoscale(), dpi=PLOT_DPI) plt.pie( values, labels=legend, colors=colors, wedgeprops={ "linewidth": 0.5, "edgecolor": "white" }, labeldistance=1.05, startangle=90, ) plt.title(title) plt.tight_layout() if gtff.USE_ION: plt.ion() plt.show() elif len(companies_per_sector) == 1: console.print( f"Only 1 sector found '{list(companies_per_sector.keys())[0]}'. No pie chart will be depicted." ) else: console.print("No sector found. No pie chart will be depicted.") console.print("") export_data( export, os.path.dirname(os.path.abspath(__file__)), "cps", df, )
def display_companies_per_sector_in_country( country: str, mktcap: str = "", exclude_exchanges: bool = True, export: str = "", raw: bool = False, max_sectors_to_display: int = 15, min_pct_to_display_sector: float = 0.015, external_axes: Optional[List[plt.Axes]] = None, ): """Display number of companies per sector in a specific country (and market cap). [Source: Finance Database] Parameters ---------- country: str Select country to get number of companies by each sector mktcap: str Select market cap of companies to consider from Small, Mid and Large exclude_exchanges : bool Exclude international exchanges export: str Format to export data as raw: bool Output all raw data max_sectors_to_display: int Maximum number of sectors to display min_pct_to_display_sector: float Minimum percentage to display sector external_axes : Optional[List[plt.Axes]], optional External axes (1 axis is expected in the list), by default None """ companies_per_sector = financedatabase_model.get_companies_per_sector_in_country( country, mktcap, exclude_exchanges) companies_per_sector = dict( OrderedDict( sorted(companies_per_sector.items(), key=lambda t: t[1], reverse=True))) for key, value in companies_per_sector.copy().items(): if value == 0: del companies_per_sector[key] if not companies_per_sector: console.print("No companies found with these parameters!\n") return df = pd.DataFrame.from_dict(companies_per_sector, orient="index") df.index.name = "Sector" df.columns = ["Number of companies"] df["Number of companies"] = df["Number of companies"].astype(int) title = mktcap + " cap companies " if mktcap else "Companies " title += f"in {country}\n" title += "excl. exchanges" if exclude_exchanges else " incl. exchanges" if raw: print_rich_table(df, headers=list(df.columns), show_index=True, title=title) else: colors = theme.get_colors() if len(companies_per_sector) > 1: total_num_companies = sum(companies_per_sector.values()) min_companies_to_represent = round(min_pct_to_display_sector * total_num_companies) filter_sectors_to_display = (np.array( list(companies_per_sector.values())) > min_companies_to_represent) if any(filter_sectors_to_display): if not all(filter_sectors_to_display): num_sectors_to_display = np.where( ~filter_sectors_to_display)[0][0] if num_sectors_to_display < max_sectors_to_display: max_sectors_to_display = num_sectors_to_display else: console.print( "The minimum threshold percentage specified is too high, thus it will be ignored." ) if len(companies_per_sector) > max_sectors_to_display: companies_per_sector_sliced = dict( list( companies_per_sector.items())[:max_sectors_to_display - 1]) companies_per_sector_sliced["Others"] = sum( dict( list(companies_per_sector.items()) [max_sectors_to_display - 1:]).values()) legend, values = zip(*companies_per_sector_sliced.items()) else: legend, values = zip(*companies_per_sector.items()) # 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]") return (ax, ) = external_axes plt.pie( values, labels=legend, colors=colors, wedgeprops={ "linewidth": 0.5, "edgecolor": "white" }, labeldistance=1.05, startangle=45, ) ax.set_title(title, fontsize=14) if not external_axes: theme.visualize_output() elif len(companies_per_sector) == 1: console.print( f"Only 1 sector found '{list(companies_per_sector.keys())[0]}'. No pie chart will be depicted." ) else: console.print("No sector found. No pie chart will be depicted.") console.print("") export_data( export, os.path.dirname(os.path.abspath(__file__)), "cps", df, )
def cps_command( country: str, mktcap: str = "", exclude_exchanges: bool = True, raw: bool = False, max_sectors_to_display: int = 15, min_pct_to_display_sector: float = 0.015, ): """Display number of companies per sector in a specific country (and market cap). [Source: Finance Database] Parameters ---------- country: str Select country to get number of companies by each sector mktcap: str Select market cap of companies to consider from Small, Mid and Large exclude_exchanges : bool Exclude international exchanges raw: bool Output all raw data max_sectors_to_display: int Maximum number of sectors to display min_pct_to_display_sector: float Minimum percentage to display sector external_axes : Optional[List[plt.Axes]], optional External axes (1 axis is expected in the list), by default None """ companies_per_sector = financedatabase_model.get_companies_per_sector_in_country( country, mktcap, exclude_exchanges ) companies_per_sector = dict( OrderedDict( sorted(companies_per_sector.items(), key=lambda t: t[1], reverse=True) ) ) for key, value in companies_per_sector.copy().items(): if value == 0: del companies_per_sector[key] if not companies_per_sector: raise Exception("No companies found with these parameters!\n") df = pd.DataFrame.from_dict(companies_per_sector, orient="index") df.index.name = "Sector" df.columns = ["Number of companies"] df["Number of companies"] = df["Number of companies"].astype(int) title = mktcap + " Cap Companies " if mktcap else "Companies " title += f"in {country}" title += " Excl. Exchanges" if exclude_exchanges else " incl. Exchanges" title = textwrap.fill(title, 40) title_plot = textwrap.indent(text=title, prefix="<br>") if raw: output = { "title": "Stocks - Sector and Industry Analysis", "description": f"{df}", } else: if len(companies_per_sector) > 1: total_num_companies = sum(companies_per_sector.values()) min_companies_to_represent = round( min_pct_to_display_sector * total_num_companies ) filter_sectors_to_display = ( np.array(list(companies_per_sector.values())) > min_companies_to_represent ) if any(filter_sectors_to_display): if not all(filter_sectors_to_display): num_sectors_to_display = np.where(~filter_sectors_to_display)[0][0] if num_sectors_to_display < max_sectors_to_display: max_sectors_to_display = num_sectors_to_display else: raise Exception( "The minimum threshold percentage specified is too high, thus it will be ignored." ) if len(companies_per_sector) > max_sectors_to_display: companies_per_sector_sliced = dict( list(companies_per_sector.items())[: max_sectors_to_display - 1] ) companies_per_sector_sliced["Others"] = sum( dict( list(companies_per_sector.items())[max_sectors_to_display - 1 :] ).values() ) legend, values = zip(*companies_per_sector_sliced.items()) else: legend, values = zip(*companies_per_sector.items()) fig = go.Figure() colors = [ "#ffed00", "#ef7d00", "#e4003a", "#c13246", "#822661", "#48277c", "#005ca9", "#00aaff", "#9b30d9", "#af005f", "#5f00af", "#af87ff", ] fig.add_trace( go.Pie( labels=legend, values=values, textinfo="label+percent", showlegend=False, ) ) fig.update_traces( textposition="outside", textfont_size=15, marker=dict( colors=colors, line=dict(color="#F5EFF3", width=0.8), ), ) if imps.PLT_WATERMARK: fig.add_layout_image(imps.PLT_WATERMARK) fig.update_layout( margin=dict(l=40, r=0, t=80, b=40), title=dict( text=title_plot, y=1, x=0.5, xanchor="center", yanchor="top", ), template=imps.PLT_CANDLE_STYLE_TEMPLATE, colorway=colors, font=imps.PLT_FONT, ) elif len(companies_per_sector) == 1: raise Exception( f"Only 1 sector found '{list(companies_per_sector.keys())[0]}'. No pie chart will be depicted." ) else: raise Exception("No sector found. No pie chart will be depicted.") imagefile = "sia_cps.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) output = { "title": "Stocks - Sector and Industry Analysis", "description": plt_link, "imagefile": imagefile, } return output