Ejemplo n.º 1
0
    def delta_underlying(self, date, spot_price, base_date, vol_last_available=False, dvd_tax_adjust=1,
                         last_available=True, exercise_ovrd=None):
        """
        :param date: date-like
            The date.
        :param spot_price: float
            The underlying spot prices used for evaluation.
        :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 delta based on the date and underlying spot price.
        """
        ql.Settings.instance().evaluationDate = to_ql_date(date)
        if to_datetime(date) > to_datetime(base_date):
            option = 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:
            option = 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)

        self.ql_process.spot_price_update(date=date, underlying_name=self.underlying_instrument, spot_price=spot_price)
        self.option.setPricingEngine(ql_option_engine(self.ql_process.bsm_process))
        return option.delta()
Ejemplo n.º 2
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()
Ejemplo n.º 3
0
def filter_series(df, initial_date=None, final_date=None):
    """ Filter inplace a pandas.Series to keep its index between an initial and a final date.

    :param df: :py:obj:`pandas.Series`
        Series to be filtered.
    :param initial_date: date-like
        Initial date.
    :param final_date: date-like
        Final date.
    :return
    """
    if initial_date is None and final_date is not None:
        final_date = to_datetime(final_date)
        df.drop(df[(df.index > final_date)].index, inplace=True)
    elif final_date is None and initial_date is not None:
        initial_date = to_datetime(initial_date)
        df.drop(df[(df.index < initial_date)].index, inplace=True)
    elif final_date is None and initial_date is None:
        pass
    elif initial_date == final_date:
        initial_date = to_datetime(initial_date)
        df.drop(df[(df.index != initial_date)].index, inplace=True)
    else:
        initial_date = to_datetime(initial_date)
        final_date = to_datetime(final_date)
        df.drop(df[(df.index < initial_date) | (df.index > final_date)].index,
                inplace=True)
Ejemplo n.º 4
0
    def dividend_yield_update(self, date, calendar, day_counter, underlying_name, dividend_yield=None, dvd_tax_adjust=1,
                              last_available=True, compounding=ql.Continuous):
        """

        :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 underlying_name: str
            The timeseries ts_name used to query the stored timeseries in self.ts_underlying
        :param dividend_yield: float, optional
            An override of the dividend yield in case you don't wan't to use the timeseries one.
        :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 compounding: QuantLib.Compounding, default=Continuous
            The compounding used to interpolate the curve.
        """
        dt_date = to_datetime(date)
        dvd_ts = self.ts_underlying.get(underlying_name).eqy_dvd_yld_12m
        if dividend_yield is None:
            dividend_yield = dvd_ts.get_values(index=dt_date, last_available=last_available)
        else:
            dividend_yield = dividend_yield

        dividend_yield = dividend_yield * dvd_tax_adjust
        dividend = ql.FlatForward(0, calendar, to_ql_quote_handle(dividend_yield), day_counter, compounding)
        self.dividend_handle.linkTo(dividend)
Ejemplo n.º 5
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)
Ejemplo n.º 6
0
    def value(self,
              date,
              last_available=False,
              dividend_adjusted=False,
              *args,
              **kwargs):
        """Try to deduce dirty value for a unit of the time series (as a financial instrument).

        :param date: date-like, optional
            The date.
        :param last_available: bool, optional
            Whether to use last available data in case dates are missing in ``quotes``.
        :param dividend_adjusted: bool
            If true it will use the adjusted price for calculation.
        :return scalar, None
            The unit dirty value of the instrument.
        """
        quotes = self.spot_prices(dividend_adjusted=dividend_adjusted)
        date = to_datetime(date)
        if last_available:
            return quotes(index=date, last_available=last_available)
        if date > quotes.ts_values.last_valid_index():
            return np.nan
        if date < quotes.ts_values.first_valid_index():
            return np.nan
        return quotes(index=date)
Ejemplo n.º 7
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
Ejemplo n.º 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()
Ejemplo n.º 9
0
    def _dividends_to_date(self, start_date, date, *args, **kwargs):
        """ Cash amount paid by a unit of the instrument between `start_date` and `date`.

        :param start_date: Date-like
            Start date of the range
        :param date: Date-like
            Final date of the range
        :return: pandas.Series
        """
        start_date = to_datetime(start_date)
        date = to_datetime(date)
        ts_dividends = getattr(self.timeseries, DIVIDENDS).ts_values
        if start_date >= date:
            start_date = date
        ts_dividends = ts_dividends[ts_dividends != 0]
        if date == start_date:
            return ts_dividends[(ts_dividends.index == date)]
        else:
            return ts_dividends[(ts_dividends.index >= start_date)
                                & (ts_dividends.index <= date)]
Ejemplo n.º 10
0
 def __init__(self, timeseries, ql_process):
     super().__init__(timeseries)
     self.opt_type = self.ts_attributes[OPTION_TYPE]
     self.strike = self.ts_attributes[STRIKE_PRICE]
     self.contract_size = self.ts_attributes[OPTION_CONTRACT_SIZE]
     self.option_maturity = to_ql_date(to_datetime(self.ts_attributes[MATURITY_DATE]))
     self.payoff = ql_option_payoff(to_ql_option_type(self.opt_type), self.strike)
     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_instrument = self.ts_attributes[UNDERLYING_INSTRUMENT]
     self.ql_process = ql_process
     self.option = None
Ejemplo n.º 11
0
 def __init__(self, timeseries, first_cc):
     super().__init__(timeseries)
     self.first_cc = first_cc
     self.calendar = to_ql_calendar(self.attributes[CALENDAR])
     try:
         self._tenor = ql.PeriodParser.parse(self.attributes[TENOR_PERIOD])
     except KeyError:
         # If the deposit rate has no tenor, it must have a maturity.
         self._maturity = to_ql_date(to_datetime(self.attributes[MATURITY_DATE]))
     self.day_counter = to_ql_day_counter(self.attributes[DAY_COUNTER])
     self.compounding = to_ql_compounding(self.attributes[COMPOUNDING])
     self.frequency = to_ql_frequency(self.attributes[FREQUENCY])
     self.business_convention = to_ql_business_convention(self.attributes[BUSINESS_CONVENTION])
     self.fixing_days = int(self.attributes[FIXING_DAYS])
Ejemplo n.º 12
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()
Ejemplo n.º 13
0
    def intrinsic(self, date):
        """
        :param date: date-like
            The date
        :return: float
            The intrinsic value o the option at date.
        """
        strike = self.strike
        dt_maturity = to_datetime(self.option_maturity)
        if to_datetime(date) >= dt_maturity:
            return 0
        else:
            spot = self.ql_process.spot_price_handle.value()
            intrinsic = 0

            if self.opt_type == 'CALL':
                intrinsic = spot - strike
            if self.opt_type == 'PUT':
                intrinsic = strike - spot

            if intrinsic < 0:
                return 0
            else:
                return intrinsic
Ejemplo n.º 14
0
    def performance(self,
                    start_date=None,
                    date=None,
                    spread=None,
                    fixing_at_start_date=False,
                    **kwargs):
        """Performance of investment in the interest rate, taking tenor into account.

        If the period between start_date and date is larger the the deposit rate's tenor, considers the investment
        is rolled at the prevailing rate at each maturity.

        :param start_date: QuantLib.Date
            Start date of the investment period.
        :param date: QuantLib.Date, c-vectorized
            End date of the investment period.
        :param spread: float
            rate to be added to the return calculation.
        :param fixing_at_start_date: bool
            Whether to use the start date as the first fixing date or not.
        :return scalar
            Performance of the investment.
        """
        first_available_date = self.quotes.ts_values.first_valid_index()
        if start_date is None:
            start_date = first_available_date
        if start_date < first_available_date:
            start_date = first_available_date
        if date < start_date:
            return np.nan
        start_date = to_ql_date(start_date)
        date = to_ql_date(date)
        fixing_dates, maturity_dates = self._get_fixing_maturity_dates(
            start_date, date, fixing_at_start_date)
        fixings = self.quotes.get_values(
            index=[to_datetime(fixing_date) for fixing_date in fixing_dates])

        if spread is not None:
            fixings += spread
        return np.prod([
            ql.InterestRate(fixing, self.day_counter, self.compounding,
                            self.frequency).compoundFactor(
                                self.value_date(fixing_date), maturity_date,
                                start_date, date)
            for fixing, fixing_date, maturity_date in zip(
                fixings, fixing_dates, maturity_dates)
            if self.value_date(fixing_date) <= maturity_date
        ]) - 1
Ejemplo n.º 15
0
    def option_engine(self, date, vol_last_available=False, dvd_tax_adjust=1, last_available=True, exercise_ovrd=None):

        """
        :param date: date-like
            The date.
        :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: QuantLib.VanillaOption
            This method returns the VanillaOption with a QuantLib engine. Used for calculating the option values
            and greeks.
        """
        dt_date = to_datetime(date)
        self.option = self.ql_option(date=dt_date, exercise_ovrd=exercise_ovrd)
        vol_updated = self.ql_process.update_process(date=date, calendar=self.calendar,
                                                     day_counter=self.day_counter,
                                                     ts_option=self.timeseries,
                                                     maturity=self.option_maturity,
                                                     underlying_name=self.underlying_instrument,
                                                     vol_last_available=vol_last_available,
                                                     dvd_tax_adjust=dvd_tax_adjust,
                                                     last_available=last_available)

        self.option.setPricingEngine(ql_option_engine(self.ql_process.bsm_process))

        if vol_updated:
            return self.option
        else:
            self.ql_process.volatility_update(date=date, calendar=self.calendar, day_counter=self.day_counter,
                                              ts_option=self.timeseries, underlying_name=self.underlying_instrument,
                                              vol_value=0.2)
            mid_price = self.px_mid.get_values(index=dt_date, last_available=True)
            implied_vol = self.option.impliedVolatility(targetValue=mid_price, process=self.ql_process.bsm_process)
            self.ql_process.volatility_update(date=date, calendar=self.calendar, day_counter=self.day_counter,
                                              ts_option=self.timeseries, underlying_name=self.underlying_instrument,
                                              vol_value=implied_vol)
            self.option.setPricingEngine(ql_option_engine(self.ql_process.bsm_process))
            return self.option
Ejemplo n.º 16
0
    def dividend_yield(self, date, last_available=True, fill_value=np.nan):
        """ 12 month dividend yield at date(s).

        :param date: Date-like
            Date or dates to be return the dividend values.
        :param last_available: bool, optional
            Whether to use last available data in case dates are missing.
        :param fill_value: scalar
            Default value in case `date` can't be found.
        :return pandas.Series
        """
        date = to_datetime(date)
        try:
            dividend_yield = getattr(self.timeseries, DIVIDEND_YIELD)
            return dividend_yield(index=date,
                                  last_available=last_available,
                                  fill_value=fill_value)
        except KeyError:
            return 0
Ejemplo n.º 17
0
 def __init__(self,
              timeseries,
              is_deposit_rate=False,
              calculate_convexity=False,
              telescopic_value_dates=False):
     super().__init__(timeseries=timeseries)
     # Class Flags
     self.is_deposit_rate = is_deposit_rate
     self.calculate_convexity = calculate_convexity
     self.telescopic_value_dates = telescopic_value_dates
     # Database Attributes
     try:
         self._tenor = ql.PeriodParser.parse(
             self.ts_attributes[TENOR_PERIOD])
     except KeyError:
         self._tenor = ql.PeriodParser.parse(
             self.ts_attributes[INDEX_TENOR])
     try:
         self.issue_date = to_ql_date(
             to_datetime(self.ts_attributes[ISSUE_DATE]))
     except KeyError:
         self.issue_date = DEFAULT_ISSUE_DATE
     self.compounding = to_ql_compounding(self.ts_attributes[COMPOUNDING])
     self.frequency = to_ql_frequency(self.ts_attributes[FREQUENCY])
     self.currency = to_ql_currency(self.ts_attributes[CURRENCY])
     # Other Interest Rate Class start from here
     self._index_tenor = None
     self._maturity = None
     # QuantLib Objects
     self.term_structure = ql.RelinkableYieldTermStructureHandle()
     self.index = None
     # QuantLib Attributes
     self.calendar = None
     self.day_counter = None
     self.business_convention = None
     self.fixing_days = None
     self.month_end = None
     self.interest_maturity_date = None
     # Rate Helper
     self.helper_rate = None
     self.helper_convexity = None
     # Defined
     self._rate_helper = None
Ejemplo n.º 18
0
    def spot_price_update(self, date, underlying_name, spot_price=None, last_available=True):
        """

        :param date: date-like
            The date.
        :param underlying_name: str
            The underlying Timeseries ts_name
        :param spot_price: float, optional
            An override of the underlying spot price 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``.
        """

        dt_date = to_datetime(date)
        ts_underlying = self.ts_underlying.get(underlying_name).price
        if spot_price is None:
            spot_price = ts_underlying.get_values(index=dt_date, last_available=last_available)
        else:
            spot_price = spot_price

        self.spot_price_handle.linkTo(ql.SimpleQuote(spot_price))
Ejemplo n.º 19
0
    def spot_price(self,
                   date,
                   last_available=True,
                   fill_value=np.nan,
                   dividend_adjusted=False):
        """ Return the daily series of unadjusted price at date(s).

        :param date: Date-like
            Date or dates to be return the dividend values.
        :param last_available: bool, optional
            Whether to use last available data in case dates are missing.
        :param fill_value: scalar
            Default value in case `date` can't be found.
        :param dividend_adjusted: bool
            If true it will use the adjusted price for calculation.
        :return pandas.Series
        """
        date = to_datetime(date)
        prices = self.spot_prices(dividend_adjusted=dividend_adjusted)
        return prices(index=date,
                      last_available=last_available,
                      fill_value=fill_value)
Ejemplo n.º 20
0
    def volatility(self,
                   date,
                   n_days=252,
                   annual_factor=252,
                   log_returns=False):
        """ The converted volatility value series at date.

        :param date: Date-like
            Date or dates to be return the dividend values.
        :param n_days: int
            Rolling window for the volatility calculation.
        :param annual_factor: int, default 252
            The number of days used for period transformation, default is 252, or 1 year.
        :param log_returns: bool
            If True it will use the log returns of prices
        :return pandas.Series
        """
        date = to_datetime(date)
        prices = self.price()
        if log_returns:
            returns = np.log(prices[prices.index <= date].tail(n_days)).diff()
        else:
            returns = prices[prices.index <= date].tail(n_days).pct_change()
        return np.std(returns) * np.sqrt(annual_factor)
Ejemplo n.º 21
0
    def cash_flow_to_date(self,
                          start_date,
                          date,
                          tax_adjust=0,
                          *args,
                          **kwargs):
        """ Cash amount paid by a unit of the instrument between `start_date` and `date`.

        :param start_date: Date-like
            Start date of the range
        :param date: Date-like
            Final date of the range
        :param tax_adjust: float
            The tax value to adjust the dividends received
        :return list of tuples with (date, date, value)
            Return the ex-date, pay-date and dividend value
        """
        ts_dividends = self._dividends_to_date(start_date=start_date,
                                               date=date,
                                               *args,
                                               **kwargs)
        return list((to_ql_date(date), to_ql_date(to_datetime(value[0])),
                     value[1] * (1 - float(tax_adjust)))
                    for date, value in ts_dividends.iteritems())
Ejemplo n.º 22
0
    def __init__(self,
                 timeseries,
                 reference_curve=None,
                 index_timeseries=None):
        super().__init__(timeseries, reference_curve, index_timeseries)
        self.coupon_reset_date = to_ql_date(
            to_datetime(self.ts_attributes[COUPON_TYPE_RESET_DATE]))
        self.fixed_coupons = [float(self.ts_attributes[COUPONS])]
        self.fixed_schedule = ql.Schedule(self.first_accrual_date,
                                          self.coupon_reset_date,
                                          self.coupon_frequency, self.calendar,
                                          self.business_convention,
                                          self.business_convention,
                                          self.date_generation, self.month_end)
        fixed_schedule_len = len(self.fixed_schedule) - 1
        float_schedule_len = len(self.schedule) - fixed_schedule_len - 1
        self.gearings = [0] * fixed_schedule_len + [1] * float_schedule_len
        self.total_spreads = self.fixed_coupons * fixed_schedule_len + self.spreads * float_schedule_len
        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()
        # noinspection PyCompatibility
        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.day_counter, self.issue_date,
                self.index, fixed_schedule_len, self.fixed_coupons,
                self.spreads, self.caps, self.floors, self.in_arrears)

        self.bond = ql.FloatingRateBond(
            self.settlement_days, self.face_amount, self.schedule,
            self.index, self.day_counter, self.business_convention,
            self.index.fixingDays(), self.gearings, self.total_spreads,
            self.caps, self.floors, self.in_arrears, self.redemption,
            self.issue_date)
        self.fixing_schedule = ql.Schedule(
            self.first_accrual_date, self.maturity_date, self._index_tenor,
            self.calendar, self.business_convention, self.business_convention,
            ql.DateGeneration.Forward, self.month_end)
        self.reference_schedule = list(self.fixing_schedule)[:-1]
        self.fixing_dates = [
            self.index.fixingDate(dt) for dt in self.reference_schedule
        ]
        # Coupon pricers
        self.pricer = ql.BlackIborCouponPricer()
        self.volatility = 0.0
        self.vol = ql.ConstantOptionletVolatility(
            self.settlement_days, self.index_calendar,
            self.index_bus_day_convention, self.volatility, self.day_counter)
        self.pricer.setCapletVolatility(
            ql.OptionletVolatilityStructureHandle(self.vol))
        self.bond_components[
            self.
            maturity_date] = self.bond  # Add the original bond to bond_components.
        for bond in self.bond_components.values():
            ql.setCouponPricer(bond.cashflows(), self.pricer)
        self._bond_components_backup = self.bond_components.copy()
Ejemplo n.º 23
0
    def ts_implied_volatility(self, date, last_available=False, fill_value=np.nan):

        date = to_datetime(to_list(date))
        return getattr(self.timeseries, IMPLIED_VOL).get_values(index=date, last_available=last_available,
                                                                fill_value=fill_value)
Ejemplo n.º 24
0
 def six_months_ago(x):
     return to_datetime(to_ql_date(x) - ql.Period(6, ql.Months))
Ejemplo n.º 25
0
 def one_month_ago(x):
     return to_datetime(to_ql_date(x) - ql.Period(1, ql.Months))
Ejemplo n.º 26
0
    def ts_mid_price(self, date, last_available=True, fill_value=np.nan):

        date = to_datetime(to_list(date))
        return getattr(self.timeseries, MID_PRICE).get_values(index=date, last_available=last_available,
                                                              fill_value=fill_value)