core/bfxbot/bfxwrapper.py

112 lines
3.4 KiB
Python

from typing import List
from bfxapi.rest.bfx_rest import BfxRest
from retrying_async import retry
from bfxbot.currency import Symbol, Balance, BalanceKind, OrderType, Direction
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=None, params=""):
if data is None:
data = {}
return await super().post(endpoint, data, params)
################################
# NEW METHODS
################################
# Calculate the average execution price for Trading or rate for Margin funding.
async def calculate_execution_price(self, pair: str, amount: float):
api_path = "/calc/trade/avg"
res = await self.post(api_path, {
'symbol': pair,
'amount': amount
})
return res[0]
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, quote: str = "USD") -> List[Balance]:
balances = []
wallets = await self.get_wallets()
for w in wallets:
kind = BalanceKind.from_str(w.type)
if not kind:
continue
execution_price = await self.calculate_execution_price(f"t{w.currency}{quote}", w.balance)
quote_equivalent = execution_price * w.balance
balances.append(Balance(w.currency, w.balance, kind, quote, quote_equivalent))
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})