docstr: Fetching price history window from the exchange bundle.
  
  Parameters
  ----------
  exchange: Exchange
  assets: list[TradingPair]
  end_dt: datetime
  bar_count: int
  frequency: str
  field: str
  data_frequency: str
  ffill: bool
  
  Returns
  -------
  DataFrame
docstr_tok: ["Fetching","price","history","window","from","the","exchange","bundle",".","Parameters","--","--","--","--","--","exchange",":","Exchange","assets",":","list","[","TradingPair","]","end_dt",":","datetime","bar_count",":","int","frequency",":","str","field",":","str","data_frequency",":","str","ffill",":","bool","Returns","--","--","--","-","DataFrame"]
code: def get_exchange_history_window(
      self,
      exchange_name,
      assets,
      end_dt,
      bar_count,
      frequency,
      field,
      data_frequency,
      ffill=True,
  ):
      """
      Fetching price history window from the exchange bundle.
  
      Parameters
      ----------
      exchange: Exchange
      assets: list[TradingPair]
      end_dt: datetime
      bar_count: int
      frequency: str
      field: str
      data_frequency: str
      ffill: bool
  
      Returns
      -------
      DataFrame
  
      """
      # TODO: verify that the exchange supports the timeframe
      bundle = self.exchange_bundles[
          exchange_name
      ]  # type: ExchangeBundle
  
      freq, candle_size, unit, adj_data_frequency = get_frequency(
          frequency, data_frequency, supported_freqs=["T", "D"]
      )
      adj_bar_count = candle_size * bar_count
  
      if data_frequency == "minute":
          # for minute frequency always request data until the
          # current minute (do not include the current minute)
          last_dt_for_series = end_dt - datetime.timedelta(minutes=1)
  
          # read the minute bundles for daily frequency to
          # support last partial candle
          # TODO: optimize this by applying this logic only for the last day
          if adj_data_frequency == "daily":
              adj_data_frequency = "minute"
              adj_bar_count = adj_bar_count * 1440
  
      else:  # data_frequency == "daily":
          last_dt_for_series = end_dt
  
      series = bundle.get_history_window_series_and_load(
          assets=assets,
          end_dt=last_dt_for_series,
          bar_count=adj_bar_count,
          field=field,
          data_frequency=adj_data_frequency,
          algo_end_dt=self._last_available_session,
      )
  
      start_dt = get_start_dt(
          last_dt_for_series, adj_bar_count, adj_data_frequency, False
      )
      df = resample_history_df(
          pd.DataFrame(series), freq, field, start_dt
      )
  
      return df
  
imports: import abc
  import datetime
  import numpy
  import pandas
  from catalyst.assets._assets import TradingPair
  from catalyst.constants import LOG_LEVEL, AUTO_INGEST
  from catalyst.data.data_portal import DataPortal
  from catalyst.exchange.exchange_bundle import ExchangeBundle
  from catalyst.exchange.exchange_errors import ExchangeRequestError, PricingDataNotLoadedError
  from catalyst.exchange.utils.exchange_utils import resample_history_df, group_assets_by_exchange
  from catalyst.exchange.utils.datetime_utils import get_frequency, get_start_dt
  from logbook import Logger
  from redo import retry
label_desc: Use image node_id 3 for calling the DataPortalExchangeBacktest obj's underlying member method code with example usage: obj.get_exchange_history_window(exchange_name, assets, end_dt, bar_count, frequency, field, data_frequency, ffill) and returns: df