Python SDK bestex-pulse 1.0.0

The official Python client for Pulse Analytics. Typed results your editor can complete, baskets of any size, and pandas tables in one call. It uses the same account as the API.

TypedEvery result is a typed object; your editor and type checker know its fields.
BasketsPrice thousands of orders in one call; sent 500 at a time for you.
pandas.to_pandas() on lists, bars, history and baskets.
Safe defaultsHTTPS only, retries on throttling, your password never stored.

Install

$pip install "bestex-pulse[pandas]"

Python 3.10 or later. Leave out [pandas] if you don't need tables. You need a Pulse account with access to the asset classes you call; request access if you don't have one.

Log in

In a notebook or terminal, create a client and you're asked for your email and password. A mistyped password can be retyped.

from bestex_pulse import Pulse pulse = Pulse() # Pulse email: you@example.com # Pulse password: # Logged in as you@example.com

For scheduled jobs, set PULSE_EMAIL and PULSE_PASSWORD in the environment and create the client with Pulse(interactive=False), which never prompts. Without a terminal (cron, CI, most containers) the client never prompts anyway. The session token is kept in memory only, and the client logs in again once by itself if it expires.

Quickstart

from bestex_pulse import Pulse pulse = Pulse() # 500 E-mini S&P contracts over an hour (times are UTC) est = pulse.futures.costs.fixed_duration( exchange_symbol="ESZ26", exchange_mic_code="XCME", date="2026-10-21", ordersize=500, start_time="14:30", end_time="15:30", ) est.total_bps # 0.338 # 200,000 shares of Apple est = pulse.equities.costs.fixed_duration(symbol="AAPL", mic="XNAS", date="2026-10-21", shares=200_000) est.predicted_total_cost_bps # 7.745

Futures

Identify a contract by exchange_symbol and exchange_mic_code. To find the one to ask about, list the contracts that traded on a day and take the most traded:

contracts = pulse.futures.instruments.active(date="2026-10-21", futures_base_symbol="ES", exchange_mic_code="XCME") front = min(contracts, key=lambda c: c.volume_rank)

Cost estimates carry total_bps, total_ticks, total_pct_spread and total_contract: market impact plus VWAP slippage. Values the API couldn't compute are None.

US equities

Pass symbol and mic, and the client looks the instrument up as of the request's date, or pass bestex_id. Each new lookup is one API call, so in a loop over many dates look it up once:

days = ["2026-10-20", "2026-10-21"] aapl = pulse.equities.instruments.resolve(symbol="AAPL", mic="XNAS") for day in days: pulse.equities.costs.fixed_duration(bestex_id=aapl.bestex_id, date=day, shares=200_000)

Baskets

Price many orders at once. Keyword arguments apply to every order that doesn't give its own. An unknown symbol comes back as that order's error (IDENTIFIER_NOT_FOUND) without failing the rest; a malformed order raises before anything is sent.

basket = pulse.equities.costs.fixed_duration_batch( [{"symbol": "AAPL", "mic": "XNAS", "shares": 200_000}, {"symbol": "MSFT", "mic": "XNAS", "shares": 150_000}], date="2026-10-21", start_time="14:00", end_time="15:30", ) basket.ok # the orders that were priced basket.errors # the rest, each with .error.error_code basket.to_pandas() # one row per order, indexed by its position

Tables (pandas)

Lists, bars, end-of-day history, intraday profiles and baskets have .to_pandas(). Values that describe the whole response go in df.attrs; missing values are <NA>.

bars = pulse.equities.history.bars(symbol="AAPL", mic="XNAS", date="2026-10-21") bars.to_pandas() # one row per minute

Method map

Every SDK method calls one API endpoint. Follow the link for that endpoint's fields, limits and responses in the API reference.

Futures
futures.instruments.supported_symbols()Supported Symbols
futures.instruments.active()Active Instruments
futures.costs.fixed_duration()Fixed Duration
futures.costs.fixed_participation()Fixed Participation
futures.costs.optimal_with_alpha_decay()Optimal POV w/ Alpha Decay
futures.analytics.trading_stats()Daily Trading Stats
futures.analytics.realized_stats()Realized Stats
futures.analytics.estimated_stats()Estimated Stats
futures.analytics.volume_estimate()Volume Estimates
futures.usage()Usage
US Equities
equities.instruments.resolve()Resolve Instrument
equities.instruments.resolve_batch()Resolve Instruments (batch)
equities.instruments.get()Instrument
equities.instruments.list()Instruments
equities.costs.fixed_duration()Fixed Duration
equities.costs.fixed_participation()Fixed Participation
equities.costs.closing_auction()Closing Auction
equities.costs.fixed_duration_batch()Fixed Duration (batch)
equities.costs.fixed_participation_batch()Fixed Participation (batch)
equities.costs.closing_auction_batch()Closing Auction (batch)
equities.analytics.intraday_profile()Intraday Profile
equities.analytics.liquidity_forecast()Intraday Liquidity Forecast
equities.analytics.liquidity_forecast_batch()Intraday Liquidity Forecast (batch)
equities.history.bars()Per-Minute Bars
equities.history.bars_enhanced()Per-Minute Bars (enhanced)
equities.history.eod()Daily EOD Series
equities.history.eod_latest()Latest EOD Row (bulk)
equities.reference.calendar()Calendar
equities.reference.countries()Countries
equities.reference.exchanges()Exchanges
equities.reference.trading_hours()Trading Hours
equities.meta.availability()Availability
equities.meta.cost_model()Cost Model
equities.meta.usage()Usage

Errors

Every error the client raises is a PulseError. API errors carry status_code, error_code, message and details.

ExceptionWhen
AuthenticationErrorWrong email or password, or the session was rejected
PermissionDeniedErrorNo access to the asset class, an ended trial, or a network your account can't call from
RateLimitErrorToo many requests, after the client's own retries
ServerErrorThe API failed on its side or is temporarily unavailable
ResponseValidationErrorThe answer didn't match this version; upgrading usually fixes it

Timeouts, retries and proxies

import httpx pulse = Pulse(timeout=60, max_retries=5) pulse = Pulse(http_client=httpx.Client(proxy="http://proxy.example.com:8080"))

Throttled requests and temporary failures are retried, waiting as the API asks. The client only talks https:// and never follows a redirect, so your password can't be sent anywhere else.

Versions and changes

Upgrades within 1.x won't break your code. Pin bestex-pulse>=1,<2.

1.0.0

First release: futures and US equities, single requests and batches, typed results with .to_pandas().

Support

Email api-support@bestexresearch.com. Your email creates a ticket for our API support team.

Package

bestex-pulse on PyPI: version history and files.