8000 refactor load_markets out of validate_pairs by xmatthias · Pull Request #1204 · freqtrade/freqtrade · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

refactor load_markets out of validate_pairs #1204

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Sep 26, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 15 additions & 7 deletions freqtrade/exchange/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ def __init__(self, config: dict) -> None:

logger.info('Using Exchange "%s"', self.name)

self.markets = self._load_markets()
# Check if all pairs are available
self.validate_pairs(config['exchange']['pair_whitelist'])

Expand Down Expand Up @@ -167,6 +168,16 @@ def _load_async_markets(self) -> None:
logger.warning('Could not load async markets. Reason: %s', e)
return

def _load_markets(self) -> Dict[str, Any]:
""" Initialize markets both sync and async """
try:
markets = self._api.load_markets()
self._load_async_markets()
return markets
except ccxt.BaseError as e:
logger.warning('Unable to initialize markets. Reason: %s', e)
return {}

def validate_pairs(self, pairs: List[str]) -> None:
"""
Checks if all given pairs are tradable on the current exchange.
Expand All @@ -175,12 +186,9 @@ def validate_pairs(self, pairs: List[str]) -> None:
:return: None
"""

try:
markets = self._api.load_markets()
self._load_async_markets()
except ccxt.BaseError as e:
logger.warning('Unable to validate pairs (assuming they are correct). Reason: %s', e)
return
if not self.markets:
logger.warning('Unable to validate pairs (assuming they are correct).')
# return

stake_cur = self._conf['stake_currency']
for pair in pairs:
Expand All @@ -189,7 +197,7 @@ def validate_pairs(self, pairs: List[str]) -> None:
if not pair.endswith(stake_cur):
raise OperationalException(
f'Pair {pair} not compatible with stake_currency: {stake_cur}')
if pair not in markets:
if self.markets and pair not in self.markets:
raise OperationalException(
f'Pair {pair} is not available at {self.name}')

Expand Down
6 changes: 4 additions & 2 deletions freqtrade/tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
from datetime import datetime
from functools import reduce
from typing import Dict, Optional
from unittest.mock import MagicMock
from unittest.mock import MagicMock, PropertyMock

import arrow
import pytest
Expand All @@ -26,8 +26,10 @@ def log_has(line, logs):


def patch_exchange(mocker, api_mock=None) -> None:
mocker.patch('freqtrade.exchange.Exchange.validate_pairs', MagicMock())
mocker.patch('freqtrade.exchange.Exchange._load_markets', MagicMock(return_value={}))
mocker.patch('freqtrade.exchange.Exchange.validate_timeframes', MagicMock())
mocker.patch('freqtrade.exchange.Exchange.name', PropertyMock(return_value="Bittrex"))
mocker.patch('freqtrade.exchange.Exchange.id', PropertyMock(return_value="bittrex"))
if api_mock:
mocker.patch('freqtrade.exchange.Exchange._init_ccxt', MagicMock(return_value=api_mock))
else:
Expand Down
46 changes: 32 additions & 14 deletions freqtrade/tests/exchange/test_exchange.py
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,29 @@ def test__load_async_markets(default_conf, mocker, caplog):
caplog.record_tuples)


def test__load_markets(default_conf, mocker, caplog):
caplog.set_level(logging.INFO)
api_mock = MagicMock()
mocker.patch('freqtrade.exchange.Exchange.name', PropertyMock(return_value='Binance'))

api_mock.load_markets = MagicMock(return_value={})
mocker.patch('freqtrade.exchange.Exchange._init_ccxt', api_mock)
mocker.patch('freqtrade.exchange.Exchange.validate_timeframes', MagicMock())
mocker.patch('freqtrade.exchange.Exchange._load_async_markets', MagicMock())

expected_return = {'ETH/BTC': 'available'}
api_mock.load_markets = MagicMock(return_value=expected_return)
mocker.patch('freqtrade.exchange.Exchange._init_ccxt', MagicMock(return_value=api_mock))
default_conf['exchange']['pair_whitelist'] = ['ETH/BTC']
ex = Exchange(default_conf)
assert ex.markets == expected_return

api_mock.load_markets = MagicMock(side_effect=ccxt.BaseError())
mocker.patch('freqtrade.exchange.Exchange._init_ccxt', MagicMock(return_value=api_mock))
Exchange(default_conf)
assert log_has('Unable to initialize markets. Reason: ', caplog.record_tuples)


def test_validate_pairs(default_conf, mocker):
api_mock = MagicMock()
api_mock.load_markets = MagicMock(return_value={
Expand All @@ -199,7 +222,7 @@ def test_validate_pairs(default_conf, mocker):

def test_validate_pairs_not_available(default_conf, mocker):
api_mock = MagicMock()
api_mock.load_markets = MagicMock(return_value={})
api_mock.load_markets = MagicMock(return_value={'XRP/BTC': 'inactive'})
mocker.patch('freqtrade.exchange.Exchange._init_ccxt', MagicMock(return_value=api_mock))
mocker.patch('freqtrade.exchange.Exchange.validate_timeframes', MagicMock())
mocker.patch('freqtrade.exchange.Exchange._load_async_markets', MagicMock())
Expand Down Expand Up @@ -234,11 +257,9 @@ def test_validate_pairs_exception(default_conf, mocker, caplog):
with pytest.raises(OperationalException, match=r'Pair ETH/BTC is not available at Binance'):
Exchange(default_conf)

api_mock.load_markets = MagicMock(side_effect=ccxt.BaseError())

mocker.patch('freqtrade.exchange.Exchange._init_ccxt', MagicMock(return_value=api_mock))
mocker.patch('freqtrade.exchange.Exchange._load_markets', MagicMock(return_value={}))
Exchange(default_conf)
assert log_has('Unable to validate pairs (assuming they are correct). Reason: ',
assert log_has('Unable to validate pairs (assuming they are correct).',
caplog.record_tuples)


Expand Down Expand Up @@ -270,7 +291,7 @@ def test_validate_timeframes(default_conf, mocker):
type(api_mock).timeframes = timeframes

mocker.patch('freqtrade.exchange.Exchange._init_ccxt', MagicMock(return_value=api_mock))
mocker.patch('freqtrade.exchange.Exchange.validate_pairs', MagicMock())
mocker.patch('freqtrade.exchange.Exchange._load_markets', MagicMock(return_value={}))
Exchange(default_conf)


Expand All @@ -286,7 +307,7 @@ def test_validate_timeframes_failed(default_conf, mocker):
type(api_mock).timeframes = timeframes

mocker.patch('freqtrade.exchange.Exchange._init_ccxt', MagicMock(return_value=api_mock))
mocker.patch('freqtrade.exchange.Exchange.validate_pairs', MagicMock())
mocker.patch('freqtrade.exchange.Exchange._load_markets', MagicMock(return_value={}))
with pytest.raises(OperationalException, match=r'Invalid ticker 3m, this Exchange supports.*'):
Exchange(default_conf)

Expand All @@ -303,7 +324,7 @@ def test_validate_timeframes_not_in_config(default_conf, mocker):
type(api_mock).timeframes = timeframes

mocker.patch('freqtrade.exchange.Exchange._init_ccxt', MagicMock(return_value=api_mock))
mocker.patch('freqtrade.exchange.Exchange.validate_pairs', MagicMock())
mocker.patch('freqtrade.exchange.Exchange._load_markets', MagicMock(return_value={}))
Exchange(default_conf)


Expand Down Expand Up @@ -940,25 +961,22 @@ def test_get_order(default_conf, mocker):


def test_name(default_conf, mocker):
mocker.patch('freqtrade.exchange.Exchange.validate_pairs',
side_effect=lambda s: True)
mocker.patch('freqtrade.exchange.Exchange._load_markets', MagicMock(return_value={}))
default_conf['exchange']['name'] = 'binance'
exchange = Exchange(default_conf)

assert exchange.name == 'Binance'


def test_id(default_conf, mocker):
mocker.patch('freqtrade.exchange.Exchange.validate_pairs',
side_effect=lambda s: True)
mocker.patch('freqtrade.exchange.Exchange._load_markets', MagicMock(return_value={}))
default_conf['exchange']['name'] = 'binance'
exchange = Exchange(default_conf)
assert exchange.id == 'binance'


def test_get_pair_detail_url(default_conf, mocker, caplog):
mocker.patch('freqtrade.exchange.Exchange.validate_pairs',
side_effect=lambda s: True)
mocker.patch('freqtrade.exchange.Exchange._load_markets', MagicMock(return_value={}))
default_conf['exchange']['name'] = 'binance'
exchange = Exchange(default_conf)

Expand Down
27 changes: 12 additions & 15 deletions freqtrade/tests/rpc/test_rpc.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
from freqtrade.rpc import RPC, RPCException
from freqtrade.state import State
from freqtrade.tests.test_freqtradebot import patch_get_signal
from freqtrade.tests.conftest import patch_coinmarketcap
from freqtrade.tests.conftest import patch_coinmarketcap, patch_exchange


# Functions for recurrent object patching
Expand All @@ -30,7 +30,7 @@ def test_rpc_trade_status(default_conf, ticker, fee, markets, mocker) -> None:
mocker.patch('freqtrade.rpc.telegram.Telegram', MagicMock())
mocker.patch.multiple(
'freqtrade.exchange.Exchange',
validate_pairs=MagicMock(),
_load_markets=MagicMock(return_value={}),
get_ticker=ticker,
get_fee=fee,
get_markets=markets
Expand Down Expand Up @@ -68,10 +68,10 @@ def test_rpc_trade_status(default_conf, ticker, fee, markets, mocker) -> None:

def test_rpc_status_table(default_conf, ticker, fee, markets, mocker) -> None:
patch_coinmarketcap(mocker)
patch_exchange(mocker)
mocker.patch('freqtrade.rpc.telegram.Telegram', MagicMock())
mocker.patch.multiple(
'freqtrade.exchange.Exchange',
validate_pairs=MagicMock(),
get_ticker=ticker,
get_fee=fee,
get_markets=markets
Expand Down Expand Up @@ -99,10 +99,10 @@ def test_rpc_status_table(default_conf, ticker, fee, markets, mocker) -> None:
def test_rpc_daily_profit(default_conf, update, ticker, fee,
limit_buy_order, limit_sell_order, markets, mocker) -> None:
patch_coinmarketcap(mocker, value={'price_usd': 15000.0})
patch_exchange(mocker)
mocker.patch('freqtrade.rpc.telegram.Telegram', MagicMock())
mocker.patch.multiple(
'freqtrade.exchange.Exchange',
validate_pairs=MagicMock(),
get_ticker=ticker,
get_fee=fee,
get_markets=markets
Expand Down Expand Up @@ -152,11 +152,11 @@ def test_rpc_trade_statistics(default_conf, ticker, ticker_sell_up, fee,
ticker=MagicMock(return_value={'price_usd': 15000.0}),
)
patch_coinmarketcap(mocker)
patch_exchange(mocker)
mocker.patch('freqtrade.rpc.rpc.CryptoToFiatConverter._find_price', return_value=15000.0)
mocker.patch('freqtrade.rpc.telegram.Telegram', MagicMock())
mocker.patch.multiple(
'freqtrade.exchange.Exchange',
validate_pairs=MagicMock(),
get_ticker=ticker,
get_fee=fee,
get_markets=markets
Expand All @@ -182,7 +182,6 @@ def test_rpc_trade_statistics(default_conf, ticker, ticker_sell_up, fee,
# Update the ticker with a market going up
mocker.patch.multiple(
'freqtrade.exchange.Exchange',
validate_pairs=MagicMock(),
get_ticker=ticker_sell_up
)
trade.update(limit_sell_order)
Expand All @@ -197,7 +196,6 @@ def test_rpc_trade_statistics(default_conf, ticker, ticker_sell_up, fee,
# Update the ticker with a market going up
mocker.patch.multiple(
'freqtrade.exchange.Exchange',
validate_pairs=MagicMock(),
get_ticker=ticker_sell_up
)
trade.update(limit_sell_order)
Expand All @@ -223,6 +221,7 @@ def test_rpc_trade_statistics(default_conf, ticker, ticker_sell_up, fee,
# trade.open_rate (it is set to None)
def test_rpc_trade_statistics_closed(mocker, default_conf, ticker, fee, markets,
ticker_sell_up, limit_buy_order, limit_sell_order):
patch_exchange(mocker)
mocker.patch.multiple(
'freqtrade.fiat_convert.Market',
ticker=MagicMock(return_value={'price_usd': 15000.0}),
Expand All @@ -231,7 +230,6 @@ def test_rpc_trade_statistics_closed(mocker, default_conf, ticker, fee, markets,
mocker.patch('freqtrade.rpc.telegram.Telegram', MagicMock())
mocker.patch.multiple(
'freqtrade.exchange.Exchange',
validate_pairs=MagicMock(),
get_ticker=ticker,
get_fee=fee,
get_markets=markets
Expand All @@ -252,7 +250,6 @@ def test_rpc_trade_statistics_closed(mocker, default_conf, ticker, fee, markets,
# Update the ticker with a market going up
mocker.patch.multiple(
'freqtrade.exchange.Exchange',
validate_pairs=MagicMock(),
get_ticker=ticker_sell_up,
get_fee=fee
)
Expand Down Expand Up @@ -298,11 +295,11 @@ def test_rpc_balance_handle(default_conf, mocker):
ticker=MagicMock(return_value={'price_usd': 15000.0}),
)
patch_coinmarketcap(mocker)
patch_exchange(mocker)
mocker.patch('freqtrade.rpc.rpc.CryptoToFiatConverter._find_price', return_value=15000.0)
mocker.patch('freqtrade.rpc.telegram.Telegram', MagicMock())
mocker.patch.multiple(
'freqtrade.exchange.Exchange',
validate_pairs=MagicMock(),
get_balances=MagicMock(return_value=mock_balance),
get_ticker=MagicMock(side_effect=TemporaryError('Could not load ticker due to xxx'))
)
Expand All @@ -328,10 +325,10 @@ def test_rpc_balance_handle(default_conf, mocker):

def test_rpc_start(mocker, default_conf) -> None:
patch_coinmarketcap(mocker)
patch_exchange(mocker)
mocker.patch('freqtrade.rpc.telegram.Telegram', MagicMock())
mocker.patch.multiple(
'freqtrade.exchange.Exchange',
validate_pairs=MagicMock(),
get_ticker=MagicMock()
)

Expand All @@ -351,10 +348,10 @@ def test_rpc_start(mocker, default_conf) -> None:

def test_rpc_stop(mocker, default_conf) -> None:
patch_coinmarketcap(mocker)
patch_exchange(mocker)
mocker.patch('freqtrade.rpc.telegram.Telegram', MagicMock())
mocker.patch.multiple(
'freqtrade.exchange.Exchange',
validate_pairs=MagicMock(),
get_ticker=MagicMock()
)

Expand All @@ -375,12 +372,12 @@ def test_rpc_stop(mocker, default_conf) -> None:

def test_rpc_forcesell(default_conf, ticker, fee, mocker, mark BC10 ets) -> None:
patch_coinmarketcap(mocker)
patch_exchange(mocker)
mocker.patch('freqtrade.rpc.telegram.Telegram', MagicMock())

cancel_order_mock = MagicMock()
mocker.patch.multiple(
'freqtrade.exchange.Exchange',
validate_pairs=MagicMock(),
get_ticker=ticker,
cancel_order=cancel_order_mock,
get_order=MagicMock(
Expand Down Expand Up @@ -476,10 +473,10 @@ def test_rpc_forcesell(default_conf, ticker, fee, mocker, markets) -> None:
def test_performance_handle(default_conf, ticker, limit_buy_order, fee,
limit_sell_order, markets, mocker) -> None:
patch_coinmarketcap(mocker)
patch_exchange(mocker)
mocker.patch('freqtrade.rpc.telegram.Telegram', MagicMock())
mocker.patch.multiple(
'freqtrade.exchange.Exchange',
validate_pairs=MagicMock(),
get_balances=MagicMock(return_value=ticker),
get_ticker=ticker,
get_fee=fee,
Expand Down Expand Up @@ -512,10 +509,10 @@ def test_performance_handle(default_conf, ticker, limit_buy_order, fee,

def test_rpc_count(mocker, default_conf, ticker, fee, markets) -> None:
patch_coinmarketcap(mocker)
patch_exchange(mocker)
mocker.patch('freqtrade.rpc.telegram.Telegram', MagicMock())
mocker.patch.multiple(
'freqtrade.exchange.Exchange',
validate_pairs=MagicMock(),
get_balances=MagicMock(return_value=ticker),
get_ticker=ticker,
get_fee=fee,
Expand Down
Loading
0