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..9a9df78e9 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(): @@ -41,44 +35,6 @@ def conf(): "stoploss": -0.05 } - -def backtest(conf, pairs, mocker, buy_strategy): - trades = [] - mocker.patch.dict('freqtrade.main._CONF', conf) - for pair in pairs: - with open('freqtrade/tests/testdata/'+pair+'.json') as data_file: - data = json.load(data_file) - - mocker.patch('freqtrade.analyze.get_ticker_history', return_value=data) - mocker.patch('arrow.utcnow', return_value=arrow.get('2017-08-20T14:50:00')) - mocker.patch('freqtrade.analyze.populate_buy_trend', side_effect=buy_strategy) - ticker = analyze_ticker(pair) - # for each buy point - for index, row in ticker[ticker.buy == 1].iterrows(): - trade = Trade( - open_rate=row['close'], - open_date=arrow.get(row['date']).datetime, - amount=1, - ) - # calculate win/lose forwards from buy point - for index2, row2 in ticker[index:].iterrows(): - if should_sell(trade, row2['close'], arrow.get(row2['date']).datetime): - current_profit = (row2['close'] - trade.open_rate) / trade.open_rate - - trades.append((pair, current_profit, index2 - index)) - break - - labels = ['currency', 'profit', 'duration'] - results = DataFrame.from_records(trades, columns=labels) - - print_results(results) - - # set the value below to suit your number concurrent trades so its realistic to 20days of data - TARGET_TRADES = 1200 - if results.profit.sum() == 0 or results.profit.mean() == 0: - return 49999999999 # avoid division by zero, return huge value to discard result - return abs(len(results.index) - 1200.1) / (results.profit.sum() ** 2) * results.duration.mean() # the smaller the better - def buy_strategy_generator(params): print(params) def populate_buy_trend(dataframe: DataFrame) -> DataFrame: @@ -120,9 +76,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 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) + + # set the value below to suit your number concurrent trades so its realistic to 20days of data + TARGET_TRADES = 1200 + if results.profit.sum() == 0 or results.profit.mean() == 0: + return 49999999999 # avoid division by zero, return huge value to discard result + return abs(len(results.index) - 1200.1) / (results.profit.sum() ** 2) * results.duration.mean() # the smaller the better space = { 'mfi': hp.choice('mfi', [ @@ -162,5 +127,4 @@ def test_hyperopt(conf, pairs, mocker): {'type': 'faststoch10'} ]), } - print('Best parameters {}'.format(fmin(fn=optimizer, space=space, algo=tpe.suggest, max_evals=40)))