docstr: Gets aggregate trade data in batches and combines the results together.
  
  Returns all results as a pandas DataFrame.
  
  Args:
      executor (ThreadPoolExecutor): Executor to use when mapping API calls as tasks.
      total_results (int): Total number of results to fetch.
      params (Dict): Overall request params to be split into batches.
docstr_tok: ["Gets","aggregate","trade","data","in","batches","and","combines","the","results","together",".","Returns","all","results","as","a","pandas","DataFrame",".","Args",":","executor","(","ThreadPoolExecutor",")",":","Executor","to","use","when","mapping","API","calls","as","tasks",".","total_results","(","int",")",":","Total","number","of","results","to","fetch",".","params","(","Dict",")",":","Overall","request","params","to","be","split","into","batches","."]
code: def _get_batch_klines(
      self,
      executor: ThreadPoolExecutor,
      total_results: int,
      params: Dict,
  ) -> pd.DataFrame:
      """Gets aggregate trade data in batches and combines the results together.
  
      Returns all results as a pandas DataFrame.
  
      Args:
          executor (ThreadPoolExecutor): Executor to use when mapping API calls as tasks.
          total_results (int): Total number of results to fetch.
          params (Dict): Overall request params to be split into batches.
      """
      interval_duration_ms = interval_str_to_duration_ms(
          params["interval"]
      )
      if "end_time" not in params:
          # Default to get all klines before the current time.
          overall_end_ms = int(time.time() * 1000)
      else:
          overall_end_ms = params["end_time"]
  
      if "start_time" not in params:
          total_duration_ms = interval_duration_ms * total_results
          # Infer start time based on the interval and how many klines we need to fetch.
          overall_start_ms = overall_end_ms - total_duration_ms
      else:
          overall_start_ms = params["start_time"]
  
      next_params = params.copy()
      next_params["start_time"] = overall_start_ms
      duration_per_api_call_ms = (
          interval_duration_ms
          * BinanceAggregatedTradesTable.DEFAULT_AGGREGATE_TRADE_LIMIT
      )
      next_params["end_time"] = min(
          overall_end_ms, overall_start_ms + duration_per_api_call_ms
      )
      all_params = [next_params.copy()]
      results_so_far = (
          BinanceAggregatedTradesTable.DEFAULT_AGGREGATE_TRADE_LIMIT
      )
      while (
          next_params["end_time"] < overall_end_ms
          and results_so_far < total_results
      ):
          next_params["limit"] = min(
              BinanceAggregatedTradesTable.DEFAULT_AGGREGATE_TRADE_LIMIT,
              total_results - results_so_far,
          )
          next_params["start_time"] = next_params["end_time"]
          next_params["end_time"] = min(
              overall_end_ms,
              next_params["start_time"] + duration_per_api_call_ms,
          )
          all_params.append(next_params.copy())
          results_so_far += next_params["limit"]
  
      aggregated_trade_subdatas = list(
          executor.map(
              lambda p: self.handler.call_binance_api(
                  method_name="klines", params=p
              ),
              all_params,
          )
      )
      if not aggregated_trade_subdatas:
          return pd.DataFrame([])
  
      aggregated_trade_data = aggregated_trade_subdatas[0]
      for aggregated_trade_subdata in aggregated_trade_subdatas[1:]:
          aggregated_trade_data = pd.concat(
              [aggregated_trade_data, aggregated_trade_subdata]
          )
      return aggregated_trade_data
  
file_path: mindsdb/mindsdb/integrations/handlers/binance_handler/binance_tables.py
imports: from mindsdb.integrations.libs.api_handler import APITable
  from mindsdb.integrations.libs.response import HandlerResponse
  from mindsdb.integrations.utilities.date_utils import interval_str_to_duration_ms, utc_date_str_to_timestamp_ms
  from mindsdb.integrations.utilities.sql_utils import extract_comparison_conditions
  from mindsdb_sql.parser import ast
  from concurrent.futures import ThreadPoolExecutor
  from typing import Dict, List
  import pandas
  import time
label_desc: Use image node_id 1 for calling the BinanceAggregatedTradesTable obj's underlying member method code with example usage: obj._get_batch_klines(executor, total_results, params) and returns: aggregated_trade_data, pd