def __init__(self, start_date, end_date, coupon_spec, first_coupon_date=None, penultimate_coupon_date=None, dtype=None, name=None): """Initialize a batch of floating cashflow streams. Args: start_date: A rank 1 `DateTensor` specifying the starting dates of the accrual of the first coupon of the cashflow stream. The shape of the input correspond to the numbercof streams being created. end_date: A rank 1 `DateTensor` specifying the end dates for accrual of the last coupon in each cashflow stream. The shape of the input should be the same as that of `start_date`. coupon_spec: A list of `FloatCouponSpecs` specifying the details of the coupon payment for the cashflow stream. The length of the list should be the same as the number of streams being created. Each coupon within the list must have the same daycount_convention and businessday_rule. first_coupon_date: An optional rank 1 `DateTensor` specifying the payment dates of the first coupon of the cashflow stream. Use this input for cashflows with irregular first coupon. Default value: None which implies regular first coupon. penultimate_coupon_date: An optional rank 1 `DateTensor` specifying the payment date of the penultimate (next to last) coupon of the cashflow stream. Use this input for cashflows with irregular last coupon. Default value: None which implies regular last coupon. dtype: `tf.Dtype`. If supplied the dtype for the real variables or ops either supplied to the FloatingCashflowStream object or created by the object. Default value: None which maps to the default dtype inferred by TensorFlow. name: Python str. The name to give to the ops created by this class. Default value: `None` which maps to 'floating_cashflow_stream'. """ super(FloatingCashflowStream, self).__init__() self._name = name or 'floating_cashflow_stream' with tf.name_scope(self._name): self._start_date = dates.convert_to_date_tensor(start_date) self._end_date = dates.convert_to_date_tensor(end_date) self._batch_size = self._start_date.shape[0] if first_coupon_date is None: self._first_coupon_date = None else: self._first_coupon_date = dates.convert_to_date_tensor( first_coupon_date) if penultimate_coupon_date is None: self._penultimate_coupon_date = None else: self._penultimate_coupon_date = dates.convert_to_date_tensor( penultimate_coupon_date) self._dtype = dtype self._setup(coupon_spec)
def __init__(self, settlement_date, maturity_date, coupon_spec, start_date=None, first_coupon_date=None, penultimate_coupon_date=None, holiday_calendar=None, dtype=None, name=None): """Initialize a batch of fixed coupon bonds. Args: settlement_date: A rank 1 `DateTensor` specifying the settlement date of the bonds. maturity_date: A rank 1 `DateTensor` specifying the maturity dates of the bonds. The shape of the input should be the same as that of `settlement_date`. coupon_spec: A list of `FixedCouponSpecs` specifying the coupon payments. The length of the list should be the same as the number of bonds being created. start_date: An optional `DateTensor` specifying the dates when the interest starts to accrue for the coupons. The input can be used to specify a forward start date for the coupons. The shape of the input correspond to the numbercof instruments being created. Default value: None in which case the coupons start to accrue from the `settlement_date`. first_coupon_date: An optional rank 1 `DateTensor` specifying the dates when first coupon will be paid for bonds with irregular first coupon. penultimate_coupon_date: An optional rank 1 `DateTensor` specifying the dates when the penultimate coupon (or last regular coupon) will be paid for bonds with irregular last coupon. holiday_calendar: An instance of `dates.HolidayCalendar` to specify weekends and holidays. Default value: None in which case a holiday calendar would be created with Saturday and Sunday being the holidays. dtype: `tf.Dtype`. If supplied the dtype for the real variables or ops either supplied to the bond object or created by the bond object. Default value: None which maps to the default dtype inferred by TensorFlow. name: Python str. The name to give to the ops created by this class. Default value: `None` which maps to 'bond'. """ self._name = name or 'bond' if holiday_calendar is None: holiday_calendar = dates.HolidayCalendar2( weekend_mask=dates.WeekendMask.SATURDAY_SUNDAY) with tf.name_scope(self._name): self._dtype = dtype self._settlement_date = dates.convert_to_date_tensor( settlement_date) self._maturity_date = dates.convert_to_date_tensor(maturity_date) self._holiday_calendar = holiday_calendar self._setup(coupon_spec, start_date, first_coupon_date, penultimate_coupon_date)
def __init__(self, start_date, maturity_date, pay_leg, receive_leg, holiday_calendar=None, dtype=None, name=None): """Initialize a batch of IRS contracts. Args: start_date: A rank 1 `DateTensor` specifying the dates for the inception (start of the accrual) of the swap contracts. The shape of the input correspond to the number of instruments being created. maturity_date: A rank 1 `DateTensor` specifying the maturity dates for each contract. The shape of the input should be the same as that of `start_date`. pay_leg: A scalar or a list of either `FixedCouponSpecs` or `FloatCouponSpecs` specifying the coupon payments for the payment leg of the swap. If specified as a list then the length of the list should be the same as the number of instruments being created. If specified as a scalar, then the elements of the namedtuple must be of the same shape as (or compatible to) the shape of `start_date`. receive_leg: A scalar or a list of either `FixedCouponSpecs` or `FloatCouponSpecs` specifying the coupon payments for the receiving leg of the swap. If specified as a list then the length of the list should be the same as the number of instruments being created. If specified as a scalar, then the elements of the namedtuple must be of the same shape as (or compatible with) the shape of `start_date`. holiday_calendar: An instance of `dates.HolidayCalendar` to specify weekends and holidays. Default value: None in which case a holiday calendar would be created with Saturday and Sunday being the holidays. dtype: `tf.Dtype`. If supplied the dtype for the real variables or ops either supplied to the IRS object or created by the IRS object. Default value: None which maps to the default dtype inferred by TensorFlow. name: Python str. The name to give to the ops created by this class. Default value: `None` which maps to 'interest_rate_swap'. """ self._name = name or 'interest_rate_swap' if holiday_calendar is None: holiday_calendar = dates.HolidayCalendar2( weekend_mask=dates.WeekendMask.SATURDAY_SUNDAY) with tf.name_scope(self._name): self._dtype = dtype self._start_date = dates.convert_to_date_tensor(start_date) self._maturity_date = dates.convert_to_date_tensor(maturity_date) self._holiday_calendar = holiday_calendar self._floating_leg = None self._fixed_leg = None self._pay_leg = self._setup_leg(pay_leg) self._receive_leg = self._setup_leg(receive_leg) self._is_payer = isinstance(self._pay_leg, cs.FixedCashflowStream)
def test_convert_to_date_tensor_ordinals(self): inputs = [1, 2, 3, 4, 5] inputs2 = tf.constant(inputs) date_tensor = dateslib.convert_to_date_tensor(inputs) date_tensor2 = dateslib.convert_to_date_tensor(inputs2) self.assert_date_tensor_equals(date_tensor, [1, 1, 1, 1, 1], [1, 1, 1, 1, 1], [1, 2, 3, 4, 5], inputs) self.assert_date_tensor_equals(date_tensor2, [1, 1, 1, 1, 1], [1, 1, 1, 1, 1], [1, 2, 3, 4, 5], inputs)
def price(self, valuation_date, market, model=None, pricing_context=None, name=None): """Returns the present value of the instrument on the valuation date. Args: valuation_date: A scalar `DateTensor` specifying the date on which valuation is being desired. market: A namedtuple of type `InterestRateMarket` which contains the necessary information for pricing the interest rate swap. model: Reserved for future use. pricing_context: Additional context relevant for pricing. name: Python str. The name to give to the ops created by this function. Default value: `None` which maps to 'price'. Returns: A Rank 1 `Tensor` of real type containing the modeled price of each IRS contract based on the input market data. """ name = name or (self._name + '_price') with tf.name_scope(name): valuation_date = dates.convert_to_date_tensor(valuation_date) pay_cf = self._pay_leg.price(valuation_date, market, model, pricing_context) receive_cf = self._receive_leg.price(valuation_date, market, model, pricing_context) return receive_cf - pay_cf
def __init__(self, swap, expiry_date=None, dtype=None, name=None): """Initialize a batch of European swaptions. Args: swap: An instance of `InterestRateSwap` specifying the interest rate swaps underlying the swaptions. The batch size of the swaptions being created would be the same as the batch size of the `swap`. expiry_date: An optional rank 1 `DateTensor` specifying the expiry dates for each swaption. The shape of the input should be the same as the batch size of the `swap` input. Default value: None in which case the option expity date is the same as the start date of each underlying swap. dtype: `tf.Dtype`. If supplied the dtype for the real variables or ops either supplied to the Swaption object or created by the Swaption object. Default value: None which maps to the default dtype inferred by TensorFlow. name: Python str. The name to give to the ops created by this class. Default value: `None` which maps to 'swaption'. """ self._name = name or 'swaption' with tf.name_scope(self._name): self._dtype = dtype self._expiry_date = dates.convert_to_date_tensor(expiry_date) self._swap = swap
def price(self, valuation_date, market, model=None): """Returns the present value of the instrument on the valuation date. Args: valuation_date: A scalar `DateTensor` specifying the date on which valuation is being desired. market: A namedtuple of type `InterestRateMarket` which contains the necessary information for pricing the FRA instrument. model: Reserved for future use. Returns: A scalar `Tensor` of real type containing the modeled price of the FRA based on the input market data. """ del model valuation_date = dates.convert_to_date_tensor(valuation_date) settlement_t = elapsed_time(valuation_date, self._settlement_date, self._dtype) accrual_start_t = elapsed_time(valuation_date, self._accrual_start_date, self._dtype) accrual_end_t = elapsed_time(valuation_date, self._accrual_end_date, self._dtype) reference_curve = market.reference_curve discount_curve = market.discount_curve fwd_rate = reference_curve.get_forward_rate(accrual_start_t, accrual_end_t, self._daycount_fraction) discount_at_settlement = discount_curve.get_discount(settlement_t) return discount_at_settlement * self._notional * ( fwd_rate - self._fixed_rate) * self._daycount_fraction / ( 1. + self._daycount_fraction * fwd_rate)
def par_rate(self, valuation_date, market, model=None): """Returns the par swap rate for the swap.""" valuation_date = dates.convert_to_date_tensor(valuation_date) swap_annuity = self._annuity(valuation_date, market, model, False) float_pv = self._floating_leg.price(valuation_date, market, model) return float_pv / swap_annuity
def test_convert_to_date_tensor_tensor_tuples(self): inputs = [ tf.constant([2018, 2042, 1947]), tf.constant([5, 11, 8]), tf.constant([4, 22, 15]) ] date_tensor = dateslib.convert_to_date_tensor(inputs) y, m, d = [2018, 2042, 1947], [5, 11, 8], [4, 22, 15] self.assert_date_tensor_equals(date_tensor, y, m, d, None)
def test_convert_to_date_tensor_datetimes(self): inputs = [ datetime.date(2018, 5, 4), datetime.date(2042, 11, 22), datetime.date(1947, 8, 15) ] date_tensor = dateslib.convert_to_date_tensor(inputs) y, m, d = [2018, 2042, 1947], [5, 11, 8], [4, 22, 15] self.assert_date_tensor_equals(date_tensor, y, m, d, None)
def test_providing_holidays(self, holidays, convert_to_date_tensor=False): if convert_to_date_tensor: holidays = dates.convert_to_date_tensor(holidays) cal = self.impl( weekend_mask=dates.WeekendMask.SATURDAY_SUNDAY, holidays=holidays) date_tensor = dates.from_tuples([(2020, 1, 1), (2020, 5, 1), (2020, 12, 25), (2021, 3, 8), (2021, 1, 1)]) self.assertAllEqual([False, True, False, True, False], cal.is_business_day(date_tensor))
def test_convert_to_date_tensor_npdatetime(self): inputs = np.array([ datetime.date(2018, 5, 4), datetime.date(2042, 11, 22), datetime.date(1947, 8, 15) ], dtype='datetime64') date_tensor = dateslib.convert_to_date_tensor(inputs) y, m, d = [2018, 2042, 1947], [5, 11, 8], [4, 22, 15] self.assert_date_tensor_equals(date_tensor, y, m, d, None)
def ratecurve_from_discounting_function(discount_fn, dtype=None): """Returns `RateCurve` object using the supplied function for discounting. Args: discount_fn: A python callable which takes a `DateTensor` as an input and returns the corresponding discount factor as an output. dtype: `tf.Dtype`. Optional input specifying the dtype of the real tensors and ops. Returns: An object of class `RateCurveFromDiscountingFunction` which uses the supplied function for discounting. """ dtype = dtype or tf.constant(0.0).dtype pseudo_maturity_dates = dates.convert_to_date_tensor([(2020, 1, 1)]) pseudo_rates = tf.convert_to_tensor([0.0], dtype=dtype) pseudo_valuation_date = dates.convert_to_date_tensor((2020, 1, 1)) return RateCurveFromDiscountingFunction(pseudo_maturity_dates, pseudo_rates, pseudo_valuation_date, discount_fn, dtype)
def get_forward_rate(self, start_date, maturity_date, daycount_fraction=None): """Returns the simply accrued forward rate between [start_dt, maturity_dt]. Args: start_date: A `DateTensor` specifying the start of the accrual period for the forward rate. maturity_date: A `DateTensor` specifying the end of the accrual period for the forward rate. The shape of `maturity_date` must be the same as the shape of the `DateTensor` `start_date`. daycount_fraction: An optional `Tensor` of real dtype specifying the time between `start_date` and `maturity_date` in years computed using the forward rate's day count basis. The shape of the input should be the same as that of `start_date` and `maturity_date`. Default value: `None`, in which case the daycount fraction is computed using `ACTUAL_365` convention. Returns: A real tensor of same shape as the inputs containing the simply compounded forward rate. """ start_date = dates.convert_to_date_tensor(start_date) maturity_date = dates.convert_to_date_tensor(maturity_date) if daycount_fraction is None: daycount_fraction = dates.daycounts.actual_365_fixed( start_date=start_date, end_date=maturity_date, dtype=self._dtype) else: daycount_fraction = tf.convert_to_tensor(daycount_fraction, self._dtype) dfstart = self.get_discount_factor(start_date) dfmaturity = self.get_discount_factor(maturity_date) return (dfstart / dfmaturity - 1.) / daycount_fraction
def __init__(self, start_date, end_date, coupon_spec, dtype=None, name=None): """Initialize a batch of fixed cashflow streams. Args: start_date: A rank 1 `DateTensor` specifying the starting dates of the accrual of the first coupon of the cashflow stream. The shape of the input correspond to the numbercof streams being created. end_date: A rank 1 `DateTensor` specifying the end dates for accrual of the last coupon in each cashflow stream. The shape of the input should be the same as that of `start_date`. coupon_spec: A list of `FixedCouponSpecs` specifying the details of the coupon payment for the cashflow stream. The length of the list should be the same as the number of streams being created. Each coupon within the list must have the same daycount_convention and businessday_rule. dtype: `tf.Dtype`. If supplied the dtype for the real variables or ops either supplied to the FixedCashflowStream object or created by the object. Default value: None which maps to the default dtype inferred by TensorFlow. name: Python str. The name to give to the ops created by this class. Default value: `None` which maps to 'fixed_cashflow_stream'. """ self._name = name or 'fixed_cashflow_stream' with tf.name_scope(self._name): self._start_date = dates.convert_to_date_tensor(start_date) self._end_date = dates.convert_to_date_tensor(end_date) self._batch_size = self._start_date.shape[0] self._dtype = dtype self._setup(coupon_spec)
def price(self, valuation_date, market, model=None): """Returns the present value of the instrument on the valuation date. Args: valuation_date: A scalar `DateTensor` specifying the date on which valuation is being desired. market: A namedtuple of type `InterestRateMarket` which contains the necessary information for pricing the interest rate swap. model: Reserved for future use. Returns: A Rank 1 `Tensor` of real type containing the modeled price of each IRS contract based on the input market data. """ valuation_date = dates.convert_to_date_tensor(valuation_date) pay_cf = self._pay_leg.price(valuation_date, market, model) receive_cf = self._receive_leg.price(valuation_date, market, model) return receive_cf - pay_cf
def price(self, valuation_date, market, model=None, pricing_context=None, name=None): """Returns the present value of the Cap/Floor on the valuation date. Args: valuation_date: A scalar `DateTensor` specifying the date on which valuation is being desired. market: A namedtuple of type `InterestRateMarket` which contains the necessary information for pricing the Cap/Floor. model: An optional input of type `InterestRateModelType` to specify which model to use for pricing. Default value: `None` in which case `LOGNORMAL_RATE` model is used. pricing_context: An optional input to provide additional parameters (such as model parameters) relevant for pricing. name: Python str. The name to give to the ops created by this function. Default value: `None` which maps to `"price"`. Returns: A Rank 1 `Tensor` of real type containing the modeled price of each cap (or floor) based on the input market data. Raises: ValueError: If an unsupported model is supplied to the function. """ model = model or rc.InterestRateModelType.LOGNORMAL_RATE name = name or (self._name + '_price') with tf.name_scope(name): valuation_date = dates.convert_to_date_tensor(valuation_date) if model == rc.InterestRateModelType.LOGNORMAL_RATE: caplet_prices = self._price_lognormal_rate(valuation_date, market, pricing_context) else: raise ValueError(f'Unsupported model {model}.') return tf.math.segment_sum(caplet_prices, self._contract_index)
def __init__(self, contract_start_date, contract_end_date, daycount_convention=None, averaging_type=None, contract_unit=1., holiday_calendar=None, dtype=None, name=None): """Initialize the Overnight index futures object. Args: contract_start_date: A Rank 1 `DateTensor` specifying the start dates of the reference period (or delivery period) of each futures contract. The published overnight index during the reference period determines the final settlement price of the futures contract. contract_end_date: A Rank 1 `DateTensor` specifying the ending dates of the reference period (or delivery period) of each futures contract. daycount_convention: An optional scalar `DayCountConvention` corresponding to the day count convention for the underlying rate for each contract. Default value: None in which case each the day count convention equal to DayCountConvention.ACTUAL_360 is used. averaging_type: An optional `AverageType` corresponding to how the final settlement rate is computed from daily rates. Default value: None, in which case `AverageType.COMPOUNDING` is used. contract_unit: An optional scalar or Rank 1 `Tensor` of real dtype specifying the notional amount for the contract. If the notional is entered as a scalar, it is assumed that all of the contracts have a notional equal to the input value. Default value: 1.0 holiday_calendar: An instance of `dates.HolidayCalenday` to specify weekends and holidays. Default value: None in which case a holiday calendar would be created with Saturday and Sunday being the holidays. dtype: `tf.Dtype`. If supplied the dtype for the real variables or ops either supplied to the EurodollarFuture object or created by the EurodollarFuture object. Default value: None which maps to the default dtype inferred by TensorFlow. name: Python str. The name to give to the ops created by this class. Default value: `None` which maps to 'eurodollar_future'. """ self._name = name or 'overnight_rate_futures' with tf.compat.v2.name_scope(self._name): self._contract_unit = tf.convert_to_tensor(contract_unit, dtype=dtype) self._dtype = dtype if dtype else self._contract_unit.dtype self._start_date = dates.convert_to_date_tensor( contract_start_date) self._end_date = dates.convert_to_date_tensor(contract_end_date) self._batch_size = self._start_date.shape[0] if daycount_convention is None: daycount_convention = rc.DayCountConvention.ACTUAL_360 if averaging_type is None: averaging_type = rc.AverageType.COMPOUNDING if holiday_calendar is None: holiday_calendar = dates.HolidayCalendar2( weekend_mask=dates.WeekendMask.SATURDAY_SUNDAY) self._daycount_convention = daycount_convention self._averaging_type = averaging_type self._holiday_calendar = holiday_calendar self._rate_tenor = dates.periods.PeriodTensor( 1, dates.PeriodType.DAY) self._setup()
def __init__(self, start_date, maturity_date, reset_frequency, strike, daycount_convention=None, notional=None, is_cap=None, dtype=None, name=None): """Initializes a batch of Interest rate Caps (or Floors). Args: start_date: A scalar `InterestRateSwap` specifying the interest rate swaps underlying the swaptions. The batch size of the swaptions being created would be the same as the bacth size of the `swap`. For receiver swaptions the receive_leg of the underlying swaps should be maturity_date: A rank 1 `DateTensor` specifying the expiry dates for each swaption. The shape of the input should be the same as the batch size of the `swap` input. Default value: None in which case the option expity date is the same as the start date of each underlying swap. reset_frequency: A rank 1 `PeriodTensor` specifying the frequency of caplet resets and caplet payments. strike: A scalar `Tensor` of real dtype specifying the strike rate against which each caplet within the cap are exercised. The shape should be compatible to the shape of `start_date` daycount_convention: An optional `DayCountConvention` associated with the underlying rate for the cap. Daycount is assumed to be the same for all contracts in a given batch. Default value: None in which case the daycount convention will default to DayCountConvention.ACTUAL_360 for all contracts. notional: An optional `Tensor` of real dtype specifying the notional amount for the cap. Default value: None in which case the notional is set to 1. is_cap: An optional boolean `Tensor` of a shape compatible with `start_date`. Indicates whether to compute the price of a Cap (if True) or a Floor (if False). Default value: None, it is assumed that every element is a Cap. dtype: `tf.Dtype`. If supplied the dtype for the real variables or ops either supplied to the Swaption object or created by the Swaption object. Default value: None which maps to the default dtype inferred by TensorFlow. name: Python str. The name to give to the ops created by this class. Default value: `None` which maps to 'cap_and_floor'. """ self._name = name or 'cap_and_floor' with tf.name_scope(self._name): self._dtype = dtype self._start_date = dates.convert_to_date_tensor(start_date) self._maturity_date = dates.convert_to_date_tensor(maturity_date) if daycount_convention is None: daycount_convention = rc.DayCountConvention.ACTUAL_360 self._daycount_convention = daycount_convention self._strike = tf.convert_to_tensor(strike, dtype=self._dtype) self._reset_frequency = reset_frequency notional = notional or 1.0 self._notional = tf.convert_to_tensor(notional, dtype=self._dtype) self._batch_size = self._start_date.shape.as_list()[0] if is_cap is None: is_cap = True self._is_cap = tf.broadcast_to( tf.convert_to_tensor(is_cap, dtype=tf.bool), self._start_date.shape) self._setup_tensors()
def price(self, valuation_date, market, model=None, pricing_context=None, name=None): """Returns the present value of the stream on the valuation date. Args: valuation_date: A scalar `DateTensor` specifying the date on which valuation is being desired. market: A namedtuple of type `InterestRateMarket` which contains the necessary information for pricing the cashflow stream. model: An optional input of type `InterestRateModelType` to specify which model to use for pricing. Default value: `None` in which case `NORMAL_RATE` model is used. pricing_context: An optional input to provide additional parameters (such as model parameters) relevant for pricing. name: Python str. The name to give to the ops created by this function. Default value: `None` which maps to 'price'. Returns: A Rank 1 `Tensor` of real type containing the modeled price of each stream contract based on the input market data. """ name = name or (self._name + '_price') with tf.name_scope(name): valuation_date = dates.convert_to_date_tensor(valuation_date) discount_curve = market.discount_curve past_fixing = rc.get_rate_index(market, self._start_date, rc.RateIndexType.SWAP, dtype=self._dtype) past_fixing = tf.repeat( tf.convert_to_tensor(past_fixing, dtype=self._dtype), self._num_cashflows) discount_factors = discount_curve.get_discount_factor( self._payment_dates) cms_rates = self._swap.par_rate(valuation_date, market, model) cms_rates = tf.where(self._daycount_fractions > 0., cms_rates, tf.zeros_like(cms_rates)) # If coupon end date is before the valuation date, the payment is in the # past. If valuation date is between coupon start date and coupon end # date, then the rate has been fixed but not paid. Otherwise the rate is # not fixed and should be read from the curve. cms_rates = tf.where( self._coupon_end_dates < valuation_date, tf.constant(0., dtype=self._dtype), tf.where(self._coupon_start_dates < valuation_date, past_fixing, cms_rates)) cms_rates = self._adjust_convexity(valuation_date, market, model, pricing_context, cms_rates, discount_factors) coupon_rate = self._coupon_multiplier * (cms_rates + self._coupon_basis) cashflow_pvs = self._notional * (self._daycount_fractions * coupon_rate * discount_factors) return tf.math.segment_sum(cashflow_pvs, self._contract_index)
def __init__(self, settlement_date, fixing_date, fixed_rate, notional=1., daycount_basis=None, rate_term=None, maturity_date=None, dtype=None, name=None): """Initialize the batch of FRA contracts. Args: settlement_date: A rank 1 `DateTensor` specifying the dates on which cashflows are settled. The shape of the input correspond to the number of instruments being created. fixing_date: A rank 1 `DateTensor` specifying the dates on which forward rate will be fixed. The shape of the inout should be the same as that of `settlement_date`. fixed_rate: A rank 1 `Tensor` of real dtype specifying the fixed rate payment agreed at the initiation of the individual contracts. The shape should be the same as that of `settlement_date`. notional: A scalar or a rank 1 `Tensor` of real dtype specifying the notional amount for each contract. When the notional is specified as a scalar, it is assumed that all contracts have the same notional. If the notional is in the form of a `Tensor`, then the shape must be the same as `settlement_date`. Default value: 1.0 daycount_basis: An optional list of `DayCountBasis` to determine how cashflows are accrued for each contract. The length of the list must be the same as the number of FRAs being created. Default value: None in which case the daycount basis will default to DayCountBasis.ACTUAL_360 for all contracts. rate_term: An optional rank 1 `PeriodTensor` specifying the term (or the tenor) of the Libor rate that determines the floating cashflow. The shape of the input should be the same as `settlement_date`. Default value: `None` in which case the the forward rate is determined for the period [settlement_date, maturity_date]. maturity_date: An optional rank 1 `DateTensor` specifying the maturity of the underlying forward rate for each contract. This input is only used if the input `rate_term` is `None`. Default value: `None` dtype: `tf.Dtype`. If supplied the dtype for the real variables or ops either supplied to the FRA object or created by the FRA object. Default value: None which maps to the default dtype inferred by TensorFlow. name: Python str. The name to give to the ops created by this class. Default value: `None` which maps to 'forward_rate_agreement'. Raises: ValueError: If both `maturity_date` and `rate_term` are unspecified. """ self._name = name or 'forward_rate_agreement' if rate_term is None and maturity_date is None: raise ValueError( 'Error creating FRA. Either rate_term or maturity_date is required.' ) with tf.name_scope(self._name): self._dtype = dtype self._notional = tf.convert_to_tensor(notional, dtype=self._dtype) self._fixing_date = dates.convert_to_date_tensor(fixing_date) self._settlement_date = dates.convert_to_date_tensor( settlement_date) self._accrual_start_date = dates.convert_to_date_tensor( settlement_date) if rate_term is None: self._accrual_end_date = dates.convert_to_date_tensor( maturity_date) else: self._accrual_end_date = self._accrual_start_date + rate_term # TODO (b/150216422): Fix tf.repeat to work with python enums if daycount_basis is None: daycount_basis = np.repeat(rc.DayCountBasis.ACTUAL_360, settlement_date.shape) self._fixed_rate = tf.convert_to_tensor(fixed_rate, dtype=self._dtype, name='fixed_rate') self._daycount_basis = daycount_basis self._daycount_fraction = rc.get_daycount_fraction( self._accrual_start_date, self._accrual_end_date, self._daycount_basis, self._dtype)
def test_convert_to_date_tensor_tuples(self): inputs = [(2018, 5, 4), (2042, 11, 22), (1947, 8, 15)] date_tensor = dateslib.convert_to_date_tensor(inputs) y, m, d = zip(*inputs) self.assert_date_tensor_equals(date_tensor, y, m, d, None)
def get_discount(self, interpolation_dates): """Returns discount factors at `interpolation_dates`.""" idates = dates.convert_to_date_tensor(interpolation_dates) times = self._get_time(idates) return tf.math.exp(-self.get_rates(idates) * times)
def get_rates(self, interpolation_dates): """Returns interpolated rates at `interpolation_dates`.""" idates = dates.convert_to_date_tensor(interpolation_dates) times = self._get_time(idates) return self._interpolator(times, self._times, self._rates)
def annuity(self, valuation_date, market, model=None): """Returns the annuity of each swap on the vauation date.""" valuation_date = dates.convert_to_date_tensor(valuation_date) return self._annuity(valuation_date, market, model, True)
def __init__(self, expiry_date, contract_notional=1., daycount_basis=None, rate_term=None, maturity_date=None, dtype=None, name=None): """Initialize the Eurodollar futures object. Args: expiry_date: A Rank 1 `DateTensor` specifying the dates on which the futures contracts expire. contract_notional: An optional scalar or Rank 1 `Tensor` of real dtype specifying the unit (or size) for the contract. For example for eurodollar futures traded on CME, the contract notional is $2500. If `contract_notional` is entered as a scalar, it is assumed that the input is the same for all of the contracts. Default value: 1.0 daycount_basis: An optional scalar `DayCountBasis` corresponding to the day count basis for the underlying rate for each contract. Daycount is assumed to be the same for all contracts in a given batch. Default value: None in which case each the day count basis of DayCountBasis.ACTUAL_360 is used for each contract. rate_term: An optional Rank 1 `PeriodTensor` specifying the term (or tenor) of the rate that determines the settlement of each contract. Default value: `None` in which case the the rate is assumed to be for the period [expiry_date, maturity_date]. maturity_date: An optional Rank 1 `DateTensor` specifying the maturity of the underlying forward rate for each contract. This input should be specified if the input `rate_term` is `None`. If both `maturity_date` and `rate_term` are specified, an error is raised. Default value: `None` dtype: `tf.Dtype`. If supplied the dtype for the real variables or ops either supplied to the EurodollarFuture object or created by the EurodollarFuture object. Default value: None which maps to the default dtype inferred by TensorFlow. name: Python str. The name to give to the ops created by this class. Default value: `None` which maps to 'eurodollar_future'. Raises: ValueError: If both `maturity_date` and `rate_term` are unspecified or if both `maturity_date` and `rate_term` are specified. """ self._name = name or 'eurodollar_futures' if (rate_term is None) == (maturity_date is None): msg = ('Error creating the EurodollarFutures contract. ' 'Either rate_term or maturity_date is required.') raise ValueError(msg) if rate_term is not None and maturity_date is not None: msg = ('Error creating the EurodollarFutures contract.' ' Both rate_term or maturity_date are specified.') raise ValueError(msg) with tf.name_scope(self._name): self._dtype = dtype self._contract_notional = tf.convert_to_tensor(contract_notional, dtype=self._dtype) self._expiry_date = dates.convert_to_date_tensor(expiry_date) self._accrual_start_date = self._expiry_date if rate_term is None: self._accrual_end_date = dates.convert_to_date_tensor( maturity_date) else: # TODO (b/150291959): Add businessday and holiday conventions self._accrual_end_date = self._accrual_start_date + rate_term if daycount_basis is None: daycount_basis = rc.DayCountBasis.ACTUAL_360 daycount_basis = [daycount_basis] self._daycount_basis = daycount_basis self._daycount_fraction = rc.get_daycount_fraction( self._accrual_start_date, self._accrual_end_date, self._daycount_basis, self._dtype)
def __init__(self, maturity_dates, rates, valuation_date, compounding=None, interpolator=None, dtype=None, name=None): """Initializes the interest rate curve. Args: maturity_dates: A `DateTensor` containing the maturity dates on which the curve is specified. rates: A `Tensor` of real dtype specifying the rates (or yields) corresponding to the input maturities. The shape of this input should match the shape of `maturity_dates`. valuation_date: A scalar `DateTensor` specifying the valuation (or settlement) date for the curve. compounding: Optional scalar `Tensor` of dtype int32 specifying the componding frequency of the input rates. Use compounding=0 for continuously compounded rates. If compounding is different than 0, then rates are converted to continuously componded rates to perform interpolation. Default value: If omitted, the default value is 0. interpolator: Optional Python callable specifying the desired interpolation method. It should have the following interface: yi = interpolator(xi, x, y) `x`, `y`, 'xi', 'yi' are all `Tensors` of real dtype. `x` and `y` are the sample points and values (respectively) of the function to be interpolated. `xi` are the points at which the interpolation is desired and `yi` are the corresponding interpolated values returned by the function. Default value: None in which case linear interpolation is used. dtype: `tf.Dtype`. Optional input specifying the dtype of the `rates` input. name: Python str. The name to give to the ops created by this function. Default value: `None` which maps to 'rate_curve'. """ self._name = name or 'rate_curve' with tf.compat.v1.name_scope(self._name): self._dtype = dtype if interpolator is None: def default_interpolator(xi, x, y): return linear.interpolate(xi, x, y, dtype=dtype) interpolator = default_interpolator if compounding is None: compounding = 0 self._dates = dates.convert_to_date_tensor(maturity_dates) self._valuation_date = dates.convert_to_date_tensor( valuation_date) self._times = self._get_time(self._dates) self._rates = tf.convert_to_tensor(rates, dtype=self._dtype, name='curve_rates') if compounding > 0: self._rates = tf.where( self._times > 0., tf.math.log( (1. + self._rates / compounding)**(compounding * self._rates)) / self._times, self._rates) self._interpolator = interpolator
def __init__(self, settlement_date, fixing_date, fixed_rate, notional=1., daycount_basis=DayCountBasis.ACTUAL_360, rate_term=None, maturity_date=None, dtype=None, name=None): """Initialize the forward rate agreement object. Args: settlement_date: A scalar `DateTensor` specifying the date on which cashflows are settled. fixing_date: A scalar `DateTensor` specifying the date on which forward rate will be fixed. fixed_rate: A scalar `Tensor` of real dtype specifying the fixed rate payment agreed at the initiation of the contract. notional: An optional scalar of real dtype specifying the notional amount for the contract. Default value: 1.0 daycount_basis: An optional scalar `DayCountBasis` to determine how cashflows are accrued. Default value: DayCountBasis.ACTUAL_360. rate_term: An optional scalar `PeriodTensor` specifying the term (or tenor) of the Libor rate that determines the floating cashflow. Default value: `None` in which case the the forward rate is determined for the period [settlement_date, maturity_date]. maturity_date: An optional scalar `DateTensor` specifying the maturity of the underlying forward rate. This input is only used if the input `rate_term` is `None`. Default value: `None` dtype: `tf.Dtype`. If supplied the dtype for the real variables or ops either supplied to the FRA object or created by the FRA object. Default value: None which maps to the default dtype inferred by TensorFlow. name: Python str. The name to give to the ops created by this class. Default value: `None` which maps to 'forward_rate_agreement'. Raises: ValueError: If both `maturity_date` and `rate_term` are unspecified. """ self._name = name or 'forward_rate_agreement' with tf.compat.v1.name_scope(self._name, values=[ notional, settlement_date, fixing_date, maturity_date, daycount_basis, fixed_rate, rate_term ]): self._dtype = dtype self._notional = tf.convert_to_tensor(notional, dtype=self._dtype) self._fixing_date = dates.convert_to_date_tensor(fixing_date) self._settlement_date = dates.convert_to_date_tensor( settlement_date) self._accrual_start_date = dates.convert_to_date_tensor( settlement_date) if rate_term is None: self._accrual_end_date = dates.convert_to_date_tensor( maturity_date) else: self._accrual_end_date = self._accrual_start_date + rate_term self._fixed_rate = tf.convert_to_tensor(fixed_rate, dtype=self._dtype, name='fixed_rate') self._daycount_basis = daycount_basis self._daycount_fraction = get_daycount_fraction( self._accrual_start_date, self._accrual_end_date, self._daycount_basis, self._dtype)