text: """Option helper functions"""
  __docformat__ = "numpy"
  
  import numpy as np
  import pandas as pd
  
  
  def get_loss_at_strike(strike: float, chain: pd.DataFrame) -> float:
      """Function to get the loss at the given expiry
  
      Parameters
      ----------
      strike : Union[int,float]
          Value to calculate total loss at
      chain : Dataframe:
          Dataframe containing at least strike and openInterest
  
      Returns
      -------
      loss : Union[float,int]
          Total loss
      """
  
      itm_calls = chain[chain.index < strike][["OI_call"]]
      itm_calls["loss"] = (strike - itm_calls.index) * itm_calls["OI_call"]
      call_loss = itm_calls["loss"].sum()
  
      itm_puts = chain[chain.index > strike][["OI_put"]]
      itm_puts["loss"] = (itm_puts.index - strike) * itm_puts["OI_put"]
      put_loss = itm_puts.loss.sum()
      loss = call_loss + put_loss
  
      return loss
  
  
  def calculate_max_pain(chain: pd.DataFrame) -> int:
      """Returns the max pain for a given call/put dataframe
  
      Parameters
      ----------
      chain : DataFrame
          Dataframe to calculate value from
  
      Returns
      -------
      max_pain : int
          Max pain value
      """
  
      strikes = np.array(chain.index)
      if ("OI_call" not in chain.columns) or ("OI_put" not in chain.columns):
          print("Incorrect columns.  Unable to parse max pain")
          return np.nan
  
      loss = []
      for price_at_exp in strikes:
          loss.append(get_loss_at_strike(price_at_exp, chain))
  
      chain["loss"] = loss
      max_pain = chain["loss"].idxmin()
  
      return max_pain
  
  
  def convert(orig: str, to: str) -> float:
      """Convert a string to a specific type of number
      Parameters
      ----------
      orig : str
          String to convert
      Returns
      -------
      number : float
          Decimal value of string
      """
      if to == "%":
          clean = orig.replace("%", "").replace("+", "")
          return float(clean) / 100
      if to == ",":
          clean = orig.replace(",", "")
          return float(clean)
      raise ValueError("Invalid to format, please use '%' or ','.")
  
  
  def rn_payoff(x: str, df: pd.DataFrame, put: bool, delta: int, rf: float) -> float:
      """The risk neutral payoff for a stock
      Parameters
      ----------
      x : str
          Strike price
      df : pd.DataFrame
          Dataframe of stocks prices and probabilities
      put : bool
          Whether the asset is a put or a call
      delta : int
          Difference between today's date and expirations date in days
      rf : float
          The current risk-free rate
  
      Returns
      -------
      number : float
          Risk neutral value of option
      """
      if put:
          df["Gain"] = np.where(x > df["Price"], x - df["Price"], 0)
      else:
          df["Gain"] = np.where(x < df["Price"], df["Price"] - x, 0)
      df["Vals"] = df["Chance"] * df["Gain"]
      risk_free = (1 + rf) ** (delta / 365)
      return sum(df["Vals"]) / risk_free
  
  
  opt_chain_cols = {
      "lastTradeDate": {"format": "date", "label": "Last Trade Date"},
      "strike": {"format": "${x:.2f}", "label": "Strike"},
      "lastPrice": {"format": "${x:.2f}", "label": "Last Price"},
      "bid": {"format": "${x:.2f}", "label": "Bid"},
      "ask": {"format": "${x:.2f}", "label": "Ask"},
      "change": {"format": "${x:.2f}", "label": "Change"},
      "percentChange": {"format": "{x:.2f}%", "label": "Percent Change"},
      "volume": {"format": "{x:.2f}", "label": "Volume"},
      "openInterest": {"format": "", "label": "Open Interest"},
      "impliedVolatility": {"format": "{x:.2f}", "label": "Implied Volatility"},
  }
  