Esempio n. 1
0
    def __getattribute__(self, name):
        ret = super().__getattribute__(name)
        if ret is not None or name not in self.properties():
            return ret

        resolved = False

        try:
            resolved = super().__getattribute__('resolution_key') is not None
        except AttributeError:
            pass

        if GsSession.current_is_set and not resolved:
            attr = getattr(super().__getattribute__('__class__'), name, None)
            if attr and isinstance(attr, property):
                resolved_inst = self.resolve(in_place=False)
                if isinstance(resolved_inst, PricingFuture):
                    ret = PricingFuture()
                    resolved_inst.add_done_callback(
                        lambda inst_f: ret.set_result(
                            object.__getattribute__(inst_f.result(), name)))
                else:
                    ret = object.__getattribute__(resolved_inst, name)

        return ret
Esempio n. 2
0
    def market(self) -> Union[OverlayMarket, PricingFuture, dict]:
        """
        Market Data map of coordinates and values. Note that this is not yet supported on all instruments

        ***Examples**

        >>> from gs_quant.markets.portfolio import Portfolio
        >>>
        >>> portfolio = Portfolio(...)
        >>> market = portfolio.market()

        """
        pricing_context = self.__pricing_context
        with pricing_context:
            futures = [i.market() for i in self.all_instruments]

        result_future = PricingFuture()
        return_future = not isinstance(
            pricing_context, PricingContext
        ) or pricing_context.is_async or pricing_context.is_entered

        def cb(future: CompositeResultFuture):
            def update_market_data(all_market_data, this_market_data):
                for item in this_market_data:
                    existing_value = all_market_data.setdefault(
                        item.coordinate, item.value)
                    if abs(existing_value - item.value) > 1e-6:
                        raise ValueError(
                            f'Conflicting values for {item.coordinate}: {existing_value} vs {item.value}'
                        )

            results = [f.result() for f in future.futures]
            is_historical = isinstance(results[0], dict)
            market_data = None if is_historical else {}
            overlay_markets = {} if is_historical else None

            for result in results:
                if market_data is not None:
                    update_market_data(market_data, result.market_data)
                else:
                    for market in result.values():
                        update_market_data(
                            overlay_markets.setdefault(market.base_market, {}),
                            market.market_data)

            if market_data:
                ret = OverlayMarket(base_market=results[0].base_market,
                                    market_data=market_data)
            else:
                ret = {
                    base_market.date: OverlayMarket(base_market=base_market,
                                                    market_data=market_data)
                    for base_market, market_data in overlay_markets.items()
                }

            if result_future:
                result_future.set_result(ret)

        CompositeResultFuture(futures).add_done_callback(cb)
        return result_future if return_future else result_future.result()
Esempio n. 3
0
    def calc(self, risk_measure: Union[RiskMeasure, Iterable[RiskMeasure]], fn=None)\
            -> Union[DataFrameWithInfo, ErrorValue, FloatWithInfo, PriceableImpl, PricingFuture,
                     SeriesWithInfo, Tuple[MarketDataCoordinate, ...]]:
        """
        Calculate the value of the risk_measure

        :param risk_measure: the risk measure to compute, e.g. IRDelta (from gs_quant.risk)
        :param fn: post-processing function (optional)
        :return: a float or dataframe, depending on whether the value is scalar or structured, or a future thereof
        (depending on how PricingContext is being used)

        **Examples**

        >>> from gs_quant.instrument import IRCap
        >>> from gs_quant.risk import IRDelta
        >>>
        >>> cap = IRCap('1y', 'USD')
        >>> delta = cap.calc(IRDelta)

        delta is a dataframe

        >>> from gs_quant.instrument import EqOption
        >>> from gs_quant.risk import EqDelta
        >>>
        >>> option = EqOption('.SPX', '3m', 'ATMF', 'Call', 'European')
        >>> delta = option.calc(EqDelta)

        delta is a float

        >>> from gs_quant.markets import PricingContext
        >>>
        >>> cap_usd = IRCap('1y', 'USD')
        >>> cap_eur = IRCap('1y', 'EUR')

        >>> with PricingContext():
        >>>     usd_delta_f = cap_usd.calc(IRDelta)
        >>>     eur_delta_f = cap_eur.calc(IRDelta)
        >>>
        >>> usd_delta = usd_delta_f.result()
        >>> eur_delta = eur_delta_f.result()

        usd_delta_f and eur_delta_f are futures, usd_delta and eur_delta are dataframes
        """
        futures = {r: r.pricing_context.calc(self, r)
                   for r in ((risk_measure,) if isinstance(risk_measure, RiskMeasure) else risk_measure)}
        future = MultipleRiskMeasureFuture(futures) if len(futures) > 1 else futures[risk_measure]

        if fn is not None:
            ret = PricingFuture()

            def cb(f):
                try:
                    ret.set_result(fn(f.result()))
                except Exception as e:
                    ret.set_exception(e)

            future.add_done_callback(cb)
            future = ret

        return future.result() if not (PricingContext.current.is_entered or PricingContext.current.is_async) else future
Esempio n. 4
0
    def resolve(self, in_place: bool = True) -> Optional[Union[PricingFuture, PriceableImpl, dict]]:
        priceables = self._get_instruments(self.__position_context.position_date, in_place, True)
        pricing_context = self._pricing_context
        with pricing_context:
            futures = [p.resolve(in_place) for p in priceables]

        if not in_place:
            ret = {} if isinstance(PricingContext.current, HistoricalPricingContext) else Portfolio(name=self.name)
            result_future = PricingFuture() if self._return_future else None

            def cb(future: CompositeResultFuture):
                if isinstance(ret, Portfolio):
                    ret.priceables = [f.result() for f in future.futures]
                else:
                    priceables_by_date = {}
                    for future in futures:
                        for date, priceable in future.result().items():
                            priceables_by_date.setdefault(date, []).append(priceable)

                    for date, priceables in priceables_by_date.items():
                        if any(p for p in priceables if not isinstance(p, PriceableImpl)):
                            _logger.error(f'Error resolving on {date}, skipping that date')
                        else:
                            ret[date] = Portfolio(priceables, name=self.name)

                if result_future:
                    result_future.set_result(ret)

            CompositeResultFuture(futures).add_done_callback(cb)
            return result_future or ret
Esempio n. 5
0
    def resolve(
        self,
        in_place: bool = True
    ) -> Optional[Union[PricingFuture, PriceableImpl, dict]]:
        pricing_context = self.__pricing_context
        with pricing_context:
            futures = [i.resolve(in_place) for i in self.__priceables]

        if not in_place:
            ret = {} if isinstance(PricingContext.current,
                                   HistoricalPricingContext) else Portfolio(
                                       name=self.name)
            result_future = PricingFuture() if not isinstance(pricing_context, PricingContext) or\
                pricing_context.is_async or pricing_context.is_entered else None

            def cb(future):
                if isinstance(ret, Portfolio):
                    ret.priceables = [f.result() for f in future.futures]
                else:
                    priceables_by_date = {}
                    for future in futures:
                        for date, priceable in future.result().items():
                            priceables_by_date.setdefault(date,
                                                          []).append(priceable)

                    for date, priceables in priceables_by_date.items():
                        ret[date] = Portfolio(priceables, name=self.name)

                if result_future:
                    result_future.set_result(ret)

            CompositeResultFuture(futures).add_done_callback(cb)
            return result_future or ret
Esempio n. 6
0
    def calc(self, risk_measure: Union[RiskMeasure, Iterable[RiskMeasure]], fn=None) ->\
        Union[DataFrameWithInfo, ErrorValue, FloatWithInfo, PriceableImpl, PricingFuture, SeriesWithInfo,
              Tuple[MarketDataCoordinate, ...]]:
        # Tactical fix until the equities pricing service notion of IRDelta is changed to match FICC

        from gs_quant.markets import PricingContext
        from gs_quant.risk import IRDelta, IRDeltaParallel

        error_result = None

        if risk_measure == IRDeltaParallel:
            risk_measure = IRDelta
        elif risk_measure == IRDelta:
            error_result = ErrorValue(None, 'IRDelta not supported for EqOption')
        elif not isinstance(risk_measure, RiskMeasure):
            if IRDelta in risk_measure:
                risk_measure = tuple(r for r in risk_measure if r != IRDelta)
            else:
                risk_measure = tuple(IRDelta if r == IRDeltaParallel else r for r in risk_measure)

        if error_result:
            return PricingFuture(error_result) if PricingContext.current.is_entered or PricingContext.current.is_async\
                else error_result
        else:
            return super().calc(risk_measure, fn=fn)
Esempio n. 7
0
    def _calc(self, priceable: Priceable, risk_key: RiskKey) -> PricingFuture:
        future = self.active_context.__pending.get((risk_key, priceable))

        if future is None:
            future = PricingFuture()
            cached_result = PricingCache.get(
                risk_key, priceable) if self.use_cache else None

            if cached_result is not None:
                future.set_result(cached_result)
            else:
                self.active_context.__pending[(risk_key, priceable)] = future

        if not (self.is_entered or self.is_async):
            self.__calc()

        return future
Esempio n. 8
0
    def _calc(self, instrument: InstrumentBase, risk_key: RiskKey) -> PricingFuture:
        pending = self.active_context.__pending

        from gs_quant.instrument import DummyInstrument
        if isinstance(instrument, DummyInstrument):
            return PricingFuture(StringWithInfo(value=instrument.dummy_result, risk_key=risk_key))

        future = pending.get((risk_key, instrument))

        if future is None:
            future = PricingFuture()
            cached_result = PricingCache.get(risk_key, instrument) if self.use_cache else None

            if cached_result is not None:
                future.set_result(cached_result)
            else:
                pending[(risk_key, instrument)] = future

        return future
Esempio n. 9
0
    def _calc(self, instrument: InstrumentBase,
              risk_key: RiskKey) -> PricingFuture:
        pending = self.active_context.__pending
        future = pending.get((risk_key, instrument))

        if future is None:
            future = PricingFuture()
            cached_result = PricingCache.get(
                risk_key, instrument) if self.use_cache else None

            if cached_result is not None:
                future.set_result(cached_result)
            else:
                pending[(risk_key, instrument)] = future

        if not (self.is_entered or self.is_async):
            self.__calc()

        return future
Esempio n. 10
0
    def calc(self, priceable: Priceable,
             risk_measure: RiskMeasure) -> PricingFuture:
        """
        Calculate the risk measure for the priceable instrument. Do not use directly, use via instruments

        :param priceable: The priceable (e.g. instrument)
        :param risk_measure: The measure we wish to calculate
        :return: A PricingFuture whose result will be the calculation result

        **Examples**

        >>> from gs_quant.instrument import IRSwap
        >>> from gs_quant.risk import IRDelta
        >>>
        >>> swap = IRSwap('Pay', '10y', 'USD', fixed_rate=0.01)
        >>> delta = swap.calc(IRDelta)
        """
        with self.active_context.__lock:
            risk_key = self.__risk_key(risk_measure, priceable.provider())
            future = self.active_context.__pending.get((risk_key, priceable))

            if future is None:
                future = PricingFuture()
                cached_result = PricingCache.get(
                    risk_key, priceable) if self.use_cache else None

                if cached_result is not None:
                    future.set_result(cached_result)
                else:
                    self.active_context.__pending[(risk_key,
                                                   priceable)] = future

        if not (self.is_entered or self.is_async):
            self.__calc()

        return future
Esempio n. 11
0
    def __getattribute__(self, name):
        ret = super().__getattribute__(name)
        flds = super().__getattribute__('_fields_by_name')()

        if ret is not None or name not in flds or super().__getattribute__(
                '_Instrument__suppress_resolution'):
            return ret

        if GsSession.current_is_set and super().__getattribute__(
                'resolution_key') is None:
            try:
                self.__suppress_resolution = True
                resolved_inst = self.resolve(in_place=False)
                if isinstance(resolved_inst, PricingFuture):
                    ret = PricingFuture()
                    resolved_inst.add_done_callback(
                        lambda inst_f: ret.set_result(
                            object.__getattribute__(inst_f.result(), name)))
                else:
                    ret = object.__getattribute__(resolved_inst, name)
            finally:
                self.__suppress_resolution = False

        return ret
Esempio n. 12
0
    def calc(self, risk_measure: Union[RiskMeasure, Iterable[RiskMeasure]], fn=None) \
            -> Union[DataFrameWithInfo, ErrorValue, FloatWithInfo, PriceableImpl, PricingFuture,
                     SeriesWithInfo, Tuple[MarketDataCoordinate, ...]]:
        """
        Calculate the value of the risk_measure

        :param risk_measure: the risk measure to compute, e.g. IRDelta (from gs_quant.risk)
        :param fn: post-processing function (optional)
        :return: a float or dataframe, depending on whether the value is scalar or structured, or a future thereof
        (depending on how PricingContext is being used)

        **Examples**

        >>> from gs_quant.instrument import IRCap
        >>> from gs_quant.risk import IRDelta
        >>>
        >>> cap = IRCap('1y', 'USD')
        >>> delta = cap.calc(IRDelta)

        delta is a dataframe

        >>> from gs_quant.instrument import EqOption
        >>> from gs_quant.risk import EqDelta
        >>>
        >>> option = EqOption('.SPX', '3m', 'ATMF', 'Call', 'European')
        >>> delta = option.calc(EqDelta)

        delta is a float

        >>> from gs_quant.markets import PricingContext
        >>>
        >>> cap_usd = IRCap('1y', 'USD')
        >>> cap_eur = IRCap('1y', 'EUR')

        >>> with PricingContext():
        >>>     usd_delta_f = cap_usd.calc(IRDelta)
        >>>     eur_delta_f = cap_eur.calc(IRDelta)
        >>>
        >>> usd_delta = usd_delta_f.result()
        >>> eur_delta = eur_delta_f.result()

        usd_delta_f and eur_delta_f are futures, usd_delta and eur_delta are dataframes
        """
        single_measure = isinstance(risk_measure, RiskMeasure)
        with self._pricing_context:
            future = risk_measure.pricing_context.calc(self, risk_measure) if single_measure else \
                MultipleRiskMeasureFuture(self, {r: r.pricing_context.calc(self, r) for r in risk_measure})

        # Warn on use of deprecated measures
        def warning_on_one_line(msg, category, _filename, _lineno, _file=None, _line=None):
            return f'{category.__name__}:{msg}'

        for measure in (risk_measure,) if single_measure else risk_measure:
            if measure.name in DEPRECATED_MEASURES.keys():
                message = '{0} risk measure is deprecated. Please use {1} instead and pass in arguments to describe ' \
                          'risk measure specifics.\n'.format(measure.name, DEPRECATED_MEASURES[measure.name])
                warnings.simplefilter('once')
                warnings.formatwarning = warning_on_one_line
                warnings.warn(message, DeprecationWarning)
                warnings.simplefilter('ignore')

        if fn is not None:
            ret = PricingFuture()

            def cb(f):
                try:
                    ret.set_result(fn(f.result()))
                except Exception as e:
                    ret.set_exception(e)

            future.add_done_callback(cb)
            future = ret

        return future if self._return_future else future.result()