Merge branch 'develop' into feat/short
This commit is contained in:
@@ -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", [
|
||||
|
Reference in New Issue
Block a user