Пример #1
0
 def get(cls, portfolio_id: str = None, portfolio_name: str = None):
     if portfolio_name:
         portfolio = GsPortfolioApi.get_portfolio_by_name(portfolio_name)
         portfolio_id = portfolio.id
     position_date = PositionContext.current.position_date if PositionContext.is_entered else dt.date.today(
     )
     portfolio = GsPortfolioApi.get_portfolio(portfolio_id)
     ret = Portfolio(name=portfolio.name)
     ret.__id = portfolio_id
     ret._get_instruments(position_date, True)
     return ret
Пример #2
0
 def _schedule_reports(self,
                       start_date,
                       end_date,
                       backcast: bool = False,
                       show_progress: bool = True):
     GsPortfolioApi.schedule_reports(portfolio_id=self.id,
                                     start_date=start_date,
                                     end_date=end_date,
                                     backcast=backcast)
     if show_progress:
         self._show_report_progress()
Пример #3
0
 def from_portfolio_id(portfolio_id: str, date=None):
     portfolio = GsPortfolioApi.get_portfolio(portfolio_id)
     response = GsPortfolioApi.get_positions_for_date(portfolio_id, date) if date else \
         GsPortfolioApi.get_latest_positions(portfolio_id)
     response = response[0] if isinstance(response, tuple) else response
     positions = response.positions if isinstance(
         response, PositionSet) else response['positions']
     instruments = GsAssetApi.get_instruments_for_positions(positions)
     ret = Portfolio(instruments, name=portfolio.name)
     ret.__id = portfolio_id
     return ret
Пример #4
0
 def schedule_reports(self,
                      start_date: dt.date = None,
                      end_date: dt.date = None,
                      backcast: bool = False):
     if None in [start_date, end_date]:
         suggested_schedule_dates = self.get_schedule_dates(backcast)
         start_date = start_date if start_date else suggested_schedule_dates[
             0]
         end_date = end_date if end_date else suggested_schedule_dates[1]
     GsPortfolioApi.schedule_reports(self.__portfolio_id,
                                     start_date,
                                     end_date,
                                     backcast=backcast)
Пример #5
0
 def _get_instruments(self, position_date: dt.date, in_place: bool, return_priceables: bool = True):
     if self.id:
         dates_prior = list(filter(lambda date: date < position_date,
                                   GsPortfolioApi.get_position_dates(self.id)))
         if len(dates_prior) == 0:
             raise ValueError('Your portfolio has no positions on the PositionContext date')
         date = max(dates_prior)
         response = GsPortfolioApi.get_positions_for_date(self.id, date)
         positions = response.positions if response else []
         instruments = GsAssetApi.get_instruments_for_positions(positions)
         if in_place:
             self.__priceables = instruments
         return instruments
     return self.__priceables if return_priceables else self.all_instruments
Пример #6
0
def test_get_many_portfolios(mocker):
    id_1 = 'MP1'
    id_2 = 'MP2'

    mock_response = {'results': (
        Portfolio.from_dict({'id': id_1, 'currency': 'USD', 'name': 'Example Port 1'}),
        Portfolio.from_dict({'id': id_2, 'currency': 'USD', 'name': 'Example Port 2'})
    ), 'totalResults': 2}

    expected_response = (
        Portfolio(id=id_1, currency='USD', name='Example Port 1'),
        Portfolio(id=id_2, currency='USD', name='Example Port 2')
    )

    # 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 = GsPortfolioApi.get_portfolios()
    GsSession.current._get.assert_called_with('/portfolios?&limit=100', cls=Portfolio)
    assert response == expected_response
Пример #7
0
 def upload_custom_aum(self,
                       aum_data: List[CustomAUMDataPoint],
                       clear_existing_data: bool = None):
     """
     Add AUM data for portfolio
     :param aum_data: list of AUM data to upload
     :param clear_existing_data: delete all previously uploaded AUM data for the portfolio
     (defaults to false)
     :return:
     """
     formatted_aum_data = [{
         'date': data.date.strftime('%Y-%m-%d'),
         'aum': data.aum
     } for data in aum_data]
     GsPortfolioApi.upload_custom_aum(self.portfolio_id, formatted_aum_data,
                                      clear_existing_data)
Пример #8
0
def pnl(portfolio_id: str,
        start_date: dt.date = None,
        end_date: dt.date = None,
        *,
        source: str = None,
        real_time: bool = False,
        request_id: Optional[str] = None) -> pd.Series:
    """
    Returns the PnL of a portfolio
    :param portfolio_id: id of portfolio
    :param start_date: start date for getting pnl
    :param end_date: end date for getting pnl
    :param source: name of function caller
    :param real_time: whether to retrieve intraday data instead of EOD
    :param request_id: server request id
    :return: portfolio pnl values
    """

    reports = GsPortfolioApi.get_reports(portfolio_id)
    performance_report_id = ""
    for report in reports:
        if report.type == ReportType.Portfolio_Performance_Analytics:
            performance_report_id = report.id
    data = PerformanceReport.get_pnl(performance_report_id, start_date,
                                     end_date)
    df = pd.DataFrame.from_records(data)
    df.set_index('date', inplace=True)
    return _extract_series_from_df(df, QueryType.PNL, True)
Пример #9
0
def test_get_latest_portfolio_positions(mocker):
    id_1 = 'MP1'
    date = dt.date(2019, 2, 18)

    mock_response = {'results': (
        PositionSet.from_dict({
            'id': 'mock1',
            'positionDate': '2019-02-18',
            'lastUpdateTime': '2019-02-19T12:10:32.401Z',
            'positions': [
                {'assetId': 'MQA123', 'quantity': 0.3},
                {'assetId': 'MQA456', 'quantity': 0.7}
            ]
        }),
    )}

    expected_response = (
        PositionSet('mock1', date, dup.parse('2019-02-19T12:10:32.401Z'), (
            Position(assetId='MQA123', quantity=0.3),
            Position(assetId='MQA456', quantity=0.7)
        ))
    )

    # mock GsSession
    mocker.patch.object(GsSession.__class__, 'current', return_value=GsSession.get(Environment.QA, 'client_id', 'secret'))
    mocker.patch.object(GsSession.current, '_get', return_value=mock_response)

    # run test
    response = GsPortfolioApi.get_latest_positions(id_1)

    GsSession.current._get.assert_called_with('/portfolios/{id}/positions/last?type=close'.format(id=id_1), cls=PositionSet)

    assert response == expected_response
Пример #10
0
    def get(cls, portfolio_id: str = None, name: str = None, **kwargs):
        if portfolio_id is None and name is None:
            raise MqValueError(
                'Please specify a portfolio ID and/or portfolio name.')

        portfolios = GsPortfolioApi.get_portfolios(
            portfolio_ids=[portfolio_id] if portfolio_id else None,
            portfolio_names=[name] if name else None)
        if len(portfolios) == 0:
            raise ValueError(
                'No portfolios in Marquee match the requested name and/or ID.')
        if len(portfolios) > 1:
            portfolios = {
                'Name': [p.name for p in portfolios],
                'ID': [p.id for p in portfolios],
                'Created Time': [p.created_time for p in portfolios]
            }
            cls._print_dict(portfolios)
            raise ValueError(
                'More than one portfolio matches the requested name and/or ID. To resolve,'
                ' please find the correct portfolio ID below and set it as your portfolio_id.'
            )
        port = portfolios[0]
        return Portfolio(name=port.name,
                         portfolio_id=port.id,
                         currency=port.currency,
                         entitlements=Entitlements.from_target(
                             port.entitlements))
Пример #11
0
 def from_portfolio_id(portfolio_id: str):
     response = GsPortfolioApi.get_latest_positions(portfolio_id)
     positions = response.positions if isinstance(response, PositionSet) else response['positions']
     instruments = GsAssetApi.get_instruments_for_positions(positions)
     ret = Portfolio(instruments)
     ret.name = portfolio_id
     return ret
Пример #12
0
 def get_aum_source(self) -> RiskAumSource:
     """
     Get portfolio AUM Source
     :return: AUM Source
     """
     portfolio = GsPortfolioApi.get_portfolio(self.portfolio_id)
     return portfolio.aum_source if portfolio.aum_source is not None else RiskAumSource.Long
Пример #13
0
 def get_schedule_dates(self, backcast: bool = False) -> List[dt.date]:
     """
     Get recommended start and end dates for a portfolio report scheduling job
     :param backcast: true if reports should be backcasted
     :return: a list of two dates, the first is the suggested start date and the second is the suggested end date
     """
     return GsPortfolioApi.get_schedule_dates(self.id, backcast)
Пример #14
0
 def schedule(self,
              start_date: dt.date = None,
              end_date: dt.date = None,
              backcast: bool = None):
     if None in [self.id, self.__position_source_id]:
         raise MqValueError(
             'Can only schedule reports with valid IDs and Position Source IDs.'
         )
     if self.position_source_type != PositionSourceType.Portfolio and None in [
             start_date, end_date
     ]:
         raise MqValueError(
             'Must specify schedule start and end dates for report.')
     if None in [start_date, end_date]:
         position_dates = GsPortfolioApi.get_position_dates(
             self.position_source_id)
         if len(position_dates) == 0:
             raise MqValueError(
                 'Cannot schedule reports for a portfolio with no positions.'
             )
         if start_date is None:
             start_date = business_day_offset(min(position_dates) - relativedelta(years=1), -1, roll='forward') \
                 if backcast else min(position_dates)
         if end_date is None:
             end_date = min(
                 position_dates) if backcast else business_day_offset(
                     dt.date.today(), -1, roll='forward')
     GsReportApi.schedule_report(report_id=self.id,
                                 start_date=start_date,
                                 end_date=end_date,
                                 backcast=backcast)
Пример #15
0
    def _create(self):
        # If a priceables portfolio, try resolving to MQ portfolio
        if self.__priceables:
            self.save()
            self.priceables = None
            return

        # If a positions portfolio, create using MQ API
        port = GsPortfolioApi.create_portfolio(
            portfolio=MQPortfolio(name=self.name,
                                  currency=self.currency,
                                  entitlements=self.entitlements.to_target()))
        PositionedEntity.__init__(self, port.id, EntityType.PORTFOLIO)
        Entity.__init__(self, port.id, EntityType.PORTFOLIO)
        self.__id = port.id
        self._PositionedEntity__entity_type = EntityType.PORTFOLIO
        self.entitlements = Entitlements.from_target(port.entitlements)
        self.currency = Currency(port.currency)

        # If the portfolio contains positions, upload them to the MQ portfolio and schedule reports
        if self.position_sets:
            position_sets = self.position_sets
            self.position_sets = None
            self.update_positions(position_sets, False)
            self._schedule_first_reports(
                [pos_set.date for pos_set in position_sets])
            self.position_sets = None
Пример #16
0
 def get_entitlements(self) -> Entitlements:
     if self.positioned_entity_type == EntityType.PORTFOLIO:
         response = GsPortfolioApi.get_portfolio(self.id)
     elif self.positioned_entity_type == EntityType.ASSET:
         response = GsAssetApi.get_asset(self.id)
     else:
         raise NotImplementedError
     return Entitlements.from_target(response.entitlements)
Пример #17
0
    def save(self):
        if not self.name:
            raise ValueError('name not set')

        try:
            portfolio_id = GsPortfolioApi.get_portfolio_by_name(self.name).id
        except ValueError:
            from gs_quant.target.portfolios import Portfolio as MarqueePortfolio
            portfolio_id = GsPortfolioApi.create_portfolio(MarqueePortfolio('USD', self.name)).id
            _logger.info('Created Marquee portfolio with ID: {}'.format(portfolio_id))

        position_set = PositionSet(
            position_date=dt.date.today(),
            positions=tuple(Position(asset_id=GsAssetApi.get_or_create_asset_from_instrument(i))
                            for i in self.instruments))

        GsPortfolioApi.update_positions(portfolio_id, (position_set,))
Пример #18
0
    def save(self, overwrite: Optional[bool] = False):
        if self.portfolios:
            raise ValueError('Cannot save portfolios with nested portfolios')

        if self.__id:
            if not overwrite:
                raise ValueError(f'Portfolio with id {id} already exists. Use overwrite=True to overwrite')
        else:
            if not self.name:
                raise ValueError('name not set')
            self.__id = GsPortfolioApi.create_portfolio(MarqueePortfolio('USD', self.name)).id
            _logger.info(f'Created Marquee portfolio {self.name} with id {self.__id}')

        position_set = PositionSet(
            position_date=self.__position_context.position_date,
            positions=tuple(Position(asset_id=GsAssetApi.get_or_create_asset_from_instrument(i))
                            for i in self.instruments))
        if len(position_set.positions) > 0:
            GsPortfolioApi.update_positions(self.__id, [position_set])
Пример #19
0
 def get_positions_data(self,
                        start: dt.date = DateLimit.LOW_LIMIT.value,
                        end: dt.date = dt.date.today(),
                        fields: [str] = None,
                        position_type: PositionType = PositionType.CLOSE) -> List[Dict]:
     if self.positioned_entity_type == EntityType.ASSET:
         return GsAssetApi.get_asset_positions_data(self.id, start, end, fields, position_type)
     if self.positioned_entity_type == EntityType.PORTFOLIO:
         return GsPortfolioApi.get_positions_data(self.id, start, end, fields, position_type)
     raise NotImplementedError
Пример #20
0
 def get_latest_position_set(self,
                             position_type: PositionType = PositionType.CLOSE) -> PositionSet:
     if self.positioned_entity_type == EntityType.ASSET:
         response = GsAssetApi.get_latest_positions(self.id, position_type)
         return PositionSet.from_target(response)
     if self.positioned_entity_type == EntityType.PORTFOLIO:
         response = GsPortfolioApi.get_latest_positions(portfolio_id=self.id,
                                                        position_type=position_type.value)
         return PositionSet.from_target(response)
     raise NotImplementedError
Пример #21
0
def test_get_portfolio_positions(mocker):
    id_1 = 'MP1'
    start_date = dt.date(2019, 2, 18)
    end_date = dt.date(2019, 2, 19)

    mock_response = {'positionSets': (
        {
            'id': 'mock1',
            'positionDate': '2019-02-18',
            'lastUpdateTime': '2019-02-19T12:10:32.401Z',
            'positions': [
                {'assetId': 'MQA123', 'quantity': 0.3},
                {'assetId': 'MQA456', 'quantity': 0.7}
            ]
        },
        {
            'id': 'mock2',
            'positionDate': '2019-02-19',
            'lastUpdateTime': '2019-02-20T05:04:32.981Z',
            'positions': [
                {'assetId': 'MQA123', 'quantity': 0.4},
                {'assetId': 'MQA456', 'quantity': 0.6}
            ]
        }
    )}

    expected_response = (
        PositionSet('mock1', start_date, dup.parse('2019-02-19T12:10:32.401Z'), (
            Position(assetId='MQA123', quantity=0.3),
            Position(assetId='MQA456', quantity=0.7)
        )),
        PositionSet('mock2', end_date, dup.parse('2019-02-20T05:04:32.981Z'), (
            Position(assetId='MQA123', quantity=0.4),
            Position(assetId='MQA456', quantity=0.6)
        ))
    )

    # mock GsSession
    mocker.patch.object(
        GsSession.__class__,
        'current',
        return_value=GsSession.get(
            Environment.QA,
            'client_id',
            'secret'))
    mocker.patch.object(GsSession.current, '_get', return_value=mock_response)

    # run test
    response = GsPortfolioApi.get_positions(id_1, start_date, end_date)

    GsSession.current._get.assert_called_with(
        '/portfolios/{id}/positions?type=close&startDate={sd}&endDate={ed}'.format(id=id_1, sd=start_date, ed=end_date))

    assert response == expected_response
Пример #22
0
 def update_positions(self,
                      position_sets: List[PositionSet],
                      net_positions: bool = True):
     if self.positioned_entity_type == EntityType.PORTFOLIO:
         if not position_sets:
             return
         currency = GsPortfolioApi.get_portfolio(self.id).currency
         new_sets = []
         for pos_set in position_sets:
             if pos_set.reference_notional is None:
                 incorrect_set = any([pos.quantity is None or pos.weight is not None for pos in pos_set.positions])
                 if incorrect_set:
                     raise MqValueError('If you would like to upload position sets without notionals, '
                                        'every position must have a quantity and cannot have a weight.')
                 new_sets.append(pos_set)
             else:
                 new_sets.append(self._convert_pos_set_with_weights(pos_set, currency))
         GsPortfolioApi.update_positions(portfolio_id=self.id, position_sets=[p.to_target() for p in new_sets])
         time.sleep(3)
     else:
         raise NotImplementedError
Пример #23
0
 def update_positions(self,
                      position_sets: List[PositionSet],
                      schedule_reports: bool = True):
     if self.positioned_entity_type == EntityType.PORTFOLIO:
         if not position_sets:
             return
         existing_positions_dates = self.get_position_dates()
         new_position_dates = [p.date for p in position_sets] if position_sets else []
         reports = [r.latest_end_date for r in self.get_reports() if r.latest_end_date]
         latest_date_covered_by_reports = min(reports) if reports else None
         latest_position_date_in_reports = max([d for d in existing_positions_dates
                                                if d <= latest_date_covered_by_reports]) \
             if latest_date_covered_by_reports else min(new_position_dates)
         start_date = min(latest_position_date_in_reports, min(new_position_dates))
         end_date = max(new_position_dates)
         GsPortfolioApi.update_positions(portfolio_id=self.id, position_sets=[p.to_target() for p in position_sets])
         if schedule_reports:
             self._schedule_reports(start_date=start_date,
                                    end_date=end_date)
     else:
         raise NotImplementedError
Пример #24
0
 def get_position_set_for_date(self,
                               date: dt.date,
                               position_type: PositionType = PositionType.CLOSE) -> PositionSet:
     if self.positioned_entity_type == EntityType.ASSET:
         response = GsAssetApi.get_asset_positions_for_date(self.id, date, position_type)[0]
         return PositionSet.from_target(response)
     if self.positioned_entity_type == EntityType.PORTFOLIO:
         response = GsPortfolioApi.get_positions_for_date(portfolio_id=self.id,
                                                          position_date=date,
                                                          position_type=position_type.value)
         return PositionSet.from_target(response) if response else None
     raise NotImplementedError
Пример #25
0
    def save_as_quote(self, overwrite: Optional[bool] = False) -> str:
        if self.portfolios:
            raise ValueError('Cannot save portfolios with nested portfolios')

        request = RiskRequest(
            tuple(RiskPosition(instrument=i, quantity=i.instrument_quantity) for i in self.instruments),
            (ResolvedInstrumentValues,),
            pricing_and_market_data_as_of=(PricingDateAndMarketDataAsOf(pricing_date=self._pricing_context.pricing_date,
                                                                        market=self._pricing_context.market),)
        )

        if self.__quote_id:
            if not overwrite:
                raise ValueError(f'Quote with id {self.__quote_id} already exists. Use overwrite=True to overwrite')
            else:
                GsPortfolioApi.update_quote(self.__quote_id, request)
                _logger.info(f'Updated quote with id {self.__quote_id}')
        else:
            self.__quote_id = GsPortfolioApi.save_quote(request)
            _logger.info(f'Created quote with id {self.__quote_id}')
        return self.__quote_id
Пример #26
0
    def save_to_shadowbook(self, name: str):
        if self.portfolios:
            raise ValueError('Cannot save portfolios with nested portfolios')

        request = RiskRequest(
            tuple(RiskPosition(instrument=i, quantity=i.instrument_quantity) for i in self.instruments),
            (ResolvedInstrumentValues,),
            pricing_and_market_data_as_of=(PricingDateAndMarketDataAsOf(pricing_date=self._pricing_context.pricing_date,
                                                                        market=self._pricing_context.market),)
        )
        status = GsPortfolioApi.save_to_shadowbook(request, name)
        print(f'Save to shadowbook status - {status}')
Пример #27
0
def test_get_portfolio(mocker):
    id_1 = 'MP1'
    mock_response = Portfolio(id=id_1, currency='USD', name='Example Port')

    # mock GsSession
    mocker.patch.object(GsSession.__class__, 'current', return_value=GsSession.get(Environment.QA, 'client_id', 'secret'))
    mocker.patch.object(GsSession.current, '_get', return_value=mock_response)

    # run test
    response = GsPortfolioApi.get_portfolio(id_1)
    GsSession.current._get.assert_called_with('/portfolios/{id}'.format(id=id_1), cls=Portfolio)
    assert response == mock_response
Пример #28
0
 def get_position_sets(self,
                       start: dt.date = DateLimit.LOW_LIMIT.value,
                       end: dt.date = dt.date.today(),
                       position_type: PositionType = PositionType.CLOSE) -> List[PositionSet]:
     if self.positioned_entity_type == EntityType.ASSET:
         response = GsAssetApi.get_asset_positions_for_dates(self.id, start, end, position_type)
         return [PositionSet.from_target(position_set) for position_set in response]
     if self.positioned_entity_type == EntityType.PORTFOLIO:
         response = GsPortfolioApi.get_positions(portfolio_id=self.id,
                                                 start_date=start,
                                                 end_date=end)
         return [PositionSet.from_target(position_set) for position_set in response]
     raise NotImplementedError
Пример #29
0
def test_delete_portfolio(mocker):
    id_1 = 'MP1'

    mock_response = "Successfully deleted portfolio."

    # mock GsSession
    mocker.patch.object(GsSession.__class__, 'current', return_value=GsSession.get(Environment.QA, 'client_id', 'secret'))
    mocker.patch.object(GsSession.current, '_delete', return_value=mock_response)

    # run test
    response = GsPortfolioApi.delete_portfolio(id_1)
    GsSession.current._delete.assert_called_with('/portfolios/{id}'.format(id=id_1))
    assert response == mock_response
Пример #30
0
def test_create_portfolio(mocker):
    id_1 = 'MP1'

    portfolio = Portfolio(id=id_1, currency='USD', name='Example Port')

    # mock GsSession
    mocker.patch.object(GsSession.__class__, 'current', return_value=GsSession.get(Environment.QA, 'client_id', 'secret'))
    mocker.patch.object(GsSession.current, '_post', return_value=portfolio)

    # run test
    response = GsPortfolioApi.create_portfolio(portfolio)
    GsSession.current._post.assert_called_with('/portfolios', portfolio, cls=Portfolio)
    assert response == portfolio