Skip to content

xbbg 1.6.0

Latest

Choose a tag to compare

@github-actions github-actions released this 23 Oct 23:37
· 5 commits to main since this release

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 shear for unused Rust dependencies (replacing the non-blocking nightly cargo udeps job), cargo deny bans that keep the binding frameworks, the MCP SDK, and xbbg-blpapi-sys inside their owning crates, and the unreachable_pub lint, 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 with cargo test -- --ignored) and the @xbbg/langgraph quality suite, and the merge gate waits for every required job.
  • The shared Rust recipes gained the features Python implemented on its own. recipe_earning supports geography and product breakdowns, a fiscal year, and a period count; recipe_adjust_ccy converts long and wide data, categorical inputs, foreign Arrow string layouts, and zoned timestamps; recipe_turnover implements 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 Python xbbg.Engine, as earlier release notes described.
  • Python 3.15. xbbg declares 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 the test extra leaves it out on 3.15, the DuckDB tests skip there, and xbbg[duckdb] on 3.15 needs a duckdb source build until it does. xbbg-langgraph stays on 3.11–3.14: LangGraph's ormsgpack dependency 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 on ubuntu-26.04 runs ahead of the ubuntu-latest move that starts on 2026-10-19, the @xbbg/langgraph quality suite runs on Node.js 24 and 26, the codegen job fails on a stale uv.lock, and pull requests that change a Dockerfile build the CI images without publishing them.
  • Delayed-data status per security. delay_status (Python blp.delay_status/adelay_status, Node engine.delayStatus, MCP delay_status, LangGraph xbbg_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 when returnEids withholds EIDs the requester lacks. check_identity=True checks 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_delayed for bdp, bdh, bdib, and bdtick (Node onDelayed; MCP on_delayed on bdp, bdh, bdib, and request; the LangGraph request tools). "warn" emits one BlpDelayedDataWarning per delayed security, "raise" fails the call, and "ignore" only records the status; the default leaves requests unchecked. bdp reads 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 as xbbg.delayed metadata (ArrowTable.delayed, pandas attrs["xbbg_delayed"], Node result.delayed).

Changed

  • Python xbbg.ext recipes 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: dividend keeps Bloomberg's column labels and no longer drops non-equities, etf_holdings keeps the BQL labels, turnover returns TURNOVER columns 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.markets delegates 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 native day/allday/pre/post/am/pm keys; empty session overrides raise; native ExchangeInfo.cached_at is None; market_timing() raises on unknown timing names and missing day sessions instead of falling back to EOD or returning an empty string, and FINISHED uses the day close when there is no allday window; and native timing and query errors propagate.
  • Shared Bloomberg vocabulary is generated. defs/bloomberg.toml now 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 parses format through the generated Format vocabulary; unknown values report Unknown 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 (Python ValueError, Node InvalidArg) 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 bdh honours 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-bar ticker columns are non-nullable, streamed historical ticker columns are nullable, and Bloomberg CHAR Y/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_type selects 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/langgraph validation matches the Python adapter. BREAKING: recoveryRate is a percentage (0–100, 40 means 40%), fixed CDX bundles enforce maxFields and forward validateFields, and kwargs and override maps enforce maxStringChars, entry limits, and unique normalized keys.
  • Large modules were split along existing seams with public names unchanged: Python blp.py, the @xbbg/core entry module, the Rust engine's engine/mod.rs, and the @xbbg/langgraph result 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, Node engines, and the pixi python, rust, libclang, and nodejs support 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-version stays 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-mcp moves to rmcp 3.5.1, and xbbg-blpapi-sys generates its bindings with bindgen 0.73.2, pinned to the crate's rust-version and 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 as blpapi_Session, blpapi_Element, and blpapi_Event no longer implement Copy and Clone, and blpapi_CorrelationId_t_ drops its zero-sized _bitfield_align_1 field; 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-toolchain 2, setup-uv 10.3, setup-pixi 0.11, cargo-binstall 1.25, Bun 1.4.3, and bindgen-cli 0.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/core and @xbbg/langgraph compile 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 blpapi Python package. The Python test jobs load the C++ SDK runtime from the SDK setup action on every OS, Windows included.
  • BREAKING (Rust): RequestParams and RequestParamsInput gain on_delayed. Complete struct literals must supply this optional field or use ..Default::default(). DelayedPolicy now covers requests as well as subscriptions; xbbg_async::DelayedPolicy and xbbg_async::engine::DelayedPolicy are unchanged.

Removed

  • BREAKING: Python 3.10. CPython 3.10 reached end of life on 2026-10-01, so xbbg now requires Python 3.11 or newer and xbbg-langgraph Python 3.11–3.14. CI and the release workflow no longer build or test 3.10 wheels, the py310 pixi 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 / activeOnly option. 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 discarded resolve_types() keyword arguments; xbbg.services.LongMode; backend.convert_backend_frame_with_default and BackendDescriptor.implemented; xbbg.markets.resolvers; markets.bloomberg.COUNTRY_TIMEZONE_MAP; markets.info.explode; implementation-only market helpers; and the module-level ext_* re-exports in migrated xbbg.ext modules. xbbg._core drops the unused PyEngine.invalidate_exchange_cache, save_exchange_cache, save_field_cache, validate_fields, get_cached_schema, and ext_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 unused SessionOptions setters. xbbg-ext: add_percentage_column, build_cdx_ticker, build_resolved_cdx_ticker, and ExtError::{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::flush and its flush_threshold, the generated OutputMode, the never-emitted BlpAsyncError::{StreamFull,Cancelled,Timeout,SessionLost}, and the duplicate BlpAsyncError::BlpError wrapper with its bloomberg error: display prefix (use BlpAsyncError::Blp, which displays the core error unchanged). xbbg-recipes: the no-option recipe_cdx_ticker and recipe_active_cdx (use the *_with_options forms); the remaining recipes take a final RequestParams argument. pyo3-xbbg drops the deprecated extension-module feature; setuptools-rust sets PYO3_BUILD_EXTENSION_MODULE for wheel builds.
  • Unused tooling and dependencies. The raw version and extAuctionFieldGroupNames addon exports, @arethetypeswrong/cli, the tsx, langchain, and @langchain/openai dev dependencies of @xbbg/langgraph, the unused Rust dependencies once_cell, anyhow, pyo3-stub-gen-derive, arc-swap, dhat, hdrhistogram, and tempfile, and the commented-out Kani CI job.

Fixed

  • BQL client context and MCP diagnostics (#358). The shared Rust engine owns optional bql_app_name (bqlAppName in Node), applying it only to BQL sendQuery requests, including raw requests. Python bql/abql accept per-call app_name, Node Engine.bql accepts appName, and MCP's XBBG_MCP_BQL_APP_NAME configures 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): EngineConfig gains bql_app_name. Complete struct literals must supply this optional field or use ..EngineConfig::default(). The default is None; 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 tinypool 2.2.0 through oxfmt 0.72.0 (#357), fixing the prototype-pollution remote code execution advisories GHSA-5gmw-xhrv-c9v3 and GHSA-85c8-ppgw-ccpr, and source-map-js 1.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 AsyncFd constructors. Neither xbbg nor the crates that depend on tokio in its build construct an AsyncFd, so earlier builds were not exposed.
  • Patched zod. The @xbbg/langgraph lock 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/langgraph still declares zod ^3.25.32 || ^4.2.0, so installs resolve their own zod. @anthropic-ai/mcpb 2.1.2, the newest release, still requests zod 3, which has no patched release, so the build tools override it; mcpb validate still 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 through pd.Timedelta emitted NumPy's DeprecationWarning that the "generic" timedelta unit will become an error. The function now sets the fraction with Timestamp.replace, and the results are unchanged.
  • The declared-floors CI job installs the declared floors, and the duckdb extra now requires 1.5.1. The job installed the wheel under UV_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, and os.fork() after xbbg's DuckDB backend had started failed with ENOMEM on 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__.pyi is generated from the runtime export registry, so the 69 public names it omitted (including configure, Backend, RequestParams, set_backend, and add_middleware) and twelve synchronous wrappers are typed, and xbbg._core declares __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-sys no 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 DATE or CURRENCY when 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 xbbg wheel with the newest PyPI release, because the untagged CI build's version sits below the adapter's xbbg>=1.5.0 floor.
  • JavaScript offline bundles are uploaded. npm --prefix js-xbbg runs the bundle script inside js-xbbg/, so its relative --out-dir put 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