Example #1
0
def basis(asset: Asset,
          termination_tenor: str,
          *,
          source: str = None,
          real_time: bool = False) -> Series:
    """
    GS end-of-day cross-currency basis swap spread.

    :param asset: asset object loaded from security master
    :param termination_tenor: relative date representation of the instrument's expiration date e.g. 1y
    :param source: name of function caller
    :param real_time: whether to retrieve intraday data instead of EOD
    :return: cross-currency basis swap spread curve
    """
    if real_time:
        raise NotImplementedError('realtime basis not implemented')

    basis_mqid = convert_asset_for_rates_data_set(
        asset, RatesConversionType.CROSS_CURRENCY_BASIS)

    _logger.debug('where tenor=%s', termination_tenor)

    q = GsDataApi.build_market_data_query(
        [basis_mqid],
        QueryType.BASIS,
        where=FieldFilterMap(tenor=termination_tenor),
        source=source,
        real_time=real_time)

    _logger.debug('q %s', q)
    df = _market_data_timed(q)
    return Series() if df.empty else df['basis']
Example #2
0
def zc_inflation_swap_rate(asset: Asset,
                           termination_tenor: str,
                           *,
                           source: str = None,
                           real_time: bool = False) -> Series:
    """
    GS end-of-day zero coupon inflation swap break-even rate.

    :param asset: asset object loaded from security master
    :param termination_tenor: relative date representation of the instrument's expiration date e.g. 1y
    :param source: name of function caller
    :param real_time: whether to retrieve intraday data instead of EOD
    :return: zero coupon inflation swap break-even rate curve
    """
    if real_time:
        raise NotImplementedError(
            'realtime zc_inflation_swap_rate not implemented')

    infl_rate_benchmark_mqid = convert_asset_for_rates_data_set(
        asset, RatesConversionType.INFLATION_BENCHMARK_RATE)

    _logger.debug('where tenor=%s', termination_tenor)

    q = GsDataApi.build_market_data_query(
        [infl_rate_benchmark_mqid],
        QueryType.INFLATION_SWAP_RATE,
        where=FieldFilterMap(tenor=termination_tenor),
        source=source,
        real_time=real_time)

    _logger.debug('q %s', q)
    df = _market_data_timed(q)
    return Series() if df.empty else df['inflationSwapRate']
Example #3
0
def excess_returns(
        price_series: pd.Series,
        benchmark_or_rate: Union[Asset, Currency, float],
        *,
        day_count_convention=DayCountConvention.ACTUAL_360) -> pd.Series:
    if isinstance(benchmark_or_rate, float):
        er = [price_series.iloc[0]]
        for j in range(1, len(price_series)):
            fraction = day_count_fraction(price_series.index[j - 1],
                                          price_series.index[j],
                                          day_count_convention)
            er.append(er[-1] + price_series.iloc[j] -
                      price_series.iloc[j - 1] *
                      (1 + benchmark_or_rate * fraction))
        return pd.Series(er, index=price_series.index)

    if isinstance(benchmark_or_rate, Currency):
        try:
            marquee_id = SharpeAssets[benchmark_or_rate.value].value
        except KeyError:
            raise MqValueError(f"unsupported currency {benchmark_or_rate}")
    else:
        marquee_id = benchmark_or_rate.get_marquee_id()

    with DataContext(price_series.index[0], price_series.index[-1]):
        q = GsDataApi.build_market_data_query([marquee_id], QueryType.SPOT)
        df = GsDataApi.get_market_data(q)
    if df.empty:
        raise MqValueError(f'could not retrieve risk-free rate {marquee_id}')
    df = df[~df.index.duplicated(
        keep='first')]  # handle bad data (duplicate rows)

    return excess_returns_pure(price_series, df['spot'])
Example #4
0
def excess_returns(
        price_series: pd.Series,
        benchmark_or_rate: Union[Asset, Currency, float],
        *,
        day_count_convention=DayCountConvention.ACTUAL_360) -> pd.Series:
    if isinstance(benchmark_or_rate, float):
        er = [price_series.iloc[0]]
        for j in range(1, len(price_series)):
            fraction = day_count_fraction(price_series.index[j - 1],
                                          price_series.index[j],
                                          day_count_convention)
            er.append(er[-1] + price_series.iloc[j] -
                      price_series.iloc[j - 1] *
                      (1 + benchmark_or_rate * fraction))
        return pd.Series(er, index=price_series.index)

    if isinstance(benchmark_or_rate, Currency):
        try:
            marquee_id = SharpeAssets[benchmark_or_rate.value].value
        except KeyError:
            raise MqValueError(f"unsupported currency {benchmark_or_rate}")
    else:
        marquee_id = benchmark_or_rate.get_marquee_id()

    with DataContext(price_series.index[0], price_series.index[-1]):
        q = GsDataApi.build_market_data_query([marquee_id], QueryType.SPOT)
        df = GsDataApi.get_market_data(q)
    curve, bench_curve = align(price_series, df['spot'], Interpolate.INTERSECT)

    e_returns = [curve.iloc[0]]
    for i in range(1, len(curve)):
        multiplier = 1 + curve.iloc[i] / curve.iloc[
            i - 1] - bench_curve.iloc[i] / bench_curve.iloc[i - 1]
        e_returns.append(e_returns[-1] * multiplier)
    return pd.Series(e_returns, index=curve.index)
Example #5
0
def vol_term(asset: Asset,
             strike_reference: SkewReference,
             relative_strike: Real,
             pricing_date: Optional[GENERIC_DATE] = None,
             *,
             source: str = None,
             real_time: bool = False) -> pd.Series:
    """
    Volatility term structure. Uses most recent date available if pricing_date is not provided.

    :param asset: asset object loaded from security master
    :param strike_reference: reference for strike level
    :param relative_strike: strike relative to reference
    :param pricing_date: YYYY-MM-DD or relative days before today e.g. 1d, 1m, 1y
    :param source: name of function caller
    :param real_time: whether to retrieve intraday data instead of EOD
    :return: volatility term structure
    """
    if real_time:
        raise NotImplementedError(
            'realtime forward term not implemented')  # TODO

    if strike_reference != SkewReference.NORMALIZED:
        relative_strike /= 100

    start, end = _range_from_pricing_date(asset.exchange, pricing_date)
    with DataContext(start, end):
        _logger.debug('where strikeReference=%s, relativeStrike=%s',
                      strike_reference.value, relative_strike)
        where = FieldFilterMap(strikeReference=strike_reference.value,
                               relativeStrike=relative_strike)
        q = GsDataApi.build_market_data_query([asset.get_marquee_id()],
                                              QueryType.IMPLIED_VOLATILITY,
                                              where=where,
                                              source=source,
                                              real_time=real_time)
        _logger.debug('q %s', q)
        df = _market_data_timed(q)

    if df.empty:
        return pd.Series()

    latest = df.index.max()
    _logger.info('selected pricing date %s', latest)
    df = df.loc[latest]
    cbd = _get_custom_bd(asset.exchange)
    df = df.assign(expirationDate=df.index + df['tenor'].map(_to_offset) +
                   cbd - cbd)
    df = df.set_index('expirationDate')
    df.sort_index(inplace=True)
    df = df.loc[DataContext.current.start_date:DataContext.current.end_date]
    return df['impliedVolatility'] if not df.empty else pd.Series()
def _get_inflation_swap_data(
        asset: Asset,
        swap_tenor: str,
        index_type: str = None,
        forward_tenor: Optional[GENERIC_DATE] = None,
        clearing_house: tm_rates._ClearingHouse = None,
        source: str = None,
        real_time: bool = False,
        query_type: QueryType = QueryType.SWAP_RATE) -> pd.DataFrame:
    if real_time:
        raise NotImplementedError(
            'realtime inflation swap data not implemented')
    currency = CurrencyEnum(asset.get_identifier(AssetIdentifier.BLOOMBERG_ID))

    if currency.value not in CURRENCY_TO_INDEX_BENCHMARK.keys():
        raise NotImplementedError(
            'Data not available for {} inflation swap rates'.format(
                currency.value))
    index_type = _check_inflation_index_type(currency, index_type)

    clearing_house = tm_rates._check_clearing_house(clearing_house)

    defaults = _get_inflation_swap_leg_defaults(currency, index_type)

    if not (tm_rates._is_valid_relative_date_tenor(swap_tenor)):
        raise MqValueError('invalid swap tenor ' + swap_tenor)

    forward_tenor = tm_rates._check_forward_tenor(forward_tenor)

    fixed_rate = 'ATM'
    kwargs = dict(type='InflationSwap',
                  asset_parameters_termination_date=swap_tenor,
                  asset_parameters_index=defaults['index_type'],
                  asset_parameters_fixed_rate=fixed_rate,
                  asset_parameters_clearing_house=clearing_house.value,
                  asset_parameters_effective_date=forward_tenor,
                  asset_parameters_notional_currency=currency.name)

    rate_mqid = _get_tdapi_inflation_rates_assets(**kwargs)

    _logger.debug(
        f'where asset= {rate_mqid}, swap_tenor={swap_tenor}, index={defaults["index_type"]}, '
        f'forward_tenor={forward_tenor}, pricing_location={defaults["pricing_location"].value}, '
        f'clearing_house={clearing_house.value}, notional_currency={currency.name}'
    )
    q = GsDataApi.build_market_data_query([rate_mqid],
                                          query_type,
                                          source=source,
                                          real_time=real_time)
    _logger.debug('q %s', q)
    df = _market_data_timed(q)
    return df
Example #7
0
def average_implied_variance(asset: Asset,
                             tenor: str,
                             strike_reference: EdrDataReference,
                             relative_strike: Real,
                             *,
                             source: str = None,
                             real_time: bool = False) -> Series:
    """
    Historic weighted average implied variance for the underlying assets of an equity index.

    :param asset: asset object loaded from security master
    :param tenor: relative date representation of expiration date e.g. 1m
    :param strike_reference: reference for strike level
    :param relative_strike: strike relative to reference
    :param source: name of function caller
    :param real_time: whether to retrieve intraday data instead of EOD
    :return: average implied variance curve
    """
    if real_time:
        raise NotImplementedError(
            'realtime average_implied_variance not implemented')

    if strike_reference == EdrDataReference.DELTA_PUT:
        relative_strike = abs(100 - relative_strike)

    relative_strike = relative_strike / 100

    delta_types = (EdrDataReference.DELTA_CALL, EdrDataReference.DELTA_PUT)
    strike_ref = "delta" if strike_reference in delta_types else strike_reference.value

    _logger.debug('where tenor=%s, strikeReference=%s, relativeStrike=%s',
                  tenor, strike_ref, relative_strike)

    mqid = asset.get_marquee_id()
    where = FieldFilterMap(tenor=tenor,
                           strikeReference=strike_ref,
                           relativeStrike=relative_strike)
    q = GsDataApi.build_market_data_query([mqid],
                                          QueryType.AVERAGE_IMPLIED_VARIANCE,
                                          where=where,
                                          source=source,
                                          real_time=real_time)

    _logger.debug('q %s', q)
    df = _market_data_timed(q)
    return Series() if df.empty else df['averageImpliedVariance']
Example #8
0
def vol_smile(asset: Asset,
              tenor: str,
              strike_reference: VolSmileReference,
              pricing_date: Optional[GENERIC_DATE] = None,
              *,
              source: str = None,
              real_time: bool = False) -> Series:
    """
    Volatility smile of an asset implied by observations of market prices.

    :param asset: asset object loaded from security master
    :param tenor: relative date representation of expiration date e.g. 1m
    :param strike_reference: reference for strike level
    :param pricing_date: YYYY-MM-DD or relative days before today e.g. 1d, 1m, 1y
    :param source: name of function caller
    :param real_time: whether to retrieve intraday data instead of EOD
    :return: implied volatility smile
    """
    if real_time:
        raise NotImplementedError('realtime vol_smile not implemented')

    mqid = asset.get_marquee_id()

    start, end = _range_from_pricing_date(asset.exchange, pricing_date)

    with DataContext(start, end):
        q = GsDataApi.build_market_data_query(
            [mqid],
            QueryType.IMPLIED_VOLATILITY,
            where=FieldFilterMap(tenor=tenor,
                                 strikeReference=strike_reference.value),
            source=source,
            real_time=real_time)
        _logger.debug('q %s', q)
        df = _market_data_timed(q)

    if df.empty:
        return Series

    latest = df.index.max()
    _logger.info('selected pricing date %s', latest)
    df = df.loc[latest]

    vols = df['impliedVolatility'].values
    strikes = df['relativeStrike'].values
    return Series(vols, index=strikes)
Example #9
0
def implied_correlation(asset: Asset,
                        tenor: str,
                        strike_reference: EdrDataReference,
                        relative_strike: Real,
                        *,
                        source: str = None,
                        real_time: bool = False) -> Series:
    """
    Correlation of an asset implied by observations of market prices.

    :param asset: asset object loaded from security master
    :param tenor: relative date representation of expiration date e.g. 1m
    :param strike_reference: reference for strike level
    :param relative_strike: strike relative to reference
    :param source: name of function caller
    :param real_time: whether to retrieve intraday data instead of EOD
    :return: implied correlation curve
    """
    if real_time:
        raise NotImplementedError(
            'realtime implied_correlation not implemented')

    if strike_reference == EdrDataReference.DELTA_PUT:
        relative_strike = abs(100 - relative_strike)

    relative_strike = relative_strike / 100

    delta_types = (EdrDataReference.DELTA_CALL, EdrDataReference.DELTA_PUT)
    strike_ref = "delta" if strike_reference in delta_types else strike_reference.value

    _logger.debug('where tenor=%s, strikeReference=%s, relativeStrike=%s',
                  tenor, strike_ref, relative_strike)

    mqid = asset.get_marquee_id()
    where = FieldFilterMap(tenor=tenor,
                           strikeReference=strike_ref,
                           relativeStrike=relative_strike)
    q = GsDataApi.build_market_data_query([mqid],
                                          QueryType.IMPLIED_CORRELATION,
                                          where=where,
                                          source=source,
                                          real_time=real_time)

    _logger.debug('q %s', q)
    df = _market_data_timed(q)
    return Series() if df.empty else df['impliedCorrelation']
Example #10
0
def midcurve_vol(asset: Asset,
                 expiration_tenor: str,
                 forward_tenor: str,
                 termination_tenor: str,
                 relative_strike: float,
                 *,
                 source: str = None,
                 real_time: bool = False) -> Series:
    """
    GS end-of-day implied normal volatility for midcurve vol matrices.

    :param asset: asset object loaded from security master
    :param expiration_tenor: relative date representation of expiration date on the option e.g. 3m
    :param forward_tenor: relative date representation of swap's start date after option expiry e.g. 2y
    :param termination_tenor: relative date representation of the instrument's expiration date e.g. 1y
    :param relative_strike: strike level relative to at the money e.g. 10
    :param source: name of function caller
    :param real_time: whether to retrieve intraday data instead of EOD
    :return: midcurve implied normal volatility curve
    """
    if real_time:
        raise NotImplementedError('realtime midcurve_vol not implemented')

    _logger.debug('where expiry=%s, forwardTenor=%s, tenor=%s, strike=%s',
                  expiration_tenor, forward_tenor, termination_tenor,
                  relative_strike)

    rate_benchmark_mqid = convert_asset_for_rates_data_set(
        asset, RatesConversionType.DEFAULT_BENCHMARK_RATE)

    q = GsDataApi.build_market_data_query([rate_benchmark_mqid],
                                          QueryType.MIDCURVE_VOL,
                                          where=FieldFilterMap(
                                              expriy=expiration_tenor,
                                              forward_tenor=forward_tenor,
                                              tenor=termination_tenor,
                                              strike=relative_strike),
                                          source=source,
                                          real_time=real_time)

    _logger.debug('q %s', q)
    df = _market_data_timed(q)
    return Series() if df.empty else df['midcurveVol']
Example #11
0
def _get_swap_data(asset: Asset, swap_tenor: str, benchmark_type: BenchmarkType = None, floating_rate_tenor: str = None,
                   forward_tenor: Optional[GENERIC_DATE] = None, clearing_house: _ClearingHouse = None,
                   source: str = None, real_time: bool = False,
                   query_type: QueryType = QueryType.SWAP_RATE) -> pd.DataFrame:
    if real_time:
        raise NotImplementedError('realtime swap_rate not implemented')
    currency = CurrencyEnum(asset.get_identifier(AssetIdentifier.BLOOMBERG_ID))

    if currency.value not in ['JPY', 'EUR', 'USD', 'GBP', 'CHF', 'SEK']:
        raise NotImplementedError('Data not available for {} swap rates'.format(currency.value))

    _check_benchmark_type(currency, benchmark_type)
    clearing_house = _check_clearing_house(clearing_house)
    defaults = _get_swap_leg_defaults(currency, benchmark_type, floating_rate_tenor)

    if not (re.fullmatch('(\\d+)([bdwmy])', swap_tenor) or re.fullmatch('(frb[1-9])', forward_tenor)):
        raise MqValueError('invalid swap tenor ' + swap_tenor)

    if not re.fullmatch('(\\d+)([bdwmy])', defaults['floating_rate_tenor']):
        raise MqValueError('invalid floating rate tenor ' + defaults['floating_rate_tenor'] + ' for index: ' +
                           defaults['benchmark_type'])

    forward_tenor = check_forward_tenor(forward_tenor)
    csaTerms = currency.value + '-1'
    fixed_rate = 'ATM'
    kwargs = dict(type='Swap', asset_parameters_termination_date=swap_tenor,
                  asset_parameters_floating_rate_option=defaults['benchmark_type'],
                  asset_parameters_fixed_rate=fixed_rate, asset_parameters_clearing_house=clearing_house.value,
                  asset_parameters_floating_rate_designated_maturity=defaults['floating_rate_tenor'],
                  asset_parameters_effective_date=forward_tenor,
                  asset_parameters_notional_currency=currency.name, pricing_location=defaults['pricing_location'].value)

    rate_mqid = _convert_asset_for_mdapi_swap_rates(**kwargs)

    _logger.debug('where asset= %s, swap_tenor=%s, benchmark_type=%s, floating_rate_tenor=%s, forward_tenor=%s, '
                  'pricing_location=%s', rate_mqid, swap_tenor, defaults['benchmark_type'],
                  defaults['floating_rate_tenor'], forward_tenor, defaults['pricing_location'].value)
    where = dict(csaTerms=csaTerms)
    q = GsDataApi.build_market_data_query([rate_mqid], query_type, where=where, source=source,
                                          real_time=real_time)
    _logger.debug('q %s', q)
    df = _market_data_timed(q)
    return df
Example #12
0
def spread_option_vol(asset: Asset,
                      expiration_tenor: str,
                      long_tenor: str,
                      short_tenor: str,
                      relative_strike: float,
                      *,
                      source: str = None,
                      real_time: bool = False) -> Series:
    """
    GS end-of-day implied normal volatility for spread option vol matrices.

    :param asset: asset object loaded from security master
    :param expiration_tenor: relative date representation of expiration date on the option e.g. 3m
    :param long_tenor: relative date representation of the instrument's tenor date e.g. 1y
    :param short_tenor: relative date representation of the instrument's tenor date e.g. 1y
    :param relative_strike: strike level relative to at the money e.g. 10
    :param source: name of function caller
    :param real_time: whether to retrieve intraday data instead of EOD
    :return: spread option implied normal volatility curve
    """
    if real_time:
        raise NotImplementedError('realtime spread_option_vol not implemented')

    rate_benchmark_mqid = convert_asset_for_rates_data_set(
        asset, RatesConversionType.DEFAULT_BENCHMARK_RATE)

    _logger.debug('where expiry=%s, longTenor=%s, shortTenor=%s, strike=%s',
                  long_tenor, short_tenor, expiration_tenor, relative_strike)

    q = GsDataApi.build_market_data_query([rate_benchmark_mqid],
                                          QueryType.SPREAD_OPTION_VOL,
                                          where=FieldFilterMap(
                                              expriy=expiration_tenor,
                                              longTenor=long_tenor,
                                              shortTenor=short_tenor,
                                              strike=relative_strike),
                                          source=source,
                                          real_time=real_time)

    _logger.debug('q %s', q)
    df = _market_data_timed(q)
    return Series() if df.empty else df['spreadOptionVol']
Example #13
0
def fci(country_id: str,
        measure: _FCI_MEASURE = _FCI_MEASURE.FCI,
        *,
        source: str = None,
        real_time: bool = False,
        request_id: Optional[str] = None) -> pd.Series:
    """
    Daily Financial Conditions Index (FCI) for each of the world's large economies and many smaller ones,
    as well as aggregate FCIs for regions.

    :param country_id: id of country/region
    :param measure: FCI metric to retrieve
    :param source: name of function caller
    :param real_time: whether to retrieve intraday data instead of EOD
    :param request_id: server request id
    :return: FCI metric value
    """
    if real_time:
        raise NotImplementedError('real-time FCI data is not available')

    type_ = QueryType(inflection.titleize(measure.value))
    if (measure == _FCI_MEASURE.REAL_FCI
            or measure == _FCI_MEASURE.REAL_TWI_CONTRIBUTION):
        ds = Dataset('FCI')
        df = ds.get_data(geographyId=country_id)
        if (measure == _FCI_MEASURE.REAL_FCI):
            measure = 'realFCI'
        else:
            measure = 'realTWIContribution'
        series = ExtendedSeries(dtype=float) if (
            measure not in df.columns) else ExtendedSeries(df[measure])
        series.dataset_ids = ('FCI', )
        return series

    q = GsDataApi.build_market_data_query([country_id],
                                          query_type=type_,
                                          source=source,
                                          real_time=real_time)
    df = _market_data_timed(q, request_id)
    return _extract_series_from_df(df, type_, True)
Example #14
0
def _get_fx_vol_swap_data(asset: Asset, expiry_tenor: str, strike_type: str = None,
                          location: PricingLocation = None,
                          source: str = None, real_time: bool = False,
                          query_type: QueryType = QueryType.STRIKE_VOL) \
        -> pd.DataFrame:
    if real_time:
        raise NotImplementedError(
            'realtime inflation swap data not implemented')

    cross = asset.get_identifier(AssetIdentifier.BLOOMBERG_ID)

    if cross not in FX_VOL_SWAP_DEFAULTS:
        raise NotImplementedError(
            'Data not available for {} FX Vol Swaps'.format(cross))

    kwargs = dict(
        asset_class='FX',
        type='VolatilitySwap',
        expiry_tenor=expiry_tenor,
        asset_parameters_pair=cross,
        # asset_parameters_strike_vol=strike_type
    )
    fxv_mqid = _get_tdapi_fxo_assets_vol_swaps(**kwargs)

    if location is None:
        pricing_location = PricingLocation.NYC
    else:
        pricing_location = PricingLocation(location)

    where = dict(pricingLocation=pricing_location.value)

    q = GsDataApi.build_market_data_query([fxv_mqid],
                                          query_type,
                                          where=where,
                                          source=source,
                                          real_time=real_time)
    _logger.debug('q %s', q)
    df = _market_data_timed(q)
    return df
Example #15
0
def swaption_atm_forward_rate(asset: Asset,
                              expiration_tenor: str,
                              termination_tenor: str,
                              *,
                              source: str = None,
                              real_time: bool = False) -> Series:
    """
    GS end-of-day at-the-money forward rate for swaption vol matrices.

    :param asset: asset object loaded from security master
    :param expiration_tenor: relative date representation of expiration date on the option e.g. 3m
    :param termination_tenor: relative date representation of the instrument's expiration date e.g. 1y
    :param source: name of function caller
    :param real_time: whether to retrieve intraday data instead of EOD
    :return: swaption at-the-money forward rate curve
    """
    if real_time:
        raise NotImplementedError(
            'realtime swaption_atm_forward_rate not implemented')

    rate_benchmark_mqid = convert_asset_for_rates_data_set(
        asset, RatesConversionType.DEFAULT_BENCHMARK_RATE)

    _logger.debug('where expiry=%s, tenor=%s', expiration_tenor,
                  termination_tenor)

    q = GsDataApi.build_market_data_query([rate_benchmark_mqid],
                                          QueryType.ATM_FWD_RATE,
                                          where=FieldFilterMap(
                                              expiry=expiration_tenor,
                                              tenor=termination_tenor,
                                              strike=0),
                                          source=source,
                                          real_time=real_time)

    _logger.debug('q %s', q)
    df = _market_data_timed(q)
    return Series() if df.empty else df['atmFwdRate']
Example #16
0
def swap_rate_2(asset: Asset,
                swap_tenor: str,
                benchmark_type: BenchmarkType = None,
                floating_rate_tenor: str = None,
                forward_tenor: str = 'Spot',
                *,
                source: str = None,
                real_time: bool = False) -> Series:
    """
    GS end-of-day Fixed-Floating interest rate swap (IRS) curves across major currencies.


    :param asset: asset object loaded from security master
    :param swap_tenor: relative date representation of expiration date e.g. 1m
    :param benchmark_type: benchmark type e.g. LIBOR
    :param floating_rate_tenor: floating index rate
    :param forward_tenor: relative date representation of forward starting point eg: '1y' or 'Spot' for
    spot starting swaps
    :param source: name of function caller
    :param real_time: whether to retrieve intraday data instead of EOD
    :return: swap rate curve
    """
    if real_time:
        raise NotImplementedError('realtime swap_rate not implemented')
    currency = CurrencyEnum(asset.get_identifier(AssetIdentifier.BLOOMBERG_ID))

    if currency.value not in ['JPY', 'EUR', 'USD', 'GBP', 'CHF', 'SEK']:
        raise NotImplementedError(
            'Data not available for {} swap rates'.format(currency.value))

    if benchmark_type is not None and \
            benchmark_type.value not in CURRENCY_TO_SWAP_RATE_BENCHMARK[currency.value].keys():
        raise MqValueError('%s is not supported for %s', benchmark_type,
                           currency.value)

    defaults = _get_swap_leg_defaults(currency, benchmark_type,
                                      floating_rate_tenor)

    if not re.fullmatch('(\\d+)([bdwmy])', swap_tenor):
        raise MqValueError('invalid swap tenor ' + swap_tenor)

    if not re.fullmatch('(\\d+)([bdwmy])', floating_rate_tenor):
        raise MqValueError('invalid floating rate tenor ' +
                           floating_rate_tenor)

    if forward_tenor is None or forward_tenor == 'Spot':
        forward_tenor = '0b'
    elif not re.fullmatch('(\\d+)([bdwmy])', forward_tenor):
        raise MqValueError('invalid forward tenor ' + forward_tenor)

    clearing_house = 'LCH'
    csaTerms = currency.value + '-1'
    fixed_rate = 'ATM'
    pay_or_receive = 'Receive'
    kwargs = dict(
        type='Swap',
        asset_parameters_termination_date=swap_tenor,
        asset_parameters_floating_rate_option=defaults['benchmark_type'],
        asset_parameters_fixed_rate=fixed_rate,
        asset_parameters_clearing_house=clearing_house,
        asset_parameters_floating_rate_designated_maturity=defaults[
            'floating_rate_tenor'],
        asset_parameters_effective_date=forward_tenor,
        asset_parameters_pay_or_receive=pay_or_receive,
        asset_parameters_notional_currency=currency.name,
        pricing_location=defaults['pricing_location'])

    rate_mqid = _convert_asset_for_mdapi_swap_rates(**kwargs)

    _logger.debug(
        'where swap_tenor=%s, benchmark_type=%s, floating_rate_tenor=%s, forward_tenor=%s, '
        'pricing_location=%s', swap_tenor, defaults['benchmark_type'],
        defaults['floating_rate_tenor'], forward_tenor,
        defaults['pricing_location'])
    where = FieldFilterMap(csaTerms=csaTerms)
    q = GsDataApi.build_market_data_query([rate_mqid],
                                          QueryType.SWAP_RATE,
                                          where=where,
                                          source=source,
                                          real_time=real_time)
    _logger.debug('q %s', q)
    df = _market_data_timed(q)

    return Series() if df.empty else df['swapRate']
def _get_inflation_swap_data(asset: Asset,
                             swap_tenor: str,
                             index_type: str = None,
                             forward_tenor: Optional[GENERIC_DATE] = None,
                             clearing_house: tm_rates._ClearingHouse = None,
                             source: str = None,
                             real_time: bool = False,
                             query_type: QueryType = QueryType.SWAP_RATE,
                             location: PricingLocation = None,
                             allow_many=False,
                             request_id: Optional[str] = None) -> pd.DataFrame:
    if real_time:
        raise NotImplementedError(
            'realtime inflation swap data not implemented')
    currency = CurrencyEnum(asset.get_identifier(AssetIdentifier.BLOOMBERG_ID))

    if currency.value not in CURRENCY_TO_INDEX_BENCHMARK.keys():
        raise NotImplementedError(
            'Data not available for {} inflation swap rates'.format(
                currency.value))
    index_type = _check_inflation_index_type(currency, index_type)

    clearing_house = tm_rates._check_clearing_house(clearing_house)

    defaults = _get_inflation_swap_leg_defaults(currency, index_type)

    if not (tm_rates._is_valid_relative_date_tenor(swap_tenor)):
        raise MqValueError('invalid swap tenor ' + swap_tenor)

    forward_tenor = tm_rates._check_forward_tenor(forward_tenor)

    fixed_rate = 'ATM'
    kwargs = dict(asset_class='Rates',
                  type='InflationSwap',
                  asset_parameters_termination_date=swap_tenor,
                  asset_parameters_index=defaults['index_type'],
                  asset_parameters_fixed_rate=fixed_rate,
                  asset_parameters_clearing_house=clearing_house.value,
                  asset_parameters_effective_date=forward_tenor,
                  asset_parameters_notional_currency=currency.name)

    rate_mqids = _get_tdapi_inflation_rates_assets(allow_many=allow_many,
                                                   **kwargs)

    if location is None:
        pricing_location = tm_rates._default_pricing_location(currency)
    else:
        pricing_location = PricingLocation(location)
    pricing_location = tm_rates._pricing_location_normalized(
        pricing_location, currency)
    where = dict(pricingLocation=pricing_location.value)
    entity_ids = [rate_mqids
                  ] if not isinstance(rate_mqids, list) else rate_mqids

    _logger.debug(
        f'where asset= {rate_mqids}, swap_tenor={swap_tenor}, index={defaults["index_type"]}, '
        f'forward_tenor={forward_tenor}, pricing_location={pricing_location.value}, '
        f'clearing_house={clearing_house.value}, notional_currency={currency.name}, '
        f'request_id={request_id}')
    q = GsDataApi.build_market_data_query(entity_ids,
                                          query_type,
                                          where=where,
                                          source=source,
                                          real_time=real_time)
    _logger.debug(f'q: {q}, request_id: {request_id}')
    df = _market_data_timed(q)
    return df
Example #18
0
def basis_swap_term_structure(asset: Asset, spread_benchmark_type: BenchmarkType = None, spread_tenor: str = None,
                              reference_benchmark_type: BenchmarkType = None, reference_tenor: str = None,
                              forward_tenor: Optional[GENERIC_DATE] = None,
                              clearing_house: _ClearingHouse = None,
                              pricing_date: Optional[GENERIC_DATE] = None,
                              *, source: str = None, real_time: bool = False, ) -> Series:
    """
    GS end-of-day Floating-Floating interest rate swap (IRS) term structure across major currencies.


    :param asset: asset object loaded from security master
    :param spread_benchmark_type: benchmark type of spread leg on which basis spread is added e.g. LIBOR
    :param spread_tenor: relative date representation of expiration date of spread leg e.g. 1m
    :param reference_benchmark_type: benchmark type of reference leg e.g. LIBOR
    :param reference_tenor: relative date representation of expiration date of reference leg e.g. 1m
    :param forward_tenor: absolute / relative date representation of forward starting point eg: '1y' or 'Spot' for
    spot starting swaps, 'imm1' or 'frb1'
    :param clearing_house: Example - "LCH", "EUREX", "JSCC", "CME"
    :param pricing_date: YYYY-MM-DD or relative date
    :param source: name of function caller
    :param real_time: whether to retrieve intraday data instead of EOD
    :return: swap rate curve
    """
    if real_time:
        raise NotImplementedError('realtime basis_swap_rate not implemented')

    currency = CurrencyEnum(asset.get_identifier(AssetIdentifier.BLOOMBERG_ID))
    if currency.value not in ['JPY', 'EUR', 'USD', 'GBP']:
        raise NotImplementedError('Data not available for {} basis swap rates'.format(currency.value))

    clearing_house = _check_clearing_house(clearing_house)

    for benchmark_type in [spread_benchmark_type, reference_benchmark_type]:
        _check_benchmark_type(currency, benchmark_type)

    # default benchmark types
    legs_w_defaults = dict()
    legs_w_defaults['spread'] = _get_swap_leg_defaults(currency, spread_benchmark_type, spread_tenor)
    legs_w_defaults['reference'] = _get_swap_leg_defaults(currency, reference_benchmark_type, reference_tenor)

    for key, leg in legs_w_defaults.items():
        if not re.fullmatch('(\\d+)([bdwmy])', leg['floating_rate_tenor']):
            raise MqValueError('invalid floating rate tenor ' + leg['floating_rate_tenor'] + ' index: ' +
                               leg['benchmark_type'])

    forward_tenor = check_forward_tenor(forward_tenor)

    calendar = legs_w_defaults['spread']['pricing_location'].value
    if pricing_date is not None and pricing_date in list(GsCalendar.get(calendar).holidays):
        raise MqValueError('Specified pricing date is a holiday in {} calendar'.format(calendar))

    csaTerms = currency.value + '-1'

    kwargs = dict(type='BasisSwap', asset_parameters_payer_rate_option=legs_w_defaults['spread']['benchmark_type'],
                  asset_parameters_payer_designated_maturity=legs_w_defaults['spread']['floating_rate_tenor'],
                  asset_parameters_receiver_rate_option=legs_w_defaults['reference']['benchmark_type'],
                  asset_parameters_receiver_designated_maturity=legs_w_defaults['reference']['floating_rate_tenor'],
                  asset_parameters_clearing_house=clearing_house.value, asset_parameters_effective_date=forward_tenor,
                  asset_parameters_notional_currency=currency.name,
                  pricing_location=legs_w_defaults['spread']['pricing_location'].value)

    assets = GsAssetApi.get_many_assets(**kwargs)
    if len(assets) == 0:
        raise MqValueError('Specified arguments did not match any asset in the dataset')
    else:
        rate_mqids = [asset.id for asset in assets]

    asset_string = ''
    for mqid in rate_mqids:
        asset_string = asset_string + ',' + mqid
    _logger.debug('assets returned %s', asset_string)

    _logger.debug('where spread_benchmark_type=%s, spread_tenor=%s,  reference_benchmark_type=%s, '
                  'reference_tenor=%s, forward_tenor=%s, pricing_location=%s ',
                  legs_w_defaults['spread']['benchmark_type'], legs_w_defaults['spread']['floating_rate_tenor'],
                  legs_w_defaults['reference']['benchmark_type'], legs_w_defaults['reference']['floating_rate_tenor'],
                  forward_tenor, legs_w_defaults['spread']['pricing_location'].value)

    start, end = _range_from_pricing_date(calendar, pricing_date)
    with DataContext(start, end):
        where = dict(csaTerms=csaTerms)
        q = GsDataApi.build_market_data_query(rate_mqids, QueryType.BASIS_SWAP_RATE, where=where,
                                              source=source, real_time=real_time)
        _logger.debug('q %s', q)
        df = _market_data_timed(q)

    if df.empty:
        series = ExtendedSeries()
    else:
        latest = df.index.max()
        _logger.info('selected pricing date %s', latest)
        df = df.loc[latest]
        business_day = _get_custom_bd(calendar)
        df = df.assign(expirationDate=df.index + df['terminationTenor'].map(_to_offset) + business_day - business_day)
        df = df.set_index('expirationDate')
        df.sort_index(inplace=True)
        df = df.loc[DataContext.current.start_date: DataContext.current.end_date]
        series = ExtendedSeries() if df.empty else ExtendedSeries(df['basisSwapRate'])
    series.dataset_ids = getattr(df, 'dataset_ids', ())
    return series
Example #19
0
def basis_swap_spread(asset: Asset, swap_tenor: str = '1y',
                      spread_benchmark_type: BenchmarkType = None, spread_tenor: str = None,
                      reference_benchmark_type: BenchmarkType = None, reference_tenor: str = None,
                      forward_tenor: Optional[GENERIC_DATE] = None, clearing_house: _ClearingHouse = None, *,
                      source: str = None, real_time: bool = False, ) -> Series:
    """
    GS end-of-day Floating-Floating interest rate swap (IRS) curves across major currencies.


    :param asset: asset object loaded from security master
    :param swap_tenor: relative date representation of expiration date e.g. 1m
    :param spread_benchmark_type: benchmark type of spread leg on which basis spread is added e.g. LIBOR
    :param spread_tenor: relative date representation of expiration date of paying leg e.g. 1m
    :param reference_benchmark_type: benchmark type of reference leg e.g. LIBOR
    :param reference_tenor: relative date representation of expiration date of reference leg e.g. 1m
    :param forward_tenor: absolute / relative date representation of forward starting point eg: '1y' or 'Spot' for
    spot starting swaps, 'imm1' or 'frb1'
    :param clearing_house: Example - "LCH", "EUREX", "JSCC", "CME"
    :param source: name of function caller
    :param real_time: whether to retrieve intraday data instead of EOD
    :return: swap rate curve
    """
    if real_time:
        raise NotImplementedError('realtime basis_swap_rate not implemented')

    currency = CurrencyEnum(asset.get_identifier(AssetIdentifier.BLOOMBERG_ID))
    if currency.value not in ['JPY', 'EUR', 'USD', 'GBP']:
        raise NotImplementedError('Data not available for {} basis swap rates'.format(currency.value))

    clearing_house = _check_clearing_house(clearing_house)

    for benchmark_type in [spread_benchmark_type, reference_benchmark_type]:
        _check_benchmark_type(currency, benchmark_type)

    if not (re.fullmatch('(\\d+)([bdwmy])', swap_tenor) or re.fullmatch('(frb[1-9])', forward_tenor)):
        raise MqValueError('invalid swap tenor ' + swap_tenor)

    # default benchmark types
    legs_w_defaults = dict()
    legs_w_defaults['spread'] = _get_swap_leg_defaults(currency, spread_benchmark_type, spread_tenor)
    legs_w_defaults['reference'] = _get_swap_leg_defaults(currency, reference_benchmark_type, reference_tenor)

    for key, leg in legs_w_defaults.items():
        if not re.fullmatch('(\\d+)([bdwmy])', leg['floating_rate_tenor']):
            raise MqValueError('invalid floating rate tenor ' + leg['floating_rate_tenor'] + ' index: ' +
                               leg['benchmark_type'])

    forward_tenor = check_forward_tenor(forward_tenor)
    csaTerms = currency.value + '-1'
    kwargs = dict(type='BasisSwap', asset_parameters_termination_date=swap_tenor,
                  asset_parameters_payer_rate_option=legs_w_defaults['spread']['benchmark_type'],
                  asset_parameters_payer_designated_maturity=legs_w_defaults['spread']['floating_rate_tenor'],
                  asset_parameters_receiver_rate_option=legs_w_defaults['reference']['benchmark_type'],
                  asset_parameters_receiver_designated_maturity=legs_w_defaults['reference']['floating_rate_tenor'],
                  asset_parameters_clearing_house=clearing_house.value, asset_parameters_effective_date=forward_tenor,
                  asset_parameters_notional_currency=currency.name,
                  pricing_location=legs_w_defaults['spread']['pricing_location'].value)

    rate_mqid = _convert_asset_for_mdapi_swap_rates(**kwargs)

    _logger.debug('where asset=%s, swap_tenor=%s, spread_benchmark_type=%s, spread_tenor=%s, '
                  'reference_benchmark_type=%s, reference_tenor=%s, forward_tenor=%s, pricing_location=%s ',
                  rate_mqid, swap_tenor, legs_w_defaults['spread']['benchmark_type'],
                  legs_w_defaults['spread']['floating_rate_tenor'],
                  legs_w_defaults['reference']['benchmark_type'], legs_w_defaults['reference']['floating_rate_tenor'],
                  forward_tenor, legs_w_defaults['spread']['pricing_location'].value)

    where = dict(csaTerms=csaTerms)
    q = GsDataApi.build_market_data_query([rate_mqid], QueryType.BASIS_SWAP_RATE, where=where, source=source,
                                          real_time=real_time)
    _logger.debug('q %s', q)
    df = _market_data_timed(q)

    series = ExtendedSeries() if df.empty else ExtendedSeries(df['basisSwapRate'])
    series.dataset_ids = getattr(df, 'dataset_ids', ())
    return series
Example #20
0
def bucketize_price(asset: Asset,
                    price_method: str,
                    price_component: str,
                    bucket: str = '7x24',
                    granularity: str = 'daily',
                    *,
                    source: str = None,
                    real_time: bool = True) -> pd.Series:
    """'
    Bucketized Elec Historical Clears

    :param asset: asset object loaded from security master
    :param price_method: price method between LMP and MCP: Default value = LMP
    :param price_component: price type among totalPrice, energy, loss and congestion: Default value = totalPrice
    :param bucket: bucket type among '7x24', 'peak', 'offpeak', '2x16h' and '7x8': Default value = 7x24
    :param granularity: daily or monthly: default value = daily
    :param source: name of function caller: default source = None
    :param real_time: whether to retrieve intraday data instead of EOD: default value = True
    :return: Bucketized Elec Historical Clears
    """

    # create granularity indicator
    if granularity.lower() in ['daily', 'd']:
        granularity = 'D'
    elif granularity.lower() in ['monthly', 'm']:
        granularity = 'M'
    else:
        raise ValueError('Invalid granularity: ' + granularity +
                         '. Expected Value: daily or monthly.')

    start_date, end_date = DataContext.current.start_date, DataContext.current.end_date
    where = FieldFilterMap(priceMethod=price_method,
                           priceComponent=price_component)

    with DataContext(start_date, end_date + datetime.timedelta(days=2)):
        q = GsDataApi.build_market_data_query([asset.get_marquee_id()],
                                              QueryType.PRICE,
                                              where=where,
                                              source=source,
                                              real_time=True)
        df = _market_data_timed(q)
        _logger.debug('q %s', q)

    # TODO: get timezone info from Asset
    # default frequency definition
    df = df.tz_convert('US/Eastern')
    peak_start = 7
    peak_end = 23
    weekends = [5, 6]
    bbid = Asset.get_identifier(asset, AssetIdentifier.BLOOMBERG_ID)
    if bbid.split(" ")[0] in ['MISO', 'CAISO', 'ERCOT', 'SPP']:
        df = df.tz_convert('US/Central')
        peak_start = 6
        peak_end = 22
    if bbid.split(" ")[0] == 'CAISO':
        df = df.tz_convert('US/Pacific')
        weekends = [6]

    start_time, end_time = pd.to_datetime(
        start_date), pd.to_datetime(end_date) + datetime.timedelta(hours=23)
    df['month'] = df.index.month
    df['date'] = df.index.date
    df['day'] = df.index.dayofweek
    df['hour'] = df.index.hour
    holidays = NercCalendar().holidays(start=start_date, end=end_date).date

    # checking missing data points
    ref_hour_range = pd.date_range(start_time,
                                   end_time,
                                   freq='1h',
                                   tz='US/Eastern')
    missing_hours = ref_hour_range[~ref_hour_range.isin(df.index)]
    missing_dates = np.unique(missing_hours.date)
    missing_months = np.unique(missing_hours.month)

    # drop dates and months which have missing data
    df = df.loc[(~df['date'].isin(missing_dates))]
    if granularity == 'M':
        df = df.loc[(~df['month'].isin(missing_months))]

    # TODO: get frequency definition from SecDB
    if bucket.lower() == '7x24':
        pass
    # offpeak: 11pm-7am & weekend & holiday
    elif bucket.lower() == 'offpeak':
        df = df.loc[df['date'].isin(holidays) | df['day'].isin(weekends) |
                    (~df['date'].isin(holidays) & ~df['day'].isin(weekends) &
                     ((df['hour'] < peak_start)
                      | (df['hour'] > peak_end - 1)))]
    # peak: 7am to 11pm on weekdays
    elif bucket.lower() == 'peak':
        df = df.loc[(~df['date'].isin(holidays)) & (~df['day'].isin(weekends))
                    & (df['hour'] > peak_start - 1)
                    & (df['hour'] < peak_end)]
    # 7x8: 11pm to 7am
    elif bucket.lower() == '7x8':
        df = df.loc[(df['hour'] < peak_start) | (df['hour'] > peak_end - 1)]
    # 2x16h: weekends & holidays
    elif bucket.lower() == '2x16h':
        df = df.loc[((df['date'].isin(holidays)) | df['day'].isin(weekends))
                    & ((df['hour'] > peak_start - 1)
                       & (df['hour'] < peak_end))]
    else:
        raise ValueError('Invalid bucket: ' + bucket +
                         '. Expected Value: peak, offpeak, 7x24, 7x8, 2x16h.')

    df = df['price'].resample(granularity).mean()
    df.index = df.index.date
    df = df.loc[start_date:end_date]
    return df
Example #21
0
def basis_swap_term_structure(
    asset: Asset,
    spread_benchmark_type: BenchmarkType = None,
    spread_tenor: str = None,
    reference_benchmark_type: BenchmarkType = None,
    reference_tenor: str = None,
    forward_tenor: str = 'Spot',
    pricing_date: Optional[GENERIC_DATE] = None,
    *,
    source: str = None,
    real_time: bool = False,
) -> Series:
    """
    GS end-of-day Floating-Floating interest rate swap (IRS) term structure across major currencies.


    :param asset: asset object loaded from security master
    :param spread_benchmark_type: benchmark type of spread leg on which basis spread is added e.g. LIBOR
    :param spread_tenor: relative date representation of expiration date of spread leg e.g. 1m
    :param reference_benchmark_type: benchmark type of reference leg e.g. LIBOR
    :param reference_tenor: relative date representation of expiration date of reference leg e.g. 1m
    :param forward_tenor: relative date representation of forward starting point eg: '1y'  or 'Spot' for spot
           starting swaps
    :param pricing_date: YYYY-MM-DD or relative date
    :param source: name of function caller
    :param real_time: whether to retrieve intraday data instead of EOD
    :return: swap rate curve
    """
    if real_time:
        raise NotImplementedError('realtime basis_swap_rate not implemented')

    currency = CurrencyEnum(asset.get_identifier(AssetIdentifier.BLOOMBERG_ID))
    if currency.value not in ['JPY', 'EUR', 'USD', 'GBP']:
        raise NotImplementedError(
            'Data not available for {} basis swap rates'.format(
                currency.value))

    for benchmark_type in [spread_benchmark_type, reference_benchmark_type]:
        if benchmark_type is not None and \
                benchmark_type.value not in CURRENCY_TO_SWAP_RATE_BENCHMARK[currency.value].keys():
            raise MqValueError('%s is not supported for %s', benchmark_type,
                               currency.value)

    for floating_rate_tenor in [spread_tenor, reference_tenor]:
        if not re.fullmatch('(\\d+)([bdwmy])', floating_rate_tenor):
            raise MqValueError('invalid floating rate tenor ' +
                               floating_rate_tenor)

    if forward_tenor == '0b' or forward_tenor is None or forward_tenor == 'Spot':
        forward_tenor = '0d'
    elif not re.fullmatch('(\\d+)([bdwmy])', forward_tenor):
        raise MqValueError('invalid forward tenor ' + forward_tenor)

    # default benchmark types
    legs_w_defaults = dict()
    legs_w_defaults['spread'] = _get_swap_leg_defaults(currency,
                                                       spread_benchmark_type,
                                                       spread_tenor)
    legs_w_defaults['reference'] = _get_swap_leg_defaults(
        currency, reference_benchmark_type, reference_tenor)

    csaTerms = currency.value + '-1'
    clearing_house = 'LCH'

    kwargs = dict(
        type='BasisSwap',
        asset_parameters_payer_rate_option=legs_w_defaults['spread']
        ['benchmark_type'],
        asset_parameters_payer_designated_maturity=legs_w_defaults['spread']
        ['floating_rate_tenor'],
        asset_parameters_receiver_rate_option=legs_w_defaults['reference']
        ['benchmark_type'],
        asset_parameters_receiver_designated_maturity=legs_w_defaults[
            'reference']['floating_rate_tenor'],
        asset_parameters_clearing_house=clearing_house,
        asset_parameters_effective_date=forward_tenor,
        asset_parameters_notional_currency=currency.name,
        pricing_location=legs_w_defaults['spread']['pricing_location'])

    assets = GsAssetApi.get_many_assets(**kwargs)
    if len(assets) == 0:
        raise MqValueError(
            'Specified arguments did not match any asset in the dataset')
    else:
        rate_mqids = [asset.id for asset in assets]

    _logger.debug(
        'where spread_benchmark_type=%s, spread_tenor=%s,  reference_benchmark_type=%s, '
        'reference_tenor=%s, forward_tenor=%s, pricing_location=%s ',
        legs_w_defaults['spread']['benchmark_type'],
        legs_w_defaults['spread']['floating_rate_tenor'],
        legs_w_defaults['reference']['benchmark_type'],
        legs_w_defaults['reference']['floating_rate_tenor'], forward_tenor,
        legs_w_defaults['spread']['pricing_location'])

    start, end = _range_from_pricing_date(assets[0].exchange, pricing_date)
    with DataContext(start, end):
        where = FieldFilterMap(csaTerms=csaTerms)
        q = GsDataApi.build_market_data_query(rate_mqids,
                                              QueryType.BASIS_SWAP_RATE,
                                              where=where,
                                              source=source,
                                              real_time=real_time)
        _logger.debug('q %s', q)
        df = _market_data_timed(q)
    if df.empty:
        return pd.Series()
    latest = df.index.max()
    _logger.info('selected pricing date %s', latest)
    df = df.loc[latest]
    business_day = _get_custom_bd(asset.exchange)
    df = df.assign(expirationDate=df.index +
                   df['terminationTenor'].map(_to_offset) + business_day -
                   business_day)
    df = df.set_index('expirationDate')
    df.sort_index(inplace=True)
    df = df.loc[DataContext.current.start_date:DataContext.current.end_date]
    return df['basisSwapRate'] if not df.empty else pd.Series()
Example #22
0
def basis_swap_spread(
    asset: Asset,
    swap_tenor: str = '1y',
    spread_benchmark_type: BenchmarkType = None,
    spread_tenor: str = None,
    reference_benchmark_type: BenchmarkType = None,
    reference_tenor: str = None,
    forward_tenor: str = 'Spot',
    *,
    source: str = None,
    real_time: bool = False,
) -> Series:
    """
    GS end-of-day Floating-Floating interest rate swap (IRS) curves across major currencies.


    :param asset: asset object loaded from security master
    :param swap_tenor: relative date representation of expiration date e.g. 1m
    :param spread_benchmark_type: benchmark type of spread leg on which basis spread is added e.g. LIBOR
    :param spread_tenor: relative date representation of expiration date of paying leg e.g. 1m
    :param reference_benchmark_type: benchmark type of reference leg e.g. LIBOR
    :param reference_tenor: relative date representation of expiration date of reference leg e.g. 1m
    :param forward_tenor: relative date representation of forward starting point eg: '1y' or 'Spot' for Spot
            Starting swap
    :param source: name of function caller
    :param real_time: whether to retrieve intraday data instead of EOD
    :return: swap rate curve
    """
    if real_time:
        raise NotImplementedError('realtime basis_swap_rate not implemented')

    currency = CurrencyEnum(asset.get_identifier(AssetIdentifier.BLOOMBERG_ID))
    if currency.value not in ['JPY', 'EUR', 'USD', 'GBP']:
        raise NotImplementedError(
            'Data not available for {} basis swap rates'.format(
                currency.value))

    for benchmark_type in [spread_benchmark_type, reference_benchmark_type]:
        if benchmark_type is not None and \
                benchmark_type.value not in CURRENCY_TO_SWAP_RATE_BENCHMARK[currency.value].keys():
            raise MqValueError('%s is not supported for %s', benchmark_type,
                               currency.value)

    if not re.fullmatch('(\\d+)([bdwmy])', swap_tenor):
        raise MqValueError('invalid swap tenor ' + swap_tenor)

    for floating_rate_tenor in [spread_tenor, reference_tenor]:
        if not re.fullmatch('(\\d+)([bdwmy])', floating_rate_tenor):
            raise MqValueError('invalid floating rate tenor ' +
                               floating_rate_tenor)

    # default benchmark types
    legs_w_defaults = dict()
    legs_w_defaults['spread'] = _get_swap_leg_defaults(currency,
                                                       spread_benchmark_type,
                                                       spread_tenor)
    legs_w_defaults['reference'] = _get_swap_leg_defaults(
        currency, reference_benchmark_type, reference_tenor)

    if forward_tenor == '0b' or forward_tenor is None or forward_tenor == 'Spot':
        forward_tenor = '0d'
    elif not re.fullmatch('(\\d+)([bdwmy])', forward_tenor):
        raise MqValueError('invalid forward tenor ' + forward_tenor)

    csaTerms = currency.value + '-1'
    clearing_house = 'LCH'

    kwargs = dict(
        type='BasisSwap',
        asset_parameters_termination_date=swap_tenor,
        asset_parameters_payer_rate_option=legs_w_defaults['spread']
        ['benchmark_type'],
        asset_parameters_payer_designated_maturity=legs_w_defaults['spread']
        ['floating_rate_tenor'],
        asset_parameters_receiver_rate_option=legs_w_defaults['reference']
        ['benchmark_type'],
        asset_parameters_receiver_designated_maturity=legs_w_defaults[
            'reference']['floating_rate_tenor'],
        asset_parameters_clearing_house=clearing_house,
        asset_parameters_effective_date=forward_tenor,
        asset_parameters_notional_currency=currency.name,
        pricing_location=legs_w_defaults['spread']['pricing_location'])

    rate_mqid = _convert_asset_for_mdapi_swap_rates(**kwargs)

    _logger.debug(
        'where swap_tenor=%s, spread_benchmark_type=%s, spread_tenor=%s,  reference_benchmark_type=%s, '
        'reference_tenor=%s, forward_tenor=%s, pricing_location=%s ',
        swap_tenor, legs_w_defaults['spread']['benchmark_type'],
        legs_w_defaults['spread']['floating_rate_tenor'],
        legs_w_defaults['reference']['benchmark_type'],
        legs_w_defaults['reference']['floating_rate_tenor'], forward_tenor,
        legs_w_defaults['spread']['pricing_location'])

    where = FieldFilterMap(csaTerms=csaTerms)
    q = GsDataApi.build_market_data_query([rate_mqid],
                                          QueryType.BASIS_SWAP_RATE,
                                          where=where,
                                          source=source,
                                          real_time=real_time)
    _logger.debug('q %s', q)
    df = _market_data_timed(q)

    return Series() if df.empty else df['basisSwapRate']
Example #23
0
def skew(asset: Asset,
         tenor: str,
         strike_reference: SkewReference,
         distance: Real,
         *,
         location: str = 'NYC',
         source: str = None,
         real_time: bool = False) -> Series:
    """
    Difference in implied volatility of equidistant out-of-the-money put and call options.

    :param asset: asset object loaded from security master
    :param tenor: relative date representation of expiration date e.g. 1m
    :param strike_reference: reference for strike level (for equities)
    :param distance: distance from at-the-money option
    :param location: location at which a price fixing has been taken (for FX assets)
    :param source: name of function caller
    :param real_time: whether to retrieve intraday data instead of EOD
    :return: skew curve
    """
    if real_time:
        raise MqValueError('real-time skew not supported')

    if strike_reference in (SkewReference.DELTA, None):
        b = 50
    elif strike_reference == SkewReference.NORMALIZED:
        b = 0
    else:
        b = 100

    kwargs = {}
    if strike_reference in (SkewReference.DELTA, None):
        # using delta call strikes so X DP is represented as (100 - X) DC
        q_strikes = [100 - distance, distance, b]
    else:
        q_strikes = [b - distance, b + distance, b]

    if asset.asset_class == AssetClass.FX:
        q_strikes = _to_fx_strikes(q_strikes)
        kwargs['location'] = location
        column = 'deltaStrike'  # should use SkewReference.DELTA for FX
    else:
        assert asset.asset_class == AssetClass.Equity
        if not strike_reference:
            raise MqTypeError('strike reference required for equities')
        if strike_reference != SkewReference.NORMALIZED:
            q_strikes = [x / 100 for x in q_strikes]
        kwargs['strikeReference'] = strike_reference.value
        column = 'relativeStrike'

    kwargs[column] = q_strikes
    _logger.debug('where tenor=%s and %s', tenor, kwargs)
    where = FieldFilterMap(tenor=tenor, **kwargs)
    q = GsDataApi.build_market_data_query([asset.get_marquee_id()],
                                          QueryType.IMPLIED_VOLATILITY,
                                          where=where,
                                          source=source)
    _logger.debug('q %s', q)
    df = _market_data_timed(q)

    if df.empty:
        return pd.Series()

    curves = {k: v for k, v in df.groupby(column)}
    if len(curves) < 3:
        raise MqValueError('skew not available for given inputs')
    series = [curves[qs]['impliedVolatility'] for qs in q_strikes]
    return (series[0] - series[1]) / series[2]
Example #24
0
def _get_fxo_data(asset: Asset, expiry_tenor: str, strike: str, option_type: str = None,
                  expiration_location: str = None,
                  location: PricingLocation = None, premium_payment_date: str = None,
                  source: str = None, real_time: bool = False,
                  query_type: QueryType = QueryType.IMPLIED_VOLATILITY) \
        -> pd.DataFrame:
    if real_time:
        raise NotImplementedError(
            'realtime inflation swap data not implemented')
    cross = asset.get_identifier(AssetIdentifier.BLOOMBERG_ID)

    if cross not in FX_DEFAULTS.keys():
        raise NotImplementedError(
            'Data not available for {} FX Vanilla options'.format(cross))

    defaults = _get_fxo_defaults(cross)

    if not (tm_rates._is_valid_relative_date_tenor(expiry_tenor)):
        raise MqValueError('invalid expiry ' + expiry_tenor)

    if expiration_location is None:
        # expirationtime = defaults["expirationTime"]
        _ = defaults["expirationTime"]
    else:
        # expirationtime = expiration_location
        _ = expiration_location

    if premium_payment_date is None:
        premium_date = defaults["premiumPaymentDate"]
    else:
        premium_date = premium_payment_date

    if option_type == "Put":
        call_ccy = defaults["over"]
        put_ccy = defaults["under"]
    else:
        call_ccy = defaults["under"]
        put_ccy = defaults["over"]

    kwargs = dict(
        asset_class='FX',
        type='Option',
        asset_parameters_call_currency=call_ccy,
        asset_parameters_put_currency=put_ccy,
        asset_parameters_expiration_date=expiry_tenor,
        # asset_parameters_expiration_time=expirationtime,
        asset_parameters_option_type=option_type,
        asset_parameters_premium_payment_date=premium_date,
        asset_parameters_strike_price_relative=strike,
    )

    rate_mqid = _get_tdapi_fxo_assets(**kwargs)

    if location is None:
        pricing_location = PricingLocation.NYC
    else:
        pricing_location = PricingLocation(location)

    where = dict(pricingLocation=pricing_location.value)

    # _logger.debug(f'where asset= {rate_mqid}, swap_tenor={swap_tenor}, index={defaults["index_type"]}, '
    #              f'forward_tenor={forward_tenor}, pricing_location={pricing_location.value}, '
    #              f'clearing_house={clearing_house.value}, notional_currency={currency.name}')
    q = GsDataApi.build_market_data_query([rate_mqid],
                                          query_type,
                                          where=where,
                                          source=source,
                                          real_time=real_time)
    _logger.debug('q %s', q)
    df = _market_data_timed(q)
    return df
Example #25
0
def swap_term_structure(asset: Asset,
                        benchmark_type: BenchmarkType = None,
                        floating_rate_tenor: str = None,
                        forward_tenor: Optional[GENERIC_DATE] = None,
                        pricing_date: Optional[GENERIC_DATE] = None,
                        *,
                        source: str = None,
                        real_time: bool = False) -> Series:
    """
    GS end-of-day Fixed-Floating interest rate swap (IRS) term structure across major currencies.

    :param asset: asset object loaded from security master
    :param benchmark_type: benchmark type e.g. LIBOR
    :param floating_rate_tenor: floating index rate
    :param forward_tenor: absolute / relative date representation of forward starting point eg: '1y' or 'Spot' for
    spot starting swaps, 'imm1' or 'frb1'
    :param pricing_date: YYYY-MM-DD or relative date
    :param source: name of function caller
    :param real_time: whether to retrieve intraday data instead of EOD
    :return: swap rate term structure
    """
    if real_time:
        raise NotImplementedError('realtime swap_rate not implemented')

    currency = asset.get_identifier(AssetIdentifier.BLOOMBERG_ID)
    currency = CurrencyEnum(currency)
    if currency.value not in ['JPY', 'EUR', 'USD', 'GBP', 'CHF', 'SEK']:
        raise NotImplementedError(
            'Data not available for {} swap rates'.format(currency.value))
    clearing_house = 'LCH'

    _check_benchmark_type(currency, benchmark_type)

    forward_tenor = check_forward_tenor(forward_tenor)

    defaults = _get_swap_leg_defaults(currency, benchmark_type,
                                      floating_rate_tenor)

    if not re.fullmatch('(\\d+)([bdwmy])', defaults['floating_rate_tenor']):
        raise MqValueError('invalid floating rate tenor ' +
                           defaults['floating_rate_tenor'] + ' for index: ' +
                           defaults['benchmark_type'])

    calendar = defaults['pricing_location'].value
    if pricing_date is not None and pricing_date in list(
            GsCalendar.get(calendar).holidays):
        raise MqValueError(
            'Specified pricing date is a holiday in {} calendar'.format(
                calendar))

    csaTerms = currency.value + '-1'
    fixed_rate = 'ATM'
    kwargs = dict(
        type='Swap',
        asset_parameters_floating_rate_option=defaults['benchmark_type'],
        asset_parameters_fixed_rate=fixed_rate,
        asset_parameters_clearing_house=clearing_house,
        asset_parameters_floating_rate_designated_maturity=defaults[
            'floating_rate_tenor'],
        asset_parameters_effective_date=forward_tenor,
        asset_parameters_notional_currency=currency.name,
        pricing_location=defaults['pricing_location'].value)

    assets = GsAssetApi.get_many_assets(**kwargs)
    if len(assets) == 0:
        raise MqValueError(
            'Specified arguments did not match any asset in the dataset')
    else:
        rate_mqids = [asset.id for asset in assets]

    asset_string = ''
    for mqid in rate_mqids:
        asset_string = asset_string + ',' + mqid
    _logger.debug('assets returned %s', asset_string)

    _logger.debug(
        'where benchmark_type=%s, floating_rate_tenor=%s, forward_tenor=%s, '
        'pricing_location=%s', defaults['benchmark_type'],
        defaults['floating_rate_tenor'], forward_tenor,
        defaults['pricing_location'].value)

    start, end = _range_from_pricing_date(calendar, pricing_date)
    with DataContext(start, end):
        where = FieldFilterMap(csaTerms=csaTerms)
        q = GsDataApi.build_market_data_query(rate_mqids,
                                              QueryType.SWAP_RATE,
                                              where=where,
                                              source=source,
                                              real_time=real_time)
        _logger.debug('q %s', q)
        df = _market_data_timed(q)

    if df.empty:
        return pd.Series()
    latest = df.index.max()
    _logger.info('selected pricing date %s', latest)
    df = df.loc[latest]
    business_day = _get_custom_bd(calendar)
    df = df.assign(expirationDate=df.index +
                   df['terminationTenor'].map(_to_offset) + business_day -
                   business_day)
    df = df.set_index('expirationDate')
    df.sort_index(inplace=True)
    df = df.loc[DataContext.current.start_date:DataContext.current.end_date]
    return df['swapRate'] if not df.empty else pd.Series()
Example #26
0
def _get_crosscurrency_swap_data(
        asset1: Asset,
        asset2: Asset,
        swap_tenor: str,
        rateoption_type: str = None,
        forward_tenor: Optional[GENERIC_DATE] = None,
        clearing_house: tm_rates._ClearingHouse = None,
        source: str = None,
        real_time: bool = False,
        query_type: QueryType = QueryType.SWAP_RATE,
        location: PricingLocation = None) -> pd.DataFrame:
    if real_time:
        raise NotImplementedError(
            'realtime swap_rate not implemented for anything but rates')

    currency1 = CurrencyEnum(
        asset1.get_identifier(AssetIdentifier.BLOOMBERG_ID))
    currency2 = CurrencyEnum(
        asset2.get_identifier(AssetIdentifier.BLOOMBERG_ID))

    if currency1.value not in CURRENCY_TO_XCCY_SWAP_RATE_BENCHMARK.keys():
        raise NotImplementedError(
            'Data not available for {} crosscurrency swap rates'.format(
                currency1.value))
    if currency2.value not in CURRENCY_TO_XCCY_SWAP_RATE_BENCHMARK.keys():
        raise NotImplementedError(
            'Data not available for {} crosscurrency swap rates'.format(
                currency2.value))

    rateoption_type1 = _check_crosscurrency_rateoption_type(
        currency1, rateoption_type)
    rateoption_type2 = _check_crosscurrency_rateoption_type(
        currency2, rateoption_type)

    if rateoption_type1 != rateoption_type2:
        raise MqValueError(
            'The two currencies do not both support the rate Option type ' +
            rateoption_type)
    rateoption_type = rateoption_type1

    clearing_house = tm_rates._check_clearing_house(clearing_house)

    defaults1 = _get_crosscurrency_swap_leg_defaults(currency1,
                                                     rateoption_type)
    defaults2 = _get_crosscurrency_swap_leg_defaults(currency2,
                                                     rateoption_type)

    if not (tm_rates._is_valid_relative_date_tenor(swap_tenor)):
        raise MqValueError('invalid swap tenor ' + swap_tenor)

    if defaults1["pricing_location"] == PricingLocation.NYC:
        default_location = defaults2["pricing_location"]
        currency = currency2
    else:
        default_location = defaults1["pricing_location"]
        currency = currency1

    if location is None:
        pricing_location = PricingLocation(default_location)
    else:
        pricing_location = PricingLocation(location)
    pricing_location = tm_rates._pricing_location_normalized(
        pricing_location, currency)
    where = dict(pricingLocation=pricing_location.value)

    forward_tenor = tm_rates._check_forward_tenor(forward_tenor)
    fixed_rate = 'ATM'
    kwargs = dict(
        asset_class='Rates',
        type='XccySwapMTM',
        asset_parameters_termination_date=swap_tenor,
        asset_parameters_effective_date=forward_tenor,
        asset_parameters_payer_spread=fixed_rate,
        # asset_parameters_payer_currency=defaults1['currency'].value,
        asset_parameters_payer_rate_option=defaults1['rateOption'],
        # asset_parameters_payer_designated_maturity=defaults1['designatedMaturity'],
        # asset_parameters_receiver_currency=defaults2['currency'].value,
        asset_parameters_receiver_rate_option=defaults2['rateOption'],
        # asset_parameters_receiver_designated_maturity=defaults2['designatedMaturity'],
        asset_parameters_clearing_house=clearing_house.value,
        pricing_location=pricing_location)

    rate_mqid = _get_tdapi_crosscurrency_rates_assets(**kwargs)

    _logger.debug(
        f'where asset= {rate_mqid}, swap_tenor={swap_tenor}, forward_tenor={forward_tenor}, '
        f'payer_currency={defaults1["currency"].value}, payer_rate_option={defaults1["rateOption"]}, '
        f'payer_designated_maturity={defaults1["designatedMaturity"]}, '
        f'receiver_currency={defaults2["currency"].value}, receiver_rate_option={defaults2["rateOption"]}, '
        f'receiver_designated_maturity={defaults2["designatedMaturity"]}, '
        f'clearing_house={clearing_house.value}, pricing_location={pricing_location.value}'
    )
    q = GsDataApi.build_market_data_query([rate_mqid],
                                          query_type,
                                          where=where,
                                          source=source,
                                          real_time=real_time)
    _logger.debug('q %s', q)
    df = _market_data_timed(q)
    return df
Example #27
0
def swap_rate(asset: Asset,
              tenor: str,
              benchmark_type: BenchmarkType = None,
              floating_index: str = None,
              *,
              source: str = None,
              real_time: bool = False) -> Series:
    """
    GS end-of-day Fixed-Floating interest rate swap (IRS) curves across major currencies.

    :param asset: asset object loaded from security master
    :param tenor: relative date representation of expiration date e.g. 1m
    :param benchmark_type: benchmark type e.g. LIBOR
    :param floating_index: floating index rate
    :param source: name of function caller
    :param real_time: whether to retrieve intraday data instead of EOD
    :return: swap rate curve
    """
    if real_time:
        raise NotImplementedError('realtime swap_rate not implemented')

    currency = asset.get_identifier(AssetIdentifier.BLOOMBERG_ID)
    currency = Currency(currency)

    # default benchmark types
    if benchmark_type is None:
        if currency == Currency.EUR:
            benchmark_type = BenchmarkType.EURIBOR
        elif currency == Currency.SEK:
            benchmark_type = BenchmarkType.STIBOR
        else:
            benchmark_type = BenchmarkType.LIBOR

    over_nights = [BenchmarkType.OIS]

    # default floating index
    if floating_index is None:
        if benchmark_type in over_nights:
            floating_index = '1d'
        else:
            if currency in [Currency.USD]:
                floating_index = '3m'
            elif currency in [
                    Currency.GBP, Currency.EUR, Currency.CHF, Currency.SEK
            ]:
                floating_index = '6m'

    mdapi_divider = " " if benchmark_type in over_nights else "-"
    mdapi_floating_index = BenchmarkType.OIS.value if benchmark_type is BenchmarkType.OIS else floating_index
    mdapi = currency.value + mdapi_divider + mdapi_floating_index

    rate_mqid = GsAssetApi.map_identifiers(GsIdType.mdapi, GsIdType.id,
                                           [mdapi])[mdapi]

    _logger.debug('where tenor=%s, floatingIndex=%s', tenor, floating_index)

    q = GsDataApi.build_market_data_query([rate_mqid],
                                          QueryType.SWAP_RATE,
                                          where=FieldFilterMap(tenor=tenor),
                                          source=source,
                                          real_time=real_time)

    _logger.debug('q %s', q)
    df = _market_data_timed(q)
    return Series() if df.empty else df['swapRate']
Example #28
0
def basis_swap_term_structure(
    asset: Asset,
    spread_benchmark_type: str = None,
    spread_tenor: str = None,
    reference_benchmark_type: str = None,
    reference_tenor: str = None,
    forward_tenor: Optional[GENERIC_DATE] = None,
    clearing_house: _ClearingHouse = None,
    pricing_date: Optional[GENERIC_DATE] = None,
    *,
    source: str = None,
    real_time: bool = False,
) -> Series:
    """
    GS end-of-day Floating-Floating interest rate swap (IRS) term structure across major currencies.


    :param asset: asset object loaded from security master
    :param spread_benchmark_type: benchmark type of spread leg on which basis spread is added e.g. LIBOR
    :param spread_tenor: relative date representation of expiration date of spread leg e.g. 1m
    :param reference_benchmark_type: benchmark type of reference leg e.g. LIBOR
    :param reference_tenor: relative date representation of expiration date of reference leg e.g. 1m
    :param forward_tenor: absolute / relative date representation of forward starting point eg: '1y' or 'Spot' for
            spot starting swaps, 'imm1' or 'frb1'
    :param clearing_house: Example - "LCH", "EUREX", "JSCC", "CME"
    :param pricing_date: YYYY-MM-DD or relative date
    :param source: name of function caller
    :param real_time: whether to retrieve intraday data instead of EOD
    :return: swap rate curve
    """
    if real_time:
        raise NotImplementedError('realtime basis_swap_rate not implemented')

    kwargs = _get_basis_swap_kwargs(
        asset=asset,
        spread_benchmark_type=spread_benchmark_type,
        spread_tenor=spread_tenor,
        reference_benchmark_type=reference_benchmark_type,
        reference_tenor=reference_tenor,
        forward_tenor=forward_tenor,
        clearing_house=clearing_house)

    calendar = kwargs['pricing_location']
    if pricing_date is not None and pricing_date in list(
            GsCalendar.get(calendar).holidays):
        raise MqValueError(
            'Specified pricing date is a holiday in {} calendar'.format(
                calendar))

    rate_mqids = _get_mdapi_rates_assets(**kwargs)

    _logger.debug('assets returned %s', ', '.join(rate_mqids))
    _logger.debug(
        'where spread_benchmark_type=%s, spread_tenor=%s,  reference_benchmark_type=%s, '
        'reference_tenor=%s, forward_tenor=%s, pricing_location=%s ',
        kwargs['asset_parameters_payer_rate_option'],
        kwargs['asset_parameters_payer_designated_maturity'],
        kwargs['asset_parameters_receiver_rate_option'],
        kwargs['asset_parameters_receiver_designated_maturity'],
        kwargs['asset_parameters_effective_date'], kwargs['pricing_location'])
    start, end = _range_from_pricing_date(calendar, pricing_date)
    with DataContext(start, end):
        where = dict(csaTerms=kwargs['asset_parameters_notional_currency'] +
                     '-1')
        q = GsDataApi.build_market_data_query(rate_mqids,
                                              QueryType.BASIS_SWAP_RATE,
                                              where=where,
                                              source=source,
                                              real_time=real_time)
        _logger.debug('q %s', q)
        df = _market_data_timed(q)

    if df.empty:
        series = ExtendedSeries()
    else:
        latest = df.index.max()
        _logger.info('selected pricing date %s', latest)
        df = df.loc[latest]
        business_day = _get_custom_bd(calendar)
        df = df.assign(expirationDate=df.index +
                       df['terminationTenor'].map(_to_offset) + business_day -
                       business_day)
        df = df.set_index('expirationDate')
        df.sort_index(inplace=True)
        df = df.loc[DataContext.current.start_date:DataContext.current.
                    end_date]
        series = ExtendedSeries() if df.empty else ExtendedSeries(
            df['basisSwapRate'])
    series.dataset_ids = getattr(df, 'dataset_ids', ())
    return series
Example #29
0
def basis_swap_spread(
    asset: Asset,
    swap_tenor: str = '1y',
    spread_benchmark_type: str = None,
    spread_tenor: str = None,
    reference_benchmark_type: str = None,
    reference_tenor: str = None,
    forward_tenor: Optional[GENERIC_DATE] = None,
    clearing_house: _ClearingHouse = None,
    *,
    source: str = None,
    real_time: bool = False,
) -> Series:
    """
    GS end-of-day Floating-Floating interest rate swap (IRS) curves across major currencies.


    :param asset: asset object loaded from security master
    :param swap_tenor: relative date representation of expiration date e.g. 1m
    :param spread_benchmark_type: benchmark type of spread leg on which basis spread is added e.g. LIBOR
    :param spread_tenor: relative date representation of expiration date of paying leg e.g. 1m
    :param reference_benchmark_type: benchmark type of reference leg e.g. LIBOR
    :param reference_tenor: relative date representation of expiration date of reference leg e.g. 1m
    :param forward_tenor: absolute / relative date representation of forward starting point eg: '1y' or 'Spot' for
            spot starting swaps, 'imm1' or 'frb1'
    :param clearing_house: Example - "LCH", "EUREX", "JSCC", "CME"
    :param source: name of function caller
    :param real_time: whether to retrieve intraday data instead of EOD
    :return: swap rate curve
    """
    if real_time:
        raise NotImplementedError('realtime basis_swap_rate not implemented')

    if not (re.fullmatch('(\\d+)([bdwmy])', swap_tenor)
            or re.fullmatch('(frb[1-9])', forward_tenor)):
        raise MqValueError('invalid swap tenor ' + swap_tenor)

    kwargs = _get_basis_swap_kwargs(
        asset=asset,
        spread_benchmark_type=spread_benchmark_type,
        spread_tenor=spread_tenor,
        reference_benchmark_type=reference_benchmark_type,
        reference_tenor=reference_tenor,
        forward_tenor=forward_tenor,
        clearing_house=clearing_house)
    kwargs['asset_parameters_termination_date'] = swap_tenor

    rate_mqid = _get_mdapi_rates_assets(**kwargs)
    _logger.debug(
        'where asset=%s, swap_tenor=%s, spread_benchmark_type=%s, spread_tenor=%s, '
        'reference_benchmark_type=%s, reference_tenor=%s, forward_tenor=%s, pricing_location=%s ',
        rate_mqid, swap_tenor, kwargs['asset_parameters_payer_rate_option'],
        kwargs['asset_parameters_payer_designated_maturity'],
        kwargs['asset_parameters_receiver_rate_option'],
        kwargs['asset_parameters_receiver_designated_maturity'],
        kwargs['asset_parameters_effective_date'], kwargs['pricing_location'])

    where = dict(csaTerms=kwargs['asset_parameters_notional_currency'] + '-1')
    q = GsDataApi.build_market_data_query([rate_mqid],
                                          QueryType.BASIS_SWAP_RATE,
                                          where=where,
                                          source=source,
                                          real_time=real_time)
    _logger.debug('q %s', q)
    df = _market_data_timed(q)

    series = ExtendedSeries() if df.empty else ExtendedSeries(
        df['basisSwapRate'])
    series.dataset_ids = getattr(df, 'dataset_ids', ())
    return series
Example #30
0
def implied_volatility(asset: Asset,
                       tenor: str,
                       strike_reference: VolReference,
                       relative_strike: Real,
                       *,
                       source: str = None,
                       real_time: bool = False) -> Series:
    """
    Volatility of an asset implied by observations of market prices.

    :param asset: asset object loaded from security master
    :param tenor: relative date representation of expiration date e.g. 1m
    :param strike_reference: reference for strike level
    :param relative_strike: strike relative to reference
    :param source: name of function caller
    :param real_time: whether to retrieve intraday data instead of EOD
    :return: implied volatility curve
    """
    if asset.asset_class == AssetClass.FX:
        # no ATM support yet
        if relative_strike == 50 and strike_reference in (
                VolReference.DELTA_CALL, VolReference.DELTA_PUT):
            delta_strike = 'DN'
        else:
            if strike_reference == VolReference.DELTA_CALL:
                delta_strike = f'{relative_strike}DC'
            elif strike_reference == VolReference.DELTA_PUT:
                delta_strike = f'{relative_strike}DP'
            elif strike_reference == VolReference.FORWARD:
                if relative_strike == 100:
                    delta_strike = 'ATMF'
                else:
                    raise MqValueError(
                        'Relative strike must be 100 for Forward strike reference'
                    )
            elif strike_reference == VolReference.SPOT:
                if relative_strike == 100:
                    delta_strike = 'ATMS'
                else:
                    raise MqValueError(
                        'Relative strike must be 100 for Spot strike reference'
                    )
            else:
                raise MqValueError('strikeReference: ' +
                                   strike_reference.value +
                                   ' not supported for FX')
        loc_string = 'NYC'
        _logger.debug('where tenor=%s, deltaStrike=%s, location=%s', tenor,
                      delta_strike, loc_string)
        where = FieldFilterMap(tenor=tenor,
                               deltaStrike=delta_strike,
                               location=loc_string)
        q = GsDataApi.build_market_data_query([asset.get_marquee_id()],
                                              QueryType.IMPLIED_VOLATILITY,
                                              where=where,
                                              source=source,
                                              real_time=real_time)
        _logger.debug('q %s', q)
        df = _market_data_timed(q)
        if df.empty:
            reversed_cross = _reverse_cross(asset.name)
            q = GsDataApi.build_market_data_query(
                [reversed_cross.get_marquee_id()],
                QueryType.IMPLIED_VOLATILITY,
                where=where,
                source=source,
                real_time=real_time)
            _logger.debug('q %s', q)
            df = _market_data_timed(q)
    else:
        if strike_reference == VolReference.DELTA_PUT:
            relative_strike = abs(100 - relative_strike)
        relative_strike = relative_strike if strike_reference == VolReference.NORMALIZED else relative_strike / 100
        ref_string = "delta" if strike_reference in (
            VolReference.DELTA_CALL,
            VolReference.DELTA_PUT) else strike_reference.value

        _logger.debug('where tenor=%s, strikeReference=%s, relativeStrike=%s',
                      tenor, ref_string, relative_strike)
        where = FieldFilterMap(tenor=tenor,
                               strikeReference=ref_string,
                               relativeStrike=relative_strike)
        q = GsDataApi.build_market_data_query([asset.get_marquee_id()],
                                              QueryType.IMPLIED_VOLATILITY,
                                              where=where,
                                              source=source,
                                              real_time=real_time)
        _logger.debug('q %s', q)
        df = _market_data_timed(q)
    return Series() if df.empty else df['impliedVolatility']