class_docstr: Implements the SABR model defined by the following equations.
  
  ```
    dF_t = v_t * F_t ^ beta * dW_{F,t}
    dv_t = volvol * v_t * dW_{v,t}
    dW_{F,t} * dW_{v,t} = rho * dt
  ```
  
  `F_t` is the forward. `v_t` is volatility. `beta` is the CEV parameter.
  `volvol` is volatility of volatility. `W_{F,t}` and `W_{v,t}` are two
  correlated Wiener processes with instantaneous correlation `rho`.
  
  This model supports time dependent parameters. In other words, `beta`,
  `volvol`, and `rho` can be functions of time. When all of these parameters are
  constants, `beta` != 1, and `enable_unbiased_sampling` is True, the almost
  exact sampling procedure described in Ref [1] will be used. Otherwise it will
  default to Euler sampling.
  
  ### Example. Simple example with time independent params.
  
  ```none
    process = sabr.SabrModel(beta=0.5, volvol=1, rho=0.5, dtype=tf.float32)
    paths = process.sample_paths(
        initial_forward=100,
        initial_volatility=0.05,
        times=[1,2,5],
        time_step=0.01,
        num_samples=10000)
  ```
  
  ### Example 2. Callable volvol and correlation coefficient.
  
  ```none
    volvol_fn = lambda t: tf.where(t < 2, 0.5, 1.0)
    rho_fn = lambda t: tf.where(t < 1, 0., 0.5)
  
    process = sabr.SabrModel(
        beta=0.5, volvol=volvol_fn, rho=rho_fn, dtype=tf.float32)
  
    # Any time where parameters vary drastically (e.g. t=2 above) should be
    # added to `times` to reduce numerical error.
    paths = process.sample_paths(
        initial_forward=100,
        initial_volatility=0.05,
        times=[1,2,5],
        time_step=0.01,
        num_samples=10000)
  ```
  
  ### References:
  [1]: Chen B, Oosterlee CW, Van Der Weide H. Efficient unbiased simulation
  scheme for the SABR stochastic volatility model. 2011
  Link: http://ta.twi.tudelft.nl/mf/users/oosterle/oosterlee/SABRMC.pdf
  [2]: Andersen, Leif B.G., Efficient Simulation of the Heston Stochastic
  Volatility Model (January 23, 2007). Available at SSRN:
  https://ssrn.com/abstract=946405 or http://dx.doi.org/10.2139/ssrn.946405
class_docstr_tok: ["Implements","the","SABR","model","defined","by","the","following","equations",".","``","`","dF_t","=","v_t","*","F_t","^","beta","*","dW_","{","F",",","t","}","dv_t","=","volvol","*","v_t","*","dW_","{","v",",","t","}","dW_","{","F",",","t","}","*","dW_","{","v",",","t","}","=","rho","*","dt","``","`","`","F_t","`","is","the","forward",".","`","v_t","`","is","volatility",".","`","beta","`","is","the","CEV","parameter",".","`","volvol","`","is","volatility","of","volatility",".","`","W_","{","F",",","t","}","`","and","`","W_","{","v",",","t","}","`","are","two","correlated","Wiener","processes","with","instantaneous","correlation","`","rho","`",".","This","model","supports","time","dependent","parameters",".","In","other","words",",","`","beta","`",",","`","volvol","`",",","and","`","rho","`","can","be","functions","of","time",".","When","all","of","these","parameters","are","constants",",","`","beta","`","!","=","1",",","and","`","enable_unbiased_sampling","`","is","True",",","the","almost","exact","sampling","procedure","described","in","Ref","[","1","]","will","be","used",".","Otherwise","it","will","default","to","Euler","sampling",".","#","#","#","Example",".","Simple","example","with","time","independent","params",".","``","`","none","process","=","sabr.SabrModel","(","beta=0.5",",","volvol=1",",","rho=0.5",",","dtype=tf.float32",")","paths","=","process.sample_paths","(","initial_forward=100",",","initial_volatility=0.05",",","times=","[","1,2,5","]",",","time_step=0.01",",","num_samples=10000",")","``","`","#","#","#","Example","2",".","Callable","volvol","and","correlation","coefficient",".","``","`","none","volvol_fn","=","lambda","t",":","tf.where","(","t","<","2",",","0.5",",","1.0",")","rho_fn","=","lambda","t",":","tf.where","(","t","<","1",",","0.",",","0.5",")","process","=","sabr.SabrModel","(","beta=0.5",",","volvol=volvol_fn",",","rho=rho_fn",",","dtype=tf.float32",")","#","Any","time","where","parameters","vary","drastically","(","e.g",".","t=2","above",")","should","be","#","added","to","`","times","`","to","reduce","numerical","error",".","paths","=","process.sample_paths","(","initial_forward=100",",","initial_volatility=0.05",",","times=","[","1,2,5","]",",","time_step=0.01",",","num_samples=10000",")","``","`","#","#","#","References",":","[","1","]",":","Chen","B",",","Oosterlee","CW",",","Van","Der","Weide","H.","Efficient","unbiased","simulation","scheme","for","the","SABR","stochastic","volatility","model",".","2011","Link",":","http",":","\/\/ta.twi.tudelft.nl\/mf\/users\/oosterle\/oosterlee\/SABRMC.pdf","[","2","]",":","Andersen",",","Leif","B.G.",",","Efficient","Simulation","of","the","Heston","Stochastic","Volatility","Model","(","January","23",",","2007",")",".","Available","at","SSRN",":","https",":","\/\/ssrn.com\/abstract=946405","or","http",":","\/\/dx.doi.org\/10.2139\/ssrn.946405"]
docstr: Initializes the SABR Model.
  
  Args:
    beta: CEV parameter of SABR model. The type and the shape must be
      one of the following: (a) A scalar real tensor in [0, 1]. When beta = 1,
        the algorithm falls back to the Euler sampling scheme. (b) A python
        callable accepting one real `Tensor` argument time t. It should return
        a scalar real value or `Tensor`.
    volvol: Volatility of volatility. Either a scalar non-negative real
      tensor, or a python callable accepting same parameters as beta callable.
    rho: The correlation coefficient between the two correlated Wiener
      processes for the forward and the volatility. Either a scalar real
      tensor in (-1, 1), or a python callable accepting same parameters as
      beta callable. Default value: 0.
    shift: Tensor holding a non-negative scalar, specifying the shift
      parameter. In the shifted model, the process modeling the forward is
      modified as: dF = sigma * (F + shift) ^ beta * dW.  With this
        modification, negative forward rates are valid as long as F > -shift.
    enable_unbiased_sampling: bool. If True, use the sampling procedure
      described in ref [1]. Default value: False
    psi_threshold: The threshold of applicability of Andersen L. (2008)
      Quadratic Exponential (QE) algorithm. See ref [1] page 13 and ref [2]. A
      scalar float value in [1, 2]. Default value: 2.
    ncx2_cdf_truncation: A positive integer. When computing the CDF of a
      noncentral X2 distribution, it needs to calculate the sum of an
      expression from 0 to infinity. In practice, it needs to be truncated to
      compute an approximate value. This argument is the index of the last
      term that will be included in the sum. Default value: 10.
    dtype: The float type to use. Default value: `tf.float32`
    name: str. The name to give to the ops created by this class.
      Default value: None which maps to the default name `sabr_model`.
  ### References:
  [1]: Chen B, Oosterlee CW, Van Der Weide H. Efficient unbiased simulation
    scheme for the SABR stochastic volatility model. 2011
  Link: http://ta.twi.tudelft.nl/mf/users/oosterle/oosterlee/SABRMC.pdf
  [2]: Andersen, Leif B.G., Efficient Simulation of the Heston Stochastic
  Volatility Model (January 23, 2007). Available at SSRN:
  https://ssrn.com/abstract=946405 or http://dx.doi.org/10.2139/ssrn.946405
docstr_tok: ["Initializes","the","SABR","Model",".","Args",":","beta",":","CEV","parameter","of","SABR","model",".","The","type","and","the","shape","must","be","one","of","the","following",":","(","a",")","A","scalar","real","tensor","in","[","0",",","1","]",".","When","beta","=","1",",","the","algorithm","falls","back","to","the","Euler","sampling","scheme",".","(","b",")","A","python","callable","accepting","one","real","`","Tensor","`","argument","time","t.","It","should","return","a","scalar","real","value","or","`","Tensor","`",".","volvol",":","Volatility","of","volatility",".","Either","a","scalar","non-negative","real","tensor",",","or","a","python","callable","accepting","same","parameters","as","beta","callable",".","rho",":","The","correlation","coefficient","between","the","two","correlated","Wiener","processes","for","the","forward","and","the","volatility",".","Either","a","scalar","real","tensor","in","(","-1",",","1",")",",","or","a","python","callable","accepting","same","parameters","as","beta","callable",".","Default","value",":","0.","shift",":","Tensor","holding","a","non-negative","scalar",",","specifying","the","shift","parameter",".","In","the","shifted","model",",","the","process","modeling","the","forward","is","modified","as",":","dF","=","sigma","*","(","F","+","shift",")","^","beta","*","dW",".","With","this","modification",",","negative","forward","rates","are","valid","as","long","as","F",">","-shift",".","enable_unbiased_sampling",":","bool",".","If","True",",","use","the","sampling","procedure","described","in","ref","[","1","]",".","Default","value",":","False","psi_threshold",":","The","threshold","of","applicability","of","Andersen","L.","(","2008",")","Quadratic","Exponential","(","QE",")","algorithm",".","See","ref","[","1","]","page","13","and","ref","[","2","]",".","A","scalar","float","value","in","[","1",",","2","]",".","Default","value",":","2.","ncx2_cdf_truncation",":","A","positive","integer",".","When","computing","the","CDF","of","a","noncentral","X2","distribution",",","it","needs","to","calculate","the","sum","of","an","expression","from","0","to","infinity",".","In","practice",",","it","needs","to","be","truncated","to","compute","an","approximate","value",".","This","argument","is","the","index","of","the","last","term","that","will","be","included","in","the","sum",".","Default","value",":","10.","dtype",":","The","float","type","to","use",".","Default","value",":","`","tf.float32","`","name",":","str",".","The","name","to","give","to","the","ops","created","by","this","class",".","Default","value",":","None","which","maps","to","the","default","name","`","sabr_model","`",".","#","#","#","References",":","[","1","]",":","Chen","B",",","Oosterlee","CW",",","Van","Der","Weide","H.","Efficient","unbiased","simulation","scheme","for","the","SABR","stochastic","volatility","model",".","2011","Link",":","http",":","\/\/ta.twi.tudelft.nl\/mf\/users\/oosterle\/oosterlee\/SABRMC.pdf","[","2","]",":","Andersen",",","Leif","B.G.",",","Efficient","Simulation","of","the","Heston","Stochastic","Volatility","Model","(","January","23",",","2007",")",".","Available","at","SSRN",":","https",":","\/\/ssrn.com\/abstract=946405","or","http",":","\/\/dx.doi.org\/10.2139\/ssrn.946405"]
code: def __init__(
      self,
      beta: types.RealTensor,
      volvol: types.RealTensor,
      rho: types.RealTensor = 0,
      shift: types.RealTensor = 0,
      enable_unbiased_sampling: bool = False,
      psi_threshold: types.RealTensor = 2,
      ncx2_cdf_truncation: int = 10,
      dtype: Optional[tf.DType] = None,
      name: Optional[str] = None,
  ):
      """Initializes the SABR Model.
  
      Args:
        beta: CEV parameter of SABR model. The type and the shape must be
          one of the following: (a) A scalar real tensor in [0, 1]. When beta = 1,
            the algorithm falls back to the Euler sampling scheme. (b) A python
            callable accepting one real `Tensor` argument time t. It should return
            a scalar real value or `Tensor`.
        volvol: Volatility of volatility. Either a scalar non-negative real
          tensor, or a python callable accepting same parameters as beta callable.
        rho: The correlation coefficient between the two correlated Wiener
          processes for the forward and the volatility. Either a scalar real
          tensor in (-1, 1), or a python callable accepting same parameters as
          beta callable. Default value: 0.
        shift: Tensor holding a non-negative scalar, specifying the shift
          parameter. In the shifted model, the process modeling the forward is
          modified as: dF = sigma * (F + shift) ^ beta * dW.  With this
            modification, negative forward rates are valid as long as F > -shift.
        enable_unbiased_sampling: bool. If True, use the sampling procedure
          described in ref [1]. Default value: False
        psi_threshold: The threshold of applicability of Andersen L. (2008)
          Quadratic Exponential (QE) algorithm. See ref [1] page 13 and ref [2]. A
          scalar float value in [1, 2]. Default value: 2.
        ncx2_cdf_truncation: A positive integer. When computing the CDF of a
          noncentral X2 distribution, it needs to calculate the sum of an
          expression from 0 to infinity. In practice, it needs to be truncated to
          compute an approximate value. This argument is the index of the last
          term that will be included in the sum. Default value: 10.
        dtype: The float type to use. Default value: `tf.float32`
        name: str. The name to give to the ops created by this class.
          Default value: None which maps to the default name `sabr_model`.
      ### References:
      [1]: Chen B, Oosterlee CW, Van Der Weide H. Efficient unbiased simulation
        scheme for the SABR stochastic volatility model. 2011
      Link: http://ta.twi.tudelft.nl/mf/users/oosterle/oosterlee/SABRMC.pdf
      [2]: Andersen, Leif B.G., Efficient Simulation of the Heston Stochastic
      Volatility Model (January 23, 2007). Available at SSRN:
      https://ssrn.com/abstract=946405 or http://dx.doi.org/10.2139/ssrn.946405
      """
      self._dtype = dtype or tf.float32
      self._name = name or "sabr_model"
      self._enable_unbiased_sampling = enable_unbiased_sampling
  
      self._beta = (
          beta
          if _is_callable(beta)
          else tf.convert_to_tensor(
              beta, dtype=self._dtype, name="beta"
          )
      )
      self._volvol = (
          volvol
          if _is_callable(volvol)
          else tf.convert_to_tensor(
              volvol, dtype=self._dtype, name="volvol"
          )
      )
      self._rho = (
          rho
          if _is_callable(rho)
          else tf.convert_to_tensor(rho, dtype=self._dtype, name="rho")
      )
      self._psi_threshold = tf.convert_to_tensor(
          psi_threshold, dtype=self._dtype, name="psi_threshold"
      )
      self._ncx2_cdf_truncation = ncx2_cdf_truncation
      self._shift = tf.convert_to_tensor(
          shift, dtype=self._dtype, name="shift"
      )
  
      drift_fn = lambda _, x: tf.zeros_like(x)
  
      def _vol_fn(t, x):
          """The volatility function for SABR model."""
          f = x[..., 0]
          v = x[..., 1]
  
          beta = (
              tf.convert_to_tensor(
                  self._beta(t), dtype=self._dtype, name="beta_fn"
              )
              if _is_callable(self._beta)
              else self._beta
          )
          volvol = (
              tf.convert_to_tensor(
                  self._volvol(t), dtype=self._dtype, name="volvol_fn"
              )
              if _is_callable(self._volvol)
              else self._volvol
          )
          rho = (
              tf.convert_to_tensor(
                  self._rho(t), dtype=self._dtype, name="rho_fn"
              )
              if _is_callable(self._rho)
              else self._rho
          )
  
          fb = f**beta
          m11 = v * fb * tf.math.sqrt(1 - tf.square(rho))
          m12 = v * fb * rho
          m21 = tf.zeros_like(m11)
          m22 = volvol * v
          mc1 = tf.concat(
              [tf.expand_dims(m11, -1), tf.expand_dims(m21, -1)], -1
          )
          mc2 = tf.concat(
              [tf.expand_dims(m12, -1), tf.expand_dims(m22, -1)], -1
          )
  
          # Set up absorbing boundary.
          should_be_zero = tf.expand_dims(
              tf.expand_dims((beta != 0) & (f <= 0.0), -1), -1
          )
          vol_matrix = tf.concat(
              [tf.expand_dims(mc1, -1), tf.expand_dims(mc2, -1)], -1
          )
          return tf.where(
              should_be_zero, tf.zeros_like(vol_matrix), vol_matrix
          )
  
      # Validate args
      control_dependencies = []
      if not _is_callable(self._beta):
          control_dependencies.append(
              tf.compat.v1.debugging.assert_greater_equal(
                  self._beta,
                  tf.constant(0, dtype=self._dtype),
                  message="Beta must be greater or equal to zero",
              )
          )
          control_dependencies.append(
              tf.compat.v1.debugging.assert_less_equal(
                  self._beta,
                  tf.constant(1, dtype=self._dtype),
                  message="Beta must be less than or equal to 1",
              )
          )
      if not _is_callable(self._volvol):
          control_dependencies.append(
              tf.compat.v1.debugging.assert_greater_equal(
                  self._volvol,
                  tf.constant(0, dtype=self._dtype),
                  message=(
                      "Volatility of volatility must be greater or equal to"
                      + " zero"
                  ),
              )
          )
      if not _is_callable(self._rho):
          control_dependencies.append(
              tf.compat.v1.debugging.assert_greater(
                  self._rho,
                  tf.constant(-1, dtype=self._dtype),
                  message="Correlation coefficient `rho` must be in (-1, 1)",
              )
          )
          control_dependencies.append(
              tf.compat.v1.debugging.assert_less(
                  self._rho,
                  tf.constant(1, dtype=self._dtype),
                  message="Correlation coefficient `rho` must be in (-1, 1)",
              )
          )
      control_dependencies.append(
          tf.compat.v1.debugging.assert_greater_equal(
              self._psi_threshold,
              tf.constant(1, dtype=self._dtype),
              message="Psi threshold must be in [1, 2]",
          )
      )
      control_dependencies.append(
          tf.compat.v1.debugging.assert_less_equal(
              self._psi_threshold,
              tf.constant(2, dtype=self._dtype),
              message="Psi threshold must be in [1, 2]",
          )
      )
      self.control_dependencies = control_dependencies
  
      super(SabrModel, self).__init__(
          2, drift_fn, _vol_fn, self._dtype, self._name
      )
  
file_path: tf-quant-finance/tf_quant_finance/models/sabr/sabr_model.py
imports: from typing import Optional
  import tensorflow.compat.v2
  from tf_quant_finance import types
  from tf_quant_finance import utils
  from tf_quant_finance.math import random_ops
  from tf_quant_finance.math.root_search.newton import root_finder
  from tf_quant_finance.models import generic_ito_process
  from tf_quant_finance.models import utils
label_desc: Use image node_id 1 to create a new SabrModel object from inherited base classes: generic_ito_process with example: obj = SabrModel(beta, volvol, rho, shift, enable_unbiased_sampling, psi_threshold, ncx2_cdf_truncation, dtype, name)