Files
Danglewood 869cfed125 [Release] openbb-v5.0.0 (#7741)
* merge branch develop with main

* bump desktop version

* fix the merge

* sync Cargo.lock to desktop 2.0.0

* fix cli conftest.py

---------

Co-authored-by: deeleeramone <>
2026-09-29 10:58:44 -07:00

161 lines
4.9 KiB
Python

"""Shared fixtures for the openbb_deribit test suite."""
import json
from pathlib import Path
import pytest
DATA_DIR = Path(__file__).parent / "data"
def payload(name: str):
"""Return one captured Deribit payload."""
return json.loads((DATA_DIR / f"{name}.json").read_text(encoding="utf-8"))
@pytest.fixture
def load():
"""Return the loader for a captured Deribit payload."""
return payload
@pytest.fixture(autouse=True)
def _no_network(request, monkeypatch):
"""Fail loudly rather than reaching the exchange from a unit test.
A test marked ``uses_session`` builds its own sessions and is left alone;
a session is only a connection pool until something asks it for a URL.
"""
if request.node.get_closest_marker("uses_session"):
return
async def _forbidden(*args, **kwargs):
raise AssertionError(
"A unit test opened a session. Patch the client or the session."
)
monkeypatch.setattr("openbb_deribit.utils.session.get_session", _forbidden)
monkeypatch.setattr("openbb_deribit.utils.session.get_cached_session", _forbidden)
@pytest.fixture
def responder(monkeypatch):
"""Answer client calls from a mapping of method name to payload."""
def install(mapping: dict):
async def _request(method, params=None, use_cache=True):
if method not in mapping:
raise AssertionError(f"No fixture registered for public/{method}.")
answer = mapping[method]
return answer(params) if callable(answer) else answer
async def _gather(calls, use_cache=True):
return [await _request(method, params) for method, params in calls]
monkeypatch.setattr("openbb_deribit.utils.client.request", _request)
monkeypatch.setattr("openbb_deribit.utils.client.gather", _gather)
return mapping
return install
def _chain_rows(inverse: bool, spot: float, size: float):
"""Build a small, well-formed chain around a spot price."""
from datetime import date, timedelta
today = date.today()
rows = []
for days in (1, 30):
expiration = today + timedelta(days=days)
for step in range(-4, 5):
strike = round(spot * (1 + step * 0.02), 4)
for option_type in ("call", "put"):
moneyness = (
max(0.0, spot - strike)
if option_type == "call"
else max(0.0, strike - spot)
)
extrinsic = spot * 0.01 * (days / 30) ** 0.5
mark = moneyness + extrinsic
rows.append(
{
"contract_symbol": (
f"TEST-{days}-{strike:g}-{option_type[0].upper()}"
),
"expiration": expiration,
"dte": days,
"strike": float(strike),
"option_type": option_type,
"contract_size": size,
"tick_size": 0.0001,
"is_inverse": inverse,
"mark": mark,
"bid": mark * 0.98,
"ask": mark * 1.02,
"last": mark,
"implied_volatility": 50.0 + abs(step) * 2,
"open_interest": 10.0 + step,
"volume": 5.0,
"underlying_price": spot,
"underlying_spot_price": spot,
"delta": 0.5,
"gamma": 0.001,
"theta": -1.0,
"vega": 10.0,
"rho": 1.0,
}
)
return rows
@pytest.fixture
def chain_frame():
"""Return a builder for a synthetic option chain."""
from pandas import DataFrame
def build(inverse: bool = True, spot: float = 100.0, size: float = 1.0):
return DataFrame(_chain_rows(inverse, spot, size))
return build
@pytest.fixture
def options_chain(chain_frame):
"""Return a synthetic chain as the model the options charts draw from."""
from openbb_deribit.utils.options.data_handler import to_chain
return to_chain(chain_frame(), "BTC")
@pytest.fixture
def loaded_chain(monkeypatch, chain_frame):
"""Serve a synthetic chain wherever a chain would be loaded."""
def install(
inverse: bool = True,
spot: float = 100.0,
size: float = 1.0,
books: list | None = None,
):
frame = chain_frame(inverse, spot, size)
async def _load(symbol, use_cache=True):
return frame.copy()
async def _combos(symbol, use_cache=True):
return list(books or [])
monkeypatch.setattr("openbb_deribit.utils.options.chain.load_chain", _load)
monkeypatch.setattr("openbb_deribit.utils.options.chain.load_combos", _combos)
return frame
return install