Merge branch 'freqtrade:develop' into strategy_utils

This commit is contained in:
hippocritical
2023-03-03 18:56:00 +01:00
committed by GitHub
123 changed files with 1855 additions and 1721 deletions

View File

@@ -24,7 +24,7 @@ from freqtrade.enums import RunMode
from freqtrade.exceptions import OperationalException
from freqtrade.persistence.models import init_db
from freqtrade.persistence.pairlock_middleware import PairLocks
from tests.conftest import (CURRENT_TEST_STRATEGY, create_mock_trades, get_args, log_has,
from tests.conftest import (CURRENT_TEST_STRATEGY, EXMS, create_mock_trades, get_args, log_has,
log_has_re, patch_exchange, patched_configuration_load_config_file)
from tests.conftest_trades import MOCK_TRADE_COUNT
@@ -454,7 +454,7 @@ def test_list_markets(mocker, markets_static, capsys):
assert re.search(r"^BLK/BTC$", captured.out, re.MULTILINE)
assert re.search(r"^LTC/USD$", captured.out, re.MULTILINE)
mocker.patch('freqtrade.exchange.Exchange.markets', PropertyMock(side_effect=ValueError))
mocker.patch(f'{EXMS}.markets', PropertyMock(side_effect=ValueError))
# Test --one-column
args = [
"list-markets",
@@ -643,9 +643,7 @@ def test_download_data_keyboardInterrupt(mocker, markets):
dl_mock = mocker.patch('freqtrade.commands.data_commands.refresh_backtest_ohlcv_data',
MagicMock(side_effect=KeyboardInterrupt))
patch_exchange(mocker)
mocker.patch(
'freqtrade.exchange.Exchange.markets', PropertyMock(return_value=markets)
)
mocker.patch(f'{EXMS}.markets', PropertyMock(return_value=markets))
args = [
"download-data",
"--exchange", "binance",
@@ -664,9 +662,7 @@ def test_download_data_timerange(mocker, markets):
dl_mock = mocker.patch('freqtrade.commands.data_commands.refresh_backtest_ohlcv_data',
MagicMock(return_value=["ETH/BTC", "XRP/BTC"]))
patch_exchange(mocker)
mocker.patch(
'freqtrade.exchange.Exchange.markets', PropertyMock(return_value=markets)
)
mocker.patch(f'{EXMS}.markets', PropertyMock(return_value=markets))
args = [
"download-data",
"--exchange", "binance",
@@ -715,9 +711,7 @@ def test_download_data_no_markets(mocker, caplog):
dl_mock = mocker.patch('freqtrade.commands.data_commands.refresh_backtest_ohlcv_data',
MagicMock(return_value=["ETH/BTC", "XRP/BTC"]))
patch_exchange(mocker, id='binance')
mocker.patch(
'freqtrade.exchange.Exchange.markets', PropertyMock(return_value={})
)
mocker.patch(f'{EXMS}.markets', PropertyMock(return_value={}))
args = [
"download-data",
"--exchange", "binance",
@@ -733,9 +727,7 @@ def test_download_data_no_exchange(mocker, caplog):
mocker.patch('freqtrade.commands.data_commands.refresh_backtest_ohlcv_data',
MagicMock(return_value=["ETH/BTC", "XRP/BTC"]))
patch_exchange(mocker)
mocker.patch(
'freqtrade.exchange.Exchange.markets', PropertyMock(return_value={})
)
mocker.patch(f'{EXMS}.markets', PropertyMock(return_value={}))
args = [
"download-data",
]
@@ -751,9 +743,7 @@ def test_download_data_no_pairs(mocker):
mocker.patch('freqtrade.commands.data_commands.refresh_backtest_ohlcv_data',
MagicMock(return_value=["ETH/BTC", "XRP/BTC"]))
patch_exchange(mocker)
mocker.patch(
'freqtrade.exchange.Exchange.markets', PropertyMock(return_value={})
)
mocker.patch(f'{EXMS}.markets', PropertyMock(return_value={}))
args = [
"download-data",
"--exchange",
@@ -771,9 +761,7 @@ def test_download_data_all_pairs(mocker, markets):
dl_mock = mocker.patch('freqtrade.commands.data_commands.refresh_backtest_ohlcv_data',
MagicMock(return_value=["ETH/BTC", "XRP/BTC"]))
patch_exchange(mocker)
mocker.patch(
'freqtrade.exchange.Exchange.markets', PropertyMock(return_value=markets)
)
mocker.patch(f'{EXMS}.markets', PropertyMock(return_value=markets))
args = [
"download-data",
"--exchange",
@@ -810,9 +798,7 @@ def test_download_data_trades(mocker, caplog):
convert_mock = mocker.patch('freqtrade.commands.data_commands.convert_trades_to_ohlcv',
MagicMock(return_value=[]))
patch_exchange(mocker)
mocker.patch(
'freqtrade.exchange.Exchange.markets', PropertyMock(return_value={})
)
mocker.patch(f'{EXMS}.markets', PropertyMock(return_value={}))
args = [
"download-data",
"--exchange", "kraken",
@@ -843,9 +829,7 @@ def test_download_data_trades(mocker, caplog):
def test_download_data_data_invalid(mocker):
patch_exchange(mocker, id="kraken")
mocker.patch(
'freqtrade.exchange.Exchange.markets', PropertyMock(return_value={})
)
mocker.patch(f'{EXMS}.markets', PropertyMock(return_value={}))
args = [
"download-data",
"--exchange", "kraken",
@@ -862,9 +846,7 @@ def test_start_convert_trades(mocker, caplog):
convert_mock = mocker.patch('freqtrade.commands.data_commands.convert_trades_to_ohlcv',
MagicMock(return_value=[]))
patch_exchange(mocker)
mocker.patch(
'freqtrade.exchange.Exchange.markets', PropertyMock(return_value={})
)
mocker.patch(f'{EXMS}.markets', PropertyMock(return_value={}))
args = [
"trades-to-ohlcv",
"--exchange", "kraken",
@@ -971,7 +953,7 @@ def test_start_list_freqAI_models(capsys):
def test_start_test_pairlist(mocker, caplog, tickers, default_conf, capsys):
patch_exchange(mocker, mock_markets=True)
mocker.patch.multiple('freqtrade.exchange.Exchange',
mocker.patch.multiple(EXMS,
exchange_has=MagicMock(return_value=True),
get_tickers=tickers,
)

View File

@@ -40,6 +40,7 @@ np.seterr(all='raise')
CURRENT_TEST_STRATEGY = 'StrategyTestV3'
TRADE_SIDES = ('long', 'short')
EXMS = 'freqtrade.exchange.exchange.Exchange'
def pytest_addoption(parser):
@@ -145,22 +146,21 @@ def patch_exchange(
mock_markets=True,
mock_supported_modes=True
) -> None:
mocker.patch('freqtrade.exchange.Exchange._load_async_markets', MagicMock(return_value={}))
mocker.patch('freqtrade.exchange.Exchange.validate_config', MagicMock())
mocker.patch('freqtrade.exchange.Exchange.validate_timeframes', MagicMock())
mocker.patch('freqtrade.exchange.Exchange.id', PropertyMock(return_value=id))
mocker.patch('freqtrade.exchange.Exchange.name', PropertyMock(return_value=id.title()))
mocker.patch('freqtrade.exchange.Exchange.precisionMode', PropertyMock(return_value=2))
mocker.patch(f'{EXMS}._load_async_markets', return_value={})
mocker.patch(f'{EXMS}.validate_config', MagicMock())
mocker.patch(f'{EXMS}.validate_timeframes', MagicMock())
mocker.patch(f'{EXMS}.id', PropertyMock(return_value=id))
mocker.patch(f'{EXMS}.name', PropertyMock(return_value=id.title()))
mocker.patch(f'{EXMS}.precisionMode', PropertyMock(return_value=2))
if mock_markets:
if isinstance(mock_markets, bool):
mock_markets = get_markets()
mocker.patch('freqtrade.exchange.Exchange.markets',
PropertyMock(return_value=mock_markets))
mocker.patch(f'{EXMS}.markets', PropertyMock(return_value=mock_markets))
if mock_supported_modes:
mocker.patch(
f'freqtrade.exchange.{id.capitalize()}._supported_trading_mode_margin_pairs',
f'freqtrade.exchange.{id}.{id.capitalize()}._supported_trading_mode_margin_pairs',
PropertyMock(return_value=[
(TradingMode.MARGIN, MarginMode.CROSS),
(TradingMode.MARGIN, MarginMode.ISOLATED),
@@ -170,10 +170,10 @@ def patch_exchange(
)
if api_mock:
mocker.patch('freqtrade.exchange.Exchange._init_ccxt', MagicMock(return_value=api_mock))
mocker.patch(f'{EXMS}._init_ccxt', return_value=api_mock)
else:
mocker.patch('freqtrade.exchange.Exchange._init_ccxt', MagicMock())
mocker.patch('freqtrade.exchange.Exchange.timeframes', PropertyMock(
mocker.patch(f'{EXMS}._init_ccxt', MagicMock())
mocker.patch(f'{EXMS}.timeframes', PropertyMock(
return_value=['5m', '15m', '1h', '1d']))
@@ -2573,7 +2573,7 @@ def import_fails() -> None:
realimport = builtins.__import__
def mockedimport(name, *args, **kwargs):
if name in ["filelock", 'systemd.journal', 'uvloop']:
if name in ["filelock", 'cysystemd.journal', 'uvloop']:
raise ImportError(f"No module named '{name}'")
return realimport(name, *args, **kwargs)

View File

@@ -8,7 +8,7 @@ from freqtrade.data.dataprovider import DataProvider
from freqtrade.enums import CandleType, RunMode
from freqtrade.exceptions import ExchangeError, OperationalException
from freqtrade.plugins.pairlistmanager import PairListManager
from tests.conftest import generate_test_data, get_patched_exchange
from tests.conftest import EXMS, generate_test_data, get_patched_exchange
@pytest.mark.parametrize('candle_type', [
@@ -223,7 +223,7 @@ def test_emit_df(mocker, default_conf, ohlcv_history):
def test_refresh(mocker, default_conf):
refresh_mock = MagicMock()
mocker.patch("freqtrade.exchange.Exchange.refresh_latest_ohlcv", refresh_mock)
mocker.patch(f"{EXMS}.refresh_latest_ohlcv", refresh_mock)
exchange = get_patched_exchange(mocker, default_conf, id="binance")
timeframe = default_conf["timeframe"]
@@ -281,7 +281,7 @@ def test_market(mocker, default_conf, markets):
def test_ticker(mocker, default_conf, tickers):
ticker_mock = MagicMock(return_value=tickers()['ETH/BTC'])
mocker.patch("freqtrade.exchange.Exchange.fetch_ticker", ticker_mock)
mocker.patch(f"{EXMS}.fetch_ticker", ticker_mock)
exchange = get_patched_exchange(mocker, default_conf)
dp = DataProvider(default_conf, exchange)
res = dp.ticker('ETH/BTC')
@@ -290,7 +290,7 @@ def test_ticker(mocker, default_conf, tickers):
assert res['symbol'] == 'ETH/BTC'
ticker_mock = MagicMock(side_effect=ExchangeError('Pair not found'))
mocker.patch("freqtrade.exchange.Exchange.fetch_ticker", ticker_mock)
mocker.patch(f"{EXMS}.fetch_ticker", ticker_mock)
exchange = get_patched_exchange(mocker, default_conf)
dp = DataProvider(default_conf, exchange)
res = dp.ticker('UNITTEST/BTC')
@@ -301,7 +301,7 @@ def test_current_whitelist(mocker, default_conf, tickers):
# patch default conf to volumepairlist
default_conf['pairlists'][0] = {'method': 'VolumePairList', "number_assets": 5}
mocker.patch.multiple('freqtrade.exchange.Exchange',
mocker.patch.multiple(EXMS,
exchange_has=MagicMock(return_value=True),
get_tickers=tickers)
exchange = get_patched_exchange(mocker, default_conf)

0
tests/data/test_entryexitanalysis.py Executable file → Normal file
View File

View File

@@ -26,7 +26,7 @@ from freqtrade.enums import CandleType
from freqtrade.exchange import timeframe_to_minutes
from freqtrade.misc import file_dump_json
from freqtrade.resolvers import StrategyResolver
from tests.conftest import (CURRENT_TEST_STRATEGY, get_patched_exchange, log_has, log_has_re,
from tests.conftest import (CURRENT_TEST_STRATEGY, EXMS, get_patched_exchange, log_has, log_has_re,
patch_exchange)
@@ -66,7 +66,7 @@ def test_load_data_7min_timeframe(caplog, testdatadir) -> None:
def test_load_data_1min_timeframe(ohlcv_history, mocker, caplog, testdatadir) -> None:
mocker.patch('freqtrade.exchange.Exchange.get_historic_ohlcv', return_value=ohlcv_history)
mocker.patch(f'{EXMS}.get_historic_ohlcv', return_value=ohlcv_history)
file = testdatadir / 'UNITTEST_BTC-1m.json'
load_data(datadir=testdatadir, timeframe='1m', pairs=['UNITTEST/BTC'])
assert file.is_file()
@@ -77,7 +77,7 @@ def test_load_data_1min_timeframe(ohlcv_history, mocker, caplog, testdatadir) ->
def test_load_data_mark(ohlcv_history, mocker, caplog, testdatadir) -> None:
mocker.patch('freqtrade.exchange.Exchange.get_historic_ohlcv', return_value=ohlcv_history)
mocker.patch(f'{EXMS}.get_historic_ohlcv', return_value=ohlcv_history)
file = testdatadir / 'futures/UNITTEST_USDT_USDT-1h-mark.json'
load_data(datadir=testdatadir, timeframe='1h', pairs=['UNITTEST/BTC'], candle_type='mark')
assert file.is_file()
@@ -109,7 +109,7 @@ def test_load_data_with_new_pair_1min(ohlcv_history_list, mocker, caplog,
Test load_pair_history() with 1 min timeframe
"""
tmpdir1 = Path(tmpdir)
mocker.patch('freqtrade.exchange.Exchange.get_historic_ohlcv', return_value=ohlcv_history_list)
mocker.patch(f'{EXMS}.get_historic_ohlcv', return_value=ohlcv_history_list)
exchange = get_patched_exchange(mocker, default_conf)
file = tmpdir1 / 'MEME_BTC-1m.json'
@@ -191,7 +191,7 @@ def test_load_cached_data_for_updating(mocker, testdatadir) -> None:
test_data = None
test_filename = testdatadir.joinpath('UNITTEST_BTC-1m.json')
with open(test_filename, "rt") as file:
with test_filename.open("rt") as file:
test_data = json.load(file)
test_data_df = ohlcv_to_dataframe(test_data, '1m', 'UNITTEST/BTC',
@@ -277,7 +277,7 @@ def test_download_pair_history(
subdir,
file_tail
) -> None:
mocker.patch('freqtrade.exchange.Exchange.get_historic_ohlcv', return_value=ohlcv_history_list)
mocker.patch(f'{EXMS}.get_historic_ohlcv', return_value=ohlcv_history_list)
exchange = get_patched_exchange(mocker, default_conf)
tmpdir1 = Path(tmpdir)
file1_1 = tmpdir1 / f'{subdir}MEME_BTC-1m{file_tail}.json'
@@ -328,7 +328,7 @@ def test_download_pair_history2(mocker, default_conf, testdatadir) -> None:
json_dump_mock = mocker.patch(
'freqtrade.data.history.jsondatahandler.JsonDataHandler.ohlcv_store',
return_value=None)
mocker.patch('freqtrade.exchange.Exchange.get_historic_ohlcv', return_value=tick)
mocker.patch(f'{EXMS}.get_historic_ohlcv', return_value=tick)
exchange = get_patched_exchange(mocker, default_conf)
_download_pair_history(datadir=testdatadir, exchange=exchange, pair="UNITTEST/BTC",
timeframe='1m', candle_type='spot')
@@ -340,7 +340,7 @@ def test_download_pair_history2(mocker, default_conf, testdatadir) -> None:
def test_download_backtesting_data_exception(mocker, caplog, default_conf, tmpdir) -> None:
mocker.patch('freqtrade.exchange.Exchange.get_historic_ohlcv',
mocker.patch(f'{EXMS}.get_historic_ohlcv',
side_effect=Exception('File Error'))
tmpdir1 = Path(tmpdir)
exchange = get_patched_exchange(mocker, default_conf)
@@ -506,9 +506,7 @@ def test_refresh_backtest_ohlcv_data(
mocker, default_conf, markets, caplog, testdatadir, trademode, callcount):
dl_mock = mocker.patch('freqtrade.data.history.history_utils._download_pair_history',
MagicMock())
mocker.patch(
'freqtrade.exchange.Exchange.markets', PropertyMock(return_value=markets)
)
mocker.patch(f'{EXMS}.markets', PropertyMock(return_value=markets))
mocker.patch.object(Path, "exists", MagicMock(return_value=True))
mocker.patch.object(Path, "unlink", MagicMock())
@@ -531,9 +529,7 @@ def test_download_data_no_markets(mocker, default_conf, caplog, testdatadir):
MagicMock())
ex = get_patched_exchange(mocker, default_conf)
mocker.patch(
'freqtrade.exchange.Exchange.markets', PropertyMock(return_value={})
)
mocker.patch(f'{EXMS}.markets', PropertyMock(return_value={}))
timerange = TimeRange.parse_timerange("20190101-20190102")
unav_pairs = refresh_backtest_ohlcv_data(exchange=ex, pairs=["BTT/BTC", "LTC/USDT"],
timeframes=["1m", "5m"],
@@ -551,9 +547,7 @@ def test_download_data_no_markets(mocker, default_conf, caplog, testdatadir):
def test_refresh_backtest_trades_data(mocker, default_conf, markets, caplog, testdatadir):
dl_mock = mocker.patch('freqtrade.data.history.history_utils._download_trades_history',
MagicMock())
mocker.patch(
'freqtrade.exchange.Exchange.markets', PropertyMock(return_value=markets)
)
mocker.patch(f'{EXMS}.markets', PropertyMock(return_value=markets))
mocker.patch.object(Path, "exists", MagicMock(return_value=True))
mocker.patch.object(Path, "unlink", MagicMock())
@@ -577,8 +571,7 @@ def test_download_trades_history(trades_history, mocker, default_conf, testdatad
tmpdir) -> None:
tmpdir1 = Path(tmpdir)
ght_mock = MagicMock(side_effect=lambda pair, *args, **kwargs: (pair, trades_history))
mocker.patch('freqtrade.exchange.Exchange.get_historic_trades',
ght_mock)
mocker.patch(f'{EXMS}.get_historic_trades', ght_mock)
exchange = get_patched_exchange(mocker, default_conf)
file1 = tmpdir1 / 'ETH_BTC-trades.json.gz'
data_handler = get_datahandler(tmpdir1, data_format='jsongz')
@@ -604,8 +597,7 @@ def test_download_trades_history(trades_history, mocker, default_conf, testdatad
file1.unlink()
mocker.patch('freqtrade.exchange.Exchange.get_historic_trades',
MagicMock(side_effect=ValueError))
mocker.patch(f'{EXMS}.get_historic_trades', MagicMock(side_effect=ValueError))
assert not _download_trades_history(data_handler=data_handler, exchange=exchange,
pair='ETH/BTC')
@@ -615,8 +607,7 @@ def test_download_trades_history(trades_history, mocker, default_conf, testdatad
copyfile(testdatadir / file2.name, file2)
ght_mock.reset_mock()
mocker.patch('freqtrade.exchange.Exchange.get_historic_trades',
ght_mock)
mocker.patch(f'{EXMS}.get_historic_trades', ght_mock)
# Since before first start date
since_time = int(trades_history[0][0] // 1000) - 500
timerange = TimeRange('date', None, since_time, 0)

View File

@@ -14,7 +14,7 @@ from freqtrade.data.converter import ohlcv_to_dataframe
from freqtrade.edge import Edge, PairInfo
from freqtrade.enums import ExitType
from freqtrade.exceptions import OperationalException
from tests.conftest import get_patched_freqtradebot, log_has
from tests.conftest import EXMS, get_patched_freqtradebot, log_has
from tests.optimize import (BTContainer, BTrade, _build_backtest_dataframe,
_get_frame_time_from_offset)
@@ -261,7 +261,7 @@ def mocked_load_data(datadir, pairs=[], timeframe='0m',
def test_edge_process_downloaded_data(mocker, edge_conf):
freqtrade = get_patched_freqtradebot(mocker, edge_conf)
mocker.patch('freqtrade.exchange.Exchange.get_fee', MagicMock(return_value=0.001))
mocker.patch(f'{EXMS}.get_fee', MagicMock(return_value=0.001))
mocker.patch('freqtrade.edge.edge_positioning.refresh_data', MagicMock())
mocker.patch('freqtrade.edge.edge_positioning.load_data', mocked_load_data)
edge = Edge(edge_conf, freqtrade.exchange, freqtrade.strategy)
@@ -273,7 +273,7 @@ def test_edge_process_downloaded_data(mocker, edge_conf):
def test_edge_process_no_data(mocker, edge_conf, caplog):
freqtrade = get_patched_freqtradebot(mocker, edge_conf)
mocker.patch('freqtrade.exchange.Exchange.get_fee', MagicMock(return_value=0.001))
mocker.patch(f'{EXMS}.get_fee', MagicMock(return_value=0.001))
mocker.patch('freqtrade.edge.edge_positioning.refresh_data', MagicMock())
mocker.patch('freqtrade.edge.edge_positioning.load_data', MagicMock(return_value={}))
edge = Edge(edge_conf, freqtrade.exchange, freqtrade.strategy)
@@ -286,7 +286,7 @@ def test_edge_process_no_data(mocker, edge_conf, caplog):
def test_edge_process_no_trades(mocker, edge_conf, caplog):
freqtrade = get_patched_freqtradebot(mocker, edge_conf)
mocker.patch('freqtrade.exchange.Exchange.get_fee', return_value=0.001)
mocker.patch(f'{EXMS}.get_fee', return_value=0.001)
mocker.patch('freqtrade.edge.edge_positioning.refresh_data', )
mocker.patch('freqtrade.edge.edge_positioning.load_data', mocked_load_data)
# Return empty
@@ -303,7 +303,7 @@ def test_edge_process_no_pairs(mocker, edge_conf, caplog):
mocker.patch('freqtrade.freqtradebot.validate_config_consistency')
freqtrade = get_patched_freqtradebot(mocker, edge_conf)
fee_mock = mocker.patch('freqtrade.exchange.Exchange.get_fee', return_value=0.001)
fee_mock = mocker.patch(f'{EXMS}.get_fee', return_value=0.001)
mocker.patch('freqtrade.edge.edge_positioning.refresh_data')
mocker.patch('freqtrade.edge.edge_positioning.load_data', mocked_load_data)
# Return empty
@@ -319,7 +319,7 @@ def test_edge_process_no_pairs(mocker, edge_conf, caplog):
def test_edge_init_error(mocker, edge_conf,):
edge_conf['stake_amount'] = 0.5
mocker.patch('freqtrade.exchange.Exchange.get_fee', MagicMock(return_value=0.001))
mocker.patch(f'{EXMS}.get_fee', MagicMock(return_value=0.001))
with pytest.raises(OperationalException, match='Edge works only with unlimited stake amount'):
get_patched_freqtradebot(mocker, edge_conf)

View File

@@ -7,7 +7,7 @@ import pytest
from freqtrade.enums import CandleType, MarginMode, TradingMode
from freqtrade.exceptions import DependencyException, InvalidOrderException, OperationalException
from tests.conftest import get_mock_coro, get_patched_exchange, log_has_re
from tests.conftest import EXMS, get_mock_coro, get_patched_exchange, log_has_re
from tests.exchange.test_exchange import ccxt_exceptionhandlers
@@ -34,8 +34,8 @@ def test_create_stoploss_order_binance(default_conf, mocker, limitratio, expecte
default_conf['dry_run'] = False
default_conf['margin_mode'] = MarginMode.ISOLATED
default_conf['trading_mode'] = trademode
mocker.patch('freqtrade.exchange.Exchange.amount_to_precision', lambda s, x, y: y)
mocker.patch('freqtrade.exchange.Exchange.price_to_precision', lambda s, x, y: y)
mocker.patch(f'{EXMS}.amount_to_precision', lambda s, x, y: y)
mocker.patch(f'{EXMS}.price_to_precision', lambda s, x, y: y)
exchange = get_patched_exchange(mocker, default_conf, api_mock, 'binance')
@@ -113,8 +113,8 @@ def test_create_stoploss_order_dry_run_binance(default_conf, mocker):
api_mock = MagicMock()
order_type = 'stop_loss_limit'
default_conf['dry_run'] = True
mocker.patch('freqtrade.exchange.Exchange.amount_to_precision', lambda s, x, y: y)
mocker.patch('freqtrade.exchange.Exchange.price_to_precision', lambda s, x, y: y)
mocker.patch(f'{EXMS}.amount_to_precision', lambda s, x, y: y)
mocker.patch(f'{EXMS}.price_to_precision', lambda s, x, y: y)
exchange = get_patched_exchange(mocker, default_conf, api_mock, 'binance')
@@ -600,7 +600,7 @@ def test_get_maintenance_ratio_and_amt_binance(
mm_ratio,
amt,
):
mocker.patch('freqtrade.exchange.Exchange.exchange_has', return_value=True)
mocker.patch(f'{EXMS}.exchange_has', return_value=True)
exchange = get_patched_exchange(mocker, default_conf, id="binance")
exchange._leverage_tiers = leverage_tiers
(result_ratio, result_amt) = exchange.get_maintenance_ratio_and_amt(pair, nominal_value)

View File

@@ -1,7 +1,7 @@
from datetime import datetime
from unittest.mock import MagicMock
from tests.conftest import get_patched_exchange
from tests.conftest import EXMS, get_patched_exchange
def test_get_trades_for_order(default_conf, mocker):
@@ -9,7 +9,7 @@ def test_get_trades_for_order(default_conf, mocker):
order_id = 'ABCD-ABCD'
since = datetime(2018, 5, 5, 0, 0, 0)
default_conf["dry_run"] = False
mocker.patch('freqtrade.exchange.Exchange.exchange_has', return_value=True)
mocker.patch(f'{EXMS}.exchange_has', return_value=True)
api_mock = MagicMock()
api_mock.fetch_my_trades = MagicMock(return_value=[{'id': 'TTR67E-3PFBD-76IISV',

View File

@@ -1,3 +1,4 @@
from datetime import datetime, timezone
from unittest.mock import MagicMock
from freqtrade.enums.marginmode import MarginMode
@@ -55,3 +56,19 @@ async def test_bybit_fetch_funding_rate(default_conf, mocker):
kwargs = api_mock.fetch_funding_rate_history.call_args_list[0][1]
assert kwargs['params'] == {'until': since_ms_end}
assert kwargs['since'] == since_ms
def test_bybit_get_funding_fees(default_conf, mocker):
now = datetime.now(timezone.utc)
exchange = get_patched_exchange(mocker, default_conf, id='bybit')
exchange._fetch_and_calculate_funding_fees = MagicMock()
exchange.get_funding_fees('BTC/USDT:USDT', 1, False, now)
assert exchange._fetch_and_calculate_funding_fees.call_count == 0
default_conf['trading_mode'] = 'futures'
default_conf['margin_mode'] = 'isolated'
exchange = get_patched_exchange(mocker, default_conf, id='bybit')
exchange._fetch_and_calculate_funding_fees = MagicMock()
exchange.get_funding_fees('BTC/USDT:USDT', 1, False, now)
assert exchange._fetch_and_calculate_funding_fees.call_count == 1

View File

@@ -17,7 +17,7 @@ from freqtrade.enums import CandleType
from freqtrade.exchange import timeframe_to_minutes, timeframe_to_prev_date
from freqtrade.exchange.exchange import Exchange, timeframe_to_msecs
from freqtrade.resolvers.exchange_resolver import ExchangeResolver
from tests.conftest import get_default_conf_usdt
from tests.conftest import EXMS, get_default_conf_usdt
EXCHANGE_FIXTURE_TYPE = Tuple[Exchange, str]
@@ -309,7 +309,7 @@ def exchange(request, exchange_conf):
@pytest.fixture(params=EXCHANGES, scope="class")
def exchange_futures(request, exchange_conf, class_mocker):
if not EXCHANGES[request.param].get('futures') is True:
if EXCHANGES[request.param].get('futures') is not True:
yield None, request.param
else:
exchange_conf = set_test_proxy(
@@ -322,13 +322,12 @@ def exchange_futures(request, exchange_conf, class_mocker):
class_mocker.patch(
'freqtrade.exchange.binance.Binance.fill_leverage_tiers')
class_mocker.patch('freqtrade.exchange.exchange.Exchange.fetch_trading_fees')
class_mocker.patch(f'{EXMS}.fetch_trading_fees')
class_mocker.patch('freqtrade.exchange.okx.Okx.additional_exchange_init')
class_mocker.patch('freqtrade.exchange.binance.Binance.additional_exchange_init')
class_mocker.patch('freqtrade.exchange.bybit.Bybit.additional_exchange_init')
class_mocker.patch('freqtrade.exchange.exchange.Exchange.load_cached_leverage_tiers',
return_value=None)
class_mocker.patch('freqtrade.exchange.exchange.Exchange.cache_leverage_tiers')
class_mocker.patch(f'{EXMS}.load_cached_leverage_tiers', return_value=None)
class_mocker.patch(f'{EXMS}.cache_leverage_tiers')
exchange = ExchangeResolver.load_exchange(
request.param, exchange_conf, validate=True, load_leverage_tiers=True)

File diff suppressed because it is too large Load Diff

View File

@@ -7,18 +7,18 @@ from freqtrade.enums import MarginMode, TradingMode
from freqtrade.exceptions import OperationalException
from freqtrade.exchange import Gate
from freqtrade.resolvers.exchange_resolver import ExchangeResolver
from tests.conftest import get_patched_exchange
from tests.conftest import EXMS, get_patched_exchange
def test_validate_order_types_gate(default_conf, mocker):
default_conf['exchange']['name'] = 'gate'
mocker.patch('freqtrade.exchange.Exchange._init_ccxt')
mocker.patch('freqtrade.exchange.Exchange._load_markets', return_value={})
mocker.patch('freqtrade.exchange.Exchange.validate_pairs')
mocker.patch('freqtrade.exchange.Exchange.validate_timeframes')
mocker.patch('freqtrade.exchange.Exchange.validate_stakecurrency')
mocker.patch('freqtrade.exchange.Exchange.validate_pricing')
mocker.patch('freqtrade.exchange.Exchange.name', 'Gate')
mocker.patch(f'{EXMS}._init_ccxt')
mocker.patch(f'{EXMS}._load_markets', return_value={})
mocker.patch(f'{EXMS}.validate_pairs')
mocker.patch(f'{EXMS}.validate_timeframes')
mocker.patch(f'{EXMS}.validate_stakecurrency')
mocker.patch(f'{EXMS}.validate_pricing')
mocker.patch(f'{EXMS}.name', 'Gate')
exch = ExchangeResolver.load_exchange('gate', default_conf, True)
assert isinstance(exch, Gate)
@@ -105,7 +105,7 @@ def test_stoploss_adjust_gate(mocker, default_conf, sl1, sl2, sl3, side):
('maker', 0.0, 0.0),
])
def test_fetch_my_trades_gate(mocker, default_conf, takerormaker, rate, cost):
mocker.patch('freqtrade.exchange.Exchange.exchange_has', return_value=True)
mocker.patch(f'{EXMS}.exchange_has', return_value=True)
tick = {'ETH/USDT:USDT': {
'info': {'user_id': '',
'taker_fee': '0.0018',

View File

@@ -5,7 +5,7 @@ import ccxt
import pytest
from freqtrade.exceptions import DependencyException, InvalidOrderException, OperationalException
from tests.conftest import get_patched_exchange
from tests.conftest import EXMS, get_patched_exchange
from tests.exchange.test_exchange import ccxt_exceptionhandlers
@@ -26,8 +26,8 @@ def test_create_stoploss_order_huobi(default_conf, mocker, limitratio, expected,
}
})
default_conf['dry_run'] = False
mocker.patch('freqtrade.exchange.Exchange.amount_to_precision', lambda s, x, y: y)
mocker.patch('freqtrade.exchange.Exchange.price_to_precision', lambda s, x, y: y)
mocker.patch(f'{EXMS}.amount_to_precision', lambda s, x, y: y)
mocker.patch(f'{EXMS}.price_to_precision', lambda s, x, y: y)
exchange = get_patched_exchange(mocker, default_conf, api_mock, 'huobi')
@@ -79,8 +79,8 @@ def test_create_stoploss_order_dry_run_huobi(default_conf, mocker):
api_mock = MagicMock()
order_type = 'stop-limit'
default_conf['dry_run'] = True
mocker.patch('freqtrade.exchange.Exchange.amount_to_precision', lambda s, x, y: y)
mocker.patch('freqtrade.exchange.Exchange.price_to_precision', lambda s, x, y: y)
mocker.patch(f'{EXMS}.amount_to_precision', lambda s, x, y: y)
mocker.patch(f'{EXMS}.price_to_precision', lambda s, x, y: y)
exchange = get_patched_exchange(mocker, default_conf, api_mock, 'huobi')

View File

@@ -5,7 +5,7 @@ import ccxt
import pytest
from freqtrade.exceptions import DependencyException, InvalidOrderException
from tests.conftest import get_patched_exchange
from tests.conftest import EXMS, get_patched_exchange
from tests.exchange.test_exchange import ccxt_exceptionhandlers
@@ -28,8 +28,8 @@ def test_buy_kraken_trading_agreement(default_conf, mocker):
})
default_conf['dry_run'] = False
mocker.patch('freqtrade.exchange.Exchange.amount_to_precision', lambda s, x, y: y)
mocker.patch('freqtrade.exchange.Exchange.price_to_precision', lambda s, x, y: y)
mocker.patch(f'{EXMS}.amount_to_precision', lambda s, x, y: y)
mocker.patch(f'{EXMS}.price_to_precision', lambda s, x, y: y)
exchange = get_patched_exchange(mocker, default_conf, api_mock, id="kraken")
order = exchange.create_order(
@@ -68,8 +68,8 @@ def test_sell_kraken_trading_agreement(default_conf, mocker):
})
default_conf['dry_run'] = False
mocker.patch('freqtrade.exchange.Exchange.amount_to_precision', lambda s, x, y: y)
mocker.patch('freqtrade.exchange.Exchange.price_to_precision', lambda s, x, y: y)
mocker.patch(f'{EXMS}.amount_to_precision', lambda s, x, y: y)
mocker.patch(f'{EXMS}.price_to_precision', lambda s, x, y: y)
exchange = get_patched_exchange(mocker, default_conf, api_mock, id="kraken")
order = exchange.create_order(pair='ETH/BTC', ordertype=order_type,
@@ -191,8 +191,8 @@ def test_create_stoploss_order_kraken(default_conf, mocker, ordertype, side, adj
})
default_conf['dry_run'] = False
mocker.patch('freqtrade.exchange.Exchange.amount_to_precision', lambda s, x, y: y)
mocker.patch('freqtrade.exchange.Exchange.price_to_precision', lambda s, x, y: y)
mocker.patch(f'{EXMS}.amount_to_precision', lambda s, x, y: y)
mocker.patch(f'{EXMS}.price_to_precision', lambda s, x, y: y)
exchange = get_patched_exchange(mocker, default_conf, api_mock, 'kraken')
@@ -262,8 +262,8 @@ def test_create_stoploss_order_kraken(default_conf, mocker, ordertype, side, adj
def test_create_stoploss_order_dry_run_kraken(default_conf, mocker, side):
api_mock = MagicMock()
default_conf['dry_run'] = True
mocker.patch('freqtrade.exchange.Exchange.amount_to_precision', lambda s, x, y: y)
mocker.patch('freqtrade.exchange.Exchange.price_to_precision', lambda s, x, y: y)
mocker.patch(f'{EXMS}.amount_to_precision', lambda s, x, y: y)
mocker.patch(f'{EXMS}.price_to_precision', lambda s, x, y: y)
exchange = get_patched_exchange(mocker, default_conf, api_mock, 'kraken')

View File

@@ -5,7 +5,7 @@ import ccxt
import pytest
from freqtrade.exceptions import DependencyException, InvalidOrderException, OperationalException
from tests.conftest import get_patched_exchange
from tests.conftest import EXMS, get_patched_exchange
from tests.exchange.test_exchange import ccxt_exceptionhandlers
@@ -26,8 +26,8 @@ def test_create_stoploss_order_kucoin(default_conf, mocker, limitratio, expected
}
})
default_conf['dry_run'] = False
mocker.patch('freqtrade.exchange.Exchange.amount_to_precision', lambda s, x, y: y)
mocker.patch('freqtrade.exchange.Exchange.price_to_precision', lambda s, x, y: y)
mocker.patch(f'{EXMS}.amount_to_precision', lambda s, x, y: y)
mocker.patch(f'{EXMS}.price_to_precision', lambda s, x, y: y)
exchange = get_patched_exchange(mocker, default_conf, api_mock, 'kucoin')
if order_type == 'limit':
@@ -87,8 +87,8 @@ def test_stoploss_order_dry_run_kucoin(default_conf, mocker):
api_mock = MagicMock()
order_type = 'market'
default_conf['dry_run'] = True
mocker.patch('freqtrade.exchange.Exchange.amount_to_precision', lambda s, x, y: y)
mocker.patch('freqtrade.exchange.Exchange.price_to_precision', lambda s, x, y: y)
mocker.patch(f'{EXMS}.amount_to_precision', lambda s, x, y: y)
mocker.patch(f'{EXMS}.price_to_precision', lambda s, x, y: y)
exchange = get_patched_exchange(mocker, default_conf, api_mock, 'kucoin')
@@ -125,3 +125,45 @@ def test_stoploss_adjust_kucoin(mocker, default_conf):
# Test with invalid order case
order['stopPrice'] = None
assert exchange.stoploss_adjust(1501, order, 'sell')
@pytest.mark.parametrize("side", ["buy", "sell"])
@pytest.mark.parametrize("ordertype,rate", [
("market", None),
("market", 200),
("limit", 200),
("stop_loss_limit", 200)
])
def test_kucoin_create_order(default_conf, mocker, side, ordertype, rate):
api_mock = MagicMock()
order_id = 'test_prod_{}_{}'.format(side, randint(0, 10 ** 6))
api_mock.create_order = MagicMock(return_value={
'id': order_id,
'info': {
'foo': 'bar'
},
'symbol': 'XRP/USDT',
'amount': 1
})
default_conf['dry_run'] = False
mocker.patch(f'{EXMS}.amount_to_precision', lambda s, x, y: y)
mocker.patch(f'{EXMS}.price_to_precision', lambda s, x, y: y)
exchange = get_patched_exchange(mocker, default_conf, api_mock, id='kucoin')
exchange._set_leverage = MagicMock()
exchange.set_margin_mode = MagicMock()
order = exchange.create_order(
pair='XRP/USDT',
ordertype=ordertype,
side=side,
amount=1,
rate=rate,
leverage=1.0
)
assert 'id' in order
assert 'info' in order
assert order['id'] == order_id
assert order['amount'] == 1
# Status must be faked to open for kucoin.
assert order['status'] == 'open'

View File

@@ -46,7 +46,7 @@ def test_get_maintenance_ratio_and_amt_okx(
default_conf['margin_mode'] = 'isolated'
default_conf['dry_run'] = False
mocker.patch.multiple(
'freqtrade.exchange.Okx',
'freqtrade.exchange.okx.Okx',
exchange_has=MagicMock(return_value=True),
load_leverage_tiers=MagicMock(return_value={
'ETH/USDT:USDT': [

View File

@@ -27,7 +27,7 @@ def freqai_conf(default_conf, tmpdir):
"timerange": "20180110-20180115",
"freqai": {
"enabled": True,
"purge_old_models": True,
"purge_old_models": 2,
"train_period_days": 2,
"backtest_period_days": 10,
"live_retrain_hours": 0,
@@ -46,6 +46,8 @@ def freqai_conf(default_conf, tmpdir):
"use_SVM_to_remove_outliers": True,
"stratify_training_data": 0,
"indicator_periods_candles": [10],
"shuffle_after_split": False,
"buffer_train_data_candles": 0
},
"data_split_parameters": {"test_size": 0.33, "shuffle": False},
"model_training_parameters": {"n_estimators": 100},

View File

@@ -35,8 +35,8 @@ def test_freqai_backtest_start_backtest_list(freqai_conf, mocker, testdatadir, c
args = get_args(args)
bt_config = setup_optimize_configuration(args, RunMode.BACKTEST)
Backtesting(bt_config)
assert log_has_re('Using --strategy-list with FreqAI REQUIRES all strategies to have identical '
'populate_any_indicators.', caplog)
assert log_has_re('Using --strategy-list with FreqAI REQUIRES all strategies to have identical',
caplog)
Backtesting.cleanup()

View File

@@ -1,5 +1,6 @@
import platform
import shutil
import sys
from pathlib import Path
from unittest.mock import MagicMock
@@ -13,10 +14,14 @@ from freqtrade.freqai.utils import download_all_data_for_training, get_required_
from freqtrade.optimize.backtesting import Backtesting
from freqtrade.persistence import Trade
from freqtrade.plugins.pairlistmanager import PairListManager
from tests.conftest import create_mock_trades, get_patched_exchange, log_has_re
from tests.conftest import EXMS, create_mock_trades, get_patched_exchange, log_has_re
from tests.freqai.conftest import get_patched_freqai_strategy, make_rl_config
def is_py11() -> bool:
return sys.version_info >= (3, 11)
def is_arm() -> bool:
machine = platform.machine()
return "arm" in machine or "aarch64" in machine
@@ -27,25 +32,32 @@ def is_mac() -> bool:
return "Darwin" in machine
@pytest.mark.parametrize('model, pca, dbscan, float32, can_short', [
('LightGBMRegressor', True, False, True, True),
('XGBoostRegressor', False, True, False, True),
('XGBoostRFRegressor', False, False, False, True),
('CatboostRegressor', False, False, False, True),
('ReinforcementLearner', False, True, False, True),
('ReinforcementLearner_multiproc', False, False, False, True),
('ReinforcementLearner_test_3ac', False, False, False, False),
('ReinforcementLearner_test_3ac', False, False, False, True),
('ReinforcementLearner_test_4ac', False, False, False, True)
])
def test_extract_data_and_train_model_Standard(mocker, freqai_conf, model, pca,
dbscan, float32, can_short):
if is_arm() and model == 'CatboostRegressor':
def can_run_model(model: str) -> None:
if (is_arm() or is_py11()) and "Catboost" in model:
pytest.skip("CatBoost is not supported on ARM")
if is_mac() and not is_arm() and 'Reinforcement' in model:
pytest.skip("Reinforcement learning module not available on intel based Mac OS")
if is_py11() and 'Reinforcement' in model:
pytest.skip("Reinforcement learning currently not available on python 3.11.")
@pytest.mark.parametrize('model, pca, dbscan, float32, can_short, shuffle, buffer', [
('LightGBMRegressor', True, False, True, True, False, 0),
('XGBoostRegressor', False, True, False, True, False, 10),
('XGBoostRFRegressor', False, False, False, True, False, 0),
('CatboostRegressor', False, False, False, True, True, 0),
('ReinforcementLearner', False, True, False, True, False, 0),
('ReinforcementLearner_multiproc', False, False, False, True, False, 0),
('ReinforcementLearner_test_3ac', False, False, False, False, False, 0),
('ReinforcementLearner_test_3ac', False, False, False, True, False, 0),
('ReinforcementLearner_test_4ac', False, False, False, True, False, 0)
])
def test_extract_data_and_train_model_Standard(mocker, freqai_conf, model, pca,
dbscan, float32, can_short, shuffle, buffer):
can_run_model(model)
model_save_ext = 'joblib'
freqai_conf.update({"freqaimodel": model})
freqai_conf.update({"timerange": "20180110-20180130"})
@@ -53,6 +65,8 @@ def test_extract_data_and_train_model_Standard(mocker, freqai_conf, model, pca,
freqai_conf['freqai']['feature_parameters'].update({"principal_component_analysis": pca})
freqai_conf['freqai']['feature_parameters'].update({"use_DBSCAN_to_remove_outliers": dbscan})
freqai_conf.update({"reduce_df_footprint": float32})
freqai_conf['freqai']['feature_parameters'].update({"shuffle_after_split": shuffle})
freqai_conf['freqai']['feature_parameters'].update({"buffer_train_data_candles": buffer})
if 'ReinforcementLearner' in model:
model_save_ext = 'zip'
@@ -114,7 +128,7 @@ def test_extract_data_and_train_model_Standard(mocker, freqai_conf, model, pca,
('CatboostClassifierMultiTarget', "freqai_test_multimodel_classifier_strat")
])
def test_extract_data_and_train_model_MultiTargets(mocker, freqai_conf, model, strat):
if is_arm() and 'Catboost' in model:
if (is_arm() or is_py11()) and 'Catboost' in model:
pytest.skip("CatBoost is not supported on ARM")
freqai_conf.update({"timerange": "20180110-20180130"})
@@ -156,7 +170,7 @@ def test_extract_data_and_train_model_MultiTargets(mocker, freqai_conf, model, s
'XGBoostRFClassifier',
])
def test_extract_data_and_train_model_Classifiers(mocker, freqai_conf, model):
if is_arm() and model == 'CatboostClassifier':
if (is_arm() or is_py11()) and model == 'CatboostClassifier':
pytest.skip("CatBoost is not supported on ARM")
freqai_conf.update({"freqaimodel": model})
@@ -203,13 +217,11 @@ def test_extract_data_and_train_model_Classifiers(mocker, freqai_conf, model):
],
)
def test_start_backtesting(mocker, freqai_conf, model, num_files, strat, caplog):
can_run_model(model)
freqai_conf.get("freqai", {}).update({"save_backtest_models": True})
freqai_conf['runmode'] = RunMode.BACKTEST
if is_arm() and "Catboost" in model:
pytest.skip("CatBoost is not supported on ARM")
if is_mac() and 'Reinforcement' in model:
pytest.skip("Reinforcement learning module not available on intel based Mac OS")
Trade.use_db = False
freqai_conf.update({"freqaimodel": model})
@@ -506,6 +518,8 @@ def test_get_state_info(mocker, freqai_conf, dp_exists, caplog, tickers):
if is_mac():
pytest.skip("Reinforcement learning module not available on intel based Mac OS")
if is_py11():
pytest.skip("Reinforcement learning currently not available on python 3.11.")
freqai_conf.update({"freqaimodel": "ReinforcementLearner"})
freqai_conf.update({"timerange": "20180110-20180130"})
@@ -517,7 +531,7 @@ def test_get_state_info(mocker, freqai_conf, dp_exists, caplog, tickers):
strategy = get_patched_freqai_strategy(mocker, freqai_conf)
exchange = get_patched_exchange(mocker, freqai_conf)
ticker_mock = MagicMock(return_value=tickers()['ETH/BTC'])
mocker.patch("freqtrade.exchange.Exchange.fetch_ticker", ticker_mock)
mocker.patch(f"{EXMS}.fetch_ticker", ticker_mock)
strategy.dp = DataProvider(freqai_conf, exchange)
if not dp_exists:

View File

@@ -8,7 +8,7 @@ from freqtrade.data.history import get_timerange
from freqtrade.enums import ExitType
from freqtrade.optimize.backtesting import Backtesting
from freqtrade.persistence.trade_model import LocalTrade
from tests.conftest import patch_exchange
from tests.conftest import EXMS, patch_exchange
from tests.optimize import (BTContainer, BTrade, _build_backtest_dataframe,
_get_frame_time_from_offset, tests_timeframe)
@@ -921,10 +921,10 @@ def test_backtest_results(default_conf, fee, mocker, caplog, data: BTContainer)
default_conf["use_exit_signal"] = data.use_exit_signal
default_conf["max_open_trades"] = 10
mocker.patch("freqtrade.exchange.Exchange.get_fee", return_value=0.0)
mocker.patch("freqtrade.exchange.Exchange.get_min_pair_stake_amount", return_value=0.00001)
mocker.patch("freqtrade.exchange.Exchange.get_max_pair_stake_amount", return_value=float('inf'))
mocker.patch("freqtrade.exchange.Binance.get_max_leverage", return_value=100)
mocker.patch(f"{EXMS}.get_fee", return_value=0.0)
mocker.patch(f"{EXMS}.get_min_pair_stake_amount", return_value=0.00001)
mocker.patch(f"{EXMS}.get_max_pair_stake_amount", return_value=float('inf'))
mocker.patch('freqtrade.exchange.binance.Binance.get_max_leverage', return_value=100)
patch_exchange(mocker)
frame = _build_backtest_dataframe(data.data)
backtesting = Backtesting(default_conf)

View File

@@ -26,8 +26,8 @@ from freqtrade.optimize.backtest_caching import get_strategy_run_id
from freqtrade.optimize.backtesting import Backtesting
from freqtrade.persistence import LocalTrade, Trade
from freqtrade.resolvers import StrategyResolver
from tests.conftest import (CURRENT_TEST_STRATEGY, get_args, log_has, log_has_re, patch_exchange,
patched_configuration_load_config_file)
from tests.conftest import (CURRENT_TEST_STRATEGY, EXMS, get_args, log_has, log_has_re,
patch_exchange, patched_configuration_load_config_file)
ORDER_TYPES = [
@@ -245,7 +245,7 @@ def test_setup_optimize_configuration_stake_amount(mocker, default_conf, caplog)
def test_start(mocker, fee, default_conf, caplog) -> None:
start_mock = MagicMock()
mocker.patch('freqtrade.exchange.Exchange.get_fee', fee)
mocker.patch(f'{EXMS}.get_fee', fee)
patch_exchange(mocker)
mocker.patch('freqtrade.optimize.backtesting.Backtesting.start', start_mock)
patched_configuration_load_config_file(mocker, default_conf)
@@ -269,7 +269,7 @@ def test_backtesting_init(mocker, default_conf, order_types) -> None:
"""
default_conf["order_types"] = order_types
patch_exchange(mocker)
get_fee = mocker.patch('freqtrade.exchange.Exchange.get_fee', MagicMock(return_value=0.5))
get_fee = mocker.patch(f'{EXMS}.get_fee', MagicMock(return_value=0.5))
backtesting = Backtesting(default_conf)
backtesting._set_strategy(backtesting.strategylist[0])
assert backtesting.config == default_conf
@@ -290,7 +290,7 @@ def test_backtesting_init_no_timeframe(mocker, default_conf, caplog) -> None:
default_conf['strategy_list'] = [CURRENT_TEST_STRATEGY,
'HyperoptableStrategy']
mocker.patch('freqtrade.exchange.Exchange.get_fee', MagicMock(return_value=0.5))
mocker.patch(f'{EXMS}.get_fee', MagicMock(return_value=0.5))
with pytest.raises(OperationalException,
match=r"Timeframe needs to be set in either configuration"):
Backtesting(default_conf)
@@ -300,7 +300,7 @@ def test_data_with_fee(default_conf, mocker) -> None:
patch_exchange(mocker)
default_conf['fee'] = 0.1234
fee_mock = mocker.patch('freqtrade.exchange.Exchange.get_fee', MagicMock(return_value=0.5))
fee_mock = mocker.patch(f'{EXMS}.get_fee', MagicMock(return_value=0.5))
backtesting = Backtesting(default_conf)
backtesting._set_strategy(backtesting.strategylist[0])
assert backtesting.fee == 0.1234
@@ -404,7 +404,7 @@ def test_backtesting_start_no_data(default_conf, mocker, caplog, testdatadir) ->
def test_backtesting_no_pair_left(default_conf, mocker, caplog, testdatadir) -> None:
mocker.patch('freqtrade.exchange.Exchange.exchange_has', MagicMock(return_value=True))
mocker.patch(f'{EXMS}.exchange_has', MagicMock(return_value=True))
mocker.patch('freqtrade.data.history.history_utils.load_pair_history',
MagicMock(return_value=pd.DataFrame()))
mocker.patch('freqtrade.data.history.get_timerange', get_timerange)
@@ -436,9 +436,9 @@ def test_backtesting_no_pair_left(default_conf, mocker, caplog, testdatadir) ->
def test_backtesting_pairlist_list(default_conf, mocker, caplog, testdatadir, tickers) -> None:
mocker.patch('freqtrade.exchange.Exchange.exchange_has', MagicMock(return_value=True))
mocker.patch('freqtrade.exchange.Exchange.get_tickers', tickers)
mocker.patch('freqtrade.exchange.Exchange.price_to_precision', lambda s, x, y: y)
mocker.patch(f'{EXMS}.exchange_has', MagicMock(return_value=True))
mocker.patch(f'{EXMS}.get_tickers', tickers)
mocker.patch(f'{EXMS}.price_to_precision', lambda s, x, y: y)
mocker.patch('freqtrade.data.history.get_timerange', get_timerange)
patch_exchange(mocker)
mocker.patch('freqtrade.optimize.backtesting.Backtesting.backtest')
@@ -474,9 +474,9 @@ def test_backtesting_pairlist_list(default_conf, mocker, caplog, testdatadir, ti
def test_backtest__enter_trade(default_conf, fee, mocker) -> None:
default_conf['use_exit_signal'] = False
mocker.patch('freqtrade.exchange.Exchange.get_fee', fee)
mocker.patch("freqtrade.exchange.Exchange.get_min_pair_stake_amount", return_value=0.00001)
mocker.patch("freqtrade.exchange.Exchange.get_max_pair_stake_amount", return_value=float('inf'))
mocker.patch(f'{EXMS}.get_fee', fee)
mocker.patch(f'{EXMS}.get_min_pair_stake_amount', return_value=0.00001)
mocker.patch(f'{EXMS}.get_max_pair_stake_amount', return_value=float('inf'))
patch_exchange(mocker)
default_conf['stake_amount'] = 'unlimited'
default_conf['max_open_trades'] = 2
@@ -525,7 +525,7 @@ def test_backtest__enter_trade(default_conf, fee, mocker) -> None:
assert trade.stake_amount == 495
assert trade.is_short is True
mocker.patch("freqtrade.exchange.Exchange.get_max_pair_stake_amount", return_value=300.0)
mocker.patch(f"{EXMS}.get_max_pair_stake_amount", return_value=300.0)
trade = backtesting._enter_trade(pair, row=row, direction='long')
assert trade
assert trade.stake_amount == 300.0
@@ -533,10 +533,10 @@ def test_backtest__enter_trade(default_conf, fee, mocker) -> None:
def test_backtest__enter_trade_futures(default_conf_usdt, fee, mocker) -> None:
default_conf_usdt['use_exit_signal'] = False
mocker.patch('freqtrade.exchange.Exchange.get_fee', fee)
mocker.patch("freqtrade.exchange.Exchange.get_min_pair_stake_amount", return_value=0.00001)
mocker.patch("freqtrade.exchange.Exchange.get_max_pair_stake_amount", return_value=float('inf'))
mocker.patch("freqtrade.exchange.Exchange.get_max_leverage", return_value=100)
mocker.patch(f'{EXMS}.get_fee', fee)
mocker.patch(f"{EXMS}.get_min_pair_stake_amount", return_value=0.00001)
mocker.patch(f"{EXMS}.get_max_pair_stake_amount", return_value=float('inf'))
mocker.patch(f"{EXMS}.get_max_leverage", return_value=100)
mocker.patch("freqtrade.optimize.backtesting.price_to_precision", lambda p, *args: p)
patch_exchange(mocker)
default_conf_usdt['stake_amount'] = 300
@@ -564,7 +564,7 @@ def test_backtest__enter_trade_futures(default_conf_usdt, fee, mocker) -> None:
]
backtesting.strategy.leverage = MagicMock(return_value=5.0)
mocker.patch("freqtrade.exchange.Exchange.get_maintenance_ratio_and_amt",
mocker.patch(f"{EXMS}.get_maintenance_ratio_and_amt",
return_value=(0.01, 0.01))
# leverage = 5
@@ -601,7 +601,7 @@ def test_backtest__enter_trade_futures(default_conf_usdt, fee, mocker) -> None:
assert pytest.approx(trade.liquidation_price) == 0.11787191
# Stake-amount too high!
mocker.patch("freqtrade.exchange.Exchange.get_min_pair_stake_amount", return_value=600.0)
mocker.patch(f"{EXMS}.get_min_pair_stake_amount", return_value=600.0)
trade = backtesting._enter_trade(pair, row=row, direction='long')
assert trade is None
@@ -616,9 +616,9 @@ def test_backtest__enter_trade_futures(default_conf_usdt, fee, mocker) -> None:
def test_backtest__check_trade_exit(default_conf, fee, mocker) -> None:
default_conf['use_exit_signal'] = False
mocker.patch('freqtrade.exchange.Exchange.get_fee', fee)
mocker.patch("freqtrade.exchange.Exchange.get_min_pair_stake_amount", return_value=0.00001)
mocker.patch("freqtrade.exchange.Exchange.get_max_pair_stake_amount", return_value=float('inf'))
mocker.patch(f'{EXMS}.get_fee', fee)
mocker.patch(f"{EXMS}.get_min_pair_stake_amount", return_value=0.00001)
mocker.patch(f"{EXMS}.get_max_pair_stake_amount", return_value=float('inf'))
patch_exchange(mocker)
default_conf['timeframe_detail'] = '1m'
default_conf['max_open_trades'] = 2
@@ -681,9 +681,9 @@ def test_backtest_one(default_conf, fee, mocker, testdatadir) -> None:
default_conf['use_exit_signal'] = False
default_conf['max_open_trades'] = 10
mocker.patch('freqtrade.exchange.Exchange.get_fee', fee)
mocker.patch("freqtrade.exchange.Exchange.get_min_pair_stake_amount", return_value=0.00001)
mocker.patch("freqtrade.exchange.Exchange.get_max_pair_stake_amount", return_value=float('inf'))
mocker.patch(f'{EXMS}.get_fee', fee)
mocker.patch(f"{EXMS}.get_min_pair_stake_amount", return_value=0.00001)
mocker.patch(f"{EXMS}.get_max_pair_stake_amount", return_value=float('inf'))
patch_exchange(mocker)
backtesting = Backtesting(default_conf)
backtesting._set_strategy(backtesting.strategylist[0])
@@ -766,9 +766,9 @@ def test_backtest_one(default_conf, fee, mocker, testdatadir) -> None:
@pytest.mark.parametrize('use_detail', [True, False])
def test_backtest_one_detail(default_conf_usdt, fee, mocker, testdatadir, use_detail) -> None:
default_conf_usdt['use_exit_signal'] = False
mocker.patch('freqtrade.exchange.Exchange.get_fee', fee)
mocker.patch("freqtrade.exchange.Exchange.get_min_pair_stake_amount", return_value=0.00001)
mocker.patch("freqtrade.exchange.Exchange.get_max_pair_stake_amount", return_value=float('inf'))
mocker.patch(f'{EXMS}.get_fee', fee)
mocker.patch(f"{EXMS}.get_min_pair_stake_amount", return_value=0.00001)
mocker.patch(f"{EXMS}.get_max_pair_stake_amount", return_value=float('inf'))
if use_detail:
default_conf_usdt['timeframe_detail'] = '1m'
patch_exchange(mocker)
@@ -854,12 +854,12 @@ def test_backtest_one_detail_futures(
default_conf_usdt['margin_mode'] = 'isolated'
default_conf_usdt['candle_type_def'] = CandleType.FUTURES
mocker.patch('freqtrade.exchange.Exchange.get_fee', fee)
mocker.patch("freqtrade.exchange.Exchange.get_min_pair_stake_amount", return_value=0.00001)
mocker.patch("freqtrade.exchange.Exchange.get_max_pair_stake_amount", return_value=float('inf'))
mocker.patch(f'{EXMS}.get_fee', fee)
mocker.patch(f"{EXMS}.get_min_pair_stake_amount", return_value=0.00001)
mocker.patch(f"{EXMS}.get_max_pair_stake_amount", return_value=float('inf'))
mocker.patch('freqtrade.plugins.pairlistmanager.PairListManager.whitelist',
PropertyMock(return_value=['XRP/USDT:USDT']))
mocker.patch("freqtrade.exchange.Exchange.get_maintenance_ratio_and_amt",
mocker.patch(f"{EXMS}.get_maintenance_ratio_and_amt",
return_value=(0.01, 0.01))
default_conf_usdt['timeframe'] = '1h'
if use_detail:
@@ -945,12 +945,12 @@ def test_backtest_one_detail_futures_funding_fees(
default_conf_usdt['minimal_roi'] = {'0': 1}
default_conf_usdt['dry_run_wallet'] = 100000
mocker.patch('freqtrade.exchange.Exchange.get_fee', fee)
mocker.patch("freqtrade.exchange.Exchange.get_min_pair_stake_amount", return_value=0.00001)
mocker.patch("freqtrade.exchange.Exchange.get_max_pair_stake_amount", return_value=float('inf'))
mocker.patch(f'{EXMS}.get_fee', fee)
mocker.patch(f"{EXMS}.get_min_pair_stake_amount", return_value=0.00001)
mocker.patch(f"{EXMS}.get_max_pair_stake_amount", return_value=float('inf'))
mocker.patch('freqtrade.plugins.pairlistmanager.PairListManager.whitelist',
PropertyMock(return_value=['XRP/USDT:USDT']))
mocker.patch("freqtrade.exchange.Exchange.get_maintenance_ratio_and_amt",
mocker.patch(f"{EXMS}.get_maintenance_ratio_and_amt",
return_value=(0.01, 0.01))
default_conf_usdt['timeframe'] = '1h'
if use_detail:
@@ -1010,9 +1010,9 @@ def test_backtest_timedout_entry_orders(default_conf, fee, mocker, testdatadir)
default_conf['startup_candle_count'] = 0
# Cancel unfilled order after 4 minutes on 5m timeframe.
default_conf["unfilledtimeout"] = {"entry": 4}
mocker.patch('freqtrade.exchange.Exchange.get_fee', fee)
mocker.patch("freqtrade.exchange.Exchange.get_min_pair_stake_amount", return_value=0.00001)
mocker.patch("freqtrade.exchange.Exchange.get_max_pair_stake_amount", return_value=float('inf'))
mocker.patch(f'{EXMS}.get_fee', fee)
mocker.patch(f"{EXMS}.get_min_pair_stake_amount", return_value=0.00001)
mocker.patch(f"{EXMS}.get_max_pair_stake_amount", return_value=float('inf'))
patch_exchange(mocker)
default_conf['max_open_trades'] = 1
backtesting = Backtesting(default_conf)
@@ -1035,9 +1035,9 @@ def test_backtest_timedout_entry_orders(default_conf, fee, mocker, testdatadir)
def test_backtest_1min_timeframe(default_conf, fee, mocker, testdatadir) -> None:
default_conf['use_exit_signal'] = False
default_conf['max_open_trades'] = 1
mocker.patch('freqtrade.exchange.Exchange.get_fee', fee)
mocker.patch("freqtrade.exchange.Exchange.get_min_pair_stake_amount", return_value=0.00001)
mocker.patch("freqtrade.exchange.Exchange.get_max_pair_stake_amount", return_value=float('inf'))
mocker.patch(f'{EXMS}.get_fee', fee)
mocker.patch(f"{EXMS}.get_min_pair_stake_amount", return_value=0.00001)
mocker.patch(f"{EXMS}.get_max_pair_stake_amount", return_value=float('inf'))
patch_exchange(mocker)
backtesting = Backtesting(default_conf)
backtesting._set_strategy(backtesting.strategylist[0])
@@ -1061,9 +1061,9 @@ def test_backtest_trim_no_data_left(default_conf, fee, mocker, testdatadir) -> N
default_conf['use_exit_signal'] = False
default_conf['max_open_trades'] = 10
mocker.patch('freqtrade.exchange.Exchange.get_fee', fee)
mocker.patch("freqtrade.exchange.Exchange.get_min_pair_stake_amount", return_value=0.00001)
mocker.patch("freqtrade.exchange.Exchange.get_max_pair_stake_amount", return_value=float('inf'))
mocker.patch(f'{EXMS}.get_fee', fee)
mocker.patch(f"{EXMS}.get_min_pair_stake_amount", return_value=0.00001)
mocker.patch(f"{EXMS}.get_max_pair_stake_amount", return_value=float('inf'))
patch_exchange(mocker)
backtesting = Backtesting(default_conf)
backtesting._set_strategy(backtesting.strategylist[0])
@@ -1105,9 +1105,9 @@ def test_processed(default_conf, mocker, testdatadir) -> None:
def test_backtest_dataprovider_analyzed_df(default_conf, fee, mocker, testdatadir) -> None:
default_conf['use_exit_signal'] = False
default_conf['max_open_trades'] = 10
mocker.patch('freqtrade.exchange.Exchange.get_fee', fee)
mocker.patch("freqtrade.exchange.Exchange.get_min_pair_stake_amount", return_value=0.00001)
mocker.patch("freqtrade.exchange.Exchange.get_max_pair_stake_amount", return_value=100000)
mocker.patch(f'{EXMS}.get_fee', fee)
mocker.patch(f"{EXMS}.get_min_pair_stake_amount", return_value=0.00001)
mocker.patch(f"{EXMS}.get_max_pair_stake_amount", return_value=100000)
patch_exchange(mocker)
backtesting = Backtesting(default_conf)
backtesting._set_strategy(backtesting.strategylist[0])
@@ -1155,9 +1155,9 @@ def test_backtest_pricecontours_protections(default_conf, fee, mocker, testdatad
default_conf['enable_protections'] = True
default_conf['timeframe'] = '1m'
default_conf['max_open_trades'] = 1
mocker.patch('freqtrade.exchange.Exchange.get_fee', fee)
mocker.patch("freqtrade.exchange.Exchange.get_min_pair_stake_amount", return_value=0.00001)
mocker.patch("freqtrade.exchange.Exchange.get_max_pair_stake_amount", return_value=float('inf'))
mocker.patch(f'{EXMS}.get_fee', fee)
mocker.patch(f"{EXMS}.get_min_pair_stake_amount", return_value=0.00001)
mocker.patch(f"{EXMS}.get_max_pair_stake_amount", return_value=float('inf'))
tests = [
['sine', 9],
['raise', 10],
@@ -1203,9 +1203,9 @@ def test_backtest_pricecontours(default_conf, fee, mocker, testdatadir,
default_conf['protections'] = protections
default_conf['enable_protections'] = True
mocker.patch("freqtrade.exchange.Exchange.get_min_pair_stake_amount", return_value=0.00001)
mocker.patch("freqtrade.exchange.Exchange.get_max_pair_stake_amount", return_value=float('inf'))
mocker.patch('freqtrade.exchange.Exchange.get_fee', fee)
mocker.patch(f"{EXMS}.get_min_pair_stake_amount", return_value=0.00001)
mocker.patch(f"{EXMS}.get_max_pair_stake_amount", return_value=float('inf'))
mocker.patch(f'{EXMS}.get_fee', fee)
# While entry-signals are unrealistic, running backtesting
# over and over again should not cause different results
@@ -1262,9 +1262,9 @@ def test_backtest_only_sell(mocker, default_conf, testdatadir):
def test_backtest_alternate_buy_sell(default_conf, fee, mocker, testdatadir):
mocker.patch("freqtrade.exchange.Exchange.get_min_pair_stake_amount", return_value=0.00001)
mocker.patch("freqtrade.exchange.Exchange.get_max_pair_stake_amount", return_value=float('inf'))
mocker.patch('freqtrade.exchange.Exchange.get_fee', fee)
mocker.patch(f"{EXMS}.get_min_pair_stake_amount", return_value=0.00001)
mocker.patch(f"{EXMS}.get_max_pair_stake_amount", return_value=float('inf'))
mocker.patch(f'{EXMS}.get_fee', fee)
default_conf['max_open_trades'] = 10
backtest_conf = _make_backtest_conf(mocker, conf=default_conf,
pair='UNITTEST/BTC', datadir=testdatadir)
@@ -1310,9 +1310,9 @@ def test_backtest_multi_pair(default_conf, fee, mocker, tres, pair, testdatadir)
dataframe['exit_short'] = 0
return dataframe
mocker.patch("freqtrade.exchange.Exchange.get_min_pair_stake_amount", return_value=0.00001)
mocker.patch("freqtrade.exchange.Exchange.get_max_pair_stake_amount", return_value=float('inf'))
mocker.patch('freqtrade.exchange.Exchange.get_fee', fee)
mocker.patch(f"{EXMS}.get_min_pair_stake_amount", return_value=0.00001)
mocker.patch(f"{EXMS}.get_max_pair_stake_amount", return_value=float('inf'))
mocker.patch(f'{EXMS}.get_fee', fee)
patch_exchange(mocker)
pairs = ['ADA/BTC', 'DASH/BTC', 'ETH/BTC', 'LTC/BTC', 'NXT/BTC']

View File

@@ -12,17 +12,17 @@ from freqtrade.data import history
from freqtrade.data.history import get_timerange
from freqtrade.enums import ExitType
from freqtrade.optimize.backtesting import Backtesting
from tests.conftest import patch_exchange
from tests.conftest import EXMS, patch_exchange
def test_backtest_position_adjustment(default_conf, fee, mocker, testdatadir) -> None:
default_conf['use_exit_signal'] = False
default_conf['max_open_trades'] = 10
mocker.patch('freqtrade.exchange.Exchange.get_fee', fee)
mocker.patch(f'{EXMS}.get_fee', fee)
mocker.patch('freqtrade.optimize.backtesting.amount_to_contract_precision',
lambda x, *args, **kwargs: round(x, 8))
mocker.patch("freqtrade.exchange.Exchange.get_min_pair_stake_amount", return_value=0.00001)
mocker.patch("freqtrade.exchange.Exchange.get_max_pair_stake_amount", return_value=float('inf'))
mocker.patch(f"{EXMS}.get_min_pair_stake_amount", return_value=0.00001)
mocker.patch(f"{EXMS}.get_max_pair_stake_amount", return_value=float('inf'))
patch_exchange(mocker)
default_conf.update({
"stake_amount": 100.0,
@@ -99,10 +99,10 @@ def test_backtest_position_adjustment(default_conf, fee, mocker, testdatadir) ->
])
def test_backtest_position_adjustment_detailed(default_conf, fee, mocker, leverage) -> None:
default_conf['use_exit_signal'] = False
mocker.patch('freqtrade.exchange.Exchange.get_fee', fee)
mocker.patch("freqtrade.exchange.Exchange.get_min_pair_stake_amount", return_value=10)
mocker.patch("freqtrade.exchange.Exchange.get_max_pair_stake_amount", return_value=float('inf'))
mocker.patch("freqtrade.exchange.Exchange.get_max_leverage", return_value=10)
mocker.patch(f'{EXMS}.get_fee', fee)
mocker.patch(f"{EXMS}.get_min_pair_stake_amount", return_value=10)
mocker.patch(f"{EXMS}.get_max_pair_stake_amount", return_value=float('inf'))
mocker.patch(f"{EXMS}.get_max_leverage", return_value=10)
patch_exchange(mocker)
default_conf.update({

View File

@@ -6,7 +6,7 @@ from unittest.mock import MagicMock
from freqtrade.commands.optimize_commands import setup_optimize_configuration, start_edge
from freqtrade.enums import RunMode
from freqtrade.optimize.edge_cli import EdgeCli
from tests.conftest import (CURRENT_TEST_STRATEGY, get_args, log_has, patch_exchange,
from tests.conftest import (CURRENT_TEST_STRATEGY, EXMS, get_args, log_has, patch_exchange,
patched_configuration_load_config_file)
@@ -71,7 +71,7 @@ def test_setup_edge_configuration_with_arguments(mocker, edge_conf, caplog) -> N
def test_start(mocker, fee, edge_conf, caplog) -> None:
start_mock = MagicMock()
mocker.patch('freqtrade.exchange.Exchange.get_fee', fee)
mocker.patch(f'{EXMS}.get_fee', fee)
patch_exchange(mocker)
mocker.patch('freqtrade.optimize.edge_cli.EdgeCli.start', start_mock)
patched_configuration_load_config_file(mocker, edge_conf)
@@ -101,7 +101,7 @@ def test_edge_init_fee(mocker, edge_conf) -> None:
patch_exchange(mocker)
edge_conf['fee'] = 0.1234
edge_conf['stake_amount'] = 20
fee_mock = mocker.patch('freqtrade.exchange.Exchange.get_fee', MagicMock(return_value=0.5))
fee_mock = mocker.patch(f'{EXMS}.get_fee', return_value=0.5)
edge_cli = EdgeCli(edge_conf)
assert edge_cli.edge.fee == 0.1234
assert fee_mock.call_count == 0

View File

@@ -20,7 +20,7 @@ from freqtrade.optimize.hyperopt_tools import HyperoptTools
from freqtrade.optimize.optimize_reports import generate_strategy_stats
from freqtrade.optimize.space import SKDecimal
from freqtrade.strategy import IntParameter
from tests.conftest import (CURRENT_TEST_STRATEGY, get_args, get_markets, log_has, log_has_re,
from tests.conftest import (CURRENT_TEST_STRATEGY, EXMS, get_args, get_markets, log_has, log_has_re,
patch_exchange, patched_configuration_load_config_file)
@@ -859,7 +859,7 @@ def test_simplified_interface_failed(mocker, hyperopt_conf, space) -> None:
def test_in_strategy_auto_hyperopt(mocker, hyperopt_conf, tmpdir, fee) -> None:
patch_exchange(mocker)
mocker.patch('freqtrade.exchange.Exchange.get_fee', fee)
mocker.patch(f'{EXMS}.get_fee', fee)
(Path(tmpdir) / 'hyperopt_results').mkdir(parents=True)
# No hyperopt needed
hyperopt_conf.update({
@@ -897,10 +897,10 @@ def test_in_strategy_auto_hyperopt(mocker, hyperopt_conf, tmpdir, fee) -> None:
def test_in_strategy_auto_hyperopt_with_parallel(mocker, hyperopt_conf, tmpdir, fee) -> None:
mocker.patch('freqtrade.exchange.Exchange.validate_config', MagicMock())
mocker.patch('freqtrade.exchange.Exchange.get_fee', fee)
mocker.patch('freqtrade.exchange.Exchange._load_markets')
mocker.patch('freqtrade.exchange.Exchange.markets',
mocker.patch(f'{EXMS}.validate_config', MagicMock())
mocker.patch(f'{EXMS}.get_fee', fee)
mocker.patch(f'{EXMS}._load_markets')
mocker.patch(f'{EXMS}.markets',
PropertyMock(return_value=get_markets()))
(Path(tmpdir) / 'hyperopt_results').mkdir(parents=True)
# No hyperopt needed
@@ -938,7 +938,7 @@ def test_in_strategy_auto_hyperopt_with_parallel(mocker, hyperopt_conf, tmpdir,
def test_in_strategy_auto_hyperopt_per_epoch(mocker, hyperopt_conf, tmpdir, fee) -> None:
patch_exchange(mocker)
mocker.patch('freqtrade.exchange.Exchange.get_fee', fee)
mocker.patch(f'{EXMS}.get_fee', fee)
(Path(tmpdir) / 'hyperopt_results').mkdir(parents=True)
hyperopt_conf.update({
@@ -996,7 +996,7 @@ def test_stake_amount_unlimited_max_open_trades(mocker, hyperopt_conf, tmpdir, f
# This test is to ensure that unlimited max_open_trades are ignored for the backtesting
# if we have an unlimited stake amount
patch_exchange(mocker)
mocker.patch('freqtrade.exchange.Exchange.get_fee', fee)
mocker.patch(f'{EXMS}.get_fee', fee)
(Path(tmpdir) / 'hyperopt_results').mkdir(parents=True)
hyperopt_conf.update({
'strategy': 'HyperoptableStrategy',
@@ -1024,7 +1024,7 @@ def test_max_open_trades_dump(mocker, hyperopt_conf, tmpdir, fee, capsys) -> Non
# This test is to ensure that after hyperopting, max_open_trades is never
# saved as inf in the output json params
patch_exchange(mocker)
mocker.patch('freqtrade.exchange.Exchange.get_fee', fee)
mocker.patch(f'{EXMS}.get_fee', fee)
(Path(tmpdir) / 'hyperopt_results').mkdir(parents=True)
hyperopt_conf.update({
'strategy': 'HyperoptableStrategy',
@@ -1070,7 +1070,7 @@ def test_max_open_trades_consistency(mocker, hyperopt_conf, tmpdir, fee) -> None
# This test is to ensure that max_open_trades is the same across all functions needing it
# after it has been changed from the hyperopt
patch_exchange(mocker)
mocker.patch('freqtrade.exchange.Exchange.get_fee', return_value=0)
mocker.patch(f'{EXMS}.get_fee', return_value=0)
(Path(tmpdir) / 'hyperopt_results').mkdir(parents=True)
hyperopt_conf.update({

View File

@@ -255,7 +255,7 @@ def test_write_read_backtest_candles(tmpdir):
# test directory exporting
stored_file = store_backtest_signal_candles(Path(tmpdir), candle_dict, '2022_01_01_15_05_13')
scp = open(stored_file, "rb")
scp = stored_file.open("rb")
pickled_signal_candles = joblib.load(scp)
scp.close()
@@ -269,7 +269,7 @@ def test_write_read_backtest_candles(tmpdir):
# test file exporting
filename = Path(tmpdir / 'testresult')
stored_file = store_backtest_signal_candles(filename, candle_dict, '2022_01_01_15_05_13')
scp = open(stored_file, "rb")
scp = stored_file.open("rb")
pickled_signal_candles = joblib.load(scp)
scp.close()

View File

@@ -2440,6 +2440,7 @@ def test_select_filled_orders(fee):
def test_order_to_ccxt(limit_buy_order_open):
order = Order.parse_from_ccxt_object(limit_buy_order_open, 'mocked', 'buy')
order.ft_trade_id = 1
order.query.session.add(order)
Order.query.session.commit()

View File

@@ -18,8 +18,8 @@ from freqtrade.persistence import Trade
from freqtrade.plugins.pairlist.pairlist_helpers import dynamic_expand_pairlist, expand_pairlist
from freqtrade.plugins.pairlistmanager import PairListManager
from freqtrade.resolvers import PairListResolver
from tests.conftest import (create_mock_trades_usdt, get_patched_exchange, get_patched_freqtradebot,
log_has, log_has_re, num_log_has)
from tests.conftest import (EXMS, create_mock_trades_usdt, get_patched_exchange,
get_patched_freqtradebot, log_has, log_has_re, num_log_has)
# Exclude RemotePairList from tests.
@@ -116,7 +116,7 @@ def static_pl_conf(whitelist_conf):
def test_log_cached(mocker, static_pl_conf, markets, tickers):
mocker.patch.multiple('freqtrade.exchange.Exchange',
mocker.patch.multiple(EXMS,
markets=PropertyMock(return_value=markets),
exchange_has=MagicMock(return_value=True),
get_tickers=tickers
@@ -139,7 +139,7 @@ def test_log_cached(mocker, static_pl_conf, markets, tickers):
def test_load_pairlist_noexist(mocker, markets, default_conf):
freqtrade = get_patched_freqtradebot(mocker, default_conf)
mocker.patch('freqtrade.exchange.Exchange.markets', PropertyMock(return_value=markets))
mocker.patch(f'{EXMS}.markets', PropertyMock(return_value=markets))
plm = PairListManager(freqtrade.exchange, default_conf, MagicMock())
with pytest.raises(OperationalException,
match=r"Impossible to load Pairlist 'NonexistingPairList'. "
@@ -150,7 +150,7 @@ def test_load_pairlist_noexist(mocker, markets, default_conf):
def test_load_pairlist_verify_multi(mocker, markets_static, default_conf):
freqtrade = get_patched_freqtradebot(mocker, default_conf)
mocker.patch('freqtrade.exchange.Exchange.markets', PropertyMock(return_value=markets_static))
mocker.patch(f'{EXMS}.markets', PropertyMock(return_value=markets_static))
plm = PairListManager(freqtrade.exchange, default_conf, MagicMock())
# Call different versions one after the other, should always consider what was passed in
# and have no side-effects (therefore the same check multiple times)
@@ -166,7 +166,7 @@ def test_refresh_market_pair_not_in_whitelist(mocker, markets, static_pl_conf):
freqtrade = get_patched_freqtradebot(mocker, static_pl_conf)
mocker.patch('freqtrade.exchange.Exchange.markets', PropertyMock(return_value=markets))
mocker.patch(f'{EXMS}.markets', PropertyMock(return_value=markets))
freqtrade.pairlists.refresh_pairlist()
# List ordered by BaseVolume
whitelist = ['ETH/BTC', 'TKN/BTC']
@@ -180,7 +180,7 @@ def test_refresh_market_pair_not_in_whitelist(mocker, markets, static_pl_conf):
def test_refresh_static_pairlist(mocker, markets, static_pl_conf):
freqtrade = get_patched_freqtradebot(mocker, static_pl_conf)
mocker.patch.multiple(
'freqtrade.exchange.Exchange',
EXMS,
exchange_has=MagicMock(return_value=True),
markets=PropertyMock(return_value=markets),
)
@@ -204,7 +204,7 @@ def test_refresh_static_pairlist_noexist(mocker, markets, static_pl_conf, pairs,
static_pl_conf['exchange']['pair_whitelist'] += pairs
freqtrade = get_patched_freqtradebot(mocker, static_pl_conf)
mocker.patch.multiple(
'freqtrade.exchange.Exchange',
EXMS,
exchange_has=MagicMock(return_value=True),
markets=PropertyMock(return_value=markets),
)
@@ -221,7 +221,7 @@ def test_invalid_blacklist(mocker, markets, static_pl_conf, caplog):
static_pl_conf['exchange']['pair_blacklist'] = ['*/BTC']
freqtrade = get_patched_freqtradebot(mocker, static_pl_conf)
mocker.patch.multiple(
'freqtrade.exchange.Exchange',
EXMS,
exchange_has=MagicMock(return_value=True),
markets=PropertyMock(return_value=markets),
)
@@ -237,7 +237,7 @@ def test_remove_logs_for_pairs_already_in_blacklist(mocker, markets, static_pl_c
logger = logging.getLogger(__name__)
freqtrade = get_patched_freqtradebot(mocker, static_pl_conf)
mocker.patch.multiple(
'freqtrade.exchange.Exchange',
EXMS,
exchange_has=MagicMock(return_value=True),
markets=PropertyMock(return_value=markets),
)
@@ -264,14 +264,14 @@ def test_remove_logs_for_pairs_already_in_blacklist(mocker, markets, static_pl_c
def test_refresh_pairlist_dynamic(mocker, shitcoinmarkets, tickers, whitelist_conf):
mocker.patch.multiple(
'freqtrade.exchange.Exchange',
EXMS,
get_tickers=tickers,
exchange_has=MagicMock(return_value=True),
)
freqtrade = get_patched_freqtradebot(mocker, whitelist_conf)
# Remock markets with shitcoinmarkets since get_patched_freqtradebot uses the markets fixture
mocker.patch.multiple(
'freqtrade.exchange.Exchange',
EXMS,
markets=PropertyMock(return_value=shitcoinmarkets),
)
# argument: use the whitelist dynamically by exchange-volume
@@ -291,7 +291,7 @@ def test_refresh_pairlist_dynamic_2(mocker, shitcoinmarkets, tickers, whitelist_
tickers_dict = tickers()
mocker.patch.multiple(
'freqtrade.exchange.Exchange',
EXMS,
exchange_has=MagicMock(return_value=True),
)
# Remove caching of ticker data to emulate changing volume by the time of second call
@@ -302,7 +302,7 @@ def test_refresh_pairlist_dynamic_2(mocker, shitcoinmarkets, tickers, whitelist_
freqtrade = get_patched_freqtradebot(mocker, whitelist_conf_2)
# Remock markets with shitcoinmarkets since get_patched_freqtradebot uses the markets fixture
mocker.patch.multiple(
'freqtrade.exchange.Exchange',
EXMS,
markets=PropertyMock(return_value=shitcoinmarkets),
)
@@ -320,11 +320,11 @@ def test_refresh_pairlist_dynamic_2(mocker, shitcoinmarkets, tickers, whitelist_
def test_VolumePairList_refresh_empty(mocker, markets_empty, whitelist_conf):
mocker.patch.multiple(
'freqtrade.exchange.Exchange',
EXMS,
exchange_has=MagicMock(return_value=True),
)
freqtrade = get_patched_freqtradebot(mocker, whitelist_conf)
mocker.patch('freqtrade.exchange.Exchange.markets', PropertyMock(return_value=markets_empty))
mocker.patch(f'{EXMS}.markets', PropertyMock(return_value=markets_empty))
# argument: use the whitelist dynamically by exchange-volume
whitelist = []
@@ -523,15 +523,15 @@ def test_VolumePairList_whitelist_gen(mocker, whitelist_conf, shitcoinmarkets, t
('HOT/BTC', '1d', CandleType.SPOT): ohlcv_history_high_vola,
}
mocker.patch('freqtrade.exchange.Exchange.exchange_has', MagicMock(return_value=True))
mocker.patch(f'{EXMS}.exchange_has', MagicMock(return_value=True))
freqtrade = get_patched_freqtradebot(mocker, whitelist_conf)
mocker.patch.multiple('freqtrade.exchange.Exchange',
mocker.patch.multiple(EXMS,
get_tickers=tickers,
markets=PropertyMock(return_value=shitcoinmarkets)
)
mocker.patch.multiple(
'freqtrade.exchange.Exchange',
EXMS,
refresh_latest_ohlcv=MagicMock(return_value=ohlcv_data),
)
@@ -649,7 +649,7 @@ def test_VolumePairList_range(mocker, whitelist_conf, shitcoinmarkets, tickers,
('HOT/BTC', '1d', CandleType.SPOT): ohlcv_history_high_volume,
}
mocker.patch('freqtrade.exchange.Exchange.exchange_has', MagicMock(return_value=True))
mocker.patch(f'{EXMS}.exchange_has', MagicMock(return_value=True))
if volumefilter_result == 'default_refresh_too_short':
with pytest.raises(OperationalException,
@@ -675,7 +675,7 @@ def test_VolumePairList_range(mocker, whitelist_conf, shitcoinmarkets, tickers,
else:
freqtrade = get_patched_freqtradebot(mocker, whitelist_conf)
mocker.patch.multiple(
'freqtrade.exchange.Exchange',
EXMS,
get_tickers=tickers,
markets=PropertyMock(return_value=shitcoinmarkets)
)
@@ -687,7 +687,7 @@ def test_VolumePairList_range(mocker, whitelist_conf, shitcoinmarkets, tickers,
ohlcv_data = []
mocker.patch.multiple(
'freqtrade.exchange.Exchange',
EXMS,
refresh_latest_ohlcv=MagicMock(return_value=ohlcv_data),
)
@@ -702,7 +702,7 @@ def test_PrecisionFilter_error(mocker, whitelist_conf) -> None:
whitelist_conf['pairlists'] = [{"method": "StaticPairList"}, {"method": "PrecisionFilter"}]
del whitelist_conf['stoploss']
mocker.patch('freqtrade.exchange.Exchange.exchange_has', MagicMock(return_value=True))
mocker.patch(f'{EXMS}.exchange_has', MagicMock(return_value=True))
with pytest.raises(OperationalException,
match=r"PrecisionFilter can only work with stoploss defined\..*"):
@@ -713,7 +713,7 @@ def test_PerformanceFilter_error(mocker, whitelist_conf, caplog) -> None:
whitelist_conf['pairlists'] = [{"method": "StaticPairList"}, {"method": "PerformanceFilter"}]
if hasattr(Trade, 'query'):
del Trade.query
mocker.patch('freqtrade.exchange.Exchange.exchange_has', MagicMock(return_value=True))
mocker.patch(f'{EXMS}.exchange_has', MagicMock(return_value=True))
exchange = get_patched_exchange(mocker, whitelist_conf)
pm = PairListManager(exchange, whitelist_conf, MagicMock())
pm.refresh_pairlist()
@@ -755,7 +755,7 @@ def test_PerformanceFilter_lookback(mocker, default_conf_usdt, fee, caplog) -> N
{"method": "StaticPairList"},
{"method": "PerformanceFilter", "minutes": 60, "min_profit": 0.01}
]
mocker.patch('freqtrade.exchange.Exchange.exchange_has', MagicMock(return_value=True))
mocker.patch(f'{EXMS}.exchange_has', MagicMock(return_value=True))
exchange = get_patched_exchange(mocker, default_conf_usdt)
pm = PairListManager(exchange, default_conf_usdt)
pm.refresh_pairlist()
@@ -781,7 +781,7 @@ def test_PerformanceFilter_keep_mid_order(mocker, default_conf_usdt, fee, caplog
{"method": "StaticPairList", "allow_inactive": True},
{"method": "PerformanceFilter", "minutes": 60, }
]
mocker.patch('freqtrade.exchange.Exchange.exchange_has', return_value=True)
mocker.patch(f'{EXMS}.exchange_has', return_value=True)
exchange = get_patched_exchange(mocker, default_conf_usdt)
pm = PairListManager(exchange, default_conf_usdt)
pm.refresh_pairlist()
@@ -806,7 +806,7 @@ def test_PerformanceFilter_keep_mid_order(mocker, default_conf_usdt, fee, caplog
def test_gen_pair_whitelist_not_supported(mocker, default_conf, tickers) -> None:
default_conf['pairlists'] = [{'method': 'VolumePairList', 'number_assets': 10}]
mocker.patch.multiple('freqtrade.exchange.Exchange',
mocker.patch.multiple(EXMS,
get_tickers=tickers,
exchange_has=MagicMock(return_value=False),
)
@@ -819,7 +819,7 @@ def test_gen_pair_whitelist_not_supported(mocker, default_conf, tickers) -> None
def test_pair_whitelist_not_supported_Spread(mocker, default_conf, tickers) -> None:
default_conf['pairlists'] = [{'method': 'StaticPairList'}, {'method': 'SpreadFilter'}]
mocker.patch.multiple('freqtrade.exchange.Exchange',
mocker.patch.multiple(EXMS,
get_tickers=tickers,
exchange_has=MagicMock(return_value=False),
)
@@ -832,7 +832,7 @@ def test_pair_whitelist_not_supported_Spread(mocker, default_conf, tickers) -> N
@pytest.mark.parametrize("pairlist", TESTABLE_PAIRLISTS)
def test_pairlist_class(mocker, whitelist_conf, markets, pairlist):
whitelist_conf['pairlists'][0]['method'] = pairlist
mocker.patch.multiple('freqtrade.exchange.Exchange',
mocker.patch.multiple(EXMS,
markets=PropertyMock(return_value=markets),
exchange_has=MagicMock(return_value=True)
)
@@ -861,7 +861,7 @@ def test_pairlist_class(mocker, whitelist_conf, markets, pairlist):
def test__whitelist_for_active_markets(mocker, whitelist_conf, markets, pairlist, whitelist, caplog,
log_message, tickers):
whitelist_conf['pairlists'][0]['method'] = pairlist
mocker.patch.multiple('freqtrade.exchange.Exchange',
mocker.patch.multiple(EXMS,
markets=PropertyMock(return_value=markets),
exchange_has=MagicMock(return_value=True),
get_tickers=tickers
@@ -881,10 +881,10 @@ def test__whitelist_for_active_markets(mocker, whitelist_conf, markets, pairlist
def test__whitelist_for_active_markets_empty(mocker, whitelist_conf, pairlist, tickers):
whitelist_conf['pairlists'][0]['method'] = pairlist
mocker.patch('freqtrade.exchange.Exchange.exchange_has', return_value=True)
mocker.patch(f'{EXMS}.exchange_has', return_value=True)
freqtrade = get_patched_freqtradebot(mocker, whitelist_conf)
mocker.patch.multiple('freqtrade.exchange.Exchange',
mocker.patch.multiple(EXMS,
markets=PropertyMock(return_value=None),
get_tickers=tickers
)
@@ -897,7 +897,7 @@ def test__whitelist_for_active_markets_empty(mocker, whitelist_conf, pairlist, t
def test_volumepairlist_invalid_sortvalue(mocker, whitelist_conf):
whitelist_conf['pairlists'][0].update({"sort_key": "asdf"})
mocker.patch('freqtrade.exchange.Exchange.exchange_has', MagicMock(return_value=True))
mocker.patch(f'{EXMS}.exchange_has', MagicMock(return_value=True))
with pytest.raises(OperationalException,
match=r"key asdf not in .*"):
get_patched_freqtradebot(mocker, whitelist_conf)
@@ -905,7 +905,7 @@ def test_volumepairlist_invalid_sortvalue(mocker, whitelist_conf):
def test_volumepairlist_caching(mocker, markets, whitelist_conf, tickers):
mocker.patch.multiple('freqtrade.exchange.Exchange',
mocker.patch.multiple(EXMS,
markets=PropertyMock(return_value=markets),
exchange_has=MagicMock(return_value=True),
get_tickers=tickers
@@ -925,7 +925,7 @@ def test_agefilter_min_days_listed_too_small(mocker, default_conf, markets, tick
default_conf['pairlists'] = [{'method': 'VolumePairList', 'number_assets': 10},
{'method': 'AgeFilter', 'min_days_listed': -1}]
mocker.patch.multiple('freqtrade.exchange.Exchange',
mocker.patch.multiple(EXMS,
markets=PropertyMock(return_value=markets),
exchange_has=MagicMock(return_value=True),
get_tickers=tickers
@@ -941,7 +941,7 @@ def test_agefilter_max_days_lower_than_min_days(mocker, default_conf, markets, t
{'method': 'AgeFilter', 'min_days_listed': 3,
"max_days_listed": 2}]
mocker.patch.multiple('freqtrade.exchange.Exchange',
mocker.patch.multiple(EXMS,
markets=PropertyMock(return_value=markets),
exchange_has=MagicMock(return_value=True),
get_tickers=tickers
@@ -956,7 +956,7 @@ def test_agefilter_min_days_listed_too_large(mocker, default_conf, markets, tick
default_conf['pairlists'] = [{'method': 'VolumePairList', 'number_assets': 10},
{'method': 'AgeFilter', 'min_days_listed': 99999}]
mocker.patch.multiple('freqtrade.exchange.Exchange',
mocker.patch.multiple(EXMS,
markets=PropertyMock(return_value=markets),
exchange_has=MagicMock(return_value=True),
get_tickers=tickers
@@ -976,7 +976,7 @@ def test_agefilter_caching(mocker, markets, whitelist_conf_agefilter, tickers, o
('LTC/BTC', '1d', CandleType.SPOT): ohlcv_history,
}
mocker.patch.multiple(
'freqtrade.exchange.Exchange',
EXMS,
markets=PropertyMock(return_value=markets),
exchange_has=MagicMock(return_value=True),
get_tickers=tickers,
@@ -1000,14 +1000,14 @@ def test_agefilter_caching(mocker, markets, whitelist_conf_agefilter, tickers, o
('LTC/BTC', '1d', CandleType.SPOT): ohlcv_history,
('XRP/BTC', '1d', CandleType.SPOT): ohlcv_history.iloc[[0]],
}
mocker.patch('freqtrade.exchange.Exchange.refresh_latest_ohlcv', return_value=ohlcv_data)
mocker.patch(f'{EXMS}.refresh_latest_ohlcv', return_value=ohlcv_data)
freqtrade.pairlists.refresh_pairlist()
assert len(freqtrade.pairlists.whitelist) == 3
assert freqtrade.exchange.refresh_latest_ohlcv.call_count == 1
# Move to next day
t.move_to("2021-09-02 01:00:00 +00:00")
mocker.patch('freqtrade.exchange.Exchange.refresh_latest_ohlcv', return_value=ohlcv_data)
mocker.patch(f'{EXMS}.refresh_latest_ohlcv', return_value=ohlcv_data)
freqtrade.pairlists.refresh_pairlist()
assert len(freqtrade.pairlists.whitelist) == 3
assert freqtrade.exchange.refresh_latest_ohlcv.call_count == 1
@@ -1021,7 +1021,7 @@ def test_agefilter_caching(mocker, markets, whitelist_conf_agefilter, tickers, o
('LTC/BTC', '1d', CandleType.SPOT): ohlcv_history,
('XRP/BTC', '1d', CandleType.SPOT): ohlcv_history,
}
mocker.patch('freqtrade.exchange.Exchange.refresh_latest_ohlcv', return_value=ohlcv_data)
mocker.patch(f'{EXMS}.refresh_latest_ohlcv', return_value=ohlcv_data)
freqtrade.pairlists.refresh_pairlist()
assert len(freqtrade.pairlists.whitelist) == 4
# Called once (only for XRP/BTC)
@@ -1033,7 +1033,7 @@ def test_OffsetFilter_error(mocker, whitelist_conf) -> None:
[{"method": "StaticPairList"}, {"method": "OffsetFilter", "offset": -1}]
)
mocker.patch('freqtrade.exchange.Exchange.exchange_has', MagicMock(return_value=True))
mocker.patch(f'{EXMS}.exchange_has', MagicMock(return_value=True))
with pytest.raises(OperationalException,
match=r'OffsetFilter requires offset to be >= 0'):
@@ -1044,7 +1044,7 @@ def test_rangestabilityfilter_checks(mocker, default_conf, markets, tickers):
default_conf['pairlists'] = [{'method': 'VolumePairList', 'number_assets': 10},
{'method': 'RangeStabilityFilter', 'lookback_days': 99999}]
mocker.patch.multiple('freqtrade.exchange.Exchange',
mocker.patch.multiple(EXMS,
markets=PropertyMock(return_value=markets),
exchange_has=MagicMock(return_value=True),
get_tickers=tickers
@@ -1074,7 +1074,7 @@ def test_rangestabilityfilter_caching(mocker, markets, default_conf, tickers, oh
'min_rate_of_change': min_rate_of_change,
"max_rate_of_change": max_rate_of_change}]
mocker.patch.multiple('freqtrade.exchange.Exchange',
mocker.patch.multiple(EXMS,
markets=PropertyMock(return_value=markets),
exchange_has=MagicMock(return_value=True),
get_tickers=tickers
@@ -1088,7 +1088,7 @@ def test_rangestabilityfilter_caching(mocker, markets, default_conf, tickers, oh
('BLK/BTC', '1d', CandleType.SPOT): ohlcv_history,
}
mocker.patch.multiple(
'freqtrade.exchange.Exchange',
EXMS,
refresh_latest_ohlcv=MagicMock(return_value=ohlcv_data),
)
@@ -1109,7 +1109,7 @@ def test_spreadfilter_invalid_data(mocker, default_conf, markets, tickers, caplo
default_conf['pairlists'] = [{'method': 'VolumePairList', 'number_assets': 10},
{'method': 'SpreadFilter', 'max_spread_ratio': 0.1}]
mocker.patch.multiple('freqtrade.exchange.Exchange',
mocker.patch.multiple(EXMS,
markets=PropertyMock(return_value=markets),
exchange_has=MagicMock(return_value=True),
get_tickers=tickers
@@ -1123,7 +1123,7 @@ def test_spreadfilter_invalid_data(mocker, default_conf, markets, tickers, caplo
tickers.return_value['ETH/BTC']['ask'] = 0.0
del tickers.return_value['TKN/BTC']
del tickers.return_value['LTC/BTC']
mocker.patch.multiple('freqtrade.exchange.Exchange', get_tickers=tickers)
mocker.patch.multiple(EXMS, get_tickers=tickers)
ftbot.pairlists.refresh_pairlist()
assert log_has_re(r'Removed .* invalid ticker data.*', caplog)
@@ -1197,7 +1197,7 @@ def test_spreadfilter_invalid_data(mocker, default_conf, markets, tickers, caplo
])
def test_pricefilter_desc(mocker, whitelist_conf, markets, pairlistconfig,
desc_expected, exception_expected):
mocker.patch.multiple('freqtrade.exchange.Exchange',
mocker.patch.multiple(EXMS,
markets=PropertyMock(return_value=markets),
exchange_has=MagicMock(return_value=True)
)
@@ -1214,7 +1214,7 @@ def test_pricefilter_desc(mocker, whitelist_conf, markets, pairlistconfig,
def test_pairlistmanager_no_pairlist(mocker, whitelist_conf):
mocker.patch('freqtrade.exchange.Exchange.exchange_has', MagicMock(return_value=True))
mocker.patch(f'{EXMS}.exchange_has', MagicMock(return_value=True))
whitelist_conf['pairlists'] = []
@@ -1266,14 +1266,14 @@ def test_performance_filter(mocker, whitelist_conf, pairlists, pair_allowlist, o
allowlist_conf['pairlists'] = pairlists
allowlist_conf['exchange']['pair_whitelist'] = pair_allowlist
mocker.patch('freqtrade.exchange.Exchange.exchange_has', MagicMock(return_value=True))
mocker.patch(f'{EXMS}.exchange_has', MagicMock(return_value=True))
freqtrade = get_patched_freqtradebot(mocker, allowlist_conf)
mocker.patch.multiple('freqtrade.exchange.Exchange',
mocker.patch.multiple(EXMS,
get_tickers=tickers,
markets=PropertyMock(return_value=markets)
)
mocker.patch.multiple('freqtrade.exchange.Exchange',
mocker.patch.multiple(EXMS,
get_historic_ohlcv=MagicMock(return_value=ohlcv_history_list),
)
mocker.patch.multiple('freqtrade.persistence.Trade',
@@ -1371,7 +1371,7 @@ def test_expand_pairlist_keep_invalid(wildcardlist, pairs, expected):
def test_ProducerPairlist_no_emc(mocker, whitelist_conf):
mocker.patch('freqtrade.exchange.Exchange.exchange_has', MagicMock(return_value=True))
mocker.patch(f'{EXMS}.exchange_has', MagicMock(return_value=True))
whitelist_conf['pairlists'] = [
{
@@ -1388,8 +1388,8 @@ def test_ProducerPairlist_no_emc(mocker, whitelist_conf):
def test_ProducerPairlist(mocker, whitelist_conf, markets):
mocker.patch('freqtrade.exchange.Exchange.exchange_has', MagicMock(return_value=True))
mocker.patch.multiple('freqtrade.exchange.Exchange',
mocker.patch(f'{EXMS}.exchange_has', MagicMock(return_value=True))
mocker.patch.multiple(EXMS,
markets=PropertyMock(return_value=markets),
exchange_has=MagicMock(return_value=True),
)

View File

@@ -1,6 +1,3 @@
# pragma pylint: disable=missing-docstring, C0103
# pragma pylint: disable=invalid-sequence-index, invalid-name, too-many-arguments
from copy import deepcopy
from datetime import datetime, timedelta, timezone
from unittest.mock import ANY, MagicMock, PropertyMock
@@ -15,19 +12,10 @@ from freqtrade.persistence import Trade
from freqtrade.persistence.pairlock_middleware import PairLocks
from freqtrade.rpc import RPC, RPCException
from freqtrade.rpc.fiat_convert import CryptoToFiatConverter
from tests.conftest import (create_mock_trades, create_mock_trades_usdt, get_patched_freqtradebot,
patch_get_signal)
from tests.conftest import (EXMS, create_mock_trades, create_mock_trades_usdt,
get_patched_freqtradebot, patch_get_signal)
# Functions for recurrent object patching
def prec_satoshi(a, b) -> float:
"""
:return: True if A and B differs less than one satoshi.
"""
return abs(a - b) < 0.00000001
# Unit tests
def test_rpc_trade_status(default_conf, ticker, fee, mocker) -> None:
gen_response = {
'trade_id': 1,
@@ -68,9 +56,6 @@ def test_rpc_trade_status(default_conf, ticker, fee, mocker) -> None:
'close_profit': None,
'close_profit_pct': None,
'close_profit_abs': None,
'current_profit': -0.00408133,
'current_profit_pct': -0.41,
'current_profit_abs': -4.09e-06,
'profit_ratio': -0.00408133,
'profit_pct': -0.41,
'profit_abs': -4.09e-06,
@@ -91,6 +76,8 @@ def test_rpc_trade_status(default_conf, ticker, fee, mocker) -> None:
'stoploss_entry_dist_ratio': -0.10376381,
'open_order': None,
'realized_profit': 0.0,
'total_profit_abs': -4.09e-06,
'total_profit_fiat': ANY,
'exchange': 'binance',
'leverage': 1.0,
'interest_rate': 0.0,
@@ -109,7 +96,7 @@ def test_rpc_trade_status(default_conf, ticker, fee, mocker) -> None:
}
mocker.patch('freqtrade.rpc.telegram.Telegram', MagicMock())
mocker.patch.multiple(
'freqtrade.exchange.Exchange',
EXMS,
fetch_ticker=ticker,
get_fee=fee,
_dry_is_price_crossed=MagicMock(side_effect=[False, True]),
@@ -134,9 +121,7 @@ def test_rpc_trade_status(default_conf, ticker, fee, mocker) -> None:
'profit_ratio': 0.0,
'profit_pct': 0.0,
'profit_abs': 0.0,
'current_profit': 0.0,
'current_profit_pct': 0.0,
'current_profit_abs': 0.0,
'total_profit_abs': 0.0,
'stop_loss_abs': 0.0,
'stop_loss_pct': None,
'stop_loss_ratio': None,
@@ -184,10 +169,10 @@ def test_rpc_trade_status(default_conf, ticker, fee, mocker) -> None:
response = deepcopy(gen_response)
assert results[0] == response
mocker.patch('freqtrade.exchange.Exchange.get_rate',
mocker.patch(f'{EXMS}.get_rate',
MagicMock(side_effect=ExchangeError("Pair 'ETH/BTC' not available")))
results = rpc._rpc_trade_status()
assert isnan(results[0]['current_profit'])
assert isnan(results[0]['profit_ratio'])
assert isnan(results[0]['current_rate'])
response_norate = deepcopy(gen_response)
# Update elements that are NaN when no rate is available.
@@ -198,9 +183,7 @@ def test_rpc_trade_status(default_conf, ticker, fee, mocker) -> None:
'profit_ratio': ANY,
'profit_pct': ANY,
'profit_abs': ANY,
'current_profit_abs': ANY,
'current_profit': ANY,
'current_profit_pct': ANY,
'total_profit_abs': ANY,
'current_rate': ANY,
})
assert results[0] == response_norate
@@ -214,7 +197,7 @@ def test_rpc_status_table(default_conf, ticker, fee, mocker) -> None:
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',
EXMS,
fetch_ticker=ticker,
get_fee=fee,
)
@@ -226,7 +209,7 @@ def test_rpc_status_table(default_conf, ticker, fee, mocker) -> None:
freqtradebot.state = State.RUNNING
with pytest.raises(RPCException, match=r'.*no active trade*'):
rpc._rpc_status_table(default_conf['stake_currency'], 'USD')
mocker.patch('freqtrade.exchange.Exchange._dry_is_price_crossed', return_value=False)
mocker.patch(f'{EXMS}._dry_is_price_crossed', return_value=False)
freqtradebot.enter_positions()
result, headers, fiat_profit_sum = rpc._rpc_status_table(default_conf['stake_currency'], 'USD')
@@ -237,7 +220,7 @@ def test_rpc_status_table(default_conf, ticker, fee, mocker) -> None:
assert '0.00' == result[0][3]
assert isnan(fiat_profit_sum)
mocker.patch('freqtrade.exchange.Exchange._dry_is_price_crossed', return_value=True)
mocker.patch(f'{EXMS}._dry_is_price_crossed', return_value=True)
freqtradebot.process()
result, headers, fiat_profit_sum = rpc._rpc_status_table(default_conf['stake_currency'], 'USD')
@@ -248,7 +231,7 @@ def test_rpc_status_table(default_conf, ticker, fee, mocker) -> None:
assert '-0.41%' == result[0][3]
assert isnan(fiat_profit_sum)
# Test with fiatconvert
# Test with fiat convert
rpc._fiat_converter = CryptoToFiatConverter()
result, headers, fiat_profit_sum = rpc._rpc_status_table(default_conf['stake_currency'], 'USD')
assert "Since" in headers
@@ -268,7 +251,7 @@ def test_rpc_status_table(default_conf, ticker, fee, mocker) -> None:
# 3 on top of the initial one.
assert result[0][4] == '1/4'
mocker.patch('freqtrade.exchange.Exchange.get_rate',
mocker.patch(f'{EXMS}.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]
@@ -281,7 +264,7 @@ def test__rpc_timeunit_profit(default_conf_usdt, ticker, fee,
limit_buy_order, limit_sell_order, markets, mocker) -> None:
mocker.patch('freqtrade.rpc.telegram.Telegram', MagicMock())
mocker.patch.multiple(
'freqtrade.exchange.Exchange',
EXMS,
fetch_ticker=ticker,
get_fee=fee,
markets=PropertyMock(return_value=markets)
@@ -322,7 +305,7 @@ def test__rpc_timeunit_profit(default_conf_usdt, ticker, fee,
def test_rpc_trade_history(mocker, default_conf, markets, fee, is_short):
mocker.patch('freqtrade.rpc.telegram.Telegram', MagicMock())
mocker.patch.multiple(
'freqtrade.exchange.Exchange',
EXMS,
markets=PropertyMock(return_value=markets)
)
@@ -350,7 +333,7 @@ def test_rpc_delete_trade(mocker, default_conf, fee, markets, caplog, is_short):
stoploss_mock = MagicMock()
cancel_mock = MagicMock()
mocker.patch.multiple(
'freqtrade.exchange.Exchange',
EXMS,
markets=PropertyMock(return_value=markets),
cancel_order=cancel_mock,
cancel_stoploss_order=stoploss_mock,
@@ -384,15 +367,13 @@ def test_rpc_delete_trade(mocker, default_conf, fee, markets, caplog, is_short):
assert stoploss_mock.call_count == 1
assert res['cancel_order_count'] == 2
stoploss_mock = mocker.patch('freqtrade.exchange.Exchange.cancel_stoploss_order',
side_effect=InvalidOrderException)
stoploss_mock = mocker.patch(f'{EXMS}.cancel_stoploss_order', side_effect=InvalidOrderException)
res = rpc._rpc_delete('3')
assert stoploss_mock.call_count == 1
stoploss_mock.reset_mock()
cancel_mock = mocker.patch('freqtrade.exchange.Exchange.cancel_order',
side_effect=InvalidOrderException)
cancel_mock = mocker.patch(f'{EXMS}.cancel_order', side_effect=InvalidOrderException)
res = rpc._rpc_delete('4')
assert cancel_mock.call_count == 1
@@ -403,7 +384,7 @@ def test_rpc_trade_statistics(default_conf_usdt, ticker, fee, mocker) -> None:
mocker.patch('freqtrade.rpc.rpc.CryptoToFiatConverter._find_price', return_value=1.1)
mocker.patch('freqtrade.rpc.telegram.Telegram', MagicMock())
mocker.patch.multiple(
'freqtrade.exchange.Exchange',
EXMS,
fetch_ticker=ticker,
get_fee=fee,
)
@@ -440,7 +421,7 @@ def test_rpc_trade_statistics(default_conf_usdt, ticker, fee, mocker) -> None:
assert stats['best_rate'] == 10.0
# Test non-available pair
mocker.patch('freqtrade.exchange.Exchange.get_rate',
mocker.patch(f'{EXMS}.get_rate',
MagicMock(side_effect=ExchangeError("Pair 'XRP/USDT' not available")))
stats = rpc._rpc_trade_statistics(stake_currency, fiat_display_currency)
assert stats['trade_count'] == 7
@@ -474,7 +455,7 @@ def test_rpc_balance_handle_error(default_conf, 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',
EXMS,
get_balances=MagicMock(return_value=mock_balance),
get_tickers=MagicMock(side_effect=TemporaryError('Could not load ticker due to xxx'))
)
@@ -537,7 +518,7 @@ def test_rpc_balance_handle(default_conf, mocker, tickers):
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',
EXMS,
validate_trading_mode_and_margin_mode=MagicMock(),
get_balances=MagicMock(return_value=mock_balance),
fetch_positions=MagicMock(return_value=mock_pos),
@@ -553,8 +534,8 @@ def test_rpc_balance_handle(default_conf, mocker, tickers):
rpc._fiat_converter = CryptoToFiatConverter()
result = rpc._rpc_balance(default_conf['stake_currency'], default_conf['fiat_display_currency'])
assert prec_satoshi(result['total'], 30.30909624)
assert prec_satoshi(result['value'], 454636.44360691)
assert pytest.approx(result['total']) == 30.30909624
assert pytest.approx(result['value']) == 454636.44360691
assert tickers.call_count == 1
assert tickers.call_args_list[0][1]['cached'] is True
assert 'USD' == result['symbol']
@@ -614,7 +595,7 @@ def test_rpc_balance_handle(default_conf, mocker, tickers):
def test_rpc_start(mocker, default_conf) -> None:
mocker.patch('freqtrade.rpc.telegram.Telegram', MagicMock())
mocker.patch.multiple(
'freqtrade.exchange.Exchange',
EXMS,
fetch_ticker=MagicMock()
)
@@ -635,7 +616,7 @@ def test_rpc_start(mocker, default_conf) -> None:
def test_rpc_stop(mocker, default_conf) -> None:
mocker.patch('freqtrade.rpc.telegram.Telegram', MagicMock())
mocker.patch.multiple(
'freqtrade.exchange.Exchange',
EXMS,
fetch_ticker=MagicMock()
)
@@ -657,7 +638,7 @@ def test_rpc_stop(mocker, default_conf) -> None:
def test_rpc_stopentry(mocker, default_conf) -> None:
mocker.patch('freqtrade.rpc.telegram.Telegram', MagicMock())
mocker.patch.multiple(
'freqtrade.exchange.Exchange',
EXMS,
fetch_ticker=MagicMock()
)
@@ -677,7 +658,7 @@ def test_rpc_force_exit(default_conf, ticker, fee, mocker) -> None:
cancel_order_mock = MagicMock()
mocker.patch.multiple(
'freqtrade.exchange.Exchange',
EXMS,
fetch_ticker=ticker,
cancel_order=cancel_order_mock,
fetch_order=MagicMock(
@@ -725,15 +706,14 @@ def test_rpc_force_exit(default_conf, ticker, fee, mocker) -> None:
freqtradebot.state = State.RUNNING
assert cancel_order_mock.call_count == 0
mocker.patch(
'freqtrade.exchange.Exchange._dry_is_price_crossed', MagicMock(return_value=False))
mocker.patch(f'{EXMS}._dry_is_price_crossed', MagicMock(return_value=False))
freqtradebot.enter_positions()
# make an limit-buy open trade
trade = Trade.query.filter(Trade.id == '3').first()
filled_amount = trade.amount / 2
# Fetch order - it's open first, and closed after cancel_order is called.
mocker.patch(
'freqtrade.exchange.Exchange.fetch_order',
f'{EXMS}.fetch_order',
side_effect=[{
'id': trade.orders[0].order_id,
'status': 'open',
@@ -755,7 +735,7 @@ def test_rpc_force_exit(default_conf, ticker, fee, mocker) -> None:
assert pytest.approx(trade.amount) == filled_amount
mocker.patch(
'freqtrade.exchange.Exchange.fetch_order',
f'{EXMS}.fetch_order',
return_value={
'status': 'open',
'type': 'limit',
@@ -769,7 +749,7 @@ def test_rpc_force_exit(default_conf, ticker, fee, mocker) -> None:
amount = trade.amount
# make an limit-buy open trade, if there is no 'filled', don't sell it
mocker.patch(
'freqtrade.exchange.Exchange.fetch_order',
f'{EXMS}.fetch_order',
return_value={
'status': 'open',
'type': 'limit',
@@ -787,7 +767,7 @@ def test_rpc_force_exit(default_conf, ticker, fee, mocker) -> None:
# make an limit-sell open trade
mocker.patch(
'freqtrade.exchange.Exchange.fetch_order',
f'{EXMS}.fetch_order',
return_value={
'status': 'open',
'type': 'limit',
@@ -807,7 +787,7 @@ def test_rpc_force_exit(default_conf, ticker, fee, mocker) -> None:
def test_performance_handle(default_conf_usdt, ticker, fee, mocker) -> None:
mocker.patch('freqtrade.rpc.telegram.Telegram', MagicMock())
mocker.patch.multiple(
'freqtrade.exchange.Exchange',
EXMS,
get_balances=MagicMock(return_value=ticker),
fetch_ticker=ticker,
get_fee=fee,
@@ -830,7 +810,7 @@ def test_enter_tag_performance_handle(default_conf, ticker, fee, mocker) -> None
mocker.patch('freqtrade.rpc.telegram.Telegram', MagicMock())
mocker.patch.multiple(
'freqtrade.exchange.Exchange',
EXMS,
get_balances=MagicMock(return_value=ticker),
fetch_ticker=ticker,
get_fee=fee,
@@ -862,7 +842,7 @@ def test_enter_tag_performance_handle(default_conf, ticker, fee, mocker) -> None
def test_enter_tag_performance_handle_2(mocker, default_conf, markets, fee):
mocker.patch('freqtrade.rpc.telegram.Telegram', MagicMock())
mocker.patch.multiple(
'freqtrade.exchange.Exchange',
EXMS,
markets=PropertyMock(return_value=markets)
)
@@ -875,23 +855,23 @@ def test_enter_tag_performance_handle_2(mocker, default_conf, markets, fee):
assert len(res) == 2
assert res[0]['enter_tag'] == 'TEST1'
assert res[0]['count'] == 1
assert prec_satoshi(res[0]['profit_pct'], 0.5)
assert pytest.approx(res[0]['profit_pct']) == 0.5
assert res[1]['enter_tag'] == 'Other'
assert res[1]['count'] == 1
assert prec_satoshi(res[1]['profit_pct'], 1.0)
assert pytest.approx(res[1]['profit_pct']) == 1.0
# Test for a specific pair
res = rpc._rpc_enter_tag_performance('ETC/BTC')
assert len(res) == 1
assert res[0]['count'] == 1
assert res[0]['enter_tag'] == 'TEST1'
assert prec_satoshi(res[0]['profit_pct'], 0.5)
assert pytest.approx(res[0]['profit_pct']) == 0.5
def test_exit_reason_performance_handle(default_conf_usdt, ticker, fee, mocker) -> None:
mocker.patch('freqtrade.rpc.telegram.Telegram', MagicMock())
mocker.patch.multiple(
'freqtrade.exchange.Exchange',
EXMS,
get_balances=MagicMock(return_value=ticker),
fetch_ticker=ticker,
get_fee=fee,
@@ -918,7 +898,7 @@ def test_exit_reason_performance_handle(default_conf_usdt, ticker, fee, mocker)
def test_exit_reason_performance_handle_2(mocker, default_conf, markets, fee):
mocker.patch('freqtrade.rpc.telegram.Telegram', MagicMock())
mocker.patch.multiple(
'freqtrade.exchange.Exchange',
EXMS,
markets=PropertyMock(return_value=markets)
)
@@ -931,23 +911,23 @@ def test_exit_reason_performance_handle_2(mocker, default_conf, markets, fee):
assert len(res) == 2
assert res[0]['exit_reason'] == 'sell_signal'
assert res[0]['count'] == 1
assert prec_satoshi(res[0]['profit_pct'], 0.5)
assert pytest.approx(res[0]['profit_pct']) == 0.5
assert res[1]['exit_reason'] == 'roi'
assert res[1]['count'] == 1
assert prec_satoshi(res[1]['profit_pct'], 1.0)
assert pytest.approx(res[1]['profit_pct']) == 1.0
# Test for a specific pair
res = rpc._rpc_exit_reason_performance('ETC/BTC')
assert len(res) == 1
assert res[0]['count'] == 1
assert res[0]['exit_reason'] == 'sell_signal'
assert prec_satoshi(res[0]['profit_pct'], 0.5)
assert pytest.approx(res[0]['profit_pct']) == 0.5
def test_mix_tag_performance_handle(default_conf, ticker, fee, mocker) -> None:
mocker.patch('freqtrade.rpc.telegram.Telegram', MagicMock())
mocker.patch.multiple(
'freqtrade.exchange.Exchange',
EXMS,
get_balances=MagicMock(return_value=ticker),
fetch_ticker=ticker,
get_fee=fee,
@@ -971,7 +951,7 @@ def test_mix_tag_performance_handle(default_conf, ticker, fee, mocker) -> None:
def test_mix_tag_performance_handle_2(mocker, default_conf, markets, fee):
mocker.patch('freqtrade.rpc.telegram.Telegram', MagicMock())
mocker.patch.multiple(
'freqtrade.exchange.Exchange',
EXMS,
markets=PropertyMock(return_value=markets)
)
@@ -984,10 +964,10 @@ def test_mix_tag_performance_handle_2(mocker, default_conf, markets, fee):
assert len(res) == 2
assert res[0]['mix_tag'] == 'TEST1 sell_signal'
assert res[0]['count'] == 1
assert prec_satoshi(res[0]['profit_pct'], 0.5)
assert pytest.approx(res[0]['profit_pct']) == 0.5
assert res[1]['mix_tag'] == 'Other roi'
assert res[1]['count'] == 1
assert prec_satoshi(res[1]['profit_pct'], 1.0)
assert pytest.approx(res[1]['profit_pct']) == 1.0
# Test for a specific pair
res = rpc._rpc_mix_tag_performance('ETC/BTC')
@@ -995,13 +975,13 @@ def test_mix_tag_performance_handle_2(mocker, default_conf, markets, fee):
assert len(res) == 1
assert res[0]['count'] == 1
assert res[0]['mix_tag'] == 'TEST1 sell_signal'
assert prec_satoshi(res[0]['profit_pct'], 0.5)
assert pytest.approx(res[0]['profit_pct']) == 0.5
def test_rpc_count(mocker, default_conf, ticker, fee) -> None:
mocker.patch('freqtrade.rpc.telegram.Telegram', MagicMock())
mocker.patch.multiple(
'freqtrade.exchange.Exchange',
EXMS,
get_balances=MagicMock(return_value=ticker),
fetch_ticker=ticker,
get_fee=fee,
@@ -1026,7 +1006,7 @@ def test_rpc_force_entry(mocker, default_conf, ticker, fee, limit_buy_order_open
mocker.patch('freqtrade.rpc.telegram.Telegram', MagicMock())
buy_mm = MagicMock(return_value=limit_buy_order_open)
mocker.patch.multiple(
'freqtrade.exchange.Exchange',
EXMS,
get_balances=MagicMock(return_value=ticker),
fetch_ticker=ticker,
get_fee=fee,
@@ -1155,7 +1135,7 @@ def test_rpc_whitelist_dynamic(mocker, default_conf) -> None:
default_conf['pairlists'] = [{'method': 'VolumePairList',
'number_assets': 4,
}]
mocker.patch('freqtrade.exchange.Exchange.exchange_has', MagicMock(return_value=True))
mocker.patch(f'{EXMS}.exchange_has', MagicMock(return_value=True))
mocker.patch('freqtrade.rpc.telegram.Telegram', MagicMock())
freqtradebot = get_patched_freqtradebot(mocker, default_conf)
@@ -1252,6 +1232,6 @@ def test_rpc_health(mocker, default_conf) -> None:
freqtradebot = get_patched_freqtradebot(mocker, default_conf)
rpc = RPC(freqtradebot)
result = rpc._health()
assert result['last_process'] == '1970-01-01 00:00:00+00:00'
assert result['last_process_ts'] == 0
result = rpc.health()
assert result['last_process'] is None
assert result['last_process_ts'] is None

View File

@@ -24,7 +24,7 @@ from freqtrade.rpc import RPC
from freqtrade.rpc.api_server import ApiServer
from freqtrade.rpc.api_server.api_auth import create_token, get_user_from_token
from freqtrade.rpc.api_server.uvicorn_threaded import UvicornServer
from tests.conftest import (CURRENT_TEST_STRATEGY, create_mock_trades, get_mock_coro,
from tests.conftest import (CURRENT_TEST_STRATEGY, EXMS, create_mock_trades, get_mock_coro,
get_patched_freqtradebot, log_has, log_has_re, patch_get_signal)
@@ -473,9 +473,9 @@ def test_api_balance(botclient, mocker, rpc_balance, tickers):
ftbot, client = botclient
ftbot.config['dry_run'] = False
mocker.patch('freqtrade.exchange.Exchange.get_balances', return_value=rpc_balance)
mocker.patch('freqtrade.exchange.Exchange.get_tickers', tickers)
mocker.patch('freqtrade.exchange.Exchange.get_valid_pair_combination',
mocker.patch(f'{EXMS}.get_balances', return_value=rpc_balance)
mocker.patch(f'{EXMS}.get_tickers', tickers)
mocker.patch(f'{EXMS}.get_valid_pair_combination',
side_effect=lambda a, b: f"{a}/{b}")
ftbot.wallets.update()
@@ -507,7 +507,7 @@ def test_api_count(botclient, mocker, ticker, fee, markets, is_short):
ftbot, client = botclient
patch_get_signal(ftbot)
mocker.patch.multiple(
'freqtrade.exchange.Exchange',
EXMS,
get_balances=MagicMock(return_value=ticker),
fetch_ticker=ticker,
get_fee=fee,
@@ -594,7 +594,7 @@ def test_api_daily(botclient, mocker, ticker, fee, markets):
ftbot, client = botclient
patch_get_signal(ftbot)
mocker.patch.multiple(
'freqtrade.exchange.Exchange',
EXMS,
get_balances=MagicMock(return_value=ticker),
fetch_ticker=ticker,
get_fee=fee,
@@ -613,7 +613,7 @@ def test_api_trades(botclient, mocker, fee, markets, is_short):
ftbot, client = botclient
patch_get_signal(ftbot)
mocker.patch.multiple(
'freqtrade.exchange.Exchange',
EXMS,
markets=PropertyMock(return_value=markets)
)
rc = client_get(client, f"{BASE_URI}/trades")
@@ -644,7 +644,7 @@ def test_api_trade_single(botclient, mocker, fee, ticker, markets, is_short):
ftbot, client = botclient
patch_get_signal(ftbot, enter_long=not is_short, enter_short=is_short)
mocker.patch.multiple(
'freqtrade.exchange.Exchange',
EXMS,
markets=PropertyMock(return_value=markets),
fetch_ticker=ticker,
)
@@ -668,7 +668,7 @@ def test_api_delete_trade(botclient, mocker, fee, markets, is_short):
stoploss_mock = MagicMock()
cancel_mock = MagicMock()
mocker.patch.multiple(
'freqtrade.exchange.Exchange',
EXMS,
markets=PropertyMock(return_value=markets),
cancel_order=cancel_mock,
cancel_stoploss_order=stoploss_mock,
@@ -713,7 +713,7 @@ def test_api_delete_open_order(botclient, mocker, fee, markets, ticker, is_short
stoploss_mock = MagicMock()
cancel_mock = MagicMock()
mocker.patch.multiple(
'freqtrade.exchange.Exchange',
EXMS,
markets=PropertyMock(return_value=markets),
fetch_ticker=ticker,
cancel_order=cancel_mock,
@@ -731,15 +731,13 @@ def test_api_delete_open_order(botclient, mocker, fee, markets, ticker, is_short
assert_response(rc, 502)
assert 'No open order for trade_id' in rc.json()['error']
trade = Trade.get_trades([Trade.id == 6]).first()
mocker.patch('freqtrade.exchange.Exchange.fetch_order',
side_effect=ExchangeError)
mocker.patch(f'{EXMS}.fetch_order', side_effect=ExchangeError)
rc = client_delete(client, f"{BASE_URI}/trades/6/open-order")
assert_response(rc, 502)
assert 'Order not found.' in rc.json()['error']
trade = Trade.get_trades([Trade.id == 6]).first()
mocker.patch('freqtrade.exchange.Exchange.fetch_order',
return_value=trade.orders[-1].to_ccxt_object())
mocker.patch(f'{EXMS}.fetch_order', return_value=trade.orders[-1].to_ccxt_object())
rc = client_delete(client, f"{BASE_URI}/trades/6/open-order")
assert_response(rc)
@@ -782,7 +780,7 @@ def test_api_edge_disabled(botclient, mocker, ticker, fee, markets):
ftbot, client = botclient
patch_get_signal(ftbot)
mocker.patch.multiple(
'freqtrade.exchange.Exchange',
EXMS,
get_balances=MagicMock(return_value=ticker),
fetch_ticker=ticker,
get_fee=fee,
@@ -844,7 +842,7 @@ def test_api_profit(botclient, mocker, ticker, fee, markets, is_short, expected)
ftbot, client = botclient
patch_get_signal(ftbot)
mocker.patch.multiple(
'freqtrade.exchange.Exchange',
EXMS,
get_balances=MagicMock(return_value=ticker),
fetch_ticker=ticker,
get_fee=fee,
@@ -902,7 +900,7 @@ def test_api_stats(botclient, mocker, ticker, fee, markets, is_short):
ftbot, client = botclient
patch_get_signal(ftbot, enter_long=not is_short, enter_short=is_short)
mocker.patch.multiple(
'freqtrade.exchange.Exchange',
EXMS,
get_balances=MagicMock(return_value=ticker),
fetch_ticker=ticker,
get_fee=fee,
@@ -983,7 +981,7 @@ def test_api_status(botclient, mocker, ticker, fee, markets, is_short,
ftbot, client = botclient
patch_get_signal(ftbot)
mocker.patch.multiple(
'freqtrade.exchange.Exchange',
EXMS,
get_balances=MagicMock(return_value=ticker),
fetch_ticker=ticker,
get_fee=fee,
@@ -1008,13 +1006,13 @@ def test_api_status(botclient, mocker, ticker, fee, markets, is_short,
'close_profit_pct': None,
'close_profit_abs': None,
'close_rate': None,
'current_profit': ANY,
'current_profit_pct': ANY,
'current_profit_abs': ANY,
'profit_ratio': ANY,
'profit_pct': ANY,
'profit_abs': ANY,
'profit_fiat': ANY,
'total_profit_abs': ANY,
'total_profit_fiat': ANY,
'realized_profit': 0.0,
'current_rate': current_rate,
'open_date': ANY,
'open_timestamp': ANY,
@@ -1068,7 +1066,7 @@ def test_api_status(botclient, mocker, ticker, fee, markets, is_short,
'orders': [ANY],
}
mocker.patch('freqtrade.exchange.Exchange.get_rate',
mocker.patch(f'{EXMS}.get_rate',
MagicMock(side_effect=ExchangeError("Pair 'ETH/BTC' not available")))
rc = client_get(client, f"{BASE_URI}/status")
@@ -1181,7 +1179,7 @@ def test_api_force_entry(botclient, mocker, fee, endpoint):
ftbot.config['force_entry_enable'] = True
fbuy_mock = MagicMock(return_value=None)
mocker.patch("freqtrade.rpc.RPC._rpc_force_entry", fbuy_mock)
mocker.patch("freqtrade.rpc.rpc.RPC._rpc_force_entry", fbuy_mock)
rc = client_post(client, f"{BASE_URI}/{endpoint}",
data={"pair": "ETH/BTC"})
assert_response(rc)
@@ -1207,7 +1205,7 @@ def test_api_force_entry(botclient, mocker, fee, endpoint):
strategy=CURRENT_TEST_STRATEGY,
trading_mode=TradingMode.SPOT
))
mocker.patch("freqtrade.rpc.RPC._rpc_force_entry", fbuy_mock)
mocker.patch("freqtrade.rpc.rpc.RPC._rpc_force_entry", fbuy_mock)
rc = client_post(client, f"{BASE_URI}/{endpoint}",
data={"pair": "ETH/BTC"})
@@ -1244,6 +1242,7 @@ def test_api_force_entry(botclient, mocker, fee, endpoint):
'profit_pct': None,
'profit_abs': None,
'profit_fiat': None,
'realized_profit': 0.0,
'fee_close': 0.0025,
'fee_close_cost': None,
'fee_close_currency': None,
@@ -1275,7 +1274,7 @@ def test_api_force_entry(botclient, mocker, fee, endpoint):
def test_api_forceexit(botclient, mocker, ticker, fee, markets):
ftbot, client = botclient
mocker.patch.multiple(
'freqtrade.exchange.Exchange',
EXMS,
get_balances=MagicMock(return_value=ticker),
fetch_ticker=ticker,
get_fee=fee,
@@ -1630,7 +1629,7 @@ def test_sysinfo(botclient):
def test_api_backtesting(botclient, mocker, fee, caplog, tmpdir):
ftbot, client = botclient
mocker.patch('freqtrade.exchange.Exchange.get_fee', fee)
mocker.patch(f'{EXMS}.get_fee', fee)
rc = client_get(client, f"{BASE_URI}/backtest")
# Backtest prevented in default mode
@@ -1737,9 +1736,15 @@ def test_api_backtesting(botclient, mocker, fee, caplog, tmpdir):
data['stake_amount'] = 101
mocker.patch('freqtrade.optimize.backtesting.Backtesting.backtest_one_strategy',
side_effect=DependencyException())
side_effect=DependencyException('DeadBeef'))
rc = client_post(client, f"{BASE_URI}/backtest", data=data)
assert log_has("Backtesting caused an error: ", caplog)
assert log_has("Backtesting caused an error: DeadBeef", caplog)
rc = client_get(client, f"{BASE_URI}/backtest")
assert_response(rc)
result = rc.json()
assert result['status'] == 'error'
assert 'Backtest failed' in result['status_msg']
# Delete backtesting to avoid leakage since the backtest-object may stick around.
rc = client_delete(client, f"{BASE_URI}/backtest")
@@ -1795,8 +1800,8 @@ def test_health(botclient):
assert_response(rc)
ret = rc.json()
assert ret['last_process_ts'] == 0
assert ret['last_process'] == '1970-01-01T00:00:00+00:00'
assert ret["last_process_ts"] is None
assert ret["last_process"] is None
def test_api_ws_subscribe(botclient, mocker):

View File

@@ -20,7 +20,8 @@ from telegram.error import BadRequest, NetworkError, TelegramError
from freqtrade import __version__
from freqtrade.constants import CANCEL_REASON
from freqtrade.edge import PairInfo
from freqtrade.enums import ExitType, RPCMessageType, RunMode, SignalDirection, State
from freqtrade.enums import (ExitType, MarketDirection, RPCMessageType, RunMode, SignalDirection,
State)
from freqtrade.exceptions import OperationalException
from freqtrade.freqtradebot import FreqtradeBot
from freqtrade.loggers import setup_logging
@@ -29,9 +30,9 @@ from freqtrade.persistence.models import Order
from freqtrade.rpc import RPC
from freqtrade.rpc.rpc import RPCException
from freqtrade.rpc.telegram import Telegram, authorized_only
from tests.conftest import (CURRENT_TEST_STRATEGY, create_mock_trades, create_mock_trades_usdt,
get_patched_freqtradebot, log_has, log_has_re, patch_exchange,
patch_get_signal, patch_whitelist)
from tests.conftest import (CURRENT_TEST_STRATEGY, EXMS, create_mock_trades,
create_mock_trades_usdt, get_patched_freqtradebot, log_has, log_has_re,
patch_exchange, patch_get_signal, patch_whitelist)
class DummyCls(Telegram):
@@ -106,7 +107,7 @@ def test_telegram_init(default_conf, mocker, caplog) -> None:
"['reload_config', 'reload_conf'], ['show_config', 'show_conf'], "
"['stopbuy', 'stopentry'], ['whitelist'], ['blacklist'], "
"['blacklist_delete', 'bl_delete'], "
"['logs'], ['edge'], ['health'], ['help'], ['version']"
"['logs'], ['edge'], ['health'], ['help'], ['version'], ['marketdir']"
"]")
assert log_has(message_str, caplog)
@@ -202,6 +203,9 @@ def test_telegram_status(default_conf, update, mocker) -> None:
'close_profit_ratio': None,
'profit': -0.0059,
'profit_ratio': -0.0059,
'profit_abs': -0.225,
'realized_profit': 0.0,
'total_profit_abs': -0.225,
'initial_stop_loss_abs': 1.098e-05,
'stop_loss_abs': 1.099e-05,
'exit_order_status': None,
@@ -236,7 +240,7 @@ def test_telegram_status_multi_entry(default_conf, update, mocker, fee) -> None:
default_conf['telegram']['chat_id'] = "123"
default_conf['position_adjustment_enable'] = True
mocker.patch.multiple(
'freqtrade.exchange.Exchange',
EXMS,
fetch_order=MagicMock(return_value=None),
get_rate=MagicMock(return_value=0.22),
)
@@ -275,6 +279,7 @@ def test_telegram_status_multi_entry(default_conf, update, mocker, fee) -> None:
assert msg_mock.call_count == 4
msg = msg_mock.call_args_list[0][0][0]
assert re.search(r'Number of Entries.*2', msg)
assert re.search(r'Number of Exits.*0', msg)
assert re.search(r'Average Entry Price', msg)
assert re.search(r'Order filled', msg)
assert re.search(r'Close Date:', msg) is None
@@ -288,7 +293,7 @@ def test_telegram_status_closed_trade(default_conf, update, mocker, fee) -> None
default_conf['telegram']['chat_id'] = "123"
default_conf['position_adjustment_enable'] = True
mocker.patch.multiple(
'freqtrade.exchange.Exchange',
EXMS,
fetch_order=MagicMock(return_value=None),
get_rate=MagicMock(return_value=0.22),
)
@@ -310,7 +315,7 @@ def test_telegram_status_closed_trade(default_conf, update, mocker, fee) -> None
def test_status_handle(default_conf, update, ticker, fee, mocker) -> None:
default_conf['max_open_trades'] = 3
mocker.patch.multiple(
'freqtrade.exchange.Exchange',
EXMS,
fetch_ticker=ticker,
get_fee=fee,
_dry_is_price_crossed=MagicMock(return_value=True),
@@ -387,7 +392,7 @@ def test_status_handle(default_conf, update, ticker, fee, mocker) -> None:
def test_status_table_handle(default_conf, update, ticker, fee, mocker) -> None:
mocker.patch.multiple(
'freqtrade.exchange.Exchange',
EXMS,
fetch_ticker=ticker,
get_fee=fee,
)
@@ -432,7 +437,7 @@ def test_daily_handle(default_conf_usdt, update, ticker, fee, mocker, time_machi
return_value=1.1
)
mocker.patch.multiple(
'freqtrade.exchange.Exchange',
EXMS,
fetch_ticker=ticker,
get_fee=fee,
)
@@ -487,7 +492,7 @@ def test_daily_handle(default_conf_usdt, update, ticker, fee, mocker, time_machi
def test_daily_wrong_input(default_conf, update, ticker, mocker) -> None:
mocker.patch.multiple(
'freqtrade.exchange.Exchange',
EXMS,
fetch_ticker=ticker
)
@@ -521,7 +526,7 @@ def test_weekly_handle(default_conf_usdt, update, ticker, fee, mocker, time_mach
return_value=1.1
)
mocker.patch.multiple(
'freqtrade.exchange.Exchange',
EXMS,
fetch_ticker=ticker,
get_fee=fee,
)
@@ -591,7 +596,7 @@ def test_monthly_handle(default_conf_usdt, update, ticker, fee, mocker, time_mac
return_value=1.1
)
mocker.patch.multiple(
'freqtrade.exchange.Exchange',
EXMS,
fetch_ticker=ticker,
get_fee=fee,
)
@@ -672,7 +677,7 @@ def test_profit_handle(default_conf_usdt, update, ticker_usdt, ticker_sell_up, f
limit_sell_order_usdt, mocker) -> None:
mocker.patch('freqtrade.rpc.rpc.CryptoToFiatConverter._find_price', return_value=1.1)
mocker.patch.multiple(
'freqtrade.exchange.Exchange',
EXMS,
fetch_ticker=ticker_usdt,
get_fee=fee,
)
@@ -702,7 +707,7 @@ def test_profit_handle(default_conf_usdt, update, ticker_usdt, ticker_sell_up, f
msg_mock.reset_mock()
# Update the ticker with a market going up
mocker.patch('freqtrade.exchange.Exchange.fetch_ticker', ticker_sell_up)
mocker.patch(f'{EXMS}.fetch_ticker', ticker_sell_up)
# Simulate fulfilled LIMIT_SELL order for trade
oobj = Order.parse_from_ccxt_object(
limit_sell_order_usdt, limit_sell_order_usdt['symbol'], 'sell')
@@ -735,7 +740,7 @@ def test_profit_handle(default_conf_usdt, update, ticker_usdt, ticker_sell_up, f
def test_telegram_stats(default_conf, update, ticker, fee, mocker, is_short) -> None:
mocker.patch('freqtrade.rpc.rpc.CryptoToFiatConverter._find_price', return_value=15000.0)
mocker.patch.multiple(
'freqtrade.exchange.Exchange',
EXMS,
fetch_ticker=ticker,
get_fee=fee,
)
@@ -760,10 +765,9 @@ def test_telegram_stats(default_conf, update, ticker, fee, mocker, is_short) ->
def test_telegram_balance_handle(default_conf, update, mocker, rpc_balance, tickers) -> None:
default_conf['dry_run'] = False
mocker.patch('freqtrade.exchange.Exchange.get_balances', return_value=rpc_balance)
mocker.patch('freqtrade.exchange.Exchange.get_tickers', tickers)
mocker.patch('freqtrade.exchange.Exchange.get_valid_pair_combination',
side_effect=lambda a, b: f"{a}/{b}")
mocker.patch(f'{EXMS}.get_balances', return_value=rpc_balance)
mocker.patch(f'{EXMS}.get_tickers', tickers)
mocker.patch(f'{EXMS}.get_valid_pair_combination', side_effect=lambda a, b: f"{a}/{b}")
telegram, freqtradebot, msg_mock = get_telegram_testobject(mocker, default_conf)
patch_get_signal(freqtradebot)
@@ -786,7 +790,7 @@ def test_telegram_balance_handle(default_conf, update, mocker, rpc_balance, tick
def test_balance_handle_empty_response(default_conf, update, mocker) -> None:
default_conf['dry_run'] = False
mocker.patch('freqtrade.exchange.Exchange.get_balances', return_value={})
mocker.patch(f'{EXMS}.get_balances', return_value={})
telegram, freqtradebot, msg_mock = get_telegram_testobject(mocker, default_conf)
patch_get_signal(freqtradebot)
@@ -799,7 +803,7 @@ def test_balance_handle_empty_response(default_conf, update, mocker) -> None:
def test_balance_handle_empty_response_dry(default_conf, update, mocker) -> None:
mocker.patch('freqtrade.exchange.Exchange.get_balances', return_value={})
mocker.patch(f'{EXMS}.get_balances', return_value={})
telegram, freqtradebot, msg_mock = get_telegram_testobject(mocker, default_conf)
patch_get_signal(freqtradebot)
@@ -927,7 +931,7 @@ def test_telegram_forceexit_handle(default_conf, update, ticker, fee,
patch_exchange(mocker)
patch_whitelist(mocker, default_conf)
mocker.patch.multiple(
'freqtrade.exchange.Exchange',
EXMS,
fetch_ticker=ticker,
get_fee=fee,
_dry_is_price_crossed=MagicMock(return_value=True),
@@ -945,7 +949,7 @@ def test_telegram_forceexit_handle(default_conf, update, ticker, fee,
assert trade
# Increase the price and sell it
mocker.patch('freqtrade.exchange.Exchange.fetch_ticker', ticker_sell_up)
mocker.patch(f'{EXMS}.fetch_ticker', ticker_sell_up)
# /forceexit 1
context = MagicMock()
@@ -996,7 +1000,7 @@ def test_telegram_force_exit_down_handle(default_conf, update, ticker, fee,
patch_whitelist(mocker, default_conf)
mocker.patch.multiple(
'freqtrade.exchange.Exchange',
EXMS,
fetch_ticker=ticker,
get_fee=fee,
_dry_is_price_crossed=MagicMock(return_value=True),
@@ -1012,7 +1016,7 @@ def test_telegram_force_exit_down_handle(default_conf, update, ticker, fee,
# Decrease the price and sell it
mocker.patch.multiple(
'freqtrade.exchange.Exchange',
EXMS,
fetch_ticker=ticker_sell_down
)
@@ -1067,7 +1071,7 @@ def test_forceexit_all_handle(default_conf, update, ticker, fee, mocker) -> None
mocker.patch('freqtrade.rpc.telegram.Telegram._init', MagicMock())
patch_whitelist(mocker, default_conf)
mocker.patch.multiple(
'freqtrade.exchange.Exchange',
EXMS,
fetch_ticker=ticker,
get_fee=fee,
_dry_is_price_crossed=MagicMock(return_value=True),
@@ -1152,7 +1156,7 @@ def test_forceexit_handle_invalid(default_conf, update, mocker) -> None:
def test_force_exit_no_pair(default_conf, update, ticker, fee, mocker) -> None:
default_conf['max_open_trades'] = 4
mocker.patch.multiple(
'freqtrade.exchange.Exchange',
EXMS,
fetch_ticker=ticker,
get_fee=fee,
_dry_is_price_crossed=MagicMock(return_value=True),
@@ -1206,7 +1210,7 @@ def test_force_enter_handle(default_conf, update, mocker) -> None:
mocker.patch('freqtrade.rpc.rpc.CryptoToFiatConverter._find_price', return_value=15000.0)
fbuy_mock = MagicMock(return_value=None)
mocker.patch('freqtrade.rpc.RPC._rpc_force_entry', fbuy_mock)
mocker.patch('freqtrade.rpc.rpc.RPC._rpc_force_entry', fbuy_mock)
telegram, freqtradebot, _ = get_telegram_testobject(mocker, default_conf)
patch_get_signal(freqtradebot)
@@ -1223,7 +1227,7 @@ def test_force_enter_handle(default_conf, update, mocker) -> None:
# Reset and retry with specified price
fbuy_mock = MagicMock(return_value=None)
mocker.patch('freqtrade.rpc.RPC._rpc_force_entry', fbuy_mock)
mocker.patch('freqtrade.rpc.rpc.RPC._rpc_force_entry', fbuy_mock)
# /forcelong ETH/BTC 0.055
context = MagicMock()
context.args = ["ETH/BTC", "0.055"]
@@ -1252,7 +1256,7 @@ def test_force_enter_no_pair(default_conf, update, mocker) -> None:
mocker.patch('freqtrade.rpc.rpc.CryptoToFiatConverter._find_price', return_value=15000.0)
fbuy_mock = MagicMock(return_value=None)
mocker.patch('freqtrade.rpc.RPC._rpc_force_entry', fbuy_mock)
mocker.patch('freqtrade.rpc.rpc.RPC._rpc_force_entry', fbuy_mock)
telegram, freqtradebot, msg_mock = get_telegram_testobject(mocker, default_conf)
@@ -1279,7 +1283,7 @@ def test_force_enter_no_pair(default_conf, update, mocker) -> None:
def test_telegram_performance_handle(default_conf_usdt, update, ticker, fee, mocker) -> None:
mocker.patch.multiple(
'freqtrade.exchange.Exchange',
EXMS,
fetch_ticker=ticker,
get_fee=fee,
)
@@ -1297,7 +1301,7 @@ def test_telegram_performance_handle(default_conf_usdt, update, ticker, fee, moc
def test_telegram_entry_tag_performance_handle(
default_conf_usdt, update, ticker, fee, mocker) -> None:
mocker.patch.multiple(
'freqtrade.exchange.Exchange',
EXMS,
fetch_ticker=ticker,
get_fee=fee,
)
@@ -1328,7 +1332,7 @@ def test_telegram_entry_tag_performance_handle(
def test_telegram_exit_reason_performance_handle(default_conf_usdt, update, ticker, fee,
mocker) -> None:
mocker.patch.multiple(
'freqtrade.exchange.Exchange',
EXMS,
fetch_ticker=ticker,
get_fee=fee,
)
@@ -1359,7 +1363,7 @@ def test_telegram_exit_reason_performance_handle(default_conf_usdt, update, tick
def test_telegram_mix_tag_performance_handle(default_conf_usdt, update, ticker, fee,
mocker) -> None:
mocker.patch.multiple(
'freqtrade.exchange.Exchange',
EXMS,
fetch_ticker=ticker,
get_fee=fee,
)
@@ -1391,7 +1395,7 @@ def test_telegram_mix_tag_performance_handle(default_conf_usdt, update, ticker,
def test_count_handle(default_conf, update, ticker, fee, mocker) -> None:
mocker.patch.multiple(
'freqtrade.exchange.Exchange',
EXMS,
fetch_ticker=ticker,
get_fee=fee,
)
@@ -1420,7 +1424,7 @@ def test_count_handle(default_conf, update, ticker, fee, mocker) -> None:
def test_telegram_lock_handle(default_conf, update, ticker, fee, mocker) -> None:
mocker.patch.multiple(
'freqtrade.exchange.Exchange',
EXMS,
fetch_ticker=ticker,
get_fee=fee,
)
@@ -1488,7 +1492,7 @@ def test_whitelist_static(default_conf, update, mocker) -> None:
def test_whitelist_dynamic(default_conf, update, mocker) -> None:
mocker.patch('freqtrade.exchange.Exchange.exchange_has', MagicMock(return_value=True))
mocker.patch(f'{EXMS}.exchange_has', return_value=True)
default_conf['pairlists'] = [{'method': 'VolumePairList',
'number_assets': 4
}]
@@ -1682,7 +1686,7 @@ def test_telegram_delete_trade(mocker, update, default_conf, fee, is_short):
def test_telegram_delete_open_order(mocker, update, default_conf, fee, is_short, ticker):
mocker.patch.multiple(
'freqtrade.exchange.Exchange',
EXMS,
fetch_ticker=ticker,
)
telegram, _, msg_mock = get_telegram_testobject(mocker, default_conf)
@@ -1703,8 +1707,7 @@ def test_telegram_delete_open_order(mocker, update, default_conf, fee, is_short,
msg_mock.reset_mock()
trade = Trade.get_trades([Trade.id == 6]).first()
mocker.patch('freqtrade.exchange.Exchange.fetch_order',
return_value=trade.orders[-1].to_ccxt_object())
mocker.patch(f'{EXMS}.fetch_order', return_value=trade.orders[-1].to_ccxt_object())
context = MagicMock()
context.args = [6]
telegram._cancel_open_order(update=update, context=context)
@@ -2394,3 +2397,15 @@ def test__send_msg_keyboard(default_conf, mocker, caplog) -> None:
assert log_has("using custom keyboard from config.json: "
"[['/daily', '/stats', '/balance', '/profit', '/profit 5'], ['/count', "
"'/start', '/reload_config', '/help']]", caplog)
def test_change_market_direction(default_conf, mocker, update) -> None:
telegram, _, msg_mock = get_telegram_testobject(mocker, default_conf)
assert telegram._rpc._freqtrade.strategy.market_direction == MarketDirection.NONE
context = MagicMock()
context.args = ["long"]
telegram._changemarketdir(update, context)
assert telegram._rpc._freqtrade.strategy.market_direction == MarketDirection.LONG
context = MagicMock()
context.args = ["invalid"]
assert telegram._rpc._freqtrade.strategy.market_direction == MarketDirection.LONG

View File

@@ -356,6 +356,14 @@ def test_exception_send_msg(default_conf, mocker, caplog):
}
webhook.send_msg(msg)
# Test no failure for not implemented but known messagetypes
for e in RPCMessageType:
msg = {
'type': e,
'status': 'whatever'
}
webhook.send_msg(msg)
def test__send_msg(default_conf, mocker, caplog):
default_conf["webhook"] = get_webhook_dict()

View File

@@ -7,6 +7,7 @@ from datetime import datetime
from pandas import DataFrame
from freqtrade.persistence.trade_model import Order
from freqtrade.strategy.interface import IStrategy
@@ -35,7 +36,7 @@ class TestStrategyImplementBuyTimeout(TestStrategyNoImplementSell):
def populate_exit_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
return super().populate_exit_trend(dataframe, metadata)
def check_buy_timeout(self, pair: str, trade, order: dict,
def check_buy_timeout(self, pair: str, trade, order: Order,
current_time: datetime, **kwargs) -> bool:
return False
@@ -44,6 +45,6 @@ class TestStrategyImplementSellTimeout(TestStrategyNoImplementSell):
def populate_exit_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
return super().populate_exit_trend(dataframe, metadata)
def check_sell_timeout(self, pair: str, trade, order: dict,
def check_sell_timeout(self, pair: str, trade, order: Order,
current_time: datetime, **kwargs) -> bool:
return False

View File

@@ -197,7 +197,7 @@ class StrategyTestV3(IStrategy):
if current_profit < -0.0075:
orders = trade.select_filled_orders(trade.entry_side)
return round(orders[0].cost, 0)
return round(orders[0].safe_cost, 0)
return None

View File

@@ -214,12 +214,12 @@ def test_ignore_expired_candle(default_conf):
current_time = latest_date + timedelta(seconds=30 + 300)
assert not strategy.ignore_expired_candle(
assert strategy.ignore_expired_candle(
latest_date=latest_date,
current_time=current_time,
timeframe_seconds=300,
enter=True
) is True
) is not True
def test_assert_df_raise(mocker, caplog, ohlcv_history):
@@ -291,18 +291,6 @@ def test_advise_all_indicators(default_conf, testdatadir) -> None:
assert len(processed['UNITTEST/BTC']) == 103
def test_populate_any_indicators(default_conf, testdatadir) -> None:
strategy = StrategyResolver.load_strategy(default_conf)
timerange = TimeRange.parse_timerange('1510694220-1510700340')
data = load_data(testdatadir, '1m', ['UNITTEST/BTC'], timerange=timerange,
fill_up_missing=True)
processed = strategy.populate_any_indicators('UNITTEST/BTC', data, '5m')
assert processed == data
assert id(processed) == id(data)
assert len(processed['UNITTEST/BTC']) == 103
def test_freqai_not_initialized(default_conf) -> None:
strategy = StrategyResolver.load_strategy(default_conf)
strategy.ft_bot_start()

View File

@@ -119,53 +119,54 @@ def test_merge_informative_pair_suffix_append_timeframe():
merge_informative_pair(data, informative, '15m', '1h', suffix="suf")
def test_stoploss_from_open():
@pytest.mark.parametrize("side,profitrange", [
# profit range for long is [-1, inf] while for shorts is [-inf, 1]
("long", [-0.99, 2, 30]),
("short", [-2.0, 0.99, 30]),
])
def test_stoploss_from_open(side, profitrange):
open_price_ranges = [
[0.01, 1.00, 30],
[1, 100, 30],
[100, 10000, 30],
]
# profit range for long is [-1, inf] while for shorts is [-inf, 1]
current_profit_range_dict = {'long': [-0.99, 2, 30], 'short': [-2.0, 0.99, 30]}
desired_stop_range = [-0.50, 0.50, 30]
for side, current_profit_range in current_profit_range_dict.items():
for open_range in open_price_ranges:
for open_price in np.linspace(*open_range):
for desired_stop in np.linspace(*desired_stop_range):
for open_range in open_price_ranges:
for open_price in np.linspace(*open_range):
for desired_stop in np.linspace(-0.50, 0.50, 30):
if side == 'long':
# -1 is not a valid current_profit, should return 1
assert stoploss_from_open(desired_stop, -1) == 1
else:
# 1 is not a valid current_profit for shorts, should return 1
assert stoploss_from_open(desired_stop, 1, True) == 1
for current_profit in np.linspace(*profitrange):
if side == 'long':
# -1 is not a valid current_profit, should return 1
assert stoploss_from_open(desired_stop, -1) == 1
current_price = open_price * (1 + current_profit)
expected_stop_price = open_price * (1 + desired_stop)
stoploss = stoploss_from_open(desired_stop, current_profit)
stop_price = current_price * (1 - stoploss)
else:
# 1 is not a valid current_profit for shorts, should return 1
assert stoploss_from_open(desired_stop, 1, True) == 1
current_price = open_price * (1 - current_profit)
expected_stop_price = open_price * (1 - desired_stop)
stoploss = stoploss_from_open(desired_stop, current_profit, True)
stop_price = current_price * (1 + stoploss)
for current_profit in np.linspace(*current_profit_range):
if side == 'long':
current_price = open_price * (1 + current_profit)
expected_stop_price = open_price * (1 + desired_stop)
stoploss = stoploss_from_open(desired_stop, current_profit)
stop_price = current_price * (1 - stoploss)
else:
current_price = open_price * (1 - current_profit)
expected_stop_price = open_price * (1 - desired_stop)
stoploss = stoploss_from_open(desired_stop, current_profit, True)
stop_price = current_price * (1 + stoploss)
assert stoploss >= 0
# Technically the formula can yield values greater than 1 for shorts
# eventhough it doesn't make sense because the position would be liquidated
if side == 'long':
assert stoploss <= 1
assert stoploss >= 0
# Technically the formula can yield values greater than 1 for shorts
# eventhough it doesn't make sense because the position would be liquidated
if side == 'long':
assert stoploss <= 1
# there is no correct answer if the expected stop price is above
# the current price
if ((side == 'long' and expected_stop_price > current_price)
or (side == 'short' and expected_stop_price < current_price)):
assert stoploss == 0
else:
assert pytest.approx(stop_price) == expected_stop_price
# there is no correct answer if the expected stop price is above
# the current price
if ((side == 'long' and expected_stop_price > current_price)
or (side == 'short' and expected_stop_price < current_price)):
assert stoploss == 0
else:
assert pytest.approx(stop_price) == expected_stop_price
def test_stoploss_from_absolute():

View File

@@ -59,7 +59,7 @@ def test_load_config_incorrect_stake_amount(default_conf) -> None:
def test_load_config_file(default_conf, mocker, caplog) -> None:
del default_conf['user_data_dir']
default_conf['datadir'] = str(default_conf['datadir'])
file_mock = mocker.patch('freqtrade.configuration.load_config.open', mocker.mock_open(
file_mock = mocker.patch('freqtrade.configuration.load_config.Path.open', mocker.mock_open(
read_data=json.dumps(default_conf)
))
@@ -73,7 +73,8 @@ def test_load_config_file_error(default_conf, mocker, caplog) -> None:
default_conf['datadir'] = str(default_conf['datadir'])
filedata = json.dumps(default_conf).replace(
'"stake_amount": 0.001,', '"stake_amount": .001,')
mocker.patch('freqtrade.configuration.load_config.open', mocker.mock_open(read_data=filedata))
mocker.patch('freqtrade.configuration.load_config.Path.open',
mocker.mock_open(read_data=filedata))
mocker.patch.object(Path, "read_text", MagicMock(return_value=filedata))
with pytest.raises(OperationalException, match=r".*Please verify the following segment.*"):
@@ -272,7 +273,7 @@ def test_load_config_max_open_trades_minus_one(default_conf, mocker, caplog) ->
def test_load_config_file_exception(mocker) -> None:
mocker.patch(
'freqtrade.configuration.configuration.open',
'freqtrade.configuration.configuration.Path.open',
MagicMock(side_effect=FileNotFoundError('File not found'))
)
@@ -701,15 +702,16 @@ def test_set_loggers_journald(mocker):
'logfile': 'journald',
}
setup_logging_pre()
setup_logging(config)
assert len(logger.handlers) == 2
assert len(logger.handlers) == 3
assert [x for x in logger.handlers if type(x).__name__ == "JournaldLogHandler"]
assert [x for x in logger.handlers if type(x) == logging.StreamHandler]
# reset handlers to not break pytest
logger.handlers = orig_handlers
def test_set_loggers_journald_importerror(mocker, import_fails):
def test_set_loggers_journald_importerror(import_fails):
logger = logging.getLogger()
orig_handlers = logger.handlers
logger.handlers = []
@@ -718,7 +720,7 @@ def test_set_loggers_journald_importerror(mocker, import_fails):
'logfile': 'journald',
}
with pytest.raises(OperationalException,
match=r'You need the systemd python package.*'):
match=r'You need the cysystemd python package.*'):
setup_logging(config)
logger.handlers = orig_handlers

File diff suppressed because it is too large Load Diff

View File

@@ -6,7 +6,7 @@ from freqtrade.enums import ExitCheckTuple, ExitType, TradingMode
from freqtrade.persistence import Trade
from freqtrade.persistence.models import Order
from freqtrade.rpc.rpc import RPC
from tests.conftest import get_patched_freqtradebot, log_has_re, patch_get_signal
from tests.conftest import EXMS, get_patched_freqtradebot, log_has_re, patch_get_signal
def test_may_execute_exit_stoploss_on_exchange_multi(default_conf, ticker, fee,
@@ -56,9 +56,9 @@ def test_may_execute_exit_stoploss_on_exchange_multi(default_conf, ticker, fee,
[ExitCheckTuple(exit_type=ExitType.EXIT_SIGNAL)]]
)
cancel_order_mock = MagicMock()
mocker.patch('freqtrade.exchange.Binance.create_stoploss', stoploss)
mocker.patch('freqtrade.exchange.binance.Binance.create_stoploss', stoploss)
mocker.patch.multiple(
'freqtrade.exchange.Exchange',
EXMS,
fetch_ticker=ticker,
get_fee=fee,
amount_to_precision=lambda s, x, y: y,
@@ -147,7 +147,7 @@ def test_forcebuy_last_unlimited(default_conf, ticker, fee, mocker, balance_rati
default_conf['telegram']['enabled'] = True
mocker.patch('freqtrade.rpc.telegram.Telegram', MagicMock())
mocker.patch.multiple(
'freqtrade.exchange.Exchange',
EXMS,
fetch_ticker=ticker,
get_fee=fee,
amount_to_precision=lambda s, x, y: y,
@@ -217,7 +217,7 @@ def test_dca_buying(default_conf_usdt, ticker_usdt, fee, mocker) -> None:
freqtrade = get_patched_freqtradebot(mocker, default_conf_usdt)
mocker.patch.multiple(
'freqtrade.exchange.Exchange',
EXMS,
fetch_ticker=ticker_usdt,
get_fee=fee,
)
@@ -239,7 +239,7 @@ def test_dca_buying(default_conf_usdt, ticker_usdt, fee, mocker) -> None:
# Reduce bid amount
ticker_usdt_modif = ticker_usdt.return_value
ticker_usdt_modif['bid'] = ticker_usdt_modif['bid'] * 0.995
mocker.patch('freqtrade.exchange.Exchange.fetch_ticker', return_value=ticker_usdt_modif)
mocker.patch(f'{EXMS}.fetch_ticker', return_value=ticker_usdt_modif)
# additional buy order
freqtrade.process()
@@ -286,7 +286,7 @@ def test_dca_short(default_conf_usdt, ticker_usdt, fee, mocker) -> None:
freqtrade = get_patched_freqtradebot(mocker, default_conf_usdt)
mocker.patch.multiple(
'freqtrade.exchange.Exchange',
EXMS,
fetch_ticker=ticker_usdt,
get_fee=fee,
amount_to_precision=lambda s, x, y: round(y, 4),
@@ -311,7 +311,7 @@ def test_dca_short(default_conf_usdt, ticker_usdt, fee, mocker) -> None:
# Reduce bid amount
ticker_usdt_modif = ticker_usdt.return_value
ticker_usdt_modif['ask'] = ticker_usdt_modif['ask'] * 1.004
mocker.patch('freqtrade.exchange.Exchange.fetch_ticker', return_value=ticker_usdt_modif)
mocker.patch(f'{EXMS}.fetch_ticker', return_value=ticker_usdt_modif)
# additional buy order
freqtrade.process()
@@ -361,16 +361,16 @@ def test_dca_order_adjust(default_conf_usdt, ticker_usdt, leverage, fee, mocker)
freqtrade = get_patched_freqtradebot(mocker, default_conf_usdt)
mocker.patch.multiple(
'freqtrade.exchange.Exchange',
EXMS,
fetch_ticker=ticker_usdt,
get_fee=fee,
amount_to_precision=lambda s, x, y: y,
price_to_precision=lambda s, x, y: y,
)
mocker.patch('freqtrade.exchange.Exchange._dry_is_price_crossed', return_value=False)
mocker.patch("freqtrade.exchange.Exchange.get_max_leverage", return_value=10)
mocker.patch("freqtrade.exchange.Exchange.get_funding_fees", return_value=0)
mocker.patch("freqtrade.exchange.Exchange.get_maintenance_ratio_and_amt", return_value=(0, 0))
mocker.patch(f'{EXMS}._dry_is_price_crossed', return_value=False)
mocker.patch(f"{EXMS}.get_max_leverage", return_value=10)
mocker.patch(f"{EXMS}.get_funding_fees", return_value=0)
mocker.patch(f"{EXMS}.get_maintenance_ratio_and_amt", return_value=(0, 0))
patch_get_signal(freqtrade)
freqtrade.strategy.custom_entry_price = lambda **kwargs: ticker_usdt['ask'] * 0.96
@@ -413,7 +413,7 @@ def test_dca_order_adjust(default_conf_usdt, ticker_usdt, leverage, fee, mocker)
assert trade.initial_stop_loss_pct is None
# Fill order
mocker.patch('freqtrade.exchange.Exchange._dry_is_price_crossed', return_value=True)
mocker.patch(f'{EXMS}._dry_is_price_crossed', return_value=True)
freqtrade.process()
trade = Trade.get_trades().first()
assert len(trade.orders) == 2
@@ -428,7 +428,7 @@ def test_dca_order_adjust(default_conf_usdt, ticker_usdt, leverage, fee, mocker)
# 2nd order - not filling
freqtrade.strategy.adjust_trade_position = MagicMock(return_value=120)
mocker.patch('freqtrade.exchange.Exchange._dry_is_price_crossed', return_value=False)
mocker.patch(f'{EXMS}._dry_is_price_crossed', return_value=False)
freqtrade.process()
trade = Trade.get_trades().first()
@@ -452,7 +452,7 @@ def test_dca_order_adjust(default_conf_usdt, ticker_usdt, leverage, fee, mocker)
# Fill DCA order
freqtrade.strategy.adjust_trade_position = MagicMock(return_value=None)
mocker.patch('freqtrade.exchange.Exchange._dry_is_price_crossed', return_value=True)
mocker.patch(f'{EXMS}._dry_is_price_crossed', return_value=True)
freqtrade.strategy.adjust_entry_price = MagicMock(side_effect=ValueError)
freqtrade.process()
@@ -477,14 +477,14 @@ def test_dca_exiting(default_conf_usdt, ticker_usdt, fee, mocker, caplog, levera
freqtrade = get_patched_freqtradebot(mocker, default_conf_usdt)
freqtrade.trading_mode = TradingMode.FUTURES
mocker.patch.multiple(
'freqtrade.exchange.Exchange',
EXMS,
fetch_ticker=ticker_usdt,
get_fee=fee,
amount_to_precision=lambda s, x, y: y,
price_to_precision=lambda s, x, y: y,
get_min_pair_stake_amount=MagicMock(return_value=10),
)
mocker.patch("freqtrade.exchange.Exchange.get_max_leverage", return_value=10)
mocker.patch(f"{EXMS}.get_max_leverage", return_value=10)
patch_get_signal(freqtrade)
freqtrade.strategy.leverage = MagicMock(return_value=leverage)
@@ -532,8 +532,7 @@ def test_dca_exiting(default_conf_usdt, ticker_usdt, fee, mocker, caplog, levera
assert trade.is_open
# use amount that would trunc to 0.0 once selling
mocker.patch("freqtrade.exchange.Exchange.amount_to_contract_precision",
lambda s, p, v: round(v, 1))
mocker.patch(f"{EXMS}.amount_to_contract_precision", lambda s, p, v: round(v, 1))
freqtrade.strategy.adjust_trade_position = MagicMock(return_value=-0.01)
freqtrade.process()
trade = Trade.get_trades().first()

View File

@@ -46,7 +46,7 @@ def test_shorten_date() -> None:
def test_file_dump_json(mocker) -> None:
file_open = mocker.patch('freqtrade.misc.open', MagicMock())
file_open = mocker.patch('freqtrade.misc.Path.open', MagicMock())
json_dump = mocker.patch('rapidjson.dump', MagicMock())
file_dump_json(Path('somefile'), [1, 2, 3])
assert file_open.call_count == 1

View File

@@ -6,13 +6,13 @@ import pytest
from freqtrade.constants import UNLIMITED_STAKE_AMOUNT
from freqtrade.exceptions import DependencyException
from tests.conftest import create_mock_trades, get_patched_freqtradebot, patch_wallet
from tests.conftest import EXMS, create_mock_trades, get_patched_freqtradebot, patch_wallet
def test_sync_wallet_at_boot(mocker, default_conf):
default_conf['dry_run'] = False
mocker.patch.multiple(
'freqtrade.exchange.Exchange',
EXMS,
get_balances=MagicMock(return_value={
"BNT": {
"free": 1.0,
@@ -45,7 +45,7 @@ def test_sync_wallet_at_boot(mocker, default_conf):
assert 'USDT' in freqtrade.wallets._wallets
assert freqtrade.wallets._last_wallet_refresh > 0
mocker.patch.multiple(
'freqtrade.exchange.Exchange',
EXMS,
get_balances=MagicMock(return_value={
"BNT": {
"free": 1.2,
@@ -87,7 +87,7 @@ def test_sync_wallet_at_boot(mocker, default_conf):
def test_sync_wallet_missing_data(mocker, default_conf):
default_conf['dry_run'] = False
mocker.patch.multiple(
'freqtrade.exchange.Exchange',
EXMS,
get_balances=MagicMock(return_value={
"BNT": {
"free": 1.0,
@@ -136,7 +136,7 @@ def test_get_trade_stake_amount_unlimited_amount(default_conf, ticker, balance_r
result1, result2, limit_buy_order_open,
fee, mocker) -> None:
mocker.patch.multiple(
'freqtrade.exchange.Exchange',
EXMS,
fetch_ticker=ticker,
create_order=MagicMock(return_value=limit_buy_order_open),
get_fee=fee
@@ -312,7 +312,7 @@ def test_sync_wallet_futures_live(mocker, default_conf):
}
]
mocker.patch.multiple(
'freqtrade.exchange.Exchange',
EXMS,
get_balances=MagicMock(return_value={
"USDT": {
"free": 900,

View File

@@ -8,11 +8,11 @@ import time_machine
from freqtrade.data.dataprovider import DataProvider
from freqtrade.enums import State
from freqtrade.worker import Worker
from tests.conftest import get_patched_worker, log_has, log_has_re
from tests.conftest import EXMS, get_patched_worker, log_has, log_has_re
def test_worker_state(mocker, default_conf, markets) -> None:
mocker.patch('freqtrade.exchange.Exchange.markets', PropertyMock(return_value=markets))
mocker.patch(f'{EXMS}.markets', PropertyMock(return_value=markets))
worker = get_patched_worker(mocker, default_conf)
assert worker.freqtrade.state is State.RUNNING