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 _metrics_collect(
      self,
      datetime: pd.Timestamp,
      market_vol: np.ndarray,
      market_price: np.ndarray,
      amount: float,  # intended to trade such amount
      exec_vol: np.ndarray,
  ) -> SAOEMetrics:
      assert len(market_vol) == len(market_price) == len(exec_vol)
  
      if np.abs(np.sum(exec_vol)) < EPS:
          exec_avg_price = 0.0
      else:
          exec_avg_price = cast(
              float, np.average(market_price, weights=exec_vol)
          )  # could be nan
          if hasattr(exec_avg_price, "item"):  # could be numpy scalar
              exec_avg_price = exec_avg_price.item()  # type: ignore
  
      return SAOEMetrics(
          stock_id=self.order.stock_id,
          datetime=datetime,
          direction=self.order.direction,
          market_volume=market_vol.sum(),
          market_price=market_price.mean(),
          amount=amount,
          inner_amount=exec_vol.sum(),
          deal_amount=exec_vol.sum(),  # in this simulator, there's no other restrictions
          trade_price=exec_avg_price,
          trade_value=float(np.sum(market_price * exec_vol)),
          position=self.position,
          ffr=float(exec_vol.sum() / self.order.amount),
          pa=price_advantage(
              exec_avg_price, self.twap_price, self.order.direction
          ),
      )
  
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 9 for calling the SingleAssetOrderExecutionSimple obj's underlying member method code with example usage: obj._metrics_collect(datetime, market_vol, market_price, amount, exec_vol) and returns: SAOEMetrics