Repository navigation
Added
- Dead-code and import-graph checks. CI and pre-commit now run vulture and import-linter for both Python packages (
pixi run -e lint deadcode,deadcode-langgraph,imports,imports-langgraph), Knip and dependency-cruiser in both JavaScript packages'npm run quality,cargo shearfor unused Rust dependencies (replacing the non-blocking nightlycargo udepsjob),cargo denybans that keep the binding frameworks, the MCP SDK, andxbbg-blpapi-sysinside their owning crates, and theunreachable_publint, so rustc's dead-code analysis also covers crate-internal items. - More CI coverage. Pull requests now run the offline Rust test suite (
cargo test --workspace; tests that need a Bloomberg session are#[ignore]d and run withcargo test -- --ignored) and the@xbbg/langgraphquality suite, and the merge gate waits for every required job. - The shared Rust recipes gained the features Python implemented on its own.
recipe_earningsupports geography and product breakdowns, a fiscal year, and a period count;recipe_adjust_ccyconverts long and wide data, categorical inputs, foreign Arrow string layouts, and zoned timestamps;recipe_turnoverimplements the VWAP × volume fallback, FX conversion, scaling, and presentation controls; futures resolution falls back to the historical contract chain; and recipes accept the common request controls (overrides, per-security overrides, elements, validation, field types, EIDs, and timezones). Engine.worker_health()is available on the public Pythonxbbg.Engine, as earlier release notes described.- Python 3.15.
xbbgdeclares CPython 3.15, and CI and the release workflow build and test 3.15 wheels for Linux x86_64 (manylinux_2_28), Windows x64, and macOS arm64. duckdb publishes no 3.15 wheels yet, so thetestextra leaves it out on 3.15, the DuckDB tests skip there, andxbbg[duckdb]on 3.15 needs a duckdb source build until it does.xbbg-langgraphstays on 3.11–3.14: LangGraph'sormsgpackdependency has no 3.15 wheels, and its PyO3 version refuses to build for 3.15. - Compatibility CI. A new job checks every workspace crate with Rust 1.88, the declared
rust-version, and another runs the offline Python suite against the newest pandas 2 and polars 1 releases, next to the current majors and the declared floors. A build-and-test leg onubuntu-26.04runs ahead of theubuntu-latestmove that starts on 2026-10-19, the@xbbg/langgraphquality suite runs on Node.js 24 and 26, the codegen job fails on a staleuv.lock, and pull requests that change a Dockerfile build the CI images without publishing them. - Delayed-data status per security.
delay_status(Pythonblp.delay_status/adelay_status, Nodeengine.delayStatus, MCPdelay_status, LangGraphxbbg_delay_status) makes one reference-data request and reports whether this session receives delayed data (IS_DELAYED_STREAM), how many minutes behind real time it is (EXCHANGE_DELAY), the exchange code, and the real-time and delayed feed EIDs (FEED_EID1–FEED_EID4,FEED_DELAYED_EID1), which Bloomberg reports even whenreturnEidswithholds EIDs the requester lacks.check_identity=Truechecks those EIDs against the engine's authorized identity on//blp/mktdata; that needs SAPI/B-PIPE authorization or an EMRS-enrolled Desktop user. The READMEs, MCP server instructions, and LangGraph tool descriptions no longer say reference data has no delayed flag. on_delayedforbdp,bdh,bdib, andbdtick(NodeonDelayed; MCPon_delayedonbdp,bdh,bdib, andrequest; the LangGraph request tools)."warn"emits oneBlpDelayedDataWarningper delayed security,"raise"fails the call, and"ignore"only records the status; the default leaves requests unchecked.bdpreads the status from the same request, while the others make one extra reference-data request, and only when the requested window ends within the last 24 hours. Results carry the status asxbbg.delayedmetadata (ArrowTable.delayed, pandasattrs["xbbg_delayed"], Noderesult.delayed).
Changed
- Python
xbbg.extrecipes run on the shared Rust implementations.yas,preferreds,corporate_bonds,bqr,fut_ticker,active_futures,dividend,earnings,turnover,etf_holdings, and currency conversion now call the same native recipes as Node.js. BREAKING (Python): they adopt the native validation, error messages, and output contracts:dividendkeeps Bloomberg's column labels and no longer drops non-equities,etf_holdingskeeps the BQL labels,turnoverreturnsTURNOVERcolumns with Date32 dates, currency fetch failures raise instead of returning unconverted data and missing FX rates become nulls, futures selection is candidate-first with a 10-day volume window, and invalid YAS yield flags raise. xbbg.marketsdelegates to the native implementation. Exchange resolution, metadata, market timing, session derivation, and timezone inference use the Rust engine. BREAKING (Python): session hours come from the native market rules where an exchange has one, and otherwise from Bloomberg's trading-hours fields as returned, instead of being converted from US Eastern time; session dictionaries use the nativeday/allday/pre/post/am/pmkeys; empty session overrides raise; nativeExchangeInfo.cached_atisNone;market_timing()raises on unknown timing names and missing day sessions instead of falling back to EOD or returning an empty string, andFINISHEDuses the day close when there is noalldaywindow; and native timing and query errors propagate.- Shared Bloomberg vocabulary is generated.
defs/bloomberg.tomlnow holds the CDX info/pricing/risk field bundles, the technical-analysis study aliases and default parameters, the volatility-surface presets, the index-member fields, and the LangGraph tool names, limit defaults, closed sets, result-policy, and chart vocabulary; Rust, Python, both JavaScript packages, and the Python LangGraph adapter use the generated copies instead of hand-maintained duplicates. The Rust request planner parsesformatthrough the generatedFormatvocabulary; unknown values reportUnknown format: <value>. - The Python and Node bindings share one Rust implementation of subscription consumption (pending updates, layout boundaries, close and drain, serialized unsubscribe), engine-configuration validation, and error presentation. BREAKING:
request_pool_size,command_queue_size, and shard limits are validated when the configuration is built (PythonValueError, NodeInvalidArg) instead of when the engine starts, and Node rejects negative TLS timeouts even without credentials. - Streamed history and intraday bars match the accumulated results. Streamed
bdhhonours requested and cached field types instead of forcing Float64 and keeps security-error and field-exception diagnostics, and streamed and accumulated intraday bars share one decoder. BREAKING: accumulated intraday-bartickercolumns are non-nullable, streamed historicaltickercolumns are nullable, and BloombergCHARY/N values decode as Booleans on every path. - BQR returns the same sorted, normalized quote columns in every language and enforces requested broker attribution; the native dividend recipe's
dvd_typeselects the matching bulk field and honours the date range; and native turnover applies its fallback, currency conversion, and factor, which previously had no effect from Node.js. @xbbg/langgraphvalidation matches the Python adapter. BREAKING:recoveryRateis a percentage (0–100, 40 means 40%), fixed CDX bundles enforcemaxFieldsand forwardvalidateFields, and kwargs and override maps enforcemaxStringChars, entry limits, and unique normalized keys.- Large modules were split along existing seams with public names unchanged: Python
blp.py, the@xbbg/coreentry module, the Rust engine'sengine/mod.rs, and the@xbbg/langgraphresult limiter. - Benchmarks measure production code. The subscription replay benchmarks drive the real
SubscriptionArrowBatcher, and the BQL parser and extractor benchmarks share one fixture table. - CI tests against pandas 3 and polars 2. The Python test matrix requires pandas 3 and polars 2, the pixi test environments lock polars 2, and the declared-floors job still covers pandas 2.2.2 and polars 0.20.4.
- Renovate keeps the declared floors. It updates lock files for in-range releases instead of raising every lower bound, widens the published Python and npm dependency ranges when a new major lands, leaves
requires-python, Nodeengines, and the pixipython,rust,libclang, andnodejssupport pins to deliberate changes, and now tracks the Dockerfile base images. - Rust edition 2024. The workspace uses edition 2024 and Cargo's MSRV-aware resolver 3, and
rust-versionstays 1.88. The lock moves to the newest releases that support Rust 1.88 (among them pyo3 0.29.3, napi 3.14.2, tokio 1.53.2, and arrow 59.3.0),xbbg-mcpmoves to rmcp 3.5.1, andxbbg-blpapi-sysgenerates its bindings with bindgen 0.73.2, pinned to the crate'srust-versionand edition so that bindings exported by a newer toolchain still compile on 1.88. BREAKING (Rust,xbbg-blpapi-sys): the opaque SDK handle types such asblpapi_Session,blpapi_Element, andblpapi_Eventno longer implementCopyandClone, andblpapi_CorrelationId_t_drops its zero-sized_bitfield_align_1field; type layouts are unchanged. - Toolchain refresh. CI and the release workflow pin uv 0.13.0 (the release workflow had used whatever uv was newest) and pixi 0.81.0, and move to
setup-rust-toolchain2,setup-uv10.3,setup-pixi0.11,cargo-binstall1.25, Bun 1.4.3, andbindgen-cli0.73.2 for the ABI check. The CI image moves from Rust 1.89 on Debian 12 to Rust 1.99 on Debian 13, still with LLVM 22. The JavaScript packages move to Vitest 5, oxlint 1.87, and oxlint-tsgolint 7, and@xbbg/coreand@xbbg/langgraphcompile for Node.js 24, their engines floor, instead of the end-of-life Node.js 20; the native core-package CI job moves from Node.js 20 to 24 as well. Pixi environments pin the regular GIL CPython build, where the solver had picked free-threaded 3.14t on Linux and Windows, and resolve Python 3.14 on every platform. - CI no longer installs Bloomberg's
blpapiPython package. The Python test jobs load the C++ SDK runtime from the SDK setup action on every OS, Windows included. - BREAKING (Rust):
RequestParamsandRequestParamsInputgainon_delayed. Complete struct literals must supply this optional field or use..Default::default().DelayedPolicynow covers requests as well as subscriptions;xbbg_async::DelayedPolicyandxbbg_async::engine::DelayedPolicyare unchanged.
Removed
- BREAKING: Python 3.10. CPython 3.10 reached end of life on 2026-10-01, so
xbbgnow requires Python 3.11 or newer andxbbg-langgraphPython 3.11–3.14. CI and the release workflow no longer build or test 3.10 wheels, thepy310pixi environment is gone, and the declared-floors job runs on 3.11. pip on Python 3.10 keeps installing the last release that supports it. - BREAKING: the corporate-bond
active_only/activeOnlyoption. It never filtered anything (debt()has no active flag), so it is gone from the Rust query builder and recipe, both bindings, Python, Node.js, and the LangGraph tools. - BREAKING (Python): compatibility leftovers.
FieldTypeCache(cache_path=...),query_api=False, and the discardedresolve_types()keyword arguments;xbbg.services.LongMode;backend.convert_backend_frame_with_defaultandBackendDescriptor.implemented;xbbg.markets.resolvers;markets.bloomberg.COUNTRY_TIMEZONE_MAP;markets.info.explode; implementation-only market helpers; and the module-levelext_*re-exports in migratedxbbg.extmodules.xbbg._coredrops the unusedPyEngine.invalidate_exchange_cache,save_exchange_cache,save_field_cache,validate_fields,get_cached_schema, andext_is_long_format. - BREAKING (Rust): unused public API.
xbbg_core:Request::set_{string,i32,i64,f64},Element::{get_cstr,get_str_unchecked,get_value_fast},Name::try_get_or_intern,BlpError::with_request_ctx,AsyncSession::shutdown_nonblocking,CorrelationId::as_int, and six unusedSessionOptionssetters.xbbg-ext:add_percentage_column,build_cdx_ticker,build_resolved_cdx_ticker, andExtError::{UnknownDividendType,EmptyData}.xbbg-async:Engine::{cache_field_types,request_worker_count,available_subscription_sessions},TypedBuilder::from_type_str,ColumnSet::has_column,create_field,UpdateValue::from_blp,SchemaCache::persist,SubscriptionState::flushand itsflush_threshold, the generatedOutputMode, the never-emittedBlpAsyncError::{StreamFull,Cancelled,Timeout,SessionLost}, and the duplicateBlpAsyncError::BlpErrorwrapper with itsbloomberg error:display prefix (useBlpAsyncError::Blp, which displays the core error unchanged).xbbg-recipes: the no-optionrecipe_cdx_tickerandrecipe_active_cdx(use the*_with_optionsforms); the remaining recipes take a finalRequestParamsargument.pyo3-xbbgdrops the deprecatedextension-modulefeature; setuptools-rust setsPYO3_BUILD_EXTENSION_MODULEfor wheel builds. - Unused tooling and dependencies. The raw
versionandextAuctionFieldGroupNamesaddon exports,@arethetypeswrong/cli, thetsx,langchain, and@langchain/openaidev dependencies of@xbbg/langgraph, the unused Rust dependenciesonce_cell,anyhow,pyo3-stub-gen-derive,arc-swap,dhat,hdrhistogram, andtempfile, and the commented-out Kani CI job.
Fixed
- BQL client context and MCP diagnostics (#358). The shared Rust engine owns optional
bql_app_name(bqlAppNamein Node), applying it only to BQLsendQueryrequests, including raw requests. Pythonbql/abqlaccept per-callapp_name, NodeEngine.bqlacceptsappName, and MCP'sXBBG_MCP_BQL_APP_NAMEconfigures the shared engine; explicit request values win. Unspecified client context and existing authentication defaults remain unchanged. MCP request failures retain Bloomberg's underlying error message and request context through the shared borrowing formatter, preserving error codes and output budgets. - BREAKING (Rust):
EngineConfiggainsbql_app_name. Complete struct literals must supply this optional field or use..EngineConfig::default(). The default isNone; existing Python, Node and MCP defaults are unchanged, and authentication app names are never used as implicit BQL client context. - Patched JavaScript dev tooling. Both JavaScript packages now lock
tinypool2.2.0 throughoxfmt0.72.0 (#357), fixing the prototype-pollution remote code execution advisories GHSA-5gmw-xhrv-c9v3 and GHSA-85c8-ppgw-ccpr, andsource-map-js1.2.2 (#356), fixing the indexed source map denial of service in GHSA-68fv-2mgg-jv7q. These are development dependencies and are not part of the published packages. - Patched tokio. The lock moves tokio from 1.53.2 to 1.53.3, clearing RUSTSEC-2026-0386, the unsound safe
AsyncFdconstructors. Neither xbbg nor the crates that depend on tokio in its build construct anAsyncFd, so earlier builds were not exposed. - Patched zod. The
@xbbg/langgraphlock and the private MCPB build tools move to zod 4.6.7, fixing the memory exhaustion while validating oversized constrained collections in GHSA-mrhx-c7xc-m3w5.@xbbg/langgraphstill declareszod^3.25.32 || ^4.2.0, so installs resolve their own zod.@anthropic-ai/mcpb2.1.2, the newest release, still requests zod 3, which has no patched release, so the build tools override it;mcpb validatestill accepts the release manifest and rejects invalid manifests at the same paths. xbbg.markets.convert_session_times_to_utc()no longer trips NumPy's generic-timedelta deprecation on pandas 2. With pandas 2.x and NumPy 2.5, carrying the caller's fractional seconds throughpd.Timedeltaemitted NumPy'sDeprecationWarningthat the "generic" timedelta unit will become an error. The function now sets the fraction withTimestamp.replace, and the results are unchanged.- The declared-floors CI job installs the declared floors, and the
duckdbextra now requires 1.5.1. The job installed the wheel underUV_RESOLUTION=lowest-direct, which lowers only direct requirements, and a wheel's own dependencies are not direct, so it had been testing the newest releases (pandas 3.1.0, polars 2.0.0) instead of pandas 2.2.2, polars 0.20.4, pyarrow 22.0.0, narwhals 2.10.0, and duckdb 1.5.0. It now passes the declared requirements as direct requirements. At the real floors, DuckDB 1.5.0 maps tens of GB of virtual memory up front, andos.fork()after xbbg's DuckDB backend had started failed withENOMEMon the 16 GB CI runners; DuckDB 1.5.1 maps that memory lazily. - Python exchange overrides take effect.
xbbg.markets.set_exchange_override()wrote a Python dictionary that nothing read, while exchange resolution consults the native registry. The Python functions now read and write the native registry. - Streams no longer drop data silently. A streamed historical or intraday-bar request whose consumer falls behind now ends with one explicit error after the chunks already delivered, instead of discarding chunks.
- Complete Python type stubs.
xbbg/__init__.pyiis generated from the runtime export registry, so the 69 public names it omitted (includingconfigure,Backend,RequestParams,set_backend, andadd_middleware) and twelve synchronous wrappers are typed, andxbbg._coredeclares__version__and__build_info__. - Checks that never ran now run. The pre-commit Rust hooks matched no files and the whitespace hooks skipped their intended root files; the unsafe-code audit pointed at a nonexistent manifest; manylinux Dockerfile edits did not rebuild the image; and the CI merge gate ignored the JavaScript, packaging, and dependency-floor jobs. Linux Rust test binaries can now link libpython.
blpapi-sysno longer reuses stale bindings after an in-place SDK header change or a bindgen upgrade.- Node recipes reject unsupported backends before calling Bloomberg, and the packaged-install smoke test picks the newest vendored SDK by version number rather than by string order.
- BQR's default window is computed from the current UTC time with offset-aware start times.
- The README notebook uses the current API with stale outputs removed, and the Python benchmark harness drops a comparison lane its install instructions could never create.
- Large BQL results keep omitted secondary columns. Results over 32 KiB dropped a secondary column such as
DATEorCURRENCYwhen Bloomberg omitted its values; they now return it as nulls, as smaller results already did. - The Python LangGraph adapter's CI tests use the wheel under test. Installing the adapter replaced the freshly built
xbbgwheel with the newest PyPI release, because the untagged CI build's version sits below the adapter'sxbbg>=1.5.0floor. - JavaScript offline bundles are uploaded.
npm --prefix js-xbbgruns the bundle script insidejs-xbbg/, so its relative--out-dirput the bundles where neither CI nor the JavaScript release workflow uploaded from, and the release's payload check would have failed on the missing artifact. The bundles now go to the path the upload step reads, and an empty upload fails the job.
Full Changelog: v1.5.1...v1.6.0