text: import numpy as np
  from typing import Optional
  from fypy.volatility.implied.ImpliedVolCalculator import ImpliedVolCalculator
  
  
  class MarketSlice(object):
      def __init__(self,
                   T: float,
                   F: float,
                   disc: float,
                   strikes: np.ndarray,
                   is_calls: np.ndarray,
                   bid_prices: Optional[np.ndarray] = None,
                   mid_prices: Optional[np.ndarray] = None,
                   ask_prices: Optional[np.ndarray] = None):
          """
          Container holding market option prices for a single slice (tenor) in a price surface. You must either supply
          mid prices, or bid and ask prices
          :param T: float, time to maturity for this slice
          :param F: float, the foward price, F(T)
          :param disc: float, the discount, D(T)
          :param strikes: np.ndarray, the strikes in increasing order along the slice- no sorting is done, this is assumed
          :param is_calls: np.ndarray, true/false indicator per strike, true if its a call option
          :param bid_prices: np.ndarray, optional, bid prices per strike
          :param mid_prices: np.ndarray, optional, mid prices per strike (if not supplied, supply both bid and ask)
          :param ask_prices: np.ndarray, optional, ask prices per strike
          """
          self.T = T
          self.F = F  # forward price  (used to determine main quotes)
          self.disc = disc
          self.strikes = strikes
          self.is_calls = is_calls
  
          self.bid_prices = bid_prices
          self.mid_prices = mid_prices
          self.ask_prices = ask_prices
          self._set_prices()
  
          # Implied Volatilies (these can be set/filled after initialization)
          self.bid_vols: Optional[np.ndarray] = None
          self.mid_vols: Optional[np.ndarray] = None
          self.ask_vols: Optional[np.ndarray] = None
  
      def set_vols(self,
                   bid_vols: Optional[np.ndarray] = None,
                   mid_vols: Optional[np.ndarray] = None,
                   ask_vols: Optional[np.ndarray] = None):
          """
          Set the implied volatilities from their value. Alternatively, you can fill them by supplying an
          ImpliedVolCalculator
          :param bid_vols: np.ndarray, bid implied vols (optional)
          :param mid_vols: np.ndarray, mid implied vols (optional)
          :param ask_vols: np.ndarray, ask implied vols (optional)
          :return: None
          """
          self.bid_vols = bid_vols
          self.ask_vols = ask_vols
          self.mid_vols = mid_vols
  
      def fill_implied_vols(self, calculator: ImpliedVolCalculator):
          """
          Fill the implied vols given a calculator. Fills in for each of bid,mid,ask, but only those that have
          corresponding prices
          :param calculator: ImpliedVolCalculator, a calculator used to fill in the vols from prices
          :return: None
          """
          for prices, which in zip((self.bid_prices, self.mid_prices, self.ask_prices),
                                   ('bid', 'mid', 'ask')):
              if prices is not None:
                  vols = calculator.imply_vols(strikes=self.strikes, prices=prices, is_calls=self.is_calls, ttm=self.T)
                  if which == 'bid':
                      self.bid_vols = vols
                  elif which == 'mid':
                      self.mid_vols = vols
                  else:
                      self.ask_vols = vols
  
      def _set_prices(self):
          if self.mid_prices is None:
              if self.bid_prices is None or self.ask_prices is None:
                  raise ValueError("If you dont supply mid prices, must supply bid and ask prices")
              self.mid_prices = (self.bid_prices + self.ask_prices) / 2
  
  
  if __name__ == '__main__':
      # Example usage
      from fypy.pricing.analytical.black_scholes import black76_price_strikes
      from fypy.termstructures.EquityForward import EquityForward, DiscountCurve_ConstRate
      from fypy.volatility.implied.ImpliedVolCalculator import ImpliedVolCalculator_Black76
  
      strikes_ = np.arange(50, 150, 1)
      is_calls_ = np.ones(len(strikes_), dtype=bool)
      T = 1.
  
      disc_curve = DiscountCurve_ConstRate(rate=0.02)
      fwd = EquityForward(S0=100, discount=disc_curve)
  
      prices_ = black76_price_strikes(F=fwd(T), K=strikes_, is_calls=is_calls_, vol=0.2, disc=disc_curve(T), T=T)
  
      mkt_slice = MarketSlice(T=T, F=fwd(T), disc=disc_curve(T), strikes=strikes_, is_calls=is_calls_,
                              mid_prices=prices_)
  
      ivc = ImpliedVolCalculator_Black76(fwd_curve=fwd, disc_curve=disc_curve)
      mkt_slice.fill_implied_vols(calculator=ivc)
      vols = mkt_slice.mid_vols
  