From f43ba44b159c6ed846492d5f5842a4946ebadbb7 Mon Sep 17 00:00:00 2001 From: Samuel Husso Date: Tue, 24 Oct 2017 07:58:42 +0300 Subject: [PATCH] refactor backtesting to its own method as we use it also in hyperopt --- freqtrade/tests/test_backtesting.py | 19 +++++++++++-------- freqtrade/tests/test_hyperopt.py | 25 ++++++++++++++----------- 2 files changed, 25 insertions(+), 19 deletions(-) diff --git a/freqtrade/tests/test_backtesting.py b/freqtrade/tests/test_backtesting.py index d008c4ae6..3af459ee4 100644 --- a/freqtrade/tests/test_backtesting.py +++ b/freqtrade/tests/test_backtesting.py @@ -21,6 +21,10 @@ def print_results(results): results.duration.mean() * 5 )) +def print_pair_results(pair, results): + print('For currency {}:'.format(pair)) + print_results(results[results.currency == pair]) + @pytest.fixture def pairs(): return ['btc-neo', 'btc-eth', 'btc-omg', 'btc-edg', 'btc-pay', @@ -38,9 +42,7 @@ def conf(): "stoploss": -0.40 } - -@pytest.mark.skipif(not os.environ.get('BACKTEST', False), reason="BACKTEST not set") -def test_backtest(conf, pairs, mocker): +def backtest(conf, pairs, mocker): trades = [] mocker.patch.dict('freqtrade.main._CONF', conf) for pair in pairs: @@ -64,14 +66,15 @@ def test_backtest(conf, pairs, mocker): trades.append((pair, current_profit, index2 - index)) break - labels = ['currency', 'profit', 'duration'] results = DataFrame.from_records(trades, columns=labels) + return results + +@pytest.mark.skipif(not os.environ.get('BACKTEST', False), reason="BACKTEST not set") +def test_backtest(conf, pairs, mocker, report=True): + results = backtest(conf, pairs, mocker) print('====================== BACKTESTING REPORT ================================') - - for pair in pairs: - print('For currency {}:'.format(pair)) - print_results(results[results.currency == pair]) + [print_pair_results(pair, results) for pair in pairs] print('TOTAL OVER ALL TRADES:') print_results(results) diff --git a/freqtrade/tests/test_hyperopt.py b/freqtrade/tests/test_hyperopt.py index 167e0d9ab..c09901f88 100644 --- a/freqtrade/tests/test_hyperopt.py +++ b/freqtrade/tests/test_hyperopt.py @@ -14,15 +14,9 @@ from freqtrade.analyze import analyze_ticker from freqtrade.main import should_sell from freqtrade.persistence import Trade -logging.disable(logging.DEBUG) # disable debug logs that slow backtesting a lot +from freqtrade.tests.test_backtesting import backtest, print_results -def print_results(results): - print('Made {} buys. Average profit {:.2f}%. Total profit was {:.3f}. Average duration {:.1f} mins.'.format( - len(results.index), - results.profit.mean() * 100.0, - results.profit.sum(), - results.duration.mean() * 5 - )) +logging.disable(logging.DEBUG) # disable debug logs that slow backtesting a lot @pytest.fixture def pairs(): @@ -42,7 +36,7 @@ def conf(): } -def backtest(conf, pairs, mocker, buy_strategy): +def backtest2(conf, pairs, mocker, buy_strategy): trades = [] mocker.patch.dict('freqtrade.main._CONF', conf) for pair in pairs: @@ -121,8 +115,18 @@ def buy_strategy_generator(params): @pytest.mark.skipif(not os.environ.get('BACKTEST', False), reason="BACKTEST not set") def test_hyperopt(conf, pairs, mocker): + # def optimizer(params): + # return backtest2(conf, pairs, mocker, buy_strategy_generator(params)) + def optimizer(params): - return backtest(conf, pairs, mocker, buy_strategy_generator(params)) + buy_strategy = buy_strategy_generator(params) + mocker.patch('freqtrade.analyze.populate_buy_trend', side_effect=buy_strategy) + results = backtest(conf, pairs, mocker) + + print_results(results) + if len(results.index) < 800: # require at least 800 trades + return 100000 # return large number to "ignore" this result + return results.duration.mean() ** 3 / results.profit.sum() / results.profit.mean() # the smaller the better space = { 'mfi': hp.choice('mfi', [ @@ -162,5 +166,4 @@ def test_hyperopt(conf, pairs, mocker): {'type': 'faststoch10'} ]), } - print('Best parameters {}'.format(fmin(fn=optimizer, space=space, algo=tpe.suggest, max_evals=40)))