Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 28 additions & 9 deletions DATA_LAYER_SERVICE_ACCESS_GUIDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -358,23 +358,42 @@ At the 2026-07-08 smoke test, Binance listed `BTCUSDT_260925` as `CURRENT_QUARTE
Preferred alpha warmup/rebalance request for basis-arb:

```bash
POST http://data_layer:8100/v1/binance/futures/basis-bundle
POST http://data_layer:8100/v1/binance/futures/continuous-basis-bundle
Content-Type: application/json

{
"perp_symbol": "BTCUSDT",
"delivery_symbol": "BTCUSDT_260925",
"pair": "BTCUSDT",
"interval": "1d",
"period": "1d",
"limit": 30,
"include_depth": true,
"depth_limit": 5,
"contract_type": "CURRENT_QUARTER"
"lookback_days": 365,
"buffer_days": 14,
"current_delivery_symbol": "BTCUSDT_260925",
"roll_policy": "research_volume_crossover"
}
```

Bundle response contract:
Continuous-basis response contract:

- data_layer rebuilds a rolling active-quarterly chain from Binance Vision USD-M kline ZIPs.
- The stitching logic mirrors the research `DataPreprocessor` contract:
- generate candidate quarterly symbols such as `BTCUSDT_250926`, `BTCUSDT_251226`, ...;
- parse expiry from symbol suffix;
- select active windows by previous expiry/current expiry;
- compute `is_after_crossover` from 3-day rolling volume crossover;
- align perpetual and active quarterly candles;
- output `quarterly_close`, `quarterly_volume`, `active_contract`, `days_to_expiry`,
`perpetual_close`, `perpetual_volume`, `basis`, and `is_after_crossover`.
- Monthly Binance Vision ZIPs are cached under `BINANCE_VISION_CACHE_DIR`
(default `/app/data/binance_vision_cache`). Daily ZIP fallback is used only for recent months
where monthly files may not be published yet.
- Optional `fallback_url` can point to a research read API if Binance Vision is unavailable.
- The endpoint is a lightweight derived wrapper, not a Redis live feed and not a long-term parquet
store.

Short recent component request remains available for diagnostics or append flows:

```bash
POST http://data_layer:8100/v1/binance/futures/basis-bundle
```

- `components` contains successful raw provider payloads keyed by component name.
- `errors` contains per-component failures.
Expand Down
25 changes: 25 additions & 0 deletions app/api/routes_binance_derivatives.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

from fastapi import APIRouter, Body, HTTPException, Query

from app.providers.binance import basis_continuous
from app.providers.binance import derivatives as binance_derivatives
from app.providers.binance.rest import BINANCE_KLINE_INTERVALS, BinanceProviderError

Expand Down Expand Up @@ -172,6 +173,30 @@ async def get_basis(
_provider_error(exc)


@router.post("/continuous-basis-bundle")
async def post_continuous_basis_bundle(body: dict[str, Any] = Body(...)):
pair = str(body.get("pair") or body.get("perp_symbol") or "").upper().strip()
if not pair:
raise HTTPException(status_code=400, detail="missing_required_field:pair")
try:
return basis_continuous.fetch_continuous_basis_bundle(
pair=pair,
interval=str(body.get("interval") or body.get("resolution") or "1d"),
lookback_days=int(body.get("lookback_days") or body.get("limit_days") or 365),
buffer_days=int(body.get("buffer_days") or 14),
roll_policy=str(body.get("roll_policy") or "research_volume_crossover"),
current_delivery_symbol=body.get("current_delivery_symbol") or body.get("delivery_symbol"),
include_components=bool(body.get("include_components", False)),
fallback_url=body.get("fallback_url"),
)
except ValueError as exc:
_bad_request(exc)
except BinanceProviderError as exc:
_provider_error(exc)
except BinanceProviderError as exc:
_provider_error(exc)


@router.post("/basis-bundle")
async def post_basis_bundle(body: dict[str, Any] = Body(...)):
try:
Expand Down
Loading
Loading