Repository navigation
Releases: nbsp1221/xret
Release list
xret-data-v0.6.0
xret-data-v0.5.1
Xret Data 0.5.1
This release corrects the provider-trust model introduced in 0.5.0. It is an intentional pre-1.0 breaking API correction: Xret no longer treats prior exchange qualification as an execution allowlist or as runtime state.
What changed
- Provider-advertised CCXT and CCXT Pro operations may run when Xret can represent the requested market and timeframe without a known lossless-contract conflict.
- Every returned observation still passes Xret's schema, timestamp, ordering, duplicate, range, OHLC, volume, finality, and coverage checks before it can be returned or committed.
- Known incompatible endpoint/timeframe combinations remain narrowly rejected.
- Historical scopes without an exact bounded-window policy use conservative presence-only pagination; validated rows are returned while every unproved interval remains
missing. - Prior qualification remains available as dated public QA evidence in the verified-support documentation, but it is not loaded into execution, capabilities, results, or warnings.
- Live subscriptions are capability-based and no longer restricted to the previously qualified Binance, Bybit, and OKX matrix.
Public API migration
BarDataset.fetch()now returnsFetchResult; use.datafor the Polars frame and inspect.source,.warnings,.gaps, and.is_completewhen needed.LiveMarketData.subscribe_bar_updates()now returnsLiveSubscriptioninstead ofNone.SyncResult.sourcerecords provider provenance when a remote observation occurred.MarketDefinition.bar_capabilitiesreports current historical/live availability and capability notices.VerificationStatus,Verification,UnverifiedProviderWarning,OperationCapability.verification, andProviderEvidence.verificationwere removed.- Call
require_complete()when an application requires a complete requested historical range.
See the provider trust model, 0.5.1 API migration, and verified-support evidence for the exact boundaries.
Known issue
Hyperliquid's candle endpoint exposes only its most recent 5,000 candles. Xret 0.5.1 currently represents an empty historical request outside that retention horizon as observed unavailable coverage rather than leaving it unknown as missing. This does not insert or synthesize bars, but callers must not treat that unavailable result as proof that no candle originally existed. Recent Hyperliquid spot/perpetual history, perpetual live delivery, and bootstrap were verified after publication. See the official Hyperliquid candle endpoint documentation for the retention boundary.
Install
uv add "xret-data==0.5.1"What's Changed
- π₯ Replace provider allowlists with runtime trust in #5
Full Changelog: xret-data-v0.5.0...xret-data-v0.5.1
xret-data-v0.5.0
xret-data-v0.4.0
xret-data 0.4.0 adds an opt-in, provider-neutral initial handoff between recent historical bars and an activated live stream. It closes the fetch-to-subscribe race without coupling live observations to canonical Parquet or SQLite state.
Highlights
- Added
bootstrap=TruetoLiveMarketData.subscribe_bar_updates(...)for an ordered recent snapshot-to-live transition. - Added
BarFinalitywithFORMING,PROVISIONAL, andFINALobservation-time classifications. - Added
BarUpdate.finalitywhile keeping finality independent from canonical persistence. - Buffered live observations win timestamp overlap with the validated recent snapshot, producing an ascending, duplicate-free initial sequence.
- Provider activation or bootstrap cancellation now makes the one-shot live session terminal when the remote subscription state may be uncertain.
Usage
import asyncio
from xret.data import BarFinality, MarketData
async def main() -> None:
market_data = MarketData()
bars = market_data.bars(
exchange="binance",
symbol="BTC/USDT",
market="spot",
timeframe="1m",
)
async with market_data.live(exchange="binance") as live:
await live.subscribe_bar_updates(bars, bootstrap=True)
async for update in live:
print(update.timestamp, update.close, update.finality)
if update.finality is BarFinality.FORMING:
print("current bar may still change")
asyncio.run(main())Important semantics
- Bootstrap activates the live route first, buffers incoming observations, acquires a small validated window of recent closed bars through the existing provider layer, and merges both sources by timestamp.
FINALmeans the observation passed Xret's time-based finality grace when received. It does not mean the value is persisted or canonical; canonical storage still requires an explicitsync().- Live subscription and bootstrap never write Parquet, open the SQLite catalog, or record coverage.
- Bootstrap handles only the initial historical-to-live boundary. It does not hide disconnects, reconnect automatically, or repair later continuity gaps.
- A provider failure, malformed update, queue overflow, or uncertain cancelled activation terminates the session. Create a new live session according to the application's recovery policy.
Release qualification
The built 0.4.0 wheel was qualified from fresh external uv environments against Binance, Bybit, and OKX spot and USDT-settled perpetual markets. Pre-release coverage exercised BTC, ETH, and SOL across 1m, 5m, and 1h for 18 combinations; the published PyPI package was then reinstalled without a local source override and reverified across all six venue and market-family combinations. These checks verified bootstrap ordering, unique initial timestamps, finality values, lifecycle cleanup, and unchanged canonical storage paths. They do not claim uninterrupted delivery, automatic reconnection, or long-running soak stability.
Upgrade
uv add "xret-data==0.4.0"This release requires Python 3.12 or newer. The feature is additive and does not change the canonical Parquet or SQLite schema, so no storage migration is required from 0.3.0.
Documentation
- Live-bar guide
- Market-data API reference
- Provider contracts
- Verified support
- Implementation pull request
Full changelog: xret-data-v0.3.0...xret-data-v0.4.0
xret-data-v0.3.0
Highlights
xret-data 0.3.0 adds provider-neutral, asynchronous live time-bar streaming. Applications can consume normalized forming-bar updates through the same canonical market identities used by Xret's historical data API, while keeping live delivery separate from the canonical Parquet store and catalog.
import asyncio
from xret.data import MarketData
async def main() -> None:
market_data = MarketData()
btc = market_data.bars(
exchange="binance",
symbol="BTC/USDT",
market="spot",
timeframe="1m",
)
async with market_data.live(exchange="binance") as live:
await live.subscribe_bar_updates(btc)
async for update in live:
print(update.timestamp, update.close, update.received_at)
asyncio.run(main())What's new
MarketData.live(...)opens a one-shot live session for a canonical exchange.LiveMarketData.subscribe_bar_updates(...)subscribes one or more bar datasets from the sameMarketDatainstance and exchange.BarUpdateexposes canonical identity and timeframe, UTC bar-start and receive timestamps, and normalized OHLCV values.- The built-in CCXT provider uses CCXT Pro for live delivery while preserving Xret's provider-neutral public API.
- The optional provider SPI now supports live-bar sessions without changing the existing historical-data contract.
Delivery and failure semantics
- Updates represent the provider's current view of a forming bar. Repeated updates for the same timestamp are expected and do not imply finality.
- Live subscriptions do not call
sync, write Parquet, modify catalog coverage, or backfill gaps. - Disconnects, malformed updates, backwards timestamps, and bounded-queue overflow terminate the session with a
ProviderError. - Xret does not silently reconnect, retry, coalesce updates, or discard old events. Applications retain control over recovery and continuity policy.
- Trades, quotes, order books, finality flags, recording, replay, fan-out, and order execution are outside this release's contract.
Verified live combinations
Release qualification used the built wheel in a fresh external uv project with CCXT 4.5.71. Each combination subscribed through the public API, delivered a validated forming bar, and closed cleanly without creating canonical storage or catalog state.
| Venue | Market family | Symbol | Timeframe |
|---|---|---|---|
| Binance | Spot | BTC/USDT |
1m |
| Binance USD-M | USDT-settled linear perpetual | BTC/USDT |
1m |
| Bybit | Spot | BTC/USDT |
1m |
| Bybit | USDT-settled linear perpetual | BTC/USDT |
1m |
| OKX | Spot | BTC/USDT |
1m |
| OKX | USDT-settled linear perpetual | BTC/USDT |
1m |
This verifies connectivity, normalization, multiplexing, and lifecycle behavior for the listed combinations. It does not claim uninterrupted continuity, exhaustive delivery, historical finality, automatic reconnection, or long-running stability.
Upgrade
uv add "xret-data==0.3.0"This release requires Python 3.12 or newer. The live API is additive; no historical Parquet or catalog migration is required.
Documentation
Full changelog: xret-data-v0.2.1...xret-data-v0.3.0
xret-data-v0.2.1
xret-data 0.2.1 introduces a provider-neutral market-data layer, market-definition discovery, and substantial correctness and performance improvements across synchronization, storage, and recovery.
Highlights
- Added an experimental provider-author API under
xret.data.providers, with direct provider injection and lazy installed-provider discovery. - Added
MarketData.fetch_markets(...)for fetching immutable, provider-independent market definitions, including canonical identity, advertised active status and timeframes, exact tick/size increments when available, and perpetual-contract interpretation. - Kept CCXT as the built-in provider while separating provider contracts, runtime validation, market normalization, and pagination from the CCXT implementation.
- Added source-lineage enforcement so canonical datasets cannot be silently extended by a different provider implementation.
- Added package metadata, bundled license files, and
xret.data.__version__.
Correctness and reliability
- Fixed sparse OHLCV pagination that could otherwise produce incomplete or corrupted acquisition results.
- Fixed month-crossing datasets that could become unreadable.
- Prevented temporary or unverified empty pages from being recorded as unavailable coverage.
- Excluded provider-native bar types that Xret's canonical timeframe grammar cannot represent safely.
- Rejected non-finite volume values before canonical publication.
- Ensured failed pre-publication synchronization attempts retain their failed ingestion-run status.
- Strengthened canonical storage validation, catalog rebuild evidence, recovery behavior, and provider error boundaries.
Performance
- Coalesced sparse missing gaps and contiguous coverage segments to reduce provider requests and catalog rewrites.
- Batched coverage recording during synchronization.
- Vectorized timeframe-gap detection, timestamp alignment, deduplication, and aggregate price validation.
Important upgrade notice
Xret 0.x does not automatically migrate incompatible canonical Parquet or SQLite catalog schemas. This release changes the canonical Parquet schema from version 4 to 5 and the catalog schema from version 3 to 4.
An existing store created by xret-data 0.1.0 is therefore not directly compatible with 0.2.1. Back up the old state if it must be retained, configure a fresh state_dir, and synchronize the required data again. Pin xret-data==0.1.0 if an application must continue reading an existing 0.1.0 store. Xret rejects incompatible state instead of silently migrating or mutating it.
Scope
The provider contract currently covers synchronous historical OHLCV time bars for crypto spot and perpetual markets. It does not define streaming data, trades, quotes, fundamentals, provider-specific columns, fallback providers, or synthetic timeframes. Market-definition availability and advertised timeframes are not equivalent to verified historical-bar support; consult the verified support matrix for qualified combinations.
Full changelog: xret-data-v0.1.0...xret-data-v0.2.1