docstr: Test that the SABR model computes the same price as the Euler method.
docstr_tok: ["Test","that","the","SABR","model","computes","the","same","price","as","the","Euler","method","."]
code: def test_pricing_european_option(
      self,
      beta,
      volvol,
      rho,
      time_step,
      initial_forward,
      strikes,
      initial_volatility,
      put_option=True,
  ):
      """Test that the SABR model computes the same price as the Euler method."""
      dtype = np.float64
      times = [0.5]
      num_samples = 10000
      test_seed = [123, 124]
      beta = tf.convert_to_tensor(beta, dtype=dtype)
      volvol = tf.convert_to_tensor(volvol, dtype=dtype)
      rho = tf.convert_to_tensor(rho, dtype=dtype)
  
      if put_option:
          option_fn = lambda samples, strike: strike - samples
      else:
          option_fn = lambda samples, strike: samples - strike
  
      drift_fn = lambda _, x: tf.zeros_like(x)
  
      def _vol_fn(t, x):
          """The volatility function for the SABR model."""
          del t
          f = x[..., 0]
          v = x[..., 1]
          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
          )
  
      euler_paths = euler_sampling.sample(
          dim=2,
          drift_fn=drift_fn,
          volatility_fn=_vol_fn,
          times=times,
          time_step=time_step,
          num_samples=num_samples,
          initial_state=[initial_forward, initial_volatility],
          random_type=tff.math.random.RandomType.STATELESS_ANTITHETIC,
          seed=test_seed,
          dtype=dtype,
      )
  
      euler_paths = self.evaluate(euler_paths)
      euler_samples = euler_paths[..., 0]
  
      process = SabrModel(
          beta=beta,
          volvol=volvol,
          rho=rho,
          dtype=dtype,
          enable_unbiased_sampling=True,
      )
      # Use a 10x grid step to make the test faster.
      paths = process.sample_paths(
          initial_forward=initial_forward,
          initial_volatility=initial_volatility,
          times=times,
          time_step=time_step * 10,
          num_samples=num_samples,
          seed=test_seed,
          validate_args=True,
          random_type=tff.math.random.RandomType.STATELESS_ANTITHETIC,
      )
      paths = self.evaluate(paths)
      samples = paths[..., 0]
  
      for strike in strikes:
          euler_mean, euler_price = (
              np.average(euler_samples),
              np.average(
                  np.maximum(option_fn(euler_samples, strike), 0)
              ),
          )
          mean, price = (
              np.average(samples),
              np.average(np.maximum(option_fn(samples, strike), 0)),
          )
          self.assertAllClose(
              [euler_mean, euler_price],
              [mean, price],
              rtol=0.05,
              atol=0.05,
          )
  
file_path: tf-quant-finance/tf_quant_finance/models/sabr/sabr_model_test.py
imports: import math
  from absl.testing import parameterized
  import numpy
  import tensorflow.compat.v2
  import tf_quant_finance
  from tensorflow.python.framework import test_util
  from tf_quant_finance.models import euler_sampling
label_desc: Use image node_id 5 for calling the SabrModelTest obj's underlying member method code with example usage: obj.test_pricing_european_option(beta, volvol, rho, time_step, initial_forward, strikes, initial_volatility, put_option) and returns: tf