class_docstr: Qlib-based RL environment, subclassing ``gym.Env``.
  A wrapper of components, including simulator, state-interpreter, action-interpreter, reward.
  
  This is what the framework of simulator - interpreter - policy looks like in RL training.
  All the components other than policy needs to be assembled into a single object called "environment".
  The "environment" are replicated into multiple workers, and (at least in tianshou's implementation),
  one single policy (agent) plays against a batch of environments.
  
  Parameters
  ----------
  simulator_fn
      A callable that is the simulator factory.
      When ``seed_iterator`` is present, the factory should take one argument,
      that is the seed (aka initial state).
      Otherwise, it should take zero argument.
  state_interpreter
      State-observation converter.
  action_interpreter
      Policy-simulator action converter.
  seed_iterator
      An iterable of seed. With the help of :class:`qlib.rl.utils.DataQueue`,
      environment workers in different processes can share one ``seed_iterator``.
  reward_fn
      A callable that accepts the StateType and returns a float (at least in single-agent case).
  aux_info_collector
      Collect auxiliary information. Could be useful in MARL.
  logger
      Log collector that collects the logs. The collected logs are sent back to main process,
      via the return value of ``env.step()``.
  
  Attributes
  ----------
  status : EnvWrapperStatus
      Status indicator. All terms are in *RL language*.
      It can be used if users care about data on the RL side.
      Can be none when no trajectory is available.
docstr: Environment step.
  
  See the code along with comments to get a sequence of things happening here.
docstr_tok: ["Environment","step",".","See","the","code","along","with","comments","to","get","a","sequence","of","things","happening","here","."]
code: def step(
      self, policy_action: PolicyActType, **kwargs: Any
  ) -> Tuple[ObsType, float, bool, InfoDict]:
      """Environment step.
  
      See the code along with comments to get a sequence of things happening here.
      """
  
      if self.seed_iterator is None:
          raise RuntimeError(
              "State queue is already exhausted, but the environment is still receiving action."
          )
  
      # Clear the logged information from last step
      self.logger.reset()
  
      # Action is what we have got from policy
      self.status["action_history"].append(policy_action)
      action = self.action_interpreter(
          self.simulator.get_state(), policy_action
      )
  
      # This update must be after action interpreter and before simulator.
      self.status["cur_step"] += 1
  
      # Use the converted action of update the simulator
      self.simulator.step(action)
  
      # Update "done" first, as this status might be used by reward_fn later
      done = self.simulator.done()
      self.status["done"] = done
  
      # Get state and calculate observation
      sim_state = self.simulator.get_state()
      obs = self.state_interpreter(sim_state)
      self.status["obs_history"].append(obs)
  
      # Reward and extra info
      if self.reward_fn is not None:
          rew = self.reward_fn(sim_state)
      else:
          # No reward. Treated as 0.
          rew = 0.0
      self.status["reward_history"].append(rew)
  
      if self.aux_info_collector is not None:
          aux_info = self.aux_info_collector(sim_state)
      else:
          aux_info = {}
  
      # Final logging stuff: RL-specific logs
      if done:
          self.logger.add_scalar(
              "steps_per_episode", self.status["cur_step"]
          )
      self.logger.add_scalar("reward", rew)
      self.logger.add_any("obs", obs, loglevel=LogLevel.DEBUG)
      self.logger.add_any(
          "policy_act", policy_action, loglevel=LogLevel.DEBUG
      )
  
      info_dict = InfoDict(log=self.logger.logs(), aux_info=aux_info)
      return obs, rew, done, info_dict
  
imports: from __future__ import annotations
  import weakref
  from typing import Any, Callable, cast, Dict, Generic, Iterable, Iterator, Optional, Tuple
  import gym
  from gym import Space
  from qlib.rl.aux_info import AuxiliaryInfoCollector
  from qlib.rl.interpreter import ActionInterpreter, ObsType, PolicyActType, StateInterpreter
  from qlib.rl.reward import Reward
  from qlib.rl.simulator import ActType, InitialStateType, Simulator, StateType
  from qlib.typehint import TypedDict
  from .finite_env import generate_nan_observation
  from .log import LogCollector, LogLevel
label_desc: Use image node_id 5 for calling the EnvWrapper obj's underlying member method code with example usage: obj.step(policy_action) and returns: obs,  rew,  done,  info_dict