code: def _build_swap_curve(
      float_leg_start_times,
      float_leg_end_times,
      float_leg_daycount_fractions,
      fixed_leg_start_times,
      fixed_leg_end_times,
      fixed_leg_cashflows,
      fixed_leg_daycount_fractions,
      float_leg_discount_rates,
      float_leg_discount_times,
      fixed_leg_discount_rates,
      fixed_leg_discount_times,
      self_discounting_float_leg,
      self_discounting_fixed_leg,
      present_values,
      pv_settlement_times,
      optimizer,
      curve_interpolator,
      initial_rates,
      instrument_weights,
      curve_tolerance,
      maximum_iterations,
  ):
      """Build the zero swap curve."""
      # The procedure uses optimization to estimate the swap curve as follows:
      # 1. Start with an initial state of the swap curve.
      # 2. Define a loss function which measures the deviations between model prices
      #   of the IR swaps and their present values specified as input.
      # 3. Use numerical optimization (currently conjugate gradient optimization) to
      #   to build the swap curve such that the loss function is minimized.
      del fixed_leg_start_times, float_leg_daycount_fractions
      curve_tensors = _create_curve_building_tensors(
          float_leg_start_times,
          float_leg_end_times,
          fixed_leg_end_times,
          pv_settlement_times,
      )
      expiry_times = curve_tensors.expiry_times
      calc_groups_float = curve_tensors.calc_groups_float
      calc_groups_fixed = curve_tensors.calc_groups_fixed
      settle_times_float = curve_tensors.settle_times_float
      settle_times_fixed = curve_tensors.settle_times_fixed
  
      float_leg_calc_times_start = tf.concat(
          float_leg_start_times, axis=-1
      )
      float_leg_calc_times_end = tf.concat(float_leg_end_times, axis=-1)
      calc_fixed_leg_cashflows = tf.concat(fixed_leg_cashflows, axis=-1)
      calc_fixed_leg_daycount = tf.concat(
          fixed_leg_daycount_fractions, axis=-1
      )
      fixed_leg_calc_times = tf.concat(fixed_leg_end_times, axis=-1)
  
      def _interpolate(x1, x_data, y_data):
          return curve_interpolator(x1, x_data, y_data)
  
      @make_val_and_grad_fn
      def loss_function(x):
          """Loss function for the optimization."""
          # Currently the loss function is a weighted root mean squared difference
          # between the model PV and market PV. The model PV is interest rate swaps is
          # computed as follows:
  
          # 1. Interpolate the swap curve at intermediate times required to compute
          #   forward rates for the computation of floating cashflows.
          # 2. Interpolate swap curve or the discount curve (if a separate discount
          #   curve is specified) at intermediate cashflow times.
          # 3. Compute the PV of the swap as the aggregate of floating and fixed legs.
          # 4. Compute the loss (which is being minized) as the weighted root mean
          #   squared difference between the model PV (computed above) and the market
          #   PV (specified as input).
  
          rates_start = _interpolate(
              float_leg_calc_times_start, expiry_times, x
          )
          rates_end = _interpolate(
              float_leg_calc_times_end, expiry_times, x
          )
          float_cashflows = (
              tf.math.exp(
                  float_leg_calc_times_end * rates_end
                  - float_leg_calc_times_start * rates_start
              )
              - 1.0
          )
  
          if self_discounting_float_leg:
              float_discount_rates = rates_end
              float_settle_rates = _interpolate(
                  settle_times_float, expiry_times, x
              )
          else:
              float_discount_rates = _interpolate(
                  float_leg_calc_times_end,
                  float_leg_discount_times,
                  float_leg_discount_rates,
              )
              float_settle_rates = _interpolate(
                  settle_times_float,
                  float_leg_discount_times,
                  float_leg_discount_rates,
              )
          if self_discounting_fixed_leg:
              fixed_discount_rates = _interpolate(
                  fixed_leg_calc_times, expiry_times, x
              )
              fixed_settle_rates = _interpolate(
                  settle_times_fixed, expiry_times, x
              )
          else:
              fixed_discount_rates = _interpolate(
                  fixed_leg_calc_times,
                  fixed_leg_discount_times,
                  fixed_leg_discount_rates,
              )
              fixed_settle_rates = _interpolate(
                  settle_times_fixed,
                  fixed_leg_discount_times,
                  fixed_leg_discount_rates,
              )
  
          # exp(-r(t) * t) / exp(-r(t_s) * t_s)
          calc_discounts_float_leg = tf.math.exp(
              -float_discount_rates * float_leg_calc_times_end
              + float_settle_rates * settle_times_float
          )
          calc_discounts_fixed_leg = tf.math.exp(
              -fixed_discount_rates * fixed_leg_calc_times
              + fixed_settle_rates * settle_times_fixed
          )
          # Fast segment sum on `calc_discounts_float_leg` groups
          # TODO(b/178173737): use tf.math.segment_sum once a fast version is
          # supported
          float_pv = tf.linalg.matvec(
              calc_groups_float,
              float_cashflows * calc_discounts_float_leg,
          )
          # Fast segment sum on `calc_fixed_leg_cashflows` groups
          # TODO(b/178173737): use tf.math.segment_sum once a fast version is
          # supported
          fixed_pv = tf.linalg.matvec(
              calc_groups_fixed,
              calc_fixed_leg_daycount
              * calc_fixed_leg_cashflows
              * calc_discounts_fixed_leg,
          )
          swap_pv = float_pv + fixed_pv
          value = tf.math.reduce_sum(
              input_tensor=instrument_weights
              * (swap_pv - present_values) ** 2,
              axis=-1,
          )
  
          return value
  
      optimization_result = optimizer(
          loss_function,
          initial_position=initial_rates,
          tolerance=curve_tolerance,
          max_iterations=maximum_iterations,
      )
  
      discount_rates = optimization_result.position
      discount_factors = tf.math.exp(-discount_rates * expiry_times)
      results = scc.SwapCurveBuilderResult(
          times=expiry_times,
          rates=discount_rates,
          discount_factors=discount_factors,
          initial_rates=initial_rates,
          converged=optimization_result.converged,
          failed=optimization_result.failed,
          iterations=optimization_result.num_iterations,
          objective_value=optimization_result.objective_value,
      )
      return results
  
file_path: tf-quant-finance/tf_quant_finance/rates/swap_curve_fit.py
imports: from typing import List, Callable, Any
  import tensorflow.compat.v2
  from tf_quant_finance import types
  from tf_quant_finance import utils
  from tf_quant_finance.math import make_val_and_grad_fn
  from tf_quant_finance.math import optimizer
  from tf_quant_finance.math.interpolation import linear
  from tf_quant_finance.rates import swap_curve_common
label_desc: Use image node_id 2 for calling a global function with example usage: _build_swap_curve(float_leg_start_times, float_leg_end_times, float_leg_daycount_fractions, fixed_leg_start_times, fixed_leg_end_times, fixed_leg_cashflows, fixed_leg_daycount_fractions, float_leg_discount_rates, float_leg_discount_times, fixed_leg_discount_rates, fixed_leg_discount_times, _discounting_float_leg, _discounting_fixed_leg, present_values, pv_settlement_times, optimizer, curve_interpolator, initial_rates, instrument_weights, curve_tolerance, maximum_iterations) and returns: results, curve_interpolator, value