mirror of
https://github.com/freqtrade/freqtrade.git
synced 2026-02-28 07:13:14 +00:00
Merge remote-tracking branch 'upstream/develop' into feature/fetch-public-trades
This commit is contained in:
@@ -67,10 +67,10 @@ def test_backtest_analysis_nomock(default_conf, mocker, caplog, testdatadir, use
|
||||
"enter_tag_long_b",
|
||||
],
|
||||
"exit_reason": [
|
||||
ExitType.ROI,
|
||||
ExitType.EXIT_SIGNAL,
|
||||
ExitType.STOP_LOSS,
|
||||
ExitType.TRAILING_STOP_LOSS,
|
||||
ExitType.ROI.value,
|
||||
ExitType.EXIT_SIGNAL.value,
|
||||
ExitType.STOP_LOSS.value,
|
||||
ExitType.TRAILING_STOP_LOSS.value,
|
||||
],
|
||||
}
|
||||
)
|
||||
|
||||
@@ -7,7 +7,7 @@ from unittest.mock import MagicMock, Mock, PropertyMock, patch
|
||||
|
||||
import ccxt
|
||||
import pytest
|
||||
from numpy import NaN
|
||||
from numpy import nan
|
||||
from pandas import DataFrame, to_datetime
|
||||
|
||||
from freqtrade.constants import DEFAULT_DATAFRAME_COLUMNS
|
||||
@@ -5014,7 +5014,7 @@ def test_get_max_leverage_from_margin(default_conf, mocker, pair, nominal_value,
|
||||
(10, 0.0001, 2.0, 1.0, 0.002, 0.002),
|
||||
(10, 0.0002, 2.0, 0.01, 0.004, 0.00004),
|
||||
(10, 0.0002, 2.5, None, 0.005, None),
|
||||
(10, 0.0002, NaN, None, 0.0, None),
|
||||
(10, 0.0002, nan, None, 0.0, None),
|
||||
],
|
||||
)
|
||||
def test_calculate_funding_fees(
|
||||
|
||||
@@ -1650,11 +1650,11 @@ def test_backtest_start_multi_strat(default_conf, mocker, caplog, testdatadir):
|
||||
]
|
||||
args = get_args(args)
|
||||
start_backtesting(args)
|
||||
# 2 backtests, 4 tables
|
||||
# 2 backtests, 6 tables (entry, exit, mixed - each 2x)
|
||||
assert backtestmock.call_count == 2
|
||||
assert text_table_mock.call_count == 4
|
||||
assert strattable_mock.call_count == 1
|
||||
assert tag_metrics_mock.call_count == 4
|
||||
assert tag_metrics_mock.call_count == 6
|
||||
assert strat_summary.call_count == 1
|
||||
|
||||
# check the logs, that will contain the backtest result
|
||||
@@ -1709,7 +1709,7 @@ def test_backtest_start_multi_strat_nomock(default_conf, mocker, caplog, testdat
|
||||
"open_rate": [0.104445, 0.10302485],
|
||||
"close_rate": [0.104969, 0.103541],
|
||||
"is_short": [False, False],
|
||||
"exit_reason": [ExitType.ROI, ExitType.ROI],
|
||||
"exit_reason": [ExitType.ROI.value, ExitType.ROI.value],
|
||||
}
|
||||
)
|
||||
result2 = pd.DataFrame(
|
||||
@@ -1729,7 +1729,7 @@ def test_backtest_start_multi_strat_nomock(default_conf, mocker, caplog, testdat
|
||||
"open_rate": [0.104445, 0.10302485, 0.122541],
|
||||
"close_rate": [0.104969, 0.103541, 0.123541],
|
||||
"is_short": [False, False, False],
|
||||
"exit_reason": [ExitType.ROI, ExitType.ROI, ExitType.STOP_LOSS],
|
||||
"exit_reason": [ExitType.ROI.value, ExitType.ROI.value, ExitType.STOP_LOSS.value],
|
||||
}
|
||||
)
|
||||
backtestmock = MagicMock(
|
||||
|
||||
@@ -415,10 +415,10 @@ def test_hyperopt_format_results(hyperopt):
|
||||
"is_short": [False, False, False, False],
|
||||
"stake_amount": [0.01, 0.01, 0.01, 0.01],
|
||||
"exit_reason": [
|
||||
ExitType.ROI,
|
||||
ExitType.STOP_LOSS,
|
||||
ExitType.ROI,
|
||||
ExitType.FORCE_EXIT,
|
||||
ExitType.ROI.value,
|
||||
ExitType.STOP_LOSS.value,
|
||||
ExitType.ROI.value,
|
||||
ExitType.FORCE_EXIT.value,
|
||||
],
|
||||
}
|
||||
),
|
||||
@@ -507,10 +507,10 @@ def test_generate_optimizer(mocker, hyperopt_conf) -> None:
|
||||
"is_short": [False, False, False, False],
|
||||
"stake_amount": [0.01, 0.01, 0.01, 0.01],
|
||||
"exit_reason": [
|
||||
ExitType.ROI,
|
||||
ExitType.STOP_LOSS,
|
||||
ExitType.ROI,
|
||||
ExitType.FORCE_EXIT,
|
||||
ExitType.ROI.value,
|
||||
ExitType.STOP_LOSS.value,
|
||||
ExitType.ROI.value,
|
||||
ExitType.FORCE_EXIT.value,
|
||||
],
|
||||
}
|
||||
),
|
||||
|
||||
@@ -70,13 +70,13 @@ def test_text_table_bt_results():
|
||||
)
|
||||
|
||||
result_str = (
|
||||
"| Pair | Entries | Avg Profit % | Tot Profit BTC | "
|
||||
"| Pair | Trades | Avg Profit % | Tot Profit BTC | "
|
||||
"Tot Profit % | Avg Duration | Win Draw Loss Win% |\n"
|
||||
"|---------+-----------+----------------+------------------+"
|
||||
"|---------+----------+----------------+------------------+"
|
||||
"----------------+----------------+-------------------------|\n"
|
||||
"| ETH/BTC | 3 | 8.33 | 0.50000000 | "
|
||||
"| ETH/BTC | 3 | 8.33 | 0.50000000 | "
|
||||
"12.50 | 0:20:00 | 2 0 1 66.7 |\n"
|
||||
"| TOTAL | 3 | 8.33 | 0.50000000 | "
|
||||
"| TOTAL | 3 | 8.33 | 0.50000000 | "
|
||||
"12.50 | 0:20:00 | 2 0 1 66.7 |"
|
||||
)
|
||||
|
||||
@@ -116,10 +116,10 @@ def test_generate_backtest_stats(default_conf, testdatadir, tmp_path):
|
||||
"is_short": [False, False, False, False],
|
||||
"stake_amount": [0.01, 0.01, 0.01, 0.01],
|
||||
"exit_reason": [
|
||||
ExitType.ROI,
|
||||
ExitType.STOP_LOSS,
|
||||
ExitType.ROI,
|
||||
ExitType.FORCE_EXIT,
|
||||
ExitType.ROI.value,
|
||||
ExitType.STOP_LOSS.value,
|
||||
ExitType.ROI.value,
|
||||
ExitType.FORCE_EXIT.value,
|
||||
],
|
||||
}
|
||||
),
|
||||
@@ -183,10 +183,10 @@ def test_generate_backtest_stats(default_conf, testdatadir, tmp_path):
|
||||
"is_short": [False, False, False, False],
|
||||
"stake_amount": [0.01, 0.01, 0.01, 0.01],
|
||||
"exit_reason": [
|
||||
ExitType.ROI,
|
||||
ExitType.ROI,
|
||||
ExitType.STOP_LOSS,
|
||||
ExitType.FORCE_EXIT,
|
||||
ExitType.ROI.value,
|
||||
ExitType.ROI.value,
|
||||
ExitType.STOP_LOSS.value,
|
||||
ExitType.FORCE_EXIT.value,
|
||||
],
|
||||
}
|
||||
),
|
||||
@@ -444,7 +444,7 @@ def test_text_table_exit_reason():
|
||||
"wins": [2, 0, 0],
|
||||
"draws": [0, 0, 0],
|
||||
"losses": [0, 0, 1],
|
||||
"exit_reason": [ExitType.ROI, ExitType.ROI, ExitType.STOP_LOSS],
|
||||
"exit_reason": [ExitType.ROI.value, ExitType.ROI.value, ExitType.STOP_LOSS.value],
|
||||
}
|
||||
)
|
||||
|
||||
@@ -509,13 +509,13 @@ def test_text_table_strategy(testdatadir):
|
||||
bt_res_data_comparison = bt_res_data.pop("strategy_comparison")
|
||||
|
||||
result_str = (
|
||||
"| Strategy | Entries | Avg Profit % | Tot Profit BTC |"
|
||||
"| Strategy | Trades | Avg Profit % | Tot Profit BTC |"
|
||||
" Tot Profit % | Avg Duration | Win Draw Loss Win% | Drawdown |\n"
|
||||
"|----------------+-----------+----------------+------------------+"
|
||||
"|----------------+----------+----------------+------------------+"
|
||||
"----------------+----------------+-------------------------+-----------------------|\n"
|
||||
"| StrategyTestV2 | 179 | 0.08 | 0.02608550 |"
|
||||
"| StrategyTestV2 | 179 | 0.08 | 0.02608550 |"
|
||||
" 260.85 | 3:40:00 | 170 0 9 95.0 | 0.00308222 BTC 8.67% |\n"
|
||||
"| TestStrategy | 179 | 0.08 | 0.02608550 |"
|
||||
"| TestStrategy | 179 | 0.08 | 0.02608550 |"
|
||||
" 260.85 | 3:40:00 | 170 0 9 95.0 | 0.00308222 BTC 8.67% |"
|
||||
)
|
||||
|
||||
|
||||
@@ -401,11 +401,11 @@ def test_load_dry_run(default_conf, mocker, config_value, expected, arglist) ->
|
||||
assert validated_conf["runmode"] == (RunMode.DRY_RUN if expected else RunMode.LIVE)
|
||||
|
||||
|
||||
def test_load_custom_strategy(default_conf, mocker) -> None:
|
||||
def test_load_custom_strategy(default_conf, mocker, tmp_path) -> None:
|
||||
default_conf.update(
|
||||
{
|
||||
"strategy": "CustomStrategy",
|
||||
"strategy_path": "/tmp/strategies",
|
||||
"strategy_path": f"{tmp_path}/strategies",
|
||||
}
|
||||
)
|
||||
patched_configuration_load_config_file(mocker, default_conf)
|
||||
@@ -415,7 +415,7 @@ def test_load_custom_strategy(default_conf, mocker) -> None:
|
||||
validated_conf = configuration.load_config()
|
||||
|
||||
assert validated_conf.get("strategy") == "CustomStrategy"
|
||||
assert validated_conf.get("strategy_path") == "/tmp/strategies"
|
||||
assert validated_conf.get("strategy_path") == f"{tmp_path}/strategies"
|
||||
|
||||
|
||||
def test_show_info(default_conf, mocker, caplog) -> None:
|
||||
@@ -469,7 +469,7 @@ def test_setup_configuration_without_arguments(mocker, default_conf, caplog) ->
|
||||
assert "timerange" not in config
|
||||
|
||||
|
||||
def test_setup_configuration_with_arguments(mocker, default_conf, caplog) -> None:
|
||||
def test_setup_configuration_with_arguments(mocker, default_conf, caplog, tmp_path) -> None:
|
||||
patched_configuration_load_config_file(mocker, default_conf)
|
||||
mocker.patch("freqtrade.configuration.configuration.create_datadir", lambda c, x: x)
|
||||
mocker.patch(
|
||||
@@ -485,7 +485,7 @@ def test_setup_configuration_with_arguments(mocker, default_conf, caplog) -> Non
|
||||
"--datadir",
|
||||
"/foo/bar",
|
||||
"--userdir",
|
||||
"/tmp/freqtrade",
|
||||
f"{tmp_path}/freqtrade",
|
||||
"--timeframe",
|
||||
"1m",
|
||||
"--enable-position-stacking",
|
||||
@@ -509,7 +509,7 @@ def test_setup_configuration_with_arguments(mocker, default_conf, caplog) -> Non
|
||||
assert "pair_whitelist" in config["exchange"]
|
||||
assert "datadir" in config
|
||||
assert log_has("Using data directory: {} ...".format("/foo/bar"), caplog)
|
||||
assert log_has("Using user-data directory: {} ...".format(Path("/tmp/freqtrade")), caplog)
|
||||
assert log_has(f"Using user-data directory: {tmp_path / 'freqtrade'} ...", caplog)
|
||||
assert "user_data_dir" in config
|
||||
|
||||
assert "timeframe" in config
|
||||
|
||||
@@ -24,16 +24,16 @@ def test_create_datadir(mocker, default_conf, caplog) -> None:
|
||||
assert log_has("Created data directory: /foo/bar", caplog)
|
||||
|
||||
|
||||
def test_create_userdata_dir(mocker, default_conf, caplog) -> None:
|
||||
def test_create_userdata_dir(mocker, tmp_path, caplog) -> None:
|
||||
mocker.patch.object(Path, "is_dir", MagicMock(return_value=False))
|
||||
md = mocker.patch.object(Path, "mkdir", MagicMock())
|
||||
|
||||
x = create_userdata_dir("/tmp/bar", create_dir=True)
|
||||
x = create_userdata_dir(tmp_path / "bar", create_dir=True)
|
||||
assert md.call_count == 10
|
||||
assert md.call_args[1]["parents"] is False
|
||||
assert log_has(f'Created user-data directory: {Path("/tmp/bar")}', caplog)
|
||||
assert log_has(f'Created user-data directory: {tmp_path / "bar"}', caplog)
|
||||
assert isinstance(x, Path)
|
||||
assert str(x) == str(Path("/tmp/bar"))
|
||||
assert str(x) == str(tmp_path / "bar")
|
||||
|
||||
|
||||
def test_create_userdata_dir_and_chown(mocker, tmp_path, caplog) -> None:
|
||||
@@ -54,63 +54,57 @@ def test_create_userdata_dir_and_chown(mocker, tmp_path, caplog) -> None:
|
||||
del os.environ["FT_APP_ENV"]
|
||||
|
||||
|
||||
def test_create_userdata_dir_exists(mocker, default_conf, caplog) -> None:
|
||||
def test_create_userdata_dir_exists(mocker, tmp_path) -> None:
|
||||
mocker.patch.object(Path, "is_dir", MagicMock(return_value=True))
|
||||
md = mocker.patch.object(Path, "mkdir", MagicMock())
|
||||
|
||||
create_userdata_dir("/tmp/bar")
|
||||
create_userdata_dir(f"{tmp_path}/bar")
|
||||
assert md.call_count == 0
|
||||
|
||||
|
||||
def test_create_userdata_dir_exists_exception(mocker, default_conf, caplog) -> None:
|
||||
def test_create_userdata_dir_exists_exception(mocker, tmp_path) -> None:
|
||||
mocker.patch.object(Path, "is_dir", MagicMock(return_value=False))
|
||||
md = mocker.patch.object(Path, "mkdir", MagicMock())
|
||||
|
||||
with pytest.raises(
|
||||
OperationalException, match=r"Directory `.{1,2}tmp.{1,2}bar` does not exist.*"
|
||||
):
|
||||
create_userdata_dir("/tmp/bar", create_dir=False)
|
||||
with pytest.raises(OperationalException, match=r"Directory `.*.{1,2}bar` does not exist.*"):
|
||||
create_userdata_dir(f"{tmp_path}/bar", create_dir=False)
|
||||
assert md.call_count == 0
|
||||
|
||||
|
||||
def test_copy_sample_files(mocker, default_conf, caplog) -> None:
|
||||
def test_copy_sample_files(mocker, tmp_path) -> None:
|
||||
mocker.patch.object(Path, "is_dir", MagicMock(return_value=True))
|
||||
mocker.patch.object(Path, "exists", MagicMock(return_value=False))
|
||||
copymock = mocker.patch("shutil.copy", MagicMock())
|
||||
|
||||
copy_sample_files(Path("/tmp/bar"))
|
||||
copy_sample_files(Path(f"{tmp_path}/bar"))
|
||||
assert copymock.call_count == 3
|
||||
assert copymock.call_args_list[0][0][1] == str(
|
||||
Path("/tmp/bar") / "strategies/sample_strategy.py"
|
||||
)
|
||||
assert copymock.call_args_list[0][0][1] == str(tmp_path / "bar/strategies/sample_strategy.py")
|
||||
assert copymock.call_args_list[1][0][1] == str(
|
||||
Path("/tmp/bar") / "hyperopts/sample_hyperopt_loss.py"
|
||||
tmp_path / "bar/hyperopts/sample_hyperopt_loss.py"
|
||||
)
|
||||
assert copymock.call_args_list[2][0][1] == str(
|
||||
Path("/tmp/bar") / "notebooks/strategy_analysis_example.ipynb"
|
||||
tmp_path / "bar/notebooks/strategy_analysis_example.ipynb"
|
||||
)
|
||||
|
||||
|
||||
def test_copy_sample_files_errors(mocker, default_conf, caplog) -> None:
|
||||
def test_copy_sample_files_errors(mocker, tmp_path, caplog) -> None:
|
||||
mocker.patch.object(Path, "is_dir", MagicMock(return_value=False))
|
||||
mocker.patch.object(Path, "exists", MagicMock(return_value=False))
|
||||
mocker.patch("shutil.copy", MagicMock())
|
||||
with pytest.raises(
|
||||
OperationalException, match=r"Directory `.{1,2}tmp.{1,2}bar` does not exist\."
|
||||
):
|
||||
copy_sample_files(Path("/tmp/bar"))
|
||||
with pytest.raises(OperationalException, match=r"Directory `.*.{1,2}bar` does not exist\."):
|
||||
copy_sample_files(Path(f"{tmp_path}/bar"))
|
||||
|
||||
mocker.patch.object(Path, "is_dir", MagicMock(side_effect=[True, False]))
|
||||
|
||||
with pytest.raises(
|
||||
OperationalException,
|
||||
match=r"Directory `.{1,2}tmp.{1,2}bar.{1,2}strategies` does not exist\.",
|
||||
match=r"Directory `.*.{1,2}bar.{1,2}strategies` does not exist\.",
|
||||
):
|
||||
copy_sample_files(Path("/tmp/bar"))
|
||||
copy_sample_files(Path(f"{tmp_path}/bar"))
|
||||
mocker.patch.object(Path, "is_dir", MagicMock(return_value=True))
|
||||
mocker.patch.object(Path, "exists", MagicMock(return_value=True))
|
||||
copy_sample_files(Path("/tmp/bar"))
|
||||
copy_sample_files(Path(f"{tmp_path}/bar"))
|
||||
assert log_has_re(r"File `.*` exists already, not deploying sample file\.", caplog)
|
||||
caplog.clear()
|
||||
copy_sample_files(Path("/tmp/bar"), overwrite=True)
|
||||
copy_sample_files(Path(f"{tmp_path}/bar"), overwrite=True)
|
||||
assert log_has_re(r"File `.*` exists already, overwriting\.", caplog)
|
||||
|
||||
Reference in New Issue
Block a user