class_docstr: Provides methods for retrieving daily stock data from
  Yahoo Finance API
code: def clean_data(self, df: pd.DataFrame) -> pd.DataFrame:
      tic_list = np.unique(df.tic.values)
      NY = "America/New_York"
  
      trading_days = self.get_trading_days(
          start=self.start, end=self.end
      )
      # produce full timestamp index
      if self.time_interval == "1d":
          times = trading_days
      elif self.time_interval == "1m":
          times = []
          for day in trading_days:
              #                NY = "America/New_York"
              current_time = pd.Timestamp(
                  day + " 09:30:00"
              ).tz_localize(NY)
              for i in range(390):  # 390 minutes in trading day
                  times.append(current_time)
                  current_time += pd.Timedelta(minutes=1)
      else:
          raise ValueError(
              "Data clean at given time interval is not supported for YahooFinance data."
          )
  
      # create a new dataframe with full timestamp series
      new_df = pd.DataFrame()
      for tic in tic_list:
          tmp_df = pd.DataFrame(
              columns=["open", "high", "low", "close", "volume"],
              index=times,
          )
          tic_df = df[
              df.tic == tic
          ]  # extract just the rows from downloaded data relating to this tic
          for i in range(
              tic_df.shape[0]
          ):  # fill empty DataFrame using original data
              tmp_df.loc[
                  tic_df.iloc[i]["timestamp"].tz_localize(NY)
              ] = tic_df.iloc[i][
                  ["open", "high", "low", "close", "volume"]
              ]
          # print("(9) tmp_df\n", tmp_df.to_string()) # print ALL dataframe to check for missing rows from download
  
          # if close on start date is NaN, fill data with first valid close
          # and set volume to 0.
          if str(tmp_df.iloc[0]["close"]) == "nan":
              print(
                  "NaN data on start date, fill using first valid data."
              )
              for i in range(tmp_df.shape[0]):
                  if str(tmp_df.iloc[i]["close"]) != "nan":
                      first_valid_close = tmp_df.iloc[i]["close"]
                      tmp_df.iloc[0] = [
                          first_valid_close,
                          first_valid_close,
                          first_valid_close,
                          first_valid_close,
                          0.0,
                      ]
                      break
  
          # if the close price of the first row is still NaN (All the prices are NaN in this case)
          if str(tmp_df.iloc[0]["close"]) == "nan":
              print(
                  "Missing data for ticker: ",
                  tic,
                  " . The prices are all NaN. Fill with 0.",
              )
              tmp_df.iloc[0] = [
                  0.0,
                  0.0,
                  0.0,
                  0.0,
                  0.0,
              ]
  
          # fill NaN data with previous close and set volume to 0.
          for i in range(tmp_df.shape[0]):
              if str(tmp_df.iloc[i]["close"]) == "nan":
                  previous_close = tmp_df.iloc[i - 1]["close"]
                  if str(previous_close) == "nan":
                      raise ValueError
                  tmp_df.iloc[i] = [
                      previous_close,
                      previous_close,
                      previous_close,
                      previous_close,
                      0.0,
                  ]
                  # print(tmp_df.iloc[i], " Filled NaN data with previous close and set volume to 0. ticker: ", tic)
  
          # merge single ticker data to new DataFrame
          tmp_df = tmp_df.astype(float)
          tmp_df["tic"] = tic
          new_df = pd.concat([new_df, tmp_df])
  
      #            print(("Data clean for ") + tic + (" is finished."))
  
      # reset index and rename columns
      new_df = new_df.reset_index()
      new_df = new_df.rename(columns={"index": "timestamp"})
  
      #        print("Data clean all finished!")
  
      return new_df
  
imports: from __future__ import annotations
  import datetime
  from datetime import date
  from datetime import timedelta
  from sqlite3 import Timestamp
  from typing import Any
  from typing import Dict
  from typing import List
  from typing import Optional
  from typing import Type
  from typing import TypeVar
  from typing import Union
  import exchange_calendars
  import numpy
  import pandas
  import pytz
  import yfinance
  from stockstats import StockDataFrame
label_desc: Use image node_id 4 for calling the YahooFinanceProcessor obj's underlying member method code with example usage: obj.clean_data(df) and returns: new_df