class_docstr: TWAP Strategy for trading
  
  NOTE:
      - This TWAP strategy will celling round when trading. This will make the TWAP trading strategy produce the order
        earlier when the total trade unit of amount is less than the trading step
class_docstr_tok: ["TWAP","Strategy","for","trading","NOTE",":","-","This","TWAP","strategy","will","celling","round","when","trading",".","This","will","make","the","TWAP","trading","strategy","produce","the","order","earlier","when","the","total","trade","unit","of","amount","is","less","than","the","trading","step"]
code: def generate_trade_decision(self, execute_result=None):
      # NOTE:  corner cases!!!
      # - If using upperbound round, please don't sell the amount which should in next step
      #   - the coordinate of the amount between steps is hard to be dealt between steps in the same level. It
      #     is easier to be dealt in upper steps
  
      # strategy is not available. Give an empty decision
      if len(self.outer_trade_decision.get_decision()) == 0:
          return TradeDecisionWO(order_list=[], strategy=self)
  
      # get the number of trading step finished, trade_step can be [0, 1, 2, ..., trade_len - 1]
      trade_step = self.trade_calendar.get_trade_step()
      # get the total count of trading step
      start_idx, end_idx = get_start_end_idx(
          self.trade_calendar, self.outer_trade_decision
      )
      trade_len = end_idx - start_idx + 1
  
      if trade_step < start_idx or trade_step > end_idx:
          # It is not time to start trading or trading has ended.
          return TradeDecisionWO(order_list=[], strategy=self)
  
      rel_trade_step = (
          trade_step - start_idx
      )  # trade_step relative to start_idx (number of steps has already passed)
  
      # update the order amount
      if execute_result is not None:
          for order, _, _, _ in execute_result:
              self.trade_amount_remain[
                  order.stock_id
              ] -= order.deal_amount
  
      (
          trade_start_time,
          trade_end_time,
      ) = self.trade_calendar.get_step_time(trade_step)
      order_list = []
      for order in self.outer_trade_decision.get_decision():
          # Don't peek the future information, so we use check_stock_suspended instead of is_stock_tradable
          # necessity of this
          # - if stock is suspended, the quote values of stocks is NaN. The following code will raise error when
          # encountering NaN factor
          if self.trade_exchange.check_stock_suspended(
              stock_id=order.stock_id,
              start_time=trade_start_time,
              end_time=trade_end_time,
          ):
              continue
  
          # the expected trade amount after current step
          amount_expect = (
              order.amount / trade_len * (rel_trade_step + 1)
          )
  
          # remain amount
          amount_remain = self.trade_amount_remain[order.stock_id]
  
          # the amount has already been finished now.
          amount_finished = order.amount - amount_remain
  
          # the expected amount of current step
          amount_delta = amount_expect - amount_finished
  
          _amount_trade_unit = (
              self.trade_exchange.get_amount_of_trade_unit(
                  stock_id=order.stock_id,
                  start_time=order.start_time,
                  end_time=order.end_time,
              )
          )
  
          # round the amount_delta by trade_unit and clip by remain
          # NOTE: this could be more than expected.
          if _amount_trade_unit is None:
              # divide the order into equal parts, and trade one part
              amount_delta_target = amount_delta
          else:
              amount_delta_target = min(
                  np.round(amount_delta / _amount_trade_unit)
                  * _amount_trade_unit,
                  amount_remain,
              )
  
          # handle last step to make sure all positions have gone
          # necessity: the last step can't be rounded to the a unit (e.g. reminder < 0.5 unit)
          if rel_trade_step == trade_len - 1:
              amount_delta_target = amount_remain
  
          if amount_delta_target > 1e-5:
              _order = Order(
                  stock_id=order.stock_id,
                  amount=amount_delta_target,
                  start_time=trade_start_time,
                  end_time=trade_end_time,
                  direction=order.direction,  # 1 for buy
              )
              order_list.append(_order)
      return TradeDecisionWO(order_list=order_list, strategy=self)
  
imports: from pathlib import Path
  import warnings
  import numpy
  import pandas
  from typing import IO, List, Tuple, Union
  from qlib.data.dataset.utils import convert_index_format
  from qlib.utils import lazy_sort_index
  from ...utils.resam import resam_ts_data, ts_data_last
  from ...data.data import D
  from ...strategy.base import BaseStrategy
  from ...backtest.decision import BaseTradeDecision, Order, TradeDecisionWO, TradeRange
  from ...backtest.exchange import Exchange, OrderHelper
  from ...backtest.utils import CommonInfrastructure, LevelInfrastructure
  from qlib.utils.file import get_io_object
  from qlib.backtest.utils import get_start_end_idx
label_desc: Use image node_id 2 for calling the TWAPStrategy obj's underlying member method code with example usage: obj.generate_trade_decision(execute_result) and returns: TradeDecisionWO, TradeDecisionWO, TradeDecisionWO