Пример #1
0
    def tenor(self, date, *args, **kwargs):
        """
        Parameters
        ----------
        date: datetime-like

        Returns
        -------
        QuantLib.Period, None
            Period representing the time to maturity or expiry of the instrument. Returns None if there is no tenor.
        """
        try:
            return ql.PeriodParser.parse(self.get_attribute(TENOR_PERIOD))
        except:
            try:
                try:
                    tenor = float(self.get_attribute(TENOR_PERIOD))
                    if tenor < 1:
                        return ql.Period(int(self.get_attribute(TENOR_PERIOD)*252), ql.Days)
                        # TODO: Amend these approx. tenors
                    return ql.Period(int(tenor), ql.Years)
                except:
                    date = to_ql_date(date)
                    maturity = to_ql_date(to_datetime(self.get_attribute(MATURITY_DATE)))
                    if date >= maturity:
                        return None
                    calendar = ql.UnitedStates(ql.UnitedStates.NYSE)
                    # TODO: This will have to be parametrized afterwards.
                    return ql.Period(calendar.businessDaysBetween(date, maturity), ql.Days)
            except:
                # Impossible to find a tenor or maturity for this TimeSeries.
                return None
Пример #2
0
    def _discount_factor_to_date(self, date, to_date, zero_rate, compounding,
                                 frequency):
        """ Calculate discount factor to a given date, at a given date, given an interest rate.

        Parameters
        ----------
        date: QuantLib.Date, (c-vectorized)
            Reference date of the interest rate.
        to_date: QuantLib.Date, (c-vectorized)
            Maturity of the discount rate.
        zero_rate: scalar, (c-vectorized)
            Interest rate at `date`, with maturity `to_date`.
        compounding: QuantLib.Compounding
            Compounding convention of the interest rate.
        frequency: QuantLib.Frequency
            Compounding frequency of the interest rate.

        Returns
        -------
        scalar
            The discount rate to `to_date`, equivalent to the given interest rate.
        """
        date = to_ql_date(date)
        to_date = to_ql_date(to_date)
        return ql.InterestRate(zero_rate, self.day_counter, compounding,
                               frequency).discountFactor(
                                   date, to_date, date, to_date)
Пример #3
0
    def forward_rate_date_to_date(self,
                                  date,
                                  to_date1,
                                  to_date2,
                                  compounding,
                                  frequency,
                                  extrapolate=True):
        """
        Parameters
        ----------
        date: QuantLib.Date, (c-vectorized)
            Date of the yield curve.
        to_date1: QuantLib.Date, (c-vectorized)
            First maturity for the fra.
        to_date2: QuantLib.Date, (c-vectorized)
            Second maturity for the fra.
        compounding: QuantLib.Compounding
            Compounding convention for the rate.
        frequency: QuantLib.Frequency
            Frequency convention for the rate.
        extrapolate: bool, optional
            Whether to enable extrapolation.

        Returns
        -------
        scalar
            Forward rate between `to_date1` and `to_date2`, implied by the yield curve at `date`.
        """
        to_date1 = to_ql_date(to_date1)
        to_date2 = to_ql_date(to_date2)
        return self.yield_curve(date).forwardRate(to_date1, to_date2,
                                                  self.day_counter,
                                                  compounding, frequency,
                                                  extrapolate).rate()
Пример #4
0
    def credit_default_swap(self,
                            date,
                            notional,
                            probability_handle,
                            base_yield_curve_handle,
                            upfront_price=1,
                            last_available=True,
                            *args,
                            **kwargs):
        """
        :param date: pd.Datetime or QuantLib.Date
            Reference Date
        :param notional: float
            Size of the contract
        :param probability_handle: QuantLib.DefaultProbabilityTermStructureHandle
            the curve used for the calculation
        :param base_yield_curve_handle: QuantLib.YieldTermStructureHandle
            the curve used for the calculation
        :param upfront_price: float
            The par value of the upfront payment.
        :param last_available: bool, optional
            Whether to use last available quotes if missing data.
        :return:
        QuantLib CDS Instrument
            The CDS Instrument for calculation purposes.
        """

        recovery_rate = self.recovery_rate
        if 'recovery_rate' in kwargs.keys():
            recovery_rate = kwargs['recovery_rate']

        # maybe the user passed a quote multiplied by 100, if so we divide by 100 to be correctly used by the CDS.
        if upfront_price > 1:
            upfront_price = upfront_price / 100
        upfront = 1 - upfront_price

        rate = self.quotes.get_values(index=date,
                                      last_available=last_available,
                                      fill_value=np.nan)
        maturity = to_ql_date(date) + self._tenor
        schedule = ql.Schedule(to_ql_date(date), maturity,
                               self.coupon_frequency, self.calendar,
                               self.business_convention, ql.Unadjusted,
                               self.date_generation, False)

        cds = ql.CreditDefaultSwap(ql.Protection.Buyer, notional, upfront,
                                   rate, schedule, self.business_convention,
                                   self.day_counter)

        engine = ql.MidPointCdsEngine(probability_handle, recovery_rate,
                                      base_yield_curve_handle)
        cds.setPricingEngine(engine)

        return cds
Пример #5
0
    def update_spread_from_timeseries(self, date, last_available=True):

        date = to_ql_date(date)
        self.spreads[date] = dict()
        for ts in self.ts_collection:
            spread = ts.get_values(date, last_available=last_available)
            try:
                spread_date_or_tenor = date + ql.Period(
                    ts.ts_attributes[TENOR_PERIOD])
            except AttributeError:
                spread_date_or_tenor = to_ql_date(
                    ts.ts_attributes[MATURITY_DATE])

            self.spreads[date][spread_date_or_tenor] = to_ql_quote_handle(
                spread)
Пример #6
0
    def __init__(self, reference_date, spot, helpers, counter_rate_day_counter,
                 counter_rate_compounding, counter_rate_frequency,
                 base_rate_day_counter, base_rate_compounding,
                 base_rate_frequency):
        """ Currency curve class analogous to QuantLib yield term structures.

        Parameters
        ----------
        reference_date: QuantLib.Date
            The reference date for the curve.
        spot: scalar
            Value of the spot exchange rate at `reference_date`.
        helpers: list of :py:pbj:CurrencyFutureHelper
            Currency future helpers for construction of the curve.
        counter_rate_day_counter: QuantLib.DayCounter
            Day counter for the counter currency interest rates.
        counter_rate_compounding: QuantLib.Compounding
            Compounding convention for the counter currency interest rates.
        counter_rate_frequency: QuantLib.Frequency
            Compounding frequency for the counter currency interest rates.
        counter_rate_day_counter: QuantLib.DayCounter
            Day counter for the counter currency interest rates.
        counter_rate_compounding: QuantLib.Compounding
            Compounding convention for the counter currency interest rates.
        counter_rate_frequency: QuantLib.Frequency
            Compounding frequency for the counter currency interest rates.
        """
        # TODO: Propose a similar class in QuantLib.
        self.reference_date = to_ql_date(reference_date)
        self.spot = spot
        self.helpers = sorted(helpers, key=attrgetter('maturity'))
        self.maturity_dates = [self.reference_date] + [
            helper.maturity for helper in self.helpers
        ]
        self.nodes = {helper.maturity: helper.quote for helper in self.helpers}
        self.nodes[reference_date] = spot
        self.max_date = to_ql_date(self.maturity_dates[-1])
        self._day_counter = ql.Actual365Fixed()
        self.counter_rate_day_counter = counter_rate_day_counter
        self.counter_rate_compounding = counter_rate_compounding
        self.counter_rate_frequency = counter_rate_frequency
        self.base_rate_day_counter = base_rate_day_counter
        self.base_rate_compounding = base_rate_compounding
        self.base_rate_frequency = base_rate_frequency

        # These will be initialized when necessary.
        self._base_rate_curve = None
        self._counter_rate_curve = None
Пример #7
0
    def forward_rate_date_to_time(self,
                                  date,
                                  to_date,
                                  to_time,
                                  compounding,
                                  frequency,
                                  extrapolate=True):
        """
        Parameters
        ----------
        date: QuantLib.Date, (c-vectorized)
            Date of the yield curve.
        to_date: QuantLib.Date, (c-vectorized)
            First maturity for the fra.
        to_time: scalar, (c-vectorized)
            Time in years after `to_date` for the fra.
        compounding: QuantLib.Compounding
            Compounding convention for the rate.
        frequency: QuantLib.Frequency
            Frequency convention for the rate.
        extrapolate: bool, optional
            Whether to enable extrapolation.

        Returns
        -------
        scalar
            Forward rate between `to_date` and `to_time`, implied by the yield curve at `date`.
        """
        to_date = to_ql_date(to_date)
        to_date2 = self.calendar.advance(to_date, to_time)
        return self.yield_curve(date).forwardRate(to_date, to_date2,
                                                  self.day_counter,
                                                  compounding, frequency,
                                                  extrapolate).rate()
Пример #8
0
    def rate_helper(self, date, last_available=True, *args, **kwargs):
        """ Rate helper object for yield curve building.

        Parameters
        ----------
        date: QuantLib.Date
            Reference date.
        last_available: bool
            Whether to use last available information if missing data.

        Returns
        -------
        QuantLib.RateHelper
            Rate helper object for yield curve construction.
        """
        # Returns None if impossible to obtain a rate helper from this time series
        if self.is_expired(date):
            return None
        rate = self.get_values(index=date,
                               last_available=last_available,
                               fill_value=np.nan)
        if np.isnan(rate):
            return None
        date = to_ql_date(date)
        try:
            tenor = self.tenor(date)
        except ValueError:
            # Return none if the deposit rate can't retrieve a tenor (i.e. is expired).
            return None

        return ql.OISRateHelper(self.settlement_days, tenor,
                                to_ql_quote_handle(rate), self.overnight_index,
                                ql.YieldTermStructureHandle(), False, 0,
                                self.business_convention)
Пример #9
0
    def exchange_rate_to_date(self, date):
        """ Exchange rate to a given date, using linear interpolation between nodes.

        Parameters
        ----------
        date: QuantLib.Date

        Returns
        -------
        scalar
            The exchange rate implied by the currency curve, using linear interpolation between nodes.
        """
        date = to_ql_date(date)
        if date > self.max_date:
            raise ValueError(
                "The requested date ({0}) is after the curve's max date ({1})".
                format(date, self.max_date))
        try:
            # If the date is in the nodes, use it.
            return self.nodes[date]
        except KeyError:
            # Use linear interpolation to obtain the result.
            lower_date_bound = find_le(self.maturity_dates, date)
            upper_date_bound = find_gt(self.maturity_dates, date)
            lower_bound = self.nodes[lower_date_bound]
            upper_bound = self.nodes[upper_date_bound]
            lower_interval = self._day_counter.yearFraction(
                lower_date_bound, date)
            interval = self._day_counter.yearFraction(lower_date_bound,
                                                      upper_date_bound)
            return lower_bound + lower_interval * (upper_bound -
                                                   lower_bound) / interval
Пример #10
0
    def base_rate_to_date(self, date, to_date, counter_rate):
        """ Get interest rate of the base currency at a given date, to a given date.

        Parameters
        ----------
        date: QuantLib.Date
            Reference date for the currency curve.
        to_date: QuantLib.Date
            Maturity date of the interest rate.
        counter_rate: scalar
            Interest rate of the counter currency to `to_date`.

        Returns
        -------
        scalar
            Interest rate of the base currency to `to_date`.
        """
        to_date = to_ql_date(to_date)
        currency_curve = self.currency_curve(date)
        helper = currency_curve.helpers[0]
        exchange_rate = currency_curve.exchange_rate_to_date(date)
        return helper.base_rate(quote=exchange_rate,
                                spot=currency_curve.spot,
                                counter_rate=counter_rate,
                                maturity=to_date)
Пример #11
0
    def upfront_npv(self,
                    date,
                    notional,
                    probability_handle,
                    base_yield_curve_handle,
                    upfront_price=1,
                    last_available=True,
                    *args,
                    **kwargs):
        """
        :param date: pd.Datetime or QuantLib.Date
            Reference Date
        :param notional: float
            Size of the contract
        :param probability_handle: QuantLib.DefaultProbabilityTermStructureHandle
            the curve used for the calculation
        :param base_yield_curve_handle: QuantLib.YieldTermStructureHandle
            the curve used for the calculation
        :param upfront_price: float
            The par value of the upfront payment.
        :param last_available: bool, optional
            Whether to use last available quotes if missing data.
        :return:
        QuantLib CDS Instrument
            CDS Net Present Value of the coupon Leg.
        """

        ql.Settings.instance().evaluationDate = to_ql_date(date)
        cds = self.credit_default_swap(date, notional, probability_handle,
                                       base_yield_curve_handle, upfront_price,
                                       last_available, *args, **kwargs)
        return cds.upfrontNPV()
Пример #12
0
    def zero_rate_to_date(self,
                          date,
                          to_date,
                          compounding,
                          frequency,
                          extrapolate=True):
        """
        Parameters
        ----------
        date: QuantLib.Date, (c-vectorized)
            Date of the yield curve.
        to_date: QuantLib.Date, (c-vectorized)
            Maturity of the rate.
        compounding: QuantLib.Compounding
            Compounding convention for the rate.
        frequency: QuantLib.Frequency
            Frequency convention for the rate.
        extrapolate: bool, optional
            Whether to enable extrapolation.

        Returns
        -------
        scalar
            Zero rate for `to_date`, implied by the yield curve at `date`.
        """
        to_date = to_ql_date(to_date)
        return self.yield_curve(date).zeroRate(to_date, self.day_counter,
                                               compounding, frequency,
                                               extrapolate).rate()
Пример #13
0
    def __init__(self,
                 ts_collection,
                 base_yield_curve,
                 calendar,
                 day_counter,
                 keep_only_on_the_run_month=False,
                 ignore_errors=False,
                 **other_rate_helper_args):
        """Time series of QuantLib YieldTermStructures objects.

        The QuantLib YieldTermStructure objects are stored in the dict self.yield_curves and are 'lazy' created and
        stored when requested.

        Parameters
        ----------
        ts_collection: :py:obj:`TimeSeriesCollection`
            Collection of instruments for building the yield curves.
        base_yield_curve: :py:obj: 'YieldCurveTimeSeries'
            Base yield curve used for discounting the cash flows.
        calendar: QuantLib.Calendar
            Calendar for the yield curves.
        day_counter: QuantLib.DayCounter
            Day counter for the yield curves.
        keep_only_on_the_run_month: bool, optional
            Whether to use only one instrument per month for the yield curves. Defaults to False.
        ignore_errors: bool, optional
            Use last available yield curve if building a yield curve fails at a given date. Defaults to False.
        **other_rate_helper_args: key=value pairs, optional
            Additional arguments to pass to ``rate_helper`` methods of the instruments in `ts_collection`.
        """
        self.ts_collection = ts_collection
        self.base_yield_curve = base_yield_curve
        self.calendar = calendar
        self.day_counter = day_counter
        self.keep_only_on_the_run_month = keep_only_on_the_run_month
        self.hazard_curves = dict()
        self.ignore_errors = ignore_errors
        self.other_rate_helper_args = other_rate_helper_args

        self.issue_dates = dict()
        # TODO: Remove issue_dates inspection from this class and add an issue_date attribute to all instrument.
        # classes.
        # Saving the issue dates.
        for ts in ts_collection:
            issue_date = None
            for issue_attribute in ISSUE_DATE_ATTRIBUTES:
                try:
                    issue_date = to_ql_date(ts.get_attribute(issue_attribute))
                    break
                except AttributeError:
                    continue
            if issue_date is None:
                # If impossible to decide the issue_date, it remains equal to "None" as we initialized above.
                # Then set it to 2000-01-01.
                issue_date = DEFAULT_ISSUE_DATE
            self.issue_dates[ts.ts_name] = issue_date
Пример #14
0
    def _get_helpers(self, date):
        helpers = dict()
        ql_date = to_ql_date(date)

        for ts in self.ts_collection:
            ts_name = ts.ts_name
            issue_date = self.issue_dates[ts_name]
            yield_curve_handle = self.base_yield_curve_handle(date)
            helper = ts.cds_rate_helper(
                date=date,
                base_yield_curve_handle=yield_curve_handle,
                **self.other_rate_helper_args)
            if helper is not None:
                tenor = ts.tenor(date)
                maturity_date = self.calendar.advance(ql_date, tenor)
                '''
                TODO: Wrap this ``ExtRateHelper`` inside a (properly named) class or namedtuple and always
                return these objects from the instrument classes. This prevents this method from calling ``ts.tenor``
                and recalculating the ``maturity_date``, because these were already calculated inside each instrument's
                ``rate_helper`` method.
                '''
                helper = ExtRateHelper(ts_name=ts_name,
                                       issue_date=issue_date,
                                       tenor=tenor,
                                       maturity_date=maturity_date,
                                       helper=helper)
                # Remove Helpers with the same maturity date (or tenor), keeping the last issued one - This is to avoid
                # error in QuantLib when trying to instantiate a yield curve with two helpers with same maturity
                # date or tenor.
                existing_helper = helpers.get(maturity_date, None)
                if existing_helper is None:
                    helpers[maturity_date] = helper
                else:
                    helpers[maturity_date] = max((helper, existing_helper),
                                                 key=attrgetter('issue_date'))

        if self.keep_only_on_the_run_month:
            # If self.keep_only_on_the_run_month is True, then filter the returned helpers so that for each month there
            # is not more than one helper. This may be used to avoid distortions in curves being generated by a large
            # amount of TimeSeries.
            month_end_helpers = dict()
            for maturity_date, helper in helpers.items():
                month_year = self._date_to_month_year(maturity_date)
                existing_helper = month_end_helpers.get(month_year, None)
                if existing_helper is None:
                    month_end_helpers[month_year] = helper
                else:
                    month_end_helpers[month_year] = max(
                        (helper, existing_helper),
                        key=attrgetter('issue_date'))
            helpers = {
                ndhelper.maturity_date: ndhelper
                for ndhelper in month_end_helpers.values()
            }

        return helpers
Пример #15
0
    def spread_handle(self, date, last_available=True):

        date = to_ql_date(date)
        try:
            return self.spreads[date]

        except KeyError:
            self.update_spread_from_timeseries(date=date,
                                               last_available=last_available)
            return self.spreads[date]
Пример #16
0
    def default_probability(self, date, period):
        """
        The survival probability given a date and period

        :param date: Date of the yield curve.
        :param period: The tenor for the maturity.
        :return: The % chance of default given the date and tenor.
        """

        ql_date = to_ql_date(date)
        ql_period = ql.Period(period)

        return self.hazard_curves[date].defaultProbability(ql_date + ql_period)
Пример #17
0
    def net_present_value(self, date, *args, **kwargs):
        """
        Parameters
        ----------
        date: date-like

        Returns
        -------
        The asset net present value
        """
        date = to_ql_date(date)
        ql.Settings.instance().evaluationDate = date
        instrument = self.security(date=date, *args, **kwargs)
        return instrument.NPV()
Пример #18
0
 def _calculate_cc(self, date, spot_price, currency_curve, DI_curve):
     maturity_date = self._maturity_on_the_run(date)
     future_price = currency_curve.exchange_rate_to_date(
         date, maturity_date)
     DI = DI_curve.zero_rate_to_date(date, maturity_date, ql.Compounded,
                                     ql.Annual)
     DI_rate = ql.InterestRate(DI, ql.Business252(), ql.Compounded,
                               ql.Annual)
     date = to_ql_date(date)
     compound = spot_price * DI_rate.compoundFactor(
         date, maturity_date) / future_price
     rate = ql.InterestRate.impliedRate(compound, ql.Actual360(), ql.Simple,
                                        ql.Annual, date, maturity_date)
     return rate.rate()
Пример #19
0
    def implied_term_structure_handle(self, date, future_date):
        """ A relinkable handle for a yield curve at a given date.

        Parameters
        ----------
        date: Date of the yield curve.
        future_date: Date of the Implied Yield Curve
        Returns
        -------
        QuantLib.RelinkableYieldTermStructureHandle
            A relinkable handle to the yield term structure object.
        """
        future_date = to_ql_date(future_date)
        return ql.ImpliedTermStructure(self.yield_curve_handle(date),
                                       future_date)
Пример #20
0
    def __init__(self, timeseries):
        super().__init__(timeseries=timeseries)
        # TODO: Add support for puttable bonds.
        # TODO: Here we assume that the call prices are always clean prices. Fix this!
        # TODO: Implement an option to reduce (some kind of 'telescopic') call dates.
        # if there are too much. This is useful in case we are treating a callable perpetual bond, for example.
        called_date = self.ts_attributes[CALLED_DATE]
        if called_date:
            self.expire_date = to_ql_date(to_datetime(called_date))
        self.callability_schedule = ql.CallabilitySchedule()
        for call_date, call_price in self.call_schedule.ts_values.iteritems():
            # The original bond (with maturity at self.maturity will be added to the components after its
            # instantiation below.
            call_date = to_ql_date(to_datetime(call_date))
            callability_price = ql.CallabilityPrice(call_price,
                                                    ql.CallabilityPrice.Clean)
            self.callability_schedule.append(
                ql.Callability(callability_price, ql.Callability.Call,
                               call_date))
            self.bond_components[call_date] = create_call_component(
                call_date, call_price, self.schedule, self.calendar,
                self.business_convention, self.coupon_frequency,
                self.date_generation, self.month_end, self.settlement_days,
                self.face_amount, self.coupons, self.day_counter,
                self.issue_date)

        self.bond = ql.CallableFixedRateBond(self.settlement_days,
                                             self.face_amount, self.schedule,
                                             self.coupons, self.day_counter,
                                             self.business_convention,
                                             self.redemption, self.issue_date,
                                             self.callability_schedule)
        self.bond_components[
            self.
            maturity_date] = self.bond  # Add the original bond to bond_components.
        self._bond_components_backup = self.bond_components.copy()
Пример #21
0
    def discount_to_date(self, date, to_date):
        """
        Parameters
        ----------
        date: QuantLib.Date, (c-vectorized)
            The date of the yield curve.
        to_date: QuantLib.Date, (c-vectorized)
            The maturity for the discount rate.

        Returns
        -------
        scalar
            The discount rate for `to_date` implied by the yield curve at `date`.
        """
        to_date = to_ql_date(to_date)
        return self.yield_curve(date).discount(to_date)
Пример #22
0
def next_cc_maturity(date):
    """Next DDI future maturity (DDI future contracts dealt by BMF in Brazil).

    Parameters
    ----------
    date: date-like

    Returns
    -------
    QuantLib.Date

    """
    date = to_ql_date(date)
    calendar = ql.Brazil()
    return calendar.advance(
        calendar.endOfMonth(calendar.advance(date, 2, ql.Days)), 1, ql.Days)
Пример #23
0
    def exchange_rate_to_date(self, date, to_date):
        """ Get exchange rate implied by the curve at a given date, to a given date, with linear interpolation.

        Parameters
        ----------
        date: QuantLib.Date
            Reference date of the currency curve.
        to_date: QuantLib.Date
            Maturity date for the future exchange rate.

        Returns
        -------
        scalar
            Exchange rate to `to_date`, at `date`.
        """
        to_date = to_ql_date(to_date)
        return self.currency_curve(date).exchange_rate_to_date(to_date)
Пример #24
0
def ts_to_dict(*args):
    """ Produce a date-indexed dictionary of tuples from the values of multiple time series.

    Parameters
    ----------
    args: time series names (each time series represents a parameter).

    Returns
    -------
    dict
        Dictionary of parameter tuples, indexed by dates.
    """
    params_df = pd.concat([ts for ts in args], axis=1)
    params = dict()
    for data in params_df.itertuples():
        params[to_ql_date(data[0])] = tuple(data[i]
                                            for i in range(1, len(data)))
    return params
Пример #25
0
    def maturity(self, date, *args, **kwargs):
        """Maturity of the "next cupom cambial".

        Parameters
        ----------
        date: QuantLib.Date
            Reference date.

        Returns
        -------
        QuantLib.Date
            Maturity date.
        """
        date = to_ql_date(date)
        calendar = self.calendar
        return calendar.advance(
            calendar.endOfMonth(calendar.advance(date, 2, ql.Days)), 1,
            ql.Days)
Пример #26
0
    def update_curves(self, dates):
        """ Update ``self.yield_curves`` with the yield curves of each date in `dates`.

        Parameters
        ----------
        dates: list of QuantLib.Dates
        """
        dates = to_list(dates)

        for date in dates:
            ql_date = to_ql_date(date)
            ql.Settings.instance().evaluationDate = ql_date

            helpers_dict = self._get_helpers(date)

            # Instantiate the curve
            helpers = [ndhelper.helper for ndhelper in helpers_dict.values()]
            # Just bootstraping the nodes
            yield_curve = ql.PiecewiseLinearZero(ql_date, helpers,
                                                 self.day_counter)

            # Get dates and discounts
            node_dates = yield_curve.dates()
            # node_discounts = [yield_curve.discount(date) for date in node_dates]
            node_rates = [
                yield_curve.zeroRate(date, self.day_counter,
                                     ql.Continuous).rate()
                for date in node_dates
            ]

            # Freezing the curve so that nothing is bothered by changing the singleton (global variable) evaluationDate.
            # yield_curve = ql.DiscountCurve(node_dates, node_discounts, yield_curve.dayCounter())
            yield_curve = ql.MonotonicCubicZeroCurve(
                node_dates,
                node_rates,
                self.day_counter,
                self.calendar,
                ql.MonotonicCubic(),
                ql.Continuous,
            )
            yield_curve.enableExtrapolation()

            self.yield_curves[date] = yield_curve
Пример #27
0
def calibrate_swaption_model(date, model_class, term_structure_ts,
                             swaption_vol_ts_collection):
    """ Calibrate a Hull-White QuantLib model.

    Parameters
    ----------
    date: QuantLib.Date
        Calibration date.
    model_class: QuantLib.Model
        Model for calibration.
    term_structure_ts: :py:obj:`YieldCurveTimeSeries`
        Yield curve time series of the curve.
    swaption_vol_ts_collection: :py:obj:`TimeSeriesCollection`
        Collection of swaption volatility (Black, log-normal) quotes.

    Returns
    -------
    QuantLib.Model
        Calibrated model.
    """
    # This has only been tested for model_class = HullWhite
    date = to_ql_date(date)
    print("Calibrating {0} 1F short rate model for date = {1}".format(
        model_class, date))
    yield_curve = term_structure_ts.yield_curve(date=date)
    term_structure = ql.YieldTermStructureHandle(yield_curve)

    ql.Settings.instance().evaluationDate = date
    model, engine = ql_swaption_engine(model_class=model_class,
                                       term_structure=term_structure)

    swaption_helpers = list()
    swaption_vol = generate_instruments(swaption_vol_ts_collection)
    for swaption in swaption_vol:
        swaption.set_yield_curve(yield_curve=yield_curve)
        helper = swaption.rate_helper(date=date)
        helper.setPricingEngine(engine)
        swaption_helpers.append(helper)

    optimization_method = ql.LevenbergMarquardt(1.0e-8, 1.0e-8, 1.0e-8)
    end_criteria = ql.EndCriteria(10000, 100, 1e-6, 1e-8, 1e-8)
    model.calibrate(swaption_helpers, optimization_method, end_criteria)
    return model
Пример #28
0
    def tenor(self, date, **kwargs):
        """Tenor of the "next cupom cambial".

        Parameters
        ----------
        date: QuantLib.Date
            Reference date.

        Returns
        -------
        QuantLib.Period
            The tenor (period) to maturity.


        """
        date = to_ql_date(date)
        maturity = self._maturity_on_the_run(date)
        days = self.calendar.businessDaysBetween(date, maturity)
        return ql.Period(days, ql.Days)
Пример #29
0
    def spreaded_zero_rate_to_date(self,
                                   date,
                                   to_date,
                                   compounding,
                                   frequency,
                                   spread_handle,
                                   extrapolate=True):
        """
        Parameters
        ----------
        date: QuantLib.Date, (c-vectorized)
            Date of the yield curve.
        to_date: QuantLib.Date, (c-vectorized)
            Maturity of the rate.
        compounding: QuantLib.Compounding
            Compounding convention for the rate.
        frequency: QuantLib.Frequency
            Frequency convention for the rate.
        spread_handle: :py:obj:'SpreadHandle'
            The spread to be added to the yield curve rates.
        extrapolate: bool, optional
            Whether to enable extrapolation.

        Returns
        -------
        scalar
            Zero rate for `to_date`, implied by the spreaded yield curve at `date`.
        """
        to_date = to_ql_date(to_date)
        spread_curve = self.spreaded_interpolated_curve(
            date=date,
            spread_handle=spread_handle,
            compounding=compounding,
            frequency=frequency)

        return spread_curve.zeroRate(to_date, self.day_counter, compounding,
                                     frequency, extrapolate).rate()
Пример #30
0
    def update_curves(self, dates):
        """ Update ``self.yield_curves`` with the yield curves of each date in `dates`.

        Parameters
        ----------
        dates: list of QuantLib.Dates
        """
        dates = to_list(dates)

        for date in dates:
            ql_date = to_ql_date(date)
            ql.Settings.instance().evaluationDate = ql_date

            helpers_dict = self._get_helpers(date)

            # Instantiate the curve
            helpers = [ndhelper.helper for ndhelper in helpers_dict.values()]
            # Just bootstrapping the nodes
            hazard_curve = ql.PiecewiseFlatHazardRate(ql_date, helpers,
                                                      self.day_counter)

            hazard_curve.enableExtrapolation()

            self.hazard_curves[date] = hazard_curve