Implement get_balance and telegram balance formatting

This commit is contained in:
enenn 2018-02-04 11:30:54 +01:00
parent b6c173e3f4
commit 5c7d0ff1df
5 changed files with 63 additions and 58 deletions

View File

@ -135,11 +135,18 @@ def get_balance(currency: str) -> float:
return _API.fetch_balance()[currency]['free'] return _API.fetch_balance()[currency]['free']
def get_balances(): def get_balances() -> dict:
if _CONF['dry_run']: if _CONF['dry_run']:
return [] return {}
return _API.fetch_balance() balances = _API.fetch_balance()
# Remove additional info from ccxt results
balances.pop("info", None)
balances.pop("free", None)
balances.pop("total", None)
balances.pop("used", None)
return balances
def get_ticker(pair: str, refresh: Optional[bool] = True) -> dict: def get_ticker(pair: str, refresh: Optional[bool] = True) -> dict:

View File

@ -94,6 +94,7 @@ def authorized_only(command_handler: Callable[[Bot, Update], None]) -> Callable[
:param command_handler: Telegram CommandHandler :param command_handler: Telegram CommandHandler
:return: decorated function :return: decorated function
""" """
def wrapper(*args, **kwargs): def wrapper(*args, **kwargs):
update = kwargs.get('update') or args[1] update = kwargs.get('update') or args[1]
@ -108,6 +109,7 @@ def authorized_only(command_handler: Callable[[Bot, Update], None]) -> Callable[
return command_handler(*args, **kwargs) return command_handler(*args, **kwargs)
except BaseException: except BaseException:
logger.exception('Exception occurred within Telegram module') logger.exception('Exception occurred within Telegram module')
return wrapper return wrapper
@ -238,9 +240,9 @@ def _daily(bot: Bot, update: Update) -> None:
profitday = today - timedelta(days=day) profitday = today - timedelta(days=day)
trades = Trade.query \ trades = Trade.query \
.filter(Trade.is_open.is_(False)) \ .filter(Trade.is_open.is_(False)) \
.filter(Trade.close_date >= profitday)\ .filter(Trade.close_date >= profitday) \
.filter(Trade.close_date < (profitday + timedelta(days=1)))\ .filter(Trade.close_date < (profitday + timedelta(days=1))) \
.order_by(Trade.close_date)\ .order_by(Trade.close_date) \
.all() .all()
curdayprofit = sum(trade.calc_profit() for trade in trades) curdayprofit = sum(trade.calc_profit() for trade in trades)
profit_days[profitday] = { profit_days[profitday] = {
@ -385,42 +387,42 @@ def _balance(bot: Bot, update: Update) -> None:
Returns current account balance per crypto Returns current account balance per crypto
""" """
output = '' output = ''
balances = [ balances = {
c for c in exchange.get_balances() k: c for k, c in exchange.get_balances().items()
if c['Balance'] or c['Available'] or c['Pending'] if c['total'] or c['free'] or c['used']
] }
if not balances: if not balances:
send_msg('`All balances are zero.`') send_msg('`All balances are zero.`')
return return
total = 0.0 total = 0.0
for currency in balances: for coin, balance in balances.items():
coin = currency['Currency']
if coin == 'BTC': if coin == 'BTC':
currency["Rate"] = 1.0 balance["rate"] = 1.0
else: else:
if coin == 'USDT': if coin == 'USDT':
currency["Rate"] = 1.0 / exchange.get_ticker('BTC/USDT', False)['bid'] balance["rate"] = 1.0 / exchange.get_ticker('BTC/USDT', False)['bid']
else: else:
currency["Rate"] = exchange.get_ticker(coin + '/BTC', False)['bid'] balance["rate"] = exchange.get_ticker(coin + '/BTC', False)['bid']
currency['BTC'] = currency["Rate"] * currency["Balance"] balance['BTCequiv'] = balance["rate"] * balance["total"]
total = total + currency['BTC'] balance['coin'] = coin
output += """*Currency*: {Currency} total = total + balance['BTCequiv']
*Available*: {Available} output += """*Currency*: {coin}
*Balance*: {Balance} *Available*: {free}
*Pending*: {Pending} *Balance*: {total}
*Est. BTC*: {BTC: .8f} *Pending*: {used}
*Est. BTC*: {BTCequiv: .8f}
""".format(**currency)
""".format(**balance)
symbol = _CONF['fiat_display_currency'] symbol = _CONF['fiat_display_currency']
value = _FIAT_CONVERT.convert_amount( value = _FIAT_CONVERT.convert_amount(
total, 'BTC', symbol total, 'BTC', symbol
) )
output += """*Estimated Value*: output += """*Estimated Value*:
*BTC*: {0: .8f} *BTC*: {0: .8f}
*{1}*: {2: .2f} *{1}*: {2: .2f}
""".format(total, symbol, value) """.format(total, symbol, value)
send_msg(output) send_msg(output)

View File

@ -147,7 +147,7 @@ def test_get_balances_dry_run(default_conf, mocker):
default_conf['dry_run'] = True default_conf['dry_run'] = True
mocker.patch.dict('freqtrade.exchange._CONF', default_conf) mocker.patch.dict('freqtrade.exchange._CONF', default_conf)
assert get_balances() == [] assert get_balances() == {}
def test_get_balances_prod(default_conf, mocker): def test_get_balances_prod(default_conf, mocker):

View File

@ -639,35 +639,31 @@ def test_stop_handle_already_stopped(default_conf, update, mocker):
def test_balance_handle(default_conf, update, mocker): def test_balance_handle(default_conf, update, mocker):
mock_balance = {
mock_balance = [{ 'BTC': {
'Currency': 'BTC', 'total': 12.0,
'Balance': 10.0, 'free': 12.0,
'Available': 12.0, 'used': 0.0,
'Pending': 0.0, },
'CryptoAddress': 'XXXX', 'ETH': {
}, { 'total': 0.0,
'Currency': 'ETH', 'free': 0.0,
'Balance': 0.0, 'used': 0.0,
'Available': 0.0, },
'Pending': 0.0, 'USDT': {
'CryptoAddress': 'XXXX', 'total': 10000.0,
}, { 'free': 0.0,
'Currency': 'USDT', 'used': 0.0,
'Balance': 10000.0, },
'Available': 0.0, 'LTC': {
'Pending': 0.0, 'total': 10.0,
'CryptoAddress': 'XXXX', 'free': 10.0,
}, { 'used': 0.0,
'Currency': 'LTC', }
'Balance': 10.0, }
'Available': 10.0,
'Pending': 0.0,
'CryptoAddress': 'XXXX',
}]
def mock_ticker(symbol, refresh): def mock_ticker(symbol, refresh):
if symbol == 'USDT_BTC': if symbol == 'BTC/USDT':
return { return {
'bid': 10000.00, 'bid': 10000.00,
'ask': 10000.00, 'ask': 10000.00,
@ -701,7 +697,7 @@ def test_balance_handle(default_conf, update, mocker):
assert '*Currency*: USDT' in result assert '*Currency*: USDT' in result
assert 'Balance' in result assert 'Balance' in result
assert 'Est. BTC' in result assert 'Est. BTC' in result
assert '*BTC*: 12.00000000' in result assert '*BTC*: 14.00000000' in result
def test_zero_balance_handle(default_conf, update, mocker): def test_zero_balance_handle(default_conf, update, mocker):
@ -712,7 +708,7 @@ def test_zero_balance_handle(default_conf, update, mocker):
init=MagicMock(), init=MagicMock(),
send_msg=msg_mock) send_msg=msg_mock)
mocker.patch.multiple('freqtrade.main.exchange', mocker.patch.multiple('freqtrade.main.exchange',
get_balances=MagicMock(return_value=[])) get_balances=MagicMock(return_value={}))
_balance(bot=MagicMock(), update=update) _balance(bot=MagicMock(), update=update)
result = msg_mock.call_args_list[0][0][0] result = msg_mock.call_args_list[0][0][0]
assert msg_mock.call_count == 1 assert msg_mock.call_count == 1

View File

@ -161,7 +161,7 @@ def test_load_config(default_conf, mocker):
def test_load_config_invalid_pair(default_conf, mocker): def test_load_config_invalid_pair(default_conf, mocker):
conf = deepcopy(default_conf) conf = deepcopy(default_conf)
conf['exchange']['pair_whitelist'].append('ETH/BTC') conf['exchange']['pair_whitelist'].append('ETH_BTC') # Should have format ETH/BTC
mocker.patch( mocker.patch(
'freqtrade.misc.open', 'freqtrade.misc.open',
mocker.mock_open( mocker.mock_open(