def get_quote(ticker) -> pd.DataFrame: """Gets ticker quote from FMP""" try: df_fa = fa.quote(ticker, cfg.API_KEY_FINANCIALMODELINGPREP) except ValueError: df_fa = pd.DataFrame() if not df_fa.empty: clean_df_index(df_fa) df_fa.loc["Market cap"][0] = lambda_long_number_format( df_fa.loc["Market cap"][0] ) df_fa.loc["Shares outstanding"][0] = lambda_long_number_format( df_fa.loc["Shares outstanding"][0] ) df_fa.loc["Volume"][0] = lambda_long_number_format(df_fa.loc["Volume"][0]) # Check if there is a valid earnings announcement if df_fa.loc["Earnings announcement"][0]: earning_announcement = datetime.strptime( df_fa.loc["Earnings announcement"][0][0:19], "%Y-%m-%dT%H:%M:%S" ) df_fa.loc["Earnings announcement"][ 0 ] = f"{earning_announcement.date()} {earning_announcement.time()}" return df_fa
def get_quote(ticker) -> pd.DataFrame: """Gets ticker quote from FMP""" df_fa = pd.DataFrame() try: df_fa = fa.quote(ticker, cfg.API_KEY_FINANCIALMODELINGPREP) # Invalid API Keys except ValueError: console.print("[red]Invalid API Key[/red]\n") # Premium feature, API plan is not authorized except HTTPError: console.print("[red]API Key not authorized for Premium feature[/red]\n") if not df_fa.empty: clean_df_index(df_fa) df_fa.loc["Market cap"][0] = lambda_long_number_format( df_fa.loc["Market cap"][0] ) df_fa.loc["Shares outstanding"][0] = lambda_long_number_format( df_fa.loc["Shares outstanding"][0] ) df_fa.loc["Volume"][0] = lambda_long_number_format(df_fa.loc["Volume"][0]) # Check if there is a valid earnings announcement if df_fa.loc["Earnings announcement"][0]: earning_announcement = datetime.strptime( df_fa.loc["Earnings announcement"][0][0:19], "%Y-%m-%dT%H:%M:%S" ) df_fa.loc["Earnings announcement"][ 0 ] = f"{earning_announcement.date()} {earning_announcement.time()}" return df_fa
def get_shareholders(ticker: str) -> Tuple[pd.DataFrame, pd.DataFrame, pd.DataFrame]: """Get shareholders from yahoo Parameters ---------- ticker : str Stock ticker Returns ------- pd.DataFrame Major holders pd.DataFrame Institutional holders pd.DataFrame Mutual Fund holders """ stock = yf.Ticker(ticker) # Major holders df_major_holders = stock.major_holders df_major_holders[1] = df_major_holders[1].apply( lambda x: x.replace("%", "Percentage") ) # Institutional holders df_institutional_shareholders = stock.institutional_holders df_institutional_shareholders.columns = ( df_institutional_shareholders.columns.str.replace("% Out", "Stake") ) df_institutional_shareholders["Shares"] = df_institutional_shareholders[ "Shares" ].apply(lambda x: lambda_long_number_format(x)) df_institutional_shareholders["Value"] = df_institutional_shareholders[ "Value" ].apply(lambda x: lambda_long_number_format(x)) df_institutional_shareholders["Stake"] = df_institutional_shareholders[ "Stake" ].apply(lambda x: str(f"{100 * x:.2f}") + " %") # Mutualfunds holders df_mutualfund_shareholders = stock.mutualfund_holders df_mutualfund_shareholders.columns = df_mutualfund_shareholders.columns.str.replace( "% Out", "Stake" ) df_mutualfund_shareholders["Shares"] = df_mutualfund_shareholders["Shares"].apply( lambda x: lambda_long_number_format(x) ) df_mutualfund_shareholders["Value"] = df_mutualfund_shareholders["Value"].apply( lambda x: lambda_long_number_format(x) ) df_mutualfund_shareholders["Stake"] = df_mutualfund_shareholders["Stake"].apply( lambda x: str(f"{100 * x:.2f}") + " %" ) return df_major_holders, df_institutional_shareholders, df_mutualfund_shareholders
def get_calendar_earnings(ticker: str) -> pd.DataFrame: """Get calendar earnings for ticker Parameters ---------- ticker : [type] Stock ticker Returns ------- pd.DataFrame Dataframe of calendar earnings """ stock = yf.Ticker(ticker) df_calendar = stock.calendar if df_calendar.empty: return pd.DataFrame() df_calendar.iloc[0, :] = df_calendar.iloc[0, :].apply( lambda x: x.date().strftime("%m/%d/%Y")) df_calendar.iloc[1:, :] = df_calendar.iloc[1:, :].applymap( lambda x: lambda_long_number_format(x)) return df_calendar
def clean_metrics_df(df_fa: pd.DataFrame, num: int, mask: bool = True) -> pd.DataFrame: """Clean metrics data frame Parameters ---------- df_fa : pd.DataFrame Metrics data frame num : int Number of columns to clean mask : bool, optional Apply mask, by default True Returns ------- pd.DataFrame Cleaned metrics data frame """ df_fa = df_fa.iloc[:, 0:num] if mask: df_fa = df_fa.mask(df_fa.astype(object).eq(num * ["None"])).dropna() df_fa = df_fa.mask(df_fa.astype(object).eq(num * ["0"])).dropna() df_fa = df_fa.applymap(lambda x: lambda_long_number_format(x)) clean_df_index(df_fa) df_fa.columns.name = "Fiscal Date Ending" df_fa = df_fa.rename( index={ "Enterprise value over e b i t d a": "Enterprise value over EBITDA", "Net debt to e b i t d a": "Net debt to EBITDA", "D c f": "DCF", "Net income per e b t": "Net income per EBT", } ) return df_fa
def short_interest(ticker: str, nyse: bool, days: int, raw: bool, export: str): """Plots the short interest of a stock. This corresponds to the number of shares that have been sold short but have not yet been covered or closed out. Either NASDAQ or NYSE [Source: Quandl] Parameters ---------- ticker : str ticker to get short interest from nyse : bool data from NYSE if true, otherwise NASDAQ days : int Number of past days to show short interest raw : bool Flag to print raw data instead export : str Export dataframe data to csv,json,xlsx file """ df_short_interest = quandl_model.get_short_interest(ticker, nyse) df_short_interest = df_short_interest.tail(days) df_short_interest.columns = [ "".join(" " + char if char.isupper() else char.strip() for char in idx).strip() for idx in df_short_interest.columns.tolist() ] pd.options.mode.chained_assignment = None vol_pct = (100 * df_short_interest["Short Volume"].values / df_short_interest["Total Volume"].values) df_short_interest["% of Volume Shorted"] = [ round(pct, 2) for pct in vol_pct ] if raw: df_short_interest["% of Volume Shorted"] = df_short_interest[ "% of Volume Shorted"].apply(lambda x: f"{x/100:.2%}") df_short_interest = df_short_interest.applymap( lambda x: lambda_long_number_format(x)).sort_index(ascending=False) df_short_interest.index = df_short_interest.index.date print_rich_table( df_short_interest, headers=list(df_short_interest.columns), show_index=True, title="Short Interest of Stock", ) console.print("") export_data( export, os.path.dirname(os.path.abspath(__file__)), "psi(quandl)", df_short_interest, )
def display_crypto_hacks( top: int, sortby: str, descend: bool, slug: str, export: str = "" ) -> None: """Display list of major crypto-related hacks. If slug is passed individual crypto hack is displayed instead of list of crypto hacks [Source: https://rekt.news] Parameters ---------- slug: str Crypto hack slug to check (e.g., polynetwork-rekt) top: int Number of hacks to search sortby: str Key by which to sort data {Platform,Date,Amount [$],Audit,Slug,URL} descend: bool Flag to sort data descending export : str Export dataframe data to csv,json,xlsx file """ if slug: text = rekt_model.get_crypto_hack(slug) if text: console.print(text) export_data( export, os.path.dirname(os.path.abspath(__file__)), "ch", text, ) else: df = rekt_model.get_crypto_hacks() if df.empty: console.print("\nError in rekt request\n") else: if sortby in rekt_model.HACKS_COLUMNS: df = df.sort_values(by=sortby, ascending=descend) df["Amount [$]"] = df["Amount [$]"].apply( lambda x: lambda_long_number_format(x) ) df["Date"] = df["Date"].dt.date print_rich_table( df.head(top), headers=list(df.columns), floatfmt=".1f", show_index=False, title="Major Crypto Hacks", ) console.print("") export_data( export, os.path.dirname(os.path.abspath(__file__)), "ch", df, )
def get_key_metrics(ticker: str) -> pd.DataFrame: """Get key metrics from overview Parameters ---------- ticker : str Stock ticker Returns ------- pd.DataFrame Dataframe of key metrics """ # Request OVERVIEW data s_req = f"https://www.alphavantage.co/query?function=OVERVIEW&symbol={ticker}&apikey={cfg.API_KEY_ALPHAVANTAGE}" result = requests.get(s_req, stream=True) # If the returned data was unsuccessful if "Error Message" in result.json(): console.print(result.json()["Error Message"]) else: # check if json is empty if not result.json() or len(result.json()) < 2: console.print("No data found") return pd.DataFrame() df_fa = pd.json_normalize(result.json()) df_fa = df_fa[list(result.json().keys())].T df_fa = df_fa.applymap(lambda x: lambda_long_number_format(x)) clean_df_index(df_fa) df_fa = df_fa.rename( index={ "E b i t d a": "EBITDA", "P e ratio": "PE ratio", "P e g ratio": "PEG ratio", "E p s": "EPS", "Return on equity t t m": "Return on equity TTM", "Price to sales ratio t t m": "Price to sales ratio TTM", } ) as_key_metrics = [ "Market capitalization", "EBITDA", "EPS", "PE ratio", "PEG ratio", "Price to book ratio", "Return on equity TTM", "Price to sales ratio TTM", "Dividend yield", "50 day moving average", "Analyst target price", "Beta", ] return df_fa.loc[as_key_metrics] return pd.DataFrame()
def display_whales_transactions( min_value: int = 800000, top: int = 100, sortby: str = "date", descend: bool = False, show_address: bool = False, export: str = "", ) -> None: """Display huge value transactions from major blockchains. [Source: https://docs.whale-alert.io/] Parameters ---------- min_value: int Minimum value of trade to track. top: int Limit of transactions. Maximum 100 sortby: str Key to sort by. descend: str Sort in descending order. show_address: bool Flag to show addresses of transactions. export : str Export dataframe data to csv,json,xlsx file """ df = whale_alert_model.get_whales_transactions(min_value) if df.empty: return df_data = df.copy() df = df.sort_values(by=sortby, ascending=descend) if not show_address: df = df.drop(["from_address", "to_address"], axis=1) else: df = df.drop(["from", "to", "blockchain"], axis=1) for col in ["amount_usd", "amount"]: df[col] = df[col].apply(lambda x: lambda_long_number_format(x)) print_rich_table( df.head(top), headers=list(df.columns), show_index=False, title="Large Value Transactions", ) console.print("") export_data( export, os.path.dirname(os.path.abspath(__file__)), "whales", df_data, )
def display_historical_tvl( dapps: str = "", export: str = "", external_axes: Optional[List[plt.Axes]] = None, ): """Displays historical TVL of different dApps [Source: https://docs.llama.fi/api] Parameters ---------- dapps: str dApps to search historical TVL. Should be split by , e.g.: anchor,sushiswap,pancakeswap export : str Export dataframe data to csv,json,xlsx file external_axes : Optional[List[plt.Axes]], optional External axes (1 axis is expected in the list), by default None """ # 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 available_protocols = read_data_file("defillama_dapps.json") if isinstance(available_protocols, dict): for dapp in dapps.split(","): if dapp in available_protocols.keys(): df = llama_model.get_defi_protocol(dapp) if not df.empty: ax.plot(df, label=available_protocols[dapp]) else: print(f"{dapp} not found\n") ax.set_ylabel("Total Value Locked ($)") ax.get_yaxis().set_major_formatter( ticker.FuncFormatter(lambda x, _: lambda_long_number_format(x))) cfg.theme.style_primary_axis(ax) ax.legend() ax.set_title("TVL in dApps") if not external_axes: cfg.theme.visualize_output() export_data( export, os.path.dirname(os.path.abspath(__file__)), "dtvl", None, )
def get_overview(ticker: str) -> pd.DataFrame: """Get alpha vantage company overview Parameters ---------- ticker : str Stock ticker Returns ------- pd.DataFrame Dataframe of fundamentals """ # Request OVERVIEW data from Alpha Vantage API s_req = f"https://www.alphavantage.co/query?function=OVERVIEW&symbol={ticker}&apikey={cfg.API_KEY_ALPHAVANTAGE}" result = requests.get(s_req, stream=True) # If the returned data was successful if result.status_code == 200: # Parse json data to dataframe if "Note" in result.json(): console.print(result.json()["Note"], "\n") return pd.DataFrame() df_fa = pd.json_normalize(result.json()) # Keep json data sorting in dataframe df_fa = df_fa[list(result.json().keys())].T df_fa.iloc[5:] = df_fa.iloc[5:].applymap(lambda x: lambda_long_number_format(x)) clean_df_index(df_fa) df_fa = df_fa.rename( index={ "E b i t d a": "EBITDA", "P e ratio": "PE ratio", "P e g ratio": "PEG ratio", "E p s": "EPS", "Revenue per share t t m": "Revenue per share TTM", "Operating margin t t m": "Operating margin TTM", "Return on assets t t m": "Return on assets TTM", "Return on equity t t m": "Return on equity TTM", "Revenue t t m": "Revenue TTM", "Gross profit t t m": "Gross profit TTM", "Diluted e p s t t m": "Diluted EPS TTM", "Quarterly earnings growth y o y": "Quarterly earnings growth YOY", "Quarterly revenue growth y o y": "Quarterly revenue growth YOY", "Trailing p e": "Trailing PE", "Forward p e": "Forward PE", "Price to sales ratio t t m": "Price to sales ratio TTM", "E v to revenue": "EV to revenue", "E v to e b i t d a": "EV to EBITDA", } ) return df_fa return pd.DataFrame()
def display_btc_confirmed_transactions( since: int, until: int, export: str, external_axes: Optional[List[plt.Axes]] = None, ) -> None: """Returns BTC confirmed transactions [Source: https://api.blockchain.info/] Parameters ---------- since : int Initial date timestamp (e.g., 1_609_459_200) until : int End date timestamp (e.g., 1_641_588_030) export : str Export dataframe data to csv,json,xlsx file external_axes : Optional[List[plt.Axes]], optional External axes (1 axis is expected in the list), by default None """ df = blockchain_model.get_btc_confirmed_transactions() df = df[ (df["x"] > datetime.fromtimestamp(since)) & (df["x"] < datetime.fromtimestamp(until)) ] # This plot has 1 axis if not external_axes: _, ax = plt.subplots(figsize=plot_autoscale(), dpi=PLOT_DPI) else: if len(external_axes) != 1: console.print("[red]Expected list of one axis item./n[/red]") return (ax,) = external_axes ax.plot(df["x"], df["y"], lw=0.8) ax.set_ylabel("Transactions") ax.set_title("BTC Confirmed Transactions") ax.get_yaxis().set_major_formatter( ticker.FuncFormatter(lambda x, _: lambda_long_number_format(x)) ) theme.style_primary_axis(ax) if not external_axes: theme.visualize_output() export_data( export, os.path.dirname(os.path.abspath(__file__)), "btcct", df, )
def get_income_statements( ticker: str, number: int, quarterly: bool = False ) -> pd.DataFrame: """Get income statements for company Parameters ---------- ticker : str Stock ticker number : int Number of past to get quarterly : bool, optional Flag to get quarterly instead of annual, by default False Returns ------- pd.DataFrame Dataframe of income statements """ url = ( f"https://www.alphavantage.co/query?function=INCOME_STATEMENT&symbol={ticker}" f"&apikey={cfg.API_KEY_ALPHAVANTAGE}" ) r = requests.get(url) # If the returned data was unsuccessful if "Error Message" in r.json(): console.print(r.json()["Error Message"]) else: # check if json is empty if not r.json(): console.print("No data found") else: statements = r.json() df_fa = pd.DataFrame() if quarterly: if "quarterlyReports" in statements: df_fa = pd.DataFrame(statements["quarterlyReports"]) else: if "annualReports" in statements: df_fa = pd.DataFrame(statements["annualReports"]) if df_fa.empty: console.print("No data found") return pd.DataFrame() df_fa = df_fa.set_index("fiscalDateEnding") df_fa = df_fa.head(number) df_fa = df_fa.applymap(lambda x: lambda_long_number_format(x)) return df_fa[::-1].T return pd.DataFrame()
def display_terra_asset_history( asset: str = "", address: str = "", export: str = "", external_axes: Optional[List[plt.Axes]] = None, ) -> None: """Displays the 30-day history of specified asset in terra address [Source: https://terra.engineer/] Parameters ---------- asset : str Terra asset {ust,luna,sdt} address : str Terra address. Valid terra addresses start with 'terra' export : str Export dataframe data to csv,json,xlsx file external_axes : Optional[List[plt.Axes]], optional External axes (1 axis is expected in the list), by default None """ df = terraengineer_model.get_history_asset_from_terra_address( address=address, asset=asset) # 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 ax.plot(df["x"], df["y"]) ax.set_ylabel(f"{asset.upper()} Amount") ax.set_title(f"{asset.upper()} Amount in {address}") ax.get_yaxis().set_major_formatter( ticker.FuncFormatter(lambda x, _: lambda_long_number_format(x))) cfg.theme.style_primary_axis(ax) if not external_axes: cfg.theme.visualize_output() export_data( export, os.path.dirname(os.path.abspath(__file__)), "aterra", df, )
def display_defi_tvl( top: int, export: str = "", external_axes: Optional[List[plt.Axes]] = None, ) -> None: """Displays historical values of the total sum of TVLs from all listed protocols. [Source: https://docs.llama.fi/api] Parameters ---------- top: int Number of records to display export : str Export dataframe data to csv,json,xlsx file external_axes : Optional[List[plt.Axes]], optional External axes (1 axis is expected in the list), by default None """ # 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 df = llama_model.get_defi_tvl() df_data = df.copy() df = df.tail(top) ax.plot(df["date"], df["totalLiquidityUSD"], ms=2) # ax.set_xlim(df["date"].iloc[0], df["date"].iloc[-1]) ax.set_ylabel("Total Value Locked ($)") ax.set_title("Total Value Locked in DeFi") ax.get_yaxis().set_major_formatter( ticker.FuncFormatter(lambda x, _: lambda_long_number_format(x))) cfg.theme.style_primary_axis(ax) if not external_axes: cfg.theme.visualize_output() export_data( export, os.path.dirname(os.path.abspath(__file__)), "stvl", df_data, )
def lambda_long_number_format_with_type_check( x: Union[int, float]) -> Union[str, Any]: """Helper which checks if type of x is int or float and it's smaller then 10^18. If yes it apply long_num_format Parameters ---------- x: int/float number to apply long_number_format method Returns ------- Union[str, Any] """ if isinstance(x, (int, float)) and x < 10**18: return lambda_long_number_format(x) return x
def plot_data( df: pd.DataFrame, symbol: str, external_axes: Optional[List[plt.Axes]] = None, ): # This plot has 2 axis if not external_axes: _, (ax1, ax2) = plt.subplots(2, 1, sharex=True, figsize=plot_autoscale(), dpi=cfgPlot.PLOT_DPI) else: if len(external_axes) != 2: logger.error("Expected list of two axis items.") console.print("[red]Expected list of two axis items./n[/red]") return ax1, ax2 = external_axes df_price = df[["price"]].copy() df_without_price = df.drop("price", axis=1) ax1.stackplot( df_without_price.index, df_without_price.transpose().to_numpy(), labels=df_without_price.columns.tolist(), ) ax1.get_yaxis().set_major_formatter( ticker.FuncFormatter(lambda x, _: lambda_long_number_format(x))) ax1.legend(df_without_price.columns, fontsize="x-small", ncol=2) ax1.set_title(f"Exchange {symbol} Futures Open Interest") ax1.set_ylabel("Open futures value[$B]") ax2.plot(df_price.index, df_price) ax2.legend([f"{symbol} price"]) ax2.set_ylabel(f"{symbol} Price [$]") ax2.set_xlim([df_price.index[0], df_price.index[-1]]) ax2.set_ylim(bottom=0.0) theme.style_primary_axis(ax1) theme.style_primary_axis(ax2) if not external_axes: theme.visualize_output()
def display_anchor_yield_reserve( export: str = "", external_axes: Optional[List[plt.Axes]] = None) -> None: """Displays the 30-day history of the Anchor Yield Reserve. [Source: https://terra.engineer/] Parameters ---------- export : str Export dataframe data to csv,json,xlsx file external_axes : Optional[List[plt.Axes]], optional External axes (1 axis is expected in the list), by default None """ df = terraengineer_model.get_history_asset_from_terra_address( address="terra1tmnqgvg567ypvsvk6rwsga3srp7e3lg6u0elp8") # 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 ax.plot(df["x"], df["y"]) ax.set_ylabel("UST Amount") ax.set_title("Anchor UST Yield Reserve") ax.get_yaxis().set_major_formatter( ticker.FuncFormatter(lambda x, _: lambda_long_number_format(x))) cfg.theme.style_primary_axis(ax) if not external_axes: cfg.theme.visualize_output() export_data( export, os.path.dirname(os.path.abspath(__file__)), "ayr", df, )
def display_trading_pairs(top: int, sortby: str, descend: bool, export: str) -> None: """Displays a list of available currency pairs for trading. [Source: Coinbase] Parameters ---------- top: int Top n of pairs sortby: str Key to sortby data descend: bool Sort descending flag export : str Export dataframe data to csv,json,xlsx file """ df = coinbase_model.get_trading_pairs() df_data = df.copy() for col in [ "base_min_size", "base_max_size", "min_market_funds", "max_market_funds", ]: df[col] = df[col].apply(lambda x: lambda_long_number_format(x)) df = df.sort_values(by=sortby, ascending=descend).head(top) print_rich_table( df, headers=list(df.columns), show_index=False, title="Available Pairs for Trading", ) console.print("") export_data( export, os.path.dirname(os.path.abspath(__file__)), "pairs", df_data, )
def get_info(ticker: str) -> pd.DataFrame: """Gets ticker info Parameters ---------- ticker : str Stock ticker Returns ------- pd.DataFrame DataFrame of yfinance information """ stock = yf.Ticker(ticker) df_info = pd.DataFrame(stock.info.items(), columns=["Metric", "Value"]) df_info = df_info.set_index("Metric") clean_df_index(df_info) if "Last split date" in df_info.index and df_info.loc[ "Last split date"].values[0]: df_info.loc["Last split date"].values[0] = datetime.fromtimestamp( df_info.loc["Last split date"].values[0]).strftime("%Y-%m-%d") df_info = df_info.mask(df_info["Value"].astype(str).eq("[]")).dropna() df_info[df_info.index != "Zip"] = df_info[df_info.index != "Zip"].applymap( lambda x: lambda_long_number_format(x)) df_info = df_info.rename( index={ "Address1": "Address", "Average daily volume10 day": "Average daily volume 10 day", "Average volume10days": "Average volume 10 days", "Price to sales trailing12 months": "Price to sales trailing 12 months", }) df_info.index = df_info.index.str.replace("eps", "EPS") df_info.index = df_info.index.str.replace("p e", "PE") df_info.index = df_info.index.str.replace("Peg", "PEG") return df_info
def get_balance_sheet( ticker: str, number: int, quarterly: bool = False ) -> pd.DataFrame: """Get balance sheets for company Parameters ---------- ticker : str Stock ticker number : int Number of past to get quarterly : bool, optional Flag to get quarterly instead of annual, by default False Returns ------- pd.DataFrame Dataframe of income statements """ url = f"https://www.alphavantage.co/query?function=BALANCE_SHEET&symbol={ticker}&apikey={cfg.API_KEY_ALPHAVANTAGE}" r = requests.get(url) if r.status_code == 200: statements = r.json() df_fa = pd.DataFrame() if quarterly: if "quarterlyReports" in statements: df_fa = pd.DataFrame(statements["quarterlyReports"]) else: if "annualReports" in statements: df_fa = pd.DataFrame(statements["annualReports"]) if df_fa.empty: return pd.DataFrame() df_fa = df_fa.set_index("fiscalDateEnding") df_fa = df_fa.head(number) df_fa = df_fa.applymap(lambda x: lambda_long_number_format(x)) return df_fa[::-1].T return pd.DataFrame()
def display_defi_vaults( chain: Optional[str] = None, protocol: Optional[str] = None, kind: Optional[str] = None, top: int = 10, sortby: str = "apy", descend: bool = False, link: bool = False, export: str = "", ) -> None: """Display Top DeFi Vaults - pools of funds with an assigned strategy which main goal is to maximize returns of its crypto assets. [Source: https://coindix.com/] Parameters ---------- chain: str Blockchain - one from list [ 'ethereum', 'polygon', 'avalanche', 'bsc', 'terra', 'fantom', 'moonriver', 'celo', 'heco', 'okex', 'cronos', 'arbitrum', 'eth', 'harmony', 'fuse', 'defichain', 'solana', 'optimism' ] protocol: str DeFi protocol - one from list: [ 'aave', 'acryptos', 'alpaca', 'anchor', 'autofarm', 'balancer', 'bancor', 'beefy', 'belt', 'compound', 'convex', 'cream', 'curve', 'defichain', 'geist', 'lido', 'liquity', 'mirror', 'pancakeswap', 'raydium', 'sushi', 'tarot', 'traderjoe', 'tulip', 'ubeswap', 'uniswap', 'venus', 'yearn' ] kind: str Kind/type of vault - one from list: ['lp','single','noimploss','stable'] top: int Number of records to display sortby: str Key by which to sort data descend: bool Flag to sort data descending link: bool Flag to show links export : str Export dataframe data to csv,json,xlsx file """ df = coindix_model.get_defi_vaults(chain=chain, protocol=protocol, kind=kind) df_data = df.copy() if df.empty: print( f"Couldn't find any vaults for " f"{'' if not chain else 'chain: ' + chain}{'' if not protocol else ', protocol: ' + protocol}" f"{'' if not kind else ', kind:' + kind}") return df = df.sort_values(by=sortby, ascending=descend) df["tvl"] = df["tvl"].apply(lambda x: lambda_long_number_format(x)) df["apy"] = df["apy"].apply(lambda x: f"{str(round(x * 100, 2))} %" if isinstance(x, (int, float)) else x) df.columns = [x.title() for x in df.columns] df.rename(columns={"Apy": "APY (%)", "Tvl": "TVL ($)"}, inplace=True) if link is True: df.drop("Link", axis=1, inplace=True) print_rich_table( df.head(top), headers=list(df.columns), show_index=False, title="Top DeFi Vaults", ) console.print("") export_data( export, os.path.dirname(os.path.abspath(__file__)), "vaults", df_data, )
def ownership_command( preset: str = "template", sort: str = "", limit: int = 5, ascend: bool = False ): """Displays stocks based on own share float and ownership data [Finviz]""" # Check for argument if preset == "template" or preset not in so.all_presets: raise Exception("Invalid preset selected!") # Debug if imps.DEBUG: logger.debug("scr-ownership %s %s %s %s", preset, sort, limit, ascend) # Check for argument if limit < 0: raise Exception("Number has to be above 0") # Output Data df_screen = get_screener_data( preset, "ownership", limit, ascend, ) title = "Stocks: [Finviz] Ownership Screener" if isinstance(df_screen, pd.DataFrame): if df_screen.empty: raise Exception("No data found.") df_screen = df_screen.dropna(axis="columns", how="all") if sort: if sort in so.d_cols_to_sort["ownership"]: df_screen = df_screen.sort_values( by=sort, ascending=ascend, na_position="last", ) else: similar_cmd = difflib.get_close_matches( " ".join(sort), so.d_cols_to_sort["ownership"], n=1, cutoff=0.7, ) if similar_cmd: df_screen = df_screen.sort_values( by=[similar_cmd[0]], ascending=ascend, na_position="last", ) else: raise ValueError( f"Wrong sort column provided! Select from: {', '.join(so.d_cols_to_sort['ownership'])}" ) df_screen.set_index("Ticker", inplace=True) df_screen = df_screen.head(n=limit) df_screen = df_screen.fillna("-") dindex = len(df_screen.index) df_screen = df_screen.applymap(lambda x: lambda_long_number_format(x, 2)) if dindex > 5: embeds: list = [] # Output i, i2, end = 0, 0, 5 df_pg, embeds_img, images_list = pd.DataFrame(), [], [] while i < dindex: df_pg = df_screen.iloc[i:end] df_pg.append(df_pg) fig = imps.plot_df( df_pg.transpose(), fig_size=(800, 720), col_width=[2, 1.5], 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 = "scr_ownership.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 += 5 end += 5 # 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_screen.transpose(), fig_size=(800, 720), col_width=[2, 1.5], 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("scr_ownership.png", fig) output = { "title": title, "imagefile": imagefile, } return output
def display_defi_protocols(top: int, sortby: str, descend: bool, description: bool, export: str = "") -> None: """Display information about listed DeFi protocols, their current TVL and changes to it in the last hour/day/week. [Source: https://docs.llama.fi/api] Parameters ---------- top: int Number of records to display sortby: str Key by which to sort data descend: bool Flag to sort data descending description: bool Flag to display description of protocol export : str Export dataframe data to csv,json,xlsx file """ df = llama_model.get_defi_protocols() df_data = df.copy() df = df.sort_values(by=sortby, ascending=descend) df = df.drop(columns="chain") df["tvl"] = df["tvl"].apply(lambda x: lambda_long_number_format(x)) if not description: df.drop(["description", "url"], axis=1, inplace=True) else: df = df[[ "name", "symbol", "category", "description", "url", ]] df.columns = [ lambda_replace_underscores_in_column_names(val) for val in df.columns ] df.rename( columns={ "Change 1H": "Change 1H (%)", "Change 1D": "Change 1D (%)", "Change 7D": "Change 7D (%)", "Tvl": "TVL ($)", }, inplace=True, ) print_rich_table(df.head(top), headers=list(df.columns), show_index=False) console.print("") export_data( export, os.path.dirname(os.path.abspath(__file__)), "ldapps", df_data, )
def display_bw( name: str, df: pd.DataFrame, target: str, yearly: bool, external_axes: Optional[List[plt.Axes]] = None, ): """Show box and whisker plots Parameters ---------- name : str Name of dataset df : pd.DataFrame Dataframe to look at target : str Data column to look at yearly : bool Flag to indicate yearly accumulation external_axes : Optional[List[plt.Axes]], optional External axes (1 axis is expected in the list), by default None """ data = df[target] start = df.index[0] # This plot has 1 axis if external_axes is None: _, 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 1 axis items./n[/red]") return (ax, ) = external_axes color = theme.get_colors()[0] if yearly: x_data = data.index.year else: x_data = data.index.month box_plot = sns.boxplot( x=x_data, y=data, ax=ax, zorder=3, boxprops=dict(edgecolor=color), flierprops=dict( linestyle="--", color=color, markerfacecolor=theme.up_color, markeredgecolor=theme.up_color, ), whiskerprops=dict(color=color), capprops=dict(color=color), ) box_plot.set( xlabel=["Monthly", "Yearly"][yearly], ylabel=target, title= f"{['Monthly','Yearly'][yearly]} box plot of {name} {target} from {start.strftime('%Y-%m-%d')}", ) l_months = [ "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", ] l_ticks = list() if not yearly: for val in box_plot.get_xticklabels(): l_ticks.append(l_months[int(val.get_text()) - 1]) box_plot.set_xticklabels(l_ticks) # remove the scientific notion on the left hand side ax.ticklabel_format(style="plain", axis="y") ax.get_yaxis().set_major_formatter( matplotlib.ticker.FuncFormatter( lambda x, _: lambda_long_number_format(x))) theme.style_primary_axis(ax) if external_axes is None: theme.visualize_output()
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
def display_line( data: pd.Series, title: str = "", log_y: bool = True, draw: bool = False, markers_lines: Optional[List[datetime]] = None, markers_scatter: Optional[List[datetime]] = None, export: str = "", external_axes: Optional[List[plt.Axes]] = None, ): """Display line plot of data Parameters ---------- data: pd.Series Data to plot title: str Title for plot log_y: bool Flag for showing y on log scale draw: bool Flag for drawing lines and annotating on the plot markers_lines: Optional[List[datetime]] List of dates to highlight using vertical lines markers_scatter: Optional[List[datetime]] List of dates to highlight using scatter export: str Format to export data external_axes : Optional[List[plt.Axes]], optional External axes (1 axis is expected in the list), by default None """ # This plot has 1 axis if external_axes is None: _, 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 1 axis items./n[/red]") return (ax, ) = external_axes if log_y: ax.semilogy(data.index, data.values) ax.yaxis.set_major_formatter(matplotlib.ticker.ScalarFormatter()) ax.yaxis.set_major_locator( matplotlib.ticker.LogLocator(base=100, subs=[1.0, 2.0, 5.0, 10.0])) ax.ticklabel_format(style="plain", axis="y") else: ax.plot(data.index, data.values) if markers_lines: ymin, ymax = ax.get_ylim() ax.vlines(markers_lines, ymin, ymax, color="#00AAFF") if markers_scatter: for n, marker_date in enumerate(markers_scatter): price_location_idx = data.index.get_loc(marker_date, method="nearest") # algo to improve text placement of highlight event number if (0 < price_location_idx < (len(data) - 1) and data.iloc[price_location_idx - 1] > data.iloc[price_location_idx] and data.iloc[price_location_idx + 1] > data.iloc[price_location_idx]): text_loc = (0, -20) else: text_loc = (0, 10) ax.annotate( str(n + 1), (mdates.date2num(marker_date), data.iloc[price_location_idx]), xytext=text_loc, textcoords="offset points", ) ax.scatter( marker_date, data.iloc[price_location_idx], color="#00AAFF", s=100, ) data_type = data.name ax.set_ylabel(data_type) ax.set_xlim(data.index[0], data.index[-1]) ax.ticklabel_format(style="plain", axis="y") ax.get_yaxis().set_major_formatter( matplotlib.ticker.FuncFormatter( lambda x, _: lambda_long_number_format(x))) if title: ax.set_title(title) if draw: LineAnnotateDrawer(ax).draw_lines_and_annotate() theme.style_primary_axis(ax) if external_axes is None: theme.visualize_output() export_data( export, os.path.dirname(os.path.abspath(__file__)).replace("common", "stocks"), "line", )
def screener( loaded_preset: str, data_type: str, limit: int = 10, ascend: bool = False, sort: str = "", export: str = "", ) -> List[str]: """Screener one of the following: overview, valuation, financial, ownership, performance, technical. Parameters ---------- loaded_preset: str Preset loaded to filter for tickers data_type : str Data type string between: overview, valuation, financial, ownership, performance, technical limit : int Limit of stocks to display ascend : bool Order of table to ascend or descend sort: str Column to sort table by export : str Export dataframe data to csv,json,xlsx file Returns ------- List[str] List of stocks that meet preset criteria """ with suppress_stdout(): df_screen = get_screener_data( preset_loaded=loaded_preset, data_type=data_type, limit=10, ascend=ascend, ) if isinstance(df_screen, pd.DataFrame): if df_screen.empty: return [] df_screen = df_screen.dropna(axis="columns", how="all") if sort: if sort in d_cols_to_sort[data_type]: df_screen = df_screen.sort_values( by=[sort], ascending=ascend, na_position="last", ) else: similar_cmd = difflib.get_close_matches( sort, d_cols_to_sort[data_type], n=1, cutoff=0.7, ) if similar_cmd: console.print( f"Replacing '{' '.join(sort)}' by '{similar_cmd[0]}' so table can be sorted." ) df_screen = df_screen.sort_values( by=[similar_cmd[0]], ascending=ascend, na_position="last", ) else: console.print( f"Wrong sort column provided! Provide one of these: {', '.join(d_cols_to_sort[data_type])}" ) df_screen = df_screen.fillna("") if data_type == "ownership": cols = [ "Market Cap", "Outstanding", "Float", "Avg Volume", "Volume" ] df_screen[cols] = df_screen[cols].applymap( lambda x: lambda_long_number_format(x, 1)) elif data_type == "overview": cols = ["Market Cap", "Volume"] df_screen[cols] = df_screen[cols].applymap( lambda x: lambda_long_number_format(x, 1)) elif data_type == "technical": cols = ["Volume"] df_screen[cols] = df_screen[cols].applymap( lambda x: lambda_long_number_format(x, 1)) elif data_type == "valuation": cols = ["Market Cap", "Volume"] df_screen[cols] = df_screen[cols].applymap( lambda x: lambda_long_number_format(x, 1)) elif data_type == "financial": cols = ["Market Cap", "Volume"] df_screen[cols] = df_screen[cols].applymap( lambda x: lambda_long_number_format(x, 1)) elif data_type == "performance": cols = ["Avg Volume", "Volume"] df_screen[cols] = df_screen[cols].applymap( lambda x: lambda_long_number_format(x, 1)) elif data_type == "technical": cols = ["Volume"] df_screen[cols] = df_screen[cols].applymap( lambda x: lambda_long_number_format(x, 1)) print_rich_table( df_screen.head(n=limit), headers=list(df_screen.columns), show_index=False, title="Finviz Screener", ) console.print("") export_data( export, os.path.dirname(os.path.abspath(__file__)), data_type, df_screen, ) return list(df_screen.head(n=limit)["Ticker"].values) console.print("") return []
def pos_command(sort="dpp_dollar", ascending: bool = False, num: int = 10): """Dark pool short position [Stockgrid]""" # Debug user input if imps.DEBUG: logger.debug("dps-pos %s %s", sort, num) # Check for argument possible_sorts = ("sv", "sv_pct", "nsv", "nsv_dollar", "dpp", "dpp_dollar") if sort not in possible_sorts: raise Exception(f"The possible sorts are: {', '.join(possible_sorts)}") if num < 0: raise Exception("Number has to be above 0") # Retrieve data df = stockgrid_model.get_dark_pool_short_positions(sort, ascending) if df.empty: raise Exception("No available data found") df = df.iloc[:num] # Debug user output if imps.DEBUG: logger.debug(df.to_string()) # Output data title = "Stocks: [Stockgrid] Dark Pool Short Position" df = df.applymap(lambda x: lambda_long_number_format(x, 2)) df = df.drop(columns=["Date"]) formats = { "Short Volume %": "{}%", "Net Short Volume $": "${}", "Dark Pools Position $": "${}", } for col, f in formats.items(): df[col] = df[col].map(lambda x: f.format(x)) # pylint: disable=W0640 df["Short Volume"] = df.apply( lambda x: f"{x['Short Volume']} (<b>{x['Short Volume %']}</b>)", axis=1) df["Net Short Volume"] = df.apply( lambda x: f"{x['Net Short Volume']:>9} (<b>{x['Net Short Volume $']:>9}</b>)", axis=1, ) df["Dark Pools Position"] = df.apply( lambda x: f"{x['Dark Pools Position']:>9} (<b>{x['Dark Pools Position $']:>9}</b>)", axis=1, ) df = df.drop(columns=[ "Short Volume %", "Net Short Volume $", "Dark Pools Position $" ]) df.columns = [ "Ticker", "Short Vol.", "Net Short Vol.", "DP Position", ] df.set_index("Ticker", inplace=True) dindex = len(df.index) if dindex > 15: embeds: list = [] # Output i, i2, end = 0, 0, 15 df_pg, embeds_img, images_list = [], [], [] while i < dindex: df_pg = df.iloc[i:end] df_pg.append(df_pg) fig = imps.plot_df( df_pg, fig_size=(720, (40 * dindex)), col_width=[2, 4, 4, 4], 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 = "dps-pos.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 += 15 end += 15 # 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, fig_size=(720, (40 * dindex)), col_width=[2, 4, 4, 4], 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("dps-pos.png", fig) output = { "title": title, "imagefile": imagefile, } return output
def display_account_growth( kind: str = "total", cumulative: bool = False, top: int = 90, export: str = "", external_axes: Optional[List[plt.Axes]] = None, ) -> None: """Display terra blockchain account growth history [Source: https://fcd.terra.dev/swagger] Parameters ---------- top: int Number of records to display kind: str display total account count or active account count. One from list [active, total] cumulative: bool Flag to show cumulative or discrete values. For active accounts only discrete value are available. export : str Export dataframe data to csv,json,xlsx file external_axes : Optional[List[plt.Axes]], optional External axes (1 axis is expected in the list), by default None """ df = terramoney_fcd_model.get_account_growth(cumulative) if kind not in ["active", "total"]: kind = "total" options = {"total": "Total accounts", "active": "Active accounts"} opt = options[kind] label = "Cumulative" if cumulative and opt == "total" else "Daily" # 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 df = df.sort_values("date", ascending=False).head(top) df = df.set_index("date") start, end = df.index[-1], df.index[0] if cumulative: ax.plot(df[opt], label=df[opt]) else: ax.bar(x=df.index, height=df[opt], label=df[opt]) ax.set_ylabel(f"{opt}") ax.get_yaxis().set_major_formatter( ticker.FuncFormatter(lambda x, _: lambda_long_number_format(x))) ax.set_title( f"{label} number of {opt.lower()} in period from {start} to {end}") cfg.theme.style_primary_axis(ax) if not external_axes: cfg.theme.visualize_output() export_data( export, os.path.dirname(os.path.abspath(__file__)), "gacc", df, )