def resolve(self, in_place: bool = True) -> Optional[dict]: with PricingContext.current if not PricingContext.current._is_entered else nullcontext( ): futures = [i.resolve(in_place) for i in self.__instruments] return dict(zip(self.__instruments, (f.result() for f in futures))) if not in_place else None
def calc( self, risk_measure: Union[RiskMeasure, Iterable[RiskMeasure]] ) -> PortfolioRiskResult: with PricingContext.current if not PricingContext.current._is_entered else nullcontext( ): return PortfolioRiskResult( self, (risk_measure, ) if isinstance(risk_measure, RiskMeasure) else risk_measure, [p.calc(risk_measure) for p in self.__instruments])
def __pricing_context(self) -> PricingContext: return PricingContext.current if not PricingContext.current.is_entered else nullcontext( )
def _pricing_context(self) -> PricingContext: pricing_context = PricingContext.current return pricing_context if not (pricing_context.is_entered or pricing_context.is_async) else nullcontext()
def calc(self, priceable: Priceable, risk_measure: Union[RiskMeasure, Iterable[RiskMeasure]])\ -> Union[list, DataFrameWithInfo, ErrorValue, FloatWithInfo, Future, MultipleRiskMeasureFuture, SeriesWithInfo]: """ 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 float, Dataframe, Series or Future (depending on is_async or whether the context is entered) **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) """ position = RiskPosition(priceable, priceable.get_quantity()) multiple_measures = not isinstance(risk_measure, RiskMeasure) futures = {} active_context_lock = self.__active_context.__lock if self.__active_context != self else nullcontext() with self.__lock, active_context_lock: for measure in risk_measure if multiple_measures else (risk_measure,): scenario = self.__scenario measure_future = self.__active_context.__futures.get((scenario, measure), {}).get(position) if measure_future is None: measure_future = PricingFuture(self) if self.__use_cache: cached_result = PricingCache.get(priceable, risk_measure) if cached_result: measure_future.set_result(cached_result) if not measure_future.done(): self.__risk_measures_in_scenario_by_provider_and_position.setdefault( priceable.provider(), {}).setdefault( position, {}).setdefault(scenario, set()).add(measure) self.__active_context.__futures.setdefault((scenario, measure), {})[position] = measure_future futures[measure] = measure_future future = MultipleRiskMeasureFuture(futures, result_future=PricingFuture(self)) if multiple_measures else\ futures[risk_measure] if not (self.is_entered or self.__is_async): if not future.done(): self._calc() return future.result() else: return future
def _calc(self): positions_by_provider = self.__active_context.__positions_by_provider session = GsSession.current batch_result = Future() if self.__is_batch else None batch_providers = set() batch_lock = Lock() if self.__is_batch else nullcontext() def handle_results(requests_to_results: Mapping[RiskRequest, dict]): for request_, result in requests_to_results.items(): try: self._handle_results(result, request_) except Exception as e: try: self._handle_results(e, request_) except Exception as he: _logger.error('Error setting error result: ' + str(he)) def run_requests(requests_: Iterable[RiskRequest], provider_: RiskApi): try: with session: results = provider_.calc_multi(requests_) if self.__is_batch: get_batch_results(dict(zip(results, requests_)), provider_) else: handle_results(dict(zip(requests_, results))) except Exception as e: handle_results({r: e for r in requests_}) def get_batch_results(ids_to_requests: Mapping[str, RiskRequest], provider_: RiskApi): def get_results(): try: with session: return provider_.get_results( ids_to_requests, self.__poll_for_batch_results, timeout=self.__batch_results_timeout) except Exception as be: return {r: be for r in ids_to_requests.values()} def set_results(results: Mapping[RiskRequest, Union[Exception, dict]]): handle_results(results) with batch_lock: # Check if we're the last provide and signal done if so batch_providers.remove(provider_) if not batch_providers: batch_result.set_result(True) if self.__is_async: batch_result_pool = ThreadPoolExecutor(1) batch_result_pool.submit(get_results).add_done_callback( lambda f: set_results(f.result())) batch_result_pool.shutdown(wait=False) else: set_results(get_results()) with self.__lock: # Group requests by risk_measures, positions, scenario - so we can create unique RiskRequest objects # Determine how many we will need while self.__risk_measures_in_scenario_by_provider_and_position: provider, risk_measures_by_scenario =\ self.__risk_measures_in_scenario_by_provider_and_position.popitem() for position, scenario_to_risk_measures in risk_measures_by_scenario.items( ): for scenario, risk_measures in scenario_to_risk_measures.items( ): risk_measures = tuple( sorted( risk_measures, key=lambda m: m.name or m.measure_type.value)) positions_by_provider.setdefault(provider, {}).setdefault((scenario, risk_measures), [])\ .append(position) if self.__positions_by_provider: num_providers = len(self.__positions_by_provider) request_pool = ThreadPoolExecutor( num_providers ) if num_providers > 1 or self.__is_async else None batch_providers = set(self.__positions_by_provider.keys()) while self.__positions_by_provider: provider, positions_by_scenario_and_risk_measures = self.__positions_by_provider.popitem( ) requests = [ RiskRequest(tuple(positions), risk_measures, parameters=self.__parameters, wait_for_results=not self.__is_batch, pricing_location=self.__market_data_location, scenario=scenario, pricing_and_market_data_as_of=self. _pricing_market_data_as_of, request_visible_to_gs=self.__visible_to_gs) for (scenario, risk_measures), positions in positions_by_scenario_and_risk_measures.items() ] if request_pool: request_pool.submit(run_requests, requests, provider) else: run_requests(requests, provider) if request_pool: request_pool.shutdown(wait=not self.__is_async) if batch_result and not self.__is_async: batch_result.result()