Replace 'get_wallet_health' and 'get_markets_summaries'
Both are now covered by 'get_markets'
This commit is contained in:
parent
eac3c4b72c
commit
0b71f7186c
@ -192,42 +192,44 @@ class FreqtradeBot(object):
|
|||||||
:param key: sort key (defaults to 'BaseVolume')
|
:param key: sort key (defaults to 'BaseVolume')
|
||||||
:return: List of pairs
|
:return: List of pairs
|
||||||
"""
|
"""
|
||||||
summaries = sorted(
|
pairs = sorted(
|
||||||
(v for s, v in exchange.get_market_summaries().items() if v['symbol'].endswith(base_currency)),
|
[s['symbol'] for s in exchange.get_markets() if s['quote'] == base_currency],
|
||||||
key=lambda v: v.get('info').get(key) or 0.0,
|
|
||||||
reverse=True
|
reverse=True
|
||||||
)
|
)
|
||||||
|
|
||||||
return [s['symbol'] for s in summaries]
|
return pairs
|
||||||
|
|
||||||
def _refresh_whitelist(self, whitelist: List[str]) -> List[str]:
|
def _refresh_whitelist(self, whitelist: List[str]) -> List[str]:
|
||||||
"""
|
"""
|
||||||
Check wallet health and remove pair from whitelist if necessary
|
Check available markets and remove pair from whitelist if necessary
|
||||||
:param whitelist: the sorted list (based on BaseVolume) of pairs the user might want to
|
:param whitelist: the sorted list (based on BaseVolume) of pairs the user might want to
|
||||||
trade
|
trade
|
||||||
:return: the list of pairs the user wants to trade without the one unavailable or
|
:return: the list of pairs the user wants to trade without the one unavailable or
|
||||||
black_listed
|
black_listed
|
||||||
"""
|
"""
|
||||||
sanitized_whitelist = whitelist
|
sanitized_whitelist = whitelist
|
||||||
health = exchange.get_wallet_health()
|
markets = exchange.get_markets()
|
||||||
|
|
||||||
|
markets = [m for m in markets if m['quote'] == self.config['stake_currency']]
|
||||||
known_pairs = set()
|
known_pairs = set()
|
||||||
for symbol, status in health.items():
|
for market in markets:
|
||||||
pair = f"{status['base']}/{self.config['stake_currency']}"
|
pair = market['symbol']
|
||||||
# pair is not int the generated dynamic market, or in the blacklist ... ignore it
|
# pair is not int the generated dynamic market, or in the blacklist ... ignore it
|
||||||
if pair not in whitelist or pair in self.config['exchange'].get('pair_blacklist', []):
|
if pair not in whitelist or pair in self.config['exchange'].get('pair_blacklist', []):
|
||||||
continue
|
continue
|
||||||
# else the pair is valid
|
# else the pair is valid
|
||||||
known_pairs.add(pair)
|
known_pairs.add(pair)
|
||||||
# Market is not active
|
# Market is not active
|
||||||
if not status['active']:
|
if not market['active']:
|
||||||
sanitized_whitelist.remove(pair)
|
sanitized_whitelist.remove(pair)
|
||||||
self.logger.info(
|
self.logger.info(
|
||||||
'Ignoring %s from whitelist (reason: %s).',
|
'Ignoring %s from whitelist. Market is not active.',
|
||||||
pair, status.get('Notice') or 'wallet is not active'
|
pair
|
||||||
)
|
)
|
||||||
|
|
||||||
# We need to remove pairs that are unknown
|
# We need to remove pairs that are unknown
|
||||||
final_list = [x for x in sanitized_whitelist if x in known_pairs]
|
final_list = [x for x in sanitized_whitelist if x in known_pairs]
|
||||||
|
|
||||||
return final_list
|
return final_list
|
||||||
|
|
||||||
def get_target_bid(self, ticker: Dict[str, float]) -> float:
|
def get_target_bid(self, ticker: Dict[str, float]) -> float:
|
||||||
|
@ -127,32 +127,80 @@ def ticker_sell_down():
|
|||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def health():
|
def markets():
|
||||||
return MagicMock(return_value={
|
return MagicMock(return_value=[
|
||||||
"ETH/BTC": {
|
{
|
||||||
|
'id': 'ethbtc',
|
||||||
|
'symbol': 'ETH/BTC',
|
||||||
'base': 'ETH',
|
'base': 'ETH',
|
||||||
|
'quote': 'BTC',
|
||||||
'active': True,
|
'active': True,
|
||||||
'LastChecked': '2017-11-13T20:15:00.00',
|
'precision': {
|
||||||
'Notice': None
|
'price': 8,
|
||||||
|
'amount': 8,
|
||||||
|
'cost': 8,
|
||||||
},
|
},
|
||||||
"TRST/BTC": {
|
'lot': 0.00000001,
|
||||||
'base': 'TRST',
|
'limits': {
|
||||||
|
'amount': {
|
||||||
|
'min': 0.01,
|
||||||
|
'max': 1000,
|
||||||
|
},
|
||||||
|
'price': 500000,
|
||||||
|
'cost': 500000,
|
||||||
|
},
|
||||||
|
'info': '',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'id': 'tknbtc',
|
||||||
|
'symbol': 'TKN/BTC',
|
||||||
|
'base': 'TKN',
|
||||||
|
'quote': 'BTC',
|
||||||
'active': True,
|
'active': True,
|
||||||
'LastChecked': '2017-11-13T20:15:00.00',
|
'precision': {
|
||||||
'Notice': None
|
'price': 8,
|
||||||
|
'amount': 8,
|
||||||
|
'cost': 8,
|
||||||
},
|
},
|
||||||
"SWT/BTC": {
|
'lot': 0.00000001,
|
||||||
'base': 'SWT',
|
'limits': {
|
||||||
|
'amount': {
|
||||||
|
'min': 0.01,
|
||||||
|
'max': 1000,
|
||||||
|
},
|
||||||
|
'price': 500000,
|
||||||
|
'cost': 500000,
|
||||||
|
},
|
||||||
|
'info': '',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'id': 'blkbtc',
|
||||||
|
'symbol': 'BLK/BTC',
|
||||||
|
'base': 'BLK',
|
||||||
|
'quote': 'BTC',
|
||||||
'active': True,
|
'active': True,
|
||||||
'LastChecked': '2017-11-13T20:15:00.00',
|
'precision': {
|
||||||
'Notice': None
|
'price': 8,
|
||||||
|
'amount': 8,
|
||||||
|
'cost': 8,
|
||||||
},
|
},
|
||||||
"BCC/BTC": {
|
'lot': 0.00000001,
|
||||||
'base': 'BCC',
|
'limits': {
|
||||||
'active': False,
|
'amount': {
|
||||||
'LastChecked': '2017-11-13T20:15:00.00',
|
'min': 0.01,
|
||||||
'Notice': None
|
'max': 1000,
|
||||||
}})
|
},
|
||||||
|
'price': 500000,
|
||||||
|
'cost': 500000,
|
||||||
|
},
|
||||||
|
'info': '',
|
||||||
|
}
|
||||||
|
])
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def markets_empty():
|
||||||
|
return MagicMock(return_value=[])
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
@ -334,3 +382,4 @@ def result():
|
|||||||
# that inserts a trade of some type and open-status
|
# that inserts a trade of some type and open-status
|
||||||
# return the open-order-id
|
# return the open-order-id
|
||||||
# See tests in rpc/main that could use this
|
# See tests in rpc/main that could use this
|
||||||
|
|
||||||
|
@ -26,81 +26,12 @@ def whitelist_conf():
|
|||||||
return config
|
return config
|
||||||
|
|
||||||
|
|
||||||
def get_market_summaries():
|
def test_refresh_market_pair_not_in_whitelist(mocker, markets):
|
||||||
return {
|
|
||||||
'TKN/BTC': {
|
|
||||||
'symbol': 'TKN/BTC',
|
|
||||||
'info': {
|
|
||||||
'High': 0.00000919,
|
|
||||||
'Low': 0.00000820,
|
|
||||||
'Volume': 74339.61396015,
|
|
||||||
'Last': 0.00000820,
|
|
||||||
'BaseVolume': 1664,
|
|
||||||
'TimeStamp': '2014-07-09T07:19:30.15',
|
|
||||||
'Bid': 0.00000820,
|
|
||||||
'Ask': 0.00000831,
|
|
||||||
'OpenBuyOrders': 15,
|
|
||||||
'OpenSellOrders': 15,
|
|
||||||
'PrevDay': 0.00000821,
|
|
||||||
'Created': '2014-03-20T06:00:00',
|
|
||||||
'DisplayMarketName': ''
|
|
||||||
}
|
|
||||||
},
|
|
||||||
'ETH/BTC': {
|
|
||||||
'symbol': 'ETH/BTC',
|
|
||||||
'info': {
|
|
||||||
'High': 0.00000072,
|
|
||||||
'Low': 0.00000001,
|
|
||||||
'Volume': 166340678.42280999,
|
|
||||||
'Last': 0.00000005,
|
|
||||||
'BaseVolume': 42,
|
|
||||||
'TimeStamp': '2014-07-09T07:21:40.51',
|
|
||||||
'Bid': 0.00000004,
|
|
||||||
'Ask': 0.00000005,
|
|
||||||
'OpenBuyOrders': 18,
|
|
||||||
'OpenSellOrders': 18,
|
|
||||||
'PrevDay': 0.00000002,
|
|
||||||
'Created': '2014-05-30T07:57:49.637',
|
|
||||||
'DisplayMarketName': ''
|
|
||||||
}
|
|
||||||
},
|
|
||||||
'BLK/BTC': {
|
|
||||||
'symbol': 'BLK/BTC',
|
|
||||||
'info': {
|
|
||||||
'High': 0.00000072,
|
|
||||||
'Low': 0.00000001,
|
|
||||||
'Volume': 166340678.42280999,
|
|
||||||
'Last': 0.00000005,
|
|
||||||
'BaseVolume': 3,
|
|
||||||
'TimeStamp': '2014-07-09T07:21:40.51',
|
|
||||||
'Bid': 0.00000004,
|
|
||||||
'Ask': 0.00000005,
|
|
||||||
'OpenBuyOrders': 18,
|
|
||||||
'OpenSellOrders': 18,
|
|
||||||
'PrevDay': 0.00000002,
|
|
||||||
'Created': '2014-05-30T07:57:49.637',
|
|
||||||
'DisplayMarketName': ''
|
|
||||||
}}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
def get_health():
|
|
||||||
return {
|
|
||||||
'ETH/BTC': {'base': 'ETH', 'active': True},
|
|
||||||
'TKN/BTC': {'base': 'TKN', 'active': True},
|
|
||||||
'BLK/BTC': {'base': 'BLK', 'active': True}}
|
|
||||||
|
|
||||||
|
|
||||||
def get_health_empty():
|
|
||||||
return {}
|
|
||||||
|
|
||||||
|
|
||||||
def test_refresh_market_pair_not_in_whitelist(mocker):
|
|
||||||
conf = whitelist_conf()
|
conf = whitelist_conf()
|
||||||
|
|
||||||
freqtradebot = tt.get_patched_freqtradebot(mocker, conf)
|
freqtradebot = tt.get_patched_freqtradebot(mocker, conf)
|
||||||
|
|
||||||
mocker.patch('freqtrade.freqtradebot.exchange.get_wallet_health', get_health)
|
mocker.patch('freqtrade.freqtradebot.exchange.get_markets', markets)
|
||||||
refreshedwhitelist = freqtradebot._refresh_whitelist(
|
refreshedwhitelist = freqtradebot._refresh_whitelist(
|
||||||
conf['exchange']['pair_whitelist'] + ['XXX/BTC']
|
conf['exchange']['pair_whitelist'] + ['XXX/BTC']
|
||||||
)
|
)
|
||||||
@ -110,11 +41,11 @@ def test_refresh_market_pair_not_in_whitelist(mocker):
|
|||||||
assert whitelist == refreshedwhitelist
|
assert whitelist == refreshedwhitelist
|
||||||
|
|
||||||
|
|
||||||
def test_refresh_whitelist(mocker):
|
def test_refresh_whitelist(mocker, markets):
|
||||||
conf = whitelist_conf()
|
conf = whitelist_conf()
|
||||||
freqtradebot = tt.get_patched_freqtradebot(mocker, conf)
|
freqtradebot = tt.get_patched_freqtradebot(mocker, conf)
|
||||||
|
|
||||||
mocker.patch('freqtrade.freqtradebot.exchange.get_wallet_health', get_health)
|
mocker.patch('freqtrade.freqtradebot.exchange.get_markets', markets)
|
||||||
refreshedwhitelist = freqtradebot._refresh_whitelist(conf['exchange']['pair_whitelist'])
|
refreshedwhitelist = freqtradebot._refresh_whitelist(conf['exchange']['pair_whitelist'])
|
||||||
|
|
||||||
# List ordered by BaseVolume
|
# List ordered by BaseVolume
|
||||||
@ -123,14 +54,10 @@ def test_refresh_whitelist(mocker):
|
|||||||
assert whitelist == refreshedwhitelist
|
assert whitelist == refreshedwhitelist
|
||||||
|
|
||||||
|
|
||||||
def test_refresh_whitelist_dynamic(mocker):
|
def test_refresh_whitelist_dynamic(mocker, markets):
|
||||||
conf = whitelist_conf()
|
conf = whitelist_conf()
|
||||||
freqtradebot = tt.get_patched_freqtradebot(mocker, conf)
|
freqtradebot = tt.get_patched_freqtradebot(mocker, conf)
|
||||||
mocker.patch.multiple(
|
mocker.patch('freqtrade.freqtradebot.exchange.get_markets', markets)
|
||||||
'freqtrade.freqtradebot.exchange',
|
|
||||||
get_wallet_health=get_health,
|
|
||||||
get_market_summaries=get_market_summaries
|
|
||||||
)
|
|
||||||
|
|
||||||
# argument: use the whitelist dynamically by exchange-volume
|
# argument: use the whitelist dynamically by exchange-volume
|
||||||
whitelist = ['TKN/BTC', 'ETH/BTC']
|
whitelist = ['TKN/BTC', 'ETH/BTC']
|
||||||
@ -142,10 +69,10 @@ def test_refresh_whitelist_dynamic(mocker):
|
|||||||
assert whitelist == refreshedwhitelist
|
assert whitelist == refreshedwhitelist
|
||||||
|
|
||||||
|
|
||||||
def test_refresh_whitelist_dynamic_empty(mocker):
|
def test_refresh_whitelist_dynamic_empty(mocker, markets_empty):
|
||||||
conf = whitelist_conf()
|
conf = whitelist_conf()
|
||||||
freqtradebot = tt.get_patched_freqtradebot(mocker, conf)
|
freqtradebot = tt.get_patched_freqtradebot(mocker, conf)
|
||||||
mocker.patch('freqtrade.freqtradebot.exchange.get_wallet_health', get_health_empty)
|
mocker.patch('freqtrade.freqtradebot.exchange.get_markets', markets_empty)
|
||||||
|
|
||||||
# argument: use the whitelist dynamically by exchange-volume
|
# argument: use the whitelist dynamically by exchange-volume
|
||||||
whitelist = []
|
whitelist = []
|
||||||
|
@ -201,15 +201,12 @@ def test_throttle_with_assets(mocker, default_conf) -> None:
|
|||||||
assert result == -1
|
assert result == -1
|
||||||
|
|
||||||
|
|
||||||
def test_gen_pair_whitelist(mocker, default_conf, get_market_summaries_data) -> None:
|
def test_gen_pair_whitelist(mocker, default_conf, markets) -> None:
|
||||||
"""
|
"""
|
||||||
Test _gen_pair_whitelist() method
|
Test _gen_pair_whitelist() method
|
||||||
"""
|
"""
|
||||||
freqtrade = get_patched_freqtradebot(mocker, default_conf)
|
freqtrade = get_patched_freqtradebot(mocker, default_conf)
|
||||||
mocker.patch(
|
mocker.patch('freqtrade.freqtradebot.exchange.get_markets', markets)
|
||||||
'freqtrade.freqtradebot.exchange.get_market_summaries',
|
|
||||||
return_value=get_market_summaries_data
|
|
||||||
)
|
|
||||||
|
|
||||||
# Test to retrieved BTC sorted on BaseVolume
|
# Test to retrieved BTC sorted on BaseVolume
|
||||||
whitelist = freqtrade._gen_pair_whitelist(base_currency='BTC')
|
whitelist = freqtrade._gen_pair_whitelist(base_currency='BTC')
|
||||||
@ -392,7 +389,7 @@ def test_create_trade_no_signal(default_conf, mocker) -> None:
|
|||||||
|
|
||||||
|
|
||||||
def test_process_trade_creation(default_conf, ticker, limit_buy_order,
|
def test_process_trade_creation(default_conf, ticker, limit_buy_order,
|
||||||
health, mocker, caplog) -> None:
|
markets, mocker, caplog) -> None:
|
||||||
"""
|
"""
|
||||||
Test the trade creation in _process() method
|
Test the trade creation in _process() method
|
||||||
"""
|
"""
|
||||||
@ -403,7 +400,7 @@ def test_process_trade_creation(default_conf, ticker, limit_buy_order,
|
|||||||
'freqtrade.freqtradebot.exchange',
|
'freqtrade.freqtradebot.exchange',
|
||||||
validate_pairs=MagicMock(),
|
validate_pairs=MagicMock(),
|
||||||
get_ticker=ticker,
|
get_ticker=ticker,
|
||||||
get_wallet_health=health,
|
get_markets=markets,
|
||||||
buy=MagicMock(return_value='mocked_limit_buy'),
|
buy=MagicMock(return_value='mocked_limit_buy'),
|
||||||
get_order=MagicMock(return_value=limit_buy_order)
|
get_order=MagicMock(return_value=limit_buy_order)
|
||||||
)
|
)
|
||||||
@ -432,7 +429,7 @@ def test_process_trade_creation(default_conf, ticker, limit_buy_order,
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def test_process_exchange_failures(default_conf, ticker, health, mocker) -> None:
|
def test_process_exchange_failures(default_conf, ticker, markets, mocker) -> None:
|
||||||
"""
|
"""
|
||||||
Test _process() method when a RequestException happens
|
Test _process() method when a RequestException happens
|
||||||
"""
|
"""
|
||||||
@ -443,7 +440,7 @@ def test_process_exchange_failures(default_conf, ticker, health, mocker) -> None
|
|||||||
'freqtrade.freqtradebot.exchange',
|
'freqtrade.freqtradebot.exchange',
|
||||||
validate_pairs=MagicMock(),
|
validate_pairs=MagicMock(),
|
||||||
get_ticker=ticker,
|
get_ticker=ticker,
|
||||||
get_wallet_health=health,
|
get_markets=markets,
|
||||||
buy=MagicMock(side_effect=requests.exceptions.RequestException)
|
buy=MagicMock(side_effect=requests.exceptions.RequestException)
|
||||||
)
|
)
|
||||||
sleep_mock = mocker.patch('time.sleep', side_effect=lambda _: None)
|
sleep_mock = mocker.patch('time.sleep', side_effect=lambda _: None)
|
||||||
@ -454,7 +451,7 @@ def test_process_exchange_failures(default_conf, ticker, health, mocker) -> None
|
|||||||
assert sleep_mock.has_calls()
|
assert sleep_mock.has_calls()
|
||||||
|
|
||||||
|
|
||||||
def test_process_operational_exception(default_conf, ticker, health, mocker) -> None:
|
def test_process_operational_exception(default_conf, ticker, markets, mocker) -> None:
|
||||||
"""
|
"""
|
||||||
Test _process() method when an OperationalException happens
|
Test _process() method when an OperationalException happens
|
||||||
"""
|
"""
|
||||||
@ -465,7 +462,7 @@ def test_process_operational_exception(default_conf, ticker, health, mocker) ->
|
|||||||
'freqtrade.freqtradebot.exchange',
|
'freqtrade.freqtradebot.exchange',
|
||||||
validate_pairs=MagicMock(),
|
validate_pairs=MagicMock(),
|
||||||
get_ticker=ticker,
|
get_ticker=ticker,
|
||||||
get_wallet_health=health,
|
get_markets=markets,
|
||||||
buy=MagicMock(side_effect=OperationalException)
|
buy=MagicMock(side_effect=OperationalException)
|
||||||
)
|
)
|
||||||
freqtrade = FreqtradeBot(default_conf, create_engine('sqlite://'))
|
freqtrade = FreqtradeBot(default_conf, create_engine('sqlite://'))
|
||||||
@ -477,7 +474,7 @@ def test_process_operational_exception(default_conf, ticker, health, mocker) ->
|
|||||||
assert 'OperationalException' in msg_mock.call_args_list[-1][0][0]
|
assert 'OperationalException' in msg_mock.call_args_list[-1][0][0]
|
||||||
|
|
||||||
|
|
||||||
def test_process_trade_handling(default_conf, ticker, limit_buy_order, health, mocker) -> None:
|
def test_process_trade_handling(default_conf, ticker, limit_buy_order, markets, mocker) -> None:
|
||||||
"""
|
"""
|
||||||
Test _process()
|
Test _process()
|
||||||
"""
|
"""
|
||||||
@ -488,7 +485,7 @@ def test_process_trade_handling(default_conf, ticker, limit_buy_order, health, m
|
|||||||
'freqtrade.freqtradebot.exchange',
|
'freqtrade.freqtradebot.exchange',
|
||||||
validate_pairs=MagicMock(),
|
validate_pairs=MagicMock(),
|
||||||
get_ticker=ticker,
|
get_ticker=ticker,
|
||||||
get_wallet_health=health,
|
get_markets=markets,
|
||||||
buy=MagicMock(return_value='mocked_limit_buy'),
|
buy=MagicMock(return_value='mocked_limit_buy'),
|
||||||
get_order=MagicMock(return_value=limit_buy_order)
|
get_order=MagicMock(return_value=limit_buy_order)
|
||||||
)
|
)
|
||||||
|
Loading…
Reference in New Issue
Block a user