class_docstr: Interface for performing queries against exchange API's
      
class_docstr_tok: ["Interface","for","performing","queries","against","exchange","API","'s"]
docstr: Get historical OHLCV for a symbol pair
  
  Decorators:
      retry
  
  Args:
      market_pair (str): Contains the symbol pair to operate on i.e. BURST/BTC
      exchange (str): Contains the exchange to fetch the historical data from.
      time_unit (str): A string specifying the ccxt time unit i.e. 5m or 1d.
      start_date (int, optional): Timestamp in milliseconds.
      max_periods (int, optional): Defaults to 100. Maximum number of time periods
        back to fetch data for.
  
  Returns:
      list: Contains a list of lists which contain timestamp, open, high, low, close, volume.
docstr_tok: ["Get","historical","OHLCV","for","a","symbol","pair","Decorators",":","retry","Args",":","market_pair","(","str",")",":","Contains","the","symbol","pair","to","operate","on","i.e",".","BURST\/BTC","exchange","(","str",")",":","Contains","the","exchange","to","fetch","the","historical","data","from",".","time_unit","(","str",")",":","A","string","specifying","the","ccxt","time","unit","i.e",".","5m","or","1d",".","start_date","(","int",",","optional",")",":","Timestamp","in","milliseconds",".","max_periods","(","int",",","optional",")",":","Defaults","to","100",".","Maximum","number","of","time","periods","back","to","fetch","data","for",".","Returns",":","list",":","Contains","a","list","of","lists","which","contain","timestamp",",","open",",","high",",","low",",","close",",","volume","."]
code: def get_historical_data(
      self,
      market_pair,
      exchange,
      time_unit,
      start_date=None,
      max_periods=100,
  ):
      """Get historical OHLCV for a symbol pair
  
      Decorators:
          retry
  
      Args:
          market_pair (str): Contains the symbol pair to operate on i.e. BURST/BTC
          exchange (str): Contains the exchange to fetch the historical data from.
          time_unit (str): A string specifying the ccxt time unit i.e. 5m or 1d.
          start_date (int, optional): Timestamp in milliseconds.
          max_periods (int, optional): Defaults to 100. Maximum number of time periods
            back to fetch data for.
  
      Returns:
          list: Contains a list of lists which contain timestamp, open, high, low, close, volume.
      """
  
      try:
          if time_unit not in self.exchanges[exchange].timeframes:
              raise ValueError(
                  "{} does not support {} timeframe for OHLCV data. Possible values are: {}".format(
                      exchange,
                      time_unit,
                      list(self.exchanges[exchange].timeframes),
                  )
              )
      except AttributeError:
          self.logger.error(
              "%s interface does not support timeframe queries! We are unable to fetch data!",
              exchange,
          )
          raise AttributeError(sys.exc_info())
  
      if not start_date:
          timeframe_regex = re.compile("([0-9]+)([a-zA-Z])")
          timeframe_matches = timeframe_regex.match(time_unit)
          time_quantity = timeframe_matches.group(1)
          time_period = timeframe_matches.group(2)
  
          timedelta_values = {
              "m": "minutes",
              "h": "hours",
              "d": "days",
              "w": "weeks",
              "M": "months",
              "y": "years",
          }
  
          timedelta_args = {
              timedelta_values[time_period]: int(time_quantity)
          }
  
          start_date_delta = timedelta(**timedelta_args)
  
          max_days_date = datetime.now() - (
              max_periods * start_date_delta
          )
          start_date = int(
              max_days_date.replace(tzinfo=timezone.utc).timestamp()
              * 1000
          )
  
      historical_data = self.exchanges[exchange].fetch_ohlcv(
          market_pair, timeframe=time_unit, since=start_date
      )
  
      if not historical_data:
          raise ValueError(
              "No historical data provided returned by exchange."
          )
  
      # Sort by timestamp in ascending order
      historical_data.sort(key=lambda d: d[0])
  
      time.sleep(self.exchanges[exchange].rateLimit / 1000)
  
      return historical_data
  
file_path: Crypto-Signal/app/exchange.py
imports: import re
  import sys
  import time
  from datetime import datetime, timedelta, timezone
  import ccxt
  import structlog
  from tenacity import retry, retry_if_exception_type, stop_after_attempt
label_desc: Use image node_id 2 for calling the ExchangeInterface obj's underlying member method code with example usage: obj.get_historical_data(market_pair, exchange, time_unit, start_date, max_periods) and returns: historical_data