From 7f44ba6df48579659d379d2f7614d67fb91f221d Mon Sep 17 00:00:00 2001 From: Janne Sinivirta Date: Tue, 26 Dec 2017 10:08:10 +0200 Subject: [PATCH] unit tests for optimize.hyperopt --- freqtrade/optimize/hyperopt.py | 14 ++-- freqtrade/tests/optimize/test_hyperopt.py | 81 +++++++++++++++++++++-- 2 files changed, 86 insertions(+), 9 deletions(-) diff --git a/freqtrade/optimize/hyperopt.py b/freqtrade/optimize/hyperopt.py index 686f15a17..aeb7c1456 100644 --- a/freqtrade/optimize/hyperopt.py +++ b/freqtrade/optimize/hyperopt.py @@ -25,12 +25,10 @@ logging.getLogger('hyperopt.tpe').setLevel(logging.WARNING) logger = logging.getLogger(__name__) - # set TARGET_TRADES to suit your number concurrent trades so its realistic to 20days of data TARGET_TRADES = 1100 TOTAL_TRIES = None _CURRENT_TRIES = 0 - CURRENT_BEST_LOSS = 100 # this is expexted avg profit * expected trade count @@ -111,6 +109,13 @@ def log_results(results): sys.stdout.flush() +def calculate_loss(total_profit: float, trade_count: int): + """ objective function, returns smaller number for more optimal results """ + trade_loss = 1 - 0.35 * exp(-(trade_count - TARGET_TRADES) ** 2 / 10 ** 5.2) + profit_loss = max(0, 1 - total_profit / EXPECTED_MAX_PROFIT) + return trade_loss + profit_loss + + def optimizer(params): global _CURRENT_TRIES @@ -129,9 +134,8 @@ def optimizer(params): 'loss': float('inf') } - trade_loss = 1 - 0.35 * exp(-(trade_count - TARGET_TRADES) ** 2 / 10 ** 5.2) - profit_loss = max(0, 1 - total_profit / EXPECTED_MAX_PROFIT) - loss = trade_loss + profit_loss + loss = calculate_loss(total_profit, trade_count) + _CURRENT_TRIES += 1 log_results({ diff --git a/freqtrade/tests/optimize/test_hyperopt.py b/freqtrade/tests/optimize/test_hyperopt.py index a8bfe7dd4..104b3bfdd 100644 --- a/freqtrade/tests/optimize/test_hyperopt.py +++ b/freqtrade/tests/optimize/test_hyperopt.py @@ -1,6 +1,79 @@ -# pragma pylint: disable=missing-docstring,W0212 +# pragma pylint: disable=missing-docstring,W0212,C0103 + +from freqtrade.optimize.hyperopt import calculate_loss, TARGET_TRADES, EXPECTED_MAX_PROFIT, start, \ + log_results -def test_optimizer(default_conf, mocker): - # TODO: implement test - pass +def test_loss_calculation_prefer_correct_trade_count(): + correct = calculate_loss(1, TARGET_TRADES) + over = calculate_loss(1, TARGET_TRADES + 100) + under = calculate_loss(1, TARGET_TRADES - 100) + assert over > correct + assert under > correct + + +def test_loss_calculation_has_limited_profit(): + correct = calculate_loss(EXPECTED_MAX_PROFIT, TARGET_TRADES) + over = calculate_loss(EXPECTED_MAX_PROFIT * 2, TARGET_TRADES) + under = calculate_loss(EXPECTED_MAX_PROFIT / 2, TARGET_TRADES) + assert over == correct + assert under > correct + + +def create_trials(mocker): + return mocker.Mock( + results=[{ + 'loss': 1, + 'result': 'foo' + }] + ) + + +def test_start_calls_fmin(mocker): + mocker.patch('freqtrade.optimize.hyperopt.Trials', return_value=create_trials(mocker)) + mocker.patch('freqtrade.optimize.preprocess') + mocker.patch('freqtrade.optimize.load_data') + mock_fmin = mocker.patch('freqtrade.optimize.hyperopt.fmin', return_value={}) + + args = mocker.Mock(epochs=1, config='config.json.example', mongodb=False) + start(args) + + mock_fmin.assert_called_once() + + +def test_start_uses_mongotrials(mocker): + mock_mongotrials = mocker.patch('freqtrade.optimize.hyperopt.MongoTrials', + return_value=create_trials(mocker)) + mocker.patch('freqtrade.optimize.preprocess') + mocker.patch('freqtrade.optimize.load_data') + mocker.patch('freqtrade.optimize.hyperopt.fmin', return_value={}) + + args = mocker.Mock(epochs=1, config='config.json.example', mongodb=True) + start(args) + + mock_mongotrials.assert_called_once() + + +def test_log_results_if_loss_improves(mocker): + logger = mocker.patch('freqtrade.optimize.hyperopt.logger.info') + global CURRENT_BEST_LOSS + CURRENT_BEST_LOSS = 2 + log_results({ + 'loss': 1, + 'current_tries': 1, + 'total_tries': 2, + 'result': 'foo' + }) + + logger.assert_called_once() + + +def test_no_log_if_loss_does_not_improve(mocker): + logger = mocker.patch('freqtrade.optimize.hyperopt.logger.info') + global CURRENT_BEST_LOSS + CURRENT_BEST_LOSS = 2 + log_results({ + 'loss': 3, + }) + + assert not logger.called