mirror of
https://github.com/aljazceru/bitfinex-api-py.git
synced 2025-12-18 22:34:21 +01:00
Apply lots of refactoring to the websocket subpackage (fix every mypy error and warning). Add integers.py and decimal.py to bfxapi.utils package. Update requirements.txt and setup.py with new mypy dependencies.
This commit is contained in:
@@ -1,6 +1,9 @@
|
||||
__all__ = [
|
||||
"BfxBaseException",
|
||||
"LabelerSerializerException"
|
||||
|
||||
"LabelerSerializerException",
|
||||
"IntegerUnderflowError",
|
||||
"IntegerOverflowflowError"
|
||||
]
|
||||
|
||||
class BfxBaseException(Exception):
|
||||
@@ -15,4 +18,18 @@ class LabelerSerializerException(BfxBaseException):
|
||||
This exception indicates an error thrown by the _Serializer class in bfxapi/labeler.py.
|
||||
"""
|
||||
|
||||
pass
|
||||
|
||||
class IntegerUnderflowError(BfxBaseException):
|
||||
"""
|
||||
This error indicates an underflow in one of the integer types defined in bfxapi/utils/integers.py.
|
||||
"""
|
||||
|
||||
pass
|
||||
|
||||
class IntegerOverflowflowError(BfxBaseException):
|
||||
"""
|
||||
This error indicates an overflow in one of the integer types defined in bfxapi/utils/integers.py.
|
||||
"""
|
||||
|
||||
pass
|
||||
@@ -1,4 +1,4 @@
|
||||
from ..exceptions import BfxBaseException
|
||||
from .. exceptions import BfxBaseException
|
||||
|
||||
__all__ = [
|
||||
"BfxRestException",
|
||||
|
||||
9
bfxapi/utils/decimal.py
Normal file
9
bfxapi/utils/decimal.py
Normal file
@@ -0,0 +1,9 @@
|
||||
import json
|
||||
|
||||
from decimal import Decimal
|
||||
|
||||
class DecimalEncoder(json.JSONEncoder):
|
||||
def default(self, obj):
|
||||
if isinstance(obj, Decimal):
|
||||
return str(obj)
|
||||
return json.JSONEncoder.default(self, obj)
|
||||
35
bfxapi/utils/integers.py
Normal file
35
bfxapi/utils/integers.py
Normal file
@@ -0,0 +1,35 @@
|
||||
from typing import cast, TypeVar
|
||||
|
||||
from .. exceptions import IntegerUnderflowError, IntegerOverflowflowError
|
||||
|
||||
__all__ = [ "Int16", "Int32", "Int45", "Int64" ]
|
||||
|
||||
T = TypeVar("T")
|
||||
|
||||
class _Int(int):
|
||||
def __new__(cls: T, integer: int) -> T:
|
||||
assert hasattr(cls, "_BITS"), "_Int must be extended by a class that has a static member _BITS (indicating the number of bits with which to represent the integers)."
|
||||
|
||||
bits = cls._BITS - 1
|
||||
|
||||
min, max = -(2 ** bits), (2 ** bits) - 1
|
||||
|
||||
if integer < min:
|
||||
raise IntegerUnderflowError(f"Underflow. Cannot store <{integer}> in {cls._BITS} bits integer. The min and max bounds are {min} and {max}.")
|
||||
|
||||
if integer > max:
|
||||
raise IntegerOverflowflowError(f"Overflow. Cannot store <{integer}> in {cls._BITS} bits integer. The min and max bounds are {min} and {max}.")
|
||||
|
||||
return cast(T, super().__new__(int, integer))
|
||||
|
||||
class Int16(_Int):
|
||||
_BITS = 16
|
||||
|
||||
class Int32(_Int):
|
||||
_BITS = 32
|
||||
|
||||
class Int45(_Int):
|
||||
_BITS = 45
|
||||
|
||||
class Int64(_Int):
|
||||
_BITS = 64
|
||||
@@ -1,25 +1,40 @@
|
||||
import traceback, json, asyncio, hmac, hashlib, time, uuid, websockets
|
||||
|
||||
from typing import Tuple, Union, Literal, TypeVar, Callable, cast
|
||||
|
||||
from enum import Enum
|
||||
|
||||
from pyee.asyncio import AsyncIOEventEmitter
|
||||
|
||||
from .typings import Inputs, Tuple, Union
|
||||
from .typings import Inputs
|
||||
from .handlers import Channels, PublicChannelsHandler, AuthenticatedChannelsHandler
|
||||
from .exceptions import ConnectionNotOpen, TooManySubscriptions, WebsocketAuthenticationRequired, InvalidAuthenticationCredentials, EventNotSupported, OutdatedClientVersion
|
||||
|
||||
from ..utils.decimal import DecimalEncoder
|
||||
|
||||
from ..utils.logger import Formatter, CustomLogger
|
||||
|
||||
_HEARTBEAT = "hb"
|
||||
|
||||
def _require_websocket_connection(function):
|
||||
F = TypeVar("F", bound=Callable[..., Literal[None]])
|
||||
|
||||
def _require_websocket_connection(function: F) -> F:
|
||||
async def wrapper(self, *args, **kwargs):
|
||||
if self.websocket == None or self.websocket.open == False:
|
||||
raise ConnectionNotOpen("No open connection with the server.")
|
||||
|
||||
await function(self, *args, **kwargs)
|
||||
|
||||
return wrapper
|
||||
return cast(F, wrapper)
|
||||
|
||||
def _require_websocket_authentication(function: F) -> F:
|
||||
async def wrapper(self, *args, **kwargs):
|
||||
if self.authentication == False:
|
||||
raise WebsocketAuthenticationRequired("To perform this action you need to authenticate using your API_KEY and API_SECRET.")
|
||||
|
||||
await _require_websocket_connection(function)(self, *args, **kwargs)
|
||||
|
||||
return cast(F, wrapper)
|
||||
|
||||
class BfxWebsocketClient(object):
|
||||
VERSION = 2
|
||||
@@ -118,22 +133,13 @@ class BfxWebsocketClient(object):
|
||||
for bucket in self.buckets:
|
||||
await bucket._close(code=code, reason=reason)
|
||||
|
||||
def __require_websocket_authentication(function):
|
||||
async def wrapper(self, *args, **kwargs):
|
||||
if self.authentication == False:
|
||||
raise WebsocketAuthenticationRequired("To perform this action you need to authenticate using your API_KEY and API_SECRET.")
|
||||
|
||||
await _require_websocket_connection(function)(self, *args, **kwargs)
|
||||
|
||||
return wrapper
|
||||
|
||||
@__require_websocket_authentication
|
||||
@_require_websocket_authentication
|
||||
async def notify(self, info, MESSAGE_ID=None, **kwargs):
|
||||
await self.websocket.send(json.dumps([ 0, "n", MESSAGE_ID, { "type": "ucm-test", "info": info, **kwargs } ]))
|
||||
|
||||
@__require_websocket_authentication
|
||||
@_require_websocket_authentication
|
||||
async def __handle_websocket_input(self, input, data):
|
||||
await self.websocket.send(json.dumps([ 0, input, None, data]))
|
||||
await self.websocket.send(json.dumps([ 0, input, None, data], cls=DecimalEncoder))
|
||||
|
||||
def __bucket_open_signal(self, index):
|
||||
if all(bucket.websocket != None and bucket.websocket.open == True for bucket in self.buckets):
|
||||
|
||||
@@ -1,4 +1,8 @@
|
||||
from .. exceptions import BfxBaseException
|
||||
|
||||
__all__ = [
|
||||
"BfxWebsocketException",
|
||||
|
||||
"ConnectionNotOpen",
|
||||
"TooManySubscriptions",
|
||||
"WebsocketAuthenticationRequired",
|
||||
@@ -7,9 +11,9 @@ __all__ = [
|
||||
"OutdatedClientVersion"
|
||||
]
|
||||
|
||||
class BfxWebsocketException(Exception):
|
||||
class BfxWebsocketException(BfxBaseException):
|
||||
"""
|
||||
Base class for all exceptions defined in bfxapi/websocket/exceptions.py.
|
||||
Base class for all custom exceptions in bfxapi/websocket/exceptions.py.
|
||||
"""
|
||||
|
||||
pass
|
||||
@@ -35,13 +39,6 @@ class WebsocketAuthenticationRequired(BfxWebsocketException):
|
||||
|
||||
pass
|
||||
|
||||
class InvalidAuthenticationCredentials(BfxWebsocketException):
|
||||
"""
|
||||
This error indicates that the user has provided incorrect credentials (API-KEY and API-SECRET) for authentication.
|
||||
"""
|
||||
|
||||
pass
|
||||
|
||||
class EventNotSupported(BfxWebsocketException):
|
||||
"""
|
||||
This error indicates a failed attempt to subscribe to an event not supported by the BfxWebsocketClient.
|
||||
@@ -54,4 +51,11 @@ class OutdatedClientVersion(BfxWebsocketException):
|
||||
This error indicates a mismatch between the client version and the server WSS version.
|
||||
"""
|
||||
|
||||
pass
|
||||
|
||||
class InvalidAuthenticationCredentials(BfxWebsocketException):
|
||||
"""
|
||||
This error indicates that the user has provided incorrect credentials (API-KEY and API-SECRET) for authentication.
|
||||
"""
|
||||
|
||||
pass
|
||||
@@ -1,25 +1,6 @@
|
||||
from typing import Generic, TypeVar, Iterable, List, Any
|
||||
|
||||
from . import typings
|
||||
|
||||
from .exceptions import BfxWebsocketException
|
||||
|
||||
T = TypeVar("T")
|
||||
|
||||
class _Serializer(Generic[T]):
|
||||
def __init__(self, name: str, labels: List[str]):
|
||||
self.name, self.__labels = name, labels
|
||||
|
||||
def __serialize(self, *args: Any, IGNORE: List[str] = [ "_PLACEHOLDER" ]) -> Iterable[T]:
|
||||
if len(self.__labels) != len(args):
|
||||
raise BfxWebsocketException("<self.__labels> and <*args> arguments should contain the same amount of elements.")
|
||||
|
||||
for index, label in enumerate(self.__labels):
|
||||
if label not in IGNORE:
|
||||
yield label, args[index]
|
||||
|
||||
def parse(self, *values: Any) -> T:
|
||||
return dict(self.__serialize(*values))
|
||||
from .. labeler import _Serializer
|
||||
|
||||
#region Serializers definition for Websocket Public Channels
|
||||
|
||||
@@ -315,7 +296,7 @@ BalanceInfo = _Serializer[typings.BalanceInfo]("BalanceInfo", labels=[
|
||||
|
||||
#region Serializers definition for Notifications channel
|
||||
|
||||
Notification = _Serializer("Notification", labels=[
|
||||
Notification = _Serializer[typings.Notification]("Notification", labels=[
|
||||
"MTS",
|
||||
"TYPE",
|
||||
"MESSAGE_ID",
|
||||
|
||||
@@ -2,301 +2,294 @@ from decimal import Decimal
|
||||
|
||||
from datetime import datetime
|
||||
|
||||
from typing import Type, Tuple, List, Dict, TypedDict, Union, Optional, Any
|
||||
from typing import Type, NewType, Tuple, List, Dict, TypedDict, Union, Optional, Any
|
||||
|
||||
int16 = int32 = int45 = int64 = int
|
||||
from ..utils.integers import Int16, Int32, Int45, Int64
|
||||
|
||||
JSON = Union[Dict[str, "JSON"], List["JSON"], bool, int, float, str, Type[None]]
|
||||
|
||||
#region Type hinting for subscription objects
|
||||
|
||||
class Subscriptions:
|
||||
TradingPairsTicker = TypedDict("Subscriptions.TradingPairsTicker", {
|
||||
"chanId": int,
|
||||
"symbol": str,
|
||||
"pair": str
|
||||
})
|
||||
class TradingPairsTicker(TypedDict):
|
||||
chanId: int
|
||||
symbol: str
|
||||
pair: str
|
||||
|
||||
FundingCurrenciesTicker = TypedDict("Subscriptions.FundingCurrenciesTicker", {
|
||||
"chanId": int,
|
||||
"symbol": str,
|
||||
"currency": str
|
||||
})
|
||||
class FundingCurrenciesTicker(TypedDict):
|
||||
chanId: int
|
||||
symbol: str
|
||||
currency: str
|
||||
|
||||
TradingPairsTrades = TypedDict("Subscriptions.TradingPairsTrades", {
|
||||
"chanId": int,
|
||||
"symbol": str,
|
||||
"pair": str
|
||||
})
|
||||
class TradingPairsTrades(TypedDict):
|
||||
chanId: int
|
||||
symbol: str
|
||||
pair: str
|
||||
|
||||
FundingCurrenciesTrades = TypedDict("Subscriptions.FundingCurrenciesTrades", {
|
||||
"chanId": int,
|
||||
"symbol": str,
|
||||
"currency": str
|
||||
})
|
||||
class FundingCurrenciesTrades(TypedDict):
|
||||
chanId: int
|
||||
symbol: str
|
||||
currency: str
|
||||
|
||||
Book = TypedDict("Subscriptions.Book", {
|
||||
"chanId": int,
|
||||
"symbol": str,
|
||||
"prec": str,
|
||||
"freq": str,
|
||||
"len": str,
|
||||
"subId": int,
|
||||
"pair": str
|
||||
})
|
||||
class Book(TypedDict):
|
||||
chanId: int
|
||||
symbol: str
|
||||
prec: str
|
||||
freq: str
|
||||
len: str
|
||||
subId: int
|
||||
pair: str
|
||||
|
||||
Candles = TypedDict("Subscriptions.Candles", {
|
||||
"chanId": int,
|
||||
"key": str
|
||||
})
|
||||
class Candles(TypedDict):
|
||||
chanId: int
|
||||
key: str
|
||||
|
||||
DerivativesStatus = TypedDict("Subscriptions.DerivativesStatus", {
|
||||
"chanId": int,
|
||||
"key": str
|
||||
})
|
||||
class DerivativesStatus(TypedDict):
|
||||
chanId: int
|
||||
key: str
|
||||
|
||||
#endregion
|
||||
|
||||
#region Type hinting for Websocket Public Channels
|
||||
|
||||
TradingPairTicker = TypedDict("TradingPairTicker", {
|
||||
"BID": float,
|
||||
"BID_SIZE": float,
|
||||
"ASK": float,
|
||||
"ASK_SIZE": float,
|
||||
"DAILY_CHANGE": float,
|
||||
"DAILY_CHANGE_RELATIVE": float,
|
||||
"LAST_PRICE": float,
|
||||
"VOLUME": float,
|
||||
"HIGH": float,
|
||||
"LOW": float
|
||||
})
|
||||
class TradingPairTicker(TypedDict):
|
||||
BID: float
|
||||
BID_SIZE: float
|
||||
ASK: float
|
||||
ASK_SIZE: float
|
||||
DAILY_CHANGE: float
|
||||
DAILY_CHANGE_RELATIVE: float
|
||||
LAST_PRICE: float
|
||||
VOLUME: float
|
||||
HIGH: float
|
||||
LOW: float
|
||||
|
||||
FundingCurrencyTicker = TypedDict("FundingCurrencyTicker", {
|
||||
"FRR": float,
|
||||
"BID": float,
|
||||
"BID_PERIOD": int,
|
||||
"BID_SIZE": float,
|
||||
"ASK": float,
|
||||
"ASK_PERIOD": int,
|
||||
"ASK_SIZE": float,
|
||||
"DAILY_CHANGE": float,
|
||||
"DAILY_CHANGE_RELATIVE": float,
|
||||
"LAST_PRICE": float,
|
||||
"VOLUME": float,
|
||||
"HIGH": float,
|
||||
"LOW": float,
|
||||
"FRR_AMOUNT_AVAILABLE": float
|
||||
})
|
||||
class FundingCurrencyTicker(TypedDict):
|
||||
FRR: float
|
||||
BID: float
|
||||
BID_PERIOD: int
|
||||
BID_SIZE: float
|
||||
ASK: float
|
||||
ASK_PERIOD: int
|
||||
ASK_SIZE: float
|
||||
DAILY_CHANGE: float
|
||||
DAILY_CHANGE_RELATIVE: float
|
||||
LAST_PRICE: float
|
||||
VOLUME: float
|
||||
HIGH: float
|
||||
LOW: float
|
||||
FRR_AMOUNT_AVAILABLE: float
|
||||
|
||||
(TradingPairTrade, FundingCurrencyTrade) = (
|
||||
TypedDict("TradingPairTrade", { "ID": int, "MTS": int, "AMOUNT": float, "PRICE": float }),
|
||||
TypedDict("FundingCurrencyTrade", { "ID": int, "MTS": int, "AMOUNT": float, "RATE": float, "PERIOD": int })
|
||||
)
|
||||
class TradingPairTrade(TypedDict):
|
||||
ID: int
|
||||
MTS: int
|
||||
AMOUNT: float
|
||||
PRICE: float
|
||||
|
||||
(TradingPairTrades, FundingCurrencyTrades) = (List[TradingPairTrade], List[FundingCurrencyTrade])
|
||||
class FundingCurrencyTrade(TypedDict):
|
||||
ID: int
|
||||
MTS: int
|
||||
AMOUNT: float
|
||||
RATE: float
|
||||
PERIOD: int
|
||||
|
||||
(TradingPairBook, FundingCurrencyBook) = (
|
||||
TypedDict("TradingPairBook", { "PRICE": float, "COUNT": int, "AMOUNT": float }),
|
||||
TypedDict("FundingCurrencyBook", { "RATE": float, "PERIOD": int, "COUNT": int, "AMOUNT": float })
|
||||
)
|
||||
class TradingPairBook(TypedDict):
|
||||
PRICE: float
|
||||
COUNT: int
|
||||
AMOUNT: float
|
||||
|
||||
class FundingCurrencyBook(TypedDict):
|
||||
RATE: float
|
||||
PERIOD: int
|
||||
COUNT: int
|
||||
AMOUNT: float
|
||||
|
||||
class TradingPairRawBook(TypedDict):
|
||||
ORDER_ID: int
|
||||
PRICE: float
|
||||
AMOUNT: float
|
||||
|
||||
class FundingCurrencyRawBook(TypedDict):
|
||||
OFFER_ID: int
|
||||
PERIOD: int
|
||||
RATE: float
|
||||
AMOUNT: float
|
||||
|
||||
(TradingPairBooks, FundingCurrencyBooks) = (List[TradingPairBook], List[FundingCurrencyBook])
|
||||
class Candle(TypedDict):
|
||||
MTS: int
|
||||
OPEN: float
|
||||
CLOSE: float
|
||||
HIGH: float
|
||||
LOW: float
|
||||
VOLUME: float
|
||||
|
||||
(TradingPairRawBook, FundingCurrencyRawBook) = (
|
||||
TypedDict("TradingPairRawBook", { "ORDER_ID": int, "PRICE": float, "AMOUNT": float }),
|
||||
TypedDict("FundingCurrencyRawBook", { "OFFER_ID": int, "PERIOD": int, "RATE": float, "AMOUNT": float }),
|
||||
)
|
||||
|
||||
(TradingPairRawBooks, FundingCurrencyRawBooks) = (List[TradingPairRawBook], List[FundingCurrencyRawBook])
|
||||
|
||||
Candle = TypedDict("Candle", {
|
||||
"MTS": int,
|
||||
"OPEN": float,
|
||||
"CLOSE": float,
|
||||
"HIGH": float,
|
||||
"LOW": float,
|
||||
"VOLUME": float
|
||||
})
|
||||
|
||||
Candles = List[Candle]
|
||||
|
||||
DerivativesStatus = TypedDict("DerivativesStatus", {
|
||||
"TIME_MS": 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
|
||||
})
|
||||
class DerivativesStatus(TypedDict):
|
||||
TIME_MS: 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
|
||||
|
||||
#endregion
|
||||
|
||||
#region Type hinting for Websocket Authenticated Channels
|
||||
|
||||
Order = TypedDict("Order", {
|
||||
"ID": int,
|
||||
"GID": int,
|
||||
"CID": int,
|
||||
"SYMBOL": str,
|
||||
"MTS_CREATE": int,
|
||||
"MTS_UPDATE": int,
|
||||
"AMOUNT": float,
|
||||
"AMOUNT_ORIG": float,
|
||||
"ORDER_TYPE": str,
|
||||
"TYPE_PREV": str,
|
||||
"MTS_TIF": int,
|
||||
"FLAGS": int,
|
||||
"ORDER_STATUS": str,
|
||||
"PRICE": float,
|
||||
"PRICE_AVG": float,
|
||||
"PRICE_TRAILING": float,
|
||||
"PRICE_AUX_LIMIT": float,
|
||||
"NOTIFY": int,
|
||||
"HIDDEN": int,
|
||||
"PLACED_ID": int,
|
||||
"ROUTING": str,
|
||||
"META": JSON
|
||||
})
|
||||
class Order(TypedDict):
|
||||
ID: int
|
||||
GID: int
|
||||
CID: int
|
||||
SYMBOL: str
|
||||
MTS_CREATE: int
|
||||
MTS_UPDATE: int
|
||||
AMOUNT: float
|
||||
AMOUNT_ORIG: float
|
||||
ORDER_TYPE: str
|
||||
TYPE_PREV: str
|
||||
MTS_TIF: int
|
||||
FLAGS: int
|
||||
ORDER_STATUS: str
|
||||
PRICE: float
|
||||
PRICE_AVG: float
|
||||
PRICE_TRAILING: float
|
||||
PRICE_AUX_LIMIT: float
|
||||
NOTIFY: int
|
||||
HIDDEN: int
|
||||
PLACED_ID: int
|
||||
ROUTING: str
|
||||
META: JSON
|
||||
|
||||
Orders = List[Order]
|
||||
class Position(TypedDict):
|
||||
SYMBOL: str
|
||||
STATUS: str
|
||||
AMOUNT: float
|
||||
BASE_PRICE: float
|
||||
MARGIN_FUNDING: float
|
||||
MARGIN_FUNDING_TYPE: int
|
||||
PL: float
|
||||
PL_PERC: float
|
||||
PRICE_LIQ: float
|
||||
LEVERAGE: float
|
||||
POSITION_ID: int
|
||||
MTS_CREATE: int
|
||||
MTS_UPDATE: int
|
||||
TYPE: int
|
||||
COLLATERAL: float
|
||||
COLLATERAL_MIN: float
|
||||
META: JSON
|
||||
|
||||
Position = TypedDict("Position", {
|
||||
"SYMBOL": str,
|
||||
"STATUS": str,
|
||||
"AMOUNT": float,
|
||||
"BASE_PRICE": float,
|
||||
"MARGIN_FUNDING": float,
|
||||
"MARGIN_FUNDING_TYPE": int,
|
||||
"PL": float,
|
||||
"PL_PERC": float,
|
||||
"PRICE_LIQ": float,
|
||||
"LEVERAGE": float,
|
||||
"POSITION_ID": int,
|
||||
"MTS_CREATE": int,
|
||||
"MTS_UPDATE": int,
|
||||
"TYPE": int,
|
||||
"COLLATERAL": float,
|
||||
"COLLATERAL_MIN": float,
|
||||
"META": JSON,
|
||||
})
|
||||
class TradeExecuted(TypedDict):
|
||||
ID: int
|
||||
SYMBOL: str
|
||||
MTS_CREATE: int
|
||||
ORDER_ID: int
|
||||
EXEC_AMOUNT: float
|
||||
EXEC_PRICE: float
|
||||
ORDER_TYPE: str
|
||||
ORDER_PRICE: float
|
||||
MAKER:int
|
||||
CID: int
|
||||
|
||||
Positions = List[Position]
|
||||
class TradeExecutionUpdate(TypedDict):
|
||||
ID: int
|
||||
SYMBOL: str
|
||||
MTS_CREATE: int
|
||||
ORDER_ID: int
|
||||
EXEC_AMOUNT: float
|
||||
EXEC_PRICE: float
|
||||
ORDER_TYPE: str
|
||||
ORDER_PRICE: float
|
||||
MAKER:int
|
||||
FEE: float
|
||||
FEE_CURRENCY: str
|
||||
CID: int
|
||||
|
||||
TradeExecuted = TypedDict("TradeExecuted", {
|
||||
"ID": int,
|
||||
"SYMBOL": str,
|
||||
"MTS_CREATE": int,
|
||||
"ORDER_ID": int,
|
||||
"EXEC_AMOUNT": float,
|
||||
"EXEC_PRICE": float,
|
||||
"ORDER_TYPE": str,
|
||||
"ORDER_PRICE": float,
|
||||
"MAKER":int,
|
||||
"CID": int
|
||||
})
|
||||
class FundingOffer(TypedDict):
|
||||
ID: int
|
||||
SYMBOL: str
|
||||
MTS_CREATED: int
|
||||
MTS_UPDATED: int
|
||||
AMOUNT: float
|
||||
AMOUNT_ORIG: float
|
||||
OFFER_TYPE: str
|
||||
FLAGS: int
|
||||
STATUS: str
|
||||
RATE: float
|
||||
PERIOD: int
|
||||
NOTIFY: int
|
||||
HIDDEN: int
|
||||
RENEW: int
|
||||
|
||||
TradeExecutionUpdate = TypedDict("TradeExecutionUpdate", {
|
||||
"ID": int,
|
||||
"SYMBOL": str,
|
||||
"MTS_CREATE": int,
|
||||
"ORDER_ID": int,
|
||||
"EXEC_AMOUNT": float,
|
||||
"EXEC_PRICE": float,
|
||||
"ORDER_TYPE": str,
|
||||
"ORDER_PRICE": float,
|
||||
"MAKER":int,
|
||||
"FEE": float,
|
||||
"FEE_CURRENCY": str,
|
||||
"CID": int
|
||||
})
|
||||
class FundingCredit(TypedDict):
|
||||
ID: int
|
||||
SYMBOL: str
|
||||
SIDE: int
|
||||
MTS_CREATE: int
|
||||
MTS_UPDATE: int
|
||||
AMOUNT: float
|
||||
FLAGS: int
|
||||
STATUS: str
|
||||
RATE: float
|
||||
PERIOD: int
|
||||
MTS_OPENING: int
|
||||
MTS_LAST_PAYOUT: int
|
||||
NOTIFY: int
|
||||
HIDDEN: int
|
||||
RENEW: int
|
||||
RATE_REAL: float
|
||||
NO_CLOSE: int
|
||||
POSITION_PAIR: str
|
||||
|
||||
FundingOffer = TypedDict("FundingOffer", {
|
||||
"ID": int,
|
||||
"SYMBOL": str,
|
||||
"MTS_CREATED": int,
|
||||
"MTS_UPDATED": int,
|
||||
"AMOUNT": float,
|
||||
"AMOUNT_ORIG": float,
|
||||
"OFFER_TYPE": str,
|
||||
"FLAGS": int,
|
||||
"STATUS": str,
|
||||
"RATE": float,
|
||||
"PERIOD": int,
|
||||
"NOTIFY": int,
|
||||
"HIDDEN": int,
|
||||
"RENEW": int,
|
||||
})
|
||||
class FundingLoan(TypedDict):
|
||||
ID: int
|
||||
SYMBOL: str
|
||||
SIDE: int
|
||||
MTS_CREATE: int
|
||||
MTS_UPDATE: int
|
||||
AMOUNT: float
|
||||
FLAGS: int
|
||||
STATUS: str
|
||||
RATE: float
|
||||
PERIOD: int
|
||||
MTS_OPENING: int
|
||||
MTS_LAST_PAYOUT: int
|
||||
NOTIFY: int
|
||||
HIDDEN: int
|
||||
RENEW: int
|
||||
RATE_REAL: float
|
||||
NO_CLOSE: int
|
||||
|
||||
FundingOffers = List[FundingOffer]
|
||||
class Wallet(TypedDict):
|
||||
WALLET_TYPE: str
|
||||
CURRENCY: str
|
||||
BALANCE: float
|
||||
UNSETTLED_INTEREST: float
|
||||
BALANCE_AVAILABLE: float
|
||||
DESCRIPTION: str
|
||||
META: JSON
|
||||
|
||||
FundingCredit = TypedDict("FundingCredit", {
|
||||
"ID": int,
|
||||
"SYMBOL": str,
|
||||
"SIDE": int,
|
||||
"MTS_CREATE": int,
|
||||
"MTS_UPDATE": int,
|
||||
"AMOUNT": float,
|
||||
"FLAGS": int,
|
||||
"STATUS": str,
|
||||
"RATE": float,
|
||||
"PERIOD": int,
|
||||
"MTS_OPENING": int,
|
||||
"MTS_LAST_PAYOUT": int,
|
||||
"NOTIFY": int,
|
||||
"HIDDEN": int,
|
||||
"RENEW": int,
|
||||
"RATE_REAL": float,
|
||||
"NO_CLOSE": int,
|
||||
"POSITION_PAIR": str
|
||||
})
|
||||
class BalanceInfo(TypedDict):
|
||||
AUM: float
|
||||
AUM_NET: float
|
||||
|
||||
FundingCredits = List[FundingCredit]
|
||||
#endregion
|
||||
|
||||
FundingLoan = TypedDict("FundingLoan", {
|
||||
"ID": int,
|
||||
"SYMBOL": str,
|
||||
"SIDE": int,
|
||||
"MTS_CREATE": int,
|
||||
"MTS_UPDATE": int,
|
||||
"AMOUNT": float,
|
||||
"FLAGS": int,
|
||||
"STATUS": str,
|
||||
"RATE": float,
|
||||
"PERIOD": int,
|
||||
"MTS_OPENING": int,
|
||||
"MTS_LAST_PAYOUT": int,
|
||||
"NOTIFY": int,
|
||||
"HIDDEN": int,
|
||||
"RENEW": int,
|
||||
"RATE_REAL": float,
|
||||
"NO_CLOSE": int
|
||||
})
|
||||
#region Serializers definition for Notifications channel
|
||||
|
||||
FundingLoans = List[FundingLoan]
|
||||
|
||||
Wallet = TypedDict("Wallet", {
|
||||
"WALLET_TYPE": str,
|
||||
"CURRENCY": str,
|
||||
"BALANCE": float,
|
||||
"UNSETTLED_INTEREST": float,
|
||||
"BALANCE_AVAILABLE": float,
|
||||
"DESCRIPTION": str,
|
||||
"META": JSON
|
||||
})
|
||||
|
||||
Wallets = List[Wallet]
|
||||
|
||||
BalanceInfo = TypedDict("BalanceInfo", {
|
||||
"AUM": float,
|
||||
"AUM_NET": float
|
||||
})
|
||||
class Notification(TypedDict):
|
||||
MTS: int
|
||||
TYPE: str
|
||||
MESSAGE_ID: int
|
||||
NOTIFY_INFO: JSON
|
||||
CODE: int
|
||||
STATUS: str
|
||||
TEXT: str
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -304,55 +297,50 @@ BalanceInfo = TypedDict("BalanceInfo", {
|
||||
|
||||
class Inputs:
|
||||
class Order:
|
||||
New = TypedDict("Inputs.Order.New", {
|
||||
"gid": Optional[int32],
|
||||
"cid": int45,
|
||||
"type": str,
|
||||
"symbol": str,
|
||||
"amount": Union[Decimal, str],
|
||||
"price": Union[Decimal, str],
|
||||
"lev": int,
|
||||
"price_trailing": Union[Decimal, str],
|
||||
"price_aux_limit": Union[Decimal, str],
|
||||
"price_oco_stop": Union[Decimal, str],
|
||||
"flags": int16,
|
||||
"tif": Union[datetime, str],
|
||||
"meta": JSON
|
||||
})
|
||||
class New(TypedDict, total=False):
|
||||
gid: Union[Int32, int]
|
||||
cid: Union[Int45, int]
|
||||
type: str
|
||||
symbol: str
|
||||
amount: Union[Decimal, str]
|
||||
price: Union[Decimal, str]
|
||||
lev: Union[Int32, int]
|
||||
price_trailing: Union[Decimal, str]
|
||||
price_aux_limit: Union[Decimal, str]
|
||||
price_oco_stop: Union[Decimal, str]
|
||||
flags: Union[Int16, int]
|
||||
tif: Union[datetime, str]
|
||||
meta: JSON
|
||||
|
||||
Update = TypedDict("Inputs.Order.Update", {
|
||||
"id": int64,
|
||||
"cid": int45,
|
||||
"cid_date": str,
|
||||
"gid": int32,
|
||||
"price": Union[Decimal, str],
|
||||
"amount": Union[Decimal, str],
|
||||
"lev": int,
|
||||
"delta": Union[Decimal, str],
|
||||
"price_aux_limit": Union[Decimal, str],
|
||||
"price_trailing": Union[Decimal, str],
|
||||
"flags": int16,
|
||||
"tif": Union[datetime, str]
|
||||
})
|
||||
class Update(TypedDict, total=False):
|
||||
id: Union[Int64, int]
|
||||
cid: Union[Int45, int]
|
||||
cid_date: str
|
||||
gid: Union[Int32, int]
|
||||
price: Union[Decimal, str]
|
||||
amount: Union[Decimal, str]
|
||||
lev: Union[Int32, int]
|
||||
delta: Union[Decimal, str]
|
||||
price_aux_limit: Union[Decimal, str]
|
||||
price_trailing: Union[Decimal, str]
|
||||
flags: Union[Int16, int]
|
||||
tif: Union[datetime, str]
|
||||
|
||||
Cancel = TypedDict("Inputs.Order.Cancel", {
|
||||
"id": int64,
|
||||
"cid": int45,
|
||||
"cid_date": str
|
||||
})
|
||||
class Cancel(TypedDict, total=False):
|
||||
id: Union[Int64, int]
|
||||
cid: Union[Int45, int]
|
||||
cid_date: Union[datetime, str]
|
||||
|
||||
class Offer:
|
||||
New = TypedDict("Inputs.Offer.New", {
|
||||
"type": str,
|
||||
"symbol": str,
|
||||
"amount": Union[Decimal, str],
|
||||
"rate": Union[Decimal, str],
|
||||
"period": int,
|
||||
"flags": int16
|
||||
})
|
||||
class New(TypedDict, total=False):
|
||||
type: str
|
||||
symbol: str
|
||||
amount: Union[Decimal, str]
|
||||
rate: Union[Decimal, str]
|
||||
period: Union[Int32, int]
|
||||
flags: Union[Int16, int]
|
||||
|
||||
Cancel = TypedDict("Inputs.Offer.Cancel", {
|
||||
"id": int
|
||||
})
|
||||
class Cancel(TypedDict, total=False):
|
||||
id: Union[Int32, int]
|
||||
|
||||
#endregion
|
||||
BIN
requirements.txt
BIN
requirements.txt
Binary file not shown.
7
setup.py
7
setup.py
@@ -11,11 +11,16 @@ setup(
|
||||
description="Official Bitfinex Python API",
|
||||
keywords="bitfinex,api,trading",
|
||||
install_requires=[
|
||||
"certifi~=2022.9.24",
|
||||
"certifi~=2022.12.7",
|
||||
"charset-normalizer~=2.1.1",
|
||||
"idna~=3.4",
|
||||
"mypy~=0.991",
|
||||
"mypy-extensions~=0.4.3",
|
||||
"pyee~=9.0.4",
|
||||
"requests~=2.28.1",
|
||||
"tomli~=2.0.1",
|
||||
"types-requests~=2.28.11.5",
|
||||
"types-urllib3~=1.26.25.4",
|
||||
"typing_extensions~=4.4.0",
|
||||
"urllib3~=1.26.13",
|
||||
"websockets~=10.4",
|
||||
|
||||
Reference in New Issue
Block a user