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.
code: def __init__(
      self,
      simulator_fn: Callable[
          ..., Simulator[InitialStateType, StateType, ActType]
      ],
      state_interpreter: StateInterpreter[StateType, ObsType],
      action_interpreter: ActionInterpreter[
          StateType, PolicyActType, ActType
      ],
      seed_iterator: Optional[Iterable[InitialStateType]],
      reward_fn: Reward | None = None,
      aux_info_collector: AuxiliaryInfoCollector[StateType, Any]
      | None = None,
      logger: LogCollector | None = None,
  ) -> None:
      # Assign weak reference to wrapper.
      #
      # Use weak reference here, because:
      # 1. Logically, the other components should be able to live without an env_wrapper.
      #    For example, they might live in a strategy_wrapper in future.
      #    Therefore injecting a "hard" attribute called "env" is not appropripate.
      # 2. When the environment gets destroyed, it gets destoryed.
      #    We don't want it to silently live inside some interpreters.
      # 3. Avoid circular reference.
      # 4. When the components get serialized, we can throw away the env without any burden.
      #    (though this part is not implemented yet)
      for obj in [
          state_interpreter,
          action_interpreter,
          reward_fn,
          aux_info_collector,
      ]:
          if obj is not None:
              obj.env = weakref.proxy(self)  # type: ignore
  
      self.simulator_fn = simulator_fn
      self.state_interpreter = state_interpreter
      self.action_interpreter = action_interpreter
  
      if seed_iterator is None:
          # In this case, there won't be any seed for simulator
          # We can't set it to None because None actually means something else.
          # If `seed_iterator` is None, it means that it's exhausted.
          self.seed_iterator = SEED_INTERATOR_MISSING
      else:
          self.seed_iterator = iter(seed_iterator)
      self.reward_fn = reward_fn
  
      self.aux_info_collector = aux_info_collector
      self.logger: LogCollector = logger or LogCollector()
      self.status: EnvWrapperStatus = cast(EnvWrapperStatus, None)
  
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 1 to create a new EnvWrapper object from inherited base classes: gym.Env, Generic with example: obj = EnvWrapper(simulator_fn, state_interpreter, action_interpreter, seed_iterator, reward_fn, aux_info_collector, logger)