class_docstr: Base executor for trading
docstr: Generator for collecting the trade decision data for rl training
  
  his function will make a step forward
  
  Parameters
  ----------
  trade_decision : BaseTradeDecision
  
  level : int
      the level of current executor. 0 indicates the top level
  
  return_value : dict
      the mem address to return the value
      e.g.  {"return_value": <the executed result>}
  
  Returns
  ----------
  execute_result : List[object]
      the executed result for trade decision.
      ** NOTE!!!! **:
      1) This is necessary,  The return value of generator will be used in NestedExecutor
      2) Please note the executed results are not merged.
  
  Yields
  -------
  object
      trade decision
docstr_tok: ["Generator","for","collecting","the","trade","decision","data","for","rl","training","his","function","will","make","a","step","forward","Parameters","--","--","--","--","--","trade_decision",":","BaseTradeDecision","level",":","int","the","level","of","current","executor",".","0","indicates","the","top","level","return_value",":","dict","the","mem","address","to","return","the","value","e.g",".","{","``","return_value","''",":","<","the","executed","result",">","}","Returns","--","--","--","--","--","execute_result",":","List","[","object","]","the","executed","result","for","trade","decision",".","*","*","NOTE","!","!","!","!","*","*",":","1",")","This","is","necessary",",","The","return","value","of","generator","will","be","used","in","NestedExecutor","2",")","Please","note","the","executed","results","are","not","merged",".","Yields","--","--","--","-","object","trade","decision"]
code: def collect_data(
      self,
      trade_decision: BaseTradeDecision,
      return_value: dict | None = None,
      level: int = 0,
  ) -> Generator[Any, Any, List[object]]:
      """Generator for collecting the trade decision data for rl training
  
      his function will make a step forward
  
      Parameters
      ----------
      trade_decision : BaseTradeDecision
  
      level : int
          the level of current executor. 0 indicates the top level
  
      return_value : dict
          the mem address to return the value
          e.g.  {"return_value": <the executed result>}
  
      Returns
      ----------
      execute_result : List[object]
          the executed result for trade decision.
          ** NOTE!!!! **:
          1) This is necessary,  The return value of generator will be used in NestedExecutor
          2) Please note the executed results are not merged.
  
      Yields
      -------
      object
          trade decision
      """
  
      if self.track_data:
          yield trade_decision
  
      atomic = not issubclass(
          self.__class__, NestedExecutor
      )  # issubclass(A, A) is True
  
      if (
          atomic
          and trade_decision.get_range_limit(default_value=None)
          is not None
      ):
          raise ValueError(
              "atomic executor doesn't support specify `range_limit`"
          )
  
      if self._settle_type != BasePosition.ST_NO:
          self.trade_account.current_position.settle_start(
              self._settle_type
          )
  
      obj = self._collect_data(
          trade_decision=trade_decision, level=level
      )
  
      if isinstance(obj, GeneratorType):
          yield_res = yield from obj
          assert isinstance(yield_res, tuple) and len(yield_res) == 2
          res, kwargs = yield_res
      else:
          # Some concrete executor don't have inner decisions
          res, kwargs = obj
  
      (
          trade_start_time,
          trade_end_time,
      ) = self.trade_calendar.get_step_time()
      # Account will not be changed in this function
      self.trade_account.update_bar_end(
          trade_start_time,
          trade_end_time,
          self.trade_exchange,
          atomic=atomic,
          outer_trade_decision=trade_decision,
          indicator_config=self.indicator_config,
          **kwargs,
      )
  
      self.trade_calendar.step()
  
      if self._settle_type != BasePosition.ST_NO:
          self.trade_account.current_position.settle_commit()
  
      if return_value is not None:
          return_value.update({"execute_result": res})
  
      return res
  
imports: from __future__ import annotations
  import copy
  from abc import abstractmethod
  from collections import defaultdict
  from types import GeneratorType
  from typing import Any, Dict, Generator, List, Tuple, Union, cast
  import pandas
  from qlib.backtest.account import Account
  from qlib.backtest.position import BasePosition
  from qlib.log import get_module_logger
  from ..strategy.base import BaseStrategy
  from ..utils import init_instance_by_config
  from .decision import BaseTradeDecision, Order
  from .exchange import Exchange
  from .utils import CommonInfrastructure, LevelInfrastructure, TradeCalendarManager, get_start_end_idx
label_desc: Use image node_id 10 for calling the BaseExecutor obj's underlying member method code with example usage: obj.collect_data(trade_decision, return_value, level) and returns: res