Add support for new various endpoints. Add ResourceNotFound error in bfxapi/rest/exceptions.py. Fix bug in BfxRestInterface.__GET method.

This commit is contained in:
Davide Casale
2022-12-09 16:16:15 +01:00
parent e0785f9f4a
commit cd5ef42118
4 changed files with 143 additions and 8 deletions

View File

@@ -2,20 +2,25 @@ import requests
from http import HTTPStatus from http import HTTPStatus
from typing import List, Union, Optional from typing import List, Union, Literal, Optional
from . import serializers from . import serializers
from .typings import * from .typings import *
from .exceptions import RequestParametersError from .exceptions import RequestParametersError, ResourceNotFound
class BfxRestInterface(object): class BfxRestInterface(object):
def __init__(self, host): def __init__(self, host):
self.host = host self.host = host
def __GET(self, endpoint, params = None): def __GET(self, endpoint, params = None):
data = requests.get(f"{self.host}/{endpoint}", params=params).json() response = requests.get(f"{self.host}/{endpoint}", params=params)
if data[0] == "error": if response.status_code == HTTPStatus.NOT_FOUND:
raise ResourceNotFound(f"No resources found at endpoint <{endpoint}>.")
data = response.json()
if len(data) and data[0] == "error":
if data[1] == 10020: if data[1] == 10020:
raise RequestParametersError(f"The request was rejected with the following parameter error: <{data[2]}>") raise RequestParametersError(f"The request was rejected with the following parameter error: <{data[2]}>")
@@ -40,7 +45,7 @@ class BfxRestInterface(object):
"f": serializers.FundingCurrencyTicker.parse "f": serializers.FundingCurrencyTicker.parse
}[symbol[0]](*self.__GET(f"ticker/{symbol}"), skip=["SYMBOL"]) }[symbol[0]](*self.__GET(f"ticker/{symbol}"), skip=["SYMBOL"])
def tickers_hist(self, symbols: List[str], start: Optional[int] = None, end: Optional[int] = None, limit: Optional[int] = None) -> TickerHistories: def tickers_history(self, symbols: List[str], start: Optional[int] = None, end: Optional[int] = None, limit: Optional[int] = None) -> TickerHistories:
params = { params = {
"symbols": ",".join(symbols), "symbols": ",".join(symbols),
"start": start, "end": end, "start": start, "end": end,
@@ -61,7 +66,7 @@ class BfxRestInterface(object):
for subdata in self.__GET(f"trades/{symbol}/hist", params=params) for subdata in self.__GET(f"trades/{symbol}/hist", params=params)
] ]
def book(self, symbol: str, precision: str, len: Optional[int]) -> Union[TradingPairBooks, FundingCurrencyBooks, TradingPairRawBooks, FundingCurrencyRawBooks]: def book(self, symbol: str, precision: str, len: Optional[int] = None) -> Union[TradingPairBooks, FundingCurrencyBooks, TradingPairRawBooks, FundingCurrencyRawBooks]:
return [ return [
{ {
"t": precision == "R0" and serializers.TradingPairRawBook.parse or serializers.TradingPairBook.parse, "t": precision == "R0" and serializers.TradingPairRawBook.parse or serializers.TradingPairBook.parse,
@@ -69,4 +74,49 @@ class BfxRestInterface(object):
}[symbol[0]](*subdata) }[symbol[0]](*subdata)
for subdata in self.__GET(f"book/{symbol}/{precision}", params={ "len": len }) for subdata in self.__GET(f"book/{symbol}/{precision}", params={ "len": len })
] ]
def stats(
self,
resource: str, section: Literal["hist", "last"],
sort: Optional[int] = None, start: Optional[str] = None, end: Optional[str] = None, limit: Optional[int] = None
) -> Union[Stat, Stats]:
endpoint = f"stats1/{resource}/{section}"
params = { "sort": sort, "start": start, "end": end, "limit": limit }
if section == "last":
return serializers.Stat.parse(*self.__GET(endpoint, params=params))
return [ serializers.Stat.parse(*subdata) for subdata in self.__GET(endpoint, params=params) ]
def candles(
self,
resource: str, section: Literal["hist", "last"],
sort: Optional[int] = None, start: Optional[str] = None, end: Optional[str] = None, limit: Optional[int] = None
) -> Union[Candle, Candles]:
endpoint = f"candles/{resource}/{section}"
params = { "sort": sort, "start": start, "end": end, "limit": limit }
if section == "last":
return serializers.Candle.parse(*self.__GET(endpoint, params=params))
return [ serializers.Candle.parse(*subdata) for subdata in self.__GET(endpoint, params=params) ]
def derivatives_status(self, type: str, keys: Optional[List[str]] = None) -> DerivativeStatuses:
params = None
if keys != None:
params = { "keys": ",".join(keys) }
return [ serializers.DerivativesStatus.parse(*subdata) for subdata in self.__GET(f"status/{type}", params=params) ]
def derivatives_status_history(
self,
type: str, symbol: str,
sort: Optional[int] = None, start: Optional[str] = None, end: Optional[str] = None, limit: Optional[int] = None
) -> DerivativeStatuses:
endpoint = f"status/{type}/{symbol}/hist"
params = { "sort": sort, "start": start, "end": end, "limit": limit }
return [ serializers.DerivativesStatus.parse(*subdata, skip=[ "KEY" ]) for subdata in self.__GET(endpoint, params=params) ]

View File

@@ -1,5 +1,6 @@
__all__ = [ __all__ = [
"RequestParametersError" "RequestParametersError",
"ResourceNotFound"
] ]
class BfxRestException(Exception): class BfxRestException(Exception):
@@ -14,4 +15,11 @@ class RequestParametersError(BfxRestException):
This error indicates that there are some invalid parameters sent along with an HTTP request. This error indicates that there are some invalid parameters sent along with an HTTP request.
""" """
pass
class ResourceNotFound(BfxRestException):
"""
This error indicates a failed HTTP request to a non-existent resource.
"""
pass pass

View File

@@ -120,4 +120,45 @@ FundingCurrencyRawBook = _Serializer[typings.FundingCurrencyRawBook]("FundingCur
"AMOUNT" "AMOUNT"
]) ])
Stat = _Serializer[typings.Stat]("Stat", labels=[
"MTS",
"VALUE"
])
Candle = _Serializer[typings.Candle]("Candle", labels=[
"MTS",
"OPEN",
"CLOSE",
"HIGH",
"LOW",
"VOLUME"
])
DerivativesStatus = _Serializer[typings.DerivativesStatus]("DerivativesStatus", labels=[
"KEY",
"MTS",
"_PLACEHOLDER",
"DERIV_PRICE",
"SPOT_PRICE",
"_PLACEHOLDER",
"INSURANCE_FUND_BALANCE",
"_PLACEHOLDER",
"NEXT_FUNDING_EVT_TIMESTAMP_MS",
"NEXT_FUNDING_ACCRUED",
"NEXT_FUNDING_STEP",
"_PLACEHOLDER",
"CURRENT_FUNDING",
"_PLACEHOLDER",
"_PLACEHOLDER",
"MARK_PRICE",
"_PLACEHOLDER",
"_PLACEHOLDER",
"OPEN_INTEREST",
"_PLACEHOLDER",
"_PLACEHOLDER",
"_PLACEHOLDER",
"CLAMP_MIN",
"CLAMP_MAX"
])
#endregion #endregion

View File

@@ -68,4 +68,40 @@ TickerHistories = List[TickerHistory]
(TradingPairRawBooks, FundingCurrencyRawBooks) = (List[TradingPairRawBook], List[FundingCurrencyRawBook]) (TradingPairRawBooks, FundingCurrencyRawBooks) = (List[TradingPairRawBook], List[FundingCurrencyRawBook])
Stat = TypedDict("Stat", {
"MTS": int,
"VALUE": float
})
Stats = List[Stat]
Candle = TypedDict("Candle", {
"MTS": int,
"OPEN": float,
"CLOSE": float,
"HIGH": float,
"LOW": float,
"VOLUME": float
})
Candles = List[Candle]
DerivativesStatus = TypedDict("DerivativesStatus", {
"KEY": str,
"MTS": int,
"DERIV_PRICE": float,
"SPOT_PRICE": float,
"INSURANCE_FUND_BALANCE": float,
"NEXT_FUNDING_EVT_TIMESTAMP_MS": int,
"NEXT_FUNDING_ACCRUED": float,
"NEXT_FUNDING_STEP": int,
"CURRENT_FUNDING": float,
"MARK_PRICE": float,
"OPEN_INTEREST": float,
"CLAMP_MIN": float,
"CLAMP_MAX": float
})
DerivativeStatuses = List[DerivativesStatus]
#endregion #endregion