class_docstr: A stock trading environment for OpenAI gym
  This environment penalizes the model for not maintaining a reserve of cash.
  This enables the model to manage cash reserves in addition to performing trading procedures.
  Reward at any step is given as follows
      r_i = (sum(cash, asset_value) - initial_cash - max(0, sum(cash, asset_value)*cash_penalty_proportion-cash))/(days_elapsed)
      This reward function takes into account a liquidity requirement, as well as long-term accrued rewards.
  Parameters:
      df (pandas.DataFrame): Dataframe containing data
      buy_cost_pct (float): cost for buying shares
      sell_cost_pct (float): cost for selling shares
      hmax (int, array): maximum cash to be traded in each trade per asset. If an array is provided, then each index correspond to each asset
      discrete_actions (bool): option to choose whether perform dicretization on actions space or not
      shares_increment (int): multiples number of shares can be bought in each trade. Only applicable if discrete_actions=True
      turbulence_threshold (float): Maximum turbulence allowed in market for purchases to occur. If exceeded, positions are liquidated
      print_verbosity(int): When iterating (step), how often to print stats about state of env
      initial_amount: (int, float): Amount of cash initially available
      daily_information_columns (list(str)): Columns to use when building state space from the dataframe. It could be OHLC columns or any other variables such as technical indicators and turbulence index
      cash_penalty_proportion (int, float): Penalty to apply if the algorithm runs out of cash
      patient (bool): option to choose whether end the cycle when we're running out of cash or just don't buy anything until we got additional cash
  
  RL Inputs and Outputs
      action space: [<n_assets>,] in range {-1, 1}
      state space: {start_cash, [shares_i for in in assets], [[indicator_j for j in indicators] for i in assets]]}
  TODO:
      Organize functions
      Write README
      Document tests
docstr: This function takes in a raw 'action' from the model and makes it into realistic transactions
  This function includes logic for discretizing
  It also includes turbulence logic.
docstr_tok: ["This","function","takes","in","a","raw","'action","'","from","the","model","and","makes","it","into","realistic","transactions","This","function","includes","logic","for","discretizing","It","also","includes","turbulence","logic","."]
code: def get_transactions(self, actions):
      """
      This function takes in a raw 'action' from the model and makes it into realistic transactions
      This function includes logic for discretizing
      It also includes turbulence logic.
      """
      # record actions of the model
      self.actions_memory.append(actions)
  
      # multiply actions by the hmax value
      actions = actions * self.hmax
  
      # Do nothing for shares with zero value
      actions = np.where(self.closings > 0, actions, 0)
  
      # discretize optionally
      if self.discrete_actions:
          # convert into integer because we can't buy fraction of shares
          actions = actions // self.closings
          actions = actions.astype(int)
          # round down actions to the nearest multiplies of shares_increment
          actions = np.where(
              actions >= 0,
              (actions // self.shares_increment)
              * self.shares_increment,
              (
                  (actions + self.shares_increment)
                  // self.shares_increment
              )
              * self.shares_increment,
          )
      else:
          actions = actions / self.closings
  
      # can't sell more than we have
      actions = np.maximum(actions, -np.array(self.holdings))
  
      # deal with turbulence
      if self.turbulence_threshold is not None:
          # if turbulence goes over threshold, just clear out all positions
          if self.turbulence >= self.turbulence_threshold:
              actions = -(np.array(self.holdings))
              self.log_step(reason="TURBULENCE")
  
      return actions
  
imports: from __future__ import annotations
  import random
  import time
  from copy import deepcopy
  import gym
  import matplotlib
  import numpy
  import pandas
  from gym import spaces
  from stable_baselines3.common import logger
  from stable_baselines3.common.vec_env import DummyVecEnv
  from stable_baselines3.common.vec_env import SubprocVecEnv
label_desc: Use image node_id 13 for calling the StockTradingEnvCashpenalty obj's underlying member method code with example usage: obj.get_transactions(actions) and returns: actions