[Feature] Add Deribit Provider Extension For Crypto Options Data (#6985)

* add deribit provider and make some small changes to the standard model to allow for fractional volume and size

* linter

* typehint

* more lint

* more touchup

* update test

* remove line in test

* maybe we need that after all..?
This commit is contained in:
Danglewood
2024-12-30 15:57:57 -08:00
committed by GitHub
parent 8fd46ed450
commit efd09ce75b
20 changed files with 2831 additions and 106 deletions

View File

@@ -0,0 +1,12 @@
# OpenBB Deribit Provider Extension
## Coverage
- obb.derivatives.options.chains
- Support for symbols:
- BTC
- ETH
- XRP
- SOL
- BNB
- PAXG

View File

@@ -0,0 +1 @@
"""OpenBB Deribit Provider Module."""

View File

@@ -0,0 +1,15 @@
"""OpenBB Deribit Provider Module."""
from openbb_core.provider.abstract.provider import Provider
from openbb_deribit.models.options_chains import DeribitOptionsChainsFetcher
deribit_provider = Provider(
name="deribit",
website="https://deribit.com/",
description="""Unofficial Python client for public data published by Deribit.""",
credentials=None,
fetcher_dict={"OptionsChains": DeribitOptionsChainsFetcher},
repr_name="Deribit Public Data",
instructions="This provider does not require any credentials and is not meant for trading.",
)

View File

@@ -0,0 +1 @@
"""Deribit Data Models."""

View File

@@ -0,0 +1,279 @@
"""Deribit Options Chains Model."""
# pylint: disable=unused-argument
from datetime import datetime
from typing import Any, Optional, Union
from openbb_core.app.model.abstract.error import OpenBBError
from openbb_core.provider.abstract.fetcher import Fetcher
from openbb_core.provider.standard_models.options_chains import (
OptionsChainsData,
OptionsChainsQueryParams,
)
from openbb_core.provider.utils.errors import EmptyDataError
from openbb_deribit.utils.helpers import DERIBIT_OPTIONS_SYMBOLS
from pydantic import Field, field_validator
class DeribitOptionsChainsQueryParams(OptionsChainsQueryParams):
"""Deribit Options Chains Query Parameters Model."""
__json_schema_extra__ = {
"symbol": {
"multiple_items_allowed": False,
"choices": DERIBIT_OPTIONS_SYMBOLS,
}
}
@field_validator("symbol", mode="before", check_fields=False)
@classmethod
def _validate_symbol(cls, v):
"""Validate the symbol."""
if v.upper() not in DERIBIT_OPTIONS_SYMBOLS:
raise ValueError(
f"Invalid Deribit symbol. Supported symbols are: {', '.join(DERIBIT_OPTIONS_SYMBOLS)}",
)
return v
class DeribitOptionsChainsData(OptionsChainsData):
"""Deribit Options Chains Data Model."""
__alias_dict__ = {
"contract_symbol": "instrument_name",
"change_percent": "price_change",
"underlying_symbol": "underlying_index",
"underlying_spot_price": "index_price",
"bid_size": "best_bid_amount",
"ask_size": "best_ask_amount",
"bid": "best_bid_price",
"ask": "best_ask_price",
"implied_volatility": "mark_iv",
"mark": "mark_price",
"last_trade_price": "last_price",
"volume_notional": "volume_usd",
}
__doc__ = OptionsChainsData.__doc__
bid_iv: list[Union[float, None]] = Field(
default_factory=list,
description="The implied volatility of the bid price.",
json_schema_extra={"x-unit_measurement": "decimal"},
)
ask_iv: list[Union[float, None]] = Field(
default_factory=list,
description="The implied volatility of the ask price.",
json_schema_extra={"x-unit_measurement": "decimal"},
)
interest_rate: list[Union[float, None]] = Field(
default_factory=list,
description="The interest rate used by Deribit to calculate greeks.",
)
underlying_spot_price: list[float] = Field(
description="The spot price of the underlying asset."
" The underlying asset is the specific future or index that the option is based on.",
json_schema_extra={"x-unit_measurement": "currency"},
)
settlement_price: list[Union[float, None]] = Field(
default_factory=list,
description="The settlement price of the contract.",
json_schema_extra={"x-unit_measurement": "currency"},
)
min_price: list[Union[float, None]] = Field(
default_factory=list,
description="The minimum price allowed.",
json_schema_extra={"x-unit_measurement": "currency"},
)
max_price: list[Union[float, None]] = Field(
default_factory=list,
description="The maximum price allowed.",
json_schema_extra={"x-unit_measurement": "currency"},
)
volume_notional: list[Union[float, None]] = Field(
default_factory=list,
description="The notional trading volume of the contract, as USD or USDC.",
json_schema_extra={"x-unit_measurement": "currency"},
)
timestamp: list[datetime] = Field(
description="The datetime of the data, as America/New_York time.",
)
class DeribitOptionsChainsFetcher(
Fetcher[DeribitOptionsChainsQueryParams, DeribitOptionsChainsData]
):
"""Deribit Options Chains Fetcher."""
require_credentials = False
@staticmethod
def transform_query(params: dict[str, Any]) -> DeribitOptionsChainsQueryParams:
"""Transform the query parameters."""
return DeribitOptionsChainsQueryParams(**params)
@staticmethod
async def aextract_data(
query: DeribitOptionsChainsQueryParams,
credentials: Optional[dict[str, str]],
**kwargs: Any,
) -> list[dict]:
"""Extract the data."""
# pylint: disable=import-outside-toplevel
import asyncio # noqa
import json
import websockets
from openbb_deribit.utils.helpers import get_options_symbols
from pandas import to_datetime
from warnings import warn
# We need to identify each option contract in order to fetch the chains data.
symbols_dict: dict[str, str] = {}
try:
symbols_dict = await get_options_symbols(query.symbol)
except OpenBBError as e:
raise OpenBBError(e) from e
# For each expiration, we need to create a websocket connection to fetch the data.
# We subscribe to each contract symbol and break the connection when we have all the data for an expiry.
# If it takes too long, we break the connection and return an error message.
results: list = []
messages: set = set()
async def call_api(expiration):
"""Call the Deribit API."""
symbols = symbols_dict[expiration]
received_symbols: set = set()
msg = {
"jsonrpc": "2.0",
"id": 3600,
"method": "public/subscribe",
"params": {"channels": ["ticker." + d + ".100ms" for d in symbols]},
}
async with websockets.connect(
"wss://www.deribit.com/ws/api/v2"
) as websocket:
await websocket.send(json.dumps(msg))
try:
await asyncio.wait_for(
receive_data(websocket, symbols, received_symbols), timeout=2.0
)
except asyncio.TimeoutError:
messages.add(f"Timeout reached for {expiration}, data incomplete.")
async def receive_data(websocket, symbols, received_symbols):
"""Receive the data from the websocket with a timeout."""
while websocket.open:
response = await websocket.recv()
data = json.loads(response)
if "params" not in data:
continue
if "error" in data and data.get("error"):
messages.add(f"Error while receiving data -> {data['error']}")
break
res = data.get("params", {}).get("data", {})
symbol = res.get("instrument_name")
# While we are handling the data, we will parse the message.
if symbol not in received_symbols:
received_symbols.add(symbol)
stats = res.pop("stats", {})
greeks = res.pop("greeks", {})
timestamp = res.pop("timestamp", None)
underlying_symbol = res.get("underlying_index")
if underlying_symbol == "index_price":
res["underlying_index"] = symbol.split("-")[0].replace("_", "-")
res["timestamp"] = to_datetime(
timestamp, unit="ms", utc=True
).tz_convert("America/New_York")
if res.get("estimated_delivery_price") == res.get("index_price"):
_ = res.pop("estimated_delivery_price", None)
_ = res.pop("state", None)
result = {
"expiration": to_datetime(symbol.split("-")[1]).date(),
"strike": (
float(symbol.split("-")[2].replace("d", "."))
if "d" in symbol.split("-")[2]
else int(symbol.split("-")[2])
),
"option_type": (
"call"
if symbol.endswith("-C")
else "put" if symbol.endswith("-P") else None
),
**res,
**stats,
**greeks,
}
result["dte"] = (
result["expiration"] - to_datetime("today").date()
).days
results.append(result)
if len(received_symbols) == len(symbols):
await websocket.close()
break
tasks = [
asyncio.create_task(call_api(expiration)) for expiration in symbols_dict
]
await asyncio.gather(*tasks)
if messages and not results:
raise OpenBBError(", ".join(messages))
if results and messages:
for message in messages:
warn(message)
if not results and not messages:
raise EmptyDataError("All requests returned empty with no error messages.")
return results
@staticmethod
def transform_data(
query: DeribitOptionsChainsQueryParams,
data: list[dict],
**kwargs: Any,
) -> DeribitOptionsChainsData:
"""Transform the data."""
# pylint: disable=import-outside-toplevel
from numpy import nan
from pandas import DataFrame
df = DataFrame(data)
# For BTC and ETH options, we need to convert price units to USD.
for col in df.columns:
if col in [
"last_price",
"settlement_price",
"mark_price",
"min_price",
"max_price",
"best_ask_price",
"best_bid_price",
"high",
"low",
] and query.symbol.upper() in ["BTC", "ETH"]:
df.loc[:, col] = df[col].astype(float).multiply(df.index_price).round(2)
elif col in ["price_change", "mark_iv", "bid_iv", "ask_iv"]:
df.loc[:, col] = df[col].astype(float).divide(100)
df = df.replace({nan: None})
df = df.sort_values(["expiration", "strike", "option_type"])
df = df.reset_index(drop=True)
df.loc[:, "contract_size"] = 1
results = df.to_dict(orient="list")
return DeribitOptionsChainsData.model_validate(results)

View File

@@ -0,0 +1 @@
"""Deribit Utility Functions."""

View File

@@ -0,0 +1,111 @@
"""Deribit Helpers Module."""
from typing import Literal, Optional
from async_lru import alru_cache
from openbb_core.app.model.abstract.error import OpenBBError
DERIBIT_OPTIONS_SYMBOLS = ["BTC", "ETH", "SOL", "XRP", "BNB", "PAXG"]
OptionsSymbols = Literal["BTC", "ETH", "SOL", "XRP", "BNB", "PAXG"]
CURRENCIES = ["BTC", "ETH", "USDC", "USDT", "EURR", "all"]
Currencies = Literal["BTC", "ETH", "USDC", "USDT", "EURR", "all"]
DERIVATIVE_TYPES = ["future", "option", "spot", "future_combo", "option_combo"]
DerivativeTypes = Literal["future", "option", "spot", "future_combo", "option_combo"]
BASE_URL = "https://www.deribit.com"
@alru_cache(maxsize=64)
async def get_instruments(
currency: Currencies = "BTC",
derivative_type: Optional[DerivativeTypes] = None,
) -> list[dict]:
"""
Get Deribit instruments.
Parameters
----------
currency : Currencies
The currency to get instruments for. Default is "BTC".
derivative_type : Optional[DerivativeTypes]
The type of derivative to get instruments for. Default is None, which gets all types.
Returns
-------
list[dict]
A list of instrument dictionaries.
"""
# pylint: disable=import-outside-toplevel
from openbb_core.provider.utils.helpers import amake_request
if currency != "all" and currency.upper() not in CURRENCIES:
raise ValueError(
f"Currency {currency} not supported. Supported currencies are: {', '.join(CURRENCIES)}"
)
if derivative_type and derivative_type not in DERIVATIVE_TYPES:
raise ValueError(
f"Kind {derivative_type} not supported. Supported kinds are: {', '.join(DERIVATIVE_TYPES)}"
)
url = f"{BASE_URL}/api/v2/public/get_instruments?currency={currency.upper() if currency != 'all' else 'any'}"
if derivative_type is not None:
url += f"&kind={derivative_type}"
try:
response = await amake_request(url)
return response.get("result", []) # type: ignore
except Exception as e: # pylint: disable=broad-except
raise OpenBBError(
f"Failed to get instruments -> {e.__class__.__name__}: {e}"
) from e
async def get_options_symbols(symbol: OptionsSymbols = "BTC") -> dict:
"""
Get a dictionary of contract symbols by expiry.
Parameters
----------
symbol : OptionsSymbols
The underlying symbol to get options for. Default is "BTC".
Returns
-------
dict[str, str]
A dictionary of contract symbols by expiry date.
"""
# pylint: disable=import-outside-toplevel
from pandas import to_datetime
if symbol.upper() not in DERIBIT_OPTIONS_SYMBOLS:
raise ValueError(
f"Invalid Deribit symbol. Supported symbols are: {', '.join(DERIBIT_OPTIONS_SYMBOLS)}",
)
currency = (
"USDC" if symbol.upper() in ["BNB", "PAXG", "SOL", "XRP"] else symbol.upper()
)
instruments = await get_instruments(currency, "option")
expirations: dict = {}
all_options = list(
set(
d.get("instrument_name")
for d in instruments
if d.get("instrument_name").startswith(symbol)
and d.get("instrument_name").endswith(("-C", "-P"))
)
)
for item in sorted(
list(
set(
(
to_datetime(d.split("-")[1]).date().strftime("%Y-%m-%d"),
d.split("-")[1],
)
for d in all_options
)
)
):
expirations[item[0]] = item[1]
return {k: [d for d in all_options if v in d] for k, v in expirations.items()}

1609
openbb_platform/providers/deribit/poetry.lock generated vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,20 @@
[tool.poetry]
name = "openbb-deribit"
version = "1.0.0b"
description = "Deribit is a crypto-native derivatives exchange."
authors = ["OpenBB Team <hello@openbb.co>"]
license = "AGPL-3.0-only"
readme = "README.md"
packages = [{ include = "openbb_deribit" }]
[tool.poetry.dependencies]
python = "^3.9"
openbb-core = "^1.3.7"
async-lru = "^2.0.4"
[build-system]
requires = ["poetry-core"]
build-backend = "poetry.core.masonry.api"
[tool.poetry.plugins."openbb_provider_extension"]
deribit = "openbb_deribit:deribit_provider"

View File

@@ -0,0 +1 @@
"""OpenBB Deribit Provider Tests."""

View File

@@ -0,0 +1,265 @@
interactions:
- request:
body: null
headers:
Accept:
- application/json
Accept-Encoding:
- gzip, deflate
Connection:
- keep-alive
method: GET
uri: https://www.deribit.com/api/v2/public/get_instruments?currency=BTC&kind=option
response:
body:
string: !!binary |
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
eHz+ifEf/zcumxcqrf8IAA==
headers:
Access-Control-Allow-Headers:
- Authorization,User-Agent,Range,X-Requested-With,Content-Type,Partner
Access-Control-Allow-Methods:
- GET, POST, OPTIONS
Access-Control-Allow-Origin:
- '*'
Cache-Control:
- no-store
Connection:
- keep-alive
Content-Encoding:
- gzip
Content-Length:
- '12385'
Content-Type:
- application/json
Date:
- Sat, 07 Dec 2024 00:22:12 GMT
Server:
- nginx
Strict-Transport-Security:
- max-age=15768000
Vary:
- Origin,Authorization,Partner
- accept-encoding
X-Frame-Options:
- SAMEORIGIN
status:
code: 200
message: OK
version: 1

View File

@@ -0,0 +1,265 @@
interactions:
- request:
body: null
headers:
Accept:
- application/json
Accept-Encoding:
- gzip, deflate
Connection:
- keep-alive
method: GET
uri: https://www.deribit.com/api/v2/public/get_instruments?currency=BTC&kind=option
response:
body:
string: !!binary |
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
wnWqHd4STq59p0cu7HFL2XWzM9wutM7ad17Akyc74Tz7r0VzPBWeJ3RSHQrvHgJ6ZdcwkT2dNNkJ
16lpIkM4qY6Fd9hbrRtOp654ezppohOuU23xhnBSHQzvsLdal1Bzv0NpcykndShdoJMmOuE6+w1K
czoVnSdwUp1w7LC3Wt/WdTXG29NJE51wnWqMN4ST6qhO95Ch63oNuf8h3vnkiupEF+ikiU64zn57
0pxORecJnFRnzrmHgl7X1RZvTydNdMJ1qi3eEE6qw5PcQ8WOu9X+Ba3BJZ0Bco1OmuiE6+z3zs3p
VHTO47xv8Wmi08OPWeg3dmrXeZlOkuhcoFNN8YZwUs2xe+ikcNzi4ISaEEJp6752net10kQnXGf3
c9KkTkXnCZxUo5geO+xW4tbvnAub23PZFZ3rddJEJ1znqHVuRqei8wROqpZ4j206LqX07xsMzrtQ
FZ0X6KSJTrjOwbfOKZ2KzhM4qfo6PbZzrtSGb3AqYnRO0XmBTprohOscXGQwpVPReQInVXOSx7Z/
1K3GwYGyaat5U3Su10kTnXCd/W+dczoVnfM47+cr0ERnwNYwa4qDlnjv3Z4UnRfoJInOBToHJ3ZO
6fz/JDr/+btXX57+44eXeloKWwypti36rYn7y9N/br+Dv/wDv6fbH/zq3e9+d/uP136m5/ab/vD4
/BPjP/5vfg/xlq3/CAA=
headers:
Access-Control-Allow-Headers:
- Authorization,User-Agent,Range,X-Requested-With,Content-Type,Partner
Access-Control-Allow-Methods:
- GET, POST, OPTIONS
Access-Control-Allow-Origin:
- '*'
Cache-Control:
- no-store
Connection:
- keep-alive
Content-Encoding:
- gzip
Content-Length:
- '12383'
Content-Type:
- application/json
Date:
- Sat, 07 Dec 2024 00:13:55 GMT
Server:
- nginx
Strict-Transport-Security:
- max-age=15768000
Vary:
- Origin,Authorization,Partner
- accept-encoding
X-Frame-Options:
- SAMEORIGIN
status:
code: 200
message: OK
version: 1

View File

@@ -0,0 +1,99 @@
"""Deribit Fetcher Tests."""
from unittest.mock import MagicMock, patch
import pytest
from openbb_core.app.service.user_service import UserService
from openbb_core.provider.utils.helpers import run_async
from openbb_deribit.models.options_chains import (
DeribitOptionsChainsData,
DeribitOptionsChainsFetcher,
)
test_credentials = UserService().default_user_settings.credentials.model_dump(
mode="json"
)
MOCK_OPTIONS_DATA = DeribitOptionsChainsData.model_validate(
{
"expiration": ["2024-12-07", "2024-12-07"],
"strike": [84000.0, 84000.0],
"option_type": ["call", "put"],
"underlying_symbol": ["SYN.BTC-7DEC24", "SYN.BTC-7DEC24"],
"underlying_price": [100671.2825, 100671.2825],
"contract_symbol": ["BTC-7DEC24-84000-C", "BTC-7DEC24-84000-P"],
"dte": [1, 1],
"contract_size": [1, 1],
"open_interest": [1.0, 124.8],
"volume": [0.1, 151.9],
"last_trade_price": [None, 20.13],
"bid": [10.06, 0.05],
"bid_size": [0.3, 0.0],
"ask": [0.06, 10.06],
"ask_size": [0.0, 0.2],
"mark": [16666.69, 0.0],
"high": [None, 442.83],
"low": [None, 10.06],
"change_percent": [0, -0.6],
"implied_volatility": [1.3618999999999999, 1.3618999999999999],
"delta": [0.99997, -3e-05],
"gamma": [0.0, 0.0],
"theta": [-0.24909, -0.0263],
"vega": [0.00366, 0.00366],
"rho": [0.91572, -3e-05],
"underlying_spot_price": [100644.24, 100644.24],
"settlement_price": [14590.44, 14.35],
"timestamp": [
"2024-12-06 17:26:36.234000-0500",
"2024-12-06 17:26:36.234000-0500",
],
"min_price": [13184.4, 10.06],
"max_price": [20078.53, 1509.66],
"interest_rate": [0.0, 0.0],
"bid_iv": [0.0, 0.0],
"ask_iv": [0.0, 2.1254],
"volume_notional": [0.0, 7083.24],
}
)
@pytest.fixture(scope="module")
def vcr_config():
"""VCR configuration."""
return {
"filter_headers": [("User-Agent", None)],
"filter_query_parameters": [
None,
],
}
@pytest.mark.record_http
def test_get_options_symbols():
"""Test getting the list of options symbols."""
# pylint: disable=import-outside-toplevel
from openbb_deribit.utils.helpers import get_options_symbols
params = {"symbol": "BTC"}
result = run_async(get_options_symbols, **params)
assert result is not None
assert isinstance(result, dict)
assert len(result) > 0
for key, value in result.items():
assert isinstance(value, list)
assert key.startswith("2")
@pytest.mark.asyncio
async def test_deribit_options_chains_fetcher(credentials=test_credentials):
"""Test Deribit Options Chains Fetcher."""
params = {"symbol": "BTC"}
fetcher = DeribitOptionsChainsFetcher()
with patch(
"openbb_deribit.models.options_chains.DeribitOptionsChainsFetcher.fetch_data",
return_value=MagicMock(MOCK_OPTIONS_DATA),
):
result = await fetcher.fetch_data(params, {})
assert isinstance(result, DeribitOptionsChainsData)