Merge branch 'develop' into feat/short
This commit is contained in:
@@ -938,247 +938,261 @@ def test_start_test_pairlist(mocker, caplog, tickers, default_conf, capsys):
|
||||
pytest.fail(f'Expected well formed JSON, but failed to parse: {captured.out}')
|
||||
|
||||
|
||||
def test_hyperopt_list(mocker, capsys, caplog, saved_hyperopt_results,
|
||||
saved_hyperopt_results_legacy, tmpdir):
|
||||
def test_hyperopt_list(mocker, capsys, caplog, saved_hyperopt_results, tmpdir):
|
||||
csv_file = Path(tmpdir) / "test.csv"
|
||||
for res in (saved_hyperopt_results, saved_hyperopt_results_legacy):
|
||||
mocker.patch(
|
||||
'freqtrade.optimize.hyperopt_tools.HyperoptTools.load_previous_results',
|
||||
MagicMock(return_value=res)
|
||||
mocker.patch(
|
||||
'freqtrade.optimize.hyperopt_tools.HyperoptTools._test_hyperopt_results_exist',
|
||||
return_value=True
|
||||
)
|
||||
|
||||
args = [
|
||||
"hyperopt-list",
|
||||
"--no-details",
|
||||
"--no-color",
|
||||
]
|
||||
pargs = get_args(args)
|
||||
pargs['config'] = None
|
||||
start_hyperopt_list(pargs)
|
||||
captured = capsys.readouterr()
|
||||
assert all(x in captured.out
|
||||
for x in [" 1/12", " 2/12", " 3/12", " 4/12", " 5/12",
|
||||
" 6/12", " 7/12", " 8/12", " 9/12", " 10/12",
|
||||
" 11/12", " 12/12"])
|
||||
args = [
|
||||
"hyperopt-list",
|
||||
"--best",
|
||||
"--no-details",
|
||||
"--no-color",
|
||||
]
|
||||
pargs = get_args(args)
|
||||
pargs['config'] = None
|
||||
start_hyperopt_list(pargs)
|
||||
captured = capsys.readouterr()
|
||||
assert all(x in captured.out
|
||||
for x in [" 1/12", " 5/12", " 10/12"])
|
||||
assert all(x not in captured.out
|
||||
for x in [" 2/12", " 3/12", " 4/12", " 6/12", " 7/12", " 8/12", " 9/12",
|
||||
" 11/12", " 12/12"])
|
||||
args = [
|
||||
"hyperopt-list",
|
||||
"--profitable",
|
||||
"--no-details",
|
||||
"--no-color",
|
||||
]
|
||||
pargs = get_args(args)
|
||||
pargs['config'] = None
|
||||
start_hyperopt_list(pargs)
|
||||
captured = capsys.readouterr()
|
||||
assert all(x in captured.out
|
||||
for x in [" 2/12", " 10/12"])
|
||||
assert all(x not in captured.out
|
||||
for x in [" 1/12", " 3/12", " 4/12", " 5/12", " 6/12", " 7/12", " 8/12", " 9/12",
|
||||
" 11/12", " 12/12"])
|
||||
args = [
|
||||
"hyperopt-list",
|
||||
"--profitable",
|
||||
"--no-color",
|
||||
]
|
||||
pargs = get_args(args)
|
||||
pargs['config'] = None
|
||||
start_hyperopt_list(pargs)
|
||||
captured = capsys.readouterr()
|
||||
assert all(x in captured.out
|
||||
for x in [" 2/12", " 10/12", "Best result:", "Buy hyperspace params",
|
||||
"Sell hyperspace params", "ROI table", "Stoploss"])
|
||||
assert all(x not in captured.out
|
||||
for x in [" 1/12", " 3/12", " 4/12", " 5/12", " 6/12", " 7/12", " 8/12", " 9/12",
|
||||
" 11/12", " 12/12"])
|
||||
args = [
|
||||
"hyperopt-list",
|
||||
"--no-details",
|
||||
"--no-color",
|
||||
"--min-trades", "20",
|
||||
]
|
||||
pargs = get_args(args)
|
||||
pargs['config'] = None
|
||||
start_hyperopt_list(pargs)
|
||||
captured = capsys.readouterr()
|
||||
assert all(x in captured.out
|
||||
for x in [" 3/12", " 6/12", " 7/12", " 9/12", " 11/12"])
|
||||
assert all(x not in captured.out
|
||||
for x in [" 1/12", " 2/12", " 4/12", " 5/12", " 8/12", " 10/12", " 12/12"])
|
||||
args = [
|
||||
"hyperopt-list",
|
||||
"--profitable",
|
||||
"--no-details",
|
||||
"--no-color",
|
||||
"--max-trades", "20",
|
||||
]
|
||||
pargs = get_args(args)
|
||||
pargs['config'] = None
|
||||
start_hyperopt_list(pargs)
|
||||
captured = capsys.readouterr()
|
||||
assert all(x in captured.out
|
||||
for x in [" 2/12", " 10/12"])
|
||||
assert all(x not in captured.out
|
||||
for x in [" 1/12", " 3/12", " 4/12", " 5/12", " 6/12", " 7/12", " 8/12", " 9/12",
|
||||
" 11/12", " 12/12"])
|
||||
args = [
|
||||
"hyperopt-list",
|
||||
"--profitable",
|
||||
"--no-details",
|
||||
"--no-color",
|
||||
"--min-avg-profit", "0.11",
|
||||
]
|
||||
pargs = get_args(args)
|
||||
pargs['config'] = None
|
||||
start_hyperopt_list(pargs)
|
||||
captured = capsys.readouterr()
|
||||
assert all(x in captured.out
|
||||
for x in [" 2/12"])
|
||||
assert all(x not in captured.out
|
||||
for x in [" 1/12", " 3/12", " 4/12", " 5/12", " 6/12", " 7/12", " 8/12", " 9/12",
|
||||
" 10/12", " 11/12", " 12/12"])
|
||||
args = [
|
||||
"hyperopt-list",
|
||||
"--no-details",
|
||||
"--no-color",
|
||||
"--max-avg-profit", "0.10",
|
||||
]
|
||||
pargs = get_args(args)
|
||||
pargs['config'] = None
|
||||
start_hyperopt_list(pargs)
|
||||
captured = capsys.readouterr()
|
||||
assert all(x in captured.out
|
||||
for x in [" 1/12", " 3/12", " 5/12", " 6/12", " 7/12", " 8/12", " 9/12",
|
||||
" 11/12"])
|
||||
assert all(x not in captured.out
|
||||
for x in [" 2/12", " 4/12", " 10/12", " 12/12"])
|
||||
args = [
|
||||
"hyperopt-list",
|
||||
"--no-details",
|
||||
"--no-color",
|
||||
"--min-total-profit", "0.4",
|
||||
]
|
||||
pargs = get_args(args)
|
||||
pargs['config'] = None
|
||||
start_hyperopt_list(pargs)
|
||||
captured = capsys.readouterr()
|
||||
assert all(x in captured.out
|
||||
for x in [" 10/12"])
|
||||
assert all(x not in captured.out
|
||||
for x in [" 1/12", " 2/12", " 3/12", " 4/12", " 5/12", " 6/12", " 7/12", " 8/12",
|
||||
" 9/12", " 11/12", " 12/12"])
|
||||
args = [
|
||||
"hyperopt-list",
|
||||
"--no-details",
|
||||
"--no-color",
|
||||
"--max-total-profit", "0.4",
|
||||
]
|
||||
pargs = get_args(args)
|
||||
pargs['config'] = None
|
||||
start_hyperopt_list(pargs)
|
||||
captured = capsys.readouterr()
|
||||
assert all(x in captured.out
|
||||
for x in [" 1/12", " 2/12", " 3/12", " 5/12", " 6/12", " 7/12", " 8/12",
|
||||
" 9/12", " 11/12"])
|
||||
assert all(x not in captured.out
|
||||
for x in [" 4/12", " 10/12", " 12/12"])
|
||||
args = [
|
||||
"hyperopt-list",
|
||||
"--no-details",
|
||||
"--no-color",
|
||||
"--min-objective", "0.1",
|
||||
]
|
||||
pargs = get_args(args)
|
||||
pargs['config'] = None
|
||||
start_hyperopt_list(pargs)
|
||||
captured = capsys.readouterr()
|
||||
assert all(x in captured.out
|
||||
for x in [" 10/12"])
|
||||
assert all(x not in captured.out
|
||||
for x in [" 1/12", " 2/12", " 3/12", " 4/12", " 5/12", " 6/12", " 7/12", " 8/12",
|
||||
" 9/12", " 11/12", " 12/12"])
|
||||
args = [
|
||||
"hyperopt-list",
|
||||
"--no-details",
|
||||
"--max-objective", "0.1",
|
||||
]
|
||||
pargs = get_args(args)
|
||||
pargs['config'] = None
|
||||
start_hyperopt_list(pargs)
|
||||
captured = capsys.readouterr()
|
||||
assert all(x in captured.out
|
||||
for x in [" 1/12", " 2/12", " 3/12", " 5/12", " 6/12", " 7/12", " 8/12",
|
||||
" 9/12", " 11/12"])
|
||||
assert all(x not in captured.out
|
||||
for x in [" 4/12", " 10/12", " 12/12"])
|
||||
args = [
|
||||
"hyperopt-list",
|
||||
"--profitable",
|
||||
"--no-details",
|
||||
"--no-color",
|
||||
"--min-avg-time", "2000",
|
||||
]
|
||||
pargs = get_args(args)
|
||||
pargs['config'] = None
|
||||
start_hyperopt_list(pargs)
|
||||
captured = capsys.readouterr()
|
||||
assert all(x in captured.out
|
||||
for x in [" 10/12"])
|
||||
assert all(x not in captured.out
|
||||
for x in [" 1/12", " 2/12", " 3/12", " 4/12", " 5/12", " 6/12", " 7/12",
|
||||
" 8/12", " 9/12", " 11/12", " 12/12"])
|
||||
args = [
|
||||
"hyperopt-list",
|
||||
"--no-details",
|
||||
"--no-color",
|
||||
"--max-avg-time", "1500",
|
||||
]
|
||||
pargs = get_args(args)
|
||||
pargs['config'] = None
|
||||
start_hyperopt_list(pargs)
|
||||
captured = capsys.readouterr()
|
||||
assert all(x in captured.out
|
||||
for x in [" 2/12", " 6/12"])
|
||||
assert all(x not in captured.out
|
||||
for x in [" 1/12", " 3/12", " 4/12", " 5/12", " 7/12", " 8/12"
|
||||
" 9/12", " 10/12", " 11/12", " 12/12"])
|
||||
args = [
|
||||
"hyperopt-list",
|
||||
"--no-details",
|
||||
"--no-color",
|
||||
"--export-csv",
|
||||
str(csv_file),
|
||||
]
|
||||
pargs = get_args(args)
|
||||
pargs['config'] = None
|
||||
start_hyperopt_list(pargs)
|
||||
captured = capsys.readouterr()
|
||||
log_has("CSV file created: test_file.csv", caplog)
|
||||
assert csv_file.is_file()
|
||||
line = csv_file.read_text()
|
||||
assert ('Best,1,2,-1.25%,-1.2222,-0.00125625,,-2.51,"3,930.0 m",0.43662' in line
|
||||
or "Best,1,2,-1.25%,-1.2222,-0.00125625,,-2.51,2 days 17:30:00,0.43662" in line)
|
||||
csv_file.unlink()
|
||||
def fake_iterator(*args, **kwargs):
|
||||
yield from [saved_hyperopt_results]
|
||||
|
||||
mocker.patch(
|
||||
'freqtrade.optimize.hyperopt_tools.HyperoptTools._read_results',
|
||||
side_effect=fake_iterator
|
||||
)
|
||||
|
||||
args = [
|
||||
"hyperopt-list",
|
||||
"--no-details",
|
||||
"--no-color",
|
||||
]
|
||||
pargs = get_args(args)
|
||||
pargs['config'] = None
|
||||
start_hyperopt_list(pargs)
|
||||
captured = capsys.readouterr()
|
||||
assert all(x in captured.out
|
||||
for x in [" 1/12", " 2/12", " 3/12", " 4/12", " 5/12",
|
||||
" 6/12", " 7/12", " 8/12", " 9/12", " 10/12",
|
||||
" 11/12", " 12/12"])
|
||||
args = [
|
||||
"hyperopt-list",
|
||||
"--best",
|
||||
"--no-details",
|
||||
"--no-color",
|
||||
]
|
||||
pargs = get_args(args)
|
||||
pargs['config'] = None
|
||||
start_hyperopt_list(pargs)
|
||||
captured = capsys.readouterr()
|
||||
assert all(x in captured.out
|
||||
for x in [" 1/12", " 5/12", " 10/12"])
|
||||
assert all(x not in captured.out
|
||||
for x in [" 2/12", " 3/12", " 4/12", " 6/12", " 7/12", " 8/12", " 9/12",
|
||||
" 11/12", " 12/12"])
|
||||
args = [
|
||||
"hyperopt-list",
|
||||
"--profitable",
|
||||
"--no-details",
|
||||
"--no-color",
|
||||
]
|
||||
pargs = get_args(args)
|
||||
pargs['config'] = None
|
||||
start_hyperopt_list(pargs)
|
||||
captured = capsys.readouterr()
|
||||
assert all(x in captured.out
|
||||
for x in [" 2/12", " 10/12"])
|
||||
assert all(x not in captured.out
|
||||
for x in [" 1/12", " 3/12", " 4/12", " 5/12", " 6/12", " 7/12", " 8/12", " 9/12",
|
||||
" 11/12", " 12/12"])
|
||||
args = [
|
||||
"hyperopt-list",
|
||||
"--profitable",
|
||||
"--no-color",
|
||||
]
|
||||
pargs = get_args(args)
|
||||
pargs['config'] = None
|
||||
start_hyperopt_list(pargs)
|
||||
captured = capsys.readouterr()
|
||||
assert all(x in captured.out
|
||||
for x in [" 2/12", " 10/12", "Best result:", "Buy hyperspace params",
|
||||
"Sell hyperspace params", "ROI table", "Stoploss"])
|
||||
assert all(x not in captured.out
|
||||
for x in [" 1/12", " 3/12", " 4/12", " 5/12", " 6/12", " 7/12", " 8/12", " 9/12",
|
||||
" 11/12", " 12/12"])
|
||||
args = [
|
||||
"hyperopt-list",
|
||||
"--no-details",
|
||||
"--no-color",
|
||||
"--min-trades", "20",
|
||||
]
|
||||
pargs = get_args(args)
|
||||
pargs['config'] = None
|
||||
start_hyperopt_list(pargs)
|
||||
captured = capsys.readouterr()
|
||||
assert all(x in captured.out
|
||||
for x in [" 3/12", " 6/12", " 7/12", " 9/12", " 11/12"])
|
||||
assert all(x not in captured.out
|
||||
for x in [" 1/12", " 2/12", " 4/12", " 5/12", " 8/12", " 10/12", " 12/12"])
|
||||
args = [
|
||||
"hyperopt-list",
|
||||
"--profitable",
|
||||
"--no-details",
|
||||
"--no-color",
|
||||
"--max-trades", "20",
|
||||
]
|
||||
pargs = get_args(args)
|
||||
pargs['config'] = None
|
||||
start_hyperopt_list(pargs)
|
||||
captured = capsys.readouterr()
|
||||
assert all(x in captured.out
|
||||
for x in [" 2/12", " 10/12"])
|
||||
assert all(x not in captured.out
|
||||
for x in [" 1/12", " 3/12", " 4/12", " 5/12", " 6/12", " 7/12", " 8/12", " 9/12",
|
||||
" 11/12", " 12/12"])
|
||||
args = [
|
||||
"hyperopt-list",
|
||||
"--profitable",
|
||||
"--no-details",
|
||||
"--no-color",
|
||||
"--min-avg-profit", "0.11",
|
||||
]
|
||||
pargs = get_args(args)
|
||||
pargs['config'] = None
|
||||
start_hyperopt_list(pargs)
|
||||
captured = capsys.readouterr()
|
||||
assert all(x in captured.out
|
||||
for x in [" 2/12"])
|
||||
assert all(x not in captured.out
|
||||
for x in [" 1/12", " 3/12", " 4/12", " 5/12", " 6/12", " 7/12", " 8/12", " 9/12",
|
||||
" 10/12", " 11/12", " 12/12"])
|
||||
args = [
|
||||
"hyperopt-list",
|
||||
"--no-details",
|
||||
"--no-color",
|
||||
"--max-avg-profit", "0.10",
|
||||
]
|
||||
pargs = get_args(args)
|
||||
pargs['config'] = None
|
||||
start_hyperopt_list(pargs)
|
||||
captured = capsys.readouterr()
|
||||
assert all(x in captured.out
|
||||
for x in [" 1/12", " 3/12", " 5/12", " 6/12", " 7/12", " 8/12", " 9/12",
|
||||
" 11/12"])
|
||||
assert all(x not in captured.out
|
||||
for x in [" 2/12", " 4/12", " 10/12", " 12/12"])
|
||||
args = [
|
||||
"hyperopt-list",
|
||||
"--no-details",
|
||||
"--no-color",
|
||||
"--min-total-profit", "0.4",
|
||||
]
|
||||
pargs = get_args(args)
|
||||
pargs['config'] = None
|
||||
start_hyperopt_list(pargs)
|
||||
captured = capsys.readouterr()
|
||||
assert all(x in captured.out
|
||||
for x in [" 10/12"])
|
||||
assert all(x not in captured.out
|
||||
for x in [" 1/12", " 2/12", " 3/12", " 4/12", " 5/12", " 6/12", " 7/12", " 8/12",
|
||||
" 9/12", " 11/12", " 12/12"])
|
||||
args = [
|
||||
"hyperopt-list",
|
||||
"--no-details",
|
||||
"--no-color",
|
||||
"--max-total-profit", "0.4",
|
||||
]
|
||||
pargs = get_args(args)
|
||||
pargs['config'] = None
|
||||
start_hyperopt_list(pargs)
|
||||
captured = capsys.readouterr()
|
||||
assert all(x in captured.out
|
||||
for x in [" 1/12", " 2/12", " 3/12", " 5/12", " 6/12", " 7/12", " 8/12",
|
||||
" 9/12", " 11/12"])
|
||||
assert all(x not in captured.out
|
||||
for x in [" 4/12", " 10/12", " 12/12"])
|
||||
args = [
|
||||
"hyperopt-list",
|
||||
"--no-details",
|
||||
"--no-color",
|
||||
"--min-objective", "0.1",
|
||||
]
|
||||
pargs = get_args(args)
|
||||
pargs['config'] = None
|
||||
start_hyperopt_list(pargs)
|
||||
captured = capsys.readouterr()
|
||||
assert all(x in captured.out
|
||||
for x in [" 10/12"])
|
||||
assert all(x not in captured.out
|
||||
for x in [" 1/12", " 2/12", " 3/12", " 4/12", " 5/12", " 6/12", " 7/12", " 8/12",
|
||||
" 9/12", " 11/12", " 12/12"])
|
||||
args = [
|
||||
"hyperopt-list",
|
||||
"--no-details",
|
||||
"--max-objective", "0.1",
|
||||
]
|
||||
pargs = get_args(args)
|
||||
pargs['config'] = None
|
||||
start_hyperopt_list(pargs)
|
||||
captured = capsys.readouterr()
|
||||
assert all(x in captured.out
|
||||
for x in [" 1/12", " 2/12", " 3/12", " 5/12", " 6/12", " 7/12", " 8/12",
|
||||
" 9/12", " 11/12"])
|
||||
assert all(x not in captured.out
|
||||
for x in [" 4/12", " 10/12", " 12/12"])
|
||||
args = [
|
||||
"hyperopt-list",
|
||||
"--profitable",
|
||||
"--no-details",
|
||||
"--no-color",
|
||||
"--min-avg-time", "2000",
|
||||
]
|
||||
pargs = get_args(args)
|
||||
pargs['config'] = None
|
||||
start_hyperopt_list(pargs)
|
||||
captured = capsys.readouterr()
|
||||
assert all(x in captured.out
|
||||
for x in [" 10/12"])
|
||||
assert all(x not in captured.out
|
||||
for x in [" 1/12", " 2/12", " 3/12", " 4/12", " 5/12", " 6/12", " 7/12",
|
||||
" 8/12", " 9/12", " 11/12", " 12/12"])
|
||||
args = [
|
||||
"hyperopt-list",
|
||||
"--no-details",
|
||||
"--no-color",
|
||||
"--max-avg-time", "1500",
|
||||
]
|
||||
pargs = get_args(args)
|
||||
pargs['config'] = None
|
||||
start_hyperopt_list(pargs)
|
||||
captured = capsys.readouterr()
|
||||
assert all(x in captured.out
|
||||
for x in [" 2/12", " 6/12"])
|
||||
assert all(x not in captured.out
|
||||
for x in [" 1/12", " 3/12", " 4/12", " 5/12", " 7/12", " 8/12"
|
||||
" 9/12", " 10/12", " 11/12", " 12/12"])
|
||||
args = [
|
||||
"hyperopt-list",
|
||||
"--no-details",
|
||||
"--no-color",
|
||||
"--export-csv",
|
||||
str(csv_file),
|
||||
]
|
||||
pargs = get_args(args)
|
||||
pargs['config'] = None
|
||||
start_hyperopt_list(pargs)
|
||||
captured = capsys.readouterr()
|
||||
log_has("CSV file created: test_file.csv", caplog)
|
||||
assert csv_file.is_file()
|
||||
line = csv_file.read_text()
|
||||
assert ('Best,1,2,-1.25%,-1.2222,-0.00125625,,-2.51,"3,930.0 m",0.43662' in line
|
||||
or "Best,1,2,-1.25%,-1.2222,-0.00125625,,-2.51,2 days 17:30:00,0.43662" in line)
|
||||
csv_file.unlink()
|
||||
|
||||
|
||||
def test_hyperopt_show(mocker, capsys, saved_hyperopt_results):
|
||||
mocker.patch(
|
||||
'freqtrade.optimize.hyperopt_tools.HyperoptTools.load_previous_results',
|
||||
MagicMock(return_value=saved_hyperopt_results)
|
||||
'freqtrade.optimize.hyperopt_tools.HyperoptTools._test_hyperopt_results_exist',
|
||||
return_value=True
|
||||
)
|
||||
|
||||
def fake_iterator(*args, **kwargs):
|
||||
yield from [saved_hyperopt_results]
|
||||
|
||||
mocker.patch(
|
||||
'freqtrade.optimize.hyperopt_tools.HyperoptTools._read_results',
|
||||
side_effect=fake_iterator
|
||||
)
|
||||
mocker.patch('freqtrade.commands.hyperopt_commands.show_backtest_result')
|
||||
|
||||
|
@@ -1851,138 +1851,6 @@ def open_trade():
|
||||
)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def saved_hyperopt_results_legacy():
|
||||
return [
|
||||
{
|
||||
'loss': 0.4366182531161519,
|
||||
'params_dict': {
|
||||
'mfi-value': 15, 'fastd-value': 20, 'adx-value': 25, 'rsi-value': 28, 'mfi-enabled': False, 'fastd-enabled': True, 'adx-enabled': True, 'rsi-enabled': True, 'trigger': 'macd_cross_signal', 'sell-mfi-value': 88, 'sell-fastd-value': 97, 'sell-adx-value': 51, 'sell-rsi-value': 67, 'sell-mfi-enabled': False, 'sell-fastd-enabled': False, 'sell-adx-enabled': True, 'sell-rsi-enabled': True, 'sell-trigger': 'sell-bb_upper', 'roi_t1': 1190, 'roi_t2': 541, 'roi_t3': 408, 'roi_p1': 0.026035863879169705, 'roi_p2': 0.12508730043628782, 'roi_p3': 0.27766427921605896, 'stoploss': -0.2562930402099556}, # noqa: E501
|
||||
'params_details': {'buy': {'mfi-value': 15, 'fastd-value': 20, 'adx-value': 25, 'rsi-value': 28, 'mfi-enabled': False, 'fastd-enabled': True, 'adx-enabled': True, 'rsi-enabled': True, 'trigger': 'macd_cross_signal'}, 'sell': {'sell-mfi-value': 88, 'sell-fastd-value': 97, 'sell-adx-value': 51, 'sell-rsi-value': 67, 'sell-mfi-enabled': False, 'sell-fastd-enabled': False, 'sell-adx-enabled': True, 'sell-rsi-enabled': True, 'sell-trigger': 'sell-bb_upper'}, 'roi': {0: 0.4287874435315165, 408: 0.15112316431545753, 949: 0.026035863879169705, 2139: 0}, 'stoploss': {'stoploss': -0.2562930402099556}}, # noqa: E501
|
||||
'results_metrics': {'trade_count': 2, 'avg_profit': -1.254995, 'median_profit': -1.2222, 'total_profit': -0.00125625, 'profit': -2.50999, 'duration': 3930.0}, # noqa: E501
|
||||
'results_explanation': ' 2 trades. Avg profit -1.25%. Total profit -0.00125625 BTC ( -2.51Σ%). Avg duration 3930.0 min.', # noqa: E501
|
||||
'total_profit': -0.00125625,
|
||||
'current_epoch': 1,
|
||||
'is_initial_point': True,
|
||||
'is_best': True
|
||||
}, {
|
||||
'loss': 20.0,
|
||||
'params_dict': {
|
||||
'mfi-value': 17, 'fastd-value': 38, 'adx-value': 48, 'rsi-value': 22, 'mfi-enabled': True, 'fastd-enabled': False, 'adx-enabled': True, 'rsi-enabled': True, 'trigger': 'macd_cross_signal', 'sell-mfi-value': 96, 'sell-fastd-value': 68, 'sell-adx-value': 63, 'sell-rsi-value': 81, 'sell-mfi-enabled': False, 'sell-fastd-enabled': True, 'sell-adx-enabled': True, 'sell-rsi-enabled': True, 'sell-trigger': 'sell-sar_reversal', 'roi_t1': 334, 'roi_t2': 683, 'roi_t3': 140, 'roi_p1': 0.06403981740598495, 'roi_p2': 0.055519840060645045, 'roi_p3': 0.3253712811342459, 'stoploss': -0.338070047333259}, # noqa: E501
|
||||
'params_details': {
|
||||
'buy': {'mfi-value': 17, 'fastd-value': 38, 'adx-value': 48, 'rsi-value': 22, 'mfi-enabled': True, 'fastd-enabled': False, 'adx-enabled': True, 'rsi-enabled': True, 'trigger': 'macd_cross_signal'}, # noqa: E501
|
||||
'sell': {'sell-mfi-value': 96, 'sell-fastd-value': 68, 'sell-adx-value': 63, 'sell-rsi-value': 81, 'sell-mfi-enabled': False, 'sell-fastd-enabled': True, 'sell-adx-enabled': True, 'sell-rsi-enabled': True, 'sell-trigger': 'sell-sar_reversal'}, # noqa: E501
|
||||
'roi': {0: 0.4449309386008759, 140: 0.11955965746663, 823: 0.06403981740598495, 1157: 0}, # noqa: E501
|
||||
'stoploss': {'stoploss': -0.338070047333259}},
|
||||
'results_metrics': {'trade_count': 1, 'avg_profit': 0.12357, 'median_profit': -1.2222, 'total_profit': 6.185e-05, 'profit': 0.12357, 'duration': 1200.0}, # noqa: E501
|
||||
'results_explanation': ' 1 trades. Avg profit 0.12%. Total profit 0.00006185 BTC ( 0.12Σ%). Avg duration 1200.0 min.', # noqa: E501
|
||||
'total_profit': 6.185e-05,
|
||||
'current_epoch': 2,
|
||||
'is_initial_point': True,
|
||||
'is_best': False
|
||||
}, {
|
||||
'loss': 14.241196856510731,
|
||||
'params_dict': {'mfi-value': 25, 'fastd-value': 16, 'adx-value': 29, 'rsi-value': 20, 'mfi-enabled': False, 'fastd-enabled': False, 'adx-enabled': False, 'rsi-enabled': False, 'trigger': 'macd_cross_signal', 'sell-mfi-value': 98, 'sell-fastd-value': 72, 'sell-adx-value': 51, 'sell-rsi-value': 82, 'sell-mfi-enabled': True, 'sell-fastd-enabled': True, 'sell-adx-enabled': True, 'sell-rsi-enabled': True, 'sell-trigger': 'sell-macd_cross_signal', 'roi_t1': 889, 'roi_t2': 533, 'roi_t3': 263, 'roi_p1': 0.04759065393663096, 'roi_p2': 0.1488819964638463, 'roi_p3': 0.4102801822104605, 'stoploss': -0.05394588767607611}, # noqa: E501
|
||||
'params_details': {'buy': {'mfi-value': 25, 'fastd-value': 16, 'adx-value': 29, 'rsi-value': 20, 'mfi-enabled': False, 'fastd-enabled': False, 'adx-enabled': False, 'rsi-enabled': False, 'trigger': 'macd_cross_signal'}, 'sell': {'sell-mfi-value': 98, 'sell-fastd-value': 72, 'sell-adx-value': 51, 'sell-rsi-value': 82, 'sell-mfi-enabled': True, 'sell-fastd-enabled': True, 'sell-adx-enabled': True, 'sell-rsi-enabled': True, 'sell-trigger': 'sell-macd_cross_signal'}, 'roi': {0: 0.6067528326109377, 263: 0.19647265040047726, 796: 0.04759065393663096, 1685: 0}, 'stoploss': {'stoploss': -0.05394588767607611}}, # noqa: E501
|
||||
'results_metrics': {'trade_count': 621, 'avg_profit': -0.43883302093397747, 'median_profit': -1.2222, 'total_profit': -0.13639474, 'profit': -272.515306, 'duration': 1691.207729468599}, # noqa: E501
|
||||
'results_explanation': ' 621 trades. Avg profit -0.44%. Total profit -0.13639474 BTC (-272.52Σ%). Avg duration 1691.2 min.', # noqa: E501
|
||||
'total_profit': -0.13639474,
|
||||
'current_epoch': 3,
|
||||
'is_initial_point': True,
|
||||
'is_best': False
|
||||
}, {
|
||||
'loss': 100000,
|
||||
'params_dict': {'mfi-value': 13, 'fastd-value': 35, 'adx-value': 39, 'rsi-value': 29, 'mfi-enabled': True, 'fastd-enabled': False, 'adx-enabled': False, 'rsi-enabled': True, 'trigger': 'macd_cross_signal', 'sell-mfi-value': 87, 'sell-fastd-value': 54, 'sell-adx-value': 63, 'sell-rsi-value': 93, 'sell-mfi-enabled': False, 'sell-fastd-enabled': True, 'sell-adx-enabled': True, 'sell-rsi-enabled': True, 'sell-trigger': 'sell-bb_upper', 'roi_t1': 1402, 'roi_t2': 676, 'roi_t3': 215, 'roi_p1': 0.06264755784937427, 'roi_p2': 0.14258587851894644, 'roi_p3': 0.20671291201040828, 'stoploss': -0.11818343570194478}, # noqa: E501
|
||||
'params_details': {'buy': {'mfi-value': 13, 'fastd-value': 35, 'adx-value': 39, 'rsi-value': 29, 'mfi-enabled': True, 'fastd-enabled': False, 'adx-enabled': False, 'rsi-enabled': True, 'trigger': 'macd_cross_signal'}, 'sell': {'sell-mfi-value': 87, 'sell-fastd-value': 54, 'sell-adx-value': 63, 'sell-rsi-value': 93, 'sell-mfi-enabled': False, 'sell-fastd-enabled': True, 'sell-adx-enabled': True, 'sell-rsi-enabled': True, 'sell-trigger': 'sell-bb_upper'}, 'roi': {0: 0.411946348378729, 215: 0.2052334363683207, 891: 0.06264755784937427, 2293: 0}, 'stoploss': {'stoploss': -0.11818343570194478}}, # noqa: E501
|
||||
'results_metrics': {'trade_count': 0, 'avg_profit': None, 'median_profit': None, 'total_profit': 0, 'profit': 0.0, 'duration': None}, # noqa: E501
|
||||
'results_explanation': ' 0 trades. Avg profit nan%. Total profit 0.00000000 BTC ( 0.00Σ%). Avg duration nan min.', # noqa: E501
|
||||
'total_profit': 0, 'current_epoch': 4, 'is_initial_point': True, 'is_best': False
|
||||
}, {
|
||||
'loss': 0.22195522184191518,
|
||||
'params_dict': {'mfi-value': 17, 'fastd-value': 21, 'adx-value': 38, 'rsi-value': 33, 'mfi-enabled': True, 'fastd-enabled': False, 'adx-enabled': True, 'rsi-enabled': False, 'trigger': 'macd_cross_signal', 'sell-mfi-value': 87, 'sell-fastd-value': 82, 'sell-adx-value': 78, 'sell-rsi-value': 69, 'sell-mfi-enabled': True, 'sell-fastd-enabled': False, 'sell-adx-enabled': True, 'sell-rsi-enabled': False, 'sell-trigger': 'sell-macd_cross_signal', 'roi_t1': 1269, 'roi_t2': 601, 'roi_t3': 444, 'roi_p1': 0.07280999507931168, 'roi_p2': 0.08946698095898986, 'roi_p3': 0.1454876733325284, 'stoploss': -0.18181041180901014}, # noqa: E501
|
||||
'params_details': {'buy': {'mfi-value': 17, 'fastd-value': 21, 'adx-value': 38, 'rsi-value': 33, 'mfi-enabled': True, 'fastd-enabled': False, 'adx-enabled': True, 'rsi-enabled': False, 'trigger': 'macd_cross_signal'}, 'sell': {'sell-mfi-value': 87, 'sell-fastd-value': 82, 'sell-adx-value': 78, 'sell-rsi-value': 69, 'sell-mfi-enabled': True, 'sell-fastd-enabled': False, 'sell-adx-enabled': True, 'sell-rsi-enabled': False, 'sell-trigger': 'sell-macd_cross_signal'}, 'roi': {0: 0.3077646493708299, 444: 0.16227697603830155, 1045: 0.07280999507931168, 2314: 0}, 'stoploss': {'stoploss': -0.18181041180901014}}, # noqa: E501
|
||||
'results_metrics': {'trade_count': 14, 'avg_profit': -0.3539515, 'median_profit': -1.2222, 'total_profit': -0.002480140000000001, 'profit': -4.955321, 'duration': 3402.8571428571427}, # noqa: E501
|
||||
'results_explanation': ' 14 trades. Avg profit -0.35%. Total profit -0.00248014 BTC ( -4.96Σ%). Avg duration 3402.9 min.', # noqa: E501
|
||||
'total_profit': -0.002480140000000001,
|
||||
'current_epoch': 5,
|
||||
'is_initial_point': True,
|
||||
'is_best': True
|
||||
}, {
|
||||
'loss': 0.545315889154162,
|
||||
'params_dict': {'mfi-value': 22, 'fastd-value': 43, 'adx-value': 46, 'rsi-value': 20, 'mfi-enabled': False, 'fastd-enabled': False, 'adx-enabled': True, 'rsi-enabled': True, 'trigger': 'bb_lower', 'sell-mfi-value': 87, 'sell-fastd-value': 65, 'sell-adx-value': 94, 'sell-rsi-value': 63, 'sell-mfi-enabled': False, 'sell-fastd-enabled': True, 'sell-adx-enabled': True, 'sell-rsi-enabled': True, 'sell-trigger': 'sell-macd_cross_signal', 'roi_t1': 319, 'roi_t2': 556, 'roi_t3': 216, 'roi_p1': 0.06251955472249589, 'roi_p2': 0.11659519602202795, 'roi_p3': 0.0953744132197762, 'stoploss': -0.024551752215582423}, # noqa: E501
|
||||
'params_details': {'buy': {'mfi-value': 22, 'fastd-value': 43, 'adx-value': 46, 'rsi-value': 20, 'mfi-enabled': False, 'fastd-enabled': False, 'adx-enabled': True, 'rsi-enabled': True, 'trigger': 'bb_lower'}, 'sell': {'sell-mfi-value': 87, 'sell-fastd-value': 65, 'sell-adx-value': 94, 'sell-rsi-value': 63, 'sell-mfi-enabled': False, 'sell-fastd-enabled': True, 'sell-adx-enabled': True, 'sell-rsi-enabled': True, 'sell-trigger': 'sell-macd_cross_signal'}, 'roi': {0: 0.2744891639643, 216: 0.17911475074452382, 772: 0.06251955472249589, 1091: 0}, 'stoploss': {'stoploss': -0.024551752215582423}}, # noqa: E501
|
||||
'results_metrics': {'trade_count': 39, 'avg_profit': -0.21400679487179478, 'median_profit': -1.2222, 'total_profit': -0.0041773, 'profit': -8.346264999999997, 'duration': 636.9230769230769}, # noqa: E501
|
||||
'results_explanation': ' 39 trades. Avg profit -0.21%. Total profit -0.00417730 BTC ( -8.35Σ%). Avg duration 636.9 min.', # noqa: E501
|
||||
'total_profit': -0.0041773,
|
||||
'current_epoch': 6,
|
||||
'is_initial_point': True,
|
||||
'is_best': False
|
||||
}, {
|
||||
'loss': 4.713497421432944,
|
||||
'params_dict': {'mfi-value': 13, 'fastd-value': 41, 'adx-value': 21, 'rsi-value': 29, 'mfi-enabled': False, 'fastd-enabled': True, 'adx-enabled': False, 'rsi-enabled': False, 'trigger': 'bb_lower', 'sell-mfi-value': 99, 'sell-fastd-value': 60, 'sell-adx-value': 81, 'sell-rsi-value': 69, 'sell-mfi-enabled': True, 'sell-fastd-enabled': True, 'sell-adx-enabled': True, 'sell-rsi-enabled': False, 'sell-trigger': 'sell-macd_cross_signal', 'roi_t1': 771, 'roi_t2': 620, 'roi_t3': 145, 'roi_p1': 0.0586919200378493, 'roi_p2': 0.04984118697312542, 'roi_p3': 0.37521058680247044, 'stoploss': -0.14613268022709905}, # noqa: E501
|
||||
'params_details': {
|
||||
'buy': {'mfi-value': 13, 'fastd-value': 41, 'adx-value': 21, 'rsi-value': 29, 'mfi-enabled': False, 'fastd-enabled': True, 'adx-enabled': False, 'rsi-enabled': False, 'trigger': 'bb_lower'}, 'sell': {'sell-mfi-value': 99, 'sell-fastd-value': 60, 'sell-adx-value': 81, 'sell-rsi-value': 69, 'sell-mfi-enabled': True, 'sell-fastd-enabled': True, 'sell-adx-enabled': True, 'sell-rsi-enabled': False, 'sell-trigger': 'sell-macd_cross_signal'}, 'roi': {0: 0.4837436938134452, 145: 0.10853310701097472, 765: 0.0586919200378493, 1536: 0}, # noqa: E501
|
||||
'stoploss': {'stoploss': -0.14613268022709905}}, # noqa: E501
|
||||
'results_metrics': {'trade_count': 318, 'avg_profit': -0.39833954716981146, 'median_profit': -1.2222, 'total_profit': -0.06339929, 'profit': -126.67197600000004, 'duration': 3140.377358490566}, # noqa: E501
|
||||
'results_explanation': ' 318 trades. Avg profit -0.40%. Total profit -0.06339929 BTC (-126.67Σ%). Avg duration 3140.4 min.', # noqa: E501
|
||||
'total_profit': -0.06339929,
|
||||
'current_epoch': 7,
|
||||
'is_initial_point': True,
|
||||
'is_best': False
|
||||
}, {
|
||||
'loss': 20.0, # noqa: E501
|
||||
'params_dict': {'mfi-value': 24, 'fastd-value': 43, 'adx-value': 33, 'rsi-value': 20, 'mfi-enabled': False, 'fastd-enabled': True, 'adx-enabled': True, 'rsi-enabled': True, 'trigger': 'sar_reversal', 'sell-mfi-value': 89, 'sell-fastd-value': 74, 'sell-adx-value': 70, 'sell-rsi-value': 70, 'sell-mfi-enabled': False, 'sell-fastd-enabled': False, 'sell-adx-enabled': False, 'sell-rsi-enabled': True, 'sell-trigger': 'sell-sar_reversal', 'roi_t1': 1149, 'roi_t2': 375, 'roi_t3': 289, 'roi_p1': 0.05571820757172588, 'roi_p2': 0.0606240398618907, 'roi_p3': 0.1729012220156157, 'stoploss': -0.1588514289110401}, # noqa: E501
|
||||
'params_details': {'buy': {'mfi-value': 24, 'fastd-value': 43, 'adx-value': 33, 'rsi-value': 20, 'mfi-enabled': False, 'fastd-enabled': True, 'adx-enabled': True, 'rsi-enabled': True, 'trigger': 'sar_reversal'}, 'sell': {'sell-mfi-value': 89, 'sell-fastd-value': 74, 'sell-adx-value': 70, 'sell-rsi-value': 70, 'sell-mfi-enabled': False, 'sell-fastd-enabled': False, 'sell-adx-enabled': False, 'sell-rsi-enabled': True, 'sell-trigger': 'sell-sar_reversal'}, 'roi': {0: 0.2892434694492323, 289: 0.11634224743361658, 664: 0.05571820757172588, 1813: 0}, 'stoploss': {'stoploss': -0.1588514289110401}}, # noqa: E501
|
||||
'results_metrics': {'trade_count': 1, 'avg_profit': 0.0, 'median_profit': 0.0, 'total_profit': 0.0, 'profit': 0.0, 'duration': 5340.0}, # noqa: E501
|
||||
'results_explanation': ' 1 trades. Avg profit 0.00%. Total profit 0.00000000 BTC ( 0.00Σ%). Avg duration 5340.0 min.', # noqa: E501
|
||||
'total_profit': 0.0,
|
||||
'current_epoch': 8,
|
||||
'is_initial_point': True,
|
||||
'is_best': False
|
||||
}, {
|
||||
'loss': 2.4731817780991223,
|
||||
'params_dict': {'mfi-value': 22, 'fastd-value': 20, 'adx-value': 29, 'rsi-value': 40, 'mfi-enabled': False, 'fastd-enabled': False, 'adx-enabled': False, 'rsi-enabled': False, 'trigger': 'sar_reversal', 'sell-mfi-value': 97, 'sell-fastd-value': 65, 'sell-adx-value': 81, 'sell-rsi-value': 64, 'sell-mfi-enabled': True, 'sell-fastd-enabled': True, 'sell-adx-enabled': True, 'sell-rsi-enabled': True, 'sell-trigger': 'sell-bb_upper', 'roi_t1': 1012, 'roi_t2': 584, 'roi_t3': 422, 'roi_p1': 0.036764323603472565, 'roi_p2': 0.10335480573205287, 'roi_p3': 0.10322347377503042, 'stoploss': -0.2780610808108503}, # noqa: E501
|
||||
'params_details': {'buy': {'mfi-value': 22, 'fastd-value': 20, 'adx-value': 29, 'rsi-value': 40, 'mfi-enabled': False, 'fastd-enabled': False, 'adx-enabled': False, 'rsi-enabled': False, 'trigger': 'sar_reversal'}, 'sell': {'sell-mfi-value': 97, 'sell-fastd-value': 65, 'sell-adx-value': 81, 'sell-rsi-value': 64, 'sell-mfi-enabled': True, 'sell-fastd-enabled': True, 'sell-adx-enabled': True, 'sell-rsi-enabled': True, 'sell-trigger': 'sell-bb_upper'}, 'roi': {0: 0.2433426031105559, 422: 0.14011912933552545, 1006: 0.036764323603472565, 2018: 0}, 'stoploss': {'stoploss': -0.2780610808108503}}, # noqa: E501
|
||||
'results_metrics': {'trade_count': 229, 'avg_profit': -0.38433433624454144, 'median_profit': -1.2222, 'total_profit': -0.044050070000000004, 'profit': -88.01256299999999, 'duration': 6505.676855895196}, # noqa: E501
|
||||
'results_explanation': ' 229 trades. Avg profit -0.38%. Total profit -0.04405007 BTC ( -88.01Σ%). Avg duration 6505.7 min.', # noqa: E501
|
||||
'total_profit': -0.044050070000000004, # noqa: E501
|
||||
'current_epoch': 9,
|
||||
'is_initial_point': True,
|
||||
'is_best': False
|
||||
}, {
|
||||
'loss': -0.2604606005845212, # noqa: E501
|
||||
'params_dict': {'mfi-value': 23, 'fastd-value': 24, 'adx-value': 22, 'rsi-value': 24, 'mfi-enabled': False, 'fastd-enabled': False, 'adx-enabled': False, 'rsi-enabled': True, 'trigger': 'macd_cross_signal', 'sell-mfi-value': 97, 'sell-fastd-value': 70, 'sell-adx-value': 64, 'sell-rsi-value': 80, 'sell-mfi-enabled': False, 'sell-fastd-enabled': True, 'sell-adx-enabled': True, 'sell-rsi-enabled': True, 'sell-trigger': 'sell-sar_reversal', 'roi_t1': 792, 'roi_t2': 464, 'roi_t3': 215, 'roi_p1': 0.04594053535385903, 'roi_p2': 0.09623192684243963, 'roi_p3': 0.04428219070850663, 'stoploss': -0.16992287161634415}, # noqa: E501
|
||||
'params_details': {'buy': {'mfi-value': 23, 'fastd-value': 24, 'adx-value': 22, 'rsi-value': 24, 'mfi-enabled': False, 'fastd-enabled': False, 'adx-enabled': False, 'rsi-enabled': True, 'trigger': 'macd_cross_signal'}, 'sell': {'sell-mfi-value': 97, 'sell-fastd-value': 70, 'sell-adx-value': 64, 'sell-rsi-value': 80, 'sell-mfi-enabled': False, 'sell-fastd-enabled': True, 'sell-adx-enabled': True, 'sell-rsi-enabled': True, 'sell-trigger': 'sell-sar_reversal'}, 'roi': {0: 0.18645465290480528, 215: 0.14217246219629864, 679: 0.04594053535385903, 1471: 0}, 'stoploss': {'stoploss': -0.16992287161634415}}, # noqa: E501
|
||||
'results_metrics': {'trade_count': 4, 'avg_profit': 0.1080385, 'median_profit': -1.2222, 'total_profit': 0.00021629, 'profit': 0.432154, 'duration': 2850.0}, # noqa: E501
|
||||
'results_explanation': ' 4 trades. Avg profit 0.11%. Total profit 0.00021629 BTC ( 0.43Σ%). Avg duration 2850.0 min.', # noqa: E501
|
||||
'total_profit': 0.00021629,
|
||||
'current_epoch': 10,
|
||||
'is_initial_point': True,
|
||||
'is_best': True
|
||||
}, {
|
||||
'loss': 4.876465945994304, # noqa: E501
|
||||
'params_dict': {'mfi-value': 20, 'fastd-value': 32, 'adx-value': 49, 'rsi-value': 23, 'mfi-enabled': True, 'fastd-enabled': True, 'adx-enabled': False, 'rsi-enabled': False, 'trigger': 'bb_lower', 'sell-mfi-value': 75, 'sell-fastd-value': 56, 'sell-adx-value': 61, 'sell-rsi-value': 62, 'sell-mfi-enabled': False, 'sell-fastd-enabled': False, 'sell-adx-enabled': True, 'sell-rsi-enabled': True, 'sell-trigger': 'sell-macd_cross_signal', 'roi_t1': 579, 'roi_t2': 614, 'roi_t3': 273, 'roi_p1': 0.05307643172744114, 'roi_p2': 0.1352282078262871, 'roi_p3': 0.1913307406325751, 'stoploss': -0.25728526022513887}, # noqa: E501
|
||||
'params_details': {'buy': {'mfi-value': 20, 'fastd-value': 32, 'adx-value': 49, 'rsi-value': 23, 'mfi-enabled': True, 'fastd-enabled': True, 'adx-enabled': False, 'rsi-enabled': False, 'trigger': 'bb_lower'}, 'sell': {'sell-mfi-value': 75, 'sell-fastd-value': 56, 'sell-adx-value': 61, 'sell-rsi-value': 62, 'sell-mfi-enabled': False, 'sell-fastd-enabled': False, 'sell-adx-enabled': True, 'sell-rsi-enabled': True, 'sell-trigger': 'sell-macd_cross_signal'}, 'roi': {0: 0.3796353801863034, 273: 0.18830463955372825, 887: 0.05307643172744114, 1466: 0}, 'stoploss': {'stoploss': -0.25728526022513887}}, # noqa: E501
|
||||
'results_metrics': {'trade_count': 117, 'avg_profit': -1.2698609145299145, 'median_profit': -1.2222, 'total_profit': -0.07436117, 'profit': -148.573727, 'duration': 4282.5641025641025}, # noqa: E501
|
||||
'results_explanation': ' 117 trades. Avg profit -1.27%. Total profit -0.07436117 BTC (-148.57Σ%). Avg duration 4282.6 min.', # noqa: E501
|
||||
'total_profit': -0.07436117,
|
||||
'current_epoch': 11,
|
||||
'is_initial_point': True,
|
||||
'is_best': False
|
||||
}, {
|
||||
'loss': 100000,
|
||||
'params_dict': {'mfi-value': 10, 'fastd-value': 36, 'adx-value': 31, 'rsi-value': 22, 'mfi-enabled': True, 'fastd-enabled': True, 'adx-enabled': True, 'rsi-enabled': False, 'trigger': 'sar_reversal', 'sell-mfi-value': 80, 'sell-fastd-value': 71, 'sell-adx-value': 60, 'sell-rsi-value': 85, 'sell-mfi-enabled': False, 'sell-fastd-enabled': False, 'sell-adx-enabled': True, 'sell-rsi-enabled': True, 'sell-trigger': 'sell-bb_upper', 'roi_t1': 1156, 'roi_t2': 581, 'roi_t3': 408, 'roi_p1': 0.06860454019988212, 'roi_p2': 0.12473718444931989, 'roi_p3': 0.2896360635226823, 'stoploss': -0.30889015124682806}, # noqa: E501
|
||||
'params_details': {'buy': {'mfi-value': 10, 'fastd-value': 36, 'adx-value': 31, 'rsi-value': 22, 'mfi-enabled': True, 'fastd-enabled': True, 'adx-enabled': True, 'rsi-enabled': False, 'trigger': 'sar_reversal'}, 'sell': {'sell-mfi-value': 80, 'sell-fastd-value': 71, 'sell-adx-value': 60, 'sell-rsi-value': 85, 'sell-mfi-enabled': False, 'sell-fastd-enabled': False, 'sell-adx-enabled': True, 'sell-rsi-enabled': True, 'sell-trigger': 'sell-bb_upper'}, 'roi': {0: 0.4829777881718843, 408: 0.19334172464920202, 989: 0.06860454019988212, 2145: 0}, 'stoploss': {'stoploss': -0.30889015124682806}}, # noqa: E501
|
||||
'results_metrics': {'trade_count': 0, 'avg_profit': None, 'median_profit': None, 'total_profit': 0, 'profit': 0.0, 'duration': None}, # noqa: E501
|
||||
'results_explanation': ' 0 trades. Avg profit nan%. Total profit 0.00000000 BTC ( 0.00Σ%). Avg duration nan min.', # noqa: E501
|
||||
'total_profit': 0,
|
||||
'current_epoch': 12,
|
||||
'is_initial_point': True,
|
||||
'is_best': False
|
||||
}
|
||||
]
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def saved_hyperopt_results():
|
||||
hyperopt_res = [
|
||||
|
@@ -119,7 +119,7 @@ def test_ohlcv_fill_up_missing_data2(caplog):
|
||||
# 3rd candle has been filled
|
||||
row = data2.loc[2, :]
|
||||
assert row['volume'] == 0
|
||||
# close shoult match close of previous candle
|
||||
# close should match close of previous candle
|
||||
assert row['close'] == data.loc[1, 'close']
|
||||
assert row['open'] == row['close']
|
||||
assert row['high'] == row['close']
|
||||
|
@@ -66,7 +66,7 @@ def test_historic_ohlcv_dataformat(mocker, default_conf, ohlcv_history):
|
||||
hdf5loadmock.assert_not_called()
|
||||
jsonloadmock.assert_called_once()
|
||||
|
||||
# Swiching to dataformat hdf5
|
||||
# Switching to dataformat hdf5
|
||||
hdf5loadmock.reset_mock()
|
||||
jsonloadmock.reset_mock()
|
||||
default_conf["dataformat_ohlcv"] = "hdf5"
|
||||
|
@@ -133,8 +133,8 @@ def test_load_data_with_new_pair_1min(ohlcv_history_list, mocker, caplog,
|
||||
load_pair_history(datadir=tmpdir1, timeframe='1m', pair='MEME/BTC')
|
||||
assert file.is_file()
|
||||
assert log_has_re(
|
||||
'Download history data for pair: "MEME/BTC", timeframe: 1m '
|
||||
'and store in .*', caplog
|
||||
r'Download history data for pair: "MEME/BTC" \(0/1\), timeframe: 1m '
|
||||
r'and store in .*', caplog
|
||||
)
|
||||
|
||||
|
||||
@@ -200,15 +200,15 @@ def test_load_cached_data_for_updating(mocker, testdatadir) -> None:
|
||||
assert start_ts == test_data[0][0] - 1000
|
||||
|
||||
# timeframe starts in the center of the cached data
|
||||
# should return the chached data w/o the last item
|
||||
# should return the cached data w/o the last item
|
||||
timerange = TimeRange('date', None, test_data[0][0] / 1000 + 1, 0)
|
||||
data, start_ts = _load_cached_data_for_updating('UNITTEST/BTC', '1m', timerange, data_handler)
|
||||
|
||||
assert_frame_equal(data, test_data_df.iloc[:-1])
|
||||
assert test_data[-2][0] <= start_ts < test_data[-1][0]
|
||||
|
||||
# timeframe starts after the chached data
|
||||
# should return the chached data w/o the last item
|
||||
# timeframe starts after the cached data
|
||||
# should return the cached data w/o the last item
|
||||
timerange = TimeRange('date', None, test_data[-1][0] / 1000 + 100, 0)
|
||||
data, start_ts = _load_cached_data_for_updating('UNITTEST/BTC', '1m', timerange, data_handler)
|
||||
assert_frame_equal(data, test_data_df.iloc[:-1])
|
||||
@@ -278,8 +278,10 @@ def test_download_pair_history2(mocker, default_conf, testdatadir) -> None:
|
||||
return_value=None)
|
||||
mocker.patch('freqtrade.exchange.Exchange.get_historic_ohlcv', return_value=tick)
|
||||
exchange = get_patched_exchange(mocker, default_conf)
|
||||
_download_pair_history(testdatadir, exchange, pair="UNITTEST/BTC", timeframe='1m')
|
||||
_download_pair_history(testdatadir, exchange, pair="UNITTEST/BTC", timeframe='3m')
|
||||
_download_pair_history(datadir=testdatadir, exchange=exchange, pair="UNITTEST/BTC",
|
||||
timeframe='1m')
|
||||
_download_pair_history(datadir=testdatadir, exchange=exchange, pair="UNITTEST/BTC",
|
||||
timeframe='3m')
|
||||
assert json_dump_mock.call_count == 2
|
||||
|
||||
|
||||
@@ -381,7 +383,7 @@ def test_get_timerange(default_conf, mocker, testdatadir) -> None:
|
||||
default_conf.update({'strategy': 'DefaultStrategy'})
|
||||
strategy = StrategyResolver.load_strategy(default_conf)
|
||||
|
||||
data = strategy.ohlcvdata_to_dataframe(
|
||||
data = strategy.advise_all_indicators(
|
||||
load_data(
|
||||
datadir=testdatadir,
|
||||
timeframe='1m',
|
||||
@@ -399,7 +401,7 @@ def test_validate_backtest_data_warn(default_conf, mocker, caplog, testdatadir)
|
||||
default_conf.update({'strategy': 'DefaultStrategy'})
|
||||
strategy = StrategyResolver.load_strategy(default_conf)
|
||||
|
||||
data = strategy.ohlcvdata_to_dataframe(
|
||||
data = strategy.advise_all_indicators(
|
||||
load_data(
|
||||
datadir=testdatadir,
|
||||
timeframe='1m',
|
||||
@@ -424,7 +426,7 @@ def test_validate_backtest_data(default_conf, mocker, caplog, testdatadir) -> No
|
||||
strategy = StrategyResolver.load_strategy(default_conf)
|
||||
|
||||
timerange = TimeRange('index', 'index', 200, 250)
|
||||
data = strategy.ohlcvdata_to_dataframe(
|
||||
data = strategy.advise_all_indicators(
|
||||
load_data(
|
||||
datadir=testdatadir,
|
||||
timeframe='5m',
|
||||
|
@@ -42,6 +42,11 @@ EXCHANGES = {
|
||||
'hasQuoteVolume': True,
|
||||
'timeframe': '5m',
|
||||
},
|
||||
'gateio': {
|
||||
'pair': 'BTC/USDT',
|
||||
'hasQuoteVolume': True,
|
||||
'timeframe': '5m',
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@@ -142,8 +147,8 @@ class TestCCXTExchange():
|
||||
def test_ccxt_get_fee(self, exchange):
|
||||
exchange, exchangename = exchange
|
||||
pair = EXCHANGES[exchangename]['pair']
|
||||
|
||||
assert 0 < exchange.get_fee(pair, 'limit', 'buy') < 1
|
||||
assert 0 < exchange.get_fee(pair, 'limit', 'sell') < 1
|
||||
assert 0 < exchange.get_fee(pair, 'market', 'buy') < 1
|
||||
assert 0 < exchange.get_fee(pair, 'market', 'sell') < 1
|
||||
threshold = 0.01
|
||||
assert 0 < exchange.get_fee(pair, 'limit', 'buy') < threshold
|
||||
assert 0 < exchange.get_fee(pair, 'limit', 'sell') < threshold
|
||||
assert 0 < exchange.get_fee(pair, 'market', 'buy') < threshold
|
||||
assert 0 < exchange.get_fee(pair, 'market', 'sell') < threshold
|
||||
|
@@ -984,16 +984,21 @@ def test_create_dry_run_order_limit_fill(default_conf, mocker, side, startprice,
|
||||
assert order['fee']
|
||||
|
||||
|
||||
@pytest.mark.parametrize("side,amount,endprice", [
|
||||
("buy", 1, 25.566),
|
||||
("buy", 100, 25.5672), # Requires interpolation
|
||||
("buy", 1000, 25.575), # More than orderbook return
|
||||
("sell", 1, 25.563),
|
||||
("sell", 100, 25.5625), # Requires interpolation
|
||||
("sell", 1000, 25.5555), # More than orderbook return
|
||||
@pytest.mark.parametrize("side,rate,amount,endprice", [
|
||||
# spread is 25.263-25.266
|
||||
("buy", 25.564, 1, 25.566),
|
||||
("buy", 25.564, 100, 25.5672), # Requires interpolation
|
||||
("buy", 25.590, 100, 25.5672), # Price above spread ... average is lower
|
||||
("buy", 25.564, 1000, 25.575), # More than orderbook return
|
||||
("buy", 24.000, 100000, 25.200), # Run into max_slippage of 5%
|
||||
("sell", 25.564, 1, 25.563),
|
||||
("sell", 25.564, 100, 25.5625), # Requires interpolation
|
||||
("sell", 25.510, 100, 25.5625), # price below spread - average is higher
|
||||
("sell", 25.564, 1000, 25.5555), # More than orderbook return
|
||||
("sell", 27, 10000, 25.65), # max-slippage 5%
|
||||
])
|
||||
@pytest.mark.parametrize("exchange_name", EXCHANGES)
|
||||
def test_create_dry_run_order_market_fill(default_conf, mocker, side, amount, endprice,
|
||||
def test_create_dry_run_order_market_fill(default_conf, mocker, side, rate, amount, endprice,
|
||||
exchange_name, order_book_l2_usd):
|
||||
default_conf['dry_run'] = True
|
||||
exchange = get_patched_exchange(mocker, default_conf, id=exchange_name)
|
||||
@@ -1003,7 +1008,7 @@ def test_create_dry_run_order_market_fill(default_conf, mocker, side, amount, en
|
||||
)
|
||||
|
||||
order = exchange.create_dry_run_order(
|
||||
pair='LTC/USDT', ordertype='market', side=side, amount=amount, rate=25.5)
|
||||
pair='LTC/USDT', ordertype='market', side=side, amount=amount, rate=rate)
|
||||
assert 'id' in order
|
||||
assert f'dry_run_{side}_' in order["id"]
|
||||
assert order["side"] == side
|
||||
@@ -1559,13 +1564,16 @@ def test_refresh_latest_ohlcv(mocker, default_conf, caplog) -> None:
|
||||
pairs = [('IOTA/ETH', '5m'), ('XRP/ETH', '5m')]
|
||||
# empty dicts
|
||||
assert not exchange._klines
|
||||
exchange.refresh_latest_ohlcv(pairs, cache=False)
|
||||
res = exchange.refresh_latest_ohlcv(pairs, cache=False)
|
||||
# No caching
|
||||
assert not exchange._klines
|
||||
|
||||
assert len(res) == len(pairs)
|
||||
assert exchange._api_async.fetch_ohlcv.call_count == 2
|
||||
exchange._api_async.fetch_ohlcv.reset_mock()
|
||||
|
||||
exchange.refresh_latest_ohlcv(pairs)
|
||||
res = exchange.refresh_latest_ohlcv(pairs)
|
||||
assert len(res) == len(pairs)
|
||||
|
||||
assert log_has(f'Refreshing candle (OHLCV) data for {len(pairs)} pairs', caplog)
|
||||
assert exchange._klines
|
||||
@@ -1582,12 +1590,16 @@ def test_refresh_latest_ohlcv(mocker, default_conf, caplog) -> None:
|
||||
assert exchange.klines(pair, copy=False) is exchange.klines(pair, copy=False)
|
||||
|
||||
# test caching
|
||||
exchange.refresh_latest_ohlcv([('IOTA/ETH', '5m'), ('XRP/ETH', '5m')])
|
||||
res = exchange.refresh_latest_ohlcv([('IOTA/ETH', '5m'), ('XRP/ETH', '5m')])
|
||||
assert len(res) == len(pairs)
|
||||
|
||||
assert exchange._api_async.fetch_ohlcv.call_count == 2
|
||||
assert log_has(f"Using cached candle (OHLCV) data for pair {pairs[0][0]}, "
|
||||
f"timeframe {pairs[0][1]} ...",
|
||||
caplog)
|
||||
res = exchange.refresh_latest_ohlcv([('IOTA/ETH', '5m'), ('XRP/ETH', '5m'), ('XRP/ETH', '1d')],
|
||||
cache=False)
|
||||
assert len(res) == 3
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@@ -2177,7 +2189,7 @@ def test_get_historic_trades_notsupported(default_conf, mocker, caplog, exchange
|
||||
pair = 'ETH/BTC'
|
||||
|
||||
with pytest.raises(OperationalException,
|
||||
match="This exchange does not suport downloading Trades."):
|
||||
match="This exchange does not support downloading Trades."):
|
||||
exchange.get_historic_trades(pair, since=trades_history[0][0],
|
||||
until=trades_history[-1][0])
|
||||
|
||||
|
@@ -52,4 +52,6 @@ def _build_backtest_dataframe(data):
|
||||
# Ensure floats are in place
|
||||
for column in ['open', 'high', 'low', 'close', 'volume']:
|
||||
frame[column] = frame[column].astype('float64')
|
||||
if 'buy_tag' not in columns:
|
||||
frame['buy_tag'] = None
|
||||
return frame
|
||||
|
@@ -1,6 +1,7 @@
|
||||
# pragma pylint: disable=missing-docstring, W0212, line-too-long, C0103, unused-argument
|
||||
|
||||
import random
|
||||
from datetime import timedelta
|
||||
from pathlib import Path
|
||||
from unittest.mock import MagicMock, PropertyMock
|
||||
|
||||
@@ -85,7 +86,7 @@ def simple_backtest(config, contour, mocker, testdatadir) -> None:
|
||||
backtesting._set_strategy(backtesting.strategylist[0])
|
||||
|
||||
data = load_data_test(contour, testdatadir)
|
||||
processed = backtesting.strategy.ohlcvdata_to_dataframe(data)
|
||||
processed = backtesting.strategy.advise_all_indicators(data)
|
||||
min_date, max_date = get_timerange(processed)
|
||||
assert isinstance(processed, dict)
|
||||
results = backtesting.backtest(
|
||||
@@ -107,7 +108,7 @@ def _make_backtest_conf(mocker, datadir, conf=None, pair='UNITTEST/BTC'):
|
||||
patch_exchange(mocker)
|
||||
backtesting = Backtesting(conf)
|
||||
backtesting._set_strategy(backtesting.strategylist[0])
|
||||
processed = backtesting.strategy.ohlcvdata_to_dataframe(data)
|
||||
processed = backtesting.strategy.advise_all_indicators(data)
|
||||
min_date, max_date = get_timerange(processed)
|
||||
return {
|
||||
'processed': processed,
|
||||
@@ -289,7 +290,7 @@ def test_backtesting_init(mocker, default_conf, order_types) -> None:
|
||||
backtesting._set_strategy(backtesting.strategylist[0])
|
||||
assert backtesting.config == default_conf
|
||||
assert backtesting.timeframe == '5m'
|
||||
assert callable(backtesting.strategy.ohlcvdata_to_dataframe)
|
||||
assert callable(backtesting.strategy.advise_all_indicators)
|
||||
assert callable(backtesting.strategy.advise_buy)
|
||||
assert callable(backtesting.strategy.advise_sell)
|
||||
assert isinstance(backtesting.strategy.dp, DataProvider)
|
||||
@@ -335,14 +336,14 @@ def test_data_to_dataframe_bt(default_conf, mocker, testdatadir) -> None:
|
||||
fill_up_missing=True)
|
||||
backtesting = Backtesting(default_conf)
|
||||
backtesting._set_strategy(backtesting.strategylist[0])
|
||||
processed = backtesting.strategy.ohlcvdata_to_dataframe(data)
|
||||
processed = backtesting.strategy.advise_all_indicators(data)
|
||||
assert len(processed['UNITTEST/BTC']) == 102
|
||||
|
||||
# Load strategy to compare the result between Backtesting function and strategy are the same
|
||||
default_conf.update({'strategy': 'DefaultStrategy'})
|
||||
strategy = StrategyResolver.load_strategy(default_conf)
|
||||
|
||||
processed2 = strategy.ohlcvdata_to_dataframe(data)
|
||||
processed2 = strategy.advise_all_indicators(data)
|
||||
assert processed['UNITTEST/BTC'].equals(processed2['UNITTEST/BTC'])
|
||||
|
||||
|
||||
@@ -535,6 +536,8 @@ def test_backtest__enter_trade(default_conf, fee, mocker) -> None:
|
||||
trade = backtesting._enter_trade(pair, row=row)
|
||||
assert trade is None
|
||||
|
||||
backtesting.cleanup()
|
||||
|
||||
|
||||
def test_backtest_one(default_conf, fee, mocker, testdatadir) -> None:
|
||||
default_conf['use_sell_signal'] = False
|
||||
@@ -547,7 +550,7 @@ def test_backtest_one(default_conf, fee, mocker, testdatadir) -> None:
|
||||
timerange = TimeRange('date', None, 1517227800, 0)
|
||||
data = history.load_data(datadir=testdatadir, timeframe='5m', pairs=['UNITTEST/BTC'],
|
||||
timerange=timerange)
|
||||
processed = backtesting.strategy.ohlcvdata_to_dataframe(data)
|
||||
processed = backtesting.strategy.advise_all_indicators(data)
|
||||
min_date, max_date = get_timerange(processed)
|
||||
result = backtesting.backtest(
|
||||
processed=processed,
|
||||
@@ -581,7 +584,7 @@ def test_backtest_one(default_conf, fee, mocker, testdatadir) -> None:
|
||||
'initial_stop_loss_ratio': [-0.1, -0.1],
|
||||
'stop_loss_abs': [0.0940005, 0.09272236],
|
||||
'stop_loss_ratio': [-0.1, -0.1],
|
||||
'min_rate': [0.1038, 0.10302485],
|
||||
'min_rate': [0.10370188, 0.10300000000000001],
|
||||
'max_rate': [0.10501, 0.1038888],
|
||||
'is_open': [False, False],
|
||||
'buy_tag': [None, None],
|
||||
@@ -612,7 +615,7 @@ def test_backtest_1min_timeframe(default_conf, fee, mocker, testdatadir) -> None
|
||||
timerange = TimeRange.parse_timerange('1510688220-1510700340')
|
||||
data = history.load_data(datadir=testdatadir, timeframe='1m', pairs=['UNITTEST/BTC'],
|
||||
timerange=timerange)
|
||||
processed = backtesting.strategy.ohlcvdata_to_dataframe(data)
|
||||
processed = backtesting.strategy.advise_all_indicators(data)
|
||||
min_date, max_date = get_timerange(processed)
|
||||
results = backtesting.backtest(
|
||||
processed=processed,
|
||||
@@ -631,7 +634,7 @@ def test_processed(default_conf, mocker, testdatadir) -> None:
|
||||
backtesting._set_strategy(backtesting.strategylist[0])
|
||||
|
||||
dict_of_tickerrows = load_data_test('raise', testdatadir)
|
||||
dataframes = backtesting.strategy.ohlcvdata_to_dataframe(dict_of_tickerrows)
|
||||
dataframes = backtesting.strategy.advise_all_indicators(dict_of_tickerrows)
|
||||
dataframe = dataframes['UNITTEST/BTC']
|
||||
cols = dataframe.columns
|
||||
# assert the dataframe got some of the indicator columns
|
||||
@@ -739,8 +742,13 @@ def test_backtest_alternate_buy_sell(default_conf, fee, mocker, testdatadir):
|
||||
# 100 buys signals
|
||||
results = result['results']
|
||||
assert len(results) == 100
|
||||
# Cached data should be 200 (no change since required_startup is 0)
|
||||
assert len(backtesting.dataprovider.get_analyzed_dataframe('UNITTEST/BTC', '1m')[0]) == 200
|
||||
# Cached data should be 200
|
||||
analyzed_df = backtesting.dataprovider.get_analyzed_dataframe('UNITTEST/BTC', '1m')[0]
|
||||
assert len(analyzed_df) == 200
|
||||
# Expect last candle to be 1 below end date (as the last candle is assumed as "incomplete"
|
||||
# during backtesting)
|
||||
expected_last_candle_date = backtest_conf['end_date'] - timedelta(minutes=1)
|
||||
assert analyzed_df.iloc[-1]['date'].to_pydatetime() == expected_last_candle_date
|
||||
|
||||
# One trade was force-closed at the end
|
||||
assert len(results.loc[results['is_open']]) == 0
|
||||
@@ -772,7 +780,8 @@ def test_backtest_multi_pair(default_conf, fee, mocker, tres, pair, testdatadir)
|
||||
data = trim_dictlist(data, -500)
|
||||
|
||||
# Remove data for one pair from the beginning of the data
|
||||
data[pair] = data[pair][tres:].reset_index()
|
||||
if tres > 0:
|
||||
data[pair] = data[pair][tres:].reset_index()
|
||||
default_conf['timeframe'] = '5m'
|
||||
|
||||
backtesting = Backtesting(default_conf)
|
||||
@@ -780,7 +789,7 @@ def test_backtest_multi_pair(default_conf, fee, mocker, tres, pair, testdatadir)
|
||||
backtesting.strategy.advise_buy = _trend_alternate_hold # Override
|
||||
backtesting.strategy.advise_sell = _trend_alternate_hold # Override
|
||||
|
||||
processed = backtesting.strategy.ohlcvdata_to_dataframe(data)
|
||||
processed = backtesting.strategy.advise_all_indicators(data)
|
||||
min_date, max_date = get_timerange(processed)
|
||||
backtest_conf = {
|
||||
'processed': processed,
|
||||
@@ -798,8 +807,11 @@ def test_backtest_multi_pair(default_conf, fee, mocker, tres, pair, testdatadir)
|
||||
assert len(evaluate_result_multi(results['results'], '5m', 3)) == 0
|
||||
|
||||
# Cached data correctly removed amounts
|
||||
removed_candles = len(data[pair]) - 1 - backtesting.strategy.startup_candle_count
|
||||
offset = 1 if tres == 0 else 0
|
||||
removed_candles = len(data[pair]) - offset - backtesting.strategy.startup_candle_count
|
||||
assert len(backtesting.dataprovider.get_analyzed_dataframe(pair, '5m')[0]) == removed_candles
|
||||
assert len(backtesting.dataprovider.get_analyzed_dataframe(
|
||||
'NXT/BTC', '5m')[0]) == len(data['NXT/BTC']) - 1 - backtesting.strategy.startup_candle_count
|
||||
|
||||
backtest_conf = {
|
||||
'processed': processed,
|
||||
|
@@ -351,7 +351,7 @@ def test_start_calls_optimizer(mocker, hyperopt_conf, capsys) -> None:
|
||||
del hyperopt_conf['timeframe']
|
||||
|
||||
hyperopt = Hyperopt(hyperopt_conf)
|
||||
hyperopt.backtesting.strategy.ohlcvdata_to_dataframe = MagicMock()
|
||||
hyperopt.backtesting.strategy.advise_all_indicators = MagicMock()
|
||||
hyperopt.custom_hyperopt.generate_roi_table = MagicMock(return_value={})
|
||||
|
||||
hyperopt.start()
|
||||
@@ -426,7 +426,7 @@ def test_hyperopt_format_results(hyperopt):
|
||||
|
||||
def test_populate_indicators(hyperopt, testdatadir) -> None:
|
||||
data = load_data(testdatadir, '1m', ['UNITTEST/BTC'], fill_up_missing=True)
|
||||
dataframes = hyperopt.backtesting.strategy.ohlcvdata_to_dataframe(data)
|
||||
dataframes = hyperopt.backtesting.strategy.advise_all_indicators(data)
|
||||
dataframe = hyperopt.custom_hyperopt.populate_indicators(dataframes['UNITTEST/BTC'],
|
||||
{'pair': 'UNITTEST/BTC'})
|
||||
|
||||
@@ -438,7 +438,7 @@ def test_populate_indicators(hyperopt, testdatadir) -> None:
|
||||
|
||||
def test_buy_strategy_generator(hyperopt, testdatadir) -> None:
|
||||
data = load_data(testdatadir, '1m', ['UNITTEST/BTC'], fill_up_missing=True)
|
||||
dataframes = hyperopt.backtesting.strategy.ohlcvdata_to_dataframe(data)
|
||||
dataframes = hyperopt.backtesting.strategy.advise_all_indicators(data)
|
||||
dataframe = hyperopt.custom_hyperopt.populate_indicators(dataframes['UNITTEST/BTC'],
|
||||
{'pair': 'UNITTEST/BTC'})
|
||||
|
||||
@@ -463,7 +463,7 @@ def test_buy_strategy_generator(hyperopt, testdatadir) -> None:
|
||||
|
||||
def test_sell_strategy_generator(hyperopt, testdatadir) -> None:
|
||||
data = load_data(testdatadir, '1m', ['UNITTEST/BTC'], fill_up_missing=True)
|
||||
dataframes = hyperopt.backtesting.strategy.ohlcvdata_to_dataframe(data)
|
||||
dataframes = hyperopt.backtesting.strategy.advise_all_indicators(data)
|
||||
dataframe = hyperopt.custom_hyperopt.populate_indicators(dataframes['UNITTEST/BTC'],
|
||||
{'pair': 'UNITTEST/BTC'})
|
||||
|
||||
@@ -660,7 +660,7 @@ def test_print_json_spaces_all(mocker, hyperopt_conf, capsys) -> None:
|
||||
})
|
||||
|
||||
hyperopt = Hyperopt(hyperopt_conf)
|
||||
hyperopt.backtesting.strategy.ohlcvdata_to_dataframe = MagicMock()
|
||||
hyperopt.backtesting.strategy.advise_all_indicators = MagicMock()
|
||||
hyperopt.custom_hyperopt.generate_roi_table = MagicMock(return_value={})
|
||||
|
||||
hyperopt.start()
|
||||
@@ -713,7 +713,7 @@ def test_print_json_spaces_default(mocker, hyperopt_conf, capsys) -> None:
|
||||
hyperopt_conf.update({'print_json': True})
|
||||
|
||||
hyperopt = Hyperopt(hyperopt_conf)
|
||||
hyperopt.backtesting.strategy.ohlcvdata_to_dataframe = MagicMock()
|
||||
hyperopt.backtesting.strategy.advise_all_indicators = MagicMock()
|
||||
hyperopt.custom_hyperopt.generate_roi_table = MagicMock(return_value={})
|
||||
|
||||
hyperopt.start()
|
||||
@@ -761,7 +761,7 @@ def test_print_json_spaces_roi_stoploss(mocker, hyperopt_conf, capsys) -> None:
|
||||
})
|
||||
|
||||
hyperopt = Hyperopt(hyperopt_conf)
|
||||
hyperopt.backtesting.strategy.ohlcvdata_to_dataframe = MagicMock()
|
||||
hyperopt.backtesting.strategy.advise_all_indicators = MagicMock()
|
||||
hyperopt.custom_hyperopt.generate_roi_table = MagicMock(return_value={})
|
||||
|
||||
hyperopt.start()
|
||||
@@ -805,7 +805,7 @@ def test_simplified_interface_roi_stoploss(mocker, hyperopt_conf, capsys) -> Non
|
||||
hyperopt_conf.update({'spaces': 'roi stoploss'})
|
||||
|
||||
hyperopt = Hyperopt(hyperopt_conf)
|
||||
hyperopt.backtesting.strategy.ohlcvdata_to_dataframe = MagicMock()
|
||||
hyperopt.backtesting.strategy.advise_all_indicators = MagicMock()
|
||||
hyperopt.custom_hyperopt.generate_roi_table = MagicMock(return_value={})
|
||||
|
||||
del hyperopt.custom_hyperopt.__class__.buy_strategy_generator
|
||||
@@ -844,7 +844,7 @@ def test_simplified_interface_all_failed(mocker, hyperopt_conf) -> None:
|
||||
hyperopt_conf.update({'spaces': 'all', })
|
||||
|
||||
hyperopt = Hyperopt(hyperopt_conf)
|
||||
hyperopt.backtesting.strategy.ohlcvdata_to_dataframe = MagicMock()
|
||||
hyperopt.backtesting.strategy.advise_all_indicators = MagicMock()
|
||||
hyperopt.custom_hyperopt.generate_roi_table = MagicMock(return_value={})
|
||||
|
||||
del hyperopt.custom_hyperopt.__class__.buy_strategy_generator
|
||||
@@ -886,7 +886,7 @@ def test_simplified_interface_buy(mocker, hyperopt_conf, capsys) -> None:
|
||||
hyperopt_conf.update({'spaces': 'buy'})
|
||||
|
||||
hyperopt = Hyperopt(hyperopt_conf)
|
||||
hyperopt.backtesting.strategy.ohlcvdata_to_dataframe = MagicMock()
|
||||
hyperopt.backtesting.strategy.advise_all_indicators = MagicMock()
|
||||
hyperopt.custom_hyperopt.generate_roi_table = MagicMock(return_value={})
|
||||
|
||||
# TODO: sell_strategy_generator() is actually not called because
|
||||
@@ -940,7 +940,7 @@ def test_simplified_interface_sell(mocker, hyperopt_conf, capsys) -> None:
|
||||
hyperopt_conf.update({'spaces': 'sell', })
|
||||
|
||||
hyperopt = Hyperopt(hyperopt_conf)
|
||||
hyperopt.backtesting.strategy.ohlcvdata_to_dataframe = MagicMock()
|
||||
hyperopt.backtesting.strategy.advise_all_indicators = MagicMock()
|
||||
hyperopt.custom_hyperopt.generate_roi_table = MagicMock(return_value={})
|
||||
|
||||
# TODO: buy_strategy_generator() is actually not called because
|
||||
@@ -985,7 +985,7 @@ def test_simplified_interface_failed(mocker, hyperopt_conf, method, space) -> No
|
||||
hyperopt_conf.update({'spaces': space})
|
||||
|
||||
hyperopt = Hyperopt(hyperopt_conf)
|
||||
hyperopt.backtesting.strategy.ohlcvdata_to_dataframe = MagicMock()
|
||||
hyperopt.backtesting.strategy.advise_all_indicators = MagicMock()
|
||||
hyperopt.custom_hyperopt.generate_roi_table = MagicMock(return_value={})
|
||||
|
||||
delattr(hyperopt.custom_hyperopt.__class__, method)
|
||||
|
@@ -10,7 +10,7 @@ import rapidjson
|
||||
from freqtrade.constants import FTHYPT_FILEVERSION
|
||||
from freqtrade.exceptions import OperationalException
|
||||
from freqtrade.optimize.hyperopt_tools import HyperoptTools, hyperopt_serializer
|
||||
from tests.conftest import log_has, log_has_re
|
||||
from tests.conftest import log_has
|
||||
|
||||
|
||||
# Functions for recurrent object patching
|
||||
@@ -20,9 +20,14 @@ def create_results() -> List[Dict]:
|
||||
|
||||
|
||||
def test_save_results_saves_epochs(hyperopt, tmpdir, caplog) -> None:
|
||||
|
||||
hyperopt.results_file = Path(tmpdir / 'ut_results.fthypt')
|
||||
|
||||
hyperopt_epochs = HyperoptTools.load_filtered_results(hyperopt.results_file, {})
|
||||
assert hyperopt_epochs == ([], 0)
|
||||
|
||||
# Test writing to temp dir and reading again
|
||||
epochs = create_results()
|
||||
hyperopt.results_file = Path(tmpdir / 'ut_results.fthypt')
|
||||
|
||||
caplog.set_level(logging.DEBUG)
|
||||
|
||||
@@ -33,36 +38,28 @@ def test_save_results_saves_epochs(hyperopt, tmpdir, caplog) -> None:
|
||||
hyperopt._save_result(epochs[0])
|
||||
assert log_has(f"2 epochs saved to '{hyperopt.results_file}'.", caplog)
|
||||
|
||||
hyperopt_epochs = HyperoptTools.load_previous_results(hyperopt.results_file)
|
||||
hyperopt_epochs = HyperoptTools.load_filtered_results(hyperopt.results_file, {})
|
||||
assert len(hyperopt_epochs) == 2
|
||||
assert hyperopt_epochs[1] == 2
|
||||
assert len(hyperopt_epochs[0]) == 2
|
||||
|
||||
|
||||
def test_load_previous_results(testdatadir, caplog) -> None:
|
||||
|
||||
results_file = testdatadir / 'hyperopt_results_SampleStrategy.pickle'
|
||||
|
||||
hyperopt_epochs = HyperoptTools.load_previous_results(results_file)
|
||||
|
||||
assert len(hyperopt_epochs) == 5
|
||||
assert log_has_re(r"Reading pickled epochs from .*", caplog)
|
||||
|
||||
caplog.clear()
|
||||
|
||||
# Modern version
|
||||
results_file = testdatadir / 'strategy_SampleStrategy.fthypt'
|
||||
|
||||
hyperopt_epochs = HyperoptTools.load_previous_results(results_file)
|
||||
|
||||
assert len(hyperopt_epochs) == 5
|
||||
assert log_has_re(r"Reading epochs from .*", caplog)
|
||||
result_gen = HyperoptTools._read_results(hyperopt.results_file, 1)
|
||||
epoch = next(result_gen)
|
||||
assert len(epoch) == 1
|
||||
assert epoch[0] == epochs[0]
|
||||
epoch = next(result_gen)
|
||||
assert len(epoch) == 1
|
||||
epoch = next(result_gen)
|
||||
assert len(epoch) == 0
|
||||
with pytest.raises(StopIteration):
|
||||
next(result_gen)
|
||||
|
||||
|
||||
def test_load_previous_results2(mocker, testdatadir, caplog) -> None:
|
||||
mocker.patch('freqtrade.optimize.hyperopt_tools.HyperoptTools._read_results_pickle',
|
||||
return_value=[{'asdf': '222'}])
|
||||
results_file = testdatadir / 'hyperopt_results_SampleStrategy.pickle'
|
||||
with pytest.raises(OperationalException, match=r"The file .* incompatible.*"):
|
||||
HyperoptTools.load_previous_results(results_file)
|
||||
with pytest.raises(OperationalException,
|
||||
match=r"Legacy hyperopt results are no longer supported.*"):
|
||||
HyperoptTools.load_filtered_results(results_file, {})
|
||||
|
||||
|
||||
@pytest.mark.parametrize("spaces, expected_results", [
|
||||
|
@@ -22,7 +22,7 @@ def test_fiat_convert_is_supported(mocker):
|
||||
def test_fiat_convert_find_price(mocker):
|
||||
fiat_convert = CryptoToFiatConverter()
|
||||
|
||||
fiat_convert._cryptomap = {}
|
||||
fiat_convert._coinlistings = {}
|
||||
fiat_convert._backoff = 0
|
||||
mocker.patch('freqtrade.rpc.fiat_convert.CryptoToFiatConverter._load_cryptomap',
|
||||
return_value=None)
|
||||
@@ -44,7 +44,7 @@ def test_fiat_convert_find_price(mocker):
|
||||
|
||||
|
||||
def test_fiat_convert_unsupported_crypto(mocker, caplog):
|
||||
mocker.patch('freqtrade.rpc.fiat_convert.CryptoToFiatConverter._cryptomap', return_value=[])
|
||||
mocker.patch('freqtrade.rpc.fiat_convert.CryptoToFiatConverter._coinlistings', return_value=[])
|
||||
fiat_convert = CryptoToFiatConverter()
|
||||
assert fiat_convert._find_price(crypto_symbol='CRYPTO_123', fiat_symbol='EUR') == 0.0
|
||||
assert log_has('unsupported crypto-symbol CRYPTO_123 - returning 0.0', caplog)
|
||||
@@ -88,9 +88,9 @@ def test_fiat_convert_two_FIAT(mocker):
|
||||
def test_loadcryptomap(mocker):
|
||||
|
||||
fiat_convert = CryptoToFiatConverter()
|
||||
assert len(fiat_convert._cryptomap) == 2
|
||||
assert len(fiat_convert._coinlistings) == 2
|
||||
|
||||
assert fiat_convert._cryptomap["btc"] == "bitcoin"
|
||||
assert fiat_convert._get_gekko_id("btc") == "bitcoin"
|
||||
|
||||
|
||||
def test_fiat_init_network_exception(mocker):
|
||||
@@ -102,11 +102,10 @@ def test_fiat_init_network_exception(mocker):
|
||||
)
|
||||
# with pytest.raises(RequestEsxception):
|
||||
fiat_convert = CryptoToFiatConverter()
|
||||
fiat_convert._cryptomap = {}
|
||||
fiat_convert._coinlistings = {}
|
||||
fiat_convert._load_cryptomap()
|
||||
|
||||
length_cryptomap = len(fiat_convert._cryptomap)
|
||||
assert length_cryptomap == 0
|
||||
assert len(fiat_convert._coinlistings) == 0
|
||||
|
||||
|
||||
def test_fiat_convert_without_network(mocker):
|
||||
@@ -132,11 +131,10 @@ def test_fiat_too_many_requests_response(mocker, caplog):
|
||||
)
|
||||
# with pytest.raises(RequestEsxception):
|
||||
fiat_convert = CryptoToFiatConverter()
|
||||
fiat_convert._cryptomap = {}
|
||||
fiat_convert._coinlistings = {}
|
||||
fiat_convert._load_cryptomap()
|
||||
|
||||
length_cryptomap = len(fiat_convert._cryptomap)
|
||||
assert length_cryptomap == 0
|
||||
assert len(fiat_convert._coinlistings) == 0
|
||||
assert fiat_convert._backoff > datetime.datetime.now().timestamp()
|
||||
assert log_has(
|
||||
'Too many requests for Coingecko API, backing off and trying again later.',
|
||||
@@ -144,20 +142,33 @@ def test_fiat_too_many_requests_response(mocker, caplog):
|
||||
)
|
||||
|
||||
|
||||
def test_fiat_multiple_coins(mocker, caplog):
|
||||
fiat_convert = CryptoToFiatConverter()
|
||||
fiat_convert._coinlistings = [
|
||||
{'id': 'helium', 'symbol': 'hnt', 'name': 'Helium'},
|
||||
{'id': 'hymnode', 'symbol': 'hnt', 'name': 'Hymnode'},
|
||||
{'id': 'bitcoin', 'symbol': 'btc', 'name': 'Bitcoin'},
|
||||
]
|
||||
|
||||
assert fiat_convert._get_gekko_id('btc') == 'bitcoin'
|
||||
assert fiat_convert._get_gekko_id('hnt') is None
|
||||
|
||||
assert log_has('Found multiple mappings in goingekko for hnt.', caplog)
|
||||
|
||||
|
||||
def test_fiat_invalid_response(mocker, caplog):
|
||||
# Because CryptoToFiatConverter is a Singleton we reset the listings
|
||||
listmock = MagicMock(return_value="{'novalidjson':DEADBEEFf}")
|
||||
listmock = MagicMock(return_value=None)
|
||||
mocker.patch.multiple(
|
||||
'freqtrade.rpc.fiat_convert.CoinGeckoAPI',
|
||||
get_coins_list=listmock,
|
||||
)
|
||||
# with pytest.raises(RequestEsxception):
|
||||
fiat_convert = CryptoToFiatConverter()
|
||||
fiat_convert._cryptomap = {}
|
||||
fiat_convert._coinlistings = []
|
||||
fiat_convert._load_cryptomap()
|
||||
|
||||
length_cryptomap = len(fiat_convert._cryptomap)
|
||||
assert length_cryptomap == 0
|
||||
assert len(fiat_convert._coinlistings) == 0
|
||||
assert log_has_re('Could not load FIAT Cryptocurrency map for the following problem: .*',
|
||||
caplog)
|
||||
|
||||
|
@@ -109,6 +109,11 @@ def test_api_ui_fallback(botclient):
|
||||
rc = client_get(client, "/something")
|
||||
assert rc.status_code == 200
|
||||
|
||||
# Test directory traversal
|
||||
rc = client_get(client, '%2F%2F%2Fetc/passwd')
|
||||
assert rc.status_code == 200
|
||||
assert '`freqtrade install-ui`' in rc.text
|
||||
|
||||
|
||||
def test_api_ui_version(botclient, mocker):
|
||||
ftbot, client = botclient
|
||||
|
@@ -232,25 +232,25 @@ def test_assert_df(ohlcv_history, caplog):
|
||||
_STRATEGY.disable_dataframe_checks = False
|
||||
|
||||
|
||||
def test_ohlcvdata_to_dataframe(default_conf, testdatadir) -> None:
|
||||
def test_advise_all_indicators(default_conf, testdatadir) -> None:
|
||||
default_conf.update({'strategy': 'DefaultStrategy'})
|
||||
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.ohlcvdata_to_dataframe(data)
|
||||
processed = strategy.advise_all_indicators(data)
|
||||
assert len(processed['UNITTEST/BTC']) == 102 # partial candle was removed
|
||||
|
||||
|
||||
def test_ohlcvdata_to_dataframe_copy(mocker, default_conf, testdatadir) -> None:
|
||||
def test_advise_all_indicators_copy(mocker, default_conf, testdatadir) -> None:
|
||||
default_conf.update({'strategy': 'DefaultStrategy'})
|
||||
strategy = StrategyResolver.load_strategy(default_conf)
|
||||
aimock = mocker.patch('freqtrade.strategy.interface.IStrategy.advise_indicators')
|
||||
timerange = TimeRange.parse_timerange('1510694220-1510700340')
|
||||
data = load_data(testdatadir, '1m', ['UNITTEST/BTC'], timerange=timerange,
|
||||
fill_up_missing=True)
|
||||
strategy.ohlcvdata_to_dataframe(data)
|
||||
strategy.advise_all_indicators(data)
|
||||
assert aimock.call_count == 1
|
||||
# Ensure that a copy of the dataframe is passed to advice_indicators
|
||||
assert aimock.call_args_list[0][0][0] is not data
|
||||
@@ -402,7 +402,7 @@ def test_stop_loss_reached(default_conf, fee, profit, adjusted, expected, traili
|
||||
exchange='binance',
|
||||
open_rate=1,
|
||||
)
|
||||
trade.adjust_min_max_rates(trade.open_rate)
|
||||
trade.adjust_min_max_rates(trade.open_rate, trade.open_rate)
|
||||
strategy.trailing_stop = trailing
|
||||
strategy.trailing_stop_positive = -0.05
|
||||
strategy.use_custom_stoploss = custom
|
||||
@@ -556,6 +556,7 @@ def test__analyze_ticker_internal_skip_analyze(ohlcv_history, mocker, caplog) ->
|
||||
def test_is_pair_locked(default_conf):
|
||||
default_conf.update({'strategy': 'DefaultStrategy'})
|
||||
PairLocks.timeframe = default_conf['timeframe']
|
||||
PairLocks.use_db = True
|
||||
strategy = StrategyResolver.load_strategy(default_conf)
|
||||
# No lock should be present
|
||||
assert len(PairLocks.get_pair_locks(None)) == 0
|
||||
@@ -633,7 +634,7 @@ def test_strategy_safe_wrapper_error(caplog, error):
|
||||
assert ret
|
||||
|
||||
caplog.clear()
|
||||
# Test supressing error
|
||||
# Test suppressing error
|
||||
ret = strategy_safe_wrapper(failing_method, message='DeadBeef', supress_error=True)()
|
||||
assert log_has_re(r'DeadBeef.*', caplog)
|
||||
|
||||
|
@@ -904,6 +904,40 @@ def test_execute_buy(mocker, default_conf, fee, limit_buy_order, limit_buy_order
|
||||
with pytest.raises(PricingError, match="Could not determine buy price."):
|
||||
freqtrade.execute_buy(pair, stake_amount)
|
||||
|
||||
# In case of custom entry price
|
||||
mocker.patch('freqtrade.exchange.Exchange.get_rate', return_value=0.50)
|
||||
limit_buy_order['status'] = 'open'
|
||||
limit_buy_order['id'] = '5566'
|
||||
freqtrade.strategy.custom_entry_price = lambda **kwargs: 0.508
|
||||
assert freqtrade.execute_buy(pair, stake_amount)
|
||||
trade = Trade.query.all()[6]
|
||||
assert trade
|
||||
assert trade.open_rate_requested == 0.508
|
||||
|
||||
# In case of custom entry price set to None
|
||||
limit_buy_order['status'] = 'open'
|
||||
limit_buy_order['id'] = '5567'
|
||||
freqtrade.strategy.custom_entry_price = lambda **kwargs: None
|
||||
|
||||
mocker.patch.multiple(
|
||||
'freqtrade.exchange.Exchange',
|
||||
get_rate=MagicMock(return_value=10),
|
||||
)
|
||||
|
||||
assert freqtrade.execute_buy(pair, stake_amount)
|
||||
trade = Trade.query.all()[7]
|
||||
assert trade
|
||||
assert trade.open_rate_requested == 10
|
||||
|
||||
# In case of custom entry price not float type
|
||||
limit_buy_order['status'] = 'open'
|
||||
limit_buy_order['id'] = '5568'
|
||||
freqtrade.strategy.custom_entry_price = lambda **kwargs: "string price"
|
||||
assert freqtrade.execute_buy(pair, stake_amount)
|
||||
trade = Trade.query.all()[8]
|
||||
assert trade
|
||||
assert trade.open_rate_requested == 10
|
||||
|
||||
|
||||
def test_execute_buy_confirm_error(mocker, default_conf, fee, limit_buy_order) -> None:
|
||||
freqtrade = get_patched_freqtradebot(mocker, default_conf)
|
||||
@@ -2716,6 +2750,70 @@ def test_execute_sell_down(default_conf, ticker, fee, ticker_sell_down, mocker)
|
||||
} == last_msg
|
||||
|
||||
|
||||
def test_execute_sell_custom_exit_price(default_conf, ticker, fee, ticker_sell_up, mocker) -> None:
|
||||
rpc_mock = patch_RPCManager(mocker)
|
||||
patch_exchange(mocker)
|
||||
mocker.patch.multiple(
|
||||
'freqtrade.exchange.Exchange',
|
||||
fetch_ticker=ticker,
|
||||
get_fee=fee,
|
||||
_is_dry_limit_order_filled=MagicMock(return_value=False),
|
||||
)
|
||||
patch_whitelist(mocker, default_conf)
|
||||
freqtrade = FreqtradeBot(default_conf)
|
||||
patch_get_signal(freqtrade)
|
||||
freqtrade.strategy.confirm_trade_exit = MagicMock(return_value=False)
|
||||
|
||||
# Create some test data
|
||||
freqtrade.enter_positions()
|
||||
rpc_mock.reset_mock()
|
||||
|
||||
trade = Trade.query.first()
|
||||
assert trade
|
||||
assert freqtrade.strategy.confirm_trade_exit.call_count == 0
|
||||
|
||||
# Increase the price and sell it
|
||||
mocker.patch.multiple(
|
||||
'freqtrade.exchange.Exchange',
|
||||
fetch_ticker=ticker_sell_up
|
||||
)
|
||||
|
||||
freqtrade.strategy.confirm_trade_exit = MagicMock(return_value=True)
|
||||
|
||||
# Set a custom exit price
|
||||
freqtrade.strategy.custom_exit_price = lambda **kwargs: 1.170e-05
|
||||
|
||||
freqtrade.execute_sell(trade=trade, limit=ticker_sell_up()['bid'],
|
||||
sell_reason=SellCheckTuple(sell_type=SellType.SELL_SIGNAL))
|
||||
|
||||
# Sell price must be different to default bid price
|
||||
|
||||
assert freqtrade.strategy.confirm_trade_exit.call_count == 1
|
||||
|
||||
assert rpc_mock.call_count == 1
|
||||
last_msg = rpc_mock.call_args_list[-1][0][0]
|
||||
assert {
|
||||
'trade_id': 1,
|
||||
'type': RPCMessageType.SELL,
|
||||
'exchange': 'Binance',
|
||||
'pair': 'ETH/BTC',
|
||||
'gain': 'profit',
|
||||
'limit': 1.170e-05,
|
||||
'amount': 91.07468123,
|
||||
'order_type': 'limit',
|
||||
'open_rate': 1.098e-05,
|
||||
'current_rate': 1.173e-05,
|
||||
'profit_amount': 6.041e-05,
|
||||
'profit_ratio': 0.06025919,
|
||||
'stake_currency': 'BTC',
|
||||
'fiat_currency': 'USD',
|
||||
'sell_reason': SellType.SELL_SIGNAL.value,
|
||||
'open_date': ANY,
|
||||
'close_date': ANY,
|
||||
'close_rate': ANY,
|
||||
} == last_msg
|
||||
|
||||
|
||||
def test_execute_sell_down_stoploss_on_exchange_dry_run(default_conf, ticker, fee,
|
||||
ticker_sell_down, mocker) -> None:
|
||||
rpc_mock = patch_RPCManager(mocker)
|
||||
@@ -4503,3 +4601,43 @@ def test_refind_lost_order(mocker, default_conf, fee, caplog):
|
||||
|
||||
freqtrade.refind_lost_order(trades[4])
|
||||
assert log_has(f"Error updating {order['id']}.", caplog)
|
||||
|
||||
|
||||
def test_get_valid_price(mocker, default_conf) -> None:
|
||||
patch_RPCManager(mocker)
|
||||
patch_exchange(mocker)
|
||||
freqtrade = FreqtradeBot(default_conf)
|
||||
freqtrade.config['custom_price_max_distance_ratio'] = 0.02
|
||||
|
||||
custom_price_string = "10"
|
||||
custom_price_badstring = "10abc"
|
||||
custom_price_float = 10.0
|
||||
custom_price_int = 10
|
||||
|
||||
custom_price_over_max_alwd = 11.0
|
||||
custom_price_under_min_alwd = 9.0
|
||||
proposed_price = 10.1
|
||||
|
||||
valid_price_from_string = freqtrade.get_valid_price(custom_price_string, proposed_price)
|
||||
valid_price_from_badstring = freqtrade.get_valid_price(custom_price_badstring, proposed_price)
|
||||
valid_price_from_int = freqtrade.get_valid_price(custom_price_int, proposed_price)
|
||||
valid_price_from_float = freqtrade.get_valid_price(custom_price_float, proposed_price)
|
||||
|
||||
valid_price_at_max_alwd = freqtrade.get_valid_price(custom_price_over_max_alwd, proposed_price)
|
||||
valid_price_at_min_alwd = freqtrade.get_valid_price(custom_price_under_min_alwd, proposed_price)
|
||||
|
||||
assert isinstance(valid_price_from_string, float)
|
||||
assert isinstance(valid_price_from_badstring, float)
|
||||
assert isinstance(valid_price_from_int, float)
|
||||
assert isinstance(valid_price_from_float, float)
|
||||
|
||||
assert valid_price_from_string == custom_price_float
|
||||
assert valid_price_from_badstring == proposed_price
|
||||
assert valid_price_from_int == custom_price_int
|
||||
assert valid_price_from_float == custom_price_float
|
||||
|
||||
assert valid_price_at_max_alwd < custom_price_over_max_alwd
|
||||
assert valid_price_at_max_alwd > proposed_price
|
||||
|
||||
assert valid_price_at_min_alwd > custom_price_under_min_alwd
|
||||
assert valid_price_at_min_alwd < proposed_price
|
||||
|
@@ -1587,25 +1587,30 @@ def test_adjust_min_max_rates(fee):
|
||||
open_rate=1,
|
||||
)
|
||||
|
||||
trade.adjust_min_max_rates(trade.open_rate)
|
||||
trade.adjust_min_max_rates(trade.open_rate, trade.open_rate)
|
||||
assert trade.max_rate == 1
|
||||
assert trade.min_rate == 1
|
||||
|
||||
# check min adjusted, max remained
|
||||
trade.adjust_min_max_rates(0.96)
|
||||
trade.adjust_min_max_rates(0.96, 0.96)
|
||||
assert trade.max_rate == 1
|
||||
assert trade.min_rate == 0.96
|
||||
|
||||
# check max adjusted, min remains
|
||||
trade.adjust_min_max_rates(1.05)
|
||||
trade.adjust_min_max_rates(1.05, 1.05)
|
||||
assert trade.max_rate == 1.05
|
||||
assert trade.min_rate == 0.96
|
||||
|
||||
# current rate "in the middle" - no adjustment
|
||||
trade.adjust_min_max_rates(1.03)
|
||||
trade.adjust_min_max_rates(1.03, 1.03)
|
||||
assert trade.max_rate == 1.05
|
||||
assert trade.min_rate == 0.96
|
||||
|
||||
# current rate "in the middle" - no adjustment
|
||||
trade.adjust_min_max_rates(1.10, 0.91)
|
||||
assert trade.max_rate == 1.10
|
||||
assert trade.min_rate == 0.91
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("init_persistence")
|
||||
@pytest.mark.parametrize('use_db', [True, False])
|
||||
@@ -2099,6 +2104,11 @@ def test_update_order_from_ccxt(caplog):
|
||||
assert o.ft_is_open
|
||||
assert o.order_filled_date is None
|
||||
|
||||
# Order is unfilled, "filled" not set
|
||||
# https://github.com/freqtrade/freqtrade/issues/5404
|
||||
ccxt_order.update({'filled': None, 'remaining': 20.0, 'status': 'canceled'})
|
||||
o.update_from_ccxt_object(ccxt_order)
|
||||
|
||||
# Order has been closed
|
||||
ccxt_order.update({'filled': 20.0, 'remaining': 0.0, 'status': 'closed'})
|
||||
o.update_from_ccxt_object(ccxt_order)
|
||||
|
Reference in New Issue
Block a user