Merge branch 'freqtrade:develop' into feature/multiple_open_orders

This commit is contained in:
Axel CHERUBIN
2023-08-02 23:48:13 -04:00
committed by GitHub
181 changed files with 3275 additions and 1744 deletions

View File

@@ -96,7 +96,7 @@ def test_rpc_trade_status(default_conf, ticker, fee, mocker) -> None:
'order_date': ANY, 'order_timestamp': ANY, 'order_filled_date': ANY,
'order_filled_timestamp': ANY, 'order_type': 'limit', 'price': 1.098e-05,
'is_open': False, 'pair': 'ETH/BTC', 'order_id': ANY,
'remaining': ANY, 'status': ANY, 'ft_is_entry': True,
'remaining': ANY, 'status': ANY, 'ft_is_entry': True, 'ft_fee_base': None,
}],
}
mocker.patch('freqtrade.rpc.telegram.Telegram', MagicMock())
@@ -401,6 +401,8 @@ def test_rpc_trade_statistics(default_conf_usdt, ticker, fee, mocker) -> None:
assert res['first_trade_timestamp'] == 0
assert res['latest_trade_date'] == ''
assert res['latest_trade_timestamp'] == 0
assert res['expectancy'] == 0
assert res['expectancy_ratio'] == 100
# Create some test data
create_mock_trades_usdt(fee)
@@ -412,6 +414,9 @@ def test_rpc_trade_statistics(default_conf_usdt, ticker, fee, mocker) -> None:
assert pytest.approx(stats['profit_all_coin']) == -77.45964918
assert pytest.approx(stats['profit_all_percent_mean']) == -57.86
assert pytest.approx(stats['profit_all_fiat']) == -85.205614098
assert pytest.approx(stats['winrate']) == 0.666666667
assert pytest.approx(stats['expectancy']) == 0.913333333
assert pytest.approx(stats['expectancy_ratio']) == 0.223308883
assert stats['trade_count'] == 7
assert stats['first_trade_humanized'] == '2 days ago'
assert stats['latest_trade_humanized'] == '17 minutes ago'

View File

@@ -829,7 +829,8 @@ def test_api_edge_disabled(botclient, mocker, ticker, fee, markets):
'profit_closed_percent_mean': -0.75, 'profit_closed_ratio_sum': -0.015,
'profit_closed_percent_sum': -1.5, 'profit_closed_ratio': -6.739057628404269e-06,
'profit_closed_percent': -0.0, 'winning_trades': 0, 'losing_trades': 2,
'profit_factor': 0.0, 'trading_volume': 91.074,
'profit_factor': 0.0, 'winrate': 0.0, 'expectancy': -0.0033695635,
'expectancy_ratio': -1.0, 'trading_volume': 91.074,
}
),
(
@@ -844,7 +845,8 @@ def test_api_edge_disabled(botclient, mocker, ticker, fee, markets):
'profit_closed_percent_mean': 0.75, 'profit_closed_ratio_sum': 0.015,
'profit_closed_percent_sum': 1.5, 'profit_closed_ratio': 7.391275897987988e-07,
'profit_closed_percent': 0.0, 'winning_trades': 2, 'losing_trades': 0,
'profit_factor': None, 'trading_volume': 91.074,
'profit_factor': None, 'winrate': 1.0, 'expectancy': 0.0003695635,
'expectancy_ratio': 100, 'trading_volume': 91.074,
}
),
(
@@ -859,7 +861,9 @@ def test_api_edge_disabled(botclient, mocker, ticker, fee, markets):
'profit_closed_percent_mean': 0.25, 'profit_closed_ratio_sum': 0.005,
'profit_closed_percent_sum': 0.5, 'profit_closed_ratio': -5.429078808526421e-06,
'profit_closed_percent': -0.0, 'winning_trades': 1, 'losing_trades': 1,
'profit_factor': 0.02775724835771106, 'trading_volume': 91.074,
'profit_factor': 0.02775724835771106, 'winrate': 0.5,
'expectancy': -0.0027145635000000003, 'expectancy_ratio': -0.48612137582114445,
'trading_volume': 91.074,
}
)
])
@@ -916,6 +920,9 @@ def test_api_profit(botclient, mocker, ticker, fee, markets, is_short, expected)
'winning_trades': expected['winning_trades'],
'losing_trades': expected['losing_trades'],
'profit_factor': expected['profit_factor'],
'winrate': expected['winrate'],
'expectancy': expected['expectancy'],
'expectancy_ratio': expected['expectancy_ratio'],
'max_drawdown': ANY,
'max_drawdown_abs': ANY,
'trading_volume': expected['trading_volume'],
@@ -1464,30 +1471,47 @@ def test_api_pair_history(botclient, mocker):
"&timerange=20180111-20180112")
assert_response(rc, 422)
# Invalid strategy
rc = client_get(client,
f"{BASE_URI}/pair_history?pair=UNITTEST%2FBTC&timeframe={timeframe}"
"&timerange=20180111-20180112&strategy={CURRENT_TEST_STRATEGY}11")
assert_response(rc, 502)
# Working
rc = client_get(client,
f"{BASE_URI}/pair_history?pair=UNITTEST%2FBTC&timeframe={timeframe}"
f"&timerange=20180111-20180112&strategy={CURRENT_TEST_STRATEGY}")
assert_response(rc, 200)
assert rc.json()['length'] == 289
assert len(rc.json()['data']) == rc.json()['length']
assert 'columns' in rc.json()
assert 'data' in rc.json()
result = rc.json()
assert result['length'] == 289
assert len(result['data']) == result['length']
assert 'columns' in result
assert 'data' in result
data = result['data']
assert len(data) == 289
# analyed DF has 28 columns
assert len(result['columns']) == 28
assert len(data[0]) == 28
date_col_idx = [idx for idx, c in enumerate(result['columns']) if c == 'date'][0]
rsi_col_idx = [idx for idx, c in enumerate(result['columns']) if c == 'rsi'][0]
assert data[0][date_col_idx] == '2018-01-11 00:00:00'
assert data[0][rsi_col_idx] is not None
assert data[0][rsi_col_idx] > 0
assert lfm.call_count == 1
assert rc.json()['pair'] == 'UNITTEST/BTC'
assert rc.json()['strategy'] == CURRENT_TEST_STRATEGY
assert rc.json()['data_start'] == '2018-01-11 00:00:00+00:00'
assert rc.json()['data_start_ts'] == 1515628800000
assert rc.json()['data_stop'] == '2018-01-12 00:00:00+00:00'
assert rc.json()['data_stop_ts'] == 1515715200000
assert result['pair'] == 'UNITTEST/BTC'
assert result['strategy'] == CURRENT_TEST_STRATEGY
assert result['data_start'] == '2018-01-11 00:00:00+00:00'
assert result['data_start_ts'] == 1515628800000
assert result['data_stop'] == '2018-01-12 00:00:00+00:00'
assert result['data_stop_ts'] == 1515715200000
# No data found
rc = client_get(client,
f"{BASE_URI}/pair_history?pair=UNITTEST%2FBTC&timeframe={timeframe}"
f"&timerange=20200111-20200112&strategy={CURRENT_TEST_STRATEGY}")
assert_response(rc, 502)
assert rc.json()['error'] == ("Error querying /api/v1/pair_history: "
"No data for UNITTEST/BTC, 5m in 20200111-20200112 found.")
assert rc.json()['detail'] == ("No data for UNITTEST/BTC, 5m in 20200111-20200112 found.")
def test_api_plot_config(botclient, mocker):
@@ -1524,6 +1548,10 @@ def test_api_plot_config(botclient, mocker):
assert_response(rc)
assert rc.json()['subplots'] == {}
rc = client_get(client, f"{BASE_URI}/plot_config?strategy=NotAStrategy")
assert_response(rc, 502)
assert rc.json()['detail'] is not None
mocker.patch('freqtrade.rpc.api_server.api_v1.get_rpc_optional', return_value=None)
rc = client_get(client, f"{BASE_URI}/plot_config")
@@ -1774,7 +1802,7 @@ def test_list_available_pairs(botclient):
rc = client_get(client, f"{BASE_URI}/available_pairs")
assert_response(rc)
assert rc.json()['length'] == 13
assert rc.json()['length'] == 12
assert isinstance(rc.json()['pairs'], list)
rc = client_get(client, f"{BASE_URI}/available_pairs?timeframe=5m")
@@ -1976,7 +2004,7 @@ def test_api_backtest_history(botclient, mocker, testdatadir):
result = rc.json()
assert len(result) == 3
fn = result[0]['filename']
assert fn == "backtest-result_multistrat.json"
assert fn == "backtest-result_multistrat"
strategy = result[0]['strategy']
rc = client_get(client, f"{BASE_URI}/backtest/history/result?filename={fn}&strategy={strategy}")
assert_response(rc)
@@ -1990,6 +2018,34 @@ def test_api_backtest_history(botclient, mocker, testdatadir):
assert result2['backtest_result']['strategy'][strategy]
def test_api_delete_backtest_history_entry(botclient, mocker, tmp_path: Path):
ftbot, client = botclient
# Create a temporary directory and file
bt_results_base = tmp_path / "backtest_results"
bt_results_base.mkdir()
file_path = bt_results_base / "test.json"
file_path.touch()
meta_path = file_path.with_suffix('.meta.json')
meta_path.touch()
rc = client_delete(client, f"{BASE_URI}/backtest/history/randomFile.json")
assert_response(rc, 503)
assert rc.json()['detail'] == 'Bot is not in the correct state.'
ftbot.config['user_data_dir'] = tmp_path
ftbot.config['runmode'] = RunMode.WEBSERVER
rc = client_delete(client, f"{BASE_URI}/backtest/history/randomFile.json")
assert rc.status_code == 404
assert rc.json()['detail'] == 'File not found.'
rc = client_delete(client, f"{BASE_URI}/backtest/history/{file_path.name}")
assert rc.status_code == 200
assert not file_path.exists()
assert not meta_path.exists()
def test_health(botclient):
ftbot, client = botclient

View File

@@ -799,6 +799,8 @@ async def test_telegram_profit_handle(
assert '*Best Performing:* `ETH/USDT: 9.45%`' in msg_mock.call_args_list[-1][0][0]
assert '*Max Drawdown:*' in msg_mock.call_args_list[-1][0][0]
assert '*Profit factor:*' in msg_mock.call_args_list[-1][0][0]
assert '*Winrate:*' in msg_mock.call_args_list[-1][0][0]
assert '*Expectancy (Ratio):*' in msg_mock.call_args_list[-1][0][0]
assert '*Trading volume:* `126 USDT`' in msg_mock.call_args_list[-1][0][0]

View File

@@ -381,7 +381,7 @@ def test__send_msg(default_conf, mocker, caplog):
webhook._send_msg(msg)
assert post.call_count == 1
assert post.call_args[1] == {'data': msg}
assert post.call_args[1] == {'data': msg, 'timeout': 10}
assert post.call_args[0] == (default_conf['webhook']['url'], )
post = MagicMock(side_effect=RequestException)
@@ -399,7 +399,7 @@ def test__send_msg_with_json_format(default_conf, mocker, caplog):
mocker.patch("freqtrade.rpc.webhook.post", post)
webhook._send_msg(msg)
assert post.call_args[1] == {'json': msg}
assert post.call_args[1] == {'json': msg, 'timeout': 10}
def test__send_msg_with_raw_format(default_conf, mocker, caplog):
@@ -411,7 +411,11 @@ def test__send_msg_with_raw_format(default_conf, mocker, caplog):
mocker.patch("freqtrade.rpc.webhook.post", post)
webhook._send_msg(msg)
assert post.call_args[1] == {'data': msg['data'], 'headers': {'Content-Type': 'text/plain'}}
assert post.call_args[1] == {
'data': msg['data'],
'headers': {'Content-Type': 'text/plain'},
'timeout': 10
}
def test_send_msg_discord(default_conf, mocker):