Environment
- LSEG Data Library for Python (lseg.data / formerly refinitiv.data)
- Portfolio Analytics (PAL) via the portfolio-analytics and o-management endpoints
- Python 3.11, running in CodeBook
What I'm building
I reconstruct a portfolio's closed positions (fully sold or redeemed in the past) from PAL transaction history, so I can produce a per-trade realized-P&L report. For each closed position I need the instrument identity (ISIN, issuer, coupon, maturity) to compute and label the trade.
How identification normally works (and works fine for ~85% of positions)
For active and most closed positions, I get the instrument identity from PAL holdings statements - each holdings snapshot lists the instrument with its issueName/ISIN. I match a transaction to a position via a shared internal id, and the position already carries its ISIN from the holdings snapshot. This works well.
The problem (the remaining ~15%)
Some positions were opened and fully closed between two holdings-snapshot dates. PAL apparently never took a holdings snapshot while these instruments were held, so they never appear in any holdings statement on any date. For these, the transaction record is the only trace - and the transaction's instrument reference contains only an internal TOPAS identifier, with no ISIN/CUSIP/RIC and an empty name.
Concretely, the transaction's symbol/security item looks like:
<iframe>
{"securityItem": {"symbolValues": [{ "type": "TOPASId", "value": "150462714" }]}}
That's the entire instrument reference - type: "TOPASId" and a numeric value, nothing else.
What I've already tried (and ruled out)
<iframe />
- Holdings densification - I scanned the full set of available holdings dates, then added targeted extra dates around each transaction window (100+ extra dates). The instrument's TOPASId is simply absent from holdingsDetails on every probed date. PAL does not appear to retain it anywhere in holdings.
- Ticker / name heuristics - not viable; these transactions carry no name, ticker, ISIN, or CUSIP at all.
- Manual mapping - works but is not scalable and defeats the purpose of automation.
The question
Is there a supported way to resolve a PAL TOPASId to a standard instrument identifier (ISIN / RIC / PermID), outside the PAL holdings endpoint?
Specifically:
- Does lseg.data symbology / symbol_conversion accept a TOPASId as an input identifier type? If so, what is the correct from_symbol_type (or equivalent) value?
- Is TOPASId queryable via the Search / discovery API (e.g. as an indexed field), so I could look the instrument up by that id?
- Is there any other endpoint that maps PAL's internal TOPAS identifier to a public identifier - given that the instrument does exist in LSEG's universe (it's an LSEG-internal id), it's only the PAL portfolio endpoint that doesn't surface its public identifiers for these closed-out trades?
Minimal anonymized example of what I'd like to achieve
import lseg.data as ldld.open_session()
This is the only identifier I have for a closed-out position:
topas_id = "150462714" # PAL transaction securityItem -> symbolValues -> type "TOPASId"
DESIRED: resolve TOPASId -> ISIN / RIC, without needing a PAL holdings snapshot.
Attempt A - symbol conversion (does TOPASId work as a from-type here?):
res = ld.symbol_conversion.Definition(symbols=[topas_id],from_symbol_type="???", # <-- is there a value that means "TOPASId"?to_symbol_types=["ISIN", "RIC"],).get_data()print(res.data.df)
Attempt B - search by the id as a query / property:
res2 = ld.discovery.search(query=topas_id,# or filter=f"TOPASId eq '{topas_id}'" <-- is TOPASId a searchable field?)print(res2)
ld.close_session()
I'm looking for either:
- the correct symbol-type / field to make one of the above work, or
- confirmation that PAL does not retain identification for positions closed entirely between holdings snapshots, so that a manual mapping is the only option.
Any pointers from people who've dealt with TOPAS internal ids or PAL transaction-level enrichment would be much appreciated.
Thank you.