Changelog
This page is generated from the repository root CHANGELOG.md during docs builds.
All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog 1.1.0, and this project adheres to Semantic Versioning 2.0.0.
Removed
Section titled “Removed”xbbg-browser,xbbg-bridge, andxbbg-serverretired: Theapps/xbbg-serverRust HTTP server, its@xbbg/bridgenpm launcher and 5 platform-specific bridge binaries, and the@xbbg/browserHTTP client are removed.js-xbbg,napi-xbbg, andpyo3-xbbgremain the supported bindings.
- Native datetime/date acceptance across all surfaces (#317):
bdh,bdib,bdtick,bqr,arequest, and thexbbg.ext.bonds/xbbg.ext.options/xbbg.ext.fixed_income/xbbg.ext.historical/xbbg.ext.futureshelpers now acceptdatetime.date,datetime.datetime(naive or tz-aware), and duck-typedpd.Timestamp(no hard pandas dependency) anywhere they previously took onlystr. ISO 8601, Bloomberg-native (YYYYMMDD), and"today"strings continue to work; ambiguousMM/DD/YYYY-style inputs are now rejected with a clearValueError. The two divergent_fmt_datehelpers were consolidated into a single source of truth inxbbg.ext._utils(extended with native-type support and a new_fmt_datetime). Bloomberg field overrides passed as**kwargs(e.g.USER_LOCAL_TRADE_DATE=date(2023, 1, 17)) are normalized toYYYYMMDDvia value-based duck typing. Mirrored on the JS side:@xbbg/coreacceptsDate, ISO/Bloomberg-nativestring, epoch-msnumber, and duck-typed LuxonDateTimeacrossbdh/bdib/bdtick/bqr/ recipe surfaces, with newformatDate/formatDateTimehelpers andDateLike/DateTimeLikeexported types. New guide atdocs/python/guides/dates. @xbbg/coresubscription replay benchmark: Added a JS-onlynpm run bench:subscription-replayharness for one-update-at-a-time synthetic replay, JSONL fixture replay, liveXBTUSD Curncycapture, and path-specific timing (legacy,arrow-decode-only,subscription-wrapper). Replay now supports--consume rows|vector|schema|noneand--warmup-iterations; row materialization remains the default. Live capture reports existingsub.statsslow-consumer telemetry without changing the production streaming API.xbbg-benchoffline Rust replay benchmarks: Added benchmark-controlled, non-Bloomberg, non-datamock harnesses for Arrow/TypedBuilderappend/finalize paths and syntheticxbbg-asyncsubscription-shaped replay. These live entirely undercrates/xbbg-bench, emit JSON artifacts, and use env knobs for row counts, flush size, and iterations so production crates do not carry benchmark-only hot-path changes.xbbg-benchcached subscription-to-Arrow bridge benchmark: Added a bounded live Bloomberg subscription capture that replays cached real SDKEvent/Messageobjects throughxbbg-asyncSubscriptionStateinto Arrow batches. This connects core SDK traversal with the subscription Arrow path while keeping Bloomberg usage to a small initial capture and avoiding datamock.- Low-data live regression coverage for recent Bloomberg issues: Added live integration coverage for recent BDTICK/ABDTICK, BDS bulk headers, numeric backend typing, optional conversion backend dispatch, BQL economic calendar, exchange-resolution, subscription timestamp, and options-extension regressions. The new fixtures favor bounded requests (
maxDataPoints, narrow chains, and current low-volume windows) so the live suite avoids excessive Bloomberg data usage while still exercising real service behavior. - Bloomberg Excel/0.x request aliases restored (#301):
bdh/abdh,bdib/abdib, andbdtick/abdticknow accept the 0.x/Excel-style request aliases (Per,PerAdj,Curr/FX,Days,Fill,Points,Quote,QuoteType/QtTyp,CshAdj*,CapChg,UseDPDF,Calendar,BarSz/BarSize,BarTp/BarType, andIncludeExchangeCodes) and normalize enum shorthand values before requests reach Bloomberg.bdh()also consumes Excel-only presentation aliases (Dts/Dates,DtFmt/DateFormat,Sort,Orientation/Direction/Dir) locally for date/period display, row ordering, and default orientation. Coverage includes offline routing tests plus a capped live Bloomberg suite.
Changed
Section titled “Changed”- Python backend clean-cutover to native xbbg Arrow objects: The Rust layer now returns native
xbbg._core.ArrowTable/ArrowRecordBatchcarriers internally, with explicitbackend="native"for callers that want those raw objects. The public default remains a Narwhals DataFrame and prefers a real PyArrow table when PyArrow is installed, then falls back through installed dataframe libraries before the minimal xbbg Narwhals plugin.backend="pyarrow"returns a realpyarrow.Table; the misleadingBackend.ARROW/backend="arrow"alias was removed. Pandas, Polars, DuckDB, and Narwhals remain explicit optional conversion backends, and PyArrow is no longer a core dependency. @xbbg/coresubscriptions now require NAPI Arrow zero-copy transfer:Subscription.next()asks the native binding for Arrow buffer descriptors and builds Apache Arrow JS tables directly from native Arrow buffers for common Bloomberg subscription types (bool,date32,float64,int32,int64,time64[us],timestamp[us],utf8,null). The JS subscription path no longer falls back to standalone IPC; unsupported or sliced schemas fail fast with column-level diagnostics while the publicSubscription.next(): TableAPI remains unchanged.@xbbg/coreexposes full Bloomberg subscription payloads: JS streaming APIs now acceptallFields: true, forwarding the existing Rust engineall_fieldsmode so callers can receive every top-level scalar field Bloomberg sends instead of only requested fields plusMKTDATA_EVENT_TYPE/MKTDATA_EVENT_SUBTYPE. The NAPI zero-copy bridge also supportstime64[us]columns for dynamic all-fields schemas.- Rust Bloomberg SDK handle ownership hardened:
xbbg-corenow models session-owned SDK views with Rust lifetimes instead of unsupportedSend/Syncmarker impls.Service, schema operations/definitions, and constants are tied to their owning session/service, pointer correlation IDs are explicit unsafe values, and async request workers reopen short-lived service handles rather than caching session-owned handles across worker state. - Reference data
fieldExceptionslogging aggregated: Per-securityfieldExceptionsdiagnostics now stay atDEBUGwith field-level detail, while bulk requests emit a single summary warning with total exception count and affected tickers. @xbbg/coreTypeScript request surface completed: JS wrappers now forwardvalidateFieldsonbdp/bds/bdh,requestTz/outputTzonbdib/bdtick, and typedbdtickinclude-code options while rejecting unknown backend strings instead of silently returning Arrow.- Generic
bds()/abds()bulk-header contract documented (#274): xbbg preserves Bloomberg bulk subfield labels exactly in the generic BDS path; onlytickerandfieldare xbbg-added metadata columns. Higher-level helpers that need stable semantic names must rename their own outputs explicitly. - Generated sync wrappers now resolve in IDEs (#307):
bdp,bdh,bds,bdib,bdtick,bql,bsrch,bqr,bflds,beqs,blkp,bport,bcurves, andbgovtsnow expose static signatures for parameter hints, hover docs, and go-to-definition. Top-levelxbbgexports were also completed forabqr/bqrand the generated endpoint stubs. - Retired mock crates removed from the workspace: The old C++ mock stack and Cargo mock feature forwarding were removed so the Rust workspace has a single live Bloomberg SDK FFI path.
-
BQR dealer attribution restored (#312):
bqr()/abqr()andxbbg.ext.bqr()now default toBID/ASKquote events withincludeBrokerCodes=true, normalize output to the 0.x-compatibleevent_type/price/broker_buy/broker_sellcolumns, warn when an attributed request is not shaped like a fixed-income ISIN with@MSG1 Corp, and raise when Bloomberg returns quote rows without broker attribution unless callers explicitly opt out withinclude_broker_codes=False. Low-data live coverage uses an@MSG1 Corpfixed-income ISIN fixture capped withmaxDataPoints=5. -
Subscription schemas preserve sparse numeric quote fields: Requested subscription fields now observe Bloomberg element datatypes even when a particular update carries a null value, so sparse streams such as
XBTUSD Curncyquote updates keepBID/ASKasFloat64instead of degrading the Arrow schema toUtf8before a non-null quote arrives. Live schema tests now print sample raw batches for easier diagnosis. -
Exchange/session resolution handles Bloomberg time-valued metadata: Exchange metadata parsing now accepts Arrow time columns for
TRADING_DAY_START_TIME_EOD/TRADING_DAY_END_TIME_EOD, avoids futures-only metadata field requests on ordinary equities, preserves futures fallback viaFUT_TRADING_HRS, and applies the Japan equity09:00-15:30session rule somarket_timing(..., "EOD", "UTC")resolves to the expected Tokyo close. -
Options live tests derive valid contracts dynamically: The options extension live suite no longer relies on stale hardcoded SPY expiry/strike fixtures; it discovers a current low-data SPY call through a narrow
option_chain()request and reuses that valid ticker/expiry/strike for info, greeks, pricing, screen, and BQL-chain checks. -
bdtickinclude-code options now keep typed tick tables (#309):IntradayTickStatedynamically discovers scalar fields inside Bloomberg’stickData.tickData[]rows, so options such asincludeConditionCodes,includeExchangeCodes, andincludeBloombergStandardConditionCodesadd typed columns after the stable core[ticker, time, type, value, size]instead of forcing callers into generic[path, type, value_str, value_num]output. Dynamic columns are padded with nulls for ticks where Bloomberg omitted that field; response metadata such astickData.eidDataremains excluded from per-tick rows. -
bdsbulk rows discover subfields across the whole response:BulkDataStatenow scans every scalar child in each Bloomberg bulk row instead of freezing the output schema from the first row. Late-appearing subfields are appended in first-seen order and earlier rows are padded with nulls, preserving row alignment for dynamic bulk datasets. -
bdsmanually selected bulk extraction could be overwritten by defaults:RequestParams::with_defaults()now preserves an explicit non-default extractor hint, preventing bulk requests from falling back to reference-data long extraction when callers build request params manually. -
Pixi/libclang bindgen discovery on Windows: Shared build support now creates an
OUT_DIR-locallibclang.dllalias for pixi/conda’s versionedlibclang-*.dll, so all bindgen build scripts can run without manually installing LLVM or mutating the pixi environment. -
Live reference-data tests and benchmarks used the wrong Bloomberg array accessor:
securityDatavalue arrays now useget_element(0)rather than child-element lookup, matching the SDK response shape. -
@xbbg/coreTypeScript package metadata repaired: Native optional dependencies now use package versions instead of localfile:links, release scripts use a checked-in CJS platform map helper, packaged-install smoke checks the publisheddistentrypoint, and the npm package includes the Apache license. -
@xbbg/corelocal Windows runtime loading fixed: The Node binding now adds the vendored Bloomberg SDK runtime DLL directory fromvendor/blpapi-sdk/<version>(orXBBG_DEV_SDK_ROOT) toPATHbefore loadingnapi_xbbg.node, so local tests do not require a manually exportedBLPAPI_ROOT. -
Python subscription unsubscribe keeps reusable workers clean:
PySubscription.unsubscribe()now propagates Bloomberg unsubscribe failures instead of suppressing them and only clears active subscription status after termination succeeds, so clean explicit unsubscribes return the subscription worker to the pool while failed/implicit cleanup keeps the conservative discard path. -
xbbg-asyncasync boundaries no longer perform cache disk I/O on hot Tokio paths: Request kwarg routing now uses memory-only schema metadata, explicit schema loads/persists are offloaded to blocking workers, field and exchange caches preload during engine startup, and exchange cache persistence snapshots entries before filesystem writes instead of holding cache locks across I/O. -
Rust subscription cleanup preserves clean worker reuse and avoids blocking drop flushes:
SubscriptionStream::unsubscribe()now clears active status after successful termination before the claim drops, matching the Python/NAPI clean-close path, whileSubscriptionState::Dropuses best-efforttry_sendsoOverflowPolicy::Blockcannot block the subscription worker during cleanup. -
Dynamic extractor hot paths avoid repeated linear duplicate scans and JSON clones:
bdsbulk rows andbdtickdynamic columns now track discovered fields with membership sets while preserving output order, and BQL JSON parsing stores borrowed intermediate values where safe before building owned Arrow arrays.
1.1.2 - 2026-04-20
Section titled “1.1.2 - 2026-04-20”bdh/bdpwithformat='semi_long'dropped Int64-typed fields (#303): Bloomberg sends integer-typed fields (PX_VOLUME,OPEN_INT, etc.) as Float64 on the wire in HistoricalDataResponse even though FieldInfo declares themInt64/Long.crates/xbbg-core/src/value.rs::Value::as_i64(and itsOwnedValuetwin) and the inlineTypedBuilder::Int32::append_valuematch incrates/xbbg-async/src/engine/state/typed_builder.rshad no Float64 arm, so the wide-path Int builder null-filled those columns. Consequence:blp.bdh("ESH20 Index", flds=[..., "PX_VOLUME", "OPEN_INT"], format='semi_long')returned NaN for every volume / open-interest row.long/long_typed/long_metadatawere unaffected because their builders route via Float64 or stringify. Fixed by acceptingFloat64when it’s finite, hasfract()==0.0, and fits the target integer range.TestOutputFormats::test_bdh_semi_long_integer_fields_issue_303locks this in live, plus existingbdp/bdhsemi_longtests now assertnotna().all()per column instead of just column names.
1.1.1 - 2026-04-20
Section titled “1.1.1 - 2026-04-20”@xbbg/core: recipe helpers exposed on the JSEngine: Eleven recipe methods surfaced through the NAPI bindings —yas,preferreds,corporateBonds,futTicker,activeFutures,cdxTicker,activeCdx,dividend,turnover,etfHoldings,currencyConversion— wrapping the correspondingxbbg_recipesentry points. Returns ArrowTableby default withBackend.JSON/Backend.POLARSopt-in viaoptions.backend; errors route through the standardBlpErrorhierarchy. Ships with TypeScript definitions (YasOptions,PreferredsOptions,CorporateBondsOptions,FuturesResolveOptions,ActiveCdxOptions,DividendOptions,TurnoverOptions,EtfHoldingsOptions,RecipeBackendOptions), README usage examples, and smoke-test coverage injs-xbbg/test.js.- Prebuilt cross-platform offline bundles for
@xbbg/core(scripts/build-offline-bundle.js): Packages@xbbg/coreplus the prebuilt@xbbg/core-<label>native addon into a hoistedbundle/node_modulestree alongside source tarballs for air-gapped installs.js_github_release.ymlgains apack-offline-bundlesjob that attachesxbbg-offline-<label>-<version>.zipto the GitHub release (covered by the existingvalidate-release-payloadscanner for Bloomberg SDK leakage);ci-rust.ymlmirrors the job per-commit with a 7-day artifact retention for downstream consumers.
Changed
Section titled “Changed”EngineConfig.request_timeout_msdefault changed from60_000to0(disabled): The previous 60s hard cap was self-inflicting timeouts on legitimately long requests — e.g. a full-daybdtickfor a liquid future routinely exceeds 60s on the Bloomberg side, so the worker was cancelling healthy requests and surfacing aBlpTimeoutErrorto the caller. The enforcement machinery is unchanged; callers who want a hard upper bound must now opt in explicitly by passingrequest_timeout_ms=<ms>(Python),requestTimeoutMs(NAPI), orPyEngineConfig.request_timeout_ms(pyo3).
-
bdtick/bdibsilently droppedoverrides=kwargs (#295):_build_abdtick_planand_build_abdib_planinpy-xbbg/src/xbbg/blp.pywere doingelements, _ = await _aroute_kwargs(...)— the_threw away the overrides list before the request reached the Rust engine. Other endpoints (bdp/bdh/bds/beqs/bport) capture both; only the two intraday builders discarded overrides. Now forwarded. Note that Bloomberg’sIntradayTickRequest/IntradayBarRequestschemas have nooverridessub-element, so forwarded overrides now surface as a Bloombergelement-not-founderror instead of being silently no-oped; for response-size limits use the top-levelmaxDataPointskwarg instead. -
bdib+maxDataPointsfell back to the generic flattener, losing the typed schema:crates/xbbg-async/src/engine/worker.rsrouted intraday-bar / tick requests throughGenericStatewhenever any user-supplied element was set, on the assumption that extra elements imply extra response columns. That holds for tickinclude*flags (condition codes, exchange codes, etc. which add per-tick columns), but not for behavior-only elements likemaxDataPoints,maxDataPointsOrigin,gapFillInitialBar, oradjustment*— those don’t change the response shape. Consequence:blp.bdib(..., maxDataPoints=1)returned[path, type, value_str, value_num]instead of the typed[ticker, time, open, high, low, close, volume, numEvents], andblp.bdtick(..., maxDataPoints=1)returned 6 rows instead of 1 (the generic extractor exploded one tick into per-field rows). Fallback removed entirely forIntradayBar(no column-adding elements exist onIntradayBarRequest); narrowed toinclude*keys onIntradayTick. -
Offline-bundle packing rejected by npm with
EBADPLATFORM:npm installin thepack-offline-bundlesjob runs on a Linux runner but pulls in@xbbg/core-<label>packages that declareos/cpufor their target platform (e.g.win32/x64).scripts/build-offline-bundle.jsnow passes--forceso the cross-platform install succeeds; the bundle is never executed on the install host, so the platform check is safe to skip. -
bdp/bdhsilently returned long-shape output forformat='semi_long'(#296, #299):crates/xbbg-async/src/engine/worker.rshad no"semi_long"arm in its format-string match — theRefDatabranch hardcodedOutputFormat::Longand only variedLongMode; theHistDatabranch only recognised"wide". Soblp.bdp(..., format='semi_long')returned[ticker, field, value]instead of the documented[ticker, <field1>, <field2>, …]pivoted shape, andblp.bdh(..., format='semi_long')returned[ticker, date, field, value]instead of[ticker, date, <field1>, …]. TheFormat::SemiLongenum inservices.rsparsed"semi_long"round-trip correctly; the break was purely in the worker routing. Fixed by mapping"semi_long" | "wide"→OutputFormat::Widein both arms. Regression coverage: newTestOutputFormatsclass inpy-xbbg/tests/live/test_api.pyasserts column shape for all fourFormatvariants (long,semi_long,long_typed,long_metadata) on bothbdpandbdh, verified live against Bloomberg.
1.1.1b1 - 2026-04-18
Section titled “1.1.1b1 - 2026-04-18”-
BQL
secondaryColumnsextracted from responses (#288, refs #289 / #290 / #291):parse_bql_jsoninxbbg-asyncnow pullsDATE,CURRENCY, and other secondary dimensions out of BQL JSON so time-series queries likewith(dates=range(-5d, 0d))return usable row labels instead of ambiguous duplicate-ticker rows. Three latent parser issues fixed in the same pass: column lengths are now clamped toidColumnsize viaresize()so partial errors with mismatched field lengths stop failingRecordBatch::try_new(#289); column typing now uses Bloomberg’svaluesColumn.typemetadata with.all()fallback instead of value-sniffing with.any()(#290); a warning is logged when BQL falls through to the legacy Element-API path wheresecondaryColumnsare unavailable (#291). -
xbbg-async: per-subscription availability tracking viaSubscriptionStreamsActivated/SubscriptionStreamsDeactivated: Bloomberg SDK v3.11.6+ recovers subscriptions internally across transient disconnections; the ChangeLog explicitly instructs applications to use theStreams*events to detect failover. xbbg now consumes both and exposes per-topicstreams_activeonTopicStatusInfo. A debounced Warning event (SubscriptionStreamsDeactivatedPersisting) fires when a topic stays streams-inactive paststreams_deactivated_warn_ms, so callers polling status can tell “SDK is still recovering” from “data is dead”. See.omc/research/reconnect-correctness.mdfor the full SDK-contract evidence trail. -
EngineConfig.request_timeout_ms(default60_000;0disables): Hard per-request upper bound. Request workers now cancel the Bloomberg request and fail the oneshot withBlpError::Timeoutwhen the timeout expires, guaranteeing callers cannot hang forever on a stuck response regardless of SDK or server-side misbehavior. Exposed through all three bindings: Pythonrequest_timeout_ms, NAPIrequestTimeoutMs, pyo3PyEngineConfig.request_timeout_ms. -
EngineConfig.streams_deactivated_warn_ms(default30_000;0disables): Threshold for the per-topic streams-inactive warning described above. Exposed asstreamsDeactivatedWarnMsin NAPI andstreams_deactivated_warn_msin pyo3/Python. -
Worker health on
SubscriptionWorker: Mirrors the existingRequestWorkerhealth field. Goes toDeadonSessionTerminated; the pool’sclaim()andrelease()paths drop Dead handles and spawn fresh replacements so a wave ofSessionTerminatedevents cannot permanently cripple the engine. -
reconnect_probeexample (crates/xbbg-core/examples/reconnect_probe.rs): Observational tool that subscribes to a live ticker and logs everySessionStatus/SubscriptionStatusevent with timestamps andreason.descriptionfor validating reconnect behavior against a real Bloomberg session. -
xbbg-bench:benches/cache_contention.rs: Harness measuringSchemaCache::getandFieldTypeResolver::getlatency percentiles under reader/writer pressure at 10/100/1000 reader concurrency, one writer inserting every 5ms, 2-second runs. Produces p50/p99/p99.9/max tables viahdrhistogramand saves them totarget/bench_cache/<BENCH_LABEL>.txtfor before/after diffing. Run withDYLD_LIBRARY_PATH=vendor/blpapi-sdk/3.26.2.1/Darwin BENCH_LABEL=<name> cargo bench -p xbbg-bench --bench cache_contention. -
Keep-alive tuning on
EngineConfig:keep_alive_enabled(bool, defaulttrue),keep_alive_inactivity_ms(Option<i32>, SDK default 20s),keep_alive_response_timeout_ms(Option<i32>, SDK default 10s). Default SDK window of ~30s silence beforeSessionConnectionDownis aggressive for VPN/WAN BPIPE connections; raising these prevents spurious disconnects without changing local-Terminal behavior. Exposed through pyo3 / NAPI / Python. -
Slow-consumer water marks on
EngineConfig:slow_consumer_hi_water_markandslow_consumer_lo_water_mark(Option<f32>, fractions ofmax_event_queue_size). SDK defaults 0.75 / 0.5. Exposed through all three bindings (slowConsumerHiWaterMark/slowConsumerLoWaterMarkin NAPI with 0.0..=1.0 / 0.0..1.0 validation). -
AuthorizationRevokedhandling during live session: Previously only checked at startup (crates/xbbg-core/src/session.rs::wait_until_started). If identity was revoked mid-session (token expiry, policy change), requests silently failed with opaqueRequestFailureand subscriptions silently stopped. BothRequestWorkerandSubscriptionWorkernow handleAuthorizationRevokedsymmetrically toSessionTerminated: drain in-flight/subscriptions with a dedicated “please re-authenticate” error, mark the workerDead, and let the pool spawn a fresh worker that re-auths during startup. -
ServiceDownnow emits a subscription-category warning when active subs exist: Previously only recorded on service status. Callers pollingsub.eventsmissed the signal that their streams were affected untilSubscriptionStreamsDeactivatedfired per topic. Now a singleServiceDownAffectsActiveSubscriptionsevent fires at the moment ofServiceDownso callers see immediately that their data may go quiet. -
reason.descriptionparsed onSubscriptionStarted: Bloomberg sometimes includes partial-permission details (e.g. “only delayed data authorized”) on thereasonelement ofSubscriptionStarted. These were discarded; now surfaced via the status eventdetail.
Changed
Section titled “Changed”-
EngineConfigtransport surface restructured as aTransportenum (internal Rust only; Python/JS kwargs unchanged): The six flat transport fields (server_host,server_port,servers,zfp_remote,socks5_host,socks5_port) and five flat TLS fields (tls_client_credentials,tls_client_credentials_password,tls_trust_material,tls_handshake_timeout_ms,tls_crl_fetch_timeout_ms) onxbbg_async::EngineConfigcollapsed intotransport: Transport+tls: Option<TlsConfig>.Transport::Direct(Vec<ServerAddr>)carries per-server SOCKS5 (matchingblpapi::SessionOptions::setServerAddress(serverHost, serverPort, socks5Config, index)invendor/blpapi-sdk/3.26.2.1/include/blpapi_sessionoptions.h:501-511);Transport::Zfp(ZfpRemote)takes no server addresses by construction, so the #294 bug class is unrepresentable in the type system. Conflict validation lives at the PyO3 / NAPI boundary —resolve_transportrejectszfp_remotecombined withhost/port/servers/socks5_*with specificValueError/InvalidArgmessages.start_configured_sessionis now a three-stage pipeline (transport → optional TLS re-apply → session-behavior config) with no shared mutation, matching Bloomberg’s own canonical demo-app structure (vendor/blpapi-sdk/.../examples/demoapps/util/ConnectionAndAuthOptions.h:213-296). TLS is applied once at the SDK level: throughZfpUtil::getOptionsForLeasedLinesfor ZFP, viaSessionOptions::setTlsOptionsfor Direct; the previous double-apply (ZfpUtil + inlineset_tls_options) is eliminated. The engine tracing span now logstransport = %config.transportvia a newDisplayimpl onTransport/ZfpRemote(e.g.localhost:8194,primary.example.com:8194 (+2 failover),zfp:8194). All public Pythonconfigure()kwargs and@xbbg/coreEngineConfigInputfields are unchanged — the flat surface is preserved and converted at the binding boundary. -
xbbg-asynccache hot paths:RwLock<HashMap>→ArcSwap<HashMap>(schema) andDashMap(field):SchemaCachereads are now lock-free atomic pointer loads; writes publish a new snapshot via RCU.FieldTypeResolverusesDashMap’s sharded internal locking (plusOnceLockfor the lazy disk-load flag). Public API unchanged; all 100xbbg-asynclib tests pass. Measured viabenches/cache_contention.rs(2s run, 1 writer inserting every 5ms, artifacts intarget/bench_cache/):Scenario p50 p99 p99.9 throughput schema, 1000 readers 1.96µs → 125ns 17.1µs → 667ns 22.5ms → 1.2µs (~19 000×) 22× more samples schema, 100 readers 1.71µs → 166ns 19.8µs → 667ns 6.5ms → 1.2µs (~5 400×) 14× more samples schema, 10 readers 1.75µs → 166ns 16.1µs → 500ns 56µs → 750ns (75×) 14× more samples field, 1000 readers 2.67µs → 125ns 19.2µs → 583ns 30.4ms → 1.2µs (~25 000×) 20× more samples field, 100 readers 2.58µs → 125ns 20.4µs → 583ns 11.1ms → 1.2µs (~9 200×) 20× more samples field, 10 readers 2.50µs → 125ns 18.4µs → 583ns 52µs → 1.1µs (46×) 19× more samples Eliminates the writer-thundering-herd pathology where a
~1µswrite-lock window would queue hundreds of readers and blow out p99.9 into the millisecond range. Relevant under burst load — e.g. many parallel//blp/refdatarequests landing during a//blp/apifldsintrospection, where schema/field lookups are on every critical-path hop. p50 and p99 also improve because the RwLock acquire/release was the dominant cost of an uncontended cache hit.maxis still OS-scheduler jitter (threads can be preempted for a full quantum) and unrelated to cache design. -
ensure_serviceswitched from synchronousopenServicetoopenServiceAsync+ nested event dispatch: The synchronousblpapi_Session_openServiceinternally blocks on the session’s event queue, which stalls delivery of every other in-flight event for the duration of the call. Measured locally against a Bloomberg Terminal:open_servicetakes 200-300ms per call, post-call delivery rates spike to 1.6-2.3× baseline (consistent with queue-and-release). Worker threads now callopen_service_async, tag replies with a dedicated high-bit-set correlation ID (1 << 62), and run a nested dispatch loop that continues to processSubscriptionData/SessionStatus/RequestStatuswhile waiting forServiceOpened. BothSubscriptionWorker::ensure_serviceandRequestWorker::ensure_serviceare affected. AddedSession::open_service_asynconxbbg-corewith aBlpError::TimeoutafterSERVICE_OPEN_TIMEOUT_MS(10s default).
Changed
Section titled “Changed”SessionConnectionDown/Upare now treated as informational on the subscription path (matching Bloomberg’s canonical guidance:vendor/blpapi-sdk/.../examples/unittests/snippets/events/events.t.cpp:42-54— “Applications can safely ignore… These events are informational only and applications should not react to them”). OnlySessionTerminateddrains active subscriptions and marks the workerDead. The SDK’s own auto-restart + internal subscription recovery handle transient network blips.- Request-side handling preserves drain-on-Down semantics but marks workers
Degraded(notDead): requests are transactional, so a response mid-transit when TCP drops is lost and must be failed fast. OnSessionConnectionUpthe worker flips back toHealthy. OnSessionTerminated, it drains and goesDeadwith pool replacement. BlpErrorproduced onRequestFailureandSessionTerminatednow includes Bloomberg’sreason.descriptioninstead of opaque"RequestFailure"/"Bloomberg session terminated"strings. Same parser shape as the existingstartup_error_from_messagehelper.SubscriptionSessionPool::claimdrops dead handles during the pop loop and spawns a fresh replacement if every available handle is Dead.release()discards Dead handles instead of returning them to the pool.
-
ZFP over leased lines failed with
Failed to connect to 127.0.0.1:8194(#294):blp.configure(zfp_remote="8194", tls_client_credentials=..., tls_trust_material=...)started a session but the SDK tried to connect tolocalhost:8194instead of the Bloomberg infrastructure endpoints. Root cause incrates/xbbg-async/src/engine/mod.rs:start_configured_sessioncalledconfigure_zfp_options(which populates theSessionOptionsserver list viaZfpUtil::getOptionsForLeasedLines), then unconditionally calledconfigure_session_options, whose server-address loop overwrote index 0 with theserver_host/server_portfallback oflocalhost:8194. The SDK contract (vendor/blpapi-sdk/3.26.2.1/include/blpapi_zfputil.h:154-162) explicitly states theSessionOptionsreturned byZfpUtilis “only valid for private leased line connectivity” — layeringsetServerAddresson top is undefined behavior. Two related latent bugs in the same code path are also fixed: passingservers=[…]alongsidezfp_remotewould clobber ZFP endpoints at indices 0..N, and passingsocks5_hostalongsidezfp_remotewrapped the overwritten localhost address in SOCKS5 semantics. All three combinations now raiseValueErroratconfigure()time with specific messages instead of producing silent connection failures. See theChangedentry below for the underlying refactor. -
Silent subscription death after a transient blip: With the default
SubscriptionRecoveryPolicy::None, aSessionConnectionDown→Upcycle would silently produce a live session with zero data flowing — the SDK reconnected TCP, but xbbg never re-established subscriptions, andsub.next()hung forever. The SDK actually recovers subscriptions itself (v3.11.6+); xbbg just needed to stop fighting it and consume theSubscriptionStreams*events. Fixed by the above refactor. -
Aggressive drain on transient
SessionConnectionDownfor subscription workers: The previous handler marked subscription workersDeadand drained all in-flight subscriptions on every transient Down event, contradicting Bloomberg’s “informational” contract. Now a no-op on the subscription side. -
Lifetime leak of
recovery_attempt_count:record_recovery_successnever reset the counter, somax_recovery_attempts=3became a process-lifetime cap, permanently disabling recovery after three flaps. Removed along with the rest of the recovery machinery (seeRemoved). -
SubscriptionWorkerwith a terminated session remained claimable from the pool: the worker drained its subs but had nohealthfield, so a subsequentclaim()would hand out a handle whose underlying session pointer was dead. Fixed by adding health tracking and the pool-level eviction + replacement path. -
Live subscription tests hardcoded to expired
H6(March 2026) futures contracts:ESH6/NQH6/UXH6returnedSecurity is not valid for subscription [EX336]from Bloomberg after 2026-03-20. Switched to generic front-month continuation tickers (ES1/NQ1/UX1) which Bloomberg auto-rolls; matches the pattern already used injs-xbbg/test-live.js. -
crates/xbbg-core/tests/live.rschecked for"SessionResumed": Not a real BLPAPI message name — zero matches in the vendored SDK headers. The check never fired becauseSessionStartedalways arrived first; removed to match the canonical event set.
Removed
Section titled “Removed”Message::topic_name(): Bloomberg deprecatedMessage::topicName()in BLPAPI SDK 3.14.8 — the method always returns an empty string, and the SDK docs explicitly instruct callers to maintain their own CID→topic map (include/blpapi_message.h:253-274). Subscription workers already do this via the slab. No production code called it.SubscriptionRecoveryPolicyenum +recover_active_subscriptions+recovery_*fields/methods: Removed entirely. The SDK recovers subscriptions internally; xbbg’s parallel implementation fought the SDK (would re-subscribe with in-use correlation IDs →correlationIdError) and its default ofNonesilently dropped subs across blips. Deleted together:SubscriptionRecoveryPolicy,recover_active_subscriptions,recovery_attempt_count,recovery_success_count,last_recovery_attempt_us,last_recovery_success_us,last_recovery_error,record_recovery_attempt,record_recovery_success,record_recovery_error, andSessionStatusInfo.recovery_policy. BREAKING: drops therecovery_policykwarg fromasubscribe/astream/subscribe_with_optionsin Python, pyo3, and NAPI, plus the corresponding fields fromsub.session_status.EngineConfig.max_recovery_attempts,EngineConfig.recovery_timeout_ms,EngineConfig.health_check_interval_ms: All three were defined, documented, and exposed through all three bindings (pyo3 / NAPI / py-xbbg), but zero consumers existed in the engine — dead config surface that misled callers. Removed from all three bindings. BREAKING for any caller that set these; the behavior they advertised wasn’t actually implemented.
Fixed (js-xbbg 1.1.x follow-ups)
Section titled “Fixed (js-xbbg 1.1.x follow-ups)”@xbbg/core:Engine.bdp/bds/bdh/bdib/bdtickignoredoptions.backend: The five core reference/historical/intraday methods did not forwardbackendintoEngine.request, so callers asking forBackend.JSONorBackend.POLARSsilently received ArrowTables regardless.backendis now threaded through all five methods and the correspondingBdpOptions/BdhOptions/BdibOptions/BdtickOptionstypes inindex.d.ts. Verified live against a Bloomberg session.@xbbg/core:Engine.requestRawandSubscription.add/removedid not wrap native errors:Engine.requestandSubscription.nextrouted native rejections throughwrapError, but the raw request path and subscription mutators did not. Callers discriminating onBlpError/BlpRequestErrorsubclasses missed failures from those paths. All three now wrap consistently.@xbbg/core: session-start failures surfaced as plainError:connect(...),new Engine(...), andEngine.withConfig(...)no longer bypasswrapError, andwrapErrornow matches the actual NAPI session-start messages ("failed to spawn worker","session start failed","Failed to start session","connect event failed"). Failed connects now classify asBlpSessionError.@xbbg/core:BlpRequestError.request_idwas never populated: The Rust engine appends[request_id=<uuid>]to request-failure messages when a correlation id exists, butwrapErrordid not parse it. The id is now extracted intoerr.request_id.@xbbg/core: a transient connect failure permanently poisoned every top-level helper:getConfiguredEnginecached the firstconnect(...)promise unconditionally, so a rejected bootstrap produced the same rejection on every subsequent call untilconfigure()was invoked again (observed live as 7.2s first attempt followed by 0ms cached rejection). Rejected promises are now cleared so the next call re-attempts.
Security
Section titled “Security”randbumped to 0.9.3 inCargo.lock(GHSA-cq8v-f236-94qc / RUSTSEC-2026-0097, low): The advisory is scoped to runtimerand::rng()use from inside a customlogimplementation that triggersThreadRngreseeding — not something xbbg exercises. The remainingrand 0.8.5in the graph is build-time only (phf_generatorforphfmacros,unicode_names2_generatorforpyo3-stub-gen), outside the advisory’s exposure surface.
1.1.0 - 2026-04-14
Section titled “1.1.0 - 2026-04-14”xbbg-mcplocal MCP server: Added a stdio Bloomberg MCP application underapps/xbbg-mcpwith tool surfaces forbdp,bdh,bds,bdib,bql,bsrch,bflds, and generic request execution. Responses are bounded structured JSON with Arrow schema metadata for coding agents.- GitHub-release MCP distribution path: Added release packaging for
xbbg-mcp, a Unix launcher wrapper (scripts/xbbg-mcp), and a convenience installer (scripts/install-xbbg-mcp.sh) so Claude Code and OpenCode users can install a local MCP binary without cloning or compiling the repo first. @xbbg/coreNode.js package: New first-class JavaScript/TypeScript client underjs-xbbg/that wraps the Rust engine via NAPI. Exposes the full request surface (bdp,bdh,bds,bdib,bdtick,bql,bqr,bsrch,beqs,blkp,bport,bcurves,bgovts,bflds), a typed error hierarchy, optional backends (Apache Arrow tables by default,nodejs-polarsas an optional peer), and a BPIPE/auth-awareconfigure(). Native addons are prebuilt and distributed as optional platform packages (@xbbg/core-darwin-arm64,@xbbg/core-linux-x64,@xbbg/core-win32-x64) sonpm install @xbbg/coreJust Works without a Rust toolchain.@xbbg/bridgeasync browser bridge: New companion package exposing the Rust engine through an async postMessage bridge, shipped alongside@xbbg/corewith matching platform-specific native addons.- GitHub-only JS package release workflow: Added a manual
js_github_release.ymlpath that builds, versions, validates, and attaches GitHub release tarballs for@xbbg/coreand@xbbg/bridgewithout npm publishing. The workflow intentionally ships the currently supported 8-asset set only:@xbbg/corewrapper plusdarwin-arm64/linux-x64/win32-x64, and@xbbg/bridgewrapper plusdarwin-arm64/linux-x64/win32-x64. The unreleased@xbbg/bridge-darwin-x64and@xbbg/bridge-linux-arm64package stubs remain excluded until Bloomberg SDK archive support exists. - Friendlier
AttributeErrorfor removedblplegacy APIs:blp.connect,blp.disconnect, andblp.getBlpapiVersionnow raise anAttributeErrorwhose message points directly at the 1.0 replacement (xbbg.configure,xbbg.shutdown/xbbg.reset,xbbg.get_sdk_info) with a copy-pasteable B-PIPE example, instead of the bare “module has no attribute” default. Implemented via a module-level__getattr__hook inpy-xbbg/src/xbbg/blp.py.
Changed
Section titled “Changed”- Backend conversion moved to a single boundary with
pa.Tableas canonical form:_execute_request_terminalnow returns the rawpa.Tablefrom the Rust engine without wrapping in narwhals first;arequestdoes a single_convert_backendcall at its return._convert_backenddispatches directly frompa.Tablevia zero-copy primitives (pl.from_arrow,table.to_pandas, identity forpa.Table → pa.Table), bypassing the narwhals wrap/unwrap on the hot path. Short-circuiting middlewares that return non-pa.Tablevalues (e.g. caches returning lists) keep full control over their result. Measured on a 1000×10 frame:pa.Table → pa.Tablewent from 17.78 µs to 0.04 µs (464×),pa.Table → pl.DataFramefrom 39.89 µs to 18.67 µs (2.1×). Subscriptions streaming at 10k msgs/sec previously spent ~33% of a core on redundant wrap/unwrap in the dispatch layer; this cuts it roughly in half. Narwhals remains the canonical abstraction for backend-agnostic data manipulation inext/historical.py,ext/currency.py,ext/futures.py,ext/_utils.py, and_reshape_bqr_generic— this refactor only removes it from the pure routing path where it added overhead without value. - Minimum
narwhalsversion bumped to>=2.0: Required for thenw.Implementationenum and.implementationproperty used by the new_convert_backenddispatch. Downstream users pinned to narwhals 1.x will need to upgrade. No other narwhals 2.x breaking changes affect xbbg —get_native_namespace,new_series(native_namespace=),from_nativeidempotency, and.to_native()all remain stable across the 1→2 boundary. xbbg.configure()rejects unknown kwargs:configure()now raisesTypeErroron any keyword it does not recognize. Previously unknown kwargs were silently dropped by the RustPyEngineConfigconstructor, which meant typos (e.g.hots=...instead ofhost=...) would leave the host at the default without any warning. The Python normalizer now validates the kwarg set against the canonical field list before handing off to Rust.- Docs site restructured with Python/JavaScript split: The Starlight site under
docs/now has distinctpython/andjavascript/sections, an auto-generatedreleases/changelog.mdxpage (scripts/generate-changelog-docs.sh), and auto-generated Python API reference (scripts/generate-python-api-docs.sh, renamed fromgenerate-api-docs.sh). Thedeploy-docs.ymlworkflow now drives publishing automatically, and the host build no longer depends onsharpso it works on macOS without libvips.
- Incorrect value types in
bdp/bdhlong format (issue #280): The default long format (LongMode::String) was converting all Bloomberg values to strings, ignoring resolvedfield_types. Now the Rust engine computes a common Arrow type from the field type hints at construction time — when all fields are numeric, thevaluecolumn isFloat64instead ofUtf8. Mixed-type queries (e.g., numeric + string fields) gracefully fall back to string. The fix is zero-copy:Valueis moved into the Arrow builder instead of being stringified and re-parsed. - macOS/Linux:
import xbbg._corefails withLibrary not loaded: @rpath/libblpapi3_64.so(issue #276): The pyo3 cdylib ships with zeroLC_RPATHentries on macOS, so dyld had nowhere to look forlibblpapi3_64.soat import time. Previously only Windows had pre-import SDK setup in__init__.py. Now_prepare_sdk_for_core_import()dispatches per-platform: Windows keeps the existingadd_dll_directorypath, while macOS and Linux preloadlibblpapi3_64.soviactypes.CDLL(..., RTLD_GLOBAL)so dyld/ld.so resolves the@rpathreference via install-name / already-loaded image matching. This mirrors the idiom Bloomberg’s ownblpapi/internals.pyuses for itsffiutilsextension (which also ships with no rpath). All four SDK sources (xbbg.set_sdk_path(),blpapipackage, DAPI,BLPAPI_ROOT) are now honored on every platform. The friendlyImportErrorwrapper also recognizes macOS dlopen error strings (Library not loaded,image not found). RequestEnvironment.zfp_remotetype annotation: Corrected the dataclass field annotation fromint | Nonetostr | Noneto match the RustOption<String>(ZFP remote values are strings like"8194"/"8196"). The defensivegetattr()access in_snapshot_request_environmenthad been masking this type mismatch from static analyzers._convert_backendno longer hard-imports polars: A follow-up to the Arrow-canonical refactor accidentally replaced the intentionalhasattr(native, "to_arrow")capability check in the pyarrow branch with an unconditionalisinstance(native, pl.DataFrame), which forcedimport polars as plat module-load time and broke environments where polars (an optional backend) isn’t installed. Restored the capability check, short-circuiting pandas inputs viaisinstancefirst so thehasattrpath only fires for genuine polars frames.- Polars/pyarrow global backend causes
AttributeErrorin all generated endpoints (issue #287):_execute_generated_endpointwas effectively calling_convert_backendtwice on the same frame — once inside the middleware terminal (which resolvedbackend=Noneto the global default and returned a native frame) and again in the outer call, which triednw_df.to_native()on the already-native frame. Pandas users were silently masked by anisinstance(nw_df, pd.DataFrame)short-circuit at the top of_convert_backend; polars and pyarrow users had no equivalent guard and sawAttributeError: 'DataFrame' object has no attribute 'to_native'. Affected all 14 generated endpoints (bdp/abdp,bdh/abdh,bds/abds,bdib/abdib,bdtick/abdtick,bql/abql,bqr/abqr,bsrch/absrch,beqs/abeqs,blkp/ablkp,bport/abport,bcurves/abcurves,bgovts/abgovts,bflds/abflds) — not justbdpas reported. Verified end-to-end against a real Bloomberg Terminal. ext/futures.pydate-like duck-typing: Collapsed threehasattr(value, "year"/"month"/"day")calls into a singleisinstance(value, date)check now thatdateis imported unconditionally. More precise and removes false positives from unrelated objects that happen to expose.year.markets/{info,bloomberg}.pyimports: Replacedimportlib.import_module("xbbg")+getattr(..., "bdp"/"abdp") # noqa: B009with deferredfrom xbbg.blp import bdp/abdpinside the consuming functions. Same lazy-loading behavior, removes the lint suppression, and lets static checkers resolve the symbol.- Incorrect timestamp in
parse_rfc3339_utctest: Fixed hardcoded expected value from1717242600to1717252200(correct UTC epoch for2024-06-01T14:30:00+00:00).
Removed
Section titled “Removed”- Legacy
configure()kwarg aliases:xbbg.configure()no longer accepts the legacy connection-style aliases carried over from xbbg 0.x:server,server_host,server_port,max_attempt,auto_restart,max_recovery,retry_max,retry_delay,retry_backoff. TheNotImplementedErrorplaceholders forsessandtls_optionsare likewise gone — unknown kwargs now raise a uniformTypeError. Use the canonicalEngineConfigfield names instead:host,port,num_start_attempts,auto_restart_on_disconnection,max_recovery_attempts,retry_max_retries,retry_initial_delay_ms,retry_backoff_factor.
1.0.0 - 2026-03-31
Section titled “1.0.0 - 2026-03-31”- Subscription event timestamps (issue #273):
asubscribe(..., tick_mode=True)and raw subscription batches now expose the eventtimestampcolumn as UTC-aware Arrow/Python datetimes instead of naive UTC values. This fixes incorrect.timestamp()conversions on non-UTC hosts.
1.0.0rc4 - 2026-03-30
Section titled “1.0.0rc4 - 2026-03-30”Changed
Section titled “Changed”- PyPI classifiers: Added
Development Status :: 5 - Production/Stable,Intended Audience :: Financial and Insurance Industry,Intended Audience :: Science/Research,Topic :: Office/Business :: Financial,Programming Language :: Rust, andTyping :: Typed. - README: Fixed all documentation links from defunct ReadTheDocs to Starlight site (
alpha-xone.github.io/xbbg), updated the latest-release marker to rc4, removed stale Codecov/Codacy/CodeFactor badges, replaced deadAuto CIbuild badge withci-rust.yml, and removed “beta” language in project description. - Issue templates: Updated documentation links and environment version examples for v1.
- CONTRIBUTING.md: Corrected minimum Rust version from 1.70 to 1.75.
- Bloomberg SDK ABI compatibility check: New
scripts/abi-check.shand CI job that verifies every C symbol xbbg-core depends on exists across SDK versions (oldest supported through latest). Minimum supported SDK version defined indefs/bloomberg.toml(min_sdk_version). - SECURITY.md: Restored security policy with vulnerability reporting instructions and hardening notes.
- GitHub Pages deploy workflow: Added
deploy-docs.ymlfor automated Starlight docs deployment on push to main. - Documentation: Wrote complete content for all guide and reference pages (migration, streaming, async, backends, output formats, configuration, type mappings).
- Shutdown panic (issue #270): Fixed tokio worker thread panic (
Python::attachafterPy_Finalize) when Python exits with active subscriptions. Root cause:signal_shutdown()didn’t close the data path to__anext__, leaving tokio futures alive during interpreter teardown. Fix addsEngine::shutdown_signal(watch channel) that immediately wakes pending__anext__futures, andshutdown_safe_futurewrapper that preventsfuture_into_pyfrom delivering results to a dead interpreter. Affects all async methods (requests, subscriptions, recipes). - Engine startup race condition (issue #272):
configure()no longer raisesRuntimeErrorif the engine was auto-created with defaults before configuration (e.g., by a health check or background thread in FastAPI). It now shuts down the default engine with aRuntimeWarningand stores the new config for the next request. Also added thread safety to_get_engine()(double-checked locking) and clear error messages when sync wrappers (bdp,bdh, etc.) are called inside async contexts. - Type checking: Resolved all 178
tyerrors to zero. Exception classes properly subclassed in Python instead of monkey-patching__init__on Rust classes. Added exception stubs to_core/__init__.pyi. Remaining 6type: ignorecomments are all upstream stub gaps (narwhals, stdlib, platform-specific). - Unused
pandasimport: Removed leftoverTYPE_CHECKINGimport ofpandasinblp.pyafterFormat.WIDEremoval. - Exception hierarchy:
BlpRequestError,BlpSecurityError,BlpFieldError, andBlpValidationErrorare now proper Python subclasses of the Rust base classes with typed__init__signatures, replacing fragile__init__monkey-patching.
Security
Section titled “Security”- Pygments ReDoS (CVE): Upgraded Pygments 2.19.2 to 2.20.0, fixing a regular expression denial of service in GUID matching.
Removed
Section titled “Removed”OverflowPolicy::DropOldest: Removed unimplemented overflow policy that silently behaved asDropNewest. Will be reintroduced in a future release with correct ring-buffer semantics. Use'drop_newest'(default) or'block'.Format.WIDE: Removed the deprecated wide output format. UseFormat.SEMI_LONGfor field-as-column output, or call.pivot()onFormat.LONGresults.asset_config(): Removed the deprecated market config helper. Usemarket_info(ticker)instead.
1.0.0rc3 - 2026-03-26
Section titled “1.0.0rc3 - 2026-03-26”- BQL error handling: Parse Bloomberg’s
responseExceptionsfor actionable error messages (e.g. “Undefined item: CUR_YLD”) instead of opaque “missing ‘results’ field” errors. Null results with no exceptions now return an empty DataFrame. Partial exceptions with valid results log warnings instead of failing. corporate_bonds()cross-market support: Switched frombondsuniv+TICKER==filter (US-only) todebt()universe, matching the approach used bypreferreds(). Now accepts full equity tickers (e.g. “9984 JT Equity”) and works across all markets.- CDX on-the-run indicator: Accept
'true'(returned by Bloomberg for CDX generic tickers) in addition to'Y'forON_THE_RUN_CURRENT_BD_INDICATOR, fixing false warnings on CDX instruments. is_connected()checks real session health: Now queries actual Bloomberg worker health viarequest_pool_health()instead of just checking if the Python engine object exists.fieldExceptionslogging: Downgraded from WARN to DEBUG and now includes actual field names and error messages (e.g. “MATURITY: Field not applicable to security”) instead of just a count.
1.0.0rc2 - 2026-03-23
Section titled “1.0.0rc2 - 2026-03-23”- Subscription field exposure (#265):
all_fieldsonasubscribe,astream, andstream(andPyEngine.subscribe/subscribe_with_options). WhenFalse(default), batches include only requested fields plusMKTDATA_EVENT_TYPEandMKTDATA_EVENT_SUBTYPE. WhenTrue, each batch includes every top-level scalar field Bloomberg sends (e.g. fullSUMMARY/INITPAINTsnapshots), with the schema growing as new fields appear. The same flag is available onavwap,amktbar,adepth, andachainsfor consistency across streaming services.
1.0.0rc1 - 2026-03-23
Section titled “1.0.0rc1 - 2026-03-23”- Intraday timezone controls (
request_tz/output_tz):abdib/bdib,abdtick/bdtick,arequest, and RustRequestParamsaccept optionalrequest_tz(interpret naivestart_datetime/end_datetimebefore Bloomberg) andoutput_tz(relabel Arrowtimeto an IANA zone). Supported labels includeUTC,local,exchange,NY/LN/TK/HK, reference tickers, and explicit IANA names. Implemented inxbbg-async(chrono-tz,iana-time-zone) with nested RefData calls routed throughrequest_without_intraday_transformto avoid recursion. - Pixi environment management: Added
pixi.tomlwith 11 environments (default, test, lint, benchmark, docs, py310–py314), 21 tasks, and conda-forge deps for Rust, libclang, and pyarrow. Singlepixi install && pixi run installreplaces manual toolchain setup. - mimalloc allocator: PyO3 extension now uses mimalloc by default (feature-gated) for improved Rust-side allocation performance.
tytype checking: Lint environment includes Astral’stytype checker alongside ruff; CI lint job now runs type checking automatically.- SOCKS5 proxy support (#180): Route Bloomberg connections through a SOCKS5 proxy via
socks5_hostandsocks5_portkwargs onconfigure()andEngine(). Uses the Bloomberg SDK’sSocks5ConfigAPI (no auth, hostname + port only). - Enterprise-friendly request middleware context:
RequestContextnow carries a read-onlyRequestEnvironmentsnapshot so middleware can inspect engine source, host/port, server list, auth method, app/user context, and validation mode without reaching into private globals.
Changed
Section titled “Changed”- Standardised on
BLPAPI_ROOT: RemovedXBBG_DEV_SDK_ROOTenv var across the codebase (build.rs, scripts, docs). SDK discovery now usesBLPAPI_ROOTonly (set by pixi activation or.cargo/config.toml). No hardcoded SDK version — build.rs scans versioned subdirs automatically. - Removed
BLPAPI_LINK_LIB_NAME: Library name is now always auto-detected bydetect_link_lib_name()based on target platform. - Build profiles cleaned up: Removed redundant
[profile.release.package.xbbg_core]; added[profile.dev.package."*"] opt-level = 2so all deps are optimised in dev builds;pixi run installusestarget-cpu=nativefor local builds. - Migrated from uv to pixi for dev tooling: Removed
[dependency-groups],[tool.uv.*]from pyproject.toml; deleteduv.lock; pre-commit hooks use bareruffinstead ofuvx ruff; README dev instructions updated to pixi commands. - Consolidated config files: Merged
.coveragercintopyproject.toml[tool.coverage.*]; deleted.env(pixi activation replaces it); un-gitignored.cargo/config.toml(now contains only project-standardBLPAPI_ROOT). - CI lint job uses pixi:
lint-pythonjob now usesprefix-dev/setup-pixiwith the lightweightlintenvironment, replacinguvx ruff. - Request tracing is more consistent: Python request middleware now sees the generated
request_idin bothRequestContext.request_idandRequestContext.params_dict, centralized request logs include the request ID, and the Rust request path forwards it as the Bloomberg request label for better audit/debug correlation. - Bindgen/libclang toolchain aligned: All Rust FFI crates now use
bindgen 0.72.1with runtime loading, and the pixi environment now requireslibclang >=22. This fixes incorrect Bloomberg SDKblpapi_ManagedPtr_t_generation under newer libclang releases and removes the need for correlation-ID layout workarounds.
Removed
Section titled “Removed”XBBG_DEV_SDK_ROOTenv var: UseBLPAPI_ROOTinstead. The.envfile fallback inblpapi-sys/build.rshas been removed.BLPAPI_LINK_LIB_NAMEenv var: Auto-detection covers all platforms.uv.lock: Replaced bypixi.lock..coveragerc: Configuration moved topyproject.toml.
- De-duplicated Rust recipe helpers: Extracted
array_value_as_string,date32_to_naive,as_string_colinto sharedxbbg-recipes/src/utils.rs. - De-duplicated Python code: Consolidated
_to_pandas_wide(was in bothinfo.pyandbloomberg.py); unified_FUTURES_MONTH_CODESto use Rust-sourcedext_get_futures_months(); extracted_apply_settle_overridehelper replacing 5 repeated blocks inbonds.py.
1.0.0b7 - 2026-03-18
Section titled “1.0.0b7 - 2026-03-18”- Python type stubs for
xbbg._coreviapyo3-stub-gen: auto-generated.pyifiles provide full IDE autocompletion and type-checker support forEngineConfig,Engine,Subscription, and all Rust-backed functions. Includespy.typedPEP 561 marker. - macOS ARM64 wheel builds in CI and release workflows. Wheels are now built and tested for Linux x86_64, Windows x86_64, and macOS ARM64 across Python 3.10–3.14.
- CI auto-regeneration of type stubs: stubs are regenerated and auto-committed after all CI checks pass, ensuring
.pyifiles stay in sync with Rust annotations. Engineclass for non-global multi-engine routing. Create independent engine instances and scope them viawith engine:(sync) orasync with engine:(async). The globalconfigure()+blp.bdp()API is unchanged —Engineis fully opt-in.- TLS support for encrypted B-PIPE connections:
tls_client_credentials,tls_trust_material,tls_handshake_timeout_msonEngineConfigandconfigure(). - Identity lifecycle FFI:
Session.generate_token(),Session.send_authorization_request(),Session.subscribe_with_identity()for multi-user entitlement flows. - Runtime SDK version:
get_sdk_info()now includesruntime_versionfield reporting the linked Bloomberg C SDK version viablpapi_getVersionInfo()(e.g.,"3.26.2.1"). Also available asxbbg._core.sdk_version()→(major, minor, patch, build)tuple. - Async request cancellation: cancelling the Python task for any async Bloomberg request now propagates to the Bloomberg SDK via
Session::cancel(correlationId). The worker drops local request state immediately after a successful cancel and remains usable for subsequent requests. - Reconnect resilience (Phases 1–3) for the Rust engine (#245):
- Fail-fast on session death: request workers now immediately drain all in-flight requests with an error on
SessionTerminated/SessionConnectionDowninstead of letting callers hang indefinitely. Workers are markedDeadand restored toHealthyonSessionConnectionUp. - Service re-open before re-subscribe:
recover_active_subscriptions()now re-opens all previously opened services before re-issuing subscriptions after reconnect, fixing a critical gap where recovery could silently fail. - Health-aware dispatch: request pool round-robin skips
Deadworkers; returnsAllWorkersDownimmediately if the entire pool is dead. - Retry with exponential backoff:
RetryPolicyonEngineConfig(retry_max_retries,retry_initial_delay_ms,retry_backoff_factor,retry_max_delay_ms) enables automatic retry of transient request failures. - Recovery limits:
max_recovery_attemptsandrecovery_timeout_mscap subscription recovery to prevent infinite loops. - Lifecycle events:
ConnectionLost,Reconnected, andRecoveryFailedevents emitted to subscription status for observability. - New error variants:
BlpAsyncError::SessionLostandAllWorkersDownmapped to PythonBlpSessionError. - Python surface: all new config fields exposed in
EngineConfig,configure(), andEngine();engine.worker_health()returns per-worker health status.
- Fail-fast on session death: request workers now immediately drain all in-flight requests with an error on
- Multi-server failover via
serverskwarg (#250). Pass a list of(host, port)tuples for automatic Bloomberg SDK failover usingsetServerAddress(host, port, index). Existinghost/portkwargs unchanged for single-server use. - ZFP over leased lines via
zfp_remotekwarg (#255). Set to"8194"or"8196"with TLS credentials to connect via Bloomberg Zero Footprint without a local Terminal. UsesZfpUtil::getOptionsForLeasedLinesfrom the SDK. - Identity entitlement checking (#252):
Identity.is_authorized(service),Identity.has_entitlements(service, eids), andIdentity.seat_type()for B-PIPE multi-user entitlement verification. - Bloomberg SDK logging bridge (#253):
enable_sdk_logging(level)andEngineConfig.sdk_log_levelroute native BLPAPI internal logs intoxbbg-logtracing targetxbbg.sdk. Default is off; registration happens before session start when enabled.
Changed
Section titled “Changed”- Engine Architecture & EngineConfig documentation: README now includes a full reference for all 20+
EngineConfigfields (worker pools, subscription tuning, buffers, validation, auth), an ASCII architecture diagram, and auth mode examples. - API surface updated to v1: README function tables, examples, and Connection Options section now reflect v1 names (
blkp,bport,earnings,convert_ccy,configure(),subscribe/stream, etc.) and remove stale v0.x references (lookupSecurity,exchange_tz,set_format,Formatenum). - Dev setup and contributing guides updated for v1 project structure (
py-xbbg/srcpaths, Astro docs,uv syncdependency-groups).
- cargo-deny advisory ignores for unmaintained
unic-*crates (transitive deps ofrustpython-parserviapyo3-stub-gen, build-time only).
1.0.0b6 - 2026-03-16
Section titled “1.0.0b6 - 2026-03-16”Changed
Section titled “Changed”- Internal correlation ID dispatch overhaul: The async engine no longer uses raw Bloomberg integer correlation IDs as direct slab indexes. All request and session dispatch now routes through an explicit dispatch-key layer at the session boundary, preventing ID collisions between auth subscriptions and user requests and aligning lifecycle tracking with Bloomberg SDK semantics.
- Logging levels better match the quiet-by-default workflow: Request roundtrip telemetry and Python subscription lifecycle messages now emit at
DEBUGinstead ofINFO, while exchange metadata fetch failures that cleanly fall back now emit atWARNINGinstead ofERROR, keeping normal control-flow noise out of default logs without hiding real request telemetry.
- SAPI authentication fails with
BLPAPI_ERROR_DUPLICATE_CORRELATIONID(#248):CorrelationId::default()returnedInt(0), which is a valid explicit correlation ID. WhensetSessionIdentityOptionsregisteredInt(0)for the auth flow, subsequentsendRequestcalls with the same default ID were rejected as duplicates (rc=131077). The default is nowCorrelationId::Unset(maps toBLPAPI_CORRELATION_TYPE_UNSETin the FFI struct), matching the official Pythonblpapibehavior where the SDK auto-generates unique IDs. Affects all SAPI authentication modes (app,user,userapp,dir,token).
1.0.0b5 - 2026-03-12
Section titled “1.0.0b5 - 2026-03-12”- Rust-backed Bloomberg session authentication for v1: Added structured auth support across the Rust core, async engine, and PyO3 bindings for
user,app,userapp,dir,manual, andtokenauth modes, enabling SAPI/B-PIPE session configuration from the v1 Python API. - Request middleware chain for telemetry and wrappers: Added
RequestContextplus middleware registration helpers aroundarequest()so callers can layer centralized request instrumentation, logging, caching, and wrapper behavior without patching individual endpoint functions.
Changed
Section titled “Changed”configure()is now the canonical engine/session setup surface: Connection/auth setup now flows throughconfigure()with support for legacy aliases such asserver_host,server_port,max_attempt, andauto_restart, while the temporaryconnect()/disconnect()wrappers were removed before release.
- Auth/session startup failures now propagate with context: Request and subscription workers now wait for Bloomberg startup/auth events before proceeding, so failed authentication and session-start problems surface as actionable errors instead of being swallowed or masked by later service-open failures.
- Rust/Python CI regressions in the new auth path: Cleaned release-blocking lint and formatting issues in the new auth/middleware code paths so the full Linux/Windows CI matrix passes with the beta 5 changes.
1.0.0b4 - 2026-03-10
Section titled “1.0.0b4 - 2026-03-10”Changed
Section titled “Changed”- Subscription failure isolation for mixed-topic streams: Real-time subscriptions now treat Bloomberg
SubscriptionFailureand unexpectedSubscriptionTerminatedevents as per-ticker status instead of fatal stream errors when other topics remain healthy. Mixed subscriptions keep delivering data for valid tickers while exposing failed topics through subscription metadata. - Subscription lifecycle observability: Real-time subscriptions now retain bounded status/event history for topic lifecycle transitions, session connectivity, service readiness, slow-consumer/data-loss signals, and reconnect recovery attempts so callers can inspect operational state without scraping logs.
- Non-fatal disconnect handling with opt-in recovery:
SessionConnectionDownno longer tears down healthy subscriptions by default. Callers can opt intorecovery_policy="resubscribe"to issue reconnect-time recovery subscribes while tracking attempts, successes, and last recovery errors through subscription status metadata.
- Subscription failure metadata: Python subscriptions now expose
failed_tickersandfailuresso callers can inspect which topics Bloomberg rejected or terminated, along with the reported reason and failure kind. - Subscription health/status surfaces: Python subscriptions now expose
status,events,topic_states,session_status,admin_status,service_status,all_failed, and expandedstatsfields including data-loss counters, last-message timestamps, and effective overflow policy.
1.0.0b3 - 2026-03-06
Section titled “1.0.0b3 - 2026-03-06”- Backend enum and availability checks (#234): Ported
Backendenum and backend availability infrastructure fromrelease/0.xintopy-xbbg/src/xbbg/backend.py. The canonicalBackendenum now has all 13 backends (addedCUDF,MODIN,DASK,IBIS,PYSPARK,SQLFRAME). New public helpers:is_backend_available(),check_backend(),get_available_backends(),print_backend_status(),validate_backend_format(),is_format_supported(),get_supported_formats(),check_format_compatibility(). IncludesMIN_VERSIONS,PACKAGE_NAMES,MODULE_NAMES, andSUPPORTED_FORMATSdicts for version validation and actionable install instructions.
Changed
Section titled “Changed”- Subscription mutation synchronization: Refactored subscription worker ownership to split the single-owner pool lease from a cloneable command handle, allowing subscription
add()/remove()paths in bothxbbg-asyncand PyO3 to drop metadata locks before awaiting Bloomberg command dispatch while still serializing mutations safely.
- Additional GIL release coverage in PyO3 bindings: Released the GIL around synchronous cache-save calls, Arrow pivot/format inspection helpers, and subscription metadata snapshots so Python threads are not blocked during disk I/O, pure Rust Arrow work, or waits on subscription state locks.
- Reduced avoidable Arrow-path copies: Removed intermediate string allocations for borrowed Bloomberg string/enum values and stopped cloning field-name/subfield-name vectors in
refdata,histdata, andbulkdataextraction paths before the existing zero-copy PyArrow export boundary. - Removed unused
liefdependency: Droppedlief>=0.17from core[project.dependencies]; the package was never imported anywhere in the codebase.
1.0.0b2 - 2026-03-05
Section titled “1.0.0b2 - 2026-03-05”- Field-validation toggle for refdata/histdata requests: Added optional
validate_fieldsrequest parameter inrequest()/arequest()and typed wrappers (abdp/bdp,abdh/bdh,abds/bds). This supports per-request strict validation override while still honoring engine-levelvalidation_modedefaults. - Engine-side field-validation enforcement:
xbbg-asyncnow validates requested fields forReferenceDataRequestandHistoricalDataRequestbefore dispatch when validation is enabled, returning configuration errors for unknown Bloomberg fields in strict mode. - Live validation toggle smoke script: Added
py-xbbg/tests/live/field_validation_toggle_smoke.pyto verify on/off behavior against a connected Bloomberg session. - Request-plumbing coverage for
validate_fields: Addedpy-xbbg/tests/test_validate_fields_toggle.pyto verify Python parameter serialization and forwarding through async/sync wrappers.
Changed
Section titled “Changed”- Canonical exception exports:
xbbg.exceptionsnow re-exports Rust_coreexception classes (BlpError,BlpRequestError, etc.) as the single source of truth, with Python-only exceptions remaining additive. - Validation helper compatibility: Preserved
BlpValidationError.from_rust_error(...)by attaching the compatibility classmethod to the canonical Rust-backed validation exception. - Generated sync wrapper metadata:
blp.pygenerated sync wrappers now derive__doc__and__annotations__from async templates directly; remaining manual generated sync wrapper boilerplate was removed. - Integration logging expectations: Updated logging integration assertions to match centralized
arequestrequest logging (bloomberg ... ReferenceDataRequest) instead of deprecated endpoint-specific debug strings. - Optional pandas integration paths: Updated pandas-dependent integration tests to use
pytest.importorskip("pandas"), avoiding hard failures when pandas is not installed.
except BlpErrorcatchability gap: Runtime exceptions raised by Rust (for exampleBlpRequestError) are now catchable viaxbbg.exceptions.BlpErrorimport paths because both now point to the same canonical Rust exception hierarchy.
1.0.0b1 - 2026-03-03
Section titled “1.0.0b1 - 2026-03-03”- Endpoint-factory regression tests: Added focused coverage for generated
abflds/bfldsandabqr/bqrrouting, validation, and reshape behavior inpy-xbbg/tests/test_endpoint_factory_bflds.pyandpy-xbbg/tests/test_endpoint_factory_bqr.py
Changed
Section titled “Changed”- Template endpoint generation in
blp.py: Migrated clean-fit wrappers to generated async/sync endpoints backed by_GeneratedEndpointSpecand_EndpointPlan, includingabdp/bdp,abdh/bdh,abds/bds,abdib/bdib,abdtick/bdtick,abql/bql,abqr/bqr,absrch/bsrch,abeqs/beqs,ablkp/blkp,abport/bport,abcurves/bcurves,abgovts/bgovts, andabflds/bflds
bqrpandas dependency regression: Removed unconditionalto_pandas()conversion in BQR postprocessing; quote requests now use Arrow-native checks/reshape and run without requiring pandas for standard flows
1.0.0a3 - 2026-02-27
Section titled “1.0.0a3 - 2026-02-27”bqr()/abqr()Bloomberg Quote Request: Tick-level dealer quotes withdate_offset(-2d,-1w,-3h),start_date/end_datedate ranges, and optionalinclude_broker_codes,include_spread_price,include_yield,include_condition_codes,include_exchange_codesparameters. Generic extractor fallback reshaped via_reshape_bqr_generic()bflds()/abflds()unified field metadata lookup: Single function for both field info (fields=[...]) and keyword search (search_spec='...').bfld/abfldprovided as backward-compatible aliases. Convenience wrappersfieldInfo()/fieldSearch()preservedinclude_security_errorsoption forbdp()/arequest(): Optionally surface per-security failures as rows in the result DataFrame instead of silently dropping them- Extension modules (
xbbg.ext):bonds(6 functions),options(6 functions + 5 enums),cdx(8 functions) for fixed income, equity options, and credit default swap index analytics - Streaming performance enhancements: Per-subscription config (
flush_threshold,overflow_policy,stream_capacity), observability metrics via shared atomics,tick_modesupport - Live integration tests: 69 tests across
test_ext_bonds.py(21),test_ext_options.py(20),test_ext_cdx.py(22) covering all ext module functions - Streaming tests: Tests for
tick_mode, per-subscription config, and observability metrics - Rust exchange/session APIs: Added low-level exchange resolution support with
ExchangeInfometadata, runtime exchange overrides, session timezone conversion utilities, andmarket_timinghelpers in the Rust layer (xbbg-ext,xbbg-async,pyo3-xbbg) - Live exchange smoke test: Added
py-xbbg/tests/live/test_exchange_resolution.pycovering override precedence, UTC session conversion, liveresolve_exchange,fetch_market_info, andmarket_timing
Changed
Section titled “Changed”- README: Updated API reference tables with
bflds(), expanded BQR section with spread/yield/broker parameters and examples - Futures resolver: Aligned with
release/0.xchain methodology (FUT_CHAIN_LAST_TRADE_DATES) - CDX resolver: Aligned methodology with
release/0.x
Removed
Section titled “Removed”- Legacy
xbbg/Python package directory: Fully removed; all code now lives inpy-xbbg/src/xbbg/
- Empty
RecordBatchconstruction: Handle empty ordered RecordBatch inxbbg-asyncwithout panic - Security failure surfacing:
refdataextractor now properly surfaces per-security errors instead of silently dropping them FIELD_SEARCHextractor: Corrected to useExtractorHint.FIELD_INFOinstead of generic extractor- Unused
loggingimport inext/options.py: Removed to pass ruff lint - Test imports:
BlpInternalErrorimported from_core(Rust) instead ofexceptions(Python) - CI fixes: Resolved 4 Python test failures, clippy warnings (
too_many_arguments,SubscriptionMetricsre-export), ruff check/format violations, cargo fmt formatting, module path fortest_markets.py, Linux test runtime setup - Exchange refdata parsing shape support:
resolve_exchangenow handles both WIDE and LONG refdata responses by mapping(field, value)rows when Bloomberg returns long-shape metadata
1.0.0a2 - 2026-02-19
Section titled “1.0.0a2 - 2026-02-19”Changed
Section titled “Changed”- README: Comprehensive rewrite with full API reference tables, comparison matrix, multi-backend documentation, detailed intraday session guide, fixed income/options/CDX analytics examples, troubleshooting section, and data storage documentation
1.0.0a1 - 2026-02-19
Section titled “1.0.0a1 - 2026-02-19”- Rust-powered engine: Complete ground-up rewrite delivering up to 10x faster data retrieval with zero-copy Arrow transfer between Rust and Python. The engine spans 11 purpose-built crates: safe FFI bindings with SIMD-accelerated parsing (
blpapi-sys,xbbg-core), an async worker pool engine with state machines for every Bloomberg request type (xbbg-async), Rust ports of extension and recipe logic (xbbg-ext,xbbg-recipes— all 12 recipes exposed via PyO3), zero-GIL tracing (xbbg-log), CI/test stubs (xbbg-sys), and PyO3 Python bindings (pyo3-xbbg) - New Python package (
py-xbbg/): Complete v1 API powered by the Rust backend, replacing the pure-Pythonxbbg/package. Lazy-loaded via__getattr__for near-instant import - Streaming APIs:
vwap()/avwap()for VWAP streaming (//blp/mktvwap),mktbar()/amktbar()for market bar streaming,depth()/adepth()for market depth (B-PIPE),chains()/achains()for option/futures chain streaming (B-PIPE) — all with async variants - New Bloomberg API functions:
bcurves()/abcurves()for yield curve lookup,bgovts()/abgovts()for government securities lookup,bflds()/abflds()for field search (replacingfieldInfo/fieldSearch) - Generic request API:
request()/arequest()— direct access to any Bloomberg service and operation with schema-driven kwargs routing. Power users can hit any Bloomberg endpoint without a dedicated wrapper - Schema introspection:
bops()/abops()to list service operations,bschema()/abschema()for full service schema,get_schema()/aget_schema(),list_operations()/alist_operations(),get_enum_values()/aget_enum_values(),list_valid_elements()/alist_valid_elements()— all with async variants.generate_stubs()andconfigure_ide_stubs()for IDE auto-completion generated from live Bloomberg schemas - Field type cache:
FieldTypeCache,FieldInfo,resolve_field_types()/aresolve_field_types(),cache_field_types(),get_field_info(),clear_field_cache()for caching and resolving Bloomberg field metadata - Engine lifecycle management:
shutdown(),reset(),is_connected()for explicit Rust engine control EngineConfig: Rust-native engine configuration (PyO3PyEngineConfig) — subscription pool size, request pool size, flush thresholds, auto-restart on disconnection- Auto-restart on disconnection: Subscription sessions automatically reconnect after network interruptions via
setAutoRestartOnDisconnection Time64Microsvalue type: Microsecond-precision time-of-day extraction from BloombergDatetimefields, with ArrowTime64Microstype support in generic, histdata, and refdata state handlersBlpBPipeErrorexception: New exception class for B-PIPE-specific errors, added to the existing exception hierarchy- Technical Analysis improvements:
ta_study_params()to inspect study parameters,generate_ta_stubs()for IDE auto-completion of TA study names - Logging control:
set_log_level(),get_log_level()to control Rust-side tracing verbosity without Python overhead - Bloomberg SDK message receive time:
Message::receive_time()for latency measurement and diagnostics - Service definitions:
Service,Operation,OutputMode,RequestParams,ExtractorHintenums for type-safe Bloomberg service configuration - Extension modules (
py-xbbg/src/xbbg/ext/):currency,fixed_income,futures,historical— ported to work with the Rust backend in LONG format - Markets module (
py-xbbg/src/xbbg/markets/):bloomberg,info,overrides,resolvers,sessions— exchange metadata, market timing, and override normalization - Data definition files:
defs/bloomberg.tomlanddefs/exchanges.tomlfor data-driven Bloomberg and exchange configuration - Starlight documentation site: Full rewrite from Sphinx to Astro Starlight — API reference (
blp.md,exceptions.md,schema.md,services.md), getting started guides (installation.mdx,introduction.mdx,quickstart.mdx), async/streaming/migration/output-format guides, and configuration reference - Benchmark suites: Rust benchmarks via Criterion (
xbbg-bench— allocation profiling, datetime/name micro-benchmarks, cached response parsing, livebdp/subscription benchmarks) and Python benchmarks (benchmarks/—bdp,bdh,bdib,bdtick,bql, rawblpapiwith version-based result tracking) - Comprehensive test suites:
py-xbbg/tests/with unit tests for imports, backends, blp API, backend conversion, currency conversion, exceptions, futures validation, integration, markets, and yield types. Live test suite (py-xbbg/tests/live/) for API, engine, subscription lifecycle, and subscription fixes - CI infrastructure:
ci-rust.ymlfor multi-platform Rust CI (clippy, rustfmt, unit tests, integration tests,cargo-audit,cargo-deny, semver-checks),ci-docker.ymlfor reusable container image builds, Docker containers for Rust CI and manylinux wheel builds - Codegen tool (
codegen/generate.py): Python code generator for service definitions, includingSEMI_LONGoutput format support fromrelease/0.x - SDK setup script (
scripts/sdktool.ps1): PowerShell script for Bloomberg SDK vendor layout management cargo-denyconfiguration (deny.toml): License and security policy for all Rust dependencies- Future language binding scaffolds:
bindings/napi-xbbg/(Node.js N-API),bindings/dotnet-xbbg/(.NET),apps/xbbg-cli/(CLI),apps/xbbg-server/(server), andjs-xbbg/(npm package) vendor/blpapi-sdk/README.md: Instructions for vendoring the Bloomberg C++ SDK locally
Changed
Section titled “Changed”- Build system: Switched to
setuptools-rust(PyO3) withsetuptools_scmversioning.pyproject.tomlnow builds the Rust extension viasetuptools.build_meta - Python package source location: Moved from
xbbg/(in-tree) topy-xbbg/src/xbbg/for the Rust-backed package layout. The native extension is compiled asxbbg._core - Runtime dependencies:
pandasis no longer required — now onlynarwhals>=1.30,pyarrow>=22.0.0,lief>=0.17. Removedblpapi,tomli, and all other previous hard dependencies - Python version support: Added Python 3.14 to classifiers (
>=3.10,<3.15) pypi_upload.ymlworkflow: Completely rewritten forsetuptools-rustwheel builds with Bloomberg SDK detection, replacing the pure-Python sdist/wheel workflowpre-commit-config.yaml: Updated hooks for the Rust+Python monorepo — addedcargo fmt,cargo clippy, and scoped ruff topy-xbbg/andxbbg/.gitignore: Expanded for Rust build artifacts (target/), native extension outputs, SDK vendor directory, benchmark results, and IDE files- README.md: Rewritten for v1.0 — concise project description, Rust-powered backend highlights, installation and quick start replacing the extensive v0.x documentation
- CONTRIBUTING.md: Rewritten for the Rust+Python development workflow
- LICENSE: Updated to Apache-2.0 with revised copyright
- Maximum-performance release builds:
lto = "fat",codegen-units = 1,panic = "abort",strip = "symbols"for production;opt-level = 3forxbbg-core,opt-level = 2for dev - Subscription pool default: Reduced from 4 to 1 worker, consolidated into
EngineConfig - Legacy
xbbg/package: Minor cleanups — addedfrom __future__ import annotationsacross all__init__.pyfiles, normalized docstring quotes from single to double, removed# noqalint suppression comments, replacedlambda: []withlistin pipeline factory registry default resolvers
Removed
Section titled “Removed”xbbg/__init__.py: Top-level package init replaced bypy-xbbg/src/xbbg/__init__.pywith Rust backendxbbg/blp.py: 178-line deprecation compatibility layer — all functions now live inpy-xbbg/src/xbbg/blp.pybacked by Rustxbbg/const.py: 187-line constants module — constants moved to Rust crates anddefs/*.tomlxbbg/core/__init__.py: 35-line core package init — core functionality replaced by Rust enginexbbg/core/process.py: 787-line Bloomberg message processing module — replaced byxbbg-asyncRust engine state machinesxbbg/utils/pipeline.py: 336-line pipeline utilities — replaced by Rust engine pipelinexbbg/io/__init__.py: IO module init removed (module gutted in v0.12.0)xbbg/markets/__init__.py: 76-line markets package init — replaced bypy-xbbg/src/xbbg/markets/xbbg/markets/resolvers.py: Futures/CDX resolvers moved toxbbg-extRust crateexamples/feeds/pub.pyandexamples/feeds/sub.py: Legacy feed examples- Sphinx documentation:
docs/conf.py,docs/index.rst(1,293 lines),docs/Makefile,docs/make.bat,docs/docstring_style.rst— replaced by Starlight .readthedocs.yaml: ReadTheDocs configuration (docs now use Starlight)MANIFEST.in: No longer needed with thesetuptools-rustbuild systemSECURITY.md: Security policy document_config.yml: Jekyll configurationcodecov.yml: Codecov configuration- 9 CI workflows:
auto_ci.yml,ci_docs.yml,codeql-analysis.yml,publish_docs.yml,publish_testpypi.yml,pypi_build_test.yml,release_assets.yml,update_index_on_release.yml,update_readme_on_release.yml— consolidated intoci-rust.yml,ci-docker.yml, and rewrittenpypi_upload.yml
- Clippy 1.93 lints: Resolved
map_orand doc indentation warnings across all Rust crates - Windows LLVM/
LIBCLANG_PATHsetup: Fixed detection and configuration forbindgenon Windows CI - Linux
LIBCLANG_PATHdetection: Fixedlibclang-devpath resolution on Linux CI - Non-ASCII characters in comments: Replaced em dashes with ASCII equivalents to pass CI source checks
- Subscription slab key reuse race: Prevented key reuse on subscription removal in
xbbg-asyncthat could cause events to route to wrong handlers - Subscription error propagation: Subscription errors now propagate as Python exceptions via PyO3 instead of being silently swallowed
- Subscription pipeline rewrite: Multi-type support, error propagation, and event time tracking in
xbbg-async Datetimefield zeroed date parts: Added parts bitmask check to correctly handle BloombergDatetimefields with zeroed date components- DLL search path setup (Windows): Moved SDK DLL search path configuration to module level in
py-xbbgto fixfrom xbbg._core import Xfailures Request::set_bool: UsesetElementStringfor Bool elements in Bloomberg requests (Bloomberg API quirk)- TA study requests: Wired through
elementsinstead of unusedjson_elementspath WIDEformat compatibility: Produces 0.7.7-compatible DataFrame structure from the Rust backend- Backend double-conversion bug: Fixed duplicate conversion when Rust backend returns data that is then converted again by Python
0.12.0 - 2026-02-18
Section titled “0.12.0 - 2026-02-18”- Async-first architecture: All Bloomberg API functions (
bdp,bds,bdh,bdib,bdtick,bql,beqs,bsrch,bqr,bta) now have async counterparts (abdp,abds,abdh, etc.) as the source of truth; sync wrappers delegate via_run_sync()(#218) - Bond analytics module (
xbbg.ext.bonds): 6 new functions for fixed income analytics —bond_info(reference metadata and ratings),bond_risk(duration, convexity, DV01),bond_spreads(OAS, Z-spread, I-spread, ASW),bond_cashflows(cash flow schedule),bond_key_rates(key rate durations and risks),bond_curve(multi-bond relative value comparison) - Options analytics module (
xbbg.ext.options): 6 new functions and 5 enums for equity option analytics —option_info(contract metadata),option_greeks(Greeks and implied volatility),option_pricing(value decomposition and activity),option_chain(chain viaCHAIN_TICKERSwith overrides),option_chain_bql(chain via BQL with rich filtering),option_screen(multi-option comparison). Enums:PutCall,ChainPeriodicity,StrikeRef,ExerciseType,ExpiryMatch - CDX analytics (
xbbg.ext.cdx): 8 new functions for credit default swap index analytics —cdx_info,cdx_defaults,cdx_pricing,cdx_risk,cdx_basis,cdx_default_prob,cdx_cashflows,cdx_curve.cdx_pricing/cdx_risksupportCDS_RRrecovery rate override YieldTypeexpanded: AddedYTW(Yield to Worst),YTP(Yield to Put),CFY(Cash Flow Yield) toYieldTypeenumworkout_dtparameter foryas(): Workout date for yield-to-worst/call calculations, maps toYAS_WORKOUT_DTBloomberg override. Acceptsstr(YYYYMMDD) ordatetimetzparameter forbdib()/abdib(): Controls output timezone for intraday bar data. Defaults toNone(exchange local timezone, matching v0.7.x behavior). Settz='UTC'to keep UTC timestamps, or pass any IANA timezone string (e.g.,'Europe/London')exchange_tz()helper: Returns the IANA timezone string for any Bloomberg ticker (e.g.,blp.exchange_tz('AAPL US Equity')->'America/New_York'). Exported viablp.exchange_tz()- LONG_TYPED output format: New
_to_long_typed()function produces typed value columns (value_f64,value_i64,value_str,value_bool,value_date,value_ts) with exactly one populated per row based on the Arrow type of each field - LONG_WITH_METADATA output format: New
_to_long_with_metadata()function produces(ticker, date, field, value, dtype)wherevalueis stringified anddtypecontains the Arrow type name (e.g.double,int64,string) - CI non-ASCII source check: New
auto_ci.ymlstep rejects non-ASCII characters in Python source files (allows CJK for ticker tests) - Comprehensive test coverage: 55+ new tests including bond analytics (7), CDX analytics (8), options analytics, timezone conversion (13),
ovrdsdict normalization (7),_events_to_table()(16),bdtickformat variants (5), mixed-type BDP (2), and output format tests (12)
Changed
Section titled “Changed”- Unified I/O layer: All Bloomberg requests now flow through a single
arequest()async entry point inconn.py, replacing scattered session/service management across modules (#218) - Futures resolution uses
FUT_CHAIN_LAST_TRADE_DATES(#223): Replaced manual candidate generation (FUT_GEN_MONTH+ batchbdp) with Bloomberg-nativeFUT_CHAIN_LAST_TRADE_DATESvia singlebds()call. ~2x faster (0.25-0.30s vs 0.53-0.72s) sync_apidecorator: Replaces 13 hand-written sync wrappers across API modules (screening.py,historical.py,intraday.py, etc.) with a singlesync_api(async_fn)call- Table-driven deprecation wrappers: 23 manual wrapper functions in
blp.pyreplaced by dict + loop pattern; 24warn_*functions indeprecation.pyreplaced by_DEPRECATION_REGISTRY+get_warn_func()lookup - Market session rules extracted to TOML (
markets/config/sessions.toml): All MIC and exchange code rules moved fromsessions.pyinto data-driven TOML config, reducingsessions.pyfrom 364 to 168 lines (54% reduction) - Pipeline factory registry (
pipeline_factories.py): Centralized factory dispatch replaces scattered conditionals - CDX ticker format corrected: Version is now a separate space-delimited token (e.g.,
CDX HY CDSI S45 V2 5Y Corpinstead ofS45V2) tomliconditional dependency added:tomli>=2.0.1for Python < 3.11 (TOML parsing forsessions.toml)- Net reduction of ~1,346 lines across 27 files from codegen and table-driven optimizations
Removed
Section titled “Removed”xbbg/io/db.py: SQLite database helper module (zero imports across codebase) (#218)xbbg/io/param.py: Legacy parameter/configuration module (zero imports across codebase) (#218)xbbg/io/files.py: File path utility module (zero imports after replacing 6 usages incache.pyandconst.pywithpathlib.Path) (#218)regression_testing/: Standalone v0.7.7 regression test directory; all scenarios covered bytest_live_endpoints.py(#218)MONTH_CODE_MAPand futures candidate generation helpers: Superseded byFUT_CHAIN_LAST_TRADE_DATESchain resolution (#223)- Stale files:
pmc_cache.json,xone.db, empty__init__files,test_param.py(#218)
bdtickformat parameter was completely non-functional: All five output formats (LONG, SEMI_LONG, WIDE, LONG_TYPED, LONG_WITH_METADATA) were broken due to MultiIndex column wrapping, killed index name, and mixed-type Arrow conversion errorsbdibtimezone regression: The Arrow pipeline rewrite (v0.11.0) dropped the UTC-to-exchange local timezone conversion that existed in v0.7.x. Restored with configurabletzparameterArrowInvalidon multi-field BDP calls: Bloomberg returns different Python types for different fields. New_events_to_table()builds Arrow tables with automatic type coercion fallback (#219)create_requestcrashed whenovrdspassed as dict: Now normalizes dict to list of tuples before iteration (SO#79880156)- Case-sensitive
backendandformatparameters: Added_missing_classmethod toBackendandFormatenums for case-insensitive lookup (#221) - Mock session leak in tests: Added autouse
_reset_session_managerfixture to preventMagicMockpersistence across test modules (#213) intervalparameter leaked as Bloomberg override: Added toPRSV_COLSso it stays local (#145)StrEnumPython 3.10 compatibility: Added polyfill for Python < 3.11- Non-ASCII characters in source: Replaced with ASCII equivalents for CI compliance
Security
Section titled “Security”- Bump
cryptographyfrom 46.0.4 to 46.0.5: Fixes CVE-2026-26007 (#217)
0.12.0b3 - 2026-02-16
Section titled “0.12.0b3 - 2026-02-16”- Bond analytics module (
xbbg.ext.bonds): 6 new functions for fixed income analytics —bond_info(reference metadata and ratings),bond_risk(duration, convexity, DV01),bond_spreads(OAS, Z-spread, I-spread, ASW),bond_cashflows(cash flow schedule),bond_key_rates(key rate durations and risks),bond_curve(multi-bond relative value comparison) - Options analytics module (
xbbg.ext.options): 6 new functions and 5 enums for equity option analytics —option_info(contract metadata),option_greeks(Greeks and implied volatility),option_pricing(value decomposition and activity),option_chain(chain viaCHAIN_TICKERSwith overrides),option_chain_bql(chain via BQL with rich filtering),option_screen(multi-option comparison). Enums:PutCall,ChainPeriodicity,StrikeRef,ExerciseType,ExpiryMatch - CDX analytics (
xbbg.ext.cdx): 8 new functions for credit default swap index analytics —cdx_info,cdx_defaults,cdx_pricing,cdx_risk,cdx_basis,cdx_default_prob,cdx_cashflows,cdx_curve.cdx_pricing/cdx_risksupportCDS_RRrecovery rate override YieldTypeexpanded: AddedYTW(Yield to Worst),YTP(Yield to Put),CFY(Cash Flow Yield) toYieldTypeenumworkout_dtparameter foryas(): Workout date for yield-to-worst/call calculations, maps toYAS_WORKOUT_DTBloomberg override. Acceptsstr(YYYYMMDD) ordatetimetzparameter forbdib()/abdib(): Controls output timezone for intraday bar data. Defaults toNone(exchange local timezone, matching v0.7.x behavior). Settz='UTC'to keep UTC timestamps, or pass any IANA timezone string (e.g.,'Europe/London')exchange_tz()helper: Returns the IANA timezone string for any Bloomberg ticker (e.g.,blp.exchange_tz('AAPL US Equity')->'America/New_York'). Exported viablp.exchange_tz()tzfield onDataRequestandRequestBuilder: Propagates timezone control through the pipeline.RequestBuildergains.tz()builder method- CI non-ASCII source check: New
auto_ci.ymlstep rejects non-ASCII characters in Python source files (allows CJK for ticker tests) - Live endpoint tests: 7 tests for bond analytics, 8 tests for CDX analytics, plus options analytics coverage in
test_live_endpoints.py - 13 unit tests for timezone conversion (
test_intraday_timezone.py): Covers default exchange tz, explicit UTC, explicit timezone, Japanese equities, empty exchange info, empty tables, column renaming, and DataRequest/RequestBuilder propagation - 7 regression tests for
ovrdsdict normalization (test_overrides.py): Covers dict crash, correct element setting, multiple overrides, list-of-tuples backward compat, and None/empty edge cases
Changed
Section titled “Changed”- Futures resolution uses
FUT_CHAIN_LAST_TRADE_DATES(#223): Replaced manual candidate generation (FUT_GEN_MONTH+ batchbdp) with Bloomberg-nativeFUT_CHAIN_LAST_TRADE_DATESvia singlebds()call. ~2x faster (0.25-0.30s vs 0.53-0.72s). RemovedMONTH_CODE_MAP,_get_cycle_months,_construct_contract_ticker sync_apidecorator: Replaces 13 hand-written sync wrappers across API modules (screening.py,historical.py,intraday.py, etc.) with a singlesync_api(async_fn)call- Table-driven deprecation wrappers: 23 manual wrapper functions in
blp.pyreplaced by dict + loop pattern; 24warn_*functions indeprecation.pyreplaced by_DEPRECATION_REGISTRY+get_warn_func()lookup - Market session rules extracted to TOML (
markets/config/sessions.toml): All MIC and exchange code rules moved fromsessions.pyinto data-driven TOML config, reducingsessions.pyfrom 364 to 168 lines (54% reduction) - Pipeline factory registry (
pipeline_factories.py): Centralized factory dispatch replaces scattered conditionals - Wildcard imports in
__init__.pyfiles: 9__init__.pyfiles simplified to use wildcard imports with explicit__all__lists - CDX ticker format corrected: Version is now a separate space-delimited token (e.g.,
CDX HY CDSI S45 V2 5Y Corpinstead ofS45V2) tomliconditional dependency added:tomli>=2.0.1for Python < 3.11 (TOML parsing forsessions.toml)- Net reduction of ~1,346 lines across 27 files from codegen and table-driven optimizations
Removed
Section titled “Removed”update_readme_on_release.ymlworkflow: Inline changelog in README replaced by link toCHANGELOG.mdMONTH_CODE_MAPand futures candidate generation helpers: Superseded byFUT_CHAIN_LAST_TRADE_DATESchain resolution (#223)
bdibtimezone regression: The Arrow pipeline rewrite (v0.11.0) dropped the UTC-to-exchange local timezone conversion that existed in v0.7.x. Intraday bar timestamps were returned in UTC instead of exchange local time. Restored the conversion inIntradayTransformer.transform()with configurabletzparametercreate_requestcrashed whenovrdspassed as dict:create_request(ovrds={"PRICING_SOURCE": "BGN"})raisedValueError: too many values to unpackbecause iterating a dict yields keys (strings), not (key, value) tuples. Now normalizes dict to list of tuples before iteration. Also updated type annotation to acceptdict[str, Any](SO#79880156)- Case-sensitive
backendandformatparameters:Backend("POLARS")andFormat("WIDE")raisedValueErrorbecause enum values are lowercase. Added_missing_classmethod to bothBackendandFormatenums for case-insensitive lookup (#221) StrEnumPython 3.10 compatibility: AddedStrEnumpolyfill in options module for Python < 3.11 whereenum.StrEnumdoes not exist- Python 3.10 mock patching: Fixed
patch.object()usage for Python 3.10 compatible mock patching in tests by exposing submodules and patching at source - Non-ASCII characters in source: Replaced checkmarks, em dashes, and arrows with ASCII equivalents across the codebase for CI compliance
- Ruff lint errors: Fixed import sorting (I001) and docstring formatting issues
0.12.0b2 - 2026-02-13
Section titled “0.12.0b2 - 2026-02-13”- 16 unit tests for
_events_to_table()(test_events_to_table.py): covers basic contract, mixed-type columns (float+str, int+str, float+date, kitchen sink), null handling, non-uniform dict keys, and pipeline integration (#219) - 2 live regression tests for mixed-type BDP (
test_live_endpoints.py):test_bdp_mixed_type_fieldsandtest_bdp_mixed_type_multiple_tickersexercise the exact bug scenario withES1 Index/NQ1 IndexusingFUT_CONT_SIZE+FUT_VAL_PT(#219)
ArrowInvalidon multi-field BDP calls: Bloomberg returns different Python types for different fields (e.g.,floatforFUT_CONT_SIZE,strforFUT_VAL_PT). When both land in the same Arrow value column,pa.array()raisedArrowInvalid. New_events_to_table()builds Arrow tables directly from event dicts with automatic type coercion fallback — stringify onArrowInvalid/ArrowTypeError, preserving nulls (#219)- Post-transform
pa.Table.from_pandas()mixed-type failure: Protected the secondary Arrow conversion (after narwhals transform) with the same stringify fallback for object columns (#219)
0.12.0b1 - 2026-02-12
Section titled “0.12.0b1 - 2026-02-12”Changed
Section titled “Changed”- Async-first architecture: All Bloomberg API functions (
bdp,bds,bdh,bdib,bdtick,bql,beqs,bsrch,bqr,bta) now have async counterparts (abdp,abds,abdh, etc.) as the source of truth; sync wrappers delegate via_run_sync()(#218) - Unified I/O layer: All Bloomberg requests now flow through a single
arequest()async entry point inconn.py, replacing scattered session/service management across modules (#218) - Pipeline and process modules: Adapted
pipeline_core,process, andrequest_builderto work with the asyncarequest()foundation (#218) - Top-level async exports: All async API variants (
abdp,abds,abdh,abdib,abdtick,abql,abeqs,absrch,abqr,abta) exported fromxbbg.blp(#218) - IO module cleanup: Removed dead code and fixed type annotations across
xbbg/io/(#218) - Test coverage expanded: 571 tests total (up from 543), covering all connection-related GitHub issues and all previously untested paths in
conn.py
Removed
Section titled “Removed”xbbg/io/db.py: SQLite database helper module (zero imports across codebase) (#218)xbbg/io/param.py: Legacy parameter/configuration module (zero imports across codebase) (#218)xbbg/io/files.py: File path utility module (zero imports after replacing 6 usages incache.pyandconst.pywithpathlib.Path) (#218)xbbg/tests/test_param.py: Tests for deletedparammodule (7 tests) (#218)xbbg/markets/cached/pmc_cache.json: Stale pandas-market-calendars cache file (pmc dependency removed in v0.11.0) (#218)xbbg/tests/__init__.py,examples/feeds/__init__.py: Empty__init__files (#218)xbbg/tests/xone.db: Stale SQLite test database (#218)regression_testing/: Standalone v0.7.7 regression test directory (6 files); all 9 test scenarios already covered byxbbg/tests/test_live_endpoints.pywith stricter assertions (#218)
- Mock session leak in tests: Added autouse
_reset_session_managerfixture inconftest.pyto preventMagicMocksessions from persisting in theSessionManagersingleton across test modules, which caused infinite__getattr__→_get_child_mockrecursion and stack overflow on Windows (#213) intervalparameter leaked as Bloomberg override:intervalwas not inPRSV_COLS, causing it to be sent to Bloomberg as an override field instead of being used locally for bar sizing (#145)- README Data Storage section: Clarified that only
bdib()(intraday bars) has caching viaBarCacheAdapter; all other functions always make live Bloomberg API calls (#215) - README async example for Jupyter: Fixed
asyncio.run()example that fails in notebooks (which already have a running event loop) by addingawait-based andnest_asyncioalternatives (#216) - Unused imports in tests: Removed
import osfromtest_intraday_api.pyandimport pytestfromtest_logging.pythat caused Ruff F401 lint failures in CI
Security
Section titled “Security”- Bump
cryptographyfrom 46.0.4 to 46.0.5: Fixes CVE-2026-26007 — subgroup attack due to missing validation for SECT binary elliptic curves (#217)
0.11.4 - 2026-02-06
Section titled “0.11.4 - 2026-02-06”bdtickArrow conversion failure: Object columns containingblpapi.Nameinstances causedpa.Table.from_pandas()to fail; now stringified before conversionadjust_ccyfield name mismatch: Looked for"Last_Price"butbdhreturns lowercase"last_price"since v0.11.1, causingKeyErroractive_futurestwo failures: Usednw.coalesce()with a column (last_tradeable_dt) not present in SEMI_LONG format, and called.height(not valid on narwhals DataFrame) instead of.shape[0]- Live test assertions: Updated 10 tests in
test_live_endpoints.pyto match WIDE format default (active since v0.7.x)
0.11.3 - 2026-02-06
Section titled “0.11.3 - 2026-02-06”- Duplicate
portkeyword argument:bbg_service()andbbg_session()used.get()to extractportthen forwarded**kwargsstill containing it, causingTypeError: got multiple values for keyword argument 'port'on non-default ports (e.g., B-Pipe connections) (#212) - Session resource leak:
clear_default_session()set_default_session = Nonewithout callingsession.stop(), leaking OS file descriptors over repeated connect/disconnect cycles (#211) - Wrong session removed on retry:
send_request()retry path calledremove_session(port=port)withoutserver_host, always targeting//localhost:{port}even for remote hosts - Inconsistent
server_hostextraction:get_session()/get_service()checkedserver_hostbeforeserver, butconnect_bbg()did the opposite, causing different code paths to resolve different hosts when both keys were present - Resource leak on start failure:
connect_bbg()did not stop the session before raisingConnectionErrorwhen.start()failed, leaking C++ resources allocated by theSession()constructor
0.11.2 - 2026-02-05
Section titled “0.11.2 - 2026-02-05”- Extended multi-backend support: Added 6 new backends matching narwhals’ full backend support:
- Eager backends:
cudf(GPU-accelerated via NVIDIA RAPIDS),modin(distributed pandas) - Lazy backends:
dask(parallel computing),ibis(portable DataFrame expressions),pyspark(Apache Spark),sqlframe(SQL-based DataFrames) - Total: 13 backends (6 eager + 7 lazy)
- Eager backends:
- Backend availability checking: New functions to check and validate backend availability with helpful error messages:
is_backend_available(backend)- Check if a backend package is installedcheck_backend(backend)- Check availability with version validation, raises helpful errorsget_available_backends()- List all currently available backendsprint_backend_status()- Diagnostic function showing all backend statuses
- Format compatibility checking: New functions to validate format support per backend:
is_format_supported(backend, format)- Check if a format works with a backendget_supported_formats(backend)- Get set of supported formats for a backendcheck_format_compatibility(backend, format)- Validate with helpful errorsvalidate_backend_format(backend, format)- Combined validation for API functions
xbbg.extmodule: New extension module for v1.0 migration containing helper functions that will be removed fromblpnamespacexbbg.ext.currency-adjust_ccy()for currency conversionxbbg.ext.dividends-dividend()for dividend historyxbbg.ext.earnings-earning()for earnings breakdownsxbbg.ext.turnover-turnover()for trading volumexbbg.ext.holdings-etf_holdings(),preferreds(),corporate_bonds()BQL helpersxbbg.ext.futures-fut_ticker(),active_futures()for futures resolutionxbbg.ext.cdx-cdx_ticker(),active_cdx()for CDX index resolutionxbbg.ext.yas-yas(),YieldTypefor fixed income analytics
- New v1.0-compatible import path:
from xbbg.ext import dividend, fut_ticker, ...(no deprecation warnings) - Pandas removed as required dependency:
xbbg.extmodules now use only stdlib datetime and narwhals, making pandas fully optional
Changed
Section titled “Changed”- Backend enum reorganized: Backends now categorized as eager (full API) vs lazy (deferred execution)
- Format restrictions: WIDE format only available for eager backends (pandas, polars, pyarrow, narwhals, cudf, modin); lazy backends limited to LONG and SEMI_LONG
- Version requirements updated: Minimum versions now match narwhals requirements (duckdb>=1.0, dask>=2024.1)
xbbg/markets/resolvers.pynow re-exports fromxbbg.ext.futuresandxbbg.ext.cdxfor backwards compatibility- Internal implementations moved to
xbbg/ext/module; old import paths still work with deprecation warnings
- BDS output format: Restored v0.10.x backward compatibility for
bds()output format (#209)- Default
format='wide'now returns single data column with ticker as index (pandas) or column (other backends) - Field column dropped for cleaner output matching v0.10.x behavior
- Users can opt-in to new 3-column format with
format='long'
- Default
- ibis backend: Updated to use
ibis.memtable()instead of deprecatedcon.read_in_memory() - sqlframe backend: Fixed import path to use
sqlframe.duckdb.DuckDBSession
0.11.1 - 2026-02-05
Section titled “0.11.1 - 2026-02-05”- Field names now lowercase: Restored v0.10.x behavior where
bdp(),bdh(), andbds()return field/column names as lowercase (#206)
0.11.0 - 2026-02-02
Section titled “0.11.0 - 2026-02-02”- Arrow-first pipeline: Complete rewrite of internal data processing using PyArrow for improved performance
- Multi-backend support: New
Backendenum supporting narwhals, pandas, polars, polars_lazy, pyarrow, duckdb - Output format control: New
Formatenum with long, semi_long, wide options - bta(): Bloomberg Technical Analysis function for 50+ technical indicators (#175)
- bqr(): Bloomberg Quote Request function emulating Excel
=BQR()for dealer quote data with broker attribution (#22) - yas(): Bloomberg YAS (Yield Analysis) wrapper for fixed income analytics with
YieldTypeenum - preferreds(): BQL convenience function to find preferred stocks for an equity ticker
- corporate_bonds(): BQL convenience function to find active corporate bonds for a ticker
set_backend(),get_backend(),set_format(),get_format()configuration functionsget_sdk_info()as replacement for deprecatedgetBlpapiVersion()- v1.0-compatible exception classes (
BlpError,BlpSessionError,BlpRequestError, etc.) EngineConfigdataclass andconfigure()function for engine configurationServiceandOperationenums for Bloomberg service URIs- Treasury & SOFR futures support: TY, ZN, ZB, ZF, ZT, UB, TN, SFR, SR1, SR3, ED futures (#198)
- Comprehensive logging improvements across critical paths with better error traceability
- CONTRIBUTING.md and CODE_OF_CONDUCT.md for community standards
Changed
Section titled “Changed”- All API functions now accept
backendandformatparameters - Internal pipeline uses PyArrow tables with narwhals transformations
- Removed pytz dependency (using stdlib
datetime.timezone) - Intraday cache now includes interval in path (#80) - different bar intervals cached separately (breaking: existing cache will miss)
- Internal class renames with backward compatible aliases (
YamlMarketInfoProvider→MetadataProvider) - Logging level adjustments:
BBG_ROOT not setpromoted to WARNING, cache timing demoted to DEBUG
Deprecated
Section titled “Deprecated”connect()/disconnect()- engine auto-initializes in v1.0getBlpapiVersion()- useget_sdk_info()insteadlookupSecurity()- will becomeblkp()in v1.0fieldInfo()/fieldSearch()- will merge intobfld()in v1.0bta_studies()- renamed tota_studies()in v1.0getPortfolio()- renamed tobport()in v1.0- Helper functions (
dividend(),earning(),turnover(),adjust_ccy()) moving toxbbg.extin v1.0 - Futures/CDX utilities (
fut_ticker(),active_futures(),cdx_ticker(),active_cdx()) moving toxbbg.extin v1.0
Removed
Section titled “Removed”- Trials mechanism: Eliminated retry-blocking system that caused silent failures after 2 failed attempts
- pandas-market-calendars dependency: Exchange info now sourced exclusively from Bloomberg API with local caching
- Import without blpapi installed: Fixed
AttributeErrorwhen importing xbbg without blpapi (#200) - Japan/non-US timezone fix for bdib: Trading hours now correctly converted to exchange’s local timezone (#198)
- stream() field values: Subscribed field values now always included in output dict (#199)
- Slow Bloomberg fields: TIMEOUT events handled correctly; requests wait for response with
slow_warn_secondswarning (#193) - Pipeline data types: Preserve original data types instead of converting to strings (#191)
- Futures symbol parsing: Fixed
market_info()to correctly parse symbols likeTYH6→TY(#198) - get_tz() optimization: Direct timezone strings recognized without Bloomberg API call
- bdtick timezone fix: Pass exchange timezone to fix blank results for non-UTC exchanges (#185)
- bdtick timeout: Increased from 10s to 2 minutes for tick data requests
- Extended BDS test date range to 120 days for quarterly dividends
- Helper functions now work correctly with LONG format output
- Logging format compliance fixes (G004, G201)
0.11.0b5 - 2026-01-25
Section titled “0.11.0b5 - 2026-01-25”Changed
Section titled “Changed”- Internal class renames with backward compatible aliases (
YamlMarketInfoProvider->MetadataProvider)
Removed
Section titled “Removed”- Trials mechanism: Eliminated retry-blocking system that caused silent failures after 2 failed attempts
- pandas-market-calendars dependency: Exchange info now sourced exclusively from Bloomberg API with local caching
- Import without blpapi installed: Fixed
AttributeErrorwhen importing xbbg without blpapi (#200) - Japan/non-US timezone fix for bdib: Bloomberg returns trading hours in EST; now correctly converted to exchange’s local timezone (#198)
- get_tz() improvement: Direct timezone strings recognized without Bloomberg API call
0.11.0b4 - 2026-01-24
Section titled “0.11.0b4 - 2026-01-24”- yas(): Bloomberg YAS (Yield Analysis) wrapper for fixed income analytics with
YieldTypeenum (#202) - Treasury and SOFR futures support: TY, ZN, ZB, ZF, ZT, UB, TN, SFR, SR1, SR3, ED futures (#198)
- stream() field values: Subscribed field values now always included in output dict (#199)
- Futures symbol parsing: Fixed
market_info()to correctly parse symbols likeTYH6->TY(#198)
0.11.0b3 - 2026-01-21
Section titled “0.11.0b3 - 2026-01-21”- bqr(): Bloomberg Quote Request function emulating Excel
=BQR()for dealer quote data with broker attribution (#22)
- Slow Bloomberg fields: TIMEOUT events handled correctly; requests wait for response with
slow_warn_secondswarning (#193) - Pipeline data types: Preserve original data types instead of converting to strings (#191)
0.11.0b2 - 2026-01-20
Section titled “0.11.0b2 - 2026-01-20”- preferreds(): BQL convenience function to find preferred stocks for an equity ticker
- corporate_bonds(): BQL convenience function to find active corporate bonds for a ticker
- bdtick timezone fix: Pass exchange timezone to fix blank results for non-UTC exchanges (#185)
- bdtick timeout: Increased from 10s to 2 minutes for tick data requests
0.11.0b1 - 2026-01-10
Section titled “0.11.0b1 - 2026-01-10”- Arrow-first pipeline: Complete rewrite of data processing using PyArrow internally
- Multi-backend support: New
Backendenum supporting narwhals, pandas, polars, polars_lazy, pyarrow, duckdb - Output format control: New
Formatenum with long, semi_long, wide options - bta(): Bloomberg Technical Analysis function for 50+ technical indicators
set_backend(),get_backend(),set_format(),get_format()configuration functionsget_sdk_info()as replacement for deprecatedgetBlpapiVersion()- v1.0-compatible exception classes (
BlpError,BlpSessionError, etc.) EngineConfigdataclass andconfigure()functionServiceandOperationenums for Bloomberg service URIs
Changed
Section titled “Changed”- All API functions now support
backendandformatparameters - Internal pipeline uses PyArrow tables with narwhals transformations
- Removed pytz dependency (using stdlib
datetime.timezone)
Deprecated
Section titled “Deprecated”connect()/disconnect()- engine auto-initializes in v1.0getBlpapiVersion()- useget_sdk_info()lookupSecurity()- will becomeblkp()in v1.0fieldInfo()/fieldSearch()- will merge intobfld()in v1.0
0.10.3 - 2025-12-29
Section titled “0.10.3 - 2025-12-29”Changed
Section titled “Changed”- Re-enabled futures and CDX resolver tests
- Updated live endpoint tests for LONG format output
- Code style improvements using contextlib.suppress instead of try-except-pass
- Extended BDS test date range to 120 days for quarterly dividends
- Helper functions now work correctly with LONG format output
0.10.2 - 2025-12-29
Section titled “0.10.2 - 2025-12-29”Changed
Section titled “Changed”- CI/CD improvements with reusable workflows (workflow_call) for release automation
- Separated pypi_upload workflow for trusted publisher compatibility
0.10.1 - 2025-12-29
Section titled “0.10.1 - 2025-12-29”Changed
Section titled “Changed”- Trigger release workflows via release event instead of workflow_dispatch
- Removed Gitter badge (replaced by Discord)
- Added Discord community link and badge
- Persist blp.connect() session for subsequent API calls (#165)
0.10.0 - 2025-12-25
Section titled “0.10.0 - 2025-12-25”- Updated polars-bloomberg support for BQL, BDIB and BSRCH (#155)
- Add identifier type prefix to B-Pipe subscription topics (#156)
- Remove pandas version cap to support Python 3.14 (#161)
- Resolve RST formatting warning in index.rst (#162)
- Update Japan equity market hours for TSE trading extension (#163)
0.9.1 - 2025-12-11
Section titled “0.9.1 - 2025-12-11”Changed
Section titled “Changed”- Add blank lines around latest-release markers in index.rst
- Remove redundant release triggers from workflows
- Trigger release workflows explicitly from semantic_version
- Fix BQL returning only one row for multi-value results (#152)
0.9.0 - 2025-12-02
Section titled “0.9.0 - 2025-12-02”- Add etf_holdings() function for retrieving ETF holdings via BQL (#147)
- Add multi-day support to bdib() (#148)
- Add multi-day cache support for bdib() (#149)
- Resolve RST duplicate link targets and Sphinx build warnings
0.8.2 - 2025-11-19
Section titled “0.8.2 - 2025-11-19”- Fix BQL options chain metadata issues (#146)
0.8.1 - 2025-11-17
Section titled “0.8.1 - 2025-11-17”Changed
Section titled “Changed”- CI/CD workflow improvements for trusted publisher compatibility
0.8.0 - 2025-11-16
Section titled “0.8.0 - 2025-11-16”- bsrch(): Bloomberg SRCH queries for fixed income, commodities, and weather data (#137)
- Fixed income securities support: ISIN/CUSIP/SEDOL identifiers for bdib (#136)
- Server host parameter: Connect to remote Bloomberg servers via
serverparameter (#138) - Interval parameter for subscribe()/live(): Configurable update intervals for real-time feeds
- Semantic versioning workflow for automated releases
- Support for GY (Xetra), IM (Borsa Italiana), and SE (SIX) exchanges (#140)
- Comprehensive bar interval selection guide for bdib function
Changed
Section titled “Changed”- Comprehensive codebase cleanup and restructuring (#144)
- Improved logging with blpapi integration and performance optimizations (#135)
- Enhanced BEQS timeout handling with configurable
timeoutandmax_timeoutsparameters - Updated README with comparison table, quickstart guide, and examples
- Fix BQL syntax documentation and error handling (#141, #142)
- Remove 1-minute offset for bare session names in bdtick (#139)
- Resolve Sphinx build errors and RST formatting issues
0.8.0rc1 - 2025-11-17
Section titled “0.8.0rc1 - 2025-11-17”Changed
Section titled “Changed”- Comprehensive codebase cleanup and restructuring (#144)
0.8.0b2 - 2025-11-14
Section titled “0.8.0b2 - 2025-11-14”- Fix BQL syntax documentation and error handling (#141, #142)
0.8.0b1 - 2025-11-14
Section titled “0.8.0b1 - 2025-11-14”- BQL support: Bloomberg Query Language with QueryRequest and result parsing
- Sub-minute intervals for bdib: 10-second bars via
intervalHasSeconds=Trueflag - bsrch(): Bloomberg SRCH queries for fixed income, commodities, and weather data (#137)
- Fixed income securities support: ISIN/CUSIP/SEDOL identifiers for bdib (#136)
- Server host parameter: Connect to remote Bloomberg servers via
serverparameter (#138) - Interval parameter for subscribe()/live(): Configurable update intervals for real-time feeds
- Support for GY (Xetra), IM (Borsa Italiana), and SE (SIX) exchanges (#140)
Changed
Section titled “Changed”- Standardized Google-style docstrings across codebase
- Migrate to uv for development with PEP 621 pyproject.toml
- Improved logging with blpapi integration and performance optimizations (#135)
- Enhanced BEQS timeout handling with configurable
timeoutandmax_timeoutsparameters
- Remove 1-minute offset for bare session names in bdtick (#139)
0.7.11 - 2025-11-12
Section titled “0.7.11 - 2025-11-12”- BQL support: Bloomberg Query Language with QueryRequest and result parsing
- Sub-minute intervals for bdib: 10-second bars via
intervalHasSeconds=Trueflag - pandas-market-calendars integration for exchange session resolution
Changed
Section titled “Changed”- Standardized Google-style docstrings across codebase
- Migrate to uv for development with PEP 621 pyproject.toml
- Switch to PyPI Trusted Publishing (OIDC)
- Exclude tests from wheel and sdist distributions
- Fix BQL to use correct service name and handle JSON response format
- Normalize UX* Index symbols; fix pandas ‘M’ deprecation to ‘ME’ in fut_ticker
0.7.10 - 2025-11-05
Section titled “0.7.10 - 2025-11-05”- Enhanced Bloomberg connection handling with alternative connection methods
- Market resolvers for active futures and CDX tickers
Changed
Section titled “Changed”- Replace flake8 with ruff for linting
- Update Python version requirements and dependencies
- Clean up CI workflows and documentation
0.7.9 - 2025-04-15
Section titled “0.7.9 - 2025-04-15”Changed
Section titled “Changed”- Add exchanges support
- CI/CD configuration updates
- Corrected typo (thanks to @ShiyuanSchonfeld)
- Pin pandas version due to pd.to_datetime behaviour change in format_raw
- Fix TLS Options typo when creating a new connection
0.7.8a2 - 2022-12-03
Section titled “0.7.8a2 - 2022-12-03”- Additional exchanges support (#83)
Changed
Section titled “Changed”- CI/CD configuration improvements
0.7.7 - 2022-06-19
Section titled “0.7.7 - 2022-06-19”- Custom config usage in bdib (contributed by @hceh)
- Options in
blp.live(contributed by @swiecki)
Changed
Section titled “Changed”- Pandas options handling in doctest
- CI/CD configuration updates
0.7.7a4 - 2022-05-25
Section titled “0.7.7a4 - 2022-05-25”Changed
Section titled “Changed”- Pandas options handling in doctest
0.7.7a3 - 2021-12-31
Section titled “0.7.7a3 - 2021-12-31”- Typo fix
0.7.7a2 - 2021-12-20
Section titled “0.7.7a2 - 2021-12-20”- Custom config and reference exchange support (contributed by @hceh)
0.7.7a1 - 2021-07-13
Section titled “0.7.7a1 - 2021-07-13”- Options in
blp.live(contributed by @swiecki)
0.7.6 - 2021-07-05
Section titled “0.7.6 - 2021-07-05”- Log folder creation handling
- Alternative connection method support
- Custom session argument for Bloomberg connections
bdtickwith custom time range support
Changed
Section titled “Changed”- Update asset universe
- Exchange info corrections
- No manual conversion of timezones
- BDS fix for edge cases
- blpapi install URL correction
0.7.6a8 - 2021-04-17
Section titled “0.7.6a8 - 2021-04-17”- Log folder creation bug
0.7.6a7 - 2021-04-02
Section titled “0.7.6a7 - 2021-04-02”Changed
Section titled “Changed”- Update asset universe
0.7.6a6 - 2021-03-27
Section titled “0.7.6a6 - 2021-03-27”- Exchange info corrected
0.7.6a5 - 2021-03-05
Section titled “0.7.6a5 - 2021-03-05”Changed
Section titled “Changed”- No manual conversion of timezones
0.7.6a4 - 2021-03-05
Section titled “0.7.6a4 - 2021-03-05”bdtickwith custom time range support
0.7.6a3 - 2021-02-10
Section titled “0.7.6a3 - 2021-02-10”- Bug fixes for BDS and blpapi install URL
0.7.6a2 - 2021-02-07
Section titled “0.7.6a2 - 2021-02-07”- Alternative connection method
0.7.6a1 - 2021-02-03
Section titled “0.7.6a1 - 2021-02-03”- Add
sessas argument for custom Bloomberg session
0.7.5 - 2021-01-31
Section titled “0.7.5 - 2021-01-31”- Currency adjusted turnover function
- Useful fields for live feeds
- More examples in documentation
Changed
Section titled “Changed”- Standardize IO operations
- Log levels adjustment
- Replace
os.pathwith pathlib - Performance function improvements
- Default args of live feeds
- CCY adjust fix
- Bug in finding exchange info
0.7.5b2 - 2021-01-30
Section titled “0.7.5b2 - 2021-01-30”Changed
Section titled “Changed”- Log levels adjustment
0.7.5b1 - 2021-01-13
Section titled “0.7.5b1 - 2021-01-13”- New methods included in
__all__
- CCY adjust fix
0.7.5a9 - 2021-01-12
Section titled “0.7.5a9 - 2021-01-12”- Currency adjusted turnover function
0.7.5a09 - 2021-01-12
Section titled “0.7.5a09 - 2021-01-12”- Currency adjusted turnover function
0.7.5a8 - 2021-01-11
Section titled “0.7.5a8 - 2021-01-11”- Fix bug in finding exchange info
0.7.5a7 - 2021-01-07
Section titled “0.7.5a7 - 2021-01-07”Changed
Section titled “Changed”- Default args of live feeds
0.7.2 - 2020-12-16
Section titled “0.7.2 - 2020-12-16”- Logo image for project branding
Changed
Section titled “Changed”- Use
asyncfor live data feeds - Speed up by caching files
- Change logic of exchange lookup and market timing
- Push all values from live subscription
- Support for Python 3.8
- Proper caching implementation
0.7.0 - 2020-08-02
Section titled “0.7.0 - 2020-08-02”Changed
Section titled “Changed”bdhpreserves column orders (both tickers and flds)timeoutargument is available for all queriesbdtickusually takes longer to respond - can usetimeout=1000for example if keep getting empty DataFrame
0.6.7 - 2020-05-17
Section titled “0.6.7 - 2020-05-17”- Add flexibility to use reference exchange as market hour definition
- No longer necessary to add
.ymlfor new tickers, provided that the exchange was defined in/xbbg/markets/exch.yml
Changed
Section titled “Changed”- Switch CI from Travis to GitHub Actions
0.6.0 - 2020-01-23
Section titled “0.6.0 - 2020-01-23”- Tick data availability via bdtick()
Changed
Section titled “Changed”- Speed improvements by removing intermediate layer of generator for processing Bloomberg responses
0.5.0 - 2020-01-08
Section titled “0.5.0 - 2020-01-08”Changed
Section titled “Changed”- Rewritten library to add subscription, BEQS, simplify interface and remove dependency of
pdblp
0.1.22 - 2019-09-15
Section titled “0.1.22 - 2019-09-15”Security
Section titled “Security”- Remove PyYAML dependency due to security vulnerability
0.1.17 - 2019-07-01
Section titled “0.1.17 - 2019-07-01”- Add
adjustargument inbdhfor easier dividend / split adjustments