class_docstr: Single-asset order execution (SAOE) simulator.
  
  As there's no "calendar" in the simple simulator, ticks are used to trade.
  A tick is a record (a line) in the pickle-styled data file.
  Each tick is considered as a individual trading opportunity.
  If such fine granularity is not needed, use ``ticks_per_step`` to
  lengthen the ticks for each step.
  
  In each step, the traded amount are "equally" separated to each tick,
  then bounded by volume maximum execution volume (i.e., ``vol_threshold``),
  and if it's the last step, try to ensure all the amount to be executed.
  
  Parameters
  ----------
  order
      The seed to start an SAOE simulator is an order.
  data_dir
      Path to load backtest data.
  feature_columns_today
      Columns of today's feature.
  feature_columns_yesterday
      Columns of yesterday's feature.
  data_granularity
      Number of ticks between consecutive data entries.
  ticks_per_step
      How many ticks per step.
  vol_threshold
      Maximum execution volume (divided by market execution volume).
class_docstr_tok: ["Single-asset","order","execution","(","SAOE",")","simulator",".","As","there","'s","no","``","calendar","''","in","the","simple","simulator",",","ticks","are","used","to","trade",".","A","tick","is","a","record","(","a","line",")","in","the","pickle-styled","data","file",".","Each","tick","is","considered","as","a","individual","trading","opportunity",".","If","such","fine","granularity","is","not","needed",",","use","``","ticks_per_step","``","to","lengthen","the","ticks","for","each","step",".","In","each","step",",","the","traded","amount","are","``","equally","''","separated","to","each","tick",",","then","bounded","by","volume","maximum","execution","volume","(","i.e.",",","``","vol_threshold","``",")",",","and","if","it","'s","the","last","step",",","try","to","ensure","all","the","amount","to","be","executed",".","Parameters","--","--","--","--","--","order","The","seed","to","start","an","SAOE","simulator","is","an","order",".","data_dir","Path","to","load","backtest","data",".","feature_columns_today","Columns","of","today","'s","feature",".","feature_columns_yesterday","Columns","of","yesterday","'s","feature",".","data_granularity","Number","of","ticks","between","consecutive","data","entries",".","ticks_per_step","How","many","ticks","per","step",".","vol_threshold","Maximum","execution","volume","(","divided","by","market","execution","volume",")","."]
code: def __init__(
      self,
      order: Order,
      data_dir: Path,
      feature_columns_today: List[str] = [],
      feature_columns_yesterday: List[str] = [],
      data_granularity: int = 1,
      ticks_per_step: int = 30,
      vol_threshold: Optional[float] = None,
  ) -> None:
      super().__init__(initial=order)
  
      assert ticks_per_step % data_granularity == 0
  
      self.order = order
      self.data_dir = data_dir
      self.feature_columns_today = feature_columns_today
      self.feature_columns_yesterday = feature_columns_yesterday
      self.ticks_per_step: int = ticks_per_step // data_granularity
      self.vol_threshold = vol_threshold
  
      self.backtest_data = self.get_backtest_data()
      self.ticks_index = self.backtest_data.get_time_index()
  
      # Get time index available for trading
      self.ticks_for_order = self._get_ticks_slice(
          self.order.start_time, self.order.end_time
      )
  
      self.cur_time = self.ticks_for_order[0]
      self.cur_step = 0
      # NOTE: astype(float) is necessary in some systems.
      # this will align the precision with `.to_numpy()` in `_split_exec_vol`
      self.twap_price = float(
          self.backtest_data.get_deal_price()
          .loc[self.ticks_for_order]
          .astype(float)
          .mean()
      )
  
      self.position = order.amount
  
      metric_keys = list(
          SAOEMetrics.__annotations__.keys()
      )  # pylint: disable=no-member
      # NOTE: can empty dataframe contain index?
      self.history_exec = pd.DataFrame(columns=metric_keys).set_index(
          "datetime"
      )
      self.history_steps = pd.DataFrame(columns=metric_keys).set_index(
          "datetime"
      )
      self.metrics = None
  
      self.market_price: Optional[np.ndarray] = None
      self.market_vol: Optional[np.ndarray] = None
      self.market_vol_limit: Optional[np.ndarray] = None
  
imports: from __future__ import annotations
  from typing import Any, cast, List, Optional
  import numpy
  import pandas
  from pathlib import Path
  from qlib.backtest.decision import Order, OrderDir
  from qlib.constant import EPS, EPS_T, float_or_ndarray
  from qlib.rl.data.base import BaseIntradayBacktestData
  from qlib.rl.data.native import DataframeIntradayBacktestData, load_handler_intraday_processed_data
  from qlib.rl.data.pickle_styled import load_simple_intraday_backtest_data
  from qlib.rl.simulator import Simulator
  from qlib.rl.utils import LogLevel
  from .state import SAOEMetrics, SAOEState
label_desc: Use image node_id 1 to create a new SingleAssetOrderExecutionSimple object from inherited base classes: Simulator with example: obj = SingleAssetOrderExecutionSimple(order, data_dir, feature_columns_today, feature_columns_yesterday, data_granularity, ticks_per_step, vol_threshold)