class_docstr: The steps to using a handler
  1. initialized data handler  (call by `init`).
  2. use the data.
  
  
  The data handler try to maintain a handler with 2 level.
  `datetime` & `instruments`.
  
  Any order of the index level can be supported (The order will be implied in the data).
  The order  <`datetime`, `instruments`> will be used when the dataframe index name is missed.
  
  Example of the data:
  The multi-index of the columns is optional.
  
  .. code-block:: text
  
                              feature                                                            label
                              $close     $volume  Ref($close, 1)  Mean($close, 3)  $high-$low  LABEL0
      datetime   instrument
      2010-01-04 SH600000    81.807068  17145150.0       83.737389        83.016739    2.741058  0.0032
                 SH600004    13.313329  11800983.0       13.313329        13.317701    0.183632  0.0042
                 SH600005    37.796539  12231662.0       38.258602        37.919757    0.970325  0.0289
  
  
  Tips for improving the performance of datahandler
  - Fetching data with `col_set=CS_RAW` will return the raw data and may avoid pandas from copying the data when calling `loc`
docstr: fetch data from underlying data source
  
  Design motivation:
  - providing a unified interface for underlying data.
  - Potential to make the interface more friendly.
  - User can improve performance when fetching data in this extra layer
  
  Parameters
  ----------
  selector : Union[pd.Timestamp, slice, str]
      describe how to select data by index
      It can be categories as following
  
      - fetch single index
      - fetch a range of index
  
          - a slice range
          - pd.Index for specific indexes
  
      Following conflicts may occur
  
      - Does ["20200101", "20210101"] mean selecting this slice or these two days?
  
          - slice have higher priorities
  
  level : Union[str, int]
      which index level to select the data
  
  col_set : Union[str, List[str]]
  
      - if isinstance(col_set, str):
  
          select a set of meaningful, pd.Index columns.(e.g. features, columns)
  
          - if col_set == CS_RAW:
  
              the raw dataset will be returned.
  
      - if isinstance(col_set, List[str]):
  
          select several sets of meaningful columns, the returned data has multiple levels
  
  proc_func: Callable
  
      - Give a hook for processing data before fetching
      - An example to explain the necessity of the hook:
  
          - A Dataset learned some processors to process data which is related to data segmentation
          - It will apply them every time when preparing data.
          - The learned processor require the dataframe remains the same format when fitting and applying
          - However the data format will change according to the parameters.
          - So the processors should be applied to the underlayer data.
  
  squeeze : bool
      whether squeeze columns and index
  
  Returns
  -------
  pd.DataFrame.
code: def fetch(
      self,
      selector: Union[pd.Timestamp, slice, str, pd.Index] = slice(
          None, None
      ),
      level: Union[str, int] = "datetime",
      col_set: Union[str, List[str]] = CS_ALL,
      squeeze: bool = False,
      proc_func: Callable = None,
  ) -> pd.DataFrame:
      """
      fetch data from underlying data source
  
      Design motivation:
      - providing a unified interface for underlying data.
      - Potential to make the interface more friendly.
      - User can improve performance when fetching data in this extra layer
  
      Parameters
      ----------
      selector : Union[pd.Timestamp, slice, str]
          describe how to select data by index
          It can be categories as following
  
          - fetch single index
          - fetch a range of index
  
              - a slice range
              - pd.Index for specific indexes
  
          Following conflicts may occur
  
          - Does ["20200101", "20210101"] mean selecting this slice or these two days?
  
              - slice have higher priorities
  
      level : Union[str, int]
          which index level to select the data
  
      col_set : Union[str, List[str]]
  
          - if isinstance(col_set, str):
  
              select a set of meaningful, pd.Index columns.(e.g. features, columns)
  
              - if col_set == CS_RAW:
  
                  the raw dataset will be returned.
  
          - if isinstance(col_set, List[str]):
  
              select several sets of meaningful columns, the returned data has multiple levels
  
      proc_func: Callable
  
          - Give a hook for processing data before fetching
          - An example to explain the necessity of the hook:
  
              - A Dataset learned some processors to process data which is related to data segmentation
              - It will apply them every time when preparing data.
              - The learned processor require the dataframe remains the same format when fitting and applying
              - However the data format will change according to the parameters.
              - So the processors should be applied to the underlayer data.
  
      squeeze : bool
          whether squeeze columns and index
  
      Returns
      -------
      pd.DataFrame.
      """
      return self._fetch_data(
          data_storage=self._data,
          selector=selector,
          level=level,
          col_set=col_set,
          squeeze=squeeze,
          proc_func=proc_func,
      )
  
imports: import warnings
  from typing import Callable, Union, Tuple, List, Iterator, Optional
  import pandas
  from qlib.typehint import Literal
  from ...log import get_module_logger, TimeInspector
  from ...utils import init_instance_by_config
  from ...utils.serial import Serializable
  from .utils import fetch_df_by_index, fetch_df_by_col
  from ...utils import lazy_sort_index
  from .loader import DataLoader
  from .None import processor
  from .None import loader
label_desc: Use image node_id 4 for calling the DataHandler obj's underlying member method code with example usage: obj.fetch(selector, level, col_set, squeeze, proc_func) and returns: self