Python client for AE Broadcast market data terminal
Project description
py-bcast
Python client for AE Broadcast (Agência Estado) market data terminal — a Bloomberg blpapi/xbbg-like interface. Suporta os dois terminais em paralelo: Antigo (bcsys32.exe, DDE + ContentProxy) e Novo (Broadcast+.exe, JWT + WebSocket).
[!IMPORTANT] Projeto não-oficial e independente.
py-bcastnão é afiliado, patrocinado nem endossado pela Agência Estado, pelo Grupo Estado ou por qualquer provedor de dados. "Broadcast" e "AE Broadcast" são marcas de seus respectivos titulares, citadas aqui apenas de forma nominativa para identificar o terminal com o qual a biblioteca interopera.A biblioteca não redistribui dados de mercado: ela conecta-se a um terminal Broadcast já licenciado e em execução na sua própria máquina. Você é o único responsável por usar este software em conformidade com o contrato de licença e os termos de uso do seu terminal. Use por sua conta e risco.
Features
Terminal Antigo (bcsys32.exe)
- Real-time streaming via DDE (
bdp,subscribe,snapshot) - Historical data via HTTP — daily close/OHLCV range (
bhistory/bclose), intraday bars (bdi), tick-by-tick (bdt) - Times & trades with top-of-book (
bticks) — TRD/QTE rows, broker ids, sessao corrente - Macroeconomic series — FX, indices, commodities, CDI (
bmacro("CDI",...)), inflation snapshot + accumulated history (binflation/binflation_history), returns - Fixed income — Tesouro prices/yields (
btreasury/btreasury_history), unit price/PU (bunit_price), pre-fixado accrual (baccrual), poupanca (bsavings) - Market stats snapshot (
bstats) — DY, last dividend, 52-week range, avg volumes, para qualquer simbolo B3 - Intraday snapshot (
bsnapshot) — OHLCV near-real-time sem DDE - Investment funds — universo de fundos (
bfund_list), historico de cotas (bfund_history), retornos por janela (bfund_returns) - Spot FX conversion (
bfx) — taxa atual entre quaisquer pares - Fundamental data — analyst consensus, indicators (Market Cap, Beta), company metadata, sector screening (
bsector_members), free float (bfree_float), top fund holders (bfund_holders), statement dates (bstatement_dates), first close (bfirst_close) - Corporate events — dividends, JCP, calendar, dividend yield, broker portfolios (
bportfolio/bportfolios_with), shareholder dates (bshareholder_dates), filings S3 links (bfilings) - Credit — sovereign/corporate CDS term-structure curves + tradable CDS index term-structures via Markit (
bcds/bcds_indices) - Reference data — 1020 companies, 37 indices, 38 sectors, real-time quotes
- News & multimedia — full-text articles, Dow Jones wires, podcasts (no auth needed)
- Instrument database — 623K+ instruments across 30+ exchanges (local
aetp_17.dat)
Terminal Novo (Broadcast+.exe)
- Real-time streaming via WebSocket (
BroadcastPlusClient/ asyncioBroadcastPlusAsyncClient) com auth refresh transparente - Market stats streaming —
subscribe_markettransmite tabelas ao vivo da Bovespa: maiores altas/baixas, volume financeiro, evolucao do Ibovespa - Instrument metadata (
binfo) — nome, tipo, exchange, flags, CVM code; nunca retorna preco (preco exclusivo via WebSocket) - Times & trades (
btrades) — ultimos 500 trades em fusoAmerica/Sao_Paulo;ask_broker_id/bid_broker_idfazem join combbrokers() - Index composition (
bindexes+bindex_members) — lista de indices e composicao com pesos de relevancia; sem equivalente no terminal antigo - Instrument logo (
blogo) — bytes PNG do logo; sem equivalente no terminal antigo - Broker & exchange registries (
bbrokers+bexchanges) — corretoras (id, nome) e bolsas (id, nome, delay); decodificam os ids debtradesebinfo - Corporate events with adjustment factors (
bcorpevents) — dividendos, JCP, splits +add_factor,calculated_factor,multiplicative_factorque obdividendslegado nao expoe - Investment funds (
bfunds/bfund) — busca e detalhe: rentabilidade, taxas, CNPJ, ANBIMA; sem equivalente no terminal antigo - News (Plus feed) (
bsections+bheadlines+bnews_content) — 121 secoes, manchetes paginadas, corpo HTML + tagging estruturado (autores, entidades, topicos, localizacoes) - Holiday catalog (
bholidays) — catalogo de tabelas de feriados por pais/bolsa - Headless login via ECDH P-384 + AES-GCM (
configure(plus_login=..., plus_password=...)) - Token discovery — memory scan do
Broadcast+.exeouBROADCAST_PLUS_TOKENenv var
Compartilhado entre os backends
- Routing automatico —
configure(terminal="auto"|"legacy"|"plus");bsearch()ja roteia - Async API —
async_apinamespace com versoes async de todas as funcoes HTTP (prefixoa:abinfo,abindex_members,abfunds,abcorpevents,abheadlines, etc.) - Caching — memoria (default) e disco (
diskcache) com TTL configuravel - Rate limiting — token-bucket e connection pooling
- Proper Python package com
src/layout, type annotations, Pydantic validation, structured logging
Requirements
- Windows 10/11
- Python 3.12+
- Pelo menos um dos dois:
- Legacy:
bcsys32.exerodando (ouBROADCAST_SESSIONenv var) - Plus:
Broadcast+.exerodando (ouBROADCAST_PLUS_TOKENenv var, ou credenciais viaconfigure)
- Legacy:
Installation
pip install -e .
Todas as dependências (incluindo pywin32, necessário para DDE) são instaladas
automaticamente.
Quick Start
Terminal Antigo (bcsys32.exe)
import os
os.environ["BROADCAST_SESSION"] = "<your_session_token>"
from py_bcast import bdp, bhistory, bdi, bmacro, bconsensus, bdividends, bsearch
# Real-time quote
price = bdp("PETR4", "ULT")
# Historical daily (works for ALL instruments) — flat DataFrame, ticker column
df = bhistory("PETR4", "20260501", "20260520")
print(df["close"].tail())
# Intraday 2-min bars
bars = bdi("PETR4", "20260520")
# Macro series (FX, indices, commodities, rates)
fx = bmacro("USDBRL", "20260101", "20260520")
# Analyst consensus (DataFrame, one row per ticker)
df = bconsensus("PETR4")
print(df["buy"].iloc[0], df["target_mean"].iloc[0])
# Dividends history (ticker; CVM auto-resolved)
divs = bdividends("PETR4")
# Instrument search — retorna pd.DataFrame (schema unificado entre backends)
df = bsearch("PETR", exchange="BVMF")
print(df[["ticker", "name", "exchange"]].head())
# Real-time streaming
from py_bcast import BroadcastClient
with BroadcastClient() as bc:
bc.subscribe(["PETR4", "VALE3"], ["ULT", "VAR"],
callback=lambda t, f, v: print(f"{t}.{f} = {v}"))
bc.run(duration=60)
Terminal Novo (Broadcast+.exe)
from py_bcast import (
BroadcastPlusClient,
binfo, bindexes, bindex_members, blogo,
bbrokers, bexchanges,
bfunds, bfund,
bsections, bheadlines, bnews_content,
bcorpevents, bholidays,
btrades, bsearch,
configure,
)
# Headless: define BROADCAST_PLUS_TOKEN no ambiente, ou:
configure(plus_login="user@example.com", plus_password="...")
# Forca o backend Plus (ou deixa "auto" para detectar Broadcast+.exe rodando)
configure(terminal="plus")
# Metadata de instrumento (nunca preco — preco exclusivo via WebSocket)
df = binfo(["PETR4", "USDBRL"])
print(df[["name", "type", "currency"]])
# Indices disponiveis e composicao com pesos
print(bindexes()["index"].tolist())
df = bindex_members("IBOV")
print(df.sort_values("relevance", ascending=False).head())
# Logo PNG
open("petr4.png", "wb").write(blogo("PETR4"))
# Fundos de investimento
hits = bfunds("Verde")
print(hits[["id", "company", "profit_1y"]].head())
detail = bfund(hits["id"].iloc[0])
# Noticias Plus (secoes, manchetes, conteudo)
sections = bsections()
headlines = bheadlines(sections["id"].iloc[0], count=10)
article = bnews_content(headlines["id"].iloc[0])
print(article["title"], article["tagging"]["entities"])
# Eventos corporativos com fatores de ajuste
df = bcorpevents("PETR4")
print(df[["type", "effective_date", "calculated_factor"]])
# Catalogo de feriados (datas por tabela indisponiveis — param nao descoberto)
print(bholidays()[["id", "name"]])
# Times & trades intraday
trades = btrades("PETR4", "20260525")
print(trades[["price", "size", "tendency"]].head())
# Instrument search via API
df = bsearch("PETR", max_results=5)
print(df[["ticker", "name", "exchange", "has_intraday"]])
# Quote streaming
def on_quote(data: dict) -> None:
print(data["COD"], data["ULT"], data["VAR"])
# Market stats streaming (tabelas ao vivo da Bovespa)
def on_market(data: dict) -> None:
print(data["header"], data["rows"][:2])
with BroadcastPlusClient() as client:
client.subscribe(["PETR4", "VALE3"], callback=on_quote)
client.subscribe_market([0, 1], callback=on_market) # maiores altas/baixas
client.run(duration=60)
DataFrame layout & Ticker objects
Every tabular function returns a flat/long DataFrame with a ticker column —
not a column MultiIndex like xbbg or yfinance.download(). Flat/long is the
canonical layout: it makes groupby("ticker"), concat, and Parquet/SQL
persistence trivial, and keeps the empty-result schema stable.
If you prefer the wide layout (df["PETR4"] selects one instrument), use the
opt-in .bcast accessor — it is a pure reshape, the default stays flat:
df = bhistory(["PETR4", "VALE3"], "20260501", "20260520") # flat: ticker column
wide = df.bcast.wide() # column MultiIndex (ticker, field)
wide["PETR4"]["close"] # select one instrument
wide.bcast.long() # inverse, back to flat
wide() suits time-series frames (bhistory, bmacro, breturn, ...) where each
(date, ticker) pair is unique.
For charting, df.bcast.ohlc() renames an OHLCV frame's open/high/low/close[/volume] to the
capitalized Open/High/Low/Close/Volume that mplfinance expects (single instrument — filter by
ticker first).
For an object-oriented style (like yfinance's Ticker), Ticker is a thin
facade over the b* functions — no new logic, just discoverability:
from py_bcast import Ticker
petr = Ticker("PETR4")
petr.history("20260501", "20260520") # -> bhistory
petr.dividends # -> bdividends
petr.quote # -> bquote
petr.indicators("EBITDA", "20260101", "20260520") # -> bindicators
Supported Assets
| Class | Examples | Real-time | Daily History | Tick Data |
|---|---|---|---|---|
| B3 Stocks | PETR4, VALE3, ITUB4 | ✅ | ✅ | ❌ |
| FIIs | HGLG11, MXRF11 | ✅ | ✅ | ❌ |
| BDRs | AAPL34, MSFT34 | ✅ | ✅ | ❌ |
| Indices | IBOV, IFIX, SMLL | ✅ | ✅ | ❌ |
| FX | USDBRL, EURUSD, GBPUSD | ✅ | ✅ | ✅ |
| Metals | GOLD, SILVER | ✅ | ✅ | ✅ |
| Energy | WTI, BRENT | ✅ | ✅ | ✅ |
| Global Indices | DAX, FTSE, VIX, DXY | ✅ | ✅ | ✅ |
| Treasuries | US10Y, US2Y | ✅ | ✅ | ✅ |
| DI Futures | DI1F27 | ✅ | ✅ | ❌ |
Project Structure
src/py_bcast/
├── __init__.py # Public API (93 exported symbols + async_api namespace)
├── _core/ # Backend-agnostic infrastructure (both backends)
│ ├── config.py # Settings dataclass + configure() (incl. terminal=, plus_login=, plus_password=)
│ ├── routing.py # get_active_terminal() — picks legacy vs plus per call
│ ├── memory.py # Win32 helpers: find_process_pid + scan_process_memory
│ ├── exceptions.py # PyBcastError, SessionError, BroadcastPlusError, BroadcastPlusAuthError, …
│ ├── constants.py # Service names, URLs (legacy + plus), exchange normalization
│ ├── cache.py # Response cache (memory + diskcache)
│ ├── ratelimit.py # Token-bucket rate limiter
│ ├── retry.py # Tenacity retry decorator
│ ├── validation.py # Pydantic types + @validate_params
│ └── (logging, dates, normalize)
├── _legacy/ # Legacy protocol stack (DDE + ContentProxy; never imported by _plus)
│ ├── dde.py # DDE conversations with bcsys32.exe
│ ├── http.py # Legacy ContentProxy httpx client pool (sync + async singletons)
│ ├── session.py # Legacy session token discovery (memory scan of bcsys32.exe)
│ ├── aetp.py # Pure AETP protocol helpers (rows_to_dicts, entity tags)
│ ├── binary.py # Binary response parser
│ ├── xml_helpers.py # Pure ContentProxy XML parsing (parse_ticks, status policy)
│ ├── resolve_state.py # Shared sync/async resolution caches + pure matchers
│ ├── columns.py # Column schemas + rename maps
│ ├── spec.py # EndpointSpec / ParamBind declarative endpoint descriptors
│ ├── endpoints.py # EndpointSpec catalog (one spec per migrated endpoint)
│ ├── output.py # DataFrame finalization (finalize_frame, empty_history_frame)
│ ├── multi.py # vectorize / vectorize_async multi-ticker fan-out
│ ├── _async/ # I/O layer SOURCE (async-first): transport, executor, resolve, quote, historical
│ └── _sync/ # I/O layer GENERATED from _async/ by scripts/gen_sync.py — do not edit
├── _plus/ # Broadcast+ backend
│ ├── session.py # JWT auth chain: env → cache → refresh → memory scan → ECDH login
│ ├── crypto.py # ECDH P-384 + AES-GCM-256 (matching app.asar buildEncryptedResult)
│ ├── http.py # Plus httpx client singletons (sync + async) + auth headers
│ ├── realtime.py # BroadcastPlusClient (WebSocket /stock/ws) — quotes + market stats
│ ├── intraday.py # btrades() facade — POST /stock/v1/timesAndTrades
│ ├── reference.py # binfo, bindexes, bindex_members, blogo, bholidays, bbrokers, bexchanges
│ ├── funds.py # bfunds, bfund — POST /funds/v1/search, GET /funds/v1/{id}
│ ├── news.py # bsections, bheadlines, bnews_content
│ ├── corporate.py # bcorpevents — POST /stock/v1/corporateevents/{symbol}
│ ├── _async/ # Plus I/O SOURCE (async-first): plus_request, trades core
│ └── _sync/ # Plus I/O GENERATED from _async/ by scripts/gen_sync.py — do not edit
├── _async/ # Async versions of all legacy HTTP data functions
├── realtime/client.py # Legacy DDE: BroadcastClient, bdp (one or many tickers)
├── historical/ # bhistory, bclose, bdi, bdt, bticks, bfirst_close (legacy ContentProxy)
├── fixedincome.py # btreasury, btreasury_history, baccrual, bsavings, bunit_price
├── funds.py # bfund_history, bfund_returns, bfund_list
├── macro/indicators.py # bmacro (inclui CDI), breturn, bvolume, binflation, binflation_history, bstats, bsnapshot, bfx
├── credit/cds.py # bcds, bcds_indices (Markit CDS / credito)
├── fundamental/ # bconsensus, bcompany, bindices, …, bcalendar, bdividends, …
├── news/api.py # bnews, bnews_recent, bnews_multimedia
└── instruments/db.py # InstrumentDB + bsearch (auto-routing legacy/plus)
tests/
├── conftest.py # Resource-aware skips (legacy_session, legacy_db, plus markers)
├── test_session.py # Session discovery + memory scanning
├── test_instruments.py # bsearch + InstrumentDB (legacy_db + plus)
├── test_historical.py, test_intraday.py, test_macro.py,
├── test_reference.py, test_events.py, test_fundamental.py # legacy_session
└── ...
scripts/ # Utilities for data regeneration / probing
docs/
├── architecture.md # Dual-backend overview + shared core
├── compatibility.md # Legacy vs Plus feature mapping
├── legacy/ # Terminal Antigo (bcsys32.exe)
│ ├── api.md # API reference
│ ├── endpoints.md # 227-endpoint status catalog
│ ├── internals.md # DDE, ContentProxy, protocols
│ ├── fields.md # DDE field reference (644 fields)
│ ├── instruments.md # Instrument database details
│ ├── limitations.md # Known limitations & workarounds
│ └── roadmap.md # Implementation backlog
└── plus/ # Terminal Novo (Broadcast+.exe)
├── api.md # API reference (Plus functions)
├── endpoints.md # Discovered endpoint catalog
├── internals.md # Auth ECDH/JWT, WebSocket, schemas
├── limitations.md # Known limitations & blockers
└── roadmap.md # Implementation backlog
Documentation
- Architecture — dual-backend overview, shared core
- Compatibility — Legacy vs Plus feature mapping
- Terminal Antigo: API | Endpoints | Internals | Limitations | Roadmap
- Terminal Novo: API | Endpoints | Internals | Limitations | Roadmap
License
MIT © py-bcast contributors
A licença cobre apenas o código-fonte desta biblioteca. Ela não concede nenhum direito sobre o serviço Broadcast, seus dados ou suas marcas.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file py_bcast-0.8.0.tar.gz.
File metadata
- Download URL: py_bcast-0.8.0.tar.gz
- Upload date:
- Size: 229.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0925d78319a751d89e91564f8d67e3eb13e1baa1b33a44910ac3fa6605ee0a0f
|
|
| MD5 |
6f375a362762b7b9f2adaf3f102ebdea
|
|
| BLAKE2b-256 |
120f84287b400d011f8233c0c13bea521b81fa4e0033a4bf7fda85d608931ac0
|
Provenance
The following attestation bundles were made for py_bcast-0.8.0.tar.gz:
Publisher:
publish.yml on enzoomoreira/py-bcast
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
py_bcast-0.8.0.tar.gz -
Subject digest:
0925d78319a751d89e91564f8d67e3eb13e1baa1b33a44910ac3fa6605ee0a0f - Sigstore transparency entry: 1854177816
- Sigstore integration time:
-
Permalink:
enzoomoreira/py-bcast@38086cf2fb1540f328d70569154162faba269550 -
Branch / Tag:
refs/heads/master - Owner: https://github.com/enzoomoreira
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@38086cf2fb1540f328d70569154162faba269550 -
Trigger Event:
workflow_dispatch
-
Statement type:
File details
Details for the file py_bcast-0.8.0-py3-none-any.whl.
File metadata
- Download URL: py_bcast-0.8.0-py3-none-any.whl
- Upload date:
- Size: 183.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
348f115a2ed0ecf69ea953179b168f9450668b8240eaef0cee8738e05c833fed
|
|
| MD5 |
595f45ced2ed78a4eba72fe0ef814c05
|
|
| BLAKE2b-256 |
2d6d92a7487009d34cff314a86d01cc66bc48162f941577d9aaf888bfd51e817
|
Provenance
The following attestation bundles were made for py_bcast-0.8.0-py3-none-any.whl:
Publisher:
publish.yml on enzoomoreira/py-bcast
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
py_bcast-0.8.0-py3-none-any.whl -
Subject digest:
348f115a2ed0ecf69ea953179b168f9450668b8240eaef0cee8738e05c833fed - Sigstore transparency entry: 1854177882
- Sigstore integration time:
-
Permalink:
enzoomoreira/py-bcast@38086cf2fb1540f328d70569154162faba269550 -
Branch / Tag:
refs/heads/master - Owner: https://github.com/enzoomoreira
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@38086cf2fb1540f328d70569154162faba269550 -
Trigger Event:
workflow_dispatch
-
Statement type: