code: def _european_swaption_mc(
      model,
      expiries,
      fixed_leg_payment_times,
      fixed_leg_daycount_fractions,
      fixed_leg_coupon,
      notional,
      is_payer_swaption,
      times,
      time_step,
      num_time_steps,
      curve_times,
      num_samples,
      random_type,
      skip,
      seed,
      dtype,
      name,
  ):
      """Price European swaptions using Monte-Carlo."""
      with tf.name_scope(name):
          if (
              (times is None)
              and (time_step is None)
              and (num_time_steps is None)
          ):
              raise ValueError(
                  "One of `times`, `time_step` or `num_time_steps` must be "
                  "provided for simulation based swaption valuation."
              )
  
          def _sample_discount_curve_path_fn(
              times, curve_times, num_samples
          ):
              p_t_tau, r_t, df = model.sample_discount_curve_paths(
                  times=times,
                  curve_times=curve_times,
                  num_samples=num_samples,
                  random_type=random_type,
                  time_step=time_step,
                  num_time_steps=num_time_steps,
                  seed=seed,
                  skip=skip,
              )
              p_t_tau = tf.expand_dims(p_t_tau, axis=-1)
              r_t = tf.expand_dims(r_t, axis=-1)
              df = tf.expand_dims(df, axis=-1)
              return p_t_tau, r_t, df
  
          (
              payoff_discount_factors,
              payoff_bond_price,
          ) = swaption_util.discount_factors_and_bond_prices_from_samples(
              expiries=expiries,
              payment_times=fixed_leg_payment_times,
              sample_discount_curve_paths_fn=_sample_discount_curve_path_fn,
              num_samples=num_samples,
              times=times,
              curve_times=curve_times,
              dtype=dtype,
          )
  
          # Add an axis corresponding to `dim`
          fixed_leg_pv = (
              tf.expand_dims(
                  fixed_leg_coupon * fixed_leg_daycount_fractions,
                  axis=-1,
              )
              * payoff_bond_price
          )
  
          # Sum fixed coupon payments within each swap.
          # Here, axis=-2 is the payments axis - i.e. summing over all payments; and
          # the last axis is the `dim` axis, as explained in comment above
          # `fixed_leg_pv` (Note that for HJM the dim of this axis is 1 always).
          fixed_leg_pv = tf.math.reduce_sum(fixed_leg_pv, axis=-2)
          float_leg_pv = 1.0 - payoff_bond_price[..., -1, :]
          payoff_swap = payoff_discount_factors[..., -1, :] * (
              float_leg_pv - fixed_leg_pv
          )
          payoff_swap = tf.where(
              is_payer_swaption, payoff_swap, -1.0 * payoff_swap
          )
          payoff_swaption = tf.math.maximum(payoff_swap, 0.0)
          # Average over all simulation paths
          option_value = tf.math.reduce_mean(payoff_swaption, axis=0)
          return notional * tf.squeeze(option_value, axis=-1)
  
file_path: tf-quant-finance/tf_quant_finance/models/hjm/swaption_pricing.py
imports: from typing import Callable, Union
  import tensorflow.compat.v2
  from tf_quant_finance import types
  from tf_quant_finance.math import pde
  from tf_quant_finance.math import random
  from tf_quant_finance.models import utils
  from tf_quant_finance.models import valuation_method
  from tf_quant_finance.models.hjm import gaussian_hjm
  from tf_quant_finance.models.hjm import quasi_gaussian_hjm
  from tf_quant_finance.models.hjm import swaption_util
label_desc: Use image node_id 2 for calling a global function with example usage: _european_swaption_mc(model, expiries, fixed_leg_payment_times, fixed_leg_daycount_fractions, fixed_leg_coupon, notional, is_payer_swaption, times, time_step, num_time_steps, curve_times, num_samples, random_type, skip, seed, dtype, name) and returns: unknown, p_t_tau,  r_t,  df