def test_interpolated_yields_with_yields(self, interpolation_times, reference_times, yields, expected): dtypes = [np.float32, np.float64] for dtype in dtypes: expected = np.array(expected, dtype=dtype) actual = self.evaluate( monotone_convex.interpolate_yields(interpolation_times, reference_times, yields=yields, dtype=dtype)) np.testing.assert_allclose(actual, expected, rtol=1e-5)
def test_interpolated_yields_consistency(self): dtypes = [np.float32, np.float64] for dtype in dtypes: reference_times = np.array([1.0, 2.0, 3.0, 4.0], dtype=dtype) yields = np.array([5.0, 4.75, 4.53333333, 4.775], dtype=dtype) # Times for which the interpolated values are required. interpolation_times_1 = tf.constant([0.25, 0.5, 1.0, 2.0, 3.0], dtype=dtype) interpolation_times_2 = tf.constant([1.1, 2.5, 2.9, 3.6, 4.0], dtype=dtype) expected = np.array([ 5.1171875, 5.09375, 5.0, 4.75, 4.533333, 4.9746, 4.624082, 4.535422, 4.661777, 4.775 ], dtype=dtype) actual_1 = monotone_convex.interpolate_yields( interpolation_times_1, reference_times, yields=yields) actual_2 = monotone_convex.interpolate_yields( interpolation_times_2, reference_times, yields=yields) actual = self.evaluate(tf.concat([actual_1, actual_2], axis=0)) np.testing.assert_allclose(actual, expected, rtol=1e-5)
def _compute_pv(cashflows, cashflow_times, reference_rates, reference_times): times = tf.concat(cashflow_times, axis=0) groups = tf.concat([ tf.zeros_like(cashflow, dtype=tf.int32) + i for i, cashflow in enumerate(cashflows) ], axis=0) rates = monotone_convex.interpolate_yields(times, reference_times, yields=reference_rates) discounts = tf.math.exp(-times * rates) cashflows = tf.concat(cashflows, axis=0) return tf.math.segment_sum(discounts * cashflows, groups)
def test_interpolated_yields_zero_time(self): """Checks the interpolation for yield curve is non-NaN for 0 time.""" dtypes = [np.float32, np.float64] for dtype in dtypes: reference_times = np.array([0.3, 1.0, 1.43, 3.7, 9.2, 12.48], dtype=dtype) yields = np.array([3.0, 3.1, 2.9, 4.1, 4.3, 5.1], dtype=dtype) # Times for which the interpolated values are required. interpolation_times = tf.constant([0.0], dtype=dtype) actual = self.evaluate( monotone_convex.interpolate_yields( interpolation_times, reference_times, yields=yields)) np.testing.assert_allclose(actual, [0.0], rtol=1e-8)
def one_step(converged, failed, iteration, expiry_discounts): """One step of the iteration.""" expiry_rates = -tf.math.log(expiry_discounts) / expiry_times failed = tf.math.reduce_any( tf.math.is_nan(expiry_rates) | tf.math.is_nan(expiry_discounts)) calc_rates = monotone_convex.interpolate_yields( calc_times, expiry_times, yields=expiry_rates) calc_discounts = tf.math.exp(-calc_rates * calc_times) next_expiry_discounts = -tf.math.segment_sum( calc_bond_cashflows * calc_discounts, calc_groups) / expiry_bond_cashflows discount_diff = tf.math.abs(next_expiry_discounts - expiry_discounts) converged = (~tf.math.reduce_any(tf.math.is_nan(discount_diff)) & (tf.math.reduce_max(discount_diff) < discount_tolerance)) return converged, failed, iteration + 1, next_expiry_discounts
def test_interpolated_yields_flat_curve(self): """Checks the interpolation for flat curves.""" dtypes = [np.float32, np.float64] for dtype in dtypes: reference_times = np.array([0.3, 1.0, 1.43, 3.7, 9.2, 12.48], dtype=dtype) yields = np.array([8.0] * 6, dtype=dtype) # Times for which the interpolated values are required. interpolation_times = tf.constant( [0.1, 1.1, 1.22, 0.45, 1.8, 3.8, 7.45, 7.73, 9.6, 11.7, 12.], dtype=dtype) expected = np.array([8.0] * 11, dtype=dtype) actual = self.evaluate( monotone_convex.interpolate_yields( interpolation_times, reference_times, yields=yields)) np.testing.assert_allclose(actual, expected, rtol=1e-5)
def test_interpolated_yields_with_discrete_forwards(self): dtypes = [np.float32, np.float64] for dtype in dtypes: reference_times = tf.constant([1.0, 2.0, 3.0, 4.0], dtype=dtype) discrete_forwards = tf.constant([5, 4.5, 4.1, 5.5], dtype=dtype) test_times = tf.constant( [0.25, 0.5, 1.0, 2.0, 3.0, 1.1, 2.5, 2.9, 3.6, 4.0], dtype=dtype) expected = np.array([ 5.1171875, 5.09375, 5.0, 4.75, 4.533333, 4.9746, 4.624082, 4.535422, 4.661777, 4.775 ], dtype=dtype) actual = self.evaluate( monotone_convex.interpolate_yields( test_times, reference_times, discrete_forwards=discrete_forwards)) np.testing.assert_allclose(actual, expected, rtol=1e-5)