def _generate_schedule(self, cpn_frequency, roll_convention): """Method to generate coupon dates.""" if (self._first_coupon_date is None) and (self._penultimate_coupon_date is None): cpn_dates = dates.PeriodicSchedule( start_date=self._start_date, end_date=self._end_date, tenor=cpn_frequency, roll_convention=roll_convention).dates() elif self._first_coupon_date is not None: cpn_dates = dates.PeriodicSchedule( start_date=self._first_coupon_date, end_date=self._end_date, tenor=cpn_frequency, roll_convention=roll_convention).dates() cpn_dates = dates.DateTensor.concat( [self._start_date.expand_dims(-1), cpn_dates], axis=1) else: cpn_dates = dates.PeriodicSchedule( start_date=self._start_date, end_date=self._penultimate_coupon_date, backward=True, tenor=cpn_frequency, roll_convention=roll_convention).dates() cpn_dates = dates.DateTensor.concat( [cpn_dates, self._end_date.expand_dims(-1)], axis=1) return cpn_dates
def _generate_schedule(self, cpn_frequency, roll_convention): """Method to generate coupon dates. Args: cpn_frequency: A `PeriodTensor` specifying the frequency of coupon payments. roll_convention: Scalar of type `BusinessDayConvention` specifying how dates are rolled if they fall on holidays. Returns: A tuple containing the generated date schedule and a boolean `Tensor` of the same shape as the schedule specifying whether the coupons are regular coupons. """ if (self._first_coupon_date is None) and (self._penultimate_coupon_date is None): cpn_dates = dates.PeriodicSchedule( start_date=self._start_date, end_date=self._end_date, tenor=cpn_frequency, roll_convention=roll_convention).dates() is_regular_cpn = tf.constant( True, dtype=bool, shape=cpn_dates[:, :-1].shape) elif self._first_coupon_date is not None: cpn_dates = dates.PeriodicSchedule( start_date=self._first_coupon_date, end_date=self._end_date, tenor=cpn_frequency, roll_convention=roll_convention).dates() cpn_dates = dates.DateTensor.concat( [self._start_date.expand_dims(-1), cpn_dates], axis=1) is_irregular_cpn = tf.constant( False, dtype=bool, shape=self._start_date.shape) is_regular_cpn = tf.concat([ tf.expand_dims(is_irregular_cpn, axis=-1), tf.constant(True, dtype=bool, shape=cpn_dates[:, :-2].shape) ], axis=1) else: cpn_dates = dates.PeriodicSchedule( start_date=self._start_date, end_date=self._penultimate_coupon_date, backward=True, tenor=cpn_frequency, roll_convention=roll_convention).dates() cpn_dates = dates.DateTensor.concat( [cpn_dates, self._end_date.expand_dims(-1)], axis=1) is_irregular_cpn = tf.constant( False, dtype=bool, shape=self._end_date.shape) is_regular_cpn = tf.concat([ tf.constant(True, dtype=bool, shape=cpn_dates[:, :-2].shape), tf.expand_dims(is_irregular_cpn, axis=-1) ], axis=1) return cpn_dates, is_regular_cpn
def test_periodic_schedule(self, start_dates, end_dates, period_quantities, period_type, backward, expected_schedule, end_of_month=False): start_dates = dates.from_np_datetimes(_to_np_datetimes(start_dates)) end_dates = dates.from_np_datetimes(_to_np_datetimes(end_dates)) tenors = dates.periods.PeriodTensor(period_quantities, period_type) expected_schedule = dates.from_np_datetimes( _to_np_datetimes(expected_schedule)) actual_schedule = dates.PeriodicSchedule( start_date=start_dates, end_date=end_dates, tenor=tenors, holiday_calendar=dates.HolidayCalendar( weekend_mask=dates.WeekendMask.SATURDAY_SUNDAY, start_year=2020, end_year=2028), roll_convention=dates.BusinessDayConvention.MODIFIED_FOLLOWING, backward=backward, end_of_month=end_of_month).dates() self.assertAllEqual(expected_schedule.ordinal(), actual_schedule.ordinal())
def _setup_tensors(self): """Sets up tensors for efficient computations.""" date_schedule = dates.PeriodicSchedule( start_date=self._start_date, end_date=self._maturity_date, tenor=self._reset_frequency).dates() # rates reset at the begining of coupon period reset_dates = date_schedule[:, :-1] # payments occur at the end of the coupon period payment_dates = date_schedule[:, 1:] daycount_fractions = rc.get_daycount_fraction( date_schedule[:, :-1], date_schedule[:, 1:], self._daycount_convention, dtype=self._dtype) contract_index = tf.repeat( tf.range(0, self._batch_size), payment_dates.shape.as_list()[-1]) self._num_caplets = daycount_fractions.shape.as_list()[-1] # TODO(b/152164086): Use the functionality from dates library self._rate_term = tf.repeat(tf.cast(reset_dates[:, 0].days_until( payment_dates[:, 0]), dtype=self._dtype) / 365.0, self._num_caplets) self._reset_dates = dates.DateTensor.reshape(reset_dates, [-1]) self._payment_dates = dates.DateTensor.reshape(payment_dates, [-1]) self._accrual_start_dates = dates.DateTensor.reshape(reset_dates, [-1]) self._accrual_end_dates = dates.DateTensor.reshape(payment_dates, [-1]) self._daycount_fractions = tf.reshape(daycount_fractions, [-1]) self._contract_index = contract_index self._strike = tf.repeat(self._strike, self._num_caplets) self._is_cap = tf.repeat(self._is_cap, self._num_caplets)
def _setup(self, coupon_spec): """Setup tensors for efficient computations.""" cpn_frequency = dates.periods.PeriodTensor.stack( [x.coupon_frequency for x in coupon_spec], axis=0) cpn_dates = dates.PeriodicSchedule( start_date=self._start_date, end_date=self._end_date, tenor=cpn_frequency, roll_convention=coupon_spec[-1].businessday_rule).dates() accrual_start_dates = cpn_dates[:, :-1] ref_term = dates.periods.PeriodTensor.stack( [x.reference_rate_term for x in coupon_spec], axis=0) accrual_end_dates = cpn_dates[:, : -1] + dates.periods.PeriodTensor.expand_dims( ref_term, axis=-1).broadcast_to( accrual_start_dates.shape) coupon_start_dates = cpn_dates[:, :-1] coupon_end_dates = cpn_dates[:, 1:] payment_dates = cpn_dates[:, 1:] daycount_fractions = rc.get_daycount_fraction( cpn_dates[:, :-1], cpn_dates[:, 1:], coupon_spec[-1].daycount_convention, dtype=self._dtype) notional = tf.repeat( tf.convert_to_tensor([x.notional for x in coupon_spec], dtype=self._dtype), payment_dates.shape.as_list()[-1]) coupon_basis = tf.repeat( tf.convert_to_tensor([x.coupon_basis for x in coupon_spec], dtype=self._dtype), payment_dates.shape.as_list()[-1]) coupon_multiplier = tf.repeat( tf.convert_to_tensor([x.coupon_multiplier for x in coupon_spec], dtype=self._dtype), payment_dates.shape.as_list()[-1]) contract_index = tf.repeat(tf.range(0, len(coupon_spec)), payment_dates.shape.as_list()[-1]) self._num_cashflows = daycount_fractions.shape.as_list()[-1] self._coupon_start_dates = coupon_start_dates.reshape([-1]) self._coupon_end_dates = coupon_end_dates.reshape([-1]) self._payment_dates = payment_dates.reshape([-1]) self._accrual_start_date = accrual_start_dates.reshape([-1]) self._accrual_end_date = accrual_end_dates.reshape([-1]) self._notional = notional self._daycount_fractions = tf.reshape(daycount_fractions, [-1]) self._coupon_basis = coupon_basis self._coupon_multiplier = coupon_multiplier self._contract_index = contract_index
def _setup(self): """Setup relevant tensors for efficient computations.""" reset_dates = [] contract_idx = [] daycount_fractions = [] for i in range(self._batch_size): instr_reset_dates = dates.PeriodicSchedule( start_date=self._start_date[i] + self._rate_tenor, end_date=self._end_date[i], tenor=self._rate_tenor, holiday_calendar=self._holiday_calendar, roll_convention=dates.BusinessDayConvention.FOLLOWING).dates() # Append the start_date of the contract instr_reset_dates = dates.DateTensor.concat( [self._start_date[i].expand_dims(axis=0), instr_reset_dates], axis=0) # Add one day beyond the end of the delivery period to compute the # accrual on the last day of the delivery. one_period_past_enddate = self._end_date[i] + self._rate_tenor instr_reset_dates = dates.DateTensor.concat([ instr_reset_dates, one_period_past_enddate.expand_dims(axis=0) ], axis=0) instr_daycount_fractions = rc.get_daycount_fraction( instr_reset_dates[:-1], instr_reset_dates[1:], self._daycount_convention, self._dtype) reset_dates.append(instr_reset_dates[:-1]) daycount_fractions.append(instr_daycount_fractions) contract_idx.append(tf.fill(tf.shape(instr_daycount_fractions), i)) self._reset_dates = dates.DateTensor.concat(reset_dates, axis=0) self._accrual_start_dates = self._reset_dates self._accrual_end_dates = self._reset_dates + self._rate_tenor self._accrual_daycount = rc.get_daycount_fraction( self._accrual_start_dates, self._accrual_end_dates, self._daycount_convention, self._dtype) self._daycount_fractions = tf.concat(daycount_fractions, axis=0) self._contract_idx = tf.concat(contract_idx, axis=0)
def _setup(self, coupon_spec): """Setup tensors for efficient computations.""" cpn_frequency = dates.periods.PeriodTensor.stack( [x.coupon_frequency for x in coupon_spec], axis=0) cpn_dates = dates.PeriodicSchedule( start_date=self._start_date, end_date=self._end_date, tenor=cpn_frequency, roll_convention=coupon_spec[-1].businessday_rule).dates() payment_dates = cpn_dates[:, 1:] notional = tf.expand_dims(tf.convert_to_tensor( [x.notional for x in coupon_spec], dtype=self._dtype), axis=-1) notional = tf.repeat(notional, payment_dates.shape.as_list()[-1], axis=-1) daycount_fractions = rc.get_daycount_fraction( cpn_dates[:, :-1], cpn_dates[:, 1:], coupon_spec[-1].daycount_convention, dtype=self._dtype) fixed_rate = tf.convert_to_tensor([x.coupon_rate for x in coupon_spec], dtype=self._dtype) coupon_rate = tf.expand_dims(fixed_rate, axis=-1) coupon_rate = tf.repeat(coupon_rate, payment_dates.shape.as_list()[-1], axis=-1) contract_index = tf.repeat(tf.range(0, len(coupon_spec)), notional.shape.as_list()[-1]) self._payment_dates = payment_dates.reshape([-1]) self._notional = tf.reshape(notional, [-1]) self._daycount_fractions = tf.reshape(daycount_fractions, [-1]) self._coupon_rate = tf.reshape(coupon_rate, [-1]) self._fixed_rate = tf.convert_to_tensor(fixed_rate, dtype=self._dtype) self._contract_index = contract_index