def update(self) -> Dict: """ Update your custom basket :return: dictionary containing asset id and report id **Usage** Make updates to your basket's metadata, pricing options, publishing options, or composition **See also** :func:`get_details` :func:`poll_status` :func:`create` """ self.__finish_populating_attributes_for_existing_basket() edit_inputs, rebal_inputs = self.__get_updates() if edit_inputs is None and rebal_inputs is None: raise MqValueError('Update failed: Nothing on the basket was changed') elif edit_inputs is not None and rebal_inputs is None: response = GsIndexApi.edit(self.id, edit_inputs) elif rebal_inputs is not None and edit_inputs is None: response = GsIndexApi.rebalance(self.id, rebal_inputs) else: response = self.__edit_and_rebalance(edit_inputs, rebal_inputs) gs_asset = GsAssetApi.get_asset(self.id) self.__latest_create_report = GsReportApi.get_report(response.report_id) self.__error_messages.remove(ErrorMessage.UNMODIFIABLE) self.__init__(gs_asset=gs_asset) return response.as_dict()
def create(self) -> Dict: """ Create a new custom basket in Marquee :return: dictionary containing asset id and report id **Usage** Create a new custom basket in Marquee **See also** :func:`get_details` :func:`poll_status` :func:`update` """ inputs, pricing, publish = {}, {}, {} for prop in CustomBasketsCreateInputs.properties(): set_(inputs, prop, get(self, prop)) for prop in CustomBasketsPricingParameters.properties(): set_(pricing, prop, get(self, prop)) for prop in PublishParameters.properties(): set_(publish, prop, get(self, prop)) set_(inputs, 'position_set', self.position_set.to_target(common=False)) set_(inputs, 'pricing_parameters', CustomBasketsPricingParameters(**pricing)) set_(inputs, 'publish_parameters', PublishParameters(**publish)) create_inputs = CustomBasketsCreateInputs(**inputs) response = GsIndexApi.create(create_inputs) gs_asset = GsAssetApi.get_asset(response.asset_id) self.__latest_create_report = GsReportApi.get_report( response.report_id) self.__init__(gs_asset=gs_asset, _finish_init=True) return response.as_dict()
def get(cls, report_id: str, acceptable_types: List[ReportType] = None): # This map cant be instantiated / stored at the top of this file, bc the Factor/RiskReport classes aren't # defined there. Don't know the best place to put this report_type_to_class_type = { ReportType.Portfolio_Factor_Risk: type(FactorRiskReport()), ReportType.Asset_Factor_Risk: type(FactorRiskReport()), ReportType.Portfolio_Performance_Analytics: type(PerformanceReport()) } report = GsReportApi.get_report(report_id=report_id) if acceptable_types is not None and report.type not in acceptable_types: raise MqValueError('Unexpected report type found.') if report.type in report_type_to_class_type: return report_type_to_class_type[report.type]( report_id=report.id, position_source_id=report.position_source_id, position_source_type=report.position_source_type, report_type=report.type, parameters=report.parameters, status=report.status) return Report(report_id=report.id, position_source_id=report.position_source_id, position_source_type=report.position_source_type, report_type=report.type, parameters=report.parameters, status=report.status)
def get(cls, report_id: str, **kwargs): """ Get a thematic report from the unique report identifier :param report_id: Marquee report ID :return: returns a ThematicReport object that correlates to the Marquee report """ return cls.from_target(GsReportApi.get_report(report_id))
def poll_report(self, report_id: str, timeout: int = 600, step: int = 30): poll = True end = dt.datetime.now() + dt.timedelta(seconds=timeout) while poll and dt.datetime.now() <= end: try: status = GsReportApi.get_report(report_id).status if status not in set(ReportStatus.error, ReportStatus.cancelled, ReportStatus.done): _logger.info( f'Report is {status} as of {dt.datetime.now().isoformat()}' ) time.sleep(step) else: poll = False if status == ReportStatus.error: raise MqError( f'Report {report_id} has failed for {self.id}. \ Please reach out to the Marquee team for assistance.' ) elif status == ReportStatus.cancelled: _logger.info( f'Report {report_id} has been cancelled. Please reach out to the \ Marquee team if you believe this is a mistake.' ) else: _logger.info(f'Report {report_id} is now complete') except Exception as err: raise MqError( f'Could not fetch report status with error {err}') raise MqError('The report is taking longer than expected to complete. \ Please check again later or reach out to the Marquee team for assistance.' )
def __edit_and_rebalance(self, edit_inputs: CustomBasketsEditInputs, rebal_inputs: CustomBasketsRebalanceInputs) -> CustomBasketsResponse: """ If updates require edit and rebalance, rebal will not be scheduled until/if edit report succeeds """ _logger.info('Current update request requires multiple reports. Your rebalance request will be submitted \ once the edit report has completed. Submitting basket edits now...') response = GsIndexApi.edit(self.id, edit_inputs) report_id = response.report_id self.__latest_create_report = GsReportApi.get_report(response.report_id) report_status = self.poll_report(report_id, timeout=600, step=15) if report_status != ReportStatus.done: raise MqError(f'The basket edit report\'s status is {status}. The current rebalance request will \ not be submitted in the meantime.') _logger.info('Your basket edits have completed successfuly. Submitting rebalance request now...') response = GsIndexApi.rebalance(self.id, rebal_inputs) return response
def test_get_report(mocker): id_1 = 'MP1' mock_response = Report.from_dict({'id': id_1, 'positionSourceType': 'Portfolio', 'positionSourceId': 'MP1', 'type': 'Portfolio Performance Analytics', 'parameters': {'transactionCostModel': 'FIXED'}}) # mock GsSession mocker.patch.object( GsSession.__class__, 'default_value', return_value=GsSession.get( Environment.QA, 'client_id', 'secret')) mocker.patch.object(GsSession.current, '_get', return_value=mock_response) # run test response = GsReportApi.get_report(id_1) GsSession.current._get.assert_called_with('/reports/{id}'.format(id=id_1), cls=Report) assert response == mock_response
def update(self) -> Dict: """ Update your custom basket :return: dictionary containing asset id and report id **Usage** Make updates to your basket's metadata, pricing options, publishing options, or composition **See also** :func:`get_details` :func:`poll_status` :func:`create` """ edit_inputs, rebal_inputs = self.__get_updates() entitlements = self.__entitlements.to_target() response = None if not entitlements == self.__initial_entitlements: response = GsAssetApi.update_asset_entitlements( self.id, entitlements) if edit_inputs is None and rebal_inputs is None: if response: return response.as_dict() raise MqValueError( 'Update failed: Nothing on the basket was changed') elif edit_inputs is not None and rebal_inputs is None: response = GsIndexApi.edit(self.id, edit_inputs) elif rebal_inputs is not None and edit_inputs is None: response = GsIndexApi.rebalance(self.id, rebal_inputs) else: response = self.__edit_and_rebalance(edit_inputs, rebal_inputs) gs_asset = GsAssetApi.get_asset(self.id) self.__latest_create_report = GsReportApi.get_report( response.report_id) self.__init__(gs_asset=gs_asset, _finish_init=True) return response.as_dict()
def get(cls, report_id: str, acceptable_types: List[ReportType] = None): return cls.from_target(GsReportApi.get_report(report_id))
def get_report_by_id(report_id: str) -> Report: """ Hits GsReportsApi to retrieve a report from id """ return GsReportApi.get_report(report_id)
def __init__(self, report_id: str): self.report = GsReportApi.get_report(report_id=report_id)