merge upstream

This commit is contained in:
மனோஜ்குமார் பழனிச்சாமி
2022-05-03 19:59:23 +05:30
145 changed files with 7072 additions and 5772 deletions

View File

@@ -52,7 +52,8 @@ def test_rpc_trade_status(default_conf, ticker, fee, mocker) -> None:
assert results[0] == {
'trade_id': 1,
'pair': 'ETH/BTC',
'base_currency': 'BTC',
'base_currency': 'ETH',
'quote_currency': 'BTC',
'open_date': ANY,
'open_timestamp': ANY,
'is_open': ANY,
@@ -136,7 +137,8 @@ def test_rpc_trade_status(default_conf, ticker, fee, mocker) -> None:
assert results[0] == {
'trade_id': 1,
'pair': 'ETH/BTC',
'base_currency': 'BTC',
'base_currency': 'ETH',
'quote_currency': 'BTC',
'open_date': ANY,
'open_timestamp': ANY,
'is_open': ANY,

View File

@@ -13,7 +13,6 @@ import uvicorn
from fastapi import FastAPI
from fastapi.exceptions import HTTPException
from fastapi.testclient import TestClient
from numpy import isnan
from requests.auth import _basic_auth_str
from freqtrade.__init__ import __version__
@@ -931,6 +930,8 @@ def test_api_status(botclient, mocker, ticker, fee, markets, is_short,
'open_order': None,
'open_rate': 0.123,
'pair': 'ETH/BTC',
'base_currency': 'ETH',
'quote_currency': 'BTC',
'stake_amount': 0.001,
'stop_loss_abs': ANY,
'stop_loss_pct': ANY,
@@ -983,7 +984,7 @@ def test_api_status(botclient, mocker, ticker, fee, markets, is_short,
assert_response(rc)
resp_values = rc.json()
assert len(resp_values) == 4
assert isnan(resp_values[0]['profit_abs'])
assert resp_values[0]['profit_abs'] is None
def test_api_version(botclient):
@@ -1097,7 +1098,7 @@ def test_api_force_entry(botclient, mocker, fee, endpoint):
# Test creating trade
fbuy_mock = MagicMock(return_value=Trade(
pair='ETH/ETH',
pair='ETH/BTC',
amount=1,
amount_requested=1,
exchange='binance',
@@ -1130,7 +1131,9 @@ def test_api_force_entry(botclient, mocker, fee, endpoint):
'open_date': ANY,
'open_timestamp': ANY,
'open_rate': 0.245441,
'pair': 'ETH/ETH',
'pair': 'ETH/BTC',
'base_currency': 'ETH',
'quote_currency': 'BTC',
'stake_amount': 1,
'stop_loss_abs': None,
'stop_loss_pct': None,
@@ -1178,7 +1181,7 @@ def test_api_force_entry(botclient, mocker, fee, endpoint):
}
def test_api_forcesell(botclient, mocker, ticker, fee, markets):
def test_api_forceexit(botclient, mocker, ticker, fee, markets):
ftbot, client = botclient
mocker.patch.multiple(
'freqtrade.exchange.Exchange',
@@ -1190,15 +1193,15 @@ def test_api_forcesell(botclient, mocker, ticker, fee, markets):
)
patch_get_signal(ftbot)
rc = client_post(client, f"{BASE_URI}/forcesell",
rc = client_post(client, f"{BASE_URI}/forceexit",
data='{"tradeid": "1"}')
assert_response(rc, 502)
assert rc.json() == {"error": "Error querying /api/v1/forcesell: invalid argument"}
assert rc.json() == {"error": "Error querying /api/v1/forceexit: invalid argument"}
Trade.query.session.rollback()
ftbot.enter_positions()
rc = client_post(client, f"{BASE_URI}/forcesell",
rc = client_post(client, f"{BASE_URI}/forceexit",
data='{"tradeid": "1"}')
assert_response(rc)
assert rc.json() == {'result': 'Created sell order for trade 1.'}
@@ -1385,7 +1388,6 @@ def test_api_strategies(botclient):
'StrategyTestV2',
'StrategyTestV3',
'StrategyTestV3Futures',
'TestStrategyLegacyV1',
]}
@@ -1481,7 +1483,7 @@ def test_api_backtesting(botclient, mocker, fee, caplog, tmpdir):
assert not result['running']
assert result['status_msg'] == 'Backtest reset'
ftbot.config['export'] = 'trades'
ftbot.config['backtest_cache'] = 'none'
ftbot.config['backtest_cache'] = 'day'
ftbot.config['user_data_dir'] = Path(tmpdir)
ftbot.config['exportfilename'] = Path(tmpdir) / "backtest_results"
ftbot.config['exportfilename'].mkdir()
@@ -1554,19 +1556,19 @@ def test_api_backtesting(botclient, mocker, fee, caplog, tmpdir):
ApiServer._bgtask_running = False
mocker.patch('freqtrade.optimize.backtesting.Backtesting.backtest_one_strategy',
side_effect=DependencyException())
rc = client_post(client, f"{BASE_URI}/backtest", data=json.dumps(data))
assert log_has("Backtesting caused an error: ", caplog)
ftbot.config['backtest_cache'] = 'day'
# Rerun backtest (should get previous result)
rc = client_post(client, f"{BASE_URI}/backtest", data=json.dumps(data))
assert_response(rc)
result = rc.json()
assert log_has_re('Reusing result of previous backtest.*', caplog)
data['stake_amount'] = 101
mocker.patch('freqtrade.optimize.backtesting.Backtesting.backtest_one_strategy',
side_effect=DependencyException())
rc = client_post(client, f"{BASE_URI}/backtest", data=json.dumps(data))
assert log_has("Backtesting caused an error: ", caplog)
# Delete backtesting to avoid leakage since the backtest-object may stick around.
rc = client_delete(client, f"{BASE_URI}/backtest")
assert_response(rc)
@@ -1577,6 +1579,38 @@ def test_api_backtesting(botclient, mocker, fee, caplog, tmpdir):
assert result['status_msg'] == 'Backtest reset'
def test_api_backtest_history(botclient, mocker, testdatadir):
ftbot, client = botclient
mocker.patch('freqtrade.data.btanalysis._get_backtest_files',
return_value=[
testdatadir / 'backtest_results/backtest-result_multistrat.json',
testdatadir / 'backtest_results/backtest-result_new.json'
])
rc = client_get(client, f"{BASE_URI}/backtest/history")
assert_response(rc, 502)
ftbot.config['user_data_dir'] = testdatadir
ftbot.config['runmode'] = RunMode.WEBSERVER
rc = client_get(client, f"{BASE_URI}/backtest/history")
assert_response(rc)
result = rc.json()
assert len(result) == 3
fn = result[0]['filename']
assert fn == "backtest-result_multistrat.json"
strategy = result[0]['strategy']
rc = client_get(client, f"{BASE_URI}/backtest/history/result?filename={fn}&strategy={strategy}")
assert_response(rc)
result2 = rc.json()
assert result2
assert result2['status'] == 'ended'
assert not result2['running']
assert result2['progress'] == 1
# Only one strategy loaded - even though we use multiresult
assert len(result2['backtest_result']['strategy']) == 1
assert result2['backtest_result']['strategy'][strategy]
def test_health(botclient):
ftbot, client = botclient

View File

@@ -184,7 +184,8 @@ def test_telegram_status(default_conf, update, mocker) -> None:
_rpc_trade_status=MagicMock(return_value=[{
'trade_id': 1,
'pair': 'ETH/BTC',
'base_currency': 'BTC',
'base_currency': 'ETH',
'quote_currency': 'BTC',
'open_date': arrow.utcnow(),
'close_date': None,
'open_rate': 1.099e-05,
@@ -398,8 +399,8 @@ def test_status_table_handle(default_conf, update, ticker, fee, mocker) -> None:
fields = re.sub('[ ]+', ' ', line[2].strip()).split(' ')
assert int(fields[0]) == 1
assert 'L' in fields[1]
assert 'ETH/BTC' in fields[2]
# assert 'L' in fields[1]
assert 'ETH/BTC' in fields[1]
assert msg_mock.call_count == 1
@@ -1016,7 +1017,7 @@ def test_reload_config_handle(default_conf, update, mocker) -> None:
assert 'Reloading config' in msg_mock.call_args_list[0][0][0]
def test_telegram_forcesell_handle(default_conf, update, ticker, fee,
def test_telegram_forceexit_handle(default_conf, update, ticker, fee,
ticker_sell_up, mocker) -> None:
mocker.patch('freqtrade.rpc.rpc.CryptoToFiatConverter._find_price', return_value=15000.0)
msg_mock = mocker.patch('freqtrade.rpc.telegram.Telegram.send_msg', MagicMock())
@@ -1044,7 +1045,7 @@ def test_telegram_forcesell_handle(default_conf, update, ticker, fee,
# Increase the price and sell it
mocker.patch('freqtrade.exchange.Exchange.fetch_ticker', ticker_sell_up)
# /forcesell 1
# /forceexit 1
context = MagicMock()
context.args = ["1"]
telegram._force_exit(update=update, context=context)
@@ -1081,8 +1082,8 @@ def test_telegram_forcesell_handle(default_conf, update, ticker, fee,
} == last_msg
def test_telegram_forcesell_down_handle(default_conf, update, ticker, fee,
ticker_sell_down, mocker) -> None:
def test_telegram_force_exit_down_handle(default_conf, update, ticker, fee,
ticker_sell_down, mocker) -> None:
mocker.patch('freqtrade.rpc.fiat_convert.CryptoToFiatConverter._find_price',
return_value=15000.0)
msg_mock = mocker.patch('freqtrade.rpc.telegram.Telegram.send_msg', MagicMock())
@@ -1114,7 +1115,7 @@ def test_telegram_forcesell_down_handle(default_conf, update, ticker, fee,
trade = Trade.query.first()
assert trade
# /forcesell 1
# /forceexit 1
context = MagicMock()
context.args = ["1"]
telegram._force_exit(update=update, context=context)
@@ -1152,7 +1153,7 @@ def test_telegram_forcesell_down_handle(default_conf, update, ticker, fee,
} == last_msg
def test_forcesell_all_handle(default_conf, update, ticker, fee, mocker) -> None:
def test_forceexit_all_handle(default_conf, update, ticker, fee, mocker) -> None:
patch_exchange(mocker)
mocker.patch('freqtrade.rpc.fiat_convert.CryptoToFiatConverter._find_price',
return_value=15000.0)
@@ -1175,7 +1176,7 @@ def test_forcesell_all_handle(default_conf, update, ticker, fee, mocker) -> None
freqtradebot.enter_positions()
msg_mock.reset_mock()
# /forcesell all
# /forceexit all
context = MagicMock()
context.args = ["all"]
telegram._force_exit(update=update, context=context)
@@ -1213,7 +1214,7 @@ def test_forcesell_all_handle(default_conf, update, ticker, fee, mocker) -> None
} == msg
def test_forcesell_handle_invalid(default_conf, update, mocker) -> None:
def test_forceexit_handle_invalid(default_conf, update, mocker) -> None:
mocker.patch('freqtrade.rpc.fiat_convert.CryptoToFiatConverter._find_price',
return_value=15000.0)
@@ -1222,26 +1223,17 @@ def test_forcesell_handle_invalid(default_conf, update, mocker) -> None:
# Trader is not running
freqtradebot.state = State.STOPPED
# /forcesell 1
# /forceexit 1
context = MagicMock()
context.args = ["1"]
telegram._force_exit(update=update, context=context)
assert msg_mock.call_count == 1
assert 'not running' in msg_mock.call_args_list[0][0][0]
# No argument
msg_mock.reset_mock()
freqtradebot.state = State.RUNNING
context = MagicMock()
context.args = []
telegram._force_exit(update=update, context=context)
assert msg_mock.call_count == 1
assert "You must specify a trade-id or 'all'." in msg_mock.call_args_list[0][0][0]
# Invalid argument
msg_mock.reset_mock()
freqtradebot.state = State.RUNNING
# /forcesell 123456
# /forceexit 123456
context = MagicMock()
context.args = ["123456"]
telegram._force_exit(update=update, context=context)
@@ -1249,6 +1241,59 @@ def test_forcesell_handle_invalid(default_conf, update, mocker) -> None:
assert 'invalid argument' in msg_mock.call_args_list[0][0][0]
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',
fetch_ticker=ticker,
get_fee=fee,
_is_dry_limit_order_filled=MagicMock(return_value=True),
)
femock = mocker.patch('freqtrade.rpc.rpc.RPC._rpc_force_exit')
telegram, freqtradebot, msg_mock = get_telegram_testobject(mocker, default_conf)
patch_get_signal(freqtradebot)
# /forceexit
context = MagicMock()
context.args = []
telegram._force_exit(update=update, context=context)
# No pair
assert msg_mock.call_args_list[0][1]['msg'] == 'No open trade found.'
# Create some test data
freqtradebot.enter_positions()
msg_mock.reset_mock()
# /forceexit
telegram._force_exit(update=update, context=context)
keyboard = msg_mock.call_args_list[0][1]['keyboard']
# 4 pairs + cancel
assert reduce(lambda acc, x: acc + len(x), keyboard, 0) == 5
assert keyboard[-1][0].text == "Cancel"
assert keyboard[1][0].callback_data == 'force_exit__2 '
update = MagicMock()
update.callback_query = MagicMock()
update.callback_query.data = keyboard[1][0].callback_data
telegram._force_exit_inline(update, None)
assert update.callback_query.answer.call_count == 1
assert update.callback_query.edit_message_text.call_count == 1
assert femock.call_count == 1
assert femock.call_args_list[0][0][0] == '2'
# Retry exiting - but cancel instead
update.callback_query.reset_mock()
telegram._force_exit(update=update, context=context)
# Use cancel button
update.callback_query.data = keyboard[-1][0].callback_data
telegram._force_exit_inline(update, None)
query = update.callback_query
assert query.answer.call_count == 1
assert query.edit_message_text.call_count == 1
assert query.edit_message_text.call_args_list[-1][1]['text'] == "Force exit canceled."
def test_force_enter_handle(default_conf, update, mocker) -> None:
mocker.patch('freqtrade.rpc.rpc.CryptoToFiatConverter._find_price', return_value=15000.0)