def test_get_fee(default_conf, mocker): api_mock = MagicMock() api_mock.calculate_fee = MagicMock(return_value={ 'type': 'taker', 'currency': 'BTC', 'rate': 0.025, 'cost': 0.05 }) exchange = get_patched_exchange(mocker, default_conf, api_mock) assert exchange.get_fee() == 0.025 # test Exceptions with pytest.raises(OperationalException): api_mock = MagicMock() api_mock.calculate_fee = MagicMock(side_effect=ccxt.BaseError) exchange = get_patched_exchange(mocker, default_conf, api_mock) exchange.get_fee() with pytest.raises(TemporaryError): api_mock = MagicMock() api_mock.calculate_fee = MagicMock(side_effect=ccxt.NetworkError) exchange = get_patched_exchange(mocker, default_conf, api_mock) exchange.get_fee() assert api_mock.calculate_fee.call_count == API_RETRY_COUNT + 1
def test_get_balances_prod(default_conf, mocker): balance_item = {'free': 10.0, 'total': 10.0, 'used': 0.0} api_mock = MagicMock() api_mock.fetch_balance = MagicMock(return_value={ '1ST': balance_item, '2ST': balance_item, '3ST': balance_item }) default_conf['dry_run'] = False exchange = get_patched_exchange(mocker, default_conf, api_mock) assert len(exchange.get_balances()) == 3 assert exchange.get_balances()['1ST']['free'] == 10.0 assert exchange.get_balances()['1ST']['total'] == 10.0 assert exchange.get_balances()['1ST']['used'] == 0.0 with pytest.raises(TemporaryError): api_mock.fetch_balance = MagicMock(side_effect=ccxt.NetworkError) exchange = get_patched_exchange(mocker, default_conf, api_mock) exchange.get_balances() assert api_mock.fetch_balance.call_count == API_RETRY_COUNT + 1 with pytest.raises(OperationalException): api_mock.fetch_balance = MagicMock(side_effect=ccxt.BaseError) exchange = get_patched_exchange(mocker, default_conf, api_mock) exchange.get_balances() assert api_mock.fetch_balance.call_count == 1
def test_get_candle_history(default_conf, mocker): api_mock = MagicMock() tick = [[ 1511686200000, # unix timestamp ms 1, # open 2, # high 3, # low 4, # close 5, # volume (in quote currency) ]] type(api_mock).has = PropertyMock(return_value={'fetchOHLCV': True}) api_mock.fetch_ohlcv = MagicMock(side_effect=make_fetch_ohlcv_mock(tick)) exchange = get_patched_exchange(mocker, default_conf, api_mock) # retrieve original ticker ticks = exchange.get_candle_history('ETH/BTC', default_conf['ticker_interval']) assert ticks[0][0] == 1511686200000 assert ticks[0][1] == 1 assert ticks[0][2] == 2 assert ticks[0][3] == 3 assert ticks[0][4] == 4 assert ticks[0][5] == 5 # change ticker and ensure tick changes new_tick = [[ 1511686210000, # unix timestamp ms 6, # open 7, # high 8, # low 9, # close 10, # volume (in quote currency) ]] api_mock.fetch_ohlcv = MagicMock( side_effect=make_fetch_ohlcv_mock(new_tick)) exchange = get_patched_exchange(mocker, default_conf, api_mock) ticks = exchange.get_candle_history('ETH/BTC', default_conf['ticker_interval']) assert ticks[0][0] == 1511686210000 assert ticks[0][1] == 6 assert ticks[0][2] == 7 assert ticks[0][3] == 8 assert ticks[0][4] == 9 assert ticks[0][5] == 10 ccxt_exceptionhandlers(mocker, default_conf, api_mock, "get_candle_history", "fetch_ohlcv", pair='ABCD/BTC', tick_interval=default_conf['ticker_interval']) with pytest.raises(OperationalException, match=r'Exchange .* does not support.*'): api_mock.fetch_ohlcv = MagicMock(side_effect=ccxt.NotSupported) exchange = get_patched_exchange(mocker, default_conf, api_mock) exchange.get_candle_history( pair='ABCD/BTC', tick_interval=default_conf['ticker_interval'])
def test_cancel_order(default_conf, mocker): default_conf['dry_run'] = False api_mock = MagicMock() api_mock.cancel_order = MagicMock(return_value=123) exchange = get_patched_exchange(mocker, default_conf, api_mock) assert exchange.cancel_order(order_id='_', pair='TKN/BTC') == 123 with pytest.raises(TemporaryError): api_mock.cancel_order = MagicMock(side_effect=ccxt.NetworkError) exchange = get_patched_exchange(mocker, default_conf, api_mock) exchange.cancel_order(order_id='_', pair='TKN/BTC') assert api_mock.cancel_order.call_count == API_RETRY_COUNT + 1 with pytest.raises(DependencyException): api_mock.cancel_order = MagicMock(side_effect=ccxt.InvalidOrder) exchange = get_patched_exchange(mocker, default_conf, api_mock) exchange.cancel_order(order_id='_', pair='TKN/BTC') assert api_mock.cancel_order.call_count == API_RETRY_COUNT + 1 with pytest.raises(OperationalException): api_mock.cancel_order = MagicMock(side_effect=ccxt.BaseError) exchange = get_patched_exchange(mocker, default_conf, api_mock) exchange.cancel_order(order_id='_', pair='TKN/BTC') assert api_mock.cancel_order.call_count == 1
def test_get_order(default_conf, mocker): default_conf['dry_run'] = True order = MagicMock() order.myid = 123 exchange = get_patched_exchange(mocker, default_conf) exchange._dry_run_open_orders['X'] = order print(exchange.get_order('X', 'TKN/BTC')) assert exchange.get_order('X', 'TKN/BTC').myid == 123 default_conf['dry_run'] = False api_mock = MagicMock() api_mock.fetch_order = MagicMock(return_value=456) exchange = get_patched_exchange(mocker, default_conf, api_mock) assert exchange.get_order('X', 'TKN/BTC') == 456 with pytest.raises(TemporaryError): api_mock.fetch_order = MagicMock(side_effect=ccxt.NetworkError) exchange = get_patched_exchange(mocker, default_conf, api_mock) exchange.get_order(order_id='_', pair='TKN/BTC') assert api_mock.fetch_order.call_count == API_RETRY_COUNT + 1 with pytest.raises(DependencyException): api_mock.fetch_order = MagicMock(side_effect=ccxt.InvalidOrder) exchange = get_patched_exchange(mocker, default_conf, api_mock) exchange.get_order(order_id='_', pair='TKN/BTC') assert api_mock.fetch_order.call_count == API_RETRY_COUNT + 1 with pytest.raises(OperationalException): api_mock.fetch_order = MagicMock(side_effect=ccxt.BaseError) exchange = get_patched_exchange(mocker, default_conf, api_mock) exchange.get_order(order_id='_', pair='TKN/BTC') assert api_mock.fetch_order.call_count == 1
def test_get_ticker_history(default_conf, mocker): api_mock = MagicMock() tick = [[ 1511686200000, # unix timestamp ms 1, # open 2, # high 3, # low 4, # close 5, # volume (in quote currency) ]] type(api_mock).has = PropertyMock(return_value={'fetchOHLCV': True}) api_mock.fetch_ohlcv = MagicMock(side_effect=make_fetch_ohlcv_mock(tick)) exchange = get_patched_exchange(mocker, default_conf, api_mock) # retrieve original ticker ticks = exchange.get_ticker_history('ETH/BTC', default_conf['ticker_interval']) assert ticks[0][0] == 1511686200000 assert ticks[0][1] == 1 assert ticks[0][2] == 2 assert ticks[0][3] == 3 assert ticks[0][4] == 4 assert ticks[0][5] == 5 # change ticker and ensure tick changes new_tick = [[ 1511686210000, # unix timestamp ms 6, # open 7, # high 8, # low 9, # close 10, # volume (in quote currency) ]] api_mock.fetch_ohlcv = MagicMock( side_effect=make_fetch_ohlcv_mock(new_tick)) exchange = get_patched_exchange(mocker, default_conf, api_mock) ticks = exchange.get_ticker_history('ETH/BTC', default_conf['ticker_interval']) assert ticks[0][0] == 1511686210000 assert ticks[0][1] == 6 assert ticks[0][2] == 7 assert ticks[0][3] == 8 assert ticks[0][4] == 9 assert ticks[0][5] == 10 with pytest.raises(TemporaryError): # test retrier api_mock.fetch_ohlcv = MagicMock(side_effect=ccxt.NetworkError) exchange = get_patched_exchange(mocker, default_conf, api_mock) # new symbol to get around cache exchange.get_ticker_history('ABCD/BTC', default_conf['ticker_interval']) with pytest.raises(OperationalException): api_mock.fetch_ohlcv = MagicMock(side_effect=ccxt.BaseError) exchange = get_patched_exchange(mocker, default_conf, api_mock) # new symbol to get around cache exchange.get_ticker_history('EFGH/BTC', default_conf['ticker_interval'])
def test_get_ticker(default_conf, mocker): api_mock = MagicMock() tick = { 'symbol': 'ETH/BTC', 'bid': 0.00001098, 'ask': 0.00001099, 'last': 0.0001, } api_mock.fetch_ticker = MagicMock(return_value=tick) exchange = get_patched_exchange(mocker, default_conf, api_mock) # retrieve original ticker ticker = exchange.get_ticker(pair='ETH/BTC') assert ticker['bid'] == 0.00001098 assert ticker['ask'] == 0.00001099 # change the ticker tick = { 'symbol': 'ETH/BTC', 'bid': 0.5, 'ask': 1, 'last': 42, } api_mock.fetch_ticker = MagicMock(return_value=tick) exchange = get_patched_exchange(mocker, default_conf, api_mock) # if not caching the result we should get the same ticker # if not fetching a new result we should get the cached ticker ticker = exchange.get_ticker(pair='ETH/BTC') assert api_mock.fetch_ticker.call_count == 1 assert ticker['bid'] == 0.5 assert ticker['ask'] == 1 assert 'ETH/BTC' in exchange._cached_ticker assert exchange._cached_ticker['ETH/BTC']['bid'] == 0.5 assert exchange._cached_ticker['ETH/BTC']['ask'] == 1 # Test caching api_mock.fetch_ticker = MagicMock() exchange.get_ticker(pair='ETH/BTC', refresh=False) assert api_mock.fetch_ticker.call_count == 0 with pytest.raises(TemporaryError): # test retrier api_mock.fetch_ticker = MagicMock(side_effect=ccxt.NetworkError) exchange = get_patched_exchange(mocker, default_conf, api_mock) exchange.get_ticker(pair='ETH/BTC', refresh=True) with pytest.raises(OperationalException): api_mock.fetch_ticker = MagicMock(side_effect=ccxt.BaseError) exchange = get_patched_exchange(mocker, default_conf, api_mock) exchange.get_ticker(pair='ETH/BTC', refresh=True) api_mock.fetch_ticker = MagicMock(return_value={}) exchange = get_patched_exchange(mocker, default_conf, api_mock) exchange.get_ticker(pair='ETH/BTC', refresh=True)
def test_stoploss_limit_order(default_conf, mocker): api_mock = MagicMock() order_id = 'test_prod_buy_{}'.format(randint(0, 10 ** 6)) order_type = 'stop_loss_limit' api_mock.create_order = MagicMock(return_value={ 'id': order_id, 'info': { 'foo': 'bar' } }) default_conf['dry_run'] = False mocker.patch('freqtrade.exchange.Exchange.symbol_amount_prec', lambda s, x, y: y) mocker.patch('freqtrade.exchange.Exchange.symbol_price_prec', lambda s, x, y: y) exchange = get_patched_exchange(mocker, default_conf, api_mock, 'binance') with pytest.raises(OperationalException): order = exchange.stoploss_limit(pair='ETH/BTC', amount=1, stop_price=190, rate=200) api_mock.create_order.reset_mock() order = exchange.stoploss_limit(pair='ETH/BTC', amount=1, stop_price=220, rate=200) assert 'id' in order assert 'info' in order assert order['id'] == order_id assert api_mock.create_order.call_args[0][0] == 'ETH/BTC' assert api_mock.create_order.call_args[0][1] == order_type assert api_mock.create_order.call_args[0][2] == 'sell' assert api_mock.create_order.call_args[0][3] == 1 assert api_mock.create_order.call_args[0][4] == 200 assert api_mock.create_order.call_args[0][5] == {'stopPrice': 220} # test exception handling with pytest.raises(DependencyException): api_mock.create_order = MagicMock(side_effect=ccxt.InsufficientFunds("0 balance")) exchange = get_patched_exchange(mocker, default_conf, api_mock, 'binance') exchange.stoploss_limit(pair='ETH/BTC', amount=1, stop_price=220, rate=200) with pytest.raises(InvalidOrderException): api_mock.create_order = MagicMock( side_effect=ccxt.InvalidOrder("binance Order would trigger immediately.")) exchange = get_patched_exchange(mocker, default_conf, api_mock, 'binance') exchange.stoploss_limit(pair='ETH/BTC', amount=1, stop_price=220, rate=200) with pytest.raises(TemporaryError): api_mock.create_order = MagicMock(side_effect=ccxt.NetworkError("No connection")) exchange = get_patched_exchange(mocker, default_conf, api_mock, 'binance') exchange.stoploss_limit(pair='ETH/BTC', amount=1, stop_price=220, rate=200) with pytest.raises(OperationalException, match=r".*DeadBeef.*"): api_mock.create_order = MagicMock(side_effect=ccxt.BaseError("DeadBeef")) exchange = get_patched_exchange(mocker, default_conf, api_mock, 'binance') exchange.stoploss_limit(pair='ETH/BTC', amount=1, stop_price=220, rate=200)
def test_get_ticker(default_conf, mocker): api_mock = MagicMock() tick = { 'symbol': 'ETH/BTC', 'bid': 0.00001098, 'ask': 0.00001099, 'last': 0.0001, } api_mock.fetch_ticker = MagicMock(return_value=tick) exchange = get_patched_exchange(mocker, default_conf, api_mock) # retrieve original ticker ticker = exchange.get_ticker(pair='ETH/BTC') assert ticker['bid'] == 0.00001098 assert ticker['ask'] == 0.00001099 # change the ticker tick = { 'symbol': 'ETH/BTC', 'bid': 0.5, 'ask': 1, 'last': 42, } api_mock.fetch_ticker = MagicMock(return_value=tick) exchange = get_patched_exchange(mocker, default_conf, api_mock) # if not caching the result we should get the same ticker # if not fetching a new result we should get the cached ticker ticker = exchange.get_ticker(pair='ETH/BTC') assert api_mock.fetch_ticker.call_count == 1 assert ticker['bid'] == 0.5 assert ticker['ask'] == 1 assert 'ETH/BTC' in exchange._cached_ticker assert exchange._cached_ticker['ETH/BTC']['bid'] == 0.5 assert exchange._cached_ticker['ETH/BTC']['ask'] == 1 # Test caching api_mock.fetch_ticker = MagicMock() exchange.get_ticker(pair='ETH/BTC', refresh=False) assert api_mock.fetch_ticker.call_count == 0 ccxt_exceptionhandlers(mocker, default_conf, api_mock, "get_ticker", "fetch_ticker", pair='ETH/BTC', refresh=True) api_mock.fetch_ticker = MagicMock(return_value={}) exchange = get_patched_exchange(mocker, default_conf, api_mock) exchange.get_ticker(pair='ETH/BTC', refresh=True)
async def async_ccxt_exception(mocker, default_conf, api_mock, fun, mock_ccxt_fun, **kwargs): with pytest.raises(TemporaryError): api_mock.__dict__[mock_ccxt_fun] = MagicMock(side_effect=ccxt.NetworkError) exchange = get_patched_exchange(mocker, default_conf, api_mock) await getattr(exchange, fun)(**kwargs) assert api_mock.__dict__[mock_ccxt_fun].call_count == API_RETRY_COUNT + 1 with pytest.raises(OperationalException): api_mock.__dict__[mock_ccxt_fun] = MagicMock(side_effect=ccxt.BaseError) exchange = get_patched_exchange(mocker, default_conf, api_mock) await getattr(exchange, fun)(**kwargs) assert api_mock.__dict__[mock_ccxt_fun].call_count == 1
def test_exchange_has(default_conf, mocker): exchange = get_patched_exchange(mocker, default_conf) assert not exchange.exchange_has('ASDFASDF') api_mock = MagicMock() type(api_mock).has = PropertyMock(return_value={'deadbeef': True}) exchange = get_patched_exchange(mocker, default_conf, api_mock) assert exchange.exchange_has("deadbeef") type(api_mock).has = PropertyMock(return_value={'deadbeef': False}) exchange = get_patched_exchange(mocker, default_conf, api_mock) assert not exchange.exchange_has("deadbeef")
def test_get_trades_for_order(default_conf, mocker): order_id = 'ABCD-ABCD' since = datetime(2018, 5, 5) default_conf["dry_run"] = False mocker.patch('freqtrade.exchange.Exchange.exchange_has', return_value=True) api_mock = MagicMock() api_mock.fetch_my_trades = MagicMock(return_value=[{ 'id': 'TTR67E-3PFBD-76IISV', 'order': 'ABCD-ABCD', 'info': { 'pair': 'XLTCZBTC', 'time': 1519860024.4388, 'type': 'buy', 'ordertype': 'limit', 'price': '20.00000', 'cost': '38.62000', 'fee': '0.06179', 'vol': '5', 'id': 'ABCD-ABCD' }, 'timestamp': 1519860024438, 'datetime': '2018-02-28T23:20:24.438Z', 'symbol': 'LTC/BTC', 'type': 'limit', 'side': 'buy', 'price': 165.0, 'amount': 0.2340606, 'fee': { 'cost': 0.06179, 'currency': 'BTC' } }]) exchange = get_patched_exchange(mocker, default_conf, api_mock) orders = exchange.get_trades_for_order(order_id, 'LTC/BTC', since) assert len(orders) == 1 assert orders[0]['price'] == 165 # test Exceptions with pytest.raises(OperationalException): api_mock = MagicMock() api_mock.fetch_my_trades = MagicMock(side_effect=ccxt.BaseError) exchange = get_patched_exchange(mocker, default_conf, api_mock) exchange.get_trades_for_order(order_id, 'LTC/BTC', since) with pytest.raises(TemporaryError): api_mock = MagicMock() api_mock.fetch_my_trades = MagicMock(side_effect=ccxt.NetworkError) exchange = get_patched_exchange(mocker, default_conf, api_mock) exchange.get_trades_for_order(order_id, 'LTC/BTC', since) assert api_mock.fetch_my_trades.call_count == API_RETRY_COUNT + 1
def test_get_balance_prod(default_conf, mocker): api_mock = MagicMock() api_mock.fetch_balance = MagicMock(return_value={'BTC': {'free': 123.4}}) default_conf['dry_run'] = False exchange = get_patched_exchange(mocker, default_conf, api_mock) assert exchange.get_balance(currency='BTC') == 123.4 with pytest.raises(OperationalException): api_mock.fetch_balance = MagicMock(side_effect=ccxt.BaseError) exchange = get_patched_exchange(mocker, default_conf, api_mock) exchange.get_balance(currency='BTC')
def test_get_order_book_exception(default_conf, mocker): api_mock = MagicMock() with pytest.raises(OperationalException): api_mock.fetch_l2_order_book = MagicMock(side_effect=ccxt.NotSupported) exchange = get_patched_exchange(mocker, default_conf, api_mock) exchange.get_order_book(pair='ETH/BTC', limit=50) with pytest.raises(TemporaryError): api_mock.fetch_l2_order_book = MagicMock(side_effect=ccxt.NetworkError) exchange = get_patched_exchange(mocker, default_conf, api_mock) exchange.get_order_book(pair='ETH/BTC', limit=50) with pytest.raises(OperationalException): api_mock.fetch_l2_order_book = MagicMock(side_effect=ccxt.BaseError) exchange = get_patched_exchange(mocker, default_conf, api_mock) exchange.get_order_book(pair='ETH/BTC', limit=50)
def test_sell_dry_run(default_conf, mocker): default_conf['dry_run'] = True exchange = get_patched_exchange(mocker, default_conf) order = exchange.sell(pair='ETH/BTC', rate=200, amount=1) assert 'id' in order assert 'dry_run_sell_' in order['id']
async def test_async_get_candles_history(default_conf, mocker): tick = [ [ 1511686200000, # unix timestamp ms 1, # open 2, # high 3, # low 4, # close 5, # volume (in quote currency) ] ] async def mock_get_candle_hist(pair, tick_interval, since_ms=None): return (pair, tick) exchange = get_patched_exchange(mocker, default_conf) # Monkey-patch async function exchange._api_async.fetch_ohlcv = get_mock_coro(tick) exchange._async_get_candle_history = Mock(wraps=mock_get_candle_hist) pairs = ['ETH/BTC', 'XRP/BTC'] res = await exchange.async_get_candles_history(pairs, "5m") assert type(res) is list assert len(res) == 2 assert type(res[0]) is tuple assert res[0][0] == pairs[0] assert res[0][1] == tick assert res[1][0] == pairs[1] assert res[1][1] == tick assert exchange._async_get_candle_history.call_count == 2
def test_refresh_tickers(mocker, default_conf, caplog) -> None: tick = [ [ 1511686200000, # unix timestamp ms 1, # open 2, # high 3, # low 4, # close 5, # volume (in quote currency) ] ] caplog.set_level(logging.DEBUG) exchange = get_patched_exchange(mocker, default_conf) exchange._api_async.fetch_ohlcv = get_mock_coro(tick) pairs = ['IOTA/ETH', 'XRP/ETH'] # empty dicts assert not exchange.klines exchange.refresh_tickers(['IOTA/ETH', 'XRP/ETH'], '5m') assert log_has(f'Refreshing klines for {len(pairs)} pairs', caplog.record_tuples) assert exchange.klines for pair in pairs: assert exchange.klines[pair]
def test_load_data_with_new_pair_1min(ticker_history_list, mocker, caplog, default_conf) -> None: """ Test load_pair_history() with 1 min ticker """ mocker.patch('freqtrade.exchange.Exchange.get_history', return_value=ticker_history_list) exchange = get_patched_exchange(mocker, default_conf) file = os.path.join(os.path.dirname(__file__), '..', 'testdata', 'MEME_BTC-1m.json') _backup_file(file) # do not download a new pair if refresh_pairs isn't set history.load_pair_history(datadir=None, ticker_interval='1m', refresh_pairs=False, pair='MEME/BTC') assert os.path.isfile(file) is False assert log_has('No data for pair: "MEME/BTC", Interval: 1m. ' 'Use --refresh-pairs-cached to download the data', caplog.record_tuples) # download a new pair if refresh_pairs is set history.load_pair_history(datadir=None, ticker_interval='1m', refresh_pairs=True, exchange=exchange, pair='MEME/BTC') assert os.path.isfile(file) is True assert log_has('Download the pair: "MEME/BTC", Interval: 1m', caplog.record_tuples) with pytest.raises(OperationalException, match=r'Exchange needs to be initialized when.*'): history.load_pair_history(datadir=None, ticker_interval='1m', refresh_pairs=True, exchange=None, pair='MEME/BTC') _clean_test_file(file)
def test_ohlcv(mocker, default_conf, ticker_history): default_conf["runmode"] = RunMode.DRY_RUN tick_interval = default_conf["ticker_interval"] exchange = get_patched_exchange(mocker, default_conf) exchange._klines[("XRP/BTC", tick_interval)] = ticker_history exchange._klines[("UNITTEST/BTC", tick_interval)] = ticker_history dp = DataProvider(default_conf, exchange) assert dp.runmode == RunMode.DRY_RUN assert ticker_history.equals(dp.ohlcv("UNITTEST/BTC", tick_interval)) assert isinstance(dp.ohlcv("UNITTEST/BTC", tick_interval), DataFrame) assert dp.ohlcv("UNITTEST/BTC", tick_interval) is not ticker_history assert dp.ohlcv("UNITTEST/BTC", tick_interval, copy=False) is ticker_history assert not dp.ohlcv("UNITTEST/BTC", tick_interval).empty assert dp.ohlcv("NONESENSE/AAA", tick_interval).empty # Test with and without parameter assert dp.ohlcv("UNITTEST/BTC", tick_interval).equals(dp.ohlcv("UNITTEST/BTC")) default_conf["runmode"] = RunMode.LIVE dp = DataProvider(default_conf, exchange) assert dp.runmode == RunMode.LIVE assert isinstance(dp.ohlcv("UNITTEST/BTC", tick_interval), DataFrame) default_conf["runmode"] = RunMode.BACKTEST dp = DataProvider(default_conf, exchange) assert dp.runmode == RunMode.BACKTEST assert dp.ohlcv("UNITTEST/BTC", tick_interval).empty
def test_download_backtesting_testdata(ticker_history, mocker, default_conf) -> None: mocker.patch('freqtrade.exchange.Exchange.get_history', return_value=ticker_history) exchange = get_patched_exchange(mocker, default_conf) # Download a 1 min ticker file file1 = os.path.join(os.path.dirname(__file__), '..', 'testdata', 'XEL_BTC-1m.json') _backup_file(file1) download_backtesting_testdata(None, exchange, pair="XEL/BTC", tick_interval='1m') assert os.path.isfile(file1) is True _clean_test_file(file1) # Download a 5 min ticker file file2 = os.path.join(os.path.dirname(__file__), '..', 'testdata', 'STORJ_BTC-5m.json') _backup_file(file2) download_backtesting_testdata(None, exchange, pair="STORJ/BTC", tick_interval='5m') assert os.path.isfile(file2) is True _clean_test_file(file2)
def test_load_data_with_new_pair_1min(ticker_history, mocker, caplog, default_conf) -> None: """ Test load_data() with 1 min ticker """ mocker.patch('freqtrade.exchange.Exchange.get_history', return_value=ticker_history) exchange = get_patched_exchange(mocker, default_conf) file = os.path.join(os.path.dirname(__file__), '..', 'testdata', 'MEME_BTC-1m.json') _backup_file(file) # do not download a new pair if refresh_pairs isn't set optimize.load_data(None, ticker_interval='1m', refresh_pairs=False, pairs=['MEME/BTC']) assert os.path.isfile(file) is False assert log_has( 'No data for pair: "MEME/BTC", Interval: 1m. ' 'Use --refresh-pairs-cached to download the data', caplog.record_tuples) # download a new pair if refresh_pairs is set optimize.load_data(None, ticker_interval='1m', refresh_pairs=True, exchange=exchange, pairs=['MEME/BTC']) assert os.path.isfile(file) is True assert log_has('Download the pair: "MEME/BTC", Interval: 1m', caplog.record_tuples) _clean_test_file(file)
def test_refresh(mocker, default_conf, ticker_history): refresh_mock = MagicMock() mocker.patch("freqtrade.exchange.Exchange.refresh_latest_ohlcv", refresh_mock) exchange = get_patched_exchange(mocker, default_conf, id="binance") tick_interval = default_conf["ticker_interval"] pairs = [("XRP/BTC", tick_interval), ("UNITTEST/BTC", tick_interval)] pairs_non_trad = [("ETH/USDT", tick_interval), ("BTC/TUSD", "1h")] dp = DataProvider(default_conf, exchange) dp.refresh(pairs) assert refresh_mock.call_count == 1 assert len(refresh_mock.call_args[0]) == 1 assert len(refresh_mock.call_args[0][0]) == len(pairs) assert refresh_mock.call_args[0][0] == pairs refresh_mock.reset_mock() dp.refresh(pairs, pairs_non_trad) assert refresh_mock.call_count == 1 assert len(refresh_mock.call_args[0]) == 1 assert len( refresh_mock.call_args[0][0]) == len(pairs) + len(pairs_non_trad) assert refresh_mock.call_args[0][0] == pairs + pairs_non_trad
def test_get_history(default_conf, mocker, caplog): exchange = get_patched_exchange(mocker, default_conf) tick = [ [ arrow.utcnow().timestamp * 1000, # unix timestamp ms 1, # open 2, # high 3, # low 4, # close 5, # volume (in quote currency) ] ] pair = 'ETH/BTC' async def mock_candle_hist(pair, tick_interval, since_ms): return pair, tick exchange._async_get_candle_history = Mock(wraps=mock_candle_hist) # one_call calculation * 1.8 should do 2 calls since = 5 * 60 * 500 * 1.8 print(f"since = {since}") ret = exchange.get_history(pair, "5m", int((arrow.utcnow().timestamp - since) * 1000)) assert exchange._async_get_candle_history.call_count == 2 # Returns twice the above tick assert len(ret) == 2
def test_get_signal_handles_exceptions(mocker, default_conf): exchange = get_patched_exchange(mocker, default_conf) mocker.patch.object( _STRATEGY, 'analyze_ticker', side_effect=Exception('invalid ticker history ') ) assert _STRATEGY.get_signal(exchange, 'ETH/BTC', '5m') == (False, False)
def test_get_signal_handles_exceptions(mocker, default_conf): mocker.patch('freqtrade.exchange.Exchange.get_candle_history', return_value=MagicMock()) exchange = get_patched_exchange(mocker, default_conf) mocker.patch.object( _STRATEGY, 'analyze_ticker', side_effect=Exception('invalid ticker history ') ) assert _STRATEGY.get_signal(exchange, 'ETH/BTC', '5m') == (False, False)
def test_init(default_conf, mocker) -> None: exchange = get_patched_exchange(mocker, default_conf) assert {} == history.load_data( datadir='', exchange=exchange, pairs=[], refresh_pairs=True, ticker_interval=default_conf['ticker_interval'])
def test_get_tickers(default_conf, mocker): api_mock = MagicMock() tick = { 'ETH/BTC': { 'symbol': 'ETH/BTC', 'bid': 0.5, 'ask': 1, 'last': 42, }, 'BCH/BTC': { 'symbol': 'BCH/BTC', 'bid': 0.6, 'ask': 0.5, 'last': 41, } } api_mock.fetch_tickers = MagicMock(return_value=tick) exchange = get_patched_exchange(mocker, default_conf, api_mock) # retrieve original ticker tickers = exchange.get_tickers() assert 'ETH/BTC' in tickers assert 'BCH/BTC' in tickers assert tickers['ETH/BTC']['bid'] == 0.5 assert tickers['ETH/BTC']['ask'] == 1 assert tickers['BCH/BTC']['bid'] == 0.6 assert tickers['BCH/BTC']['ask'] == 0.5 with pytest.raises(TemporaryError): # test retrier api_mock.fetch_tickers = MagicMock(side_effect=ccxt.NetworkError) exchange = get_patched_exchange(mocker, default_conf, api_mock) exchange.get_tickers() with pytest.raises(OperationalException): api_mock.fetch_tickers = MagicMock(side_effect=ccxt.BaseError) exchange = get_patched_exchange(mocker, default_conf, api_mock) exchange.get_tickers() with pytest.raises(OperationalException): api_mock.fetch_tickers = MagicMock(side_effect=ccxt.NotSupported) exchange = get_patched_exchange(mocker, default_conf, api_mock) exchange.get_tickers() api_mock.fetch_tickers = MagicMock(return_value={}) exchange = get_patched_exchange(mocker, default_conf, api_mock) exchange.get_tickers()
def test_get_signal_empty(default_conf, mocker, caplog): caplog.set_level(logging.INFO) mocker.patch('freqtrade.exchange.Exchange.get_ticker_history', return_value=None) exchange = get_patched_exchange(mocker, default_conf) assert (False, False) == _ANALYZE.get_signal(exchange, 'foo', default_conf['ticker_interval']) assert log_has('Empty ticker history for pair foo', caplog.record_tuples)
def test_download_pair_history(ticker_history_list, mocker, default_conf) -> None: mocker.patch('freqtrade.exchange.Exchange.get_history', return_value=ticker_history_list) exchange = get_patched_exchange(mocker, default_conf) file1_1 = os.path.join(os.path.dirname(__file__), '..', 'testdata', 'MEME_BTC-1m.json') file1_5 = os.path.join(os.path.dirname(__file__), '..', 'testdata', 'MEME_BTC-5m.json') file2_1 = os.path.join(os.path.dirname(__file__), '..', 'testdata', 'CFI_BTC-1m.json') file2_5 = os.path.join(os.path.dirname(__file__), '..', 'testdata', 'CFI_BTC-5m.json') _backup_file(file1_1) _backup_file(file1_5) _backup_file(file2_1) _backup_file(file2_5) assert os.path.isfile(file1_1) is False assert os.path.isfile(file2_1) is False assert download_pair_history(datadir=None, exchange=exchange, pair='MEME/BTC', ticker_interval='1m') assert download_pair_history(datadir=None, exchange=exchange, pair='CFI/BTC', ticker_interval='1m') assert not exchange._pairs_last_refresh_time assert os.path.isfile(file1_1) is True assert os.path.isfile(file2_1) is True # clean files freshly downloaded _clean_test_file(file1_1) _clean_test_file(file2_1) assert os.path.isfile(file1_5) is False assert os.path.isfile(file2_5) is False assert download_pair_history(datadir=None, exchange=exchange, pair='MEME/BTC', ticker_interval='5m') assert download_pair_history(datadir=None, exchange=exchange, pair='CFI/BTC', ticker_interval='5m') assert not exchange._pairs_last_refresh_time assert os.path.isfile(file1_5) is True assert os.path.isfile(file2_5) is True # clean files freshly downloaded _clean_test_file(file1_5) _clean_test_file(file2_5)
def test_get_amount_lots(default_conf, mocker): api_mock = MagicMock() api_mock.amount_to_lots = MagicMock(return_value=1.0) api_mock.markets = None marketmock = MagicMock() api_mock.load_markets = marketmock exchange = get_patched_exchange(mocker, default_conf, api_mock) assert exchange.get_amount_lots('LTC/BTC', 1.54) == 1 assert marketmock.call_count == 1