131 lines
3.4 KiB
Python
131 lines
3.4 KiB
Python
from enum import Enum
|
|
from typing import List
|
|
|
|
from bfxapi.rest.bfx_rest import BfxRest
|
|
from retrying_async import retry
|
|
|
|
from bfxbot.currency import Symbol
|
|
|
|
|
|
class BalanceKind(Enum):
|
|
EXCHANGE = "exchange",
|
|
MARGIN = "margin"
|
|
|
|
@staticmethod
|
|
def from_str(string: str):
|
|
string = string.lower()
|
|
|
|
if "margin" in string:
|
|
return BalanceKind.MARGIN
|
|
if "exchange" in string:
|
|
return BalanceKind.EXCHANGE
|
|
|
|
return None
|
|
|
|
|
|
class Balance:
|
|
def __init__(self, currency: str, amount: int, kind: BalanceKind):
|
|
self.currency: str = currency
|
|
self.amount: int = amount
|
|
self.kind: BalanceKind = kind
|
|
|
|
|
|
class Direction(Enum):
|
|
UP = 1,
|
|
DOWN = -1
|
|
|
|
|
|
class OrderType(Enum):
|
|
EXCHANGE = "EXCHANGE",
|
|
MARGIN = "MARGIN"
|
|
|
|
|
|
class BfxWrapper(BfxRest):
|
|
def __init__(self, api_key: str, api_secret: str):
|
|
super().__init__(API_KEY=api_key, API_SECRET=api_secret)
|
|
|
|
#######################################
|
|
# OVERRIDDEN METHODS TO IMPLEMENT RETRY
|
|
#######################################
|
|
|
|
@retry()
|
|
async def get_public_ticker(self, symbol):
|
|
if isinstance(symbol, Symbol):
|
|
symbol = str(symbol)
|
|
|
|
return await super().get_public_ticker(symbol)
|
|
|
|
@retry()
|
|
async def get_active_position(self):
|
|
return await super().get_active_position()
|
|
|
|
@retry()
|
|
async def get_active_orders(self, symbol):
|
|
if isinstance(symbol, Symbol):
|
|
symbol = str(symbol)
|
|
|
|
return await super().get_active_orders(symbol)
|
|
|
|
@retry()
|
|
async def get_trades(self, symbol, start, end):
|
|
if isinstance(symbol, Symbol):
|
|
symbol = str(symbol)
|
|
|
|
return await super().get_trades(symbol, start, end)
|
|
|
|
@retry()
|
|
async def post(self, endpoint: str, data: dict = {}, params=""):
|
|
return await super().post(endpoint, data, params)
|
|
|
|
################################
|
|
# NEW METHODS
|
|
################################
|
|
|
|
async def get_current_prices(self, symbol) -> (float, float, float):
|
|
if isinstance(symbol, Symbol):
|
|
symbol = str(symbol)
|
|
|
|
tickers = await self.get_public_ticker(symbol)
|
|
|
|
bid_price = tickers[0]
|
|
ask_price = tickers[2]
|
|
ticker_price = tickers[6]
|
|
|
|
return bid_price, ask_price, ticker_price
|
|
|
|
async def get_usd_balance(self):
|
|
balance = 0.0
|
|
|
|
wallets = await self.get_wallets()
|
|
|
|
for w in wallets:
|
|
if w.currency == "USD":
|
|
balance += w.balance
|
|
else:
|
|
current_price = await self.get_current_prices(f"t{w.currency}USD")
|
|
balance += current_price * w.balance
|
|
|
|
return balance
|
|
|
|
async def get_balances(self) -> List[Balance]:
|
|
balances = []
|
|
wallets = await self.get_wallets()
|
|
|
|
for w in wallets:
|
|
kind = BalanceKind.from_str(w.type)
|
|
|
|
if not kind:
|
|
continue
|
|
|
|
balances.append(Balance(w.currency, w.balance, kind))
|
|
|
|
return balances
|
|
|
|
async def maximum_order_amount(self, symbol: Symbol, direction: Direction,
|
|
order_type: OrderType = OrderType.EXCHANGE,
|
|
rate: int = 1):
|
|
api_path = "auth/calc/order/avail"
|
|
|
|
return await self.post(api_path,
|
|
{'symbol': str(symbol), 'type': order_type.value, "dir": direction.value, "rate": rate})
|