Entitlement IDs
return_eids=True on bdp, bds, bdh, bdib, and bdtick.
Entitlements and provenance
Opt in to entitlement IDs, check them against the authorized identity, flag delayed data per security, and keep the Bloomberg support RequestId behind every result.
return_eids=True on bdp, bds, bdh, bdib, and bdtick.
seat_type, check_entitlements, and identity_is_authorized for the engine's authorized identity.
delay_status per security, and on_delayed on requests.
SDK-assigned request IDs on results and on request and timeout errors.
All of these work on the global engine or inside a scoped with xbbg.Engine(...) block. Every helper has an a-prefixed async twin.
Bloomberg returns entitlement IDs (EIDs) only for four request operations, and only when asked. Opt in with return_eids=True:
| Bloomberg operation | Python routes |
|---|---|
ReferenceDataRequest | bdp, bds (BDS uses the reference-data operation) |
HistoricalDataRequest | bdh |
IntradayBarRequest | bdib |
IntradayTickRequest | bdtick |
request() and arequest() accept return_eids=True for the same four operations. Any other operation raises BlpValidationError before anything is sent.
import xbbg
ticks = xbbg.bdtick(
"AAPL US Equity",
"2024-01-15T09:30:00",
"2024-01-15T10:00:00",
return_eids=True,
backend="native",
)
eid_data = ticks.eid_data or {}
eids = sorted({eid for security_eids in eid_data.values() for eid in security_eids})
if eids:
report = xbbg.check_entitlements(eids)
print(report.entitled, report.failed_eids)eid_data maps each security to its list of EIDs. Where it lives depends on the backend:
| Backend | Read EIDs from |
|---|---|
native | table.eid_data (None when absent) |
pandas | frame.attrs["xbbg_eid_data"] |
pyarrow | json.loads(table.schema.metadata[b"xbbg.eid_data"]) |
polars, duckdb | Not available; these libraries have no stable metadata side channel |
Use the native, PyArrow, or pandas backend whenever you need EIDs (see Output backends).
delay_status reports its feed EIDs instead.EID field that subscription messages carry.import xbbg
print(xbbg.seat_type()) # "BPS", "NONBPS", or "INVALID"
print(xbbg.identity_is_authorized()) # //blp/refdata
print(xbbg.identity_is_authorized("//blp/mktdata"))| Sync | Async | Returns |
|---|---|---|
seat_type() | aseat_type() | "BPS", "NONBPS", or "INVALID" |
check_entitlements(eids, service="//blp/refdata") | acheck_entitlements(...) | Report with entitled (True only when every EID is entitled) and failed_eids (the EIDs the identity lacks) |
identity_is_authorized(service="//blp/refdata") | aidentity_is_authorized(...) | bool |
The engine authorizes its identity lazily on first use: the configured authentication (configure(auth_method=...), see Configuration) when present, otherwise the Desktop Terminal's OS-logon user. The first call can take a moment, and a timeout during that first authorization can be retried.
Bloomberg serves delayed data to sessions without a real-time entitlement for an exchange, and requests neither fail nor flag it: bdp returns delayed snapshot values, bdh returns a delayed row for today, and bdib/bdtick stop the delay period before now.
delay_status import xbbg
status = xbbg.delay_status(["AAPL US Equity", "VOD LN Equity", "CL1 Comdty"])delay_status(tickers, *, check_identity=False, backend=None) (async: adelay_status) sends one reference-data request for IS_DELAYED_STREAM, EXCHANGE_DELAY, EXCH_CODE, FEED_EID1 to FEED_EID4, and FEED_DELAYED_EID1. It works on any Desktop, Server API, or B-PIPE session, keeps input order, and drops duplicates. One row per security:
| Column | Meaning |
|---|---|
ticker | The security (security when the engine uses key_column="security") |
delayed | This session receives delayed data (null when Bloomberg did not say) |
delay_minutes | Minutes behind real time; null when real time or unparseable |
exchange_delay | Bloomberg's EXCHANGE_DELAY text, which also names the delay a real-time security would have |
exch_code | Exchange code |
realtime_eid1 to realtime_eid4 | Real-time feed EIDs (FEED_EID1 to FEED_EID4) |
delayed_eid | Delayed feed EID (FEED_DELAYED_EID1) |
realtime_entitled, delayed_entitled | Identity check results; null unless check_identity=True |
error | Bloomberg's security error message, if any |
Bloomberg reports the feed EIDs even when it withholds them from return_eids results. check_identity=True checks them against the engine's authorized identity on //blp/mktdata and fills realtime_entitled (every real-time EID is entitled) and delayed_entitled. It needs SAPI/B-PIPE authorization through configure(auth_method=...) or a Desktop user enrolled in EMRS; otherwise the call raises Bloomberg's identity error.
on_delayed bdp, bdh, bdib, and bdtick accept on_delayed:
| Value | Behavior |
|---|---|
None (default) | No check |
"warn" | One BlpDelayedDataWarning per delayed security |
"raise" | BlpRequestError naming the delayed securities (up to ten, then "and N more") |
"ignore" | Status recorded in the result metadata only |
bdp reads the status from the same request; the status fields are added to the wire request and never appear as rows.bdh makes one extra reference-data request alongside the data, and only when end_date is on or after yesterday (UTC).bdib and bdtick make the extra request only when the requested window ends within the last 24 hours.bds has no on_delayed. request()/arequest() accept it for bdp-shaped ReferenceDataRequest, HistoricalDataRequest, IntradayBarRequest, and IntradayTickRequest; bulk reference requests and other operations raise BlpValidationError, as do values other than the three policies (matched case-insensitively).import warnings
import xbbg
with warnings.catch_warnings(record=True) as caught:
warnings.simplefilter("always", xbbg.BlpDelayedDataWarning)
prices = xbbg.bdp(["AAPL US Equity", "VOD LN Equity"], "PX_LAST", on_delayed="warn", backend="native")
print(prices.delayed) # {ticker: {"delayed": bool, "delay_minutes": int | None}}
print([str(warning.message) for warning in caught])
try:
history = xbbg.bdh("VOD LN Equity", "PX_LAST", "2024-01-02", on_delayed="raise")
except xbbg.BlpRequestError as exc:
print(exc)The status is stored under the xbbg.delayed metadata key as {ticker: {"delayed": bool, "delay_minutes": int | None}}:
| Backend | Read the status from |
|---|---|
native | table.delayed |
pandas | frame.attrs["xbbg_delayed"] |
pyarrow | json.loads(table.schema.metadata[b"xbbg.delayed"]) |
polars, duckdb | Not available; warnings are emitted before backend conversion, so "warn" still warns |
Subscriptions check delayed data by default (on_delayed="warn", once per topic), record the flag in sub.topic_states[topic]["delayed"] and the delayed column of latest(), and can reject only the delayed topics with on_delayed="raise". See Streaming.
Bloomberg can refuse individual fields, for example when the session is not entitled to them, without failing the request:
| Metadata | Source | Native | pandas | PyArrow schema metadata |
|---|---|---|---|---|
xbbg.field_exceptions | Per-security field exceptions in reference and historical results | table.field_exceptions | attrs["xbbg_field_exceptions"] | xbbg.field_exceptions |
xbbg.field_errors (1.8.0) | Fields that //blp/apiflds refused in bflds() and other FieldInfoRequest results, kept even when the result is empty | table.field_errors | attrs["xbbg_field_errors"] | xbbg.field_errors |
field_exceptions reads as {ticker: [{"field", "category", "code", "subcategory", "message"}, ...]} through the native and pandas accessors. Since 1.8.0 the raw xbbg.field_exceptions schema metadata, which PyArrow results carry, is a compact version-1 envelope with de-duplicated payloads, so read exceptions through the native or pandas accessors rather than parsing the raw value. field_errors maps each refused field to Bloomberg's category, code, subcategory, and message. Since 1.8.0, bflds() results also carry Bloomberg's field id (for example PR005) in a trailing id column, and lenient warnings and strict BlpValidationErrors from field validation include Bloomberg's refusal details.
Results keep the request ID that the Bloomberg SDK assigned, which Bloomberg support asks for when you report a data problem. It is distinct from xbbg's own request_id label (also visible to middleware as context.request_id) and from the SDK correlation ID.
import xbbg
table = xbbg.bdp("AAPL US Equity", "PX_LAST", backend="native")
print(table.bloomberg_request_id) # the ID when there is exactly one, else None
print(table.bloomberg_request_ids) # every ID, sorted and unique
try:
xbbg.bdh("AAPL US Equity", "PX_LAST", "2024-01-02", "2024-01-31")
except (xbbg.BlpRequestError, xbbg.BlpTimeoutError) as exc:
print(exc.request_id, exc.bloomberg_request_id, exc.bloomberg_request_ids)| Backend | Single ID | Several IDs |
|---|---|---|
native | table.bloomberg_request_id | table.bloomberg_request_ids (also lists a single ID) |
pyarrow | schema.metadata[b"xbbg.bloomberg_request_id"], plain UTF-8 | schema.metadata[b"xbbg.bloomberg_request_ids"], a sorted unique JSON array |
pandas | attrs["xbbg_bloomberg_request_id"] | attrs["xbbg_bloomberg_request_ids"] |
polars, duckdb | Not available | Not available |
on_delayed status lookup, and xbbg.ext recipes such as auction_snapshot) usually carry several IDs, so the singular form is None; read the plural form. A recipe that fails attaches the IDs of the requests that completed to the exception it raises.BlpRequestError and BlpTimeoutError raised by the engine carry bloomberg_request_id and bloomberg_request_ids; request_id stays the xbbg label.Delayed-data and rejected-field handling on subscriptions.
Which backends keep xbbg metadata.
BlpDelayedDataWarning, BlpRequestError, and filtering warnings.
SAPI/B-PIPE authentication used by identity checks.