Cannot open session platform.rdp

Hi,

I am trying to use the EDP API and have created the .json file with credentials. However, I keep getting the same error:

KeyError: 'sessions.platform.rdp'

NameError: Cannot open session platform.rdp
This session is not defined in the configuration file

Please refer to attached snippets. In the .json file, I also tried removing the last two rows.

May you kindly guide me on how to proceed?

lseg-data config.png platform rdp error.png

Answers

  • Hello @l_abdilla

    The structure of JSON file is incorrect. You are using the LD Library, and should begin by using the examples and configuration provided with the package. This is the correct structure of the JSON configuration file. Please see this repo for more example notebooks.

    {
      "sessions": {
        "default": "platform.ldp",
        "platform": {
          "ldp": {
            "app-key": "YOUR APP KEY GOES HERE!",
            "username": "YOUR LDP LOGIN OR MACHINE GOES HERE!",
            "password": "YOUR LDP PASSWORD GOES HERE!"
          },
    

    and use -

    ld.open_session(name='platform.ldp')
    
  • l_abdilla
    l_abdilla Newcomer

    Thank you!

    Can you also confirm which modules (other than ownership) should be imported in Python to obtain the following fields that were previously obtained using the EIKON API, when using this data library?

    fields = [
    "TR.AssetCategory",
    "TR.AssetsUnderMgmtActual",
    "TR.AvgAssetsUnderMgmtActual",
    "TR.CompanyName",
    "TR.CountryOfIncorporation",
    "TR.ExpRatioActual",
    "TR.F.AssetsUnderMgmtAUM",
    "TR.FundAddrCountry",
    "TR.FundClassId",
    "TR.FundEarliestHoldDate",
    "TR.FundHoldingName",
    "TR.FundHoldingsDate",
    "TR.FundInceptionDate",
    "TR.FundLatestFilingDate",
    "TR.FundName",
    "TR.FundNumberOfShares",
    "TR.FundPctPortfolio",
    "TR.FundPercentageOfFundAssets",
    "TR.FundPortfolioName",
    "TR.FundSharesHeldValue",
    "TR.FundTER",
    "TR.FundTERDate",
    "TR.GICSCode",
    "TR.GICSSector",
    "TR.GICSIndustry",
    "TR.GICSSubIndustry",
    "TR.HistFdAdjPctOfShsOutHeld",
    "TR.InvParentType",
    "TR.InvestorFullName",
    "TR.ISINCode",
    "TR.LipperFundClassID",
    "TR.NUMBEROFSTOCKS",
    "TR.PEFundSFDRFundType",
    "TR.SICIndustry",
    "TR.ShareClass",
    "TR.SharesHeld",
    "TR.SharesHeldValue",
    "TR.ShareHeld",
    "TR.TR.FF12Industry",
    "TR.TR.FF12Sector",
    "TR.TR.FF12SubIndustry"
    ]

  • No additional imports should be necessary. The fields do not depend on any imported module - but rather the instrument that you are requesting data for.

  • l_abdilla
    l_abdilla Newcomer

    Thanks for clarifying.

    I am querying data for one fund as a test, as follows:

    fund_id = "LP68085723"

    response = ownership.fund.holdings.Definition(fund_id).get_data()

    df = response.data.df
    print(df.head())  

    However, a ScopeError is returned as follows:

    ScopeError Traceback (most recent call last)
    Cell In[9], line 3
    1 # Test query to confirm session is valid
    2 fund_id = "LP68085723"
    ----> 3 response = ownership.fund.holdings.Definition(fund_id).get_data()
    4 df = response.data.df
    6 print(df.head()) # If this prints, your session and token are working

    File ~\AppData\Roaming\Python\Python312\site-packages\lseg\data\content_content_provider_layer.py:51, in ContentUsageLoggerMixin.get_data(self, session)
    44 # Library usage logging
    45 get_usage_logger().log_func(
    46 name=f"{ModuleName.CONTENT}.{self._USAGE_CLS_NAME}.get_data",
    47 func_path=f"{self.class.module}.{self.class.qualname}.get_data",
    48 kwargs={**self._kwargs},
    49 desc={FilterType.SYNC, FilterType.LAYER_CONTENT},
    50 )
    ---> 51 return super().get_data(session)

    File ~\AppData\Roaming\Python\Python312\site-packages\lseg\data\delivery_data_data_provider_layer.py:139, in DataProviderLayer.get_data(self, session)
    125 """
    126 Sends a request to the client file store to retrieve the previously defined data.
    127
    (...)
    136
    137 """
    138 session = get_valid_session(session)
    --> 139 response = get_data(self._data_type, self._provider, session, **self._kwargs)
    140 _check_response(response, session.config)
    141 return response

    File ~\AppData\Roaming\Python\Python312\site-packages\lseg\data\delivery_data_data_provider_layer.py:50, in get_data(data_type, provider, session, **kwargs)
    43 # Library usage logging
    44 get_usage_logger().log_func(
    45 name=f"{ModuleName.DELIVERY}.{DataProviderLayer._USAGE_CLS_NAME}.get_data",
    46 func_path=f"{DataProviderLayer.module}.{DataProviderLayer.qualname}.get_data",
    47 kwargs={"url": url, "auto_retry": auto_retry, **kwargs},
    48 desc={FilterType.SYNC, FilterType.LAYER_DELIVERY},
    49 )
    ---> 50 response = provider.get_data(session, url, auto_retry=auto_retry, **kwargs)
    51 return response

    File ~\AppData\Roaming\Python\Python312\site-packages\lseg\data\content\ownership_ownership_data_provider.py:80, in OwnershipDataProvider.get_data(self, *args, **kwargs)
    77 limit = kwargs.get("limit")
    79 if limit is None:
    ---> 80 response = super().get_data(*args, **kwargs)
    82 else:
    83 responses = []

    File ~\AppData\Roaming\Python\Python312\site-packages\lseg\data\delivery_data_data_provider.py:81, in DataProvider.get_data(self, session, *args, **kwargs)
    79 request = self.request.create(session, *args, **kwargs)
    80 raw_response = self.connection.send(request, session, *args, **kwargs)
    ---> 81 return self._process_response(raw_response, request, session, *args, **kwargs)

    File ~\AppData\Roaming\Python\Python312\site-packages\lseg\data\delivery_data_data_provider.py:73, in DataProvider._process_response(self, raw_response, base_request, session, *args, **kwargs)
    64 def _process_response(
    65 self,
    66 raw_response: "httpx.Response",
    (...)
    70 **kwargs,
    71 ) -> Response:
    72 is_success, parsed_data = self.parser.parse_raw_response(raw_response)
    ---> 73 self._handle_scope_error(base_request, session, parsed_data)
    74 is_success = is_success and self.validator.validate(parsed_data)
    75 return self.response.create_response(is_success, parsed_data=parsed_data, session=session, **kwargs)

    File ~\AppData\Roaming\Python\Python312\site-packages\lseg\data\delivery_data_data_provider.py:58, in DataProvider._handle_scope_error(self, request, session, parsed_data)
    56 def _handle_scope_error(self, request: Request, session: "Session", parsed_data):
    57 if 403 in parsed_data.error_codes:
    ---> 58 session._handle_insufficient_scope(
    59 request.path,
    60 request.method,
    61 parsed_data.status.get("error", {}).get("message"),
    62 )

    File ~\AppData\Roaming\Python\Python312\site-packages\lseg\data_core\session_platform_session.py:270, in PlatformSession._handle_insufficient_scope(self, path, method, message)
    268 required_scopes = [set(i.split()) for i in required_scope_groups]
    269 self._connection.auth_manager.set_scope(path, method, required_scopes)
    --> 270 raise ScopeError(
    271 required_scopes,
    272 self._connection.auth_manager._token_info.scope,
    273 path,
    274 method,
    275 )

    ScopeError: Insufficient scope for key=/data/ownership/v1/views/fund/holdings, method=GET.
    Required scopes: {'trapi.data.ownership.adv'} OR {'trapi.demo-access'}
    Available scopes: {'trapi.alerts.publication.crud', 'trapi.frtb.sentimarization', 'trapi.search.metadata.read', 'trapi.graphql.subscriber.access', 'trapi.user-framework.recently-used.crud', 'trapi.platform.iam.guiss', 'trapi.auth.cloud-credentials', 'trapi.search.lookup.read', 'trapi.data.get.data.read', 'trapi.user-framework.workspace.crud', 'trapi.commodities.yesenergy.read', 'trapi.streaming.synthetic.read', 'trapi.data.quantitative-analytics.read', 'trapi.alerts.subscription.crud', 'trapi.searchcore.metadata.read', 'trapi.streaming.pricing.read', 'trapi.user-framework.mobile.crud', 'trapi.alerts.history.crud', 'trapi.platform.iam.acl_service', 'trapi.sdbold', 'trapi.streaming.prcperf.read', 'trapi.user-framework.application-metadata.raplib', 'trapi.data.benchmark.bmk_read', 'trapi.search.explore.read', 'trapi.data.historical-pricing.events.read', 'trapi.search.read', 'trapi.alerts.preferences.crud', 'trapi.data.historical-pricing.summaries.read', 'trapi.searchcore.read', 'trapi.searchcore.lookup.read', 'trapi.data.average-volume-analytics.ava_read', 'trapi.synthetic.crud'}
    Missing scopes: {'trapi.data.ownership.adv'} OR {'trapi.demo-access'}

    I was preiously retrieving ownership data using the EIKON API. However, when I now raise queries using the the security ISINs, no data is returned. This is the reason why I am trying to switch to the above-mentioned.

    Does the above reflect an access rights issue?

    Thanks!

  • Jirapongse
    Jirapongse ✭✭✭✭✭

    @l_abdilla

    According to the error, it is a permission issue.

    ScopeError: Insufficient scope for key=/data/ownership/v1/views/fund/holdings, method=GET.
    Required scopes: {'trapi.data.ownership.adv'} OR {'trapi.demo-access'}

    The account doesn't have permission to access the /data/ownership/v1/views/fund/holdings service.

    Please contact your LSEG account team or Sales team directly to verify this.