diff --git a/build_helpers/TA_Lib-0.4.20-cp37-cp37m-win_amd64.whl b/build_helpers/TA_Lib-0.4.20-cp37-cp37m-win_amd64.whl deleted file mode 100644 index b4eee9c47..000000000 Binary files a/build_helpers/TA_Lib-0.4.20-cp37-cp37m-win_amd64.whl and /dev/null differ diff --git a/build_helpers/TA_Lib-0.4.20-cp38-cp38-win_amd64.whl b/build_helpers/TA_Lib-0.4.20-cp38-cp38-win_amd64.whl deleted file mode 100644 index de7393fde..000000000 Binary files a/build_helpers/TA_Lib-0.4.20-cp38-cp38-win_amd64.whl and /dev/null differ diff --git a/build_helpers/TA_Lib-0.4.21-cp37-cp37m-win_amd64.whl b/build_helpers/TA_Lib-0.4.21-cp37-cp37m-win_amd64.whl new file mode 100644 index 000000000..bccfd090f Binary files /dev/null and b/build_helpers/TA_Lib-0.4.21-cp37-cp37m-win_amd64.whl differ diff --git a/build_helpers/TA_Lib-0.4.21-cp38-cp38-win_amd64.whl b/build_helpers/TA_Lib-0.4.21-cp38-cp38-win_amd64.whl new file mode 100644 index 000000000..67b41bf99 Binary files /dev/null and b/build_helpers/TA_Lib-0.4.21-cp38-cp38-win_amd64.whl differ diff --git a/build_helpers/TA_Lib-0.4.21-cp39-cp39-win_amd64.whl b/build_helpers/TA_Lib-0.4.21-cp39-cp39-win_amd64.whl new file mode 100644 index 000000000..da9d74558 Binary files /dev/null and b/build_helpers/TA_Lib-0.4.21-cp39-cp39-win_amd64.whl differ diff --git a/build_helpers/install_windows.ps1 b/build_helpers/install_windows.ps1 index d2a27dd26..ec38ea212 100644 --- a/build_helpers/install_windows.ps1 +++ b/build_helpers/install_windows.ps1 @@ -6,10 +6,13 @@ python -m pip install --upgrade pip $pyv = python -c "import sys; print(f'{sys.version_info.major}.{sys.version_info.minor}')" if ($pyv -eq '3.7') { - pip install build_helpers\TA_Lib-0.4.20-cp37-cp37m-win_amd64.whl + pip install build_helpers\TA_Lib-0.4.21-cp37-cp37m-win_amd64.whl } if ($pyv -eq '3.8') { - pip install build_helpers\TA_Lib-0.4.20-cp38-cp38-win_amd64.whl + pip install build_helpers\TA_Lib-0.4.21-cp38-cp38-win_amd64.whl +} +if ($pyv -eq '3.9') { + pip install build_helpers\TA_Lib-0.4.21-cp39-cp39-win_amd64.whl } pip install -r requirements-dev.txt diff --git a/build_helpers/publish_docker_arm64.sh b/build_helpers/publish_docker_arm64.sh index 981b559c3..756d5e41d 100755 --- a/build_helpers/publish_docker_arm64.sh +++ b/build_helpers/publish_docker_arm64.sh @@ -42,7 +42,7 @@ docker build --cache-from freqtrade:${TAG_ARM} --build-arg sourceimage=${TAG_ARM docker tag freqtrade:$TAG_PLOT_ARM ${CACHE_IMAGE}:$TAG_PLOT_ARM # Run backtest -docker run --rm -v $(pwd)/config_bittrex.json.example:/freqtrade/config.json:ro -v $(pwd)/tests:/tests freqtrade:${TAG_ARM} backtesting --datadir /tests/testdata --strategy-path /tests/strategy/strats/ --strategy DefaultStrategy +docker run --rm -v $(pwd)/config_examples/config_bittrex.example.json:/freqtrade/config.json:ro -v $(pwd)/tests:/tests freqtrade:${TAG_ARM} backtesting --datadir /tests/testdata --strategy-path /tests/strategy/strats/ --strategy DefaultStrategy if [ $? -ne 0 ]; then echo "failed running backtest" diff --git a/docs/requirements-docs.txt b/docs/requirements-docs.txt index e346fe5a5..32a1df58e 100644 --- a/docs/requirements-docs.txt +++ b/docs/requirements-docs.txt @@ -1,4 +1,4 @@ -mkdocs==1.2.1 -mkdocs-material==7.1.10 +mkdocs==1.2.2 +mkdocs-material==7.1.11 mdx_truly_sane_lists==1.2 pymdown-extensions==8.2 diff --git a/docs/windows_installation.md b/docs/windows_installation.md index edc0a1404..2db0ae913 100644 --- a/docs/windows_installation.md +++ b/docs/windows_installation.md @@ -23,7 +23,7 @@ git clone https://github.com/freqtrade/freqtrade.git Install ta-lib according to the [ta-lib documentation](https://github.com/mrjbq7/ta-lib#windows). -As compiling from source on windows has heavy dependencies (requires a partial visual studio installation), there is also a repository of unofficial pre-compiled windows Wheels [here](https://www.lfd.uci.edu/~gohlke/pythonlibs/#ta-lib), which needs to be downloaded and installed using `pip install TA_Lib‑0.4.20‑cp38‑cp38‑win_amd64.whl` (make sure to use the version matching your python version). +As compiling from source on windows has heavy dependencies (requires a partial visual studio installation), there is also a repository of unofficial pre-compiled windows Wheels [here](https://www.lfd.uci.edu/~gohlke/pythonlibs/#ta-lib), which need to be downloaded and installed using `pip install TA_Lib-0.4.21-cp38-cp38-win_amd64.whl` (make sure to use the version matching your python version). Freqtrade provides these dependencies for the latest 2 Python versions (3.7 and 3.8) and for 64bit Windows. Other versions must be downloaded from the above link. diff --git a/freqtrade/exchange/exchange.py b/freqtrade/exchange/exchange.py index 42e86db3e..91b278077 100644 --- a/freqtrade/exchange/exchange.py +++ b/freqtrade/exchange/exchange.py @@ -551,7 +551,7 @@ class Exchange: amount_reserve_percent = 1.0 + self._config.get('amount_reserve_percent', DEFAULT_AMOUNT_RESERVE_PERCENT) amount_reserve_percent = ( - amount_reserve_percent / (1 - abs(stoploss)) if abs(stoploss) != 1 else 1.5 + amount_reserve_percent / (1 - abs(stoploss)) if abs(stoploss) != 1 else 1.5 ) # it should not be more than 50% amount_reserve_percent = max(min(amount_reserve_percent, 1.5), 1) @@ -999,94 +999,64 @@ class Exchange: except ccxt.BaseError as e: raise OperationalException(e) from e - def get_buy_rate(self, pair: str, refresh: bool) -> float: + def get_rate(self, pair: str, refresh: bool, side: str) -> float: """ - Calculates bid target between current ask price and last price + Calculates bid/ask target + bid rate - between current ask price and last price + ask rate - either using ticker bid or first bid based on orderbook + or remain static in any other case since it's not updating. :param pair: Pair to get rate for :param refresh: allow cached data + :param side: "buy" or "sell" :return: float: Price :raises PricingError if orderbook price could not be determined. """ + cache_rate: TTLCache = self._buy_rate_cache if side == "buy" else self._sell_rate_cache + [strat_name, name] = ['bid_strategy', 'Buy'] if side == "buy" else ['ask_strategy', 'Sell'] + if not refresh: - rate = self._buy_rate_cache.get(pair) + rate = cache_rate.get(pair) # Check if cache has been invalidated if rate: - logger.debug(f"Using cached buy rate for {pair}.") + logger.debug(f"Using cached {side} rate for {pair}.") return rate - bid_strategy = self._config.get('bid_strategy', {}) - if 'use_order_book' in bid_strategy and bid_strategy.get('use_order_book', False): + conf_strategy = self._config.get(strat_name, {}) - order_book_top = bid_strategy.get('order_book_top', 1) + if conf_strategy.get('use_order_book', False) and ('use_order_book' in conf_strategy): + + order_book_top = conf_strategy.get('order_book_top', 1) order_book = self.fetch_l2_order_book(pair, order_book_top) logger.debug('order_book %s', order_book) # top 1 = index 0 try: - rate_from_l2 = order_book[f"{bid_strategy['price_side']}s"][order_book_top - 1][0] + rate = order_book[f"{conf_strategy['price_side']}s"][order_book_top - 1][0] except (IndexError, KeyError) as e: logger.warning( - "Buy Price from orderbook could not be determined." - f"Orderbook: {order_book}" - ) - raise PricingError from e - logger.info(f"Buy price from orderbook {bid_strategy['price_side'].capitalize()} side " - f"- top {order_book_top} order book buy rate {rate_from_l2:.8f}") - used_rate = rate_from_l2 - else: - logger.info(f"Using Last {bid_strategy['price_side'].capitalize()} / Last Price") - ticker = self.fetch_ticker(pair) - ticker_rate = ticker[bid_strategy['price_side']] - if ticker['last'] and ticker_rate > ticker['last']: - balance = bid_strategy['ask_last_balance'] - ticker_rate = ticker_rate + balance * (ticker['last'] - ticker_rate) - used_rate = ticker_rate - - self._buy_rate_cache[pair] = used_rate - - return used_rate - - def get_sell_rate(self, pair: str, refresh: bool) -> float: - """ - Get sell rate - either using ticker bid or first bid based on orderbook - or remain static in any other case since it's not updating. - :param pair: Pair to get rate for - :param refresh: allow cached data - :return: Bid rate - :raises PricingError if price could not be determined. - """ - if not refresh: - rate = self._sell_rate_cache.get(pair) - # Check if cache has been invalidated - if rate: - logger.debug(f"Using cached sell rate for {pair}.") - return rate - - ask_strategy = self._config.get('ask_strategy', {}) - if ask_strategy.get('use_order_book', False): - logger.debug( - f"Getting price from order book {ask_strategy['price_side'].capitalize()} side." - ) - order_book_top = ask_strategy.get('order_book_top', 1) - order_book = self.fetch_l2_order_book(pair, order_book_top) - try: - rate = order_book[f"{ask_strategy['price_side']}s"][order_book_top - 1][0] - except (IndexError, KeyError) as e: - logger.warning( - f"Sell Price at location {order_book_top} from orderbook could not be " + f"{name} Price at location {order_book_top} from orderbook could not be " f"determined. Orderbook: {order_book}" ) raise PricingError from e + + logger.info(f"{name} price from orderbook {conf_strategy['price_side'].capitalize()}" + f"side - top {order_book_top} order book {side} rate {rate:.8f}") else: + logger.info(f"Using Last {conf_strategy['price_side'].capitalize()} / Last Price") ticker = self.fetch_ticker(pair) - ticker_rate = ticker[ask_strategy['price_side']] - if ticker['last'] and ticker_rate < ticker['last']: - balance = ask_strategy.get('bid_last_balance', 0.0) - ticker_rate = ticker_rate - balance * (ticker_rate - ticker['last']) + ticker_rate = ticker[conf_strategy['price_side']] + if ticker['last']: + if side == 'buy' and ticker_rate > ticker['last']: + balance = conf_strategy['ask_last_balance'] + ticker_rate = ticker_rate + balance * (ticker['last'] - ticker_rate) + elif side == 'sell' and ticker_rate < ticker['last']: + balance = conf_strategy.get('bid_last_balance', 0.0) + ticker_rate = ticker_rate - balance * (ticker_rate - ticker['last']) rate = ticker_rate if rate is None: - raise PricingError(f"Sell-Rate for {pair} was empty.") - self._sell_rate_cache[pair] = rate + raise PricingError(f"{name}-Rate for {pair} was empty.") + cache_rate[pair] = rate + return rate # Fee handling @@ -1318,8 +1288,8 @@ class Exchange: self._pairs_last_refresh_time[(pair, timeframe)] = ticks[-1][0] // 1000 # keeping parsed dataframe in cache ohlcv_df = ohlcv_to_dataframe( - ticks, timeframe, pair=pair, fill_missing=True, - drop_incomplete=self._ohlcv_partial_candle) + ticks, timeframe, pair=pair, fill_missing=True, + drop_incomplete=self._ohlcv_partial_candle) results_df[(pair, timeframe)] = ohlcv_df if cache: self._klines[(pair, timeframe)] = ohlcv_df diff --git a/freqtrade/freqtradebot.py b/freqtrade/freqtradebot.py index 5ef109387..d430dbc48 100644 --- a/freqtrade/freqtradebot.py +++ b/freqtrade/freqtradebot.py @@ -475,7 +475,7 @@ class FreqtradeBot(LoggingMixin): buy_limit_requested = price else: # Calculate price - buy_limit_requested = self.exchange.get_buy_rate(pair, True) + buy_limit_requested = self.exchange.get_rate(pair, refresh=True, side="buy") if not buy_limit_requested: raise PricingError('Could not determine buy price.') @@ -609,7 +609,7 @@ class FreqtradeBot(LoggingMixin): """ Sends rpc notification when a buy cancel occurred. """ - current_rate = self.exchange.get_buy_rate(trade.pair, False) + current_rate = self.exchange.get_rate(trade.pair, refresh=False, side="buy") msg = { 'trade_id': trade.id, @@ -695,7 +695,7 @@ class FreqtradeBot(LoggingMixin): (buy, sell) = self.strategy.get_signal(trade.pair, self.strategy.timeframe, analyzed_df) logger.debug('checking sell') - sell_rate = self.exchange.get_sell_rate(trade.pair, True) + sell_rate = self.exchange.get_rate(trade.pair, refresh=True, side="sell") if self._check_and_execute_sell(trade, sell_rate, buy, sell): return True @@ -1132,7 +1132,8 @@ class FreqtradeBot(LoggingMixin): profit_rate = trade.close_rate if trade.close_rate else trade.close_rate_requested profit_trade = trade.calc_profit(rate=profit_rate) # Use cached rates here - it was updated seconds ago. - current_rate = self.exchange.get_sell_rate(trade.pair, False) if not fill else None + current_rate = self.exchange.get_rate( + trade.pair, refresh=False, side="sell") if not fill else None profit_ratio = trade.calc_profit_ratio(profit_rate) gain = "profit" if profit_ratio > 0 else "loss" @@ -1177,7 +1178,7 @@ class FreqtradeBot(LoggingMixin): profit_rate = trade.close_rate if trade.close_rate else trade.close_rate_requested profit_trade = trade.calc_profit(rate=profit_rate) - current_rate = self.exchange.get_sell_rate(trade.pair, False) + current_rate = self.exchange.get_rate(trade.pair, refresh=False, side="sell") profit_ratio = trade.calc_profit_ratio(profit_rate) gain = "profit" if profit_ratio > 0 else "loss" diff --git a/freqtrade/rpc/rpc.py b/freqtrade/rpc/rpc.py index b3198fa1c..902975fde 100644 --- a/freqtrade/rpc/rpc.py +++ b/freqtrade/rpc/rpc.py @@ -154,7 +154,8 @@ class RPC: # calculate profit and send message to user if trade.is_open: try: - current_rate = self._freqtrade.exchange.get_sell_rate(trade.pair, False) + current_rate = self._freqtrade.exchange.get_rate( + trade.pair, refresh=False, side="sell") except (ExchangeError, PricingError): current_rate = NAN else: @@ -213,7 +214,8 @@ class RPC: for trade in trades: # calculate profit and send message to user try: - current_rate = self._freqtrade.exchange.get_sell_rate(trade.pair, False) + current_rate = self._freqtrade.exchange.get_rate( + trade.pair, refresh=False, side="sell") except (PricingError, ExchangeError): current_rate = NAN trade_percent = (100 * trade.calc_profit_ratio(current_rate)) @@ -272,10 +274,10 @@ class RPC: 'date': key, 'abs_profit': value["amount"], 'fiat_value': self._fiat_converter.convert_amount( - value['amount'], - stake_currency, - fiat_display_currency - ) if self._fiat_converter else 0, + value['amount'], + stake_currency, + fiat_display_currency + ) if self._fiat_converter else 0, 'trade_count': value["trades"], } for key, value in profit_days.items() @@ -372,7 +374,8 @@ class RPC: else: # Get current rate try: - current_rate = self._freqtrade.exchange.get_sell_rate(trade.pair, False) + current_rate = self._freqtrade.exchange.get_rate( + trade.pair, refresh=False, side="sell") except (PricingError, ExchangeError): current_rate = NAN profit_ratio = trade.calc_profit_ratio(rate=current_rate) @@ -551,7 +554,8 @@ class RPC: if not fully_canceled: # Get current rate and execute sell - current_rate = self._freqtrade.exchange.get_sell_rate(trade.pair, False) + current_rate = self._freqtrade.exchange.get_rate( + trade.pair, refresh=False, side="sell") sell_reason = SellCheckTuple(sell_type=SellType.FORCE_SELL) self._freqtrade.execute_sell(trade, current_rate, sell_reason) # ---- EOF def _exec_forcesell ---- diff --git a/requirements.txt b/requirements.txt index 08a04d5f5..8e26dfc6c 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,19 +1,19 @@ -numpy==1.21.0 +numpy==1.21.1 pandas==1.3.0 -ccxt==1.52.83 +ccxt==1.53.25 # Pin cryptography for now due to rust build errors with piwheels cryptography==3.4.7 aiohttp==3.7.4.post0 -SQLAlchemy==1.4.20 +SQLAlchemy==1.4.21 python-telegram-bot==13.7 arrow==1.1.1 cachetools==4.2.2 -requests==2.25.1 +requests==2.26.0 urllib3==1.26.6 wrapt==1.12.1 jsonschema==3.2.0 -TA-Lib==0.4.20 +TA-Lib==0.4.21 technical==1.3.0 tabulate==0.8.9 pycoingecko==2.2.0 @@ -39,5 +39,5 @@ aiofiles==0.7.0 # Support for colorized terminal output colorama==0.4.4 # Building config files interactively -questionary==1.9.0 +questionary==1.10.0 prompt-toolkit==3.0.19 diff --git a/setup.sh b/setup.sh index 3bcbfc48d..a85bd3104 100755 --- a/setup.sh +++ b/setup.sh @@ -4,8 +4,12 @@ function check_installed_pip() { ${PYTHON} -m pip > /dev/null if [ $? -ne 0 ]; then - echo "pip not found (called as '${PYTHON} -m pip'). Please make sure that pip is available for ${PYTHON}." - exit 1 + echo "-----------------------------" + echo "Installing Pip for ${PYTHON}" + echo "-----------------------------" + curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py + ${PYTHON} get-pip.py + rm get-pip.py fi } @@ -17,13 +21,12 @@ function check_installed_python() { exit 2 fi - for v in 8 9 7 + for v in 9 8 7 do PYTHON="python3.${v}" which $PYTHON if [ $? -eq 0 ]; then echo "using ${PYTHON}" - check_installed_pip return fi @@ -136,7 +139,7 @@ function install_macos() { /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)" fi #Gets number after decimal in python version - version=$(egrep -o 3.\[0-9\]+ <<< $PYTHON | sed 's/3.//g' ) + version=$(egrep -o 3.\[0-9\]+ <<< $PYTHON | sed 's/3.//g') if [[ $version -ge 9 ]]; then #Checks if python version >= 3.9 install_mac_newer_python_dependencies @@ -147,7 +150,7 @@ function install_macos() { # Install bot Debian_ubuntu function install_debian() { sudo apt-get update - sudo apt-get install -y build-essential autoconf libtool pkg-config make wget git libpython3-dev + sudo apt-get install -y build-essential autoconf libtool pkg-config make wget git $(echo lib${PYTHON}-dev ${PYTHON}-venv) install_talib } @@ -236,12 +239,12 @@ function install() { } function plot() { -echo " ------------------------------------------ -Installing dependencies for Plotting scripts ------------------------------------------ -" -${PYTHON} -m pip install plotly --upgrade + echo " + ----------------------------------------- + Installing dependencies for Plotting scripts + ----------------------------------------- + " + ${PYTHON} -m pip install plotly --upgrade } function help() { diff --git a/tests/exchange/test_exchange.py b/tests/exchange/test_exchange.py index 524dc873c..02adf01c4 100644 --- a/tests/exchange/test_exchange.py +++ b/tests/exchange/test_exchange.py @@ -1783,14 +1783,14 @@ def test_get_buy_rate(mocker, default_conf, caplog, side, ask, bid, mocker.patch('freqtrade.exchange.Exchange.fetch_ticker', return_value={'ask': ask, 'last': last, 'bid': bid}) - assert exchange.get_buy_rate('ETH/BTC', True) == expected + assert exchange.get_rate('ETH/BTC', refresh=True, side="buy") == expected assert not log_has("Using cached buy rate for ETH/BTC.", caplog) - assert exchange.get_buy_rate('ETH/BTC', False) == expected + assert exchange.get_rate('ETH/BTC', refresh=False, side="buy") == expected assert log_has("Using cached buy rate for ETH/BTC.", caplog) # Running a 2nd time with Refresh on! caplog.clear() - assert exchange.get_buy_rate('ETH/BTC', True) == expected + assert exchange.get_rate('ETH/BTC', refresh=True, side="buy") == expected assert not log_has("Using cached buy rate for ETH/BTC.", caplog) @@ -1825,12 +1825,12 @@ def test_get_sell_rate(default_conf, mocker, caplog, side, bid, ask, # Test regular mode exchange = get_patched_exchange(mocker, default_conf) - rate = exchange.get_sell_rate(pair, True) + rate = exchange.get_rate(pair, refresh=True, side="sell") assert not log_has("Using cached sell rate for ETH/BTC.", caplog) assert isinstance(rate, float) assert rate == expected # Use caching - rate = exchange.get_sell_rate(pair, False) + rate = exchange.get_rate(pair, refresh=False, side="sell") assert rate == expected assert log_has("Using cached sell rate for ETH/BTC.", caplog) @@ -1848,11 +1848,11 @@ def test_get_sell_rate_orderbook(default_conf, mocker, caplog, side, expected, o pair = "ETH/BTC" mocker.patch('freqtrade.exchange.Exchange.fetch_l2_order_book', order_book_l2) exchange = get_patched_exchange(mocker, default_conf) - rate = exchange.get_sell_rate(pair, True) + rate = exchange.get_rate(pair, refresh=True, side="sell") assert not log_has("Using cached sell rate for ETH/BTC.", caplog) assert isinstance(rate, float) assert rate == expected - rate = exchange.get_sell_rate(pair, False) + rate = exchange.get_rate(pair, refresh=False, side="sell") assert rate == expected assert log_has("Using cached sell rate for ETH/BTC.", caplog) @@ -1868,7 +1868,7 @@ def test_get_sell_rate_orderbook_exception(default_conf, mocker, caplog): return_value={'bids': [[]], 'asks': [[]]}) exchange = get_patched_exchange(mocker, default_conf) with pytest.raises(PricingError): - exchange.get_sell_rate(pair, True) + exchange.get_rate(pair, refresh=True, side="sell") assert log_has_re(r"Sell Price at location 1 from orderbook could not be determined\..*", caplog) @@ -1881,18 +1881,18 @@ def test_get_sell_rate_exception(default_conf, mocker, caplog): return_value={'ask': None, 'bid': 0.12, 'last': None}) exchange = get_patched_exchange(mocker, default_conf) with pytest.raises(PricingError, match=r"Sell-Rate for ETH/BTC was empty."): - exchange.get_sell_rate(pair, True) + exchange.get_rate(pair, refresh=True, side="sell") exchange._config['ask_strategy']['price_side'] = 'bid' - assert exchange.get_sell_rate(pair, True) == 0.12 + assert exchange.get_rate(pair, refresh=True, side="sell") == 0.12 # Reverse sides mocker.patch('freqtrade.exchange.Exchange.fetch_ticker', return_value={'ask': 0.13, 'bid': None, 'last': None}) with pytest.raises(PricingError, match=r"Sell-Rate for ETH/BTC was empty."): - exchange.get_sell_rate(pair, True) + exchange.get_rate(pair, refresh=True, side="sell") exchange._config['ask_strategy']['price_side'] = 'ask' - assert exchange.get_sell_rate(pair, True) == 0.13 + assert exchange.get_rate(pair, refresh=True, side="sell") == 0.13 def make_fetch_ohlcv_mock(data): @@ -2203,7 +2203,7 @@ def test_cancel_order_dry_run(default_conf, mocker, exchange_name): ({'status': 'canceled', 'filled': 10.0}, False), ({'status': 'unknown', 'filled': 10.0}, False), ({'result': 'testest123'}, False), - ]) +]) def test_check_order_canceled_empty(mocker, default_conf, exchange_name, order, result): exchange = get_patched_exchange(mocker, default_conf, id=exchange_name) assert exchange.check_order_canceled_empty(order) == result diff --git a/tests/rpc/test_rpc.py b/tests/rpc/test_rpc.py index 0049e59bb..fad24f9e2 100644 --- a/tests/rpc/test_rpc.py +++ b/tests/rpc/test_rpc.py @@ -109,7 +109,7 @@ def test_rpc_trade_status(default_conf, ticker, fee, mocker) -> None: 'exchange': 'binance', } - mocker.patch('freqtrade.exchange.Exchange.get_sell_rate', + mocker.patch('freqtrade.exchange.Exchange.get_rate', MagicMock(side_effect=ExchangeError("Pair 'ETH/BTC' not available"))) results = rpc._rpc_trade_status() assert isnan(results[0]['current_profit']) @@ -217,7 +217,7 @@ def test_rpc_status_table(default_conf, ticker, fee, mocker) -> None: assert '-0.41% (-0.06)' == result[0][3] assert '-0.06' == f'{fiat_profit_sum:.2f}' - mocker.patch('freqtrade.exchange.Exchange.get_sell_rate', + mocker.patch('freqtrade.exchange.Exchange.get_rate', MagicMock(side_effect=ExchangeError("Pair 'ETH/BTC' not available"))) result, headers, fiat_profit_sum = rpc._rpc_status_table(default_conf['stake_currency'], 'USD') assert 'instantly' == result[0][2] @@ -427,7 +427,7 @@ def test_rpc_trade_statistics(default_conf, ticker, ticker_sell_up, fee, assert prec_satoshi(stats['best_rate'], 6.2) # Test non-available pair - mocker.patch('freqtrade.exchange.Exchange.get_sell_rate', + mocker.patch('freqtrade.exchange.Exchange.get_rate', MagicMock(side_effect=ExchangeError("Pair 'ETH/BTC' not available"))) stats = rpc._rpc_trade_statistics(stake_currency, fiat_display_currency) assert stats['trade_count'] == 2 diff --git a/tests/rpc/test_rpc_apiserver.py b/tests/rpc/test_rpc_apiserver.py index eeb829719..921d8160d 100644 --- a/tests/rpc/test_rpc_apiserver.py +++ b/tests/rpc/test_rpc_apiserver.py @@ -879,7 +879,7 @@ def test_api_status(botclient, mocker, ticker, fee, markets): 'exchange': 'binance', } - mocker.patch('freqtrade.exchange.Exchange.get_sell_rate', + mocker.patch('freqtrade.exchange.Exchange.get_rate', MagicMock(side_effect=ExchangeError("Pair 'ETH/BTC' not available"))) rc = client_get(client, f"{BASE_URI}/status") diff --git a/tests/test_freqtradebot.py b/tests/test_freqtradebot.py index addf72bbb..4912a2a4d 100644 --- a/tests/test_freqtradebot.py +++ b/tests/test_freqtradebot.py @@ -161,7 +161,7 @@ def test_get_trade_stake_amount(default_conf, ticker, mocker) -> None: (True, 0.0022, 3, 0.5, [0.001, 0.001, 0.0]), (True, 0.0027, 3, 0.5, [0.001, 0.001, 0.000673]), (True, 0.0022, 3, 1, [0.001, 0.001, 0.0]), - ]) +]) def test_check_available_stake_amount(default_conf, ticker, mocker, fee, limit_buy_order_open, amend_last, wallet, max_open, lsamr, expected) -> None: patch_RPCManager(mocker) @@ -784,7 +784,7 @@ def test_execute_buy(mocker, default_conf, fee, limit_buy_order, limit_buy_order buy_mm = MagicMock(return_value=limit_buy_order_open) mocker.patch.multiple( 'freqtrade.exchange.Exchange', - get_buy_rate=buy_rate_mock, + get_rate=buy_rate_mock, fetch_ticker=MagicMock(return_value={ 'bid': 0.00001172, 'ask': 0.00001173, @@ -824,7 +824,7 @@ def test_execute_buy(mocker, default_conf, fee, limit_buy_order, limit_buy_order limit_buy_order_open['id'] = '33' fix_price = 0.06 assert freqtrade.execute_buy(pair, stake_amount, fix_price) - # Make sure get_buy_rate wasn't called again + # Make sure get_rate wasn't called again assert buy_rate_mock.call_count == 0 assert buy_mm.call_count == 2 @@ -893,7 +893,7 @@ def test_execute_buy(mocker, default_conf, fee, limit_buy_order, limit_buy_order assert not freqtrade.execute_buy(pair, stake_amount) # Fail to get price... - mocker.patch('freqtrade.exchange.Exchange.get_buy_rate', MagicMock(return_value=0.0)) + mocker.patch('freqtrade.exchange.Exchange.get_rate', MagicMock(return_value=0.0)) with pytest.raises(PricingError, match="Could not determine buy price."): freqtrade.execute_buy(pair, stake_amount) @@ -909,7 +909,7 @@ def test_execute_buy_confirm_error(mocker, default_conf, fee, limit_buy_order) - 'last': 0.00001172 }), buy=MagicMock(return_value=limit_buy_order), - get_buy_rate=MagicMock(return_value=0.11), + get_rate=MagicMock(return_value=0.11), get_min_pair_stake_amount=MagicMock(return_value=1), get_fee=fee, ) @@ -2513,7 +2513,7 @@ def test_handle_cancel_sell_limit(mocker, default_conf, fee) -> None: 'freqtrade.exchange.Exchange', cancel_order=cancel_order_mock, ) - mocker.patch('freqtrade.exchange.Exchange.get_sell_rate', return_value=0.245441) + mocker.patch('freqtrade.exchange.Exchange.get_rate', return_value=0.245441) freqtrade = FreqtradeBot(default_conf) @@ -3956,7 +3956,7 @@ def test_order_book_depth_of_market_high_delta(default_conf, ticker, limit_buy_o def test_order_book_bid_strategy1(mocker, default_conf, order_book_l2) -> None: """ - test if function get_buy_rate will return the order book price + test if function get_rate will return the order book price instead of the ask rate """ patch_exchange(mocker) @@ -3974,7 +3974,7 @@ def test_order_book_bid_strategy1(mocker, default_conf, order_book_l2) -> None: default_conf['telegram']['enabled'] = False freqtrade = FreqtradeBot(default_conf) - assert freqtrade.exchange.get_buy_rate('ETH/BTC', True) == 0.043935 + assert freqtrade.exchange.get_rate('ETH/BTC', refresh=True, side="buy") == 0.043935 assert ticker_mock.call_count == 0 @@ -3996,8 +3996,8 @@ def test_order_book_bid_strategy_exception(mocker, default_conf, caplog) -> None freqtrade = FreqtradeBot(default_conf) # orderbook shall be used even if tickers would be lower. with pytest.raises(PricingError): - freqtrade.exchange.get_buy_rate('ETH/BTC', refresh=True) - assert log_has_re(r'Buy Price from orderbook could not be determined.', caplog) + freqtrade.exchange.get_rate('ETH/BTC', refresh=True, side="buy") + assert log_has_re(r'Buy Price at location 1 from orderbook could not be determined.', caplog) def test_check_depth_of_market_buy(default_conf, mocker, order_book_l2) -> None: