code: """Rolling Statistics"""
  __docformat__ = "numpy"
  
  import logging
  from typing import Tuple
  
  import pandas as pd
  import pandas_ta as ta
  
  from gamestonk_terminal.decorators import log_start_end
  
  logger = logging.getLogger(__name__)
  
  
  @log_start_end(log=logger)
  def get_rolling_avg(df: pd.DataFrame, length: int) -> Tuple[pd.DataFrame, pd.DataFrame]:
      """Return rolling mean and standard deviation
  
      Parameters
      ----------
      df_stock : pd.DataFrame
          Dataframe of target data
      length : int
          Length of rolling window
  
      Returns
      -------
      pd.DataFrame :
          Dataframe of rolling mean
      pd.DataFrame :
          Dataframe of rolling standard deviation
      """
      rolling_mean = df.rolling(length, center=True, min_periods=1).mean()
      rolling_std = df.rolling(length, center=True, min_periods=1).std()
  
      return pd.DataFrame(rolling_mean), pd.DataFrame(rolling_std)
  
  
  @log_start_end(log=logger)
  def get_spread(df: pd.DataFrame, length: int) -> Tuple[pd.DataFrame, pd.DataFrame]:
      """Standard Deviation and Variance
  
      Parameters
      ----------
      df_stock : pd.DataFrame
          DataFrame of targeted data
  
      Returns
      -------
      df_sd : pd.DataFrame
          Dataframe of rolling standard deviation
      df_var : pd.DataFrame
          Dataframe of rolling standard deviation
      """
      df_sd = ta.stdev(
          close=df,
          length=length,
      ).dropna()
      df_var = ta.variance(
          close=df,
          length=length,
      ).dropna()
  
      return pd.DataFrame(df_sd), pd.DataFrame(df_var)
  
  
  @log_start_end(log=logger)
  def get_quantile(
      df: pd.DataFrame, length: int, quantile_pct: float
  ) -> Tuple[pd.DataFrame, pd.DataFrame]:
      """Overlay Median & Quantile
  
      Parameters
      ----------
      df : pd.DataFrame
          Dataframe of targeted data
      length : int
          Length of window
      quantile : float
          Quantile to display
  
      Returns
      -------
      df_med : pd.DataFrame
          Dataframe of median prices over window
      df_quantile : pd.DataFrame
          Dataframe of gievn quantile prices over window
      """
      df_med = ta.median(close=df, length=length).dropna()
      df_quantile = ta.quantile(
          df,
          length=length,
          q=quantile_pct,
      ).dropna()
  
      return pd.DataFrame(df_med), pd.DataFrame(df_quantile)
  
  
  @log_start_end(log=logger)
  def get_skew(df: pd.DataFrame, length: int) -> pd.DataFrame:
      """Skewness Indicator
  
      Parameters
      ----------
      df_stock : pd.DataFrame
          Dataframe of targeted data
      length : int
          Length of window
  
      Returns
      -------
      df_skew : pd.DataFrame
          Dataframe of rolling skew
      """
      df_skew = ta.skew(close=df, length=length).dropna()
      return df_skew
  
  
  @log_start_end(log=logger)
  def get_kurtosis(df: pd.DataFrame, length: int) -> pd.DataFrame:
      """Kurtosis Indicator
  
      Parameters
      ----------
      df_stock : pd.DataFrame
          Dataframe of targeted data
      length : int
          Length of window
  
      Returns
      -------
      df_kurt : pd.DataFrame
          Dataframe of rolling kurtosis
      """
      df_kurt = ta.kurtosis(close=df, length=length).dropna()
      return df_kurt
   """Portfolio View"""
  __docformat__ = "numpy"
  
  import logging
  from typing import List, Optional
  import os
  
  import numpy as np
  import pandas as pd
  from matplotlib import pyplot as plt
  
  from gamestonk_terminal.config_terminal import theme
  from gamestonk_terminal.config_plot import PLOT_DPI
  from gamestonk_terminal.portfolio import (
      portfolio_model,
  )
  
  from gamestonk_terminal.helper_funcs import (
      plot_autoscale,
      export_data,
  )
  from gamestonk_terminal.decorators import log_start_end
  from gamestonk_terminal.rich_config import console
  
  # from reportlab.lib.pagesizes import letter
  # from reportlab.pdfgen import canvas
  # from reportlab.lib.utils import ImageReader
  # from gamestonk_terminal.portfolio import reportlab_helpers
  
  logger = logging.getLogger(__name__)
  
  
  @log_start_end(log=logger)
  def load_info():
      """Prints instructions to load a CSV
  
      Returns
      ----------
      text : str
          Information on how to load a csv
      """
      text = """
  In order to load a CSV do the following:
  
  1. Add headers to the first row, below is data for each column:\n
  \t1. Identifier for the asset (such as a stock ticker)
  \t2. Type of asset (stock, bond, option, crypto)
  \t3. The volume of the asset transacted
  \t4. The buy date in yyyy/mm/dd
  \t5. The Price paid for the asset
  \t6. Any fees paid during the transaction
  \t7. A premium paid or received if this was an option
  \t8. Whether the asset was bought (covered) or sold (shorted)\n
  2. Place this file in gamestonk_terminal/portfolio/portfolios\n
          """
      console.print(text)
  
  
  @log_start_end(log=logger)
  def display_returns_vs_bench(
      portfolio: portfolio_model.Portfolio,
      benchmark: str = "SPY",
      external_axes: Optional[plt.Axes] = None,
  ):
      """Display portfolio returns vs benchmark
  
      Parameters
      ----------
      portfolio: Portfolio
          Custom portfolio object with trade list
      benchmark: str
          Symbol for benchmark.  Defaults to SPY
      external_axes: plt.Axes
          Optional axes to display plot on
      """
      if external_axes is None:
          _, ax = plt.subplots(figsize=plot_autoscale(), dpi=PLOT_DPI)
      else:
          ax = external_axes
  
      portfolio.generate_holdings_from_trades()
      portfolio.add_benchmark(benchmark)
  
      cumulative_returns = (1 + portfolio.returns).cumprod()
      benchmark_c_returns = (1 + portfolio.benchmark_returns).cumprod()
  
      ax.plot(cumulative_returns.index, cumulative_returns, label="Portfolio")
      ax.plot(benchmark_c_returns.index, benchmark_c_returns, label="Benchmark")
      ax.set_ylabel("Cumulative Returns")
      ax.legend(loc="upper left")
      theme.style_primary_axis(ax)
      if not external_axes:
          theme.visualize_output()
  
  
  @log_start_end(log=logger)
  def display_allocation(
      portfolio: portfolio_model.Portfolio,
      export: str = "",
      external_axes: Optional[plt.Axes] = None,
  ):
      """Display allocation of assets vs time
  
      Parameters
      ----------
      portfolio: Portfolio
          Portfolio object with trades loaded
      export: str
          Format to export plot
      external_axes: plt.Axes
          Optional axes to display plot on
      """
      portfolio.generate_holdings_from_trades()
      all_holdings = pd.concat(
          [
              portfolio.portfolio["StockHoldings"],
              portfolio.portfolio["ETFHoldings"],
              portfolio.portfolio["CryptoHoldings"],
          ],
          axis=1,
      )
      all_holdings = all_holdings.drop(columns=["temp"])
  
      if external_axes is None:
          _, ax = plt.subplots(figsize=plot_autoscale(), dpi=PLOT_DPI)
      else:
          ax = external_axes
      all_holdings.plot(ax=ax)
      ax.set_title("Individual Asset Holdings")
      ax.legend(loc="upper left")
      ax.set_ylabel("Holdings ($)")
      theme.style_primary_axis(ax)
      if external_axes is None:
          theme.visualize_output()
  
      export_data(
          export,
          os.path.dirname(os.path.abspath(__file__)),
          "rolling",
      )
  
  
  @log_start_end(log=logger)
  def display_rolling_stats(
      portfolio: portfolio_model.Portfolio,
      length: int = 60,
      benchmark: str = "SPY",
      risk_free_rate: float = 0,
      external_axes: Optional[List[plt.Axes]] = None,
      export: str = "",
  ):
      """Display portfolio returns vs benchmark
  
      Parameters
      ----------
      portfolio: Portfolio
          Custom portfolio object with trade list
      length: int
          Length of rolling window
      benchmark: str
          Symbol for benchmark.  Defaults to SPY
      risk_free_rate: float
          Value to use for risk free rate in sharpe/other calculations
      external_axes: Optional[List[plt.Axes]]
          Optional axes to display plot on
      export: str
          Export to file
      """
      portfolio.generate_holdings_from_trades()
      portfolio.add_benchmark(benchmark)
      portfolio.add_rf(risk_free_rate)
      if external_axes is None:
          _, ax = plt.subplots(4, 1, figsize=(8, 8), dpi=PLOT_DPI, sharex=True)
      else:
          if len(external_axes) != 4:
              console.print("[red]4 axes expected./n[/red]")
              return
          ax = external_axes
      rolling_volatility = portfolio.returns.rolling(length).std()
      rolling_volatility_bench = portfolio.benchmark_returns.rolling(length).std()
  
      rolling_sharpe = portfolio.returns.rolling(length).apply(
          lambda x: (x.mean() - risk_free_rate) / x.std()
      )
      rolling_sharpe_bench = portfolio.benchmark_returns.rolling(length).apply(
          lambda x: (x.mean() - risk_free_rate) / x.std()
      )
  
      rolling_volatility.plot(ax=ax[1])
      rolling_volatility_bench.plot(ax=ax[1])
      ax[1].set_title("Rolling Volatility")
  
      rolling_sharpe.plot(ax=ax[2])
      rolling_sharpe_bench.plot(ax=ax[2])
      ax[2].set_title("Rolling Sharpe Ratio")
  
      # Rolling beta is defined as Cov(Port,Bench)/var(Bench)
      covs = (
          pd.DataFrame(
              {"Portfolio": portfolio.returns, "Benchmark": portfolio.benchmark_returns}
          )
          .dropna(axis=0)
          .rolling(length)
          .cov()
          .unstack()
          .dropna()
      )
      rolling_beta = covs["Portfolio"]["Benchmark"] / covs["Benchmark"]["Benchmark"]
      rolling_beta.plot(ax=ax[3])
      ax[3].set_title("Rolling Beta to Benchmark")
  
      c_returns = (1 + portfolio.returns).cumprod()
      bench_c_rets = (1 + portfolio.benchmark_returns).cumprod()
  
      ax[0].plot(c_returns.index, c_returns)
      ax[0].plot(bench_c_rets.index, bench_c_rets)
      ax[0].set_title("Cumulative Returns")
  
      if external_axes is None:
  
          for a in ax[0], ax[1], ax[2]:
              a.legend(["Portfolio", "Benchmark"], loc="upper left")
          for a in ax[0], ax[1], ax[2], ax[3]:
              a.set_xlim(portfolio.returns.index[0], portfolio.returns.index[-1])
              a.set_xlabel([])
              a.grid("on")
              theme.style_primary_axis(a)
  
          ax[3].set_xlabel("Date")
  
          theme.visualize_output()
      export_data(
          export,
          os.path.dirname(os.path.abspath(__file__)),
          "rolling",
      )
  
  
  @log_start_end(log=logger)
  def display_drawdown(
      holdings: pd.DataFrame,
      export: str = "",
      external_axes: Optional[List[plt.Axes]] = None,
  ):
      """Display drawdown curve
  
      Parameters
      ----------
      holdings: pd.DataFrame
          Dataframe of holdings vs time
      export: str
          Format to export data
      external_axes: plt.Axes
          Optional axes to display plot on
      """
      drawdown = portfolio_model.calculate_drawdown(holdings)
      if external_axes is None:
          _, ax = plt.subplots(2, 1, figsize=plot_autoscale(), dpi=PLOT_DPI, sharex=True)
      else:
          ax = external_axes
  
      ax[0].plot(holdings.index, holdings)
      ax[0].set_title("Holdings")
      ax[1].plot(holdings.index, drawdown)
      ax[1].fill_between(holdings.index, np.asarray(drawdown), alpha=0.4)
      ax[1].set_title("Portfolio Drawdown")
  
      theme.style_primary_axis(ax[1])
      if external_axes is None:
          theme.visualize_output()
      export_data(
          export,
          os.path.dirname(os.path.abspath(__file__)),
          "dd",
      )
  
  
  #
  # @log_start_end(log=logger)
  # def plot_overall_return(
  #     comb: pd.DataFrame, m_tick: str, plot: bool = False
  # ) -> ImageReader:
  #     """Generates overall return graph
  #
  #     Parameters
  #     ----------
  #     comb : pd.DataFrame
  #         Dataframe with returns
  #     m_tick : str
  #         The ticker for the market asset
  #     plot : bool
  #         Whether to plot the graph or return it for PDF
  #
  #     Returns
  #     ----------
  #     img : ImageReader
  #         Overal return graph
  #     """
  #     fig, ax = plt.subplots(figsize=(10, 5))
  #     ax.plot(comb.index, comb["return"], color="tab:blue", label="Portfolio")
  #     ax.plot(comb.index, comb[("Market", "Return")], color="orange", label=m_tick)
  #
  #     ax.set_ylabel("", fontweight="bold", fontsize=12, color="black")
  #     ax.set_xlabel("")
  #     ax.yaxis.set_label_coords(-0.1, 0.5)
  #     ax.grid(True)
  #     ax.spines["top"].set_visible(False)
  #     ax.spines["right"].set_visible(False)
  #     ax.spines["bottom"].set_visible(False)
  #     ax.spines["left"].set_visible(False)
  #     fig.suptitle(
  #         "Cumulative Performance", y=0.99, fontweight="bold", fontsize=14, color="black"
  #     )
  #     ax.axhline(0, ls="-", lw=1, color="gray", zorder=1)
  #     ax.axhline(0, ls="--", lw=1, color="black", zorder=2)
  #     fig.set_facecolor("white")
  #     ax.set_title(
  #         f'{comb.index[:1][0].strftime("%Y/%m/%d")} - {comb.index[-1:][0].strftime("%Y/%m/%d")}',
  #         fontsize=12,
  #         color="gray",
  #     )
  #     ax.yaxis.set_major_formatter(mtick.PercentFormatter(1.0))
  #     ax.set_facecolor("white")
  #     ax.legend()
  #     fig.autofmt_xdate()
  #     if plot:
  #         plt.show()
  #         console.print("")
  #         return None
  #     imgdata = BytesIO()
  #     fig.savefig(imgdata, format="png")
  #     plt.close("all")
  #     imgdata.seek(0)
  #     return ImageReader(imgdata)
  #
  #
  # @log_start_end(log=logger)
  # def plot_rolling_beta(df: pd.DataFrame) -> ImageReader:
  #     """Returns a chart with the portfolio's rolling beta
  #
  #     Parameters
  #     ----------
  #     df : pd.DataFrame
  #         The dataframe to be analyzed
  #
  #     Returns
  #     ----------
  #     img : ImageReader
  #         Rolling beta graph
  #     """
  #
  #     fig, ax = plt.subplots(figsize=(10, 5))
  #     ax.plot(
  #         df.index,
  #         df["total"],
  #         color="tab:blue",
  #     )
  #
  #     ax.set_ylabel("", fontweight="bold", fontsize=12, color="black")
  #     ax.set_xlabel("")
  #     ax.yaxis.set_label_coords(-0.1, 0.5)
  #     ax.grid(True)
  #     ax.spines["top"].set_visible(False)
  #     ax.spines["right"].set_visible(False)
  #     ax.spines["bottom"].set_visible(False)
  #     ax.spines["left"].set_visible(False)
  #     fig.suptitle(
  #         "Rolling Beta of Stocks", y=0.99, fontweight="bold", fontsize=14, color="black"
  #     )
  #     ax.axhline(0, ls="-", lw=1, color="gray", zorder=1)
  #     ax.axhline(0, ls="--", lw=1, color="black", zorder=2)
  #     fig.set_facecolor("white")
  #     ax.set_title(
  #         f'{df.index[:1][0].strftime("%Y-%m-%d")} - {df.index[-1:][0].strftime("%Y-%m-%d")}',
  #         color="gray",
  #     )
  #     ax.set_facecolor("white")
  #     fig.autofmt_xdate()
  #     imgdata = BytesIO()
  #     fig.savefig(imgdata, format="png")
  #     plt.close("all")
  #     imgdata.seek(0)
  #     return ImageReader(imgdata)
  #
  #
  # @log_start_end(log=logger)
  # def plot_ef(
  #     stocks: List[str],
  #     variance: float,
  #     per_ret: float,
  #     rf_rate: float,
  #     period: str = "3mo",
  #     n_portfolios: int = 300,
  #     risk_free: bool = False,
  # ):
  #     """Display efficient frontier
  #
  #     Parameters
  #     ----------
  #     stocks : List[str]
  #         List of the stocks to be included in the weights
  #     variance : float
  #         The variance for the portfolio
  #     per_ret : float
  #         The portfolio's return for the portfolio
  #     rf_rate : float
  #         The risk free rate
  #     period : str
  #         The period to track
  #     n_portfolios : int
  #         The number of portfolios to generate
  #     risk_free : bool
  #         Include the risk-free asset
  #     """
  #     fig, ax = plt.subplots(figsize=(10, 5), dpi=PLOT_DPI)
  #     ef, rets, stds = optimizer_model.generate_random_portfolios(
  #         [x.upper() for x in stocks], period, n_portfolios
  #     )
  #     sharpes = rets / stds
  #     ax.scatter(stds, rets, marker=".", c=sharpes, cmap="viridis_r")
  #     plotting.plot_efficient_frontier(ef, ax=ax, show_assets=True)
  #     # Find the tangency portfolio
  #     ret_sharpe, std_sharpe, _ = ef.portfolio_performance(risk_free_rate=rf_rate)
  #     ax.scatter(std_sharpe, ret_sharpe, marker="*", s=100, c="r", label="Max Sharpe")
  #     plt.plot(variance, per_ret, "ro", label="Portfolio")
  #     # Add risk free line
  #     if risk_free:
  #         y = ret_sharpe * 1.2
  #         m = (ret_sharpe - rf_rate) / std_sharpe
  #         x2 = (y - rf_rate) / m
  #         x = [0, x2]
  #         y = [rf_rate, y]
  #         line = Line2D(x, y, color="#FF0000", label="Capital Allocation Line")
  #         ax.set_xlim(xmin=min(stds) * 0.8)
  #         ax.add_line(line)
  #     ax.set_title(f"Efficient Frontier simulating {n_portfolios} portfolios")
  #     ax.legend()
  #     fig.tight_layout()
  #     ax.grid(b=True, which="major", color="#666666", linestyle="-")
  #
  #     if gtff.USE_ION:
  #         plt.ion()
  #
  #     imgdata = BytesIO()
  #     fig.savefig(imgdata, format="png")
  #     plt.close("all")
  #     imgdata.seek(0)
  #     return ImageReader(imgdata)
  
  
  # @log_start_end(log=logger)
  # def display_allocation2(data: pd.DataFrame, graph: bool):
  #     """Displays allocation
  #     Parameters
  #     ----------
  #     data: pd.DataFrame
  #         The portfolio allocation dataframe
  #     graph: bool
  #         If pie chart shall be displayed with table"""
  #
  #     print_rich_table(data, headers=list(data.columns), title="Allocation")
  #     console.print("")
  #
  #     if graph:
  #         graph_data = data[data["pct_allocation"] >= 5].copy()
  #         if not graph_data.empty:
  #             graph_data.loc["Other"] = [
  #                 "NA",
  #                 data["value"].sum() - graph_data["value"].sum(),
  #                 100 - graph_data["value"].sum(),
  #             ]
  #             labels = graph_data.index.values
  #             sizes = graph_data["value"].to_list()
  #         else:
  #             labels = data.index.values
  #             sizes = data["value"].to_list()
  #         fig, ax = plt.subplots()
  #         ax.pie(sizes, labels=labels, autopct="%1.1f%%", startangle=90)
  #         ax.axis("equal")
  #         ax.set_title("Portfolio Allocation")
  #         fig.set_tight_layout(True)
  #
  #         plt.show()
  
  #
  # class Report:
  #     @log_start_end(log=logger)
  #     def __init__(self, df: pd.DataFrame, hist: pd.DataFrame, m_tick: str):
  #         """Generate financial reports.
  #         Financial reports allow users to show the how they have been performing in
  #         trades. This allows for a simple way to show progress and analyze metrics
  #         that track portfolio performance
  #
  #         Parameters
  #         ----------
  #         df : pd.DataFrame
  #             The dataframe with previous holdings information
  #         hist : pd.DataFrame
  #             The dataframe with previous prices for stocks in the portfolio
  #         df_m : pd.DataFrame
  #             Dataframe of benchmark
  #         n : int
  #             The number of days to analyze
  #
  #         Attributes
  #         ----------
  #         generate_report : None
  #             Generates a report with the given parameters
  #         generate_pg1 : None
  #             Creates the first page of the PDF report
  #         generate_pg2 : None
  #             Creates the second page of the PDF report
  #
  #         """
  #         self.df = df
  #         self.hist = hist
  #         self.m_tick = m_tick
  #         self.df_m = yfinance_model.get_market(self.df.index[0], self.m_tick)
  #         # self.returns, self.variance = portfolio_model.get_return(df, self.df_m, n)
  #         self.returns = pd.DataFrame()
  #         self.rf = get_rf()
  #         self.betas = portfolio_model.get_rolling_beta(
  #             self.df, self.hist, self.df_m, 365
  #         )
  #
  #     @log_start_end(log=logger)
  #     def generate_report(self) -> None:
  #         d = path.dirname(path.abspath(__file__)).replace(
  #             "gamestonk_terminal", "exports"
  #         )
  #         loc = path.abspath(
  #             path.join(
  #                 d,
  #                 f"ar_{datetime.now().strftime('%Y%m%d_%H%M%S')}.pdf",
  #             )
  #         )
  #         report = canvas.Canvas(loc, pagesize=letter)
  #         reportlab_helpers.base_format(report, "Overview")
  #         self.generate_pg1(report)
  #         self.generate_pg2(report)
  #         report.save()
  #         console.print("File save in:\n", loc, "\n")
  #
  #     @log_start_end(log=logger)
  #     def generate_pg1(self, report: canvas.Canvas) -> None:
  #         report.drawImage(
  #             plot_overall_return(self.returns, self.m_tick, False), 15, 400, 600, 300
  #         )
  #         main_text = portfolio_model.get_main_text(self.returns)
  #         reportlab_helpers.draw_paragraph(report, main_text, 30, 410, 550, 200)
  #         current_return = self.returns["return"][-1]
  #         beta = self.betas["total"][-1]
  #         market_return = self.returns[("Market", "Return")][-1]
  #         sharpe = f"{(current_return - self.rf)/ np.std(self.returns['return']):.2f}"
  #         treynor = f"{(current_return - self.rf)/ beta:.2f}" if beta > 0 else "N/A"
  #         alpha = f"{current_return - (self.rf + beta * (market_return - self.rf)):.2f}"
  #         information = (
  #             f"{float(alpha)/ (np.std(self.returns['return'] - market_return)):.2f}"
  #         )
  #         perf = [
  #             ["Sharpe", sharpe],
  #             ["Treynor", treynor],
  #             ["Alpha", alpha],
  #             ["Information", information],
  #         ]
  #         reportlab_helpers.draw_table(report, "Performance", 540, 300, 30, perf)
  #         reportlab_helpers.draw_paragraph(
  #             report, portfolio_model.performance_text, 140, 290, 460, 200
  #         )
  #         report.showPage()
  #
  #     @log_start_end(log=logger)
  #     def generate_pg2(self, report: canvas.Canvas) -> None:
  #         reportlab_helpers.base_format(report, "Portfolio Analysis")
  #         if "Holding" in self.df.columns:
  #             report.drawImage(plot_rolling_beta(self.betas), 15, 400, 600, 300)
  #             main_t = portfolio_model.get_beta_text(self.betas)
  #             reportlab_helpers.draw_paragraph(report, main_t, 30, 410, 550, 200)
  #             # report.drawImage(plot_ef(uniques, self.variance, self.returns["return"][-1], self.rf), 15, 65, 600, 300)
   """ opensea.io Model """
  
  import logging
  from datetime import datetime
  
  import pandas as pd
  import requests
  
  from gamestonk_terminal.decorators import log_start_end
  
  logger = logging.getLogger(__name__)
  
  API_URL = "https://api.opensea.io/api/v1"
  
  
  @log_start_end(log=logger)
  def get_collection_stats(slug: str) -> pd.DataFrame:
      """Get stats of a nft collection [Source: opensea.io]
  
      Parameters
      -------
      slug : str
          Opensea collection slug. If the name of the collection is Mutant Ape Yacht Club the slug is mutant-ape-yacht-club
  
      Returns
      -------
      pd.DataFrame
          collection stats
      """
      res = requests.get(f"{API_URL}/collection/{slug}")
      if res.status_code == 200:
          data = res.json()
          collection = data["collection"]
          stats = collection["stats"]
          metrics = [
              "Name",
              "Floor Price (ETH)",
              "Number of Owners",
              "Market Cap (ETH)",
              "Average Price ETH",
              "One day volume (ETH)",
              "One day change (%)",
              "One day sales (ETH)",
              "One day average price (ETH)",
              "Thirty day volume (ETH)",
              "Thirty day change (%)",
              "Thirty day sales (ETH)",
              "Thirty day average price (ETH)",
              "Total Supply (ETH)",
              "Total Sales (ETH)",
              "Total Volume (ETH)",
              "Creation Date",
              "URL",
          ]
          values = [
              collection["name"],
              "-" if not stats["floor_price"] else float(stats["floor_price"]),
              round(float(stats["num_owners"]), 2),
              round(float(stats["market_cap"]), 2),
              round(float(stats["average_price"]), 2),
              round(float(stats["one_day_volume"]), 2),
              round(float(stats["one_day_change"]) * 100, 2),
              round(float(stats["one_day_sales"]), 2),
              round(float(stats["one_day_average_price"]), 2),
              round(float(stats["thirty_day_volume"]), 2),
              round(float(stats["thirty_day_change"]) * 100, 2),
              round(float(stats["thirty_day_sales"]), 2),
              round(float(stats["thirty_day_average_price"]), 2),
              round(float(stats["total_supply"]), 2),
              round(float(stats["total_sales"]), 2),
              round(float(stats["total_volume"]), 2),
              datetime.strptime(
                  collection["created_date"], "%Y-%m-%dT%H:%M:%S.%f"
              ).strftime("%b %d, %Y"),
              "-" if not collection["external_url"] else collection["external_url"],
          ]
          df = pd.DataFrame({"Metric": metrics, "Value": values})
          return df
      return pd.DataFrame()
  
apis: pandas.DataFrame
apis: numpy.asarray pandas.DataFrame pandas.concat matplotlib.pyplot.subplots
apis: pandas.DataFrame