Merge pull request #7976 from adarkforce/max-open-trades
Hyperopt Max open trades
This commit is contained in:
@@ -919,6 +919,7 @@ def test_backtest_results(default_conf, fee, mocker, caplog, data: BTContainer)
|
||||
default_conf["trailing_stop_positive"] = data.trailing_stop_positive
|
||||
default_conf["trailing_stop_positive_offset"] = data.trailing_stop_positive_offset
|
||||
default_conf["use_exit_signal"] = data.use_exit_signal
|
||||
default_conf["max_open_trades"] = 10
|
||||
|
||||
mocker.patch("freqtrade.exchange.Exchange.get_fee", return_value=0.0)
|
||||
mocker.patch("freqtrade.exchange.Exchange.get_min_pair_stake_amount", return_value=0.00001)
|
||||
@@ -951,7 +952,6 @@ def test_backtest_results(default_conf, fee, mocker, caplog, data: BTContainer)
|
||||
processed=data_processed,
|
||||
start_date=min_date,
|
||||
end_date=max_date,
|
||||
max_open_trades=10,
|
||||
)
|
||||
|
||||
results = result['results']
|
||||
|
@@ -96,7 +96,6 @@ def _make_backtest_conf(mocker, datadir, conf=None, pair='UNITTEST/BTC'):
|
||||
'processed': processed,
|
||||
'start_date': min_date,
|
||||
'end_date': max_date,
|
||||
'max_open_trades': 10,
|
||||
}
|
||||
|
||||
|
||||
@@ -685,6 +684,8 @@ def test_backtest__get_sell_trade_entry(default_conf, fee, mocker) -> None:
|
||||
|
||||
def test_backtest_one(default_conf, fee, mocker, testdatadir) -> None:
|
||||
default_conf['use_exit_signal'] = False
|
||||
default_conf['max_open_trades'] = 10
|
||||
|
||||
mocker.patch('freqtrade.exchange.Exchange.get_fee', fee)
|
||||
mocker.patch("freqtrade.exchange.Exchange.get_min_pair_stake_amount", return_value=0.00001)
|
||||
mocker.patch("freqtrade.exchange.Exchange.get_max_pair_stake_amount", return_value=float('inf'))
|
||||
@@ -702,7 +703,6 @@ def test_backtest_one(default_conf, fee, mocker, testdatadir) -> None:
|
||||
processed=deepcopy(processed),
|
||||
start_date=min_date,
|
||||
end_date=max_date,
|
||||
max_open_trades=10,
|
||||
)
|
||||
results = result['results']
|
||||
assert not results.empty
|
||||
@@ -786,6 +786,8 @@ def test_backtest_one_detail(default_conf_usdt, fee, mocker, testdatadir, use_de
|
||||
def custom_entry_price(proposed_rate, **kwargs):
|
||||
return proposed_rate * 0.997
|
||||
|
||||
default_conf_usdt['max_open_trades'] = 10
|
||||
|
||||
backtesting = Backtesting(default_conf_usdt)
|
||||
backtesting._set_strategy(backtesting.strategylist[0])
|
||||
backtesting.strategy.populate_entry_trend = advise_entry
|
||||
@@ -806,7 +808,6 @@ def test_backtest_one_detail(default_conf_usdt, fee, mocker, testdatadir, use_de
|
||||
processed=deepcopy(processed),
|
||||
start_date=min_date,
|
||||
end_date=max_date,
|
||||
max_open_trades=10,
|
||||
)
|
||||
results = result['results']
|
||||
assert not results.empty
|
||||
@@ -860,6 +861,7 @@ def test_backtest_timedout_entry_orders(default_conf, fee, mocker, testdatadir)
|
||||
mocker.patch("freqtrade.exchange.Exchange.get_min_pair_stake_amount", return_value=0.00001)
|
||||
mocker.patch("freqtrade.exchange.Exchange.get_max_pair_stake_amount", return_value=float('inf'))
|
||||
patch_exchange(mocker)
|
||||
default_conf['max_open_trades'] = 1
|
||||
backtesting = Backtesting(default_conf)
|
||||
backtesting._set_strategy(backtesting.strategylist[0])
|
||||
# Testing dataframe contains 11 candles. Expecting 10 timed out orders.
|
||||
@@ -872,7 +874,6 @@ def test_backtest_timedout_entry_orders(default_conf, fee, mocker, testdatadir)
|
||||
processed=deepcopy(data),
|
||||
start_date=min_date,
|
||||
end_date=max_date,
|
||||
max_open_trades=1,
|
||||
)
|
||||
|
||||
assert result['timedout_entry_orders'] == 10
|
||||
@@ -880,6 +881,7 @@ def test_backtest_timedout_entry_orders(default_conf, fee, mocker, testdatadir)
|
||||
|
||||
def test_backtest_1min_timeframe(default_conf, fee, mocker, testdatadir) -> None:
|
||||
default_conf['use_exit_signal'] = False
|
||||
default_conf['max_open_trades'] = 1
|
||||
mocker.patch('freqtrade.exchange.Exchange.get_fee', fee)
|
||||
mocker.patch("freqtrade.exchange.Exchange.get_min_pair_stake_amount", return_value=0.00001)
|
||||
mocker.patch("freqtrade.exchange.Exchange.get_max_pair_stake_amount", return_value=float('inf'))
|
||||
@@ -897,7 +899,6 @@ def test_backtest_1min_timeframe(default_conf, fee, mocker, testdatadir) -> None
|
||||
processed=processed,
|
||||
start_date=min_date,
|
||||
end_date=max_date,
|
||||
max_open_trades=1,
|
||||
)
|
||||
assert not results['results'].empty
|
||||
assert len(results['results']) == 1
|
||||
@@ -905,6 +906,8 @@ def test_backtest_1min_timeframe(default_conf, fee, mocker, testdatadir) -> None
|
||||
|
||||
def test_backtest_trim_no_data_left(default_conf, fee, mocker, testdatadir) -> None:
|
||||
default_conf['use_exit_signal'] = False
|
||||
default_conf['max_open_trades'] = 10
|
||||
|
||||
mocker.patch('freqtrade.exchange.Exchange.get_fee', fee)
|
||||
mocker.patch("freqtrade.exchange.Exchange.get_min_pair_stake_amount", return_value=0.00001)
|
||||
mocker.patch("freqtrade.exchange.Exchange.get_max_pair_stake_amount", return_value=float('inf'))
|
||||
@@ -928,7 +931,6 @@ def test_backtest_trim_no_data_left(default_conf, fee, mocker, testdatadir) -> N
|
||||
processed=deepcopy(processed),
|
||||
start_date=min_date,
|
||||
end_date=max_date,
|
||||
max_open_trades=10,
|
||||
)
|
||||
|
||||
|
||||
@@ -949,6 +951,7 @@ def test_processed(default_conf, mocker, testdatadir) -> None:
|
||||
|
||||
def test_backtest_dataprovider_analyzed_df(default_conf, fee, mocker, testdatadir) -> None:
|
||||
default_conf['use_exit_signal'] = False
|
||||
default_conf['max_open_trades'] = 10
|
||||
mocker.patch('freqtrade.exchange.Exchange.get_fee', fee)
|
||||
mocker.patch("freqtrade.exchange.Exchange.get_min_pair_stake_amount", return_value=0.00001)
|
||||
mocker.patch("freqtrade.exchange.Exchange.get_max_pair_stake_amount", return_value=100000)
|
||||
@@ -982,7 +985,6 @@ def test_backtest_dataprovider_analyzed_df(default_conf, fee, mocker, testdatadi
|
||||
processed=deepcopy(processed),
|
||||
start_date=min_date,
|
||||
end_date=max_date,
|
||||
max_open_trades=10,
|
||||
)
|
||||
assert count == 5
|
||||
|
||||
@@ -999,6 +1001,7 @@ def test_backtest_pricecontours_protections(default_conf, fee, mocker, testdatad
|
||||
|
||||
default_conf['enable_protections'] = True
|
||||
default_conf['timeframe'] = '1m'
|
||||
default_conf['max_open_trades'] = 1
|
||||
mocker.patch('freqtrade.exchange.Exchange.get_fee', fee)
|
||||
mocker.patch("freqtrade.exchange.Exchange.get_min_pair_stake_amount", return_value=0.00001)
|
||||
mocker.patch("freqtrade.exchange.Exchange.get_max_pair_stake_amount", return_value=float('inf'))
|
||||
@@ -1025,7 +1028,6 @@ def test_backtest_pricecontours_protections(default_conf, fee, mocker, testdatad
|
||||
processed=processed,
|
||||
start_date=min_date,
|
||||
end_date=max_date,
|
||||
max_open_trades=1,
|
||||
)
|
||||
assert len(results['results']) == numres
|
||||
|
||||
@@ -1063,11 +1065,12 @@ def test_backtest_pricecontours(default_conf, fee, mocker, testdatadir,
|
||||
processed = backtesting.strategy.advise_all_indicators(data)
|
||||
min_date, max_date = get_timerange(processed)
|
||||
assert isinstance(processed, dict)
|
||||
backtesting.strategy.max_open_trades = 1
|
||||
backtesting.config.update({'max_open_trades': 1})
|
||||
results = backtesting.backtest(
|
||||
processed=processed,
|
||||
start_date=min_date,
|
||||
end_date=max_date,
|
||||
max_open_trades=1,
|
||||
)
|
||||
assert len(results['results']) == expected
|
||||
|
||||
@@ -1078,7 +1081,7 @@ def test_backtest_clash_buy_sell(mocker, default_conf, testdatadir):
|
||||
buy_value = 1
|
||||
sell_value = 1
|
||||
return _trend(dataframe, buy_value, sell_value)
|
||||
|
||||
default_conf['max_open_trades'] = 10
|
||||
backtest_conf = _make_backtest_conf(mocker, conf=default_conf, datadir=testdatadir)
|
||||
backtesting = Backtesting(default_conf)
|
||||
backtesting._set_strategy(backtesting.strategylist[0])
|
||||
@@ -1095,6 +1098,7 @@ def test_backtest_only_sell(mocker, default_conf, testdatadir):
|
||||
sell_value = 1
|
||||
return _trend(dataframe, buy_value, sell_value)
|
||||
|
||||
default_conf['max_open_trades'] = 10
|
||||
backtest_conf = _make_backtest_conf(mocker, conf=default_conf, datadir=testdatadir)
|
||||
backtesting = Backtesting(default_conf)
|
||||
backtesting._set_strategy(backtesting.strategylist[0])
|
||||
@@ -1108,6 +1112,7 @@ def test_backtest_alternate_buy_sell(default_conf, fee, mocker, testdatadir):
|
||||
mocker.patch("freqtrade.exchange.Exchange.get_min_pair_stake_amount", return_value=0.00001)
|
||||
mocker.patch("freqtrade.exchange.Exchange.get_max_pair_stake_amount", return_value=float('inf'))
|
||||
mocker.patch('freqtrade.exchange.Exchange.get_fee', fee)
|
||||
default_conf['max_open_trades'] = 10
|
||||
backtest_conf = _make_backtest_conf(mocker, conf=default_conf,
|
||||
pair='UNITTEST/BTC', datadir=testdatadir)
|
||||
default_conf['timeframe'] = '1m'
|
||||
@@ -1166,6 +1171,7 @@ def test_backtest_multi_pair(default_conf, fee, mocker, tres, pair, testdatadir)
|
||||
if tres > 0:
|
||||
data[pair] = data[pair][tres:].reset_index()
|
||||
default_conf['timeframe'] = '5m'
|
||||
default_conf['max_open_trades'] = 3
|
||||
|
||||
backtesting = Backtesting(default_conf)
|
||||
backtesting._set_strategy(backtesting.strategylist[0])
|
||||
@@ -1174,11 +1180,11 @@ def test_backtest_multi_pair(default_conf, fee, mocker, tres, pair, testdatadir)
|
||||
|
||||
processed = backtesting.strategy.advise_all_indicators(data)
|
||||
min_date, max_date = get_timerange(processed)
|
||||
|
||||
backtest_conf = {
|
||||
'processed': deepcopy(processed),
|
||||
'start_date': min_date,
|
||||
'end_date': max_date,
|
||||
'max_open_trades': 3,
|
||||
}
|
||||
|
||||
results = backtesting.backtest(**backtest_conf)
|
||||
@@ -1196,11 +1202,12 @@ def test_backtest_multi_pair(default_conf, fee, mocker, tres, pair, testdatadir)
|
||||
backtesting.dataprovider.get_analyzed_dataframe('NXT/BTC', '5m')[0]
|
||||
) == len(data['NXT/BTC']) - 1 - backtesting.strategy.startup_candle_count
|
||||
|
||||
backtesting.strategy.max_open_trades = 1
|
||||
backtesting.config.update({'max_open_trades': 1})
|
||||
backtest_conf = {
|
||||
'processed': deepcopy(processed),
|
||||
'start_date': min_date,
|
||||
'end_date': max_date,
|
||||
'max_open_trades': 1,
|
||||
}
|
||||
results = backtesting.backtest(**backtest_conf)
|
||||
assert len(evaluate_result_multi(results['results'], '5m', 1)) == 0
|
||||
|
@@ -17,6 +17,7 @@ from tests.conftest import patch_exchange
|
||||
|
||||
def test_backtest_position_adjustment(default_conf, fee, mocker, testdatadir) -> None:
|
||||
default_conf['use_exit_signal'] = False
|
||||
default_conf['max_open_trades'] = 10
|
||||
mocker.patch('freqtrade.exchange.Exchange.get_fee', fee)
|
||||
mocker.patch('freqtrade.optimize.backtesting.amount_to_contract_precision',
|
||||
lambda x, *args, **kwargs: round(x, 8))
|
||||
@@ -41,7 +42,6 @@ def test_backtest_position_adjustment(default_conf, fee, mocker, testdatadir) ->
|
||||
processed=deepcopy(processed),
|
||||
start_date=min_date,
|
||||
end_date=max_date,
|
||||
max_open_trades=10,
|
||||
)
|
||||
results = result['results']
|
||||
assert not results.empty
|
||||
|
@@ -1,5 +1,6 @@
|
||||
# pragma pylint: disable=missing-docstring,W0212,C0103
|
||||
from datetime import datetime, timedelta
|
||||
from functools import wraps
|
||||
from pathlib import Path
|
||||
from unittest.mock import ANY, MagicMock, PropertyMock
|
||||
|
||||
@@ -7,6 +8,7 @@ import pandas as pd
|
||||
import pytest
|
||||
from arrow import Arrow
|
||||
from filelock import Timeout
|
||||
from skopt.space import Integer
|
||||
|
||||
from freqtrade.commands.optimize_commands import setup_optimize_configuration, start_hyperopt
|
||||
from freqtrade.data.history import load_data
|
||||
@@ -292,6 +294,8 @@ def test_params_no_optimize_details(hyperopt) -> None:
|
||||
assert res['roi']['0'] == 0.04
|
||||
assert "stoploss" in res
|
||||
assert res['stoploss']['stoploss'] == -0.1
|
||||
assert "max_open_trades" in res
|
||||
assert res['max_open_trades']['max_open_trades'] == 1
|
||||
|
||||
|
||||
def test_start_calls_optimizer(mocker, hyperopt_conf, capsys) -> None:
|
||||
@@ -334,8 +338,7 @@ def test_start_calls_optimizer(mocker, hyperopt_conf, capsys) -> None:
|
||||
assert dumper2.call_count == 1
|
||||
assert hasattr(hyperopt.backtesting.strategy, "advise_exit")
|
||||
assert hasattr(hyperopt.backtesting.strategy, "advise_entry")
|
||||
assert hasattr(hyperopt, "max_open_trades")
|
||||
assert hyperopt.max_open_trades == hyperopt_conf['max_open_trades']
|
||||
assert hyperopt.backtesting.strategy.max_open_trades == hyperopt_conf['max_open_trades']
|
||||
assert hasattr(hyperopt.backtesting, "_position_stacking")
|
||||
|
||||
|
||||
@@ -474,6 +477,7 @@ def test_generate_optimizer(mocker, hyperopt_conf) -> None:
|
||||
'trailing_stop_positive': 0.02,
|
||||
'trailing_stop_positive_offset_p1': 0.05,
|
||||
'trailing_only_offset_is_reached': False,
|
||||
'max_open_trades': 3,
|
||||
}
|
||||
response_expected = {
|
||||
'loss': 1.9147239021396234,
|
||||
@@ -499,7 +503,9 @@ def test_generate_optimizer(mocker, hyperopt_conf) -> None:
|
||||
'trailing': {'trailing_only_offset_is_reached': False,
|
||||
'trailing_stop': True,
|
||||
'trailing_stop_positive': 0.02,
|
||||
'trailing_stop_positive_offset': 0.07}},
|
||||
'trailing_stop_positive_offset': 0.07},
|
||||
'max_open_trades': {'max_open_trades': 3}
|
||||
},
|
||||
'params_dict': optimizer_param,
|
||||
'params_not_optimized': {'buy': {}, 'protection': {}, 'sell': {}},
|
||||
'results_metrics': ANY,
|
||||
@@ -548,7 +554,8 @@ def test_print_json_spaces_all(mocker, hyperopt_conf, capsys) -> None:
|
||||
'buy': {'mfi-value': None},
|
||||
'sell': {'sell-mfi-value': None},
|
||||
'roi': {}, 'stoploss': {'stoploss': None},
|
||||
'trailing': {'trailing_stop': None}
|
||||
'trailing': {'trailing_stop': None},
|
||||
'max_open_trades': {'max_open_trades': None}
|
||||
},
|
||||
'results_metrics': generate_result_metrics(),
|
||||
}])
|
||||
@@ -571,7 +578,7 @@ def test_print_json_spaces_all(mocker, hyperopt_conf, capsys) -> None:
|
||||
out, err = capsys.readouterr()
|
||||
result_str = (
|
||||
'{"params":{"mfi-value":null,"sell-mfi-value":null},"minimal_roi"'
|
||||
':{},"stoploss":null,"trailing_stop":null}'
|
||||
':{},"stoploss":null,"trailing_stop":null,"max_open_trades":null}'
|
||||
)
|
||||
assert result_str in out # noqa: E501
|
||||
# Should be called for historical candle data
|
||||
@@ -702,8 +709,7 @@ def test_simplified_interface_roi_stoploss(mocker, hyperopt_conf, capsys) -> Non
|
||||
|
||||
assert hasattr(hyperopt.backtesting.strategy, "advise_exit")
|
||||
assert hasattr(hyperopt.backtesting.strategy, "advise_entry")
|
||||
assert hasattr(hyperopt, "max_open_trades")
|
||||
assert hyperopt.max_open_trades == hyperopt_conf['max_open_trades']
|
||||
assert hyperopt.backtesting.strategy.max_open_trades == hyperopt_conf['max_open_trades']
|
||||
assert hasattr(hyperopt.backtesting, "_position_stacking")
|
||||
|
||||
|
||||
@@ -776,8 +782,7 @@ def test_simplified_interface_buy(mocker, hyperopt_conf, capsys) -> None:
|
||||
assert dumper2.call_count == 1
|
||||
assert hasattr(hyperopt.backtesting.strategy, "advise_exit")
|
||||
assert hasattr(hyperopt.backtesting.strategy, "advise_entry")
|
||||
assert hasattr(hyperopt, "max_open_trades")
|
||||
assert hyperopt.max_open_trades == hyperopt_conf['max_open_trades']
|
||||
assert hyperopt.backtesting.strategy.max_open_trades == hyperopt_conf['max_open_trades']
|
||||
assert hasattr(hyperopt.backtesting, "_position_stacking")
|
||||
|
||||
|
||||
@@ -819,8 +824,7 @@ def test_simplified_interface_sell(mocker, hyperopt_conf, capsys) -> None:
|
||||
assert dumper2.call_count == 1
|
||||
assert hasattr(hyperopt.backtesting.strategy, "advise_exit")
|
||||
assert hasattr(hyperopt.backtesting.strategy, "advise_entry")
|
||||
assert hasattr(hyperopt, "max_open_trades")
|
||||
assert hyperopt.max_open_trades == hyperopt_conf['max_open_trades']
|
||||
assert hyperopt.backtesting.strategy.max_open_trades == hyperopt_conf['max_open_trades']
|
||||
assert hasattr(hyperopt.backtesting, "_position_stacking")
|
||||
|
||||
|
||||
@@ -874,6 +878,7 @@ def test_in_strategy_auto_hyperopt(mocker, hyperopt_conf, tmpdir, fee) -> None:
|
||||
assert hyperopt.backtesting.strategy.buy_rsi.value == 35
|
||||
assert hyperopt.backtesting.strategy.sell_rsi.value == 74
|
||||
assert hyperopt.backtesting.strategy.protection_cooldown_lookback.value == 30
|
||||
assert hyperopt.backtesting.strategy.max_open_trades == 1
|
||||
buy_rsi_range = hyperopt.backtesting.strategy.buy_rsi.range
|
||||
assert isinstance(buy_rsi_range, range)
|
||||
# Range from 0 - 50 (inclusive)
|
||||
@@ -884,6 +889,7 @@ def test_in_strategy_auto_hyperopt(mocker, hyperopt_conf, tmpdir, fee) -> None:
|
||||
assert hyperopt.backtesting.strategy.protection_cooldown_lookback.value != 30
|
||||
assert hyperopt.backtesting.strategy.buy_rsi.value != 35
|
||||
assert hyperopt.backtesting.strategy.sell_rsi.value != 74
|
||||
assert hyperopt.backtesting.strategy.max_open_trades != 1
|
||||
|
||||
hyperopt.custom_hyperopt.generate_estimator = lambda *args, **kwargs: 'ET1'
|
||||
with pytest.raises(OperationalException, match="Estimator ET1 not supported."):
|
||||
@@ -984,3 +990,124 @@ def test_SKDecimal():
|
||||
assert space.transform([2.0]) == [200]
|
||||
assert space.transform([1.0]) == [100]
|
||||
assert space.transform([1.5, 1.6]) == [150, 160]
|
||||
|
||||
|
||||
def test_stake_amount_unlimited_max_open_trades(mocker, hyperopt_conf, tmpdir, fee) -> None:
|
||||
# This test is to ensure that unlimited max_open_trades are ignored for the backtesting
|
||||
# if we have an unlimited stake amount
|
||||
patch_exchange(mocker)
|
||||
mocker.patch('freqtrade.exchange.Exchange.get_fee', fee)
|
||||
(Path(tmpdir) / 'hyperopt_results').mkdir(parents=True)
|
||||
hyperopt_conf.update({
|
||||
'strategy': 'HyperoptableStrategy',
|
||||
'user_data_dir': Path(tmpdir),
|
||||
'hyperopt_random_state': 42,
|
||||
'spaces': ['trades'],
|
||||
'stake_amount': 'unlimited'
|
||||
})
|
||||
hyperopt = Hyperopt(hyperopt_conf)
|
||||
mocker.patch('freqtrade.optimize.hyperopt.Hyperopt._get_params_dict',
|
||||
return_value={
|
||||
'max_open_trades': -1
|
||||
})
|
||||
|
||||
assert isinstance(hyperopt.custom_hyperopt, HyperOptAuto)
|
||||
|
||||
assert hyperopt.backtesting.strategy.max_open_trades == 1
|
||||
|
||||
hyperopt.start()
|
||||
|
||||
assert hyperopt.backtesting.strategy.max_open_trades == 1
|
||||
|
||||
|
||||
def test_max_open_trades_dump(mocker, hyperopt_conf, tmpdir, fee, capsys) -> None:
|
||||
# This test is to ensure that after hyperopting, max_open_trades is never
|
||||
# saved as inf in the output json params
|
||||
patch_exchange(mocker)
|
||||
mocker.patch('freqtrade.exchange.Exchange.get_fee', fee)
|
||||
(Path(tmpdir) / 'hyperopt_results').mkdir(parents=True)
|
||||
hyperopt_conf.update({
|
||||
'strategy': 'HyperoptableStrategy',
|
||||
'user_data_dir': Path(tmpdir),
|
||||
'hyperopt_random_state': 42,
|
||||
'spaces': ['trades'],
|
||||
})
|
||||
hyperopt = Hyperopt(hyperopt_conf)
|
||||
mocker.patch('freqtrade.optimize.hyperopt.Hyperopt._get_params_dict',
|
||||
return_value={
|
||||
'max_open_trades': -1
|
||||
})
|
||||
|
||||
assert isinstance(hyperopt.custom_hyperopt, HyperOptAuto)
|
||||
|
||||
hyperopt.start()
|
||||
|
||||
out, err = capsys.readouterr()
|
||||
|
||||
assert 'max_open_trades = -1' in out
|
||||
assert 'max_open_trades = inf' not in out
|
||||
|
||||
##############
|
||||
|
||||
hyperopt_conf.update({'print_json': True})
|
||||
|
||||
hyperopt = Hyperopt(hyperopt_conf)
|
||||
mocker.patch('freqtrade.optimize.hyperopt.Hyperopt._get_params_dict',
|
||||
return_value={
|
||||
'max_open_trades': -1
|
||||
})
|
||||
|
||||
assert isinstance(hyperopt.custom_hyperopt, HyperOptAuto)
|
||||
|
||||
hyperopt.start()
|
||||
|
||||
out, err = capsys.readouterr()
|
||||
|
||||
assert '"max_open_trades":-1' in out
|
||||
|
||||
|
||||
def test_max_open_trades_consistency(mocker, hyperopt_conf, tmpdir, fee) -> None:
|
||||
# This test is to ensure that max_open_trades is the same across all functions needing it
|
||||
# after it has been changed from the hyperopt
|
||||
patch_exchange(mocker)
|
||||
mocker.patch('freqtrade.exchange.Exchange.get_fee', return_value=0)
|
||||
|
||||
(Path(tmpdir) / 'hyperopt_results').mkdir(parents=True)
|
||||
hyperopt_conf.update({
|
||||
'strategy': 'HyperoptableStrategy',
|
||||
'user_data_dir': Path(tmpdir),
|
||||
'hyperopt_random_state': 42,
|
||||
'spaces': ['trades'],
|
||||
'stake_amount': 'unlimited',
|
||||
'dry_run_wallet': 8,
|
||||
'available_capital': 8,
|
||||
'dry_run': True,
|
||||
'epochs': 1
|
||||
})
|
||||
hyperopt = Hyperopt(hyperopt_conf)
|
||||
|
||||
assert isinstance(hyperopt.custom_hyperopt, HyperOptAuto)
|
||||
|
||||
hyperopt.custom_hyperopt.max_open_trades_space = lambda: [
|
||||
Integer(1, 10, name='max_open_trades')]
|
||||
|
||||
first_time_evaluated = False
|
||||
|
||||
def stake_amount_interceptor(func):
|
||||
@wraps(func)
|
||||
def wrapper(*args, **kwargs):
|
||||
nonlocal first_time_evaluated
|
||||
stake_amount = func(*args, **kwargs)
|
||||
if first_time_evaluated is False:
|
||||
assert stake_amount == 1
|
||||
first_time_evaluated = True
|
||||
return stake_amount
|
||||
return wrapper
|
||||
|
||||
hyperopt.backtesting.wallets._calculate_unlimited_stake_amount = stake_amount_interceptor(
|
||||
hyperopt.backtesting.wallets._calculate_unlimited_stake_amount)
|
||||
|
||||
hyperopt.start()
|
||||
|
||||
assert hyperopt.backtesting.strategy.max_open_trades == 8
|
||||
assert hyperopt.config['max_open_trades'] == 8
|
||||
|
@@ -66,52 +66,58 @@ def test_load_previous_results2(mocker, testdatadir, caplog) -> None:
|
||||
@pytest.mark.parametrize("spaces, expected_results", [
|
||||
(['buy'],
|
||||
{'buy': True, 'sell': False, 'roi': False, 'stoploss': False, 'trailing': False,
|
||||
'protection': False}),
|
||||
'protection': False, 'trades': False}),
|
||||
(['sell'],
|
||||
{'buy': False, 'sell': True, 'roi': False, 'stoploss': False, 'trailing': False,
|
||||
'protection': False}),
|
||||
'protection': False, 'trades': False}),
|
||||
(['roi'],
|
||||
{'buy': False, 'sell': False, 'roi': True, 'stoploss': False, 'trailing': False,
|
||||
'protection': False}),
|
||||
'protection': False, 'trades': False}),
|
||||
(['stoploss'],
|
||||
{'buy': False, 'sell': False, 'roi': False, 'stoploss': True, 'trailing': False,
|
||||
'protection': False}),
|
||||
'protection': False, 'trades': False}),
|
||||
(['trailing'],
|
||||
{'buy': False, 'sell': False, 'roi': False, 'stoploss': False, 'trailing': True,
|
||||
'protection': False}),
|
||||
'protection': False, 'trades': False}),
|
||||
(['buy', 'sell', 'roi', 'stoploss'],
|
||||
{'buy': True, 'sell': True, 'roi': True, 'stoploss': True, 'trailing': False,
|
||||
'protection': False}),
|
||||
'protection': False, 'trades': False}),
|
||||
(['buy', 'sell', 'roi', 'stoploss', 'trailing'],
|
||||
{'buy': True, 'sell': True, 'roi': True, 'stoploss': True, 'trailing': True,
|
||||
'protection': False}),
|
||||
'protection': False, 'trades': False}),
|
||||
(['buy', 'roi'],
|
||||
{'buy': True, 'sell': False, 'roi': True, 'stoploss': False, 'trailing': False,
|
||||
'protection': False}),
|
||||
'protection': False, 'trades': False}),
|
||||
(['all'],
|
||||
{'buy': True, 'sell': True, 'roi': True, 'stoploss': True, 'trailing': True,
|
||||
'protection': True}),
|
||||
'protection': True, 'trades': True}),
|
||||
(['default'],
|
||||
{'buy': True, 'sell': True, 'roi': True, 'stoploss': True, 'trailing': False,
|
||||
'protection': False}),
|
||||
'protection': False, 'trades': False}),
|
||||
(['default', 'trailing'],
|
||||
{'buy': True, 'sell': True, 'roi': True, 'stoploss': True, 'trailing': True,
|
||||
'protection': False}),
|
||||
'protection': False, 'trades': False}),
|
||||
(['all', 'buy'],
|
||||
{'buy': True, 'sell': True, 'roi': True, 'stoploss': True, 'trailing': True,
|
||||
'protection': True}),
|
||||
'protection': True, 'trades': True}),
|
||||
(['default', 'buy'],
|
||||
{'buy': True, 'sell': True, 'roi': True, 'stoploss': True, 'trailing': False,
|
||||
'protection': False}),
|
||||
'protection': False, 'trades': False}),
|
||||
(['all'],
|
||||
{'buy': True, 'sell': True, 'roi': True, 'stoploss': True, 'trailing': True,
|
||||
'protection': True}),
|
||||
'protection': True, 'trades': True}),
|
||||
(['protection'],
|
||||
{'buy': False, 'sell': False, 'roi': False, 'stoploss': False, 'trailing': False,
|
||||
'protection': True}),
|
||||
'protection': True, 'trades': False}),
|
||||
(['trades'],
|
||||
{'buy': False, 'sell': False, 'roi': False, 'stoploss': False, 'trailing': False,
|
||||
'protection': False, 'trades': True}),
|
||||
(['default', 'trades'],
|
||||
{'buy': True, 'sell': True, 'roi': True, 'stoploss': True, 'trailing': False,
|
||||
'protection': False, 'trades': True}),
|
||||
])
|
||||
def test_has_space(hyperopt_conf, spaces, expected_results):
|
||||
for s in ['buy', 'sell', 'roi', 'stoploss', 'trailing', 'protection']:
|
||||
for s in ['buy', 'sell', 'roi', 'stoploss', 'trailing', 'protection', 'trades']:
|
||||
hyperopt_conf.update({'spaces': spaces})
|
||||
assert HyperoptTools.has_space(hyperopt_conf, s) == expected_results[s]
|
||||
|
||||
@@ -193,6 +199,9 @@ def test_export_params(tmpdir):
|
||||
"346": 0.08499,
|
||||
"507": 0.049,
|
||||
"1595": 0
|
||||
},
|
||||
"max_open_trades": {
|
||||
"max_open_trades": 5
|
||||
}
|
||||
},
|
||||
"params_not_optimized": {
|
||||
@@ -219,6 +228,7 @@ def test_export_params(tmpdir):
|
||||
assert "roi" in content["params"]
|
||||
assert "stoploss" in content["params"]
|
||||
assert "trailing" in content["params"]
|
||||
assert "max_open_trades" in content["params"]
|
||||
|
||||
|
||||
def test_try_export_params(default_conf, tmpdir, caplog, mocker):
|
||||
@@ -297,6 +307,9 @@ def test_params_print(capsys):
|
||||
"trailing_stop_positive_offset": 0.1,
|
||||
"trailing_only_offset_is_reached": True
|
||||
},
|
||||
"max_open_trades": {
|
||||
"max_open_trades": 5
|
||||
}
|
||||
|
||||
}
|
||||
HyperoptTools._params_pretty_print(params, 'buy', 'No header', non_optimized)
|
||||
@@ -327,6 +340,13 @@ def test_params_print(capsys):
|
||||
assert re.search('trailing_stop_positive_offset = 0.1 # value loaded.*\n', captured.out)
|
||||
assert re.search('trailing_only_offset_is_reached = True # value loaded.*\n', captured.out)
|
||||
|
||||
HyperoptTools._params_pretty_print(
|
||||
params, 'max_open_trades', "Max Open Trades:", non_optimized)
|
||||
captured = capsys.readouterr()
|
||||
|
||||
assert re.search("# Max Open Trades:", captured.out)
|
||||
assert re.search('max_open_trades = 5 # value loaded.*\n', captured.out)
|
||||
|
||||
|
||||
def test_hyperopt_serializer():
|
||||
|
||||
|
@@ -30,6 +30,9 @@ class StrategyTestV3(IStrategy):
|
||||
"0": 0.04
|
||||
}
|
||||
|
||||
# Optimal max_open_trades for the strategy
|
||||
max_open_trades = -1
|
||||
|
||||
# Optimal stoploss designed for the strategy
|
||||
stoploss = -0.10
|
||||
|
||||
|
@@ -6,6 +6,7 @@ from pathlib import Path
|
||||
import pytest
|
||||
from pandas import DataFrame
|
||||
|
||||
from freqtrade.configuration import Configuration
|
||||
from freqtrade.exceptions import OperationalException
|
||||
from freqtrade.resolvers import StrategyResolver
|
||||
from freqtrade.strategy.interface import IStrategy
|
||||
@@ -175,6 +176,18 @@ def test_strategy_override_stoploss(caplog, default_conf):
|
||||
assert log_has("Override strategy 'stoploss' with value in config file: -0.5.", caplog)
|
||||
|
||||
|
||||
def test_strategy_override_max_open_trades(caplog, default_conf):
|
||||
caplog.set_level(logging.INFO)
|
||||
default_conf.update({
|
||||
'strategy': CURRENT_TEST_STRATEGY,
|
||||
'max_open_trades': 7
|
||||
})
|
||||
strategy = StrategyResolver.load_strategy(default_conf)
|
||||
|
||||
assert strategy.max_open_trades == 7
|
||||
assert log_has("Override strategy 'max_open_trades' with value in config file: 7.", caplog)
|
||||
|
||||
|
||||
def test_strategy_override_trailing_stop(caplog, default_conf):
|
||||
caplog.set_level(logging.INFO)
|
||||
default_conf.update({
|
||||
@@ -349,6 +362,38 @@ def test_strategy_override_use_exit_profit_only(caplog, default_conf):
|
||||
assert log_has("Override strategy 'exit_profit_only' with value in config file: True.", caplog)
|
||||
|
||||
|
||||
def test_strategy_max_open_trades_infinity_from_strategy(caplog, default_conf):
|
||||
caplog.set_level(logging.INFO)
|
||||
default_conf.update({
|
||||
'strategy': CURRENT_TEST_STRATEGY,
|
||||
})
|
||||
del default_conf['max_open_trades']
|
||||
|
||||
strategy = StrategyResolver.load_strategy(default_conf)
|
||||
|
||||
# this test assumes -1 set to 'max_open_trades' in CURRENT_TEST_STRATEGY
|
||||
assert strategy.max_open_trades == float('inf')
|
||||
assert default_conf['max_open_trades'] == float('inf')
|
||||
|
||||
|
||||
def test_strategy_max_open_trades_infinity_from_config(caplog, default_conf, mocker):
|
||||
caplog.set_level(logging.INFO)
|
||||
default_conf.update({
|
||||
'strategy': CURRENT_TEST_STRATEGY,
|
||||
'max_open_trades': -1,
|
||||
'exchange': 'binance'
|
||||
})
|
||||
|
||||
configuration = Configuration(args=default_conf)
|
||||
parsed_config = configuration.get_config()
|
||||
|
||||
assert parsed_config['max_open_trades'] == float('inf')
|
||||
|
||||
strategy = StrategyResolver.load_strategy(parsed_config)
|
||||
|
||||
assert strategy.max_open_trades == float('inf')
|
||||
|
||||
|
||||
@ pytest.mark.filterwarnings("ignore:deprecated")
|
||||
def test_missing_implements(default_conf, caplog):
|
||||
|
||||
@@ -438,3 +483,19 @@ def test_strategy_interface_versioning(dataframe_1m, default_conf):
|
||||
assert isinstance(exitdf, DataFrame)
|
||||
assert 'sell' not in exitdf
|
||||
assert 'exit_long' in exitdf
|
||||
|
||||
|
||||
def test_strategy_ft_load_params_from_file(mocker, default_conf):
|
||||
default_conf.update({'strategy': 'StrategyTestV2'})
|
||||
del default_conf['max_open_trades']
|
||||
mocker.patch('freqtrade.strategy.hyper.HyperStrategyMixin.load_params_from_file',
|
||||
return_value={
|
||||
'params': {
|
||||
'max_open_trades': {
|
||||
'max_open_trades': -1
|
||||
}
|
||||
}
|
||||
})
|
||||
strategy = StrategyResolver.load_strategy(default_conf)
|
||||
assert strategy.max_open_trades == float('inf')
|
||||
assert strategy.config['max_open_trades'] == float('inf')
|
||||
|
Reference in New Issue
Block a user