class_docstr: Holds data for an FX vol surface and also interpolates vol surface,
  converts strikes to implied vols etc.
class_docstr_tok: ["Holds","data","for","an","FX","vol","surface","and","also","interpolates","vol","surface",",","converts","strikes","to","implied","vols","etc","."]
docstr: Creates an interpolated implied vol surface which can be plotted 
  (in strike space), and also in delta space for key strikes (ATM, 25d 
  call and put). Also for key strikes converts from delta to strike space.
  
  Parameters
  ----------
  num_strike_intervals : int
      Number of points to interpolate
  
  Returns
  -------
  dict
docstr_tok: ["Creates","an","interpolated","implied","vol","surface","which","can","be","plotted","(","in","strike","space",")",",","and","also","in","delta","space","for","key","strikes","(","ATM",",","25d","call","and","put",")",".","Also","for","key","strikes","converts","from","delta","to","strike","space",".","Parameters","--","--","--","--","--","num_strike_intervals",":","int","Number","of","points","to","interpolate","Returns","--","--","--","-","dict"]
code: def extract_vol_surface(
      self, num_strike_intervals=60, low_K_pc=0.95, high_K_pc=1.05
  ):
      """Creates an interpolated implied vol surface which can be plotted
      (in strike space), and also in delta space for key strikes (ATM, 25d
      call and put). Also for key strikes converts from delta to strike space.
  
      Parameters
      ----------
      num_strike_intervals : int
          Number of points to interpolate
  
      Returns
      -------
      dict
      """
      ## Modified from FinancePy code for plotting vol curves
  
      # columns = tenors
      df_vol_surface_strike_space = pd.DataFrame(
          columns=self._fin_fx_vol_surface._tenors
      )
      df_vol_surface_delta_space = pd.DataFrame(
          columns=self._fin_fx_vol_surface._tenors
      )
  
      # columns = tenors
      df_vol_surface_implied_pdf = pd.DataFrame(
          columns=self._fin_fx_vol_surface._tenors
      )
  
      # Conversion between main deltas and strikes
      df_deltas_vs_strikes = pd.DataFrame(
          columns=self._fin_fx_vol_surface._tenors
      )
  
      # ATM, 10d + 25d market strangle and 25d risk reversals
      df_vol_surface_quoted_points = pd.DataFrame(
          columns=self._fin_fx_vol_surface._tenors
      )
  
      # Note, at present we"re not using 10d strikes
      quoted_strikes_names = [
          "ATM",
          "STR_25D_MS",
          "RR_25D_P",
          "STR_10D_MS",
          "RR_10D_P",
      ]
      key_strikes_names = [
          "K_10D_P",
          "K_10D_P_MS",
          "K_25D_P",
          "K_25D_P_MS",
          "ATM",
          "K_25D_C",
          "K_25D_C_MS",
          "K_10D_C",
          "K_10D_C_MS",
      ]
  
      # Get max/min strikes to interpolate (from the longest dated tenor)
      low_K = self._fin_fx_vol_surface._K_25D_P[-1] * low_K_pc
      high_K = self._fin_fx_vol_surface._K_25D_C[-1] * high_K_pc
  
      if num_strike_intervals is not None:
          # In case using old version of FinancePy
          try:
              implied_pdf_fin_distribution = (
                  self._fin_fx_vol_surface.implied_dbns(
                      low_K, high_K, num_strike_intervals
                  )
              )
          except:
              pass
  
      for tenor_index in range(
          0, self._fin_fx_vol_surface._num_vol_curves
      ):
          # Get the quoted vol points
          tenor_label = self._fin_fx_vol_surface._tenors[tenor_index]
  
          atm_vol = (
              self._fin_fx_vol_surface._atm_vols[tenor_index] * 100
          )
          ms_25d_vol = (
              self._fin_fx_vol_surface._mktStrangle25DeltaVols[
                  tenor_index
              ]
              * 100
          )
          rr_25d_vol = (
              self._fin_fx_vol_surface._riskReversal25DeltaVols[
                  tenor_index
              ]
              * 100
          )
          ms_10d_vol = (
              self._fin_fx_vol_surface._mktStrangle10DeltaVols[
                  tenor_index
              ]
              * 100
          )
          rr_10d_vol = (
              self._fin_fx_vol_surface._riskReversal10DeltaVols[
                  tenor_index
              ]
              * 100
          )
  
          df_vol_surface_quoted_points[tenor_label] = pd.Series(
              index=quoted_strikes_names,
              data=[
                  atm_vol,
                  ms_25d_vol,
                  rr_25d_vol,
                  ms_10d_vol,
                  rr_10d_vol,
              ],
          )
  
          # Do interpolation in strike space for the implied vols (if intervals have been specified)
          strikes = []
          vols = []
  
          if num_strike_intervals is not None:
              K = low_K
              dK = (high_K - low_K) / num_strike_intervals
  
              for i in range(0, num_strike_intervals):
                  sigma = (
                      self.get_vol_from_quoted_tenor(K, tenor_index)
                      * 100.0
                  )
                  strikes.append(K)
                  vols.append(sigma)
                  K = K + dK
  
              df_vol_surface_strike_space[tenor_label] = pd.Series(
                  index=strikes, data=vols
              )
  
          try:
              df_vol_surface_implied_pdf[tenor_label] = pd.Series(
                  index=implied_pdf_fin_distribution[tenor_index]._x,
                  data=implied_pdf_fin_distribution[
                      tenor_index
                  ]._densitydx,
              )
          except:
              pass
  
          # Extract strikes for the quoted points (ie. 10d, 25d and ATM)
          key_strikes = []
          key_strikes.append(
              self._fin_fx_vol_surface._K_10D_P[tenor_index]
          )
          key_strikes.append(
              self._fin_fx_vol_surface._K_10D_P_MS[tenor_index]
          )
          key_strikes.append(
              self._fin_fx_vol_surface._K_25D_P[tenor_index]
          )
          key_strikes.append(
              self._fin_fx_vol_surface._K_25D_P_MS[tenor_index]
          )
          key_strikes.append(
              self._fin_fx_vol_surface._K_ATM[tenor_index]
          )
          key_strikes.append(
              self._fin_fx_vol_surface._K_25D_C[tenor_index]
          )
          key_strikes.append(
              self._fin_fx_vol_surface._K_25D_C_MS[tenor_index]
          )
          key_strikes.append(
              self._fin_fx_vol_surface._K_10D_C[tenor_index]
          )
          key_strikes.append(
              self._fin_fx_vol_surface._K_10D_C_MS[tenor_index]
          )
  
          df_deltas_vs_strikes[tenor_label] = pd.Series(
              index=key_strikes_names, data=key_strikes
          )
  
          # Put a conversion between quoted deltas and strikes (eg. which is ATM in strike space, 25d call/put strikes)
          key_vols = []
  
          for K, name in zip(key_strikes, key_strikes_names):
              sigma = (
                  self.get_vol_from_quoted_tenor(K, tenor_index) * 100.0
              )
              key_vols.append(sigma)
  
          df_vol_surface_delta_space[tenor_label] = pd.Series(
              index=key_strikes_names, data=key_vols
          )
  
      df_vol_dict = {}
      df_vol_dict[
          "vol_surface_implied_pdf"
      ] = df_vol_surface_implied_pdf
      df_vol_dict[
          "vol_surface_strike_space"
      ] = df_vol_surface_strike_space
      df_vol_dict[
          "vol_surface_delta_space"
      ] = df_vol_surface_delta_space
      df_vol_dict[
          "vol_surface_delta_space_exc_ms"
      ] = df_vol_surface_delta_space[
          ~df_vol_surface_delta_space.index.str.contains("_MS")
      ]
      df_vol_dict[
          "vol_surface_quoted_points"
      ] = df_vol_surface_quoted_points
      df_vol_dict["deltas_vs_strikes"] = df_deltas_vs_strikes
  
      self._df_vol_dict = df_vol_dict
  
      return df_vol_dict
  
imports: import pandas
  import numpy
  from financepy.market.curves.discount_curve_flat import DiscountCurveFlat
  from financepy.utils.date import Date
  from financepy.market.volatility.fx_vol_surface_plus import FXVolSurfacePlus
  from financepy.market.volatility.fx_vol_surface_plus import FinFXATMMethod
  from financepy.market.volatility.fx_vol_surface_plus import FinFXDeltaMethod
  from financepy.market.volatility.fx_vol_surface_plus import vol_function
  from financepy.market.volatility.fx_vol_surface_plus import VolFunctionTypes
  from financepy.utils.global_types import FinSolverTypes
  from findatapy.util.dataconstants import DataConstants
  from finmarketpy.curve.volatility.abstractvolsurface import AbstractVolSurface
  from finmarketpy.util.marketconstants import MarketConstants
  from finmarketpy.util.marketutil import MarketUtil
label_desc: Use image node_id 5 for calling the FXVolSurface obj's underlying member method code with example usage: obj.extract_vol_surface(num_strike_intervals, low_K_pc, high_K_pc) and returns: df_vol_dict