code: def balance(p, tdate, cashlevel):
      r"""Balance the portfolio using a weighting variable.
  
      Rebalancing is the process of equalizing a portfolio's positions
      using some criterion. For example, if a portfolio is *dollar-weighted*,
      then one position can increase in proportion to the rest of the
      portfolio, i.e., its fraction of the overall portfolio is greater
      than the other positions. To make the portfolio "equal dollar",
      then some positions have to be decreased and others decreased.
  
      The rebalancing process is periodic (e.g., once per month) and
      generates a series of trades to balance the positions. Other
      portfolios are *volatility-weighted* because a more volatile
      stock has a greater effect on the beta, i.e., the more volatile
      the instrument, the smaller the position size.
  
      Technically, any type of weight can be used for rebalancing, so
      AlphaPy gives the user the ability to specify a ``weightby``
      column name.
  
      Parameters
      ----------
      p : alphapy.Portfolio
          Portfolio to rebalance.
      tdate : datetime
          The rebalancing date.
      cashlevel : float
          The cash level to maintain during rebalancing.
  
      Returns
      -------
      p : alphapy.Portfolio
          The rebalanced portfolio.
  
      Notes
      -----
  
      .. warning:: The portfolio management functions ``balance``,
         ``kick_out``, and ``stop_loss`` are not part of the
         main **StockStream** pipeline, and thus have not been
         thoroughly tested. Feel free to exercise the code and
         report any issues.
  
      """
      currentcash = p.cash
      mincash = p.mincash
      weightby = p.weightby
      if not weightby:
          weightby = "close"
      p = valuate_portfolio(p, tdate)
      pvalue = p.value - cashlevel * p.value
      positions = p.positions
      bdata = np.ones(len(positions))
      # get weighting variable values
      if weightby[0] == "-":
          invert = True
          weightby = weightby[1:]
      else:
          invert = False
      attrs = [
          aname
          for aname in dir(positions[0])
          if not aname.startswith("_")
      ]
      for i, pos in enumerate(positions):
          if weightby in attrs:
              estr = ".".join("pos", weightby)
              bdata[i] = eval(estr)
          else:
              bdata[i] = pos.pdata.loc[tdate][weightby]
      if invert:
          bweights = (2 * bdata.mean() - bdata) / sum(bdata)
      else:
          bweights = bdata / sum(bdata)
      # rebalance
      for i, pos in enumerate(positions):
          multiplier = pos.multiplier
          bdelta = bweights[i] * pvalue - pos.value
          cp = pos.pdata.loc[tdate]["close"]
          tradesize = math.trunc(bdelta / cp)
          ntv = abs(tradesize) * cp * multiplier
          if tradesize > 0:
              order = Orders.le
          if tradesize < 0:
              order = Orders.se
          exec_trade(p, pos.name, order, tradesize, cp, tdate)
          p.cash = currentcash + bdelta - ntv
      return p
  
imports: from alphapy.frame import Frame
  from alphapy.frame import frame_name
  from alphapy.frame import read_frame
  from alphapy.frame import write_frame
  from alphapy.globals import MULTIPLIERS, SSEP
  from alphapy.globals import Orders
  from alphapy.space import Space
  import logging
  import math
  import numpy
  from pandas import DataFrame
  from pandas import date_range
  from pandas import Series
label_desc: Use image node_id 11 for calling a global function with example usage: balance(p, tdate, cashlevel) and returns: p