예제 #1
0
    def yield_curve_update(self, date, calendar, day_counter, maturity, risk_free=None, compounding=ql.Continuous,
                           frequency=ql.Once):
        """

        :param date: date-like
            The date.
        :param calendar: QuantLib.Calendar
            The option calendar used to evaluate the model
        :param day_counter: QuantLib.DayCounter
            The option day count used to evaluate the model
        :param maturity: date-like
            The option maturity.
        :param risk_free: float, optional
            An override of the zero rate in case you don't wan't to use the yield curve implied one.
        :param compounding: QuantLib.Compounding, default=Continuous
            The compounding used to interpolate the curve.
        :param frequency: QuantLib.Frequency, default = Once
            The frequency of the quoted yield.
        """

        ql_date = to_ql_date(date)
        mat_date = to_ql_date(maturity)
        if risk_free is not None:
            zero_rate = risk_free
        else:
            zero_rate = self.yield_curve.zero_rate_to_date(date=ql_date, to_date=mat_date, compounding=compounding,
                                                           frequency=frequency)
        yield_curve = ql.FlatForward(0, calendar, to_ql_quote_handle(zero_rate), day_counter, compounding)
        self.risk_free_handle.linkTo(yield_curve)
예제 #2
0
    def new_f(self, **kwargs):

        # Dates
        if kwargs.get("bypass_option_default_values", False):
            return f(self, **kwargs)
        try:
            kwargs['date'] = to_ql_date(kwargs['date'])
        except TypeError:
            kwargs['date'] = to_ql_date(kwargs['date'][0])
        if kwargs.get('base_date', None) is None:
            kwargs['base_date'] = kwargs['date']
        try:
            kwargs['base_date'] = to_ql_date(kwargs['base_date'])
        except TypeError:
            kwargs['base_date'] = to_ql_date(kwargs['base_date'][0])
        # Option Setup Arguments
        if kwargs.get('base_equity_process', None) is None:
            kwargs['base_equity_process'] = self.base_equity_process
        else:
            base_equity_process = kwargs['base_equity_process']
            try:
                kwargs['base_equity_process'] = base_equity_process(calendar=self.calendar,
                                                                    day_counter=self.day_counter)
            except TypeError:
                base_equity_process.calendar = self.calendar
                base_equity_process.day_counter = self.day_counter
                kwargs['base_equity_process'] = base_equity_process

        if kwargs.get('risk_free_yield_curve_ts', None) is None:
            kwargs['risk_free_yield_curve_ts'] = self.risk_free_yield_curve_ts
        if kwargs.get('underlying_instrument', None) is None:
            kwargs['underlying_instrument'] = self.underlying_instrument
        else:
            self.set_underlying_instrument(underlying_instrument=kwargs['underlying_instrument'])
            kwargs['underlying_instrument'] = self.underlying_instrument
        if kwargs.get('engine_name', None) is None:
            kwargs['engine_name'] = self.engine_name
        # Date setup
        search_date = kwargs['base_date'] if kwargs['date'] > kwargs['base_date'] else kwargs['date']
        if kwargs.get('last_available', None) is None:
            kwargs['last_available'] = True
        last = kwargs['last_available']
        # Underlying Timeseries Values
        underlying = kwargs['underlying_instrument']
        if kwargs.get('spot_price', None) is None:
            spot_prices = getattr(underlying, UNADJUSTED_PRICE)
            kwargs['spot_price'] = spot_prices(index=search_date, last_available=last)
        if kwargs.get('dividend_yield', None) is None:
            dividend_yield = getattr(underlying, DIVIDEND_YIELD)
            kwargs['dividend_yield'] = dividend_yield(index=search_date, last_available=last)
        if kwargs.get('dividend_tax', None) is None:
            kwargs['dividend_tax'] = 0
        # Option Timeseries Values
        if kwargs.get('option_price', None) is None:
            mid_prices = getattr(self.timeseries, MID_PRICE)
            kwargs['option_price'] = mid_prices(index=search_date, last_available=last)
        if kwargs.get('quote', None) is None:
            kwargs['quote'] = kwargs['option_price']
        kwargs['volatility'] = kwargs.get('volatility', None)
        return f(self, **kwargs)
예제 #3
0
    def zero_rate_to_date(self,
                          date,
                          to_date,
                          compounding,
                          frequency,
                          extrapolate=True,
                          day_counter=None):
        """
        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.
        day_counter: QuantLib.DayCounter, optional
            The day counter for the calculation.

        Returns
        -------
        scalar
            Zero rate for `to_date`, implied by the yield curve at `date`.
        """
        date = to_ql_date(date)
        to_date = to_ql_date(to_date)
        day_counter = day_counter if day_counter is not None else self.day_counter
        return self.yield_curve(date).zeroRate(to_date, day_counter,
                                               compounding, frequency,
                                               extrapolate).rate()
예제 #4
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)
예제 #5
0
    def underlying_price(self, date, base_date, vol_last_available=False, dvd_tax_adjust=1, last_available=True,
                         exercise_ovrd=None):
        """
        :param date: date-like
            The date.
        :param base_date: date-like
            When date is a future date base_date is the last date on the "present" used to estimate future values.
        :param vol_last_available: bool, optional
            Whether to use last available data in case dates are missing in volatility values.
        :param dvd_tax_adjust: float, default=1
            The multiplier used to adjust for dividend tax. For example, US dividend taxes are 30% so you pass 0.7.
        :param last_available: bool, optional
            Whether to use last available data in case dates are missing in ``quotes``.
        :param exercise_ovrd: str, optional
            Used to force the option model to use a specific type of option. Only working for American and European
            option types.
        :return: float
            The option underlying spot price.
        """
        ql.Settings.instance().evaluationDate = to_ql_date(date)
        dt_maturity = to_datetime(self.option_maturity)
        if to_datetime(date) >= dt_maturity:
            return 0
        else:
            ql.Settings.instance().evaluationDate = to_ql_date(date)
            if to_datetime(date) > to_datetime(base_date):
                self.option_engine(date=base_date, vol_last_available=vol_last_available,
                                   dvd_tax_adjust=dvd_tax_adjust, last_available=last_available,
                                   exercise_ovrd=exercise_ovrd)
            else:
                self.option_engine(date=date, vol_last_available=vol_last_available,
                                   dvd_tax_adjust=dvd_tax_adjust, last_available=last_available,
                                   exercise_ovrd=exercise_ovrd)

            return self.ql_process.spot_price_handle.value()
예제 #6
0
def option_exercise_type(exercise_type, date, maturity):
    if exercise_type.upper() == 'AMERICAN':
        return ql.AmericanExercise(to_ql_date(date), to_ql_date(maturity))
    elif exercise_type.upper() == 'EUROPEAN':
        return ql.EuropeanExercise(to_ql_date(maturity))
    else:
        raise ValueError('Exercise type not supported')
예제 #7
0
    def security(self,
                 date,
                 maturity=None,
                 yield_curve_time_series=None,
                 *args,
                 **kwargs):
        """
        Parameters
        ----------
        date: Date-Like
            The evaluation date
        maturity: QuantLib.Date
            The maturity date or call date to retrieve from self.bond_components
        yield_curve_time_series: :py:class:`YieldCurveTimeSeries`
            The yield curve used for discounting the bond to retrieve the NPV
        Returns
        -------
        The python object representing a Bond
        """

        date = to_ql_date(date)
        bond_components = self.bond_components.copy()
        yield_curve = yield_curve_time_series.yield_curve_handle(date=date)
        bond_components[self.maturity_date] = ql.FixedRateBond(
            self.settlement_days, self.face_amount, self.schedule,
            self.coupons, self.day_counter, self.business_convention,
            self.redemption, self.issue_date)
        if maturity is None:
            maturity = self.maturity_date
        else:
            maturity = to_ql_date(maturity)
        bond_components[maturity].setPricingEngine(
            ql.DiscountingBondEngine(yield_curve))
        return bond_components[maturity]
예제 #8
0
 def __init__(self, timeseries):
     super().__init__(timeseries=timeseries)
     self.option_type = self.ts_attributes[OPTION_TYPE]
     self.strike = float(self.ts_attributes[STRIKE_PRICE])
     self.contract_size = float(self.ts_attributes[CONTRACT_SIZE])
     self._maturity = to_ql_date(to_datetime(self.ts_attributes[MATURITY_DATE]))
     self.calendar = to_ql_calendar(self.ts_attributes[CALENDAR])
     self.day_counter = to_ql_day_counter(self.ts_attributes[DAY_COUNTER])
     self.exercise_type = self.ts_attributes[EXERCISE_TYPE]
     self.underlying_name = self.ts_attributes[UNDERLYING_INSTRUMENT]
     try:
         self.earliest_date = to_ql_date(self.ts_attributes[EARLIEST_DATE])
     except KeyError:
         self.earliest_date = ql.Date.minDate()
     self.exercise = to_ql_option_exercise_type(self.exercise_type, self.earliest_date, self._maturity)
     self.payoff = to_ql_option_payoff(self.ts_attributes[PAYOFF_TYPE], to_ql_option_type(self.option_type),
                                       self.strike)
     self.option = to_ql_one_asset_option(self.payoff, self.exercise)
     self.risk_free_yield_curve_ts = None
     self.underlying_instrument = None
     # engine setup
     self.engine_name = 'FINITE_DIFFERENCES'
     self.base_equity_process = None
     self._implied_volatility = dict()
     self._implied_volatility_prices = dict()
 def __init__(self, start_date, end_date, tenor, calendar, day_counter):
     self.start_date = to_ql_date(start_date)
     self.end_date = to_ql_date(end_date)
     self.tenor = ql.PeriodParser.parse(tenor)
     self.calendar = to_ql_calendar(calendar)
     self.day_counter = to_ql_day_counter(day_counter)
     self.schedule = ql.Schedule(self.start_date, self.end_date, self.tenor, self.calendar, ql.Unadjusted,
                                 ql.Unadjusted, ql.DateGeneration.Forward, False)
예제 #10
0
def nth_weekday_of_month(start_year,
                         n_years,
                         frequency,
                         weekday,
                         nth_day,
                         min_date=None,
                         max_date=None):
    """ Function to get a list of dates following a specific weekday at a specific recurrence inside a month

     example: the 3rd friday of the month, every 3 months.
    :param start_year: int
        The base year for the date calculation
    :param n_years:
        The amount of years ahead to forecast
    :param frequency: str
        The frequency of the monthly occurrence, ex: ANNUAL, SEMIANNUAL, EVERY_FOUR_MONTH, QUARTERLY,
         BIMONTHLY, MONTHLY"
    :param weekday: str
        The weekday of the recurrence, Monday, Tuesday...
    :param nth_day: int
        The nth occurrence inside of the month.
    :param min_date: Date-like, optional
        The minimum date of the list
    :param max_date: Date-like, optional
        The minimum date of the list
    :return: list of QuantLib.Dates
    """
    frequency = str(frequency).upper()
    ql_frequency = to_ql_frequency(frequency)
    if not 0 < ql_frequency <= 12:
        raise ValueError(
            "Only supported frequencies are: ANNUAL, SEMIANNUAL, EVERY_FOUR_MONTH,"
            " QUARTERLY, BIMONTHLY, MONTHLY")

    weekday = str(weekday).upper()
    ql_weekday = to_ql_weekday(weekday)
    nth_day = int(nth_day)

    dates = list()
    for j in range(n_years + 1):
        year = start_year + j
        for i in range(ql_frequency):
            month = int((i + 1) * (12 / ql_frequency))
            dates.append(ql.Date.nthWeekday(nth_day, ql_weekday, month, year))

    if min_date is not None and max_date is None:
        min_date = to_ql_date(min_date)
        dates = [date for date in dates if date >= min_date]
    elif min_date is None and max_date is not None:
        max_date = to_ql_date(max_date)
        dates = [date for date in dates if date <= max_date]
    elif min_date is not None and max_date is not None:
        min_date = to_ql_date(min_date)
        max_date = to_ql_date(max_date)
        dates = [date for date in dates if min_date <= date <= max_date]

    return dates
예제 #11
0
    def implied_fx_rate_to_date(self, date, to_date):

        date = to_ql_date(date)
        to_date = to_ql_date(to_date)
        to_time = self.day_counter.yearFraction(date, to_date)
        continuous_rate = self.zero_rate_to_time(date, to_time, ql.Continuous,
                                                 ql.NoFrequency)
        fx_spot = self.fx_spot_price[date].value()
        return fx_spot * np.exp(continuous_rate * to_time)
예제 #12
0
    def update_spread_from_value(self, date, spread, tenor_date, day_counter,
                                 frequency, compounding):

        date = to_ql_date(date)
        tenor_date = to_ql_date(tenor_date)
        self.spreads[date] = dict()
        self.spreads[date][tenor_date] = ql.InterestRate(
            spread, day_counter, compounding, frequency)
        return self
예제 #13
0
 def new_f(self, *args, **kwargs):
     # Just to avoid a bug when passing the dates
     try:
         date = to_ql_date(kwargs['date'][0])
     except:
         date = to_ql_date(kwargs['date'])
     ql.Settings.instance().evaluationDate = date
     self.add_fixings(date=date)
     self.link_to_curves(date=date)
     return f(self, *args, **kwargs)
예제 #14
0
    def base_rate(self, spot, counter_rate, quote, date,
                  counter_rate_day_counter, counter_rate_compounding,
                  counter_rate_frequency, base_rate_day_counter,
                  base_rate_compounding, base_rate_frequency, maturity, *args,
                  **kwargs):
        """Obtain the interest rate of the base currency.

        Parameters
        ----------
        spot: scalar
            Spot exchange rate.
        counter_rate: scalar
            Interest rate of the base currency.
        quote: scalar, optional
            Quote of the contract.
            Default: see :py:func:`default_arguments_currency_future`.
        date: QuantLib.Date, optional
            Reference date.
            Default: see :py:func:`default_arguments_currency_future`.
        counter_rate_day_counter: QuantLib.DayCounter, optional
            Day counter of the counter currency interest rate.
            Default: see :py:func:`default_arguments_currency_future`.
        counter_rate_compounding: QuantLib.Compounding, optional
            Compounding convention of the counter currency interest rate.
            Default: see :py:func:`default_arguments_currency_future`.
        counter_rate_frequency: QuantLib.Frequency, optional
            Compounding frequency of the counter currency interest rate.
            Default: see :py:func:`default_arguments_currency_future`.
        base_rate_day_counter: QuantLib.DayCounter, optional
            Day base of the base currency interest rate.
            Default: see :py:func:`default_arguments_currency_future`.
        base_rate_compounding: QuantLib.Compounding, optional
            Compounding convention of the base currency interest rate.
            Default: see :py:func:`default_arguments_currency_future`.
        base_rate_frequency: QuantLib.Frequency, optional
            Compounding frequency of the base currency interest rate.
            Default: see :py:func:`default_arguments_currency_future`.
        maturity: QuantLib.Date, optional
            Maturity date of the contract.
            Default: see :py:func:`default_arguments_currency_future`.

        Returns
        -------
        scalar
            Implied interest rate to `maturity` in the base currency.
        """
        date = to_ql_date(date)
        maturity = to_ql_date(maturity)
        counter_rate = ql.InterestRate(counter_rate, counter_rate_day_counter,
                                       counter_rate_compounding,
                                       counter_rate_frequency)
        compound = spot * counter_rate.compoundFactor(date, maturity) / quote
        return ql.InterestRate_impliedRate(compound, base_rate_day_counter,
                                           base_rate_compounding,
                                           base_rate_frequency, date, maturity)
예제 #15
0
    def default_probability_to_date(self, date, to_date):
        """
        The default probability given a date and period

        :param date: Date of the yield curve.
        :param to_date: The target date
        :return: The % chance of default given the date and tenor.
        """

        date = to_ql_date(date)
        to_date = to_ql_date(to_date)
        ql.Settings.instance().evaluationDate = date
        return self.hazard_curve(date).defaultProbability(to_date)
예제 #16
0
    def hazard_rate_to_date(self, date, to_date):
        """
        The hazard rate of a given date

        :param date: Date of the yield curve.
        :param to_date: The target date
        :return: The % chance of default given the date and tenor.
        """

        date = to_ql_date(date)
        to_date = to_ql_date(to_date)
        ql.Settings.instance().evaluationDate = date
        return self.hazard_curve(date).hazardRate(to_date)
예제 #17
0
def calibrate_swaption_model(date,
                             model_name,
                             term_structure_ts,
                             swaption_vol_ts_collection,
                             solver_name=None,
                             use_scipy=False,
                             fix_mean=False,
                             mean_reversion_value=0.03,
                             **kwargs):
    """ Calibrate a QuantLib Swaption model.

    :param date: QuantLib.Date
        Calibration date.
    :param model_name: str
        The model name for calibration
    :param term_structure_ts: :py:obj:`YieldCurveTimeSeries`
        Yield curve time series of the curve.
    :param swaption_vol_ts_collection: :py:obj:`TimeSeriesCollection`
        Collection of swaption volatility (Black, log-normal) quotes.
    :param solver_name: str
        The solver to be used, see :py:func:calibrate_ql_model for options
    :param use_scipy: bool
        Whether to use the QuantLib solvers or Scipy solvers, see :py:func:calibrate_ql_model for options
    :param fix_mean: bool
        If you want to fix or not the mean reversion of the model
    :param mean_reversion_value: float
        Mean reversion value, used when the mean reversion is fixed.
    :return: QuantLib.CalibratedModel
        Calibrated model.
    """
    date = to_ql_date(date)
    model_name = str(model_name).upper()
    term_structure = term_structure_ts.yield_curve_handle(date=date)

    ql.Settings.instance().evaluationDate = date
    if fix_mean:
        model = to_ql_short_rate_model(model_name=model_name)(
            term_structure, mean_reversion_value)
    else:
        model = to_ql_short_rate_model(model_name=model_name)(term_structure)
    engine = to_ql_swaption_engine(model_name=model_name, model=model)

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

    return calibrate_ql_model(date=date,
                              model_name=model_name,
                              model=model,
                              helpers=swaption_helpers,
                              solver_name=solver_name,
                              use_scipy=use_scipy,
                              max_iteration=10000,
                              max_stationary_state_iteration=100,
                              **kwargs)
예제 #18
0
    def spread_rate(self, date, last_available=True, **kwargs):
        """ Returns the QuantLib.InterestRate representing the spread at date

        This will return the rate with the specific characteristics of the rate as Day Counter, Compounding and
        Frequency. This way when we ask for a rate to be used as spread we can be sure that the rate being used
        is correctly adjusted to the base rate characteristics
        :param date: QuantLib.Date
            Reference date.
        :param last_available: bool, optional
            Whether to use last available quotes if missing data.
        :param kwargs:
        :return:QuantLib.InterestRate
            The QuantLib object with the rate and characteristics
        """
        date = to_ql_date(date)
        # Returns None if impossible to obtain a rate helper from this time series
        if self.is_expired(date):
            return None
        rate = self.quotes.get_values(index=date,
                                      last_available=last_available,
                                      fill_value=np.nan)
        if np.isnan(rate):
            return None
        return ql.InterestRate(rate, self.day_counter, self.compounding,
                               self.frequency)
예제 #19
0
    def rate_helper(self,
                    date,
                    last_available=True,
                    spread=None,
                    sigma=None,
                    mean=None,
                    **other_args):
        """Helper for yield curve construction.

        :param date: QuantLib.Date
            Reference date.
        :param last_available: bool, optional
            Whether to use last available quotes if missing data.
        :param spread: float
            Rate Spread
        :param sigma: :py:obj:`TimeSeries`
            The timeseries of the sigma, used for convexity calculation
        :param mean: :py:obj:`TimeSeries`
            The timeseries of the mean, used for convexity calculation
        :return QuantLib.RateHelper
            Rate helper for yield curve construction.
        """
        # Returns None if impossible to obtain a rate helper from this time series
        date = to_ql_date(date)
        if self.is_expired(date, **other_args):
            return None
        rate = self.quotes.get_values(index=date,
                                      last_available=last_available,
                                      fill_value=np.nan)
        if np.isnan(rate):
            return None
        return None
예제 #20
0
 def __init__(self, timeseries, calculate_convexity=True):
     super().__init__(timeseries, calculate_convexity=calculate_convexity)
     # Database Attributes
     self.last_delivery = to_ql_date(
         to_datetime(self.ts_attributes[LAST_DELIVERY]))
     self._index_tenor = ql.PeriodParser.parse(
         self.ts_attributes[INDEX_TENOR])
     self.contract_size = float(self.ts_attributes[CONTRACT_SIZE])
     self.tick_size = float(self.ts_attributes[TICK_SIZE])
     self.tick_value = float(self.ts_attributes[TICK_VALUE])
     self.term_number = int(self.ts_attributes[TERM_NUMBER])
     self.term_period = to_ql_time_unit(self.ts_attributes[TERM_PERIOD])
     self.settlement_days = int(self.ts_attributes[SETTLEMENT_DAYS])
     # QuantLib Objects
     self.index = to_ql_rate_index(self.ts_attributes[INDEX],
                                   self._index_tenor)
     # QuantLib Attributes
     self._maturity = self.interest_start_date = self.index.valueDate(
         self.last_delivery)
     self.calendar = self.index.fixingCalendar()
     self.day_counter = self.index.dayCounter()
     self.business_convention = self.index.businessDayConvention()
     self.fixing_days = self.index.fixingDays()
     self.month_end = self.index.endOfMonth()
     self.interest_maturity_date = self.index.maturityDate(
         self.interest_start_date)
     self.futures_type = ql.Futures.IMM
     # Rate Helper
     self.helper_rate = ql.SimpleQuote(100)
     self.helper_convexity = ql.SimpleQuote(0)
예제 #21
0
    def update_curves(self, dates):

        dates = to_list(dates)
        for date in dates:
            date = to_ql_date(date)

            ql.Settings.instance().evaluationDate = date
            spread_dict = dict()
            if self.spreads_ts_collection is not None:
                for ts in self.spreads_ts_collection:
                    maturity = ts.maturity(date=date)
                    rate = ts.spread_rate(date=date).equivalentRate(
                        self.day_counter, self.compounding, self.frequency,
                        date, maturity).rate()
                    spread_dict[maturity] = ql.SimpleQuote(rate)
            elif self.spreads is not None:
                # passing the dict with dates and simple quotes directly.
                spread_dict = self.spreads

            date_list = list()
            spread_list = list()
            for maturity in sorted(spread_dict.keys()):
                date_list.append(maturity)
                spread_list.append(ql.QuoteHandle(spread_dict[maturity]))

            curve_handle = ql.YieldTermStructureHandle(
                self.yield_curve_time_series.yield_curve(date=date))
            spread_curve = ql.SpreadedLinearZeroInterpolatedTermStructure(
                curve_handle, spread_list, date_list, self.compounding,
                self.frequency, self.day_counter)
            spread_curve.enableExtrapolation()

            self.spreaded_curves[date] = spread_curve
예제 #22
0
    def spreaded_curve(self,
                       date,
                       spreads=None,
                       compounding=None,
                       frequency=None,
                       day_counter=None):

        ql_date = to_ql_date(date)
        if compounding is None:
            compounding = self.compounding
        if frequency is None:
            frequency = self.frequency
        if day_counter is None:
            day_counter = self.day_counter
        if spreads is None:
            spreads_at_date = self.spreads[ql_date]
        else:
            spreads_at_date = spreads[ql_date]

        curve_handle = self.yield_curve_time_series.yield_curve_handle(
            date=ql_date)
        yield_curve = ql.ZeroSpreadedTermStructure(
            curve_handle, ql.QuoteHandle(spreads_at_date), compounding,
            frequency, day_counter)
        yield_curve.enableExtrapolation()

        self.spreaded_curves[ql_date] = yield_curve
예제 #23
0
    def tenor(self, date, *args, **kwargs):
        """Get tenor of the deposit rate.

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

        Returns
        -------
        QuantLib.Period
            The tenor (period) to maturity of the deposit rate.
        """
        try:
            # If the object has a tenor attribute, return it.
            assert self._tenor
            return self._tenor
        except (AttributeError, AssertionError):
            # If no tenor, then it must have a maturity. Use it to calculate the tenor.
            date = to_ql_date(date)
            if self.is_expired(date):
                raise ValueError(
                    "The requested date is equal or higher than the instrument's maturity: {}"
                    .format(self.name))

            return ql.Period(self._maturity - date, ql.Days)
예제 #24
0
    def rate_helper(self, date, last_available=True, *args, **kwargs):
        """ Get a Rate helper object for this instrument.

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

        Returns
        -------
        QuantLib.RateHelper
            Object used to build yield curves.
        """
        # Returns None if impossible to obtain a rate helper from this time series.
        if self.is_expired(date):
            return None
        rate = self.quotes.get_values(index=date, last_available=last_available, fill_value=np.nan)
        first_cc_rate = self.first_cc.get_values(index=date, last_available=last_available, fill_value=np.nan)
        if np.isnan(rate):
            return None
        if np.isnan(first_cc_rate):
            return None
        date = to_ql_date(date)
        reference_date = self.reference_date(date)
        tenor = self.tenor(date)
        maturity_date = self.calendar.advance(reference_date, tenor)
        day_counter = self.day_counter
        implied_rate = (((1 + first_cc_rate * day_counter.yearFraction(date, reference_date)) *
                        (1 + rate * day_counter.yearFraction(reference_date, maturity_date)) - 1)
                        / day_counter.yearFraction(date, maturity_date))
        tenor = ql.Period(self.calendar.businessDaysBetween(date, maturity_date), ql.Days)
        return ql.DepositRateHelper(ql.QuoteHandle(ql.SimpleQuote(implied_rate)), tenor, 0, self.calendar,
                                    ql.Unadjusted, False, self.day_counter)
예제 #25
0
def ql_irr(cash_flow, first_amount, first_date):
    """ Calculate the IRR from a given cash flow

    :param cash_flow: list
        List of QuantLib.SimpleCashFlow (s)
    :param first_amount: Int
        The Amount of the first cash flow
    :param first_date: Date-Like
        The date of the first cash flow
    :return: float
    """

    ql.Settings.instance().evaluationDate = to_ql_date(first_date)
    try:
        fixed_rate = ql.CashFlows.yieldRate(cash_flow, float(first_amount),
                                            ql.Actual365Fixed(), ql.Compounded,
                                            ql.Annual, False, ql.Date(),
                                            ql.Date(), 1.0e-6, 1000, 0.05)
    except RuntimeError:
        try:
            fixed_rate = ql.CashFlows.yieldRate(cash_flow, float(first_amount),
                                                ql.Actual365Fixed(),
                                                ql.Compounded,
                                                ql.Annual, False, ql.Date(),
                                                ql.Date(), 1.0e-6, 1000, -0.1)
        except RuntimeError:
            fixed_rate = ql.CashFlows.yieldRate(cash_flow, float(first_amount),
                                                ql.Actual365Fixed(),
                                                ql.Compounded,
                                                ql.Annual, False, ql.Date(),
                                                ql.Date(), 1.0e-6, 1000, -0.5)
    return fixed_rate
예제 #26
0
    def __init__(self, timeseries, *args, **kwargs):
        super().__init__(timeseries)
        self.base_currency = to_ql_currency(self.ts_attributes[BASE_CURRENCY])
        self.counter_currency = to_ql_currency(
            self.ts_attributes[COUNTER_CURRENCY])
        self.maturity_date = to_ql_date(self.ts_attributes[MATURITY_DATE])
        self.quotes = self.timeseries.price.ts_values
        self.calendar = to_ql_calendar(self.ts_attributes[CALENDAR])
        self.base_rate_day_counter = to_ql_day_counter(
            self.ts_attributes[BASE_RATE_DAY_COUNTER])
        self.counter_rate_day_counter = to_ql_day_counter(
            self.ts_attributes[COUNTER_RATE_DAY_COUNTER])
        self.base_rate_compounding = to_ql_compounding(
            self.ts_attributes[BASE_RATE_COMPOUNDING])
        self.counter_rate_compounding = to_ql_compounding(
            self.ts_attributes[COUNTER_RATE_COMPOUNDING])
        self.base_rate_frequency = to_ql_frequency(
            self.ts_attributes[BASE_RATE_FREQUENCY])
        self.counter_rate_frequency = to_ql_frequency(
            self.ts_attributes[COUNTER_RATE_FREQUENCY])
        self.settlement_days = int(self.ts_attributes[SETTLEMENT_DAYS])

        self.base_currency_future = BaseCurrencyFuture(
            self.base_currency, self.counter_currency, self.maturity_date,
            self.calendar, self.base_rate_day_counter,
            self.base_rate_compounding, self.base_rate_frequency,
            self.counter_rate_day_counter, self.counter_rate_compounding,
            self.counter_rate_frequency, self.settlement_days)
예제 #27
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:
            date = to_ql_date(date)
            ql.Settings.instance().evaluationDate = 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(date, helpers,
                                                      self.day_counter)
            hazard_dates = hazard_curve.dates()
            hazard_rates = [
                hazard_curve.hazardRate(h_date) for h_date in hazard_dates
            ]

            hazard_curve = ql.HazardRateCurve(hazard_dates, hazard_rates,
                                              self.day_counter, self.calendar)
            hazard_curve.enableExtrapolation()

            self.hazard_curves[date] = hazard_curve
예제 #28
0
    def volatility_update(self, date, calendar, day_counter, ts_option, underlying_name, vol_value=None,
                          last_available=False):

        """

        :param date: date-like
            The date.
        :param calendar: QuantLib.Calendar
            The option calendar used to evaluate the model
        :param day_counter: QuantLib.DayCounter
            The option day count used to evaluate the model
        :param ts_option: py:class:`TimeSeries`
            The option Timeseries.
        :param underlying_name:
            The underlying Timeseries ts_name
        :param vol_value: float, optional
            An override of the volatility value in case you don't wan't to use the timeseries one.
        :param last_available:  bool, optional
            Whether to use last available data in case dates are missing in ``quotes``.
        :return:
        """
        dt_date = to_datetime(date)
        vol_updated = True

        if vol_value is not None:
            volatility_value = vol_value
        else:
            volatility_value = ts_option.ivol_mid.get_values(index=dt_date, last_available=last_available)
            if np.isnan(volatility_value):
                volatility_value = 0
                vol_updated = False

        back_constant_vol = ql.BlackConstantVol(0, calendar, to_ql_quote_handle(volatility_value), day_counter)
        self.volatility_handle.linkTo(back_constant_vol)
        self.vol_updated[underlying_name][to_ql_date(date)] = vol_updated
예제 #29
0
    def rate_helper(self, date, last_available=True, spread=None, sigma=None, mean=None, **other_args):
        """Helper for yield curve construction.

        :param date: QuantLib.Date
            Reference date.
        :param last_available: bool, optional
            Whether to use last available quotes if missing data.
        :param spread: float
            Rate Spread
        :param sigma: :py:obj:`TimeSeries`
            The timeseries of the sigma, used for convexity calculation
        :param mean: :py:obj:`TimeSeries`
            The timeseries of the mean, used for convexity calculation
        :return QuantLib.RateHelper
            Rate helper for yield curve construction.
        """
        # Returns None if impossible to obtain a rate helper from this time series
        date = to_ql_date(date)
        if self.is_expired(date, **other_args):
            return None
        rate = self.quotes.get_values(index=date, last_available=last_available, fill_value=np.nan)
        if np.isnan(rate):
            return None
        time = self.day_counter.yearFraction(date, self.maturity(date))
        rate = ql.InterestRate(rate, self.day_counter, self.compounding, self.frequency)
        self.helper_rate.setValue(rate.equivalentRate(ql.Simple, ql.Annual, time).rate())
        return ql.DepositRateHelper(ql.QuoteHandle(self.helper_rate),
                                    ql.Period(self.day_counter.dayCount(date, self._maturity), ql.Days),
                                    self.fixing_days,
                                    self.calendar,
                                    self.business_convention,
                                    self.month_end,
                                    self.day_counter)
예제 #30
0
    def set_coupon_rate_helper(self):
        """Set Rate Helper if None has been defined yet

        Returns
        -------
        QuantLib.RateHelper
        """
        for call_date, call_price in self.call_schedule.ts_values.iteritems():
            call_date = to_ql_date(call_date)
            schedule = create_schedule_for_component(call_date, self.schedule,
                                                     self.calendar,
                                                     self.business_convention,
                                                     self.coupon_frequency,
                                                     self.date_generation,
                                                     self.month_end)
            self._clean_price[call_date] = ql.SimpleQuote(100)
            self._bond_rate_helper[call_date] = ql.FixedRateBondHelper(
                ql.QuoteHandle(self._clean_price[call_date]),
                self.settlement_days, self.face_amount, schedule, self.coupons,
                self.day_counter, self.business_convention, self.redemption,
                self.issue_date)
        self._clean_price[self.maturity_date] = ql.SimpleQuote(100)
        self._bond_rate_helper[self.maturity_date] = ql.FixedRateBondHelper(
            ql.QuoteHandle(self._clean_price[self.maturity_date]),
            self.settlement_days, self.face_amount, self.schedule,
            self.coupons, self.day_counter, self.business_convention,
            self.redemption, self.issue_date)