docstr: Demonstrate that lower/upper limits can be set independently in batch.
docstr_tok: ["Demonstrate","that","lower\/upper","limits","can","be","set","independently","in","batch","."]
code: def test_calibration_batch_limits(self):
      """Demonstrate that lower/upper limits can be set independently in batch."""
      dtype = np.float64
  
      observed_prices = np.array(
          [
              [
                  29.45783648,
                  24.15306768,
                  19.73346361,
                  16.08792179,
                  13.10198113,
              ],
              [
                  16.02509124,
                  21.51061818,
                  27.61195796,
                  34.24527161,
                  41.33562669,
              ],
          ],
          dtype=dtype,
      )
  
      strikes = np.array(
          [
              [80.0, 90.0, 100.0, 110.0, 120.0],
              [80.0, 90.0, 100.0, 110.0, 120.0],
          ],
          dtype=dtype,
      )
      expiries = np.array([[0.5], [1.0]], dtype=dtype)
      forwards = 100.0
      is_call_options = np.array([[True], [False]])
  
      models, is_converged, _ = tff.models.heston.calibration(
          prices=observed_prices,
          strikes=strikes,
          expiries=expiries,
          forwards=forwards,
          is_call_options=is_call_options,
          mean_reversion=np.array([0.4, 0.4], dtype=dtype),
          mean_reversion_lower_bound=np.array([0.05, 0.1]),
          mean_reversion_upper_bound=np.array([1.0, 5.0]),
          theta=np.array([0.9, 0.9], dtype=dtype),
          theta_lower_bound=np.array([0.1, 0.0]),
          theta_upper_bound=np.array([1.0, 1.0]),
          initial_variance=np.array([0.25, 0.25], dtype=dtype),
          initial_variance_lower_bound=np.array([0.1, 0.0]),
          initial_variance_upper_bound=np.array([5.0, 1.0]),
          volvol=np.array([0.75, 0.75], dtype=dtype),
          volvol_lower_bound=np.array([0.0, 0.05]),
          volvol_upper_bound=np.array([1.0, 5.0]),
          rho=np.array([-0.5, -0.5], dtype=dtype),
          rho_lower_bound=np.array([-1.0, -0.75]),
          rho_upper_bound=np.array([1.0, 0.75]),
          maximum_iterations=100,
      )
  
      [
          calibrated_initial_variance,
          calibrated_mean_reversion,
          calibrated_volvol,
          calibrated_rho,
          calibrated_theta,
          is_converged,
      ] = self.evaluate(
          [
              models.initial_variance[:, tf.newaxis],
              models.mean_reversion[:, tf.newaxis],
              models.volvol[:, tf.newaxis],
              models.rho[:, tf.newaxis],
              models.theta[:, tf.newaxis],
              is_converged,
          ]
      )
  
      with self.subTest("AllConverged"):
          self.assertTrue(all(is_converged))
  
      calibrated_prices = (
          tff.models.heston.approximations.european_option_price(
              variances=calibrated_initial_variance,
              strikes=strikes,
              expiries=expiries,
              forwards=forwards,
              is_call_options=is_call_options,
              mean_reversion=calibrated_mean_reversion,
              theta=calibrated_theta,
              volvol=calibrated_volvol,
              rho=calibrated_rho,
              dtype=dtype,
          )
      )
      with self.subTest("PricesRecovered"):
          self.assertAllClose(
              calibrated_prices, observed_prices, atol=1e-3, rtol=1e-3
          )
  
file_path: tf-quant-finance/tf_quant_finance/models/heston/approximations/calibration_test.py
imports: from absl.testing import parameterized
  import numpy
  import tensorflow.compat.v2
  import tf_quant_finance
  from tensorflow.python.framework import test_util
label_desc: Use image node_id 2 for calling the CalibrationTest obj's underlying member method code with example usage: obj.test_calibration_batch_limits() without return types