Merge pull request #1276 from freqtrade/fix/1272

solve /balance crashes
This commit is contained in:
Matthias 2018-11-02 16:05:42 +01:00 committed by GitHub
commit 9cadb188d7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 67 additions and 7 deletions

View File

@ -375,6 +375,8 @@ class Exchange(object):
def get_ticker(self, pair: str, refresh: Optional[bool] = True) -> dict:
if refresh or pair not in self._cached_ticker.keys():
try:
if pair not in self._api.markets:
raise DependencyException(f"Pair {pair} not available")
data = self._api.fetch_ticker(pair)
try:
self._cached_ticker[pair] = {

View File

@ -10,10 +10,10 @@ from typing import Dict, Any, List, Optional
import arrow
import sqlalchemy as sql
from numpy import mean, nan_to_num
from numpy import mean, nan_to_num, NAN
from pandas import DataFrame
from freqtrade import TemporaryError
from freqtrade import TemporaryError, DependencyException
from freqtrade.fiat_convert import CryptoToFiatConverter
from freqtrade.misc import shorten_date
from freqtrade.persistence import Trade
@ -93,7 +93,10 @@ class RPC(object):
if trade.open_order_id:
order = self._freqtrade.exchange.get_order(trade.open_order_id, trade.pair)
# calculate profit and send message to user
current_rate = self._freqtrade.exchange.get_ticker(trade.pair, False)['bid']
try:
current_rate = self._freqtrade.exchange.get_ticker(trade.pair, False)['bid']
except DependencyException:
current_rate = NAN
current_profit = trade.calc_profit_percent(current_rate)
fmt_close_profit = (f'{round(trade.close_profit * 100, 2):.2f}%'
if trade.close_profit else None)
@ -122,7 +125,10 @@ class RPC(object):
trades_list = []
for trade in trades:
# calculate profit and send message to user
current_rate = self._freqtrade.exchange.get_ticker(trade.pair, False)['bid']
try:
current_rate = self._freqtrade.exchange.get_ticker(trade.pair, False)['bid']
except DependencyException:
current_rate = NAN
trade_perc = (100 * trade.calc_profit_percent(current_rate))
trades_list.append([
trade.id,
@ -207,7 +213,10 @@ class RPC(object):
profit_closed_percent.append(profit_percent)
else:
# Get current rate
current_rate = self._freqtrade.exchange.get_ticker(trade.pair, False)['bid']
try:
current_rate = self._freqtrade.exchange.get_ticker(trade.pair, False)['bid']
except DependencyException:
current_rate = NAN
profit_percent = trade.calc_profit_percent(rate=current_rate)
profit_all_coin.append(
@ -275,7 +284,7 @@ class RPC(object):
rate = 1.0 / self._freqtrade.exchange.get_ticker('BTC/USDT', False)['bid']
else:
rate = self._freqtrade.exchange.get_ticker(coin + '/BTC', False)['bid']
except TemporaryError:
except (TemporaryError, DependencyException):
continue
est_btc: float = rate * balance['total']
total = total + est_btc

View File

@ -572,6 +572,7 @@ def test_get_ticker(default_conf, mocker):
'last': 0.0001,
}
api_mock.fetch_ticker = MagicMock(return_value=tick)
api_mock.markets = {'ETH/BTC': {}}
exchange = get_patched_exchange(mocker, default_conf, api_mock)
# retrieve original ticker
ticker = exchange.get_ticker(pair='ETH/BTC')
@ -614,6 +615,9 @@ def test_get_ticker(default_conf, mocker):
exchange = get_patched_exchange(mocker, default_conf, api_mock)
exchange.get_ticker(pair='ETH/BTC', refresh=True)
with pytest.raises(DependencyException, match=r'Pair XRP/ETH not available'):
exchange.get_ticker(pair='XRP/ETH', refresh=True)
def test_get_history(default_conf, mocker, caplog):
exchange = get_patched_exchange(mocker, default_conf)

View File

@ -5,8 +5,9 @@ from datetime import datetime
from unittest.mock import MagicMock, ANY
import pytest
from numpy import isnan
from freqtrade import TemporaryError
from freqtrade import TemporaryError, DependencyException
from freqtrade.fiat_convert import CryptoToFiatConverter
from freqtrade.freqtradebot import FreqtradeBot
from freqtrade.persistence import Trade
@ -61,6 +62,27 @@ def test_rpc_trade_status(default_conf, ticker, fee, markets, mocker) -> None:
'open_order': '(limit buy rem=0.00000000)'
} == results[0]
mocker.patch('freqtrade.exchange.Exchange.get_ticker',
MagicMock(side_effect=DependencyException(f"Pair 'ETH/BTC' not available")))
# invalidate ticker cache
rpc._freqtrade.exchange._cached_ticker = {}
results = rpc._rpc_trade_status()
assert isnan(results[0]['current_profit'])
assert isnan(results[0]['current_rate'])
assert {
'trade_id': 1,
'pair': 'ETH/BTC',
'market_url': 'https://bittrex.com/Market/Index?MarketName=BTC-ETH',
'date': ANY,
'open_rate': 1.099e-05,
'close_rate': None,
'current_rate': ANY,
'amount': 90.99181074,
'close_profit': None,
'current_profit': ANY,
'open_order': '(limit buy rem=0.00000000)'
} == results[0]
def test_rpc_status_table(default_conf, ticker, fee, markets, mocker) -> None:
patch_coinmarketcap(mocker)
@ -87,6 +109,15 @@ def test_rpc_status_table(default_conf, ticker, fee, markets, mocker) -> None:
assert 'ETH/BTC' in result['Pair'].all()
assert '-0.59%' in result['Profit'].all()
mocker.patch('freqtrade.exchange.Exchange.get_ticker',
MagicMock(side_effect=DependencyException(f"Pair 'ETH/BTC' not available")))
# invalidate ticker cache
rpc._freqtrade.exchange._cached_ticker = {}
result = rpc._rpc_status_table()
assert 'just now' in result['Since'].all()
assert 'ETH/BTC' in result['Pair'].all()
assert 'nan%' in result['Profit'].all()
def test_rpc_daily_profit(default_conf, update, ticker, fee,
limit_buy_order, limit_sell_order, markets, mocker) -> None:
@ -208,6 +239,20 @@ def test_rpc_trade_statistics(default_conf, ticker, ticker_sell_up, fee,
assert stats['best_pair'] == 'ETH/BTC'
assert prec_satoshi(stats['best_rate'], 6.2)
# Test non-available pair
mocker.patch('freqtrade.exchange.Exchange.get_ticker',
MagicMock(side_effect=DependencyException(f"Pair 'ETH/BTC' not available")))
# invalidate ticker cache
rpc._freqtrade.exchange._cached_ticker = {}
stats = rpc._rpc_trade_statistics(stake_currency, fiat_display_currency)
assert stats['trade_count'] == 2
assert stats['first_trade_date'] == 'just now'
assert stats['latest_trade_date'] == 'just now'
assert stats['avg_duration'] == '0:00:00'
assert stats['best_pair'] == 'ETH/BTC'
assert prec_satoshi(stats['best_rate'], 6.2)
assert isnan(stats['profit_all_coin'])
# Test that rpc_trade_statistics can handle trades that lacks
# trade.open_rate (it is set to None)