def display_performance( s_group: str, sort_col: str = "Name", ascending: bool = True, export: str = "", ): """View group (sectors, industry or country) performance data. [Source: Finviz] Parameters ---------- s_group : str group between sectors, industry or country sort_col : str Column to sort by ascending : bool Flag to sort in ascending order export : str Export data to csv,json,xlsx or png,jpg,pdf,svg file """ df_group = finviz_model.get_valuation_performance_data( s_group, "performance") df_group = df_group.rename( columns={ "Perf Week": "Week", "Perf Month": "Month", "Perf Quart": "3Month", "Perf Half": "6Month", "Perf Year": "1Year", "Perf YTD": "YTD", "Avg Volume": "AvgVolume", "Rel Volume": "RelVolume", }) df_group["Week"] = df_group["Week"].apply( lambda x: float(x.strip("%")) / 100) df_group = df_group.sort_values(by=sort_col, ascending=ascending) df_group["Volume"] = df_group["Volume"] / 1_000_000 df_group["AvgVolume"] = df_group["AvgVolume"] / 1_000_000 df_group = df_group.rename(columns={ "Volume": "Volume (1M)", "AvgVolume": "AvgVolume (1M)" }) print_rich_table( df_group.fillna(""), show_index=False, headers=df_group.columns, title="Group Performance Data", ) console.print("") export_data( export, os.path.dirname(os.path.abspath(__file__)), "performance", df_group, )
def view_group_data(s_group: str, data_type: str, export: str): """View group (sectors, industry or country) valuation/performance/spectrum data Parameters ---------- s_group : str group between sectors, industry or country data_type : str select data type to see data between valuation, performance and spectrum export : str Export data to csv,json,xlsx or png,jpg,pdf,svg file """ if data_type in ("valuation", "performance"): df_group = finviz_model.get_valuation_performance_data(s_group, data_type) if gtff.USE_TABULATE_DF: print( tabulate( df_group.fillna(""), showindex=False, floatfmt=".2f", headers=df_group.columns, tablefmt="fancy_grid", ) ) else: print(df_group.fillna("").to_string(index=False)) print("") export_data( export, os.path.dirname(os.path.abspath(__file__)), data_type, df_group, ) elif data_type == "spectrum": finviz_model.get_spectrum_data(s_group) print("") img = Image.open(s_group + ".jpg") plt.imshow(img) export_data( export, os.path.dirname(os.path.abspath(__file__)), "spectrum", ) img.show() else: print( "Invalid data type. Choose between valuation, performance and spectrum.\n" )
def display_valuation( s_group: str, sort_col: str = "Name", ascending: bool = True, export: str = "", ): """View group (sectors, industry or country) valuation data. [Source: Finviz] Parameters ---------- s_group : str group between sectors, industry or country sort_col : str Column to sort by ascending : bool Flag to sort in ascending order export : str Export data to csv,json,xlsx or png,jpg,pdf,svg file """ df_group = finviz_model.get_valuation_performance_data( s_group, "valuation") df_group["Market Cap"] = df_group["Market Cap"].apply( lambda x: float(x.strip("B"))) df_group.columns = [col.replace(" ", "") for col in df_group.columns] df_group = df_group.sort_values(by=sort_col, ascending=ascending) df_group["Volume"] = df_group["Volume"] / 1_000_000 df_group = df_group.rename(columns={"Volume": "Volume (1M)"}) if gtff.USE_TABULATE_DF: print( tabulate( df_group.fillna(""), showindex=False, headers=df_group.columns, tablefmt="fancy_grid", floatfmt=".2f", )) else: print(df_group.fillna("").to_string(index=False)) print("") export_data( export, os.path.dirname(os.path.abspath(__file__)), "valuation", df_group, )
def display_valuation( s_group: str, sort_col: str = "Name", ascending: bool = True, export: str = "", ): """View group (sectors, industry or country) valuation data. [Source: Finviz] Parameters ---------- s_group : str group between sectors, industry or country sort_col : str Column to sort by ascending : bool Flag to sort in ascending order export : str Export data to csv,json,xlsx or png,jpg,pdf,svg file """ df_group = finviz_model.get_valuation_performance_data( s_group, "valuation") df_group["Market Cap"] = df_group["Market Cap"].apply(lambda x: float( x.strip("B")) if x.endswith("B") else float(x.strip("M")) / 1000) df_group.columns = [col.replace(" ", "") for col in df_group.columns] df_group = df_group.sort_values(by=sort_col, ascending=ascending) df_group["Volume"] = df_group["Volume"] / 1_000_000 df_group = df_group.rename(columns={"Volume": "Volume (1M)"}) print_rich_table( df_group.fillna(""), show_index=False, headers=list(df_group.columns), title="Group Valuation Data", ) console.print() export_data( export, os.path.dirname(os.path.abspath(__file__)), "valuation", df_group, )
def test_get_valuation_performance_data(data_type, recorder): result_df = finviz_model.get_valuation_performance_data( group="Sector", data_type=data_type) recorder.capture(result_df)
async def valuation_command(ctx, economy_group="sector"): """Valuation of sectors, industry, country [Finviz]""" d_economy_group = { "sector": "Sector", "industry": "Industry", "basic_materials": "Industry (Basic Materials)", "communication_services": "Industry (Communication Services)", "consumer_cyclical": "Industry (Consumer Cyclical)", "consumer_defensive": "Industry (Consumer Defensive)", "energy": "Industry (Energy)", "financial": "Industry (Financial)", "healthcare": "Industry (Healthcare)", "industrials": "Industry (Industrials)", "real_estate": "Industry (Real Estate)", "technology": "Industry (Technology)", "utilities": "Industry (Utilities)", "country": "Country (U.S. listed stocks only)", "capitalization": "Capitalization", } try: # Debug user input if cfg.DEBUG: logger.debug("econ-valuation %s", economy_group) # Select default group if economy_group == "": if cfg.DEBUG: logger.debug("Use default economy_group: 'sector'") economy_group = "sector" # Check for argument possible_groups = list(d_economy_group.keys()) if economy_group not in possible_groups: raise Exception( f"Select a valid group from {', '.join(possible_groups)}" # nosec ) group = d_economy_group[economy_group] # Retrieve data df_group = finviz_model.get_valuation_performance_data( group, "valuation") # Check for argument if df_group.empty: raise Exception("No available data found") # Output data df = pd.DataFrame(df_group) df = df.replace(np.nan, 0) df = df.set_axis( [ "Name", "MarketCap", "P/E", "FwdP/E", "PEG", "P/S", "P/B", "P/C", "P/FCF", "EPSpast5Y", "EPSnext5Y", "Salespast5Y", "Change", "Volume", ], axis="columns", ) df["P/E"] = pd.to_numeric(df["P/E"].astype(float)) df["FwdP/E"] = pd.to_numeric(df["FwdP/E"].astype(float)) df["EPSpast5Y"] = pd.to_numeric(df["EPSpast5Y"].astype(float)) df["EPSnext5Y"] = pd.to_numeric(df["EPSnext5Y"].astype(float)) df["Salespast5Y"] = pd.to_numeric(df["Salespast5Y"].astype(float)) df["Volume"] = pd.to_numeric(df["Volume"].astype(float)) df["Volume"] = df["Volume"] / 1_000_000 formats = { "P/E": "{:.2f}", "FwdP/E": "{:.2f}", "EPSpast5Y": "{:.2f}", "EPSnext5Y": "{:.2f}", "Salespast5Y": "{:.2f}", "Change": "{:.2f}", "Volume": "{:.0f}M", } for col, value in formats.items(): df[col] = df[col].map(lambda x: value.format(x)) # pylint: disable=W0640 df = df.fillna("") df.set_index("Name", inplace=True) dindex = len(df.index) fig = df2img.plot_dataframe( df, fig_size=(1600, (40 + (50 * dindex))), col_width=[12, 5, 4, 4, 4, 4, 4, 4, 4, 6, 6, 6, 4, 4], tbl_cells=dict( align=["left", "center"], height=35, ), template="plotly_dark", font=dict( family="Consolas", size=20, ), paper_bgcolor="rgba(0, 0, 0, 0)", ) imagefile = "econ-valuation.png" df2img.save_dataframe(fig=fig, filename=imagefile) image = Image.open(imagefile) image = autocrop_image(image, 0) image.save(imagefile, "PNG", quality=100) image = disnake.File(imagefile) title = f"Economy: [Finviz] Valuation {group}" embed = disnake.Embed(title=title, colour=cfg.COLOR) embed.set_image(url=f"attachment://{imagefile}") embed.set_author( name=cfg.AUTHOR_NAME, icon_url=cfg.AUTHOR_ICON_URL, ) os.remove(imagefile) await ctx.send(embed=embed, file=image) except Exception as e: embed = disnake.Embed( title="ERROR Economy: [Finviz] Valuation", colour=cfg.COLOR, description=e, ) embed.set_author( name=cfg.AUTHOR_NAME, icon_url=cfg.AUTHOR_ICON_URL, ) await ctx.send(embed=embed, delete_after=30.0)
def performance_command(economy_group="sector"): """Performance of sectors, industry, country [Finviz]""" d_economy_group = { "sector": "Sector", "industry": "Industry", "basic_materials": "Industry (Basic Materials)", "communication_services": "Industry (Communication Services)", "consumer_cyclical": "Industry (Consumer Cyclical)", "consumer_defensive": "Industry (Consumer Defensive)", "energy": "Industry (Energy)", "financial": "Industry (Financial)", "healthcare": "Industry (Healthcare)", "industrials": "Industry (Industrials)", "real_estate": "Industry (Real Estate)", "technology": "Industry (Technology)", "utilities": "Industry (Utilities)", "country": "Country (U.S. listed stocks only)", "capitalization": "Capitalization", } # Debug user input if imps.DEBUG: logger.debug("econ-performance %s", economy_group) # Select default group if not economy_group: if imps.DEBUG: logger.debug("Use default economy_group: 'sector'") economy_group = "sector" # Check for argument possible_groups = list(d_economy_group.keys()) if economy_group not in possible_groups: possible_group_list = ", ".join(possible_groups) raise Exception(f"Select a valid group from {possible_group_list}") # nosec group = d_economy_group[economy_group] # Retrieve data df_group = finviz_model.get_valuation_performance_data(group, "performance") # Check for argument if df_group.empty: raise Exception("No available data found") # Output data df = pd.DataFrame(df_group) df["Volume"] = df["Volume"] / 1_000_000 df["Avg Volume"] = df["Avg Volume"] / 1_000_000 formats = { "Perf Month": "{:.2f}", "Perf Quart": "{:.2f}%", "Perf Half": "{:.2f}%", "Perf Year": "{:.2f}%", "Perf YTD": "{:.2f}%", "Avg Volume": "{:.0f}M", "Change": "{:.2f}%", "Volume": "{:.0f}M", } for col, value in formats.items(): df[col] = df[col].map(lambda x: value.format(x)) # pylint: disable=W0640 df = df.set_axis( [ "Name", "Week", "Month", "3 Mouth", "6 Mouth", "1 Year", "YTD", "Recom", "Avg Volume", "Rel Volume", "Change", "Volume", ], axis="columns", ) df.set_index("Name", inplace=True) df = df.fillna("-") df = df.applymap(lambda x: lambda_long_number_format(x, 2)) title = f"Economy: [WSJ] Performance {group}" dindex = len(df.index) if dindex > 2: embeds: list = [] # Output i, i2, end = 0, 0, 2 df_pg, embeds_img, images_list = pd.DataFrame(), [], [] while i < dindex: df_pg = df.iloc[i:end] df_pg.append(df_pg) fig = imps.plot_df( df_pg.transpose(), fig_size=(800, 720), col_width=[6, 10], tbl_header=imps.PLT_TBL_HEADER, tbl_cells=imps.PLT_TBL_CELLS, font=imps.PLT_TBL_FONT, row_fill_color=imps.PLT_TBL_ROW_COLORS, paper_bgcolor="rgba(0, 0, 0, 0)", ) fig.update_traces(cells=(dict(align=["center", "right"]))) imagefile = "econ_performance.png" imagefile = imps.save_image(imagefile, fig) if imps.IMAGES_URL or not imps.IMG_HOST_ACTIVE: image_link = imps.multi_image(imagefile) images_list.append(imagefile) else: image_link = imps.multi_image(imagefile) embeds_img.append( f"{image_link}", ) embeds.append( disnake.Embed( title=title, colour=imps.COLOR, ), ) i2 += 1 i += 2 end += 2 # Author/Footer for i in range(0, i2): embeds[i].set_author( name=imps.AUTHOR_NAME, url=imps.AUTHOR_URL, icon_url=imps.AUTHOR_ICON_URL, ) embeds[i].set_footer( text=imps.AUTHOR_NAME, icon_url=imps.AUTHOR_ICON_URL, ) i = 0 for i in range(0, i2): embeds[i].set_image(url=embeds_img[i]) i += 1 embeds[0].set_footer(text=f"Page 1 of {len(embeds)}") choices = [ disnake.SelectOption(label="Home", value="0", emoji="🟢"), ] output = { "view": imps.Menu, "title": title, "embed": embeds, "choices": choices, "embeds_img": embeds_img, "images_list": images_list, } else: fig = imps.plot_df( df.transpose(), fig_size=(800, 720), col_width=[6, 10], tbl_header=imps.PLT_TBL_HEADER, tbl_cells=imps.PLT_TBL_CELLS, font=imps.PLT_TBL_FONT, row_fill_color=imps.PLT_TBL_ROW_COLORS, paper_bgcolor="rgba(0, 0, 0, 0)", ) fig.update_traces(cells=(dict(align=["center", "right"]))) imagefile = imps.save_image("econ_performance.png", fig) output = { "title": title, "imagefile": imagefile, } return output
async def performance_command(ctx, arg="sector"): """Gets the performance data of a entered sector from GST and sends it Parameters ----------- arg: str sector (or any other input in the economy_group), -h or help Returns ------- discord message Sends a message containing an embed of the performance data of the given arg with pagination to the user """ economy_group = { "sector": "Sector", "industry": "Industry", "basic_materials": "Industry (Basic Materials)", "communication services": "Industry (Communication Services)", "consumer_cyclical": "Industry (Consumer Cyclical)", "consumer_defensive": "Industry (Consumer Defensive)", "energy": "Industry (Energy)", "financial": "Industry (Financial)", "healthcare": "Industry (Healthcare)", "industrials": "Industry (Industrials)", "real_estate": "Industry (Real Estate)", "technology": "Industry (Technology)", "utilities": "Industry (Utilities)", "country": "Country (U.S. listed stocks only)", "capitalization": "Capitalization", } try: # Debug if cfg.DEBUG: print(f"!stocks.economy.performance {arg}") # Help if arg == "-h" or arg == "help": help_txt = "Group performance [Source: Finviz]\n" possible_args = "" for k, v in economy_group.items(): possible_args += f"\n{k}: {v}" help_txt += "\nPossible arguments:\n" help_txt += "<GROUP> Groups to get data from. Default: sector\n" help_txt += f"The choices are:{possible_args}" embed = discord.Embed( title="Economy: [Finviz] Performance HELP", description=help_txt, colour=cfg.COLOR, ) embed.set_author( name=cfg.AUTHOR_NAME, icon_url=cfg.AUTHOR_ICON_URL, ) await ctx.send(embed=embed) else: # Parse argument try: group = economy_group[arg] except KeyError: title = "ERROR Economy: [Finviz] Performance" embed = discord.Embed(title=title, colour=cfg.COLOR) embed.set_author( name=cfg.AUTHOR_NAME, icon_url=cfg.AUTHOR_ICON_URL, ) embed.set_description( f"Entered group argument: {arg}" "\nEnter a valid group argument, example: sector") await ctx.send(embed=embed) if cfg.DEBUG: print("ERROR: Bad group argument entered") return df_group = finviz_model.get_valuation_performance_data( group, "performance") future_column_name = df_group["Name"] df_group = df_group.transpose() df_group.columns = future_column_name df_group.drop("Name") columns = [] initial_str = "Page 0: Overview" i = 1 for col_name in df_group.columns.values: initial_str += f"\nPage {i}: {col_name}" i += 1 columns.append( discord.Embed( title=f"Economy: [Finviz] Performance {group}", description=initial_str, colour=cfg.COLOR, ).set_author( name=cfg.AUTHOR_NAME, icon_url=cfg.AUTHOR_ICON_URL, )) for column in df_group.columns.values: columns.append( discord.Embed( description="```" + df_group[column].fillna("").to_string() + "```", colour=cfg.COLOR, ).set_author( name=cfg.AUTHOR_NAME, icon_url=cfg.AUTHOR_ICON_URL, )) await pagination(columns, ctx) except Exception as e: title = "INTERNAL ERROR" embed = discord.Embed(title=title, colour=cfg.COLOR) embed.set_author( name=cfg.AUTHOR_NAME, icon_url=cfg.AUTHOR_ICON_URL, ) embed.set_description( "Try updating the bot, make sure DEBUG is True in the config " "and restart it.\nIf the error still occurs open a issue at: " "https://github.com/GamestonkTerminal/GamestonkTerminal/issues" f"\n{e}") await ctx.send(embed=embed) if cfg.DEBUG: print(e)
def valuation_command(economy_group="sector"): """Valuation of sectors, industry, country [Finviz]""" d_economy_group = { "sector": "Sector", "industry": "Industry", "basic_materials": "Industry (Basic Materials)", "communication_services": "Industry (Communication Services)", "consumer_cyclical": "Industry (Consumer Cyclical)", "consumer_defensive": "Industry (Consumer Defensive)", "energy": "Industry (Energy)", "financial": "Industry (Financial)", "healthcare": "Industry (Healthcare)", "industrials": "Industry (Industrials)", "real_estate": "Industry (Real Estate)", "technology": "Industry (Technology)", "utilities": "Industry (Utilities)", "country": "Country (U.S. listed stocks only)", "capitalization": "Capitalization", } # Debug user input if cfg.DEBUG: logger.debug("econ-valuation %s", economy_group) # Select default group if economy_group == "": if cfg.DEBUG: logger.debug("Use default economy_group: 'sector'") economy_group = "sector" # Check for argument possible_groups = list(d_economy_group.keys()) if economy_group not in possible_groups: raise Exception( f"Select a valid group from {', '.join(possible_groups)}" # nosec ) group = d_economy_group[economy_group] # Retrieve data df_group = finviz_model.get_valuation_performance_data(group, "valuation") # Check for argument if df_group.empty: raise Exception("No available data found") # Output data df = pd.DataFrame(df_group) df = df.replace(np.nan, 0) df = df.set_axis( [ "Name", "MarketCap", "P/E", "FwdP/E", "PEG", "P/S", "P/B", "P/C", "P/FCF", "EPSpast5Y", "EPSnext5Y", "Salespast5Y", "Change", "Volume", ], axis="columns", ) df["P/E"] = pd.to_numeric(df["P/E"].astype(float)) df["FwdP/E"] = pd.to_numeric(df["FwdP/E"].astype(float)) df["EPSpast5Y"] = pd.to_numeric(df["EPSpast5Y"].astype(float)) df["EPSnext5Y"] = pd.to_numeric(df["EPSnext5Y"].astype(float)) df["Salespast5Y"] = pd.to_numeric(df["Salespast5Y"].astype(float)) df["Volume"] = pd.to_numeric(df["Volume"].astype(float)) df["Volume"] = df["Volume"] / 1_000_000 formats = { "P/E": "{:.2f}", "FwdP/E": "{:.2f}", "EPSpast5Y": "{:.2f}", "EPSnext5Y": "{:.2f}", "Salespast5Y": "{:.2f}", "Change": "{:.2f}", "Volume": "{:.0f}M", } for col, value in formats.items(): df[col] = df[col].map(lambda x: value.format(x)) # pylint: disable=W0640 df = df.fillna("") df.set_index("Name", inplace=True) dindex = len(df.index) fig = df2img.plot_dataframe( df, fig_size=(1600, (40 + (50 * dindex))), col_width=[12, 5, 4, 4, 4, 4, 4, 4, 4, 6, 6, 6, 4, 4], tbl_cells=dict( align=["left", "center"], height=35, ), template="plotly_dark", font=dict( family="Consolas", size=20, ), paper_bgcolor="rgba(0, 0, 0, 0)", ) imagefile = save_image("econ-valuation.png", fig) return { "title": "Economy: [Finviz] Valuation", "imagefile": imagefile, }
async def valuation_command(ctx, economy_group="sector"): """Valuation of sectors, industry, country [Finviz]""" d_economy_group = { "sector": "Sector", "industry": "Industry", "basic_materials": "Industry (Basic Materials)", "communication_services": "Industry (Communication Services)", "consumer_cyclical": "Industry (Consumer Cyclical)", "consumer_defensive": "Industry (Consumer Defensive)", "energy": "Industry (Energy)", "financial": "Industry (Financial)", "healthcare": "Industry (Healthcare)", "industrials": "Industry (Industrials)", "real_estate": "Industry (Real Estate)", "technology": "Industry (Technology)", "utilities": "Industry (Utilities)", "country": "Country (U.S. listed stocks only)", "capitalization": "Capitalization", } try: # Debug user input if cfg.DEBUG: logger.debug("!economy.valuation %s", economy_group) # Select default group if economy_group == "": if cfg.DEBUG: logger.debug("Use default economy_group: 'sector'") economy_group = "sector" # Check for argument possible_groups = list(d_economy_group.keys()) if economy_group not in possible_groups: raise Exception( f"Select a valid group from {', '.join(possible_groups)}" # nosec ) group = d_economy_group[economy_group] # Retrieve data df_group = finviz_model.get_valuation_performance_data(group, "valuation") # Debug user output if cfg.DEBUG: logger.debug(df_group.to_string()) # Output data future_column_name = df_group["Name"] df_group = df_group.transpose() df_group.columns = future_column_name df_group.drop("Name") columns = [] initial_str = "Page 0: Overview" i = 1 for col_name in df_group.columns.values: initial_str += f"\nPage {i}: {col_name}" i += 1 columns.append( discord.Embed( title=f"Economy: [Finviz] Valuation {group}", description=initial_str, colour=cfg.COLOR, ).set_author( name=cfg.AUTHOR_NAME, icon_url=cfg.AUTHOR_ICON_URL, ) ) for column in df_group.columns.values: columns.append( discord.Embed( description="```" + df_group[column].fillna("").to_string() + "```", colour=cfg.COLOR, ).set_author( name=cfg.AUTHOR_NAME, icon_url=cfg.AUTHOR_ICON_URL, ) ) await pagination(columns, ctx) except Exception as e: embed = discord.Embed( title="ERROR Economy: [Finviz] Valuation", colour=cfg.COLOR, description=e, ) embed.set_author( name=cfg.AUTHOR_NAME, icon_url=cfg.AUTHOR_ICON_URL, ) await ctx.send(embed=embed)
def performance_command(economy_group="sector"): """Performance of sectors, industry, country [Finviz]""" d_economy_group = { "sector": "Sector", "industry": "Industry", "basic_materials": "Industry (Basic Materials)", "communication_services": "Industry (Communication Services)", "consumer_cyclical": "Industry (Consumer Cyclical)", "consumer_defensive": "Industry (Consumer Defensive)", "energy": "Industry (Energy)", "financial": "Industry (Financial)", "healthcare": "Industry (Healthcare)", "industrials": "Industry (Industrials)", "real_estate": "Industry (Real Estate)", "technology": "Industry (Technology)", "utilities": "Industry (Utilities)", "country": "Country (U.S. listed stocks only)", "capitalization": "Capitalization", } # Debug user input if cfg.DEBUG: logger.debug("econ-performance %s", economy_group) # Select default group if not economy_group: if cfg.DEBUG: logger.debug("Use default economy_group: 'sector'") economy_group = "sector" # Check for argument possible_groups = list(d_economy_group.keys()) if economy_group not in possible_groups: possible_group_list = ", ".join(possible_groups) raise Exception( f"Select a valid group from {possible_group_list}") # nosec group = d_economy_group[economy_group] # Retrieve data df_group = finviz_model.get_valuation_performance_data( group, "performance") # Check for argument if df_group.empty: raise Exception("No available data found") # Output data df = pd.DataFrame(df_group) df = df.replace(np.nan, 0) df["Volume"] = df["Volume"] / 1_000_000 df["Avg Volume"] = df["Avg Volume"] / 1_000_000 formats = { "Perf Month": "{:.2f}", "Perf Quart": "{:.2f}", "Perf Half": "{:.2f}", "Perf Year": "{:.2f}", "Perf YTD": "{:.2f}", "Avg Volume": "{:.0f}M", "Change": "{:.2f}", "Volume": "{:.0f}M", } for col, value in formats.items(): df[col] = df[col].map(lambda x: value.format(x)) # pylint: disable=W0640 df = df.set_axis( [ "Name", "Week", "Month", "3Month", "6Month", "1Year", "YTD", "Recom", "Avg Vol.", "RelVolume", "Change", "Volume", ], axis="columns", ) df = df.fillna("") df.set_index("Name", inplace=True) dindex = len(df.index) fig = df2img.plot_dataframe( df, fig_size=(1500, (40 + (50 * dindex))), col_width=[10, 3, 3, 3, 3, 3, 3, 3, 4, 4, 3, 3.5], tbl_cells=dict( align=["left", "center"], height=35, ), template="plotly_dark", font=dict( family="Consolas", size=20, ), paper_bgcolor="rgba(0, 0, 0, 0)", ) imagefile = save_image("econ-performance.png", fig) return { "title": f"Economy: [WSJ] Performance {group}", "imagefile": imagefile, }