Merge branch 'develop' into pair-to-strat

This commit is contained in:
Gert Wohlgemuth
2018-07-05 16:17:29 -07:00
committed by GitHub
62 changed files with 3478 additions and 2932 deletions

View File

@@ -9,13 +9,15 @@ from unittest.mock import MagicMock
import numpy as np
import pandas as pd
import pytest
from arrow import Arrow
from freqtrade import optimize
from freqtrade import DependencyException, constants, optimize
from freqtrade.analyze import Analyze
from freqtrade.arguments import Arguments, TimeRange
from freqtrade.optimize.backtesting import Backtesting, start, setup_configuration
from freqtrade.tests.conftest import log_has
from freqtrade.optimize.backtesting import (Backtesting, setup_configuration,
start)
from freqtrade.tests.conftest import log_has, patch_exchange
def get_args(args) -> List[str]:
@@ -83,7 +85,7 @@ def load_data_test(what):
def simple_backtest(config, contour, num_results, mocker) -> None:
mocker.patch('freqtrade.exchange.validate_pairs', MagicMock(return_value=True))
patch_exchange(mocker)
backtesting = Backtesting(config)
data = load_data_test(contour)
@@ -101,7 +103,8 @@ def simple_backtest(config, contour, num_results, mocker) -> None:
assert len(results) == num_results
def mocked_load_data(datadir, pairs=[], ticker_interval='0m', refresh_pairs=False, timerange=None):
def mocked_load_data(datadir, pairs=[], ticker_interval='0m', refresh_pairs=False,
timerange=None, exchange=None):
tickerdata = optimize.load_tickerdata_file(datadir, 'UNITTEST/BTC', '1m', timerange=timerange)
pairdata = {'UNITTEST/BTC': tickerdata}
return pairdata
@@ -118,7 +121,7 @@ def _load_pair_as_ticks(pair, tickfreq):
def _make_backtest_conf(mocker, conf=None, pair='UNITTEST/BTC', record=None):
data = optimize.load_data(None, ticker_interval='8m', pairs=[pair])
data = trim_dictlist(data, -201)
mocker.patch('freqtrade.exchange.validate_pairs', MagicMock(return_value=True))
patch_exchange(mocker)
backtesting = Backtesting(conf)
return {
'stake_amount': conf['stake_amount'],
@@ -267,13 +270,35 @@ def test_setup_configuration_with_arguments(mocker, default_conf, caplog) -> Non
)
def test_setup_configuration_unlimited_stake_amount(mocker, default_conf, caplog) -> None:
"""
Test setup_configuration() function
"""
conf = deepcopy(default_conf)
conf['stake_amount'] = constants.UNLIMITED_STAKE_AMOUNT
mocker.patch('freqtrade.configuration.open', mocker.mock_open(
read_data=json.dumps(conf)
))
args = [
'--config', 'config.json',
'--strategy', 'DefaultStrategy',
'backtesting'
]
with pytest.raises(DependencyException, match=r'.*stake amount.*'):
setup_configuration(get_args(args))
def test_start(mocker, fee, default_conf, caplog) -> None:
"""
Test start() function
"""
start_mock = MagicMock()
mocker.patch('freqtrade.exchange.get_fee', fee)
mocker.patch('freqtrade.exchange.validate_pairs', MagicMock(return_value=True))
mocker.patch('freqtrade.exchange.Exchange.get_fee', fee)
patch_exchange(mocker)
mocker.patch('freqtrade.optimize.backtesting.Backtesting.start', start_mock)
mocker.patch('freqtrade.configuration.open', mocker.mock_open(
read_data=json.dumps(default_conf)
@@ -296,7 +321,8 @@ def test_backtesting_init(mocker, default_conf) -> None:
"""
Test Backtesting._init() method
"""
mocker.patch('freqtrade.exchange.validate_pairs', MagicMock(return_value=True))
patch_exchange(mocker)
get_fee = mocker.patch('freqtrade.exchange.Exchange.get_fee', MagicMock(return_value=0.5))
backtesting = Backtesting(default_conf)
assert backtesting.config == default_conf
assert isinstance(backtesting.analyze, Analyze)
@@ -304,13 +330,15 @@ def test_backtesting_init(mocker, default_conf) -> None:
assert callable(backtesting.tickerdata_to_dataframe)
assert callable(backtesting.populate_buy_trend)
assert callable(backtesting.populate_sell_trend)
get_fee.assert_called()
assert backtesting.fee == 0.5
def test_tickerdata_to_dataframe(default_conf, mocker) -> None:
"""
Test Backtesting.tickerdata_to_dataframe() method
"""
mocker.patch('freqtrade.exchange.validate_pairs', MagicMock(return_value=True))
patch_exchange(mocker)
timerange = TimeRange(None, 'line', 0, -100)
tick = optimize.load_tickerdata_file(None, 'UNITTEST/BTC', '1m', timerange=timerange)
tickerlist = {'UNITTEST/BTC': tick}
@@ -329,7 +357,7 @@ def test_get_timeframe(default_conf, mocker) -> None:
"""
Test Backtesting.get_timeframe() method
"""
mocker.patch('freqtrade.exchange.validate_pairs', MagicMock(return_value=True))
patch_exchange(mocker)
backtesting = Backtesting(default_conf)
data = backtesting.tickerdata_to_dataframe(
@@ -348,15 +376,15 @@ def test_generate_text_table(default_conf, mocker):
"""
Test Backtesting.generate_text_table() method
"""
mocker.patch('freqtrade.exchange.validate_pairs', MagicMock(return_value=True))
patch_exchange(mocker)
backtesting = Backtesting(default_conf)
results = pd.DataFrame(
{
'currency': ['ETH/BTC', 'ETH/BTC'],
'pair': ['ETH/BTC', 'ETH/BTC'],
'profit_percent': [0.1, 0.2],
'profit_BTC': [0.2, 0.4],
'duration': [10, 30],
'profit_abs': [0.2, 0.4],
'trade_duration': [10, 30],
'profit': [2, 0],
'loss': [0, 0]
}
@@ -385,8 +413,8 @@ def test_backtesting_start(default_conf, mocker, caplog) -> None:
mocker.patch('freqtrade.freqtradebot.Analyze', MagicMock())
mocker.patch('freqtrade.optimize.load_data', mocked_load_data)
mocker.patch('freqtrade.exchange.get_ticker_history')
mocker.patch('freqtrade.exchange.validate_pairs', MagicMock(return_value=True))
mocker.patch('freqtrade.exchange.Exchange.get_ticker_history')
patch_exchange(mocker)
mocker.patch.multiple(
'freqtrade.optimize.backtesting.Backtesting',
backtest=MagicMock(),
@@ -426,8 +454,8 @@ def test_backtesting_start_no_data(default_conf, mocker, caplog) -> None:
mocker.patch('freqtrade.freqtradebot.Analyze', MagicMock())
mocker.patch('freqtrade.optimize.load_data', MagicMock(return_value={}))
mocker.patch('freqtrade.exchange.get_ticker_history')
mocker.patch('freqtrade.exchange.validate_pairs', MagicMock(return_value=True))
mocker.patch('freqtrade.exchange.Exchange.get_ticker_history')
patch_exchange(mocker)
mocker.patch.multiple(
'freqtrade.optimize.backtesting.Backtesting',
backtest=MagicMock(),
@@ -454,8 +482,8 @@ def test_backtest(default_conf, fee, mocker) -> None:
"""
Test Backtesting.backtest() method
"""
mocker.patch('freqtrade.exchange.get_fee', fee)
mocker.patch('freqtrade.exchange.validate_pairs', MagicMock(return_value=True))
mocker.patch('freqtrade.exchange.Exchange.get_fee', fee)
patch_exchange(mocker)
backtesting = Backtesting(default_conf)
data = optimize.load_data(None, ticker_interval='5m', pairs=['UNITTEST/BTC'])
@@ -469,14 +497,15 @@ def test_backtest(default_conf, fee, mocker) -> None:
}
)
assert not results.empty
assert len(results) == 2
def test_backtest_1min_ticker_interval(default_conf, fee, mocker) -> None:
"""
Test Backtesting.backtest() method with 1 min ticker
"""
mocker.patch('freqtrade.exchange.get_fee', fee)
mocker.patch('freqtrade.exchange.validate_pairs', MagicMock(return_value=True))
mocker.patch('freqtrade.exchange.Exchange.get_fee', fee)
patch_exchange(mocker)
backtesting = Backtesting(default_conf)
# Run a backtesting for an exiting 5min ticker_interval
@@ -491,13 +520,14 @@ def test_backtest_1min_ticker_interval(default_conf, fee, mocker) -> None:
}
)
assert not results.empty
assert len(results) == 1
def test_processed(default_conf, mocker) -> None:
"""
Test Backtesting.backtest() method with offline data
"""
mocker.patch('freqtrade.exchange.validate_pairs', MagicMock(return_value=True))
patch_exchange(mocker)
backtesting = Backtesting(default_conf)
dict_of_tickerrows = load_data_test('raise')
@@ -511,16 +541,16 @@ def test_processed(default_conf, mocker) -> None:
def test_backtest_pricecontours(default_conf, fee, mocker) -> None:
mocker.patch('freqtrade.optimize.backtesting.exchange.get_fee', fee)
tests = [['raise', 17], ['lower', 0], ['sine', 16]]
mocker.patch('freqtrade.exchange.Exchange.get_fee', fee)
tests = [['raise', 18], ['lower', 0], ['sine', 16]]
for [contour, numres] in tests:
simple_backtest(default_conf, contour, numres, mocker)
# Test backtest using offline data (testdata directory)
def test_backtest_ticks(default_conf, fee, mocker):
mocker.patch('freqtrade.exchange.get_fee', fee)
mocker.patch('freqtrade.exchange.validate_pairs', MagicMock(return_value=True))
mocker.patch('freqtrade.exchange.Exchange.get_fee', fee)
patch_exchange(mocker)
ticks = [1, 5]
fun = Backtesting(default_conf).populate_buy_trend
for _ in ticks:
@@ -539,7 +569,6 @@ def test_backtest_clash_buy_sell(mocker, default_conf):
sell_value = 1
return _trend(dataframe, buy_value, sell_value)
mocker.patch('freqtrade.exchange.validate_pairs', MagicMock(return_value=True))
backtest_conf = _make_backtest_conf(mocker, conf=default_conf)
backtesting = Backtesting(default_conf)
backtesting.populate_buy_trend = fun # Override
@@ -555,7 +584,6 @@ def test_backtest_only_sell(mocker, default_conf):
sell_value = 1
return _trend(dataframe, buy_value, sell_value)
mocker.patch('freqtrade.exchange.validate_pairs', MagicMock(return_value=True))
backtest_conf = _make_backtest_conf(mocker, conf=default_conf)
backtesting = Backtesting(default_conf)
backtesting.populate_buy_trend = fun # Override
@@ -565,50 +593,68 @@ def test_backtest_only_sell(mocker, default_conf):
def test_backtest_alternate_buy_sell(default_conf, fee, mocker):
mocker.patch('freqtrade.optimize.backtesting.exchange.get_fee', fee)
mocker.patch('freqtrade.exchange.validate_pairs', MagicMock(return_value=True))
mocker.patch('freqtrade.exchange.Exchange.get_fee', fee)
backtest_conf = _make_backtest_conf(mocker, conf=default_conf, pair='UNITTEST/BTC')
backtesting = Backtesting(default_conf)
backtesting.populate_buy_trend = _trend_alternate # Override
backtesting.populate_sell_trend = _trend_alternate # Override
results = backtesting.backtest(backtest_conf)
assert len(results) == 3
backtesting._store_backtest_result("test_.json", results)
assert len(results) == 4
# One trade was force-closed at the end
assert len(results.loc[results.open_at_end]) == 1
def test_backtest_record(default_conf, fee, mocker):
names = []
records = []
mocker.patch('freqtrade.exchange.validate_pairs', MagicMock(return_value=True))
mocker.patch('freqtrade.optimize.backtesting.exchange.get_fee', fee)
patch_exchange(mocker)
mocker.patch('freqtrade.exchange.Exchange.get_fee', fee)
mocker.patch(
'freqtrade.optimize.backtesting.file_dump_json',
new=lambda n, r: (names.append(n), records.append(r))
)
backtest_conf = _make_backtest_conf(
mocker,
conf=default_conf,
pair='UNITTEST/BTC',
record="trades"
)
backtesting = Backtesting(default_conf)
backtesting.populate_buy_trend = _trend_alternate # Override
backtesting.populate_sell_trend = _trend_alternate # Override
results = backtesting.backtest(backtest_conf)
assert len(results) == 3
results = pd.DataFrame({"pair": ["UNITTEST/BTC", "UNITTEST/BTC",
"UNITTEST/BTC", "UNITTEST/BTC"],
"profit_percent": [0.003312, 0.010801, 0.013803, 0.002780],
"profit_abs": [0.000003, 0.000011, 0.000014, 0.000003],
"open_time": [Arrow(2017, 11, 14, 19, 32, 00).datetime,
Arrow(2017, 11, 14, 21, 36, 00).datetime,
Arrow(2017, 11, 14, 22, 12, 00).datetime,
Arrow(2017, 11, 14, 22, 44, 00).datetime],
"close_time": [Arrow(2017, 11, 14, 21, 35, 00).datetime,
Arrow(2017, 11, 14, 22, 10, 00).datetime,
Arrow(2017, 11, 14, 22, 43, 00).datetime,
Arrow(2017, 11, 14, 22, 58, 00).datetime],
"open_rate": [0.002543, 0.003003, 0.003089, 0.003214],
"close_rate": [0.002546, 0.003014, 0.003103, 0.003217],
"open_index": [1, 119, 153, 185],
"close_index": [118, 151, 184, 199],
"trade_duration": [123, 34, 31, 14],
"open_at_end": [False, False, False, True]
})
backtesting._store_backtest_result("backtest-result.json", results)
assert len(results) == 4
# Assert file_dump_json was only called once
assert names == ['backtest-result.json']
records = records[0]
# Ensure records are of correct type
assert len(records) == 3
assert len(records) == 4
# ('UNITTEST/BTC', 0.00331158, '1510684320', '1510691700', 0, 117)
# Below follows just a typecheck of the schema/type of trade-records
oix = None
for (pair, profit, date_buy, date_sell, buy_index, dur) in records:
for (pair, profit, date_buy, date_sell, buy_index, dur,
openr, closer, open_at_end) in records:
assert pair == 'UNITTEST/BTC'
isinstance(profit, float)
assert isinstance(profit, float)
# FIX: buy/sell should be converted to ints
isinstance(date_buy, str)
isinstance(date_sell, str)
assert isinstance(date_buy, float)
assert isinstance(date_sell, float)
assert isinstance(openr, float)
assert isinstance(closer, float)
assert isinstance(open_at_end, bool)
isinstance(buy_index, pd._libs.tslib.Timestamp)
if oix:
assert buy_index > oix
@@ -619,9 +665,9 @@ def test_backtest_record(default_conf, fee, mocker):
def test_backtest_start_live(default_conf, mocker, caplog):
conf = deepcopy(default_conf)
conf['exchange']['pair_whitelist'] = ['UNITTEST/BTC']
mocker.patch('freqtrade.exchange.get_ticker_history',
new=lambda n, i: _load_pair_as_ticks(n, i))
mocker.patch('freqtrade.exchange.validate_pairs', MagicMock())
mocker.patch('freqtrade.exchange.Exchange.get_ticker_history',
new=lambda s, n, i: _load_pair_as_ticks(n, i))
patch_exchange(mocker)
mocker.patch('freqtrade.optimize.backtesting.Backtesting.backtest', MagicMock())
mocker.patch('freqtrade.optimize.backtesting.Backtesting._generate_text_table', MagicMock())
mocker.patch('freqtrade.configuration.open', mocker.mock_open(

View File

@@ -1,6 +1,5 @@
# pragma pylint: disable=missing-docstring,W0212,C0103
import os
import signal
from copy import deepcopy
from unittest.mock import MagicMock
@@ -10,7 +9,7 @@ import pytest
from freqtrade.optimize.__init__ import load_tickerdata_file
from freqtrade.optimize.hyperopt import Hyperopt, start
from freqtrade.strategy.resolver import StrategyResolver
from freqtrade.tests.conftest import log_has
from freqtrade.tests.conftest import log_has, patch_exchange
from freqtrade.tests.optimize.test_backtesting import get_args
# Avoid to reinit the same object again and again
@@ -22,10 +21,7 @@ _HYPEROPT = None
def init_hyperopt(default_conf, mocker):
global _HYPEROPT_INITIALIZED, _HYPEROPT
if not _HYPEROPT_INITIALIZED:
mocker.patch('freqtrade.exchange.validate_pairs', MagicMock(return_value=True))
mocker.patch('freqtrade.optimize.hyperopt.hyperopt_optimize_conf',
MagicMock(return_value=default_conf))
mocker.patch('freqtrade.exchange.validate_pairs', MagicMock())
patch_exchange(mocker)
_HYPEROPT = Hyperopt(default_conf)
_HYPEROPT_INITIALIZED = True
@@ -43,30 +39,22 @@ def create_trials(mocker) -> None:
mocker.patch('freqtrade.optimize.hyperopt.os.path.exists', return_value=False)
mocker.patch('freqtrade.optimize.hyperopt.os.path.getsize', return_value=1)
mocker.patch('freqtrade.optimize.hyperopt.os.remove', return_value=True)
mocker.patch('freqtrade.optimize.hyperopt.pickle.dump', return_value=None)
mocker.patch('freqtrade.optimize.hyperopt.dump', return_value=None)
return mocker.Mock(
results=[
{
'loss': 1,
'result': 'foo',
'status': 'ok'
}
],
best_trial={'misc': {'vals': {'adx': 999}}}
)
return [{'loss': 1, 'result': 'foo', 'params': {}}]
# Unit tests
def test_start(mocker, default_conf, caplog) -> None:
"""
Test start() function
"""
start_mock = MagicMock()
mocker.patch(
'freqtrade.configuration.Configuration._load_config_file',
lambda *args, **kwargs: default_conf
)
mocker.patch('freqtrade.optimize.hyperopt.Hyperopt.start', start_mock)
mocker.patch('freqtrade.optimize.hyperopt.hyperopt_optimize_conf',
MagicMock(return_value=default_conf))
mocker.patch('freqtrade.freqtradebot.exchange.validate_pairs', MagicMock())
patch_exchange(mocker)
args = [
'--config', 'config.json',
@@ -149,159 +137,18 @@ def test_no_log_if_loss_does_not_improve(init_hyperopt, caplog) -> None:
assert caplog.record_tuples == []
def test_fmin_best_results(mocker, init_hyperopt, default_conf, caplog) -> None:
fmin_result = {
"macd_below_zero": 0,
"adx": 1,
"adx-value": 15.0,
"fastd": 1,
"fastd-value": 40.0,
"green_candle": 1,
"mfi": 0,
"over_sar": 0,
"rsi": 1,
"rsi-value": 37.0,
"trigger": 2,
"uptrend_long_ema": 1,
"uptrend_short_ema": 0,
"uptrend_sma": 0,
"stoploss": -0.1,
"roi_t1": 1,
"roi_t2": 2,
"roi_t3": 3,
"roi_p1": 1,
"roi_p2": 2,
"roi_p3": 3,
}
conf = deepcopy(default_conf)
conf.update({'config': 'config.json.example'})
conf.update({'epochs': 1})
conf.update({'timerange': None})
conf.update({'spaces': 'all'})
mocker.patch('freqtrade.optimize.hyperopt.load_data', MagicMock())
mocker.patch('freqtrade.optimize.hyperopt.fmin', return_value=fmin_result)
mocker.patch('freqtrade.optimize.hyperopt.hyperopt_optimize_conf', return_value=conf)
mocker.patch('freqtrade.freqtradebot.exchange.validate_pairs', MagicMock())
StrategyResolver({'strategy': 'DefaultStrategy'})
hyperopt = Hyperopt(conf)
hyperopt.trials = create_trials(mocker)
hyperopt.tickerdata_to_dataframe = MagicMock()
hyperopt.start()
exists = [
'Best parameters:',
'"adx": {\n "enabled": true,\n "value": 15.0\n },',
'"fastd": {\n "enabled": true,\n "value": 40.0\n },',
'"green_candle": {\n "enabled": true\n },',
'"macd_below_zero": {\n "enabled": false\n },',
'"mfi": {\n "enabled": false\n },',
'"over_sar": {\n "enabled": false\n },',
'"roi_p1": 1.0,',
'"roi_p2": 2.0,',
'"roi_p3": 3.0,',
'"roi_t1": 1.0,',
'"roi_t2": 2.0,',
'"roi_t3": 3.0,',
'"rsi": {\n "enabled": true,\n "value": 37.0\n },',
'"stoploss": -0.1,',
'"trigger": {\n "type": "faststoch10"\n },',
'"uptrend_long_ema": {\n "enabled": true\n },',
'"uptrend_short_ema": {\n "enabled": false\n },',
'"uptrend_sma": {\n "enabled": false\n }',
'ROI table:\n{0: 6.0, 3.0: 3.0, 5.0: 1.0, 6.0: 0}',
'Best Result:\nfoo'
]
for line in exists:
assert line in caplog.text
def test_fmin_throw_value_error(mocker, init_hyperopt, default_conf, caplog) -> None:
mocker.patch('freqtrade.optimize.hyperopt.load_data', MagicMock())
mocker.patch('freqtrade.optimize.hyperopt.fmin', side_effect=ValueError())
conf = deepcopy(default_conf)
conf.update({'config': 'config.json.example'})
conf.update({'epochs': 1})
conf.update({'timerange': None})
conf.update({'spaces': 'all'})
mocker.patch('freqtrade.optimize.hyperopt.hyperopt_optimize_conf', return_value=conf)
mocker.patch('freqtrade.freqtradebot.exchange.validate_pairs', MagicMock())
StrategyResolver({'strategy': 'DefaultStrategy'})
hyperopt = Hyperopt(conf)
hyperopt.trials = create_trials(mocker)
hyperopt.tickerdata_to_dataframe = MagicMock()
hyperopt.start()
exists = [
'Best Result:',
'Sorry, Hyperopt was not able to find good parameters. Please try with more epochs '
'(param: -e).',
]
for line in exists:
assert line in caplog.text
def test_resuming_previous_hyperopt_results_succeeds(mocker, init_hyperopt, default_conf) -> None:
trials = create_trials(mocker)
conf = deepcopy(default_conf)
conf.update({'config': 'config.json.example'})
conf.update({'epochs': 1})
conf.update({'mongodb': False})
conf.update({'timerange': None})
conf.update({'spaces': 'all'})
mocker.patch('freqtrade.optimize.hyperopt.os.path.exists', return_value=True)
mocker.patch('freqtrade.optimize.hyperopt.len', return_value=len(trials.results))
mock_read = mocker.patch(
'freqtrade.optimize.hyperopt.Hyperopt.read_trials',
return_value=trials
)
mock_save = mocker.patch(
'freqtrade.optimize.hyperopt.Hyperopt.save_trials',
return_value=None
)
mocker.patch('freqtrade.optimize.hyperopt.sorted', return_value=trials.results)
mocker.patch('freqtrade.optimize.hyperopt.load_data', MagicMock())
mocker.patch('freqtrade.optimize.hyperopt.fmin', return_value={})
mocker.patch('freqtrade.optimize.hyperopt.hyperopt_optimize_conf', return_value=conf)
mocker.patch('freqtrade.exchange.validate_pairs', MagicMock())
StrategyResolver({'strategy': 'DefaultStrategy'})
hyperopt = Hyperopt(conf)
hyperopt.trials = trials
hyperopt.tickerdata_to_dataframe = MagicMock()
hyperopt.start()
mock_read.assert_called_once()
mock_save.assert_called_once()
current_tries = hyperopt.current_tries
total_tries = hyperopt.total_tries
assert current_tries == len(trials.results)
assert total_tries == (current_tries + len(trials.results))
def test_save_trials_saves_trials(mocker, init_hyperopt, caplog) -> None:
create_trials(mocker)
mock_dump = mocker.patch('freqtrade.optimize.hyperopt.pickle.dump', return_value=None)
trials = create_trials(mocker)
mock_dump = mocker.patch('freqtrade.optimize.hyperopt.dump', return_value=None)
hyperopt = _HYPEROPT
mocker.patch('freqtrade.optimize.hyperopt.open', return_value=hyperopt.trials_file)
_HYPEROPT.trials = trials
hyperopt.save_trials()
trials_file = os.path.join('freqtrade', 'tests', 'optimize', 'ut_trials.pickle')
assert log_has(
'Saving Trials to \'{}\''.format(trials_file),
'Saving 1 evaluations to \'{}\''.format(trials_file),
caplog.record_tuples
)
mock_dump.assert_called_once()
@@ -309,8 +156,7 @@ def test_save_trials_saves_trials(mocker, init_hyperopt, caplog) -> None:
def test_read_trials_returns_trials_file(mocker, init_hyperopt, caplog) -> None:
trials = create_trials(mocker)
mock_load = mocker.patch('freqtrade.optimize.hyperopt.pickle.load', return_value=trials)
mock_open = mocker.patch('freqtrade.optimize.hyperopt.open', return_value=mock_load)
mock_load = mocker.patch('freqtrade.optimize.hyperopt.load', return_value=trials)
hyperopt = _HYPEROPT
hyperopt_trial = hyperopt.read_trials()
@@ -320,7 +166,6 @@ def test_read_trials_returns_trials_file(mocker, init_hyperopt, caplog) -> None:
caplog.record_tuples
)
assert hyperopt_trial == trials
mock_open.assert_called_once()
mock_load.assert_called_once()
@@ -338,56 +183,31 @@ def test_roi_table_generation(init_hyperopt) -> None:
assert hyperopt.generate_roi_table(params) == {0: 6, 15: 3, 25: 1, 30: 0}
def test_start_calls_fmin(mocker, init_hyperopt, default_conf) -> None:
trials = create_trials(mocker)
mocker.patch('freqtrade.optimize.hyperopt.sorted', return_value=trials.results)
def test_start_calls_optimizer(mocker, init_hyperopt, default_conf, caplog) -> None:
dumper = mocker.patch('freqtrade.optimize.hyperopt.dump', MagicMock())
mocker.patch('freqtrade.optimize.hyperopt.load_data', MagicMock())
mocker.patch('freqtrade.exchange.validate_pairs', MagicMock())
mock_fmin = mocker.patch('freqtrade.optimize.hyperopt.fmin', return_value={})
conf = deepcopy(default_conf)
conf.update({'config': 'config.json.example'})
conf.update({'epochs': 1})
conf.update({'mongodb': False})
conf.update({'timerange': None})
conf.update({'spaces': 'all'})
hyperopt = Hyperopt(conf)
hyperopt.trials = trials
hyperopt.tickerdata_to_dataframe = MagicMock()
hyperopt.start()
mock_fmin.assert_called_once()
def test_start_uses_mongotrials(mocker, init_hyperopt, default_conf) -> None:
mocker.patch('freqtrade.optimize.hyperopt.load_data', MagicMock())
mock_fmin = mocker.patch('freqtrade.optimize.hyperopt.fmin', return_value={})
mock_mongotrials = mocker.patch(
'freqtrade.optimize.hyperopt.MongoTrials',
return_value=create_trials(mocker)
mocker.patch('freqtrade.optimize.hyperopt.multiprocessing.cpu_count', MagicMock(return_value=1))
parallel = mocker.patch(
'freqtrade.optimize.hyperopt.Hyperopt.run_optimizer_parallel',
MagicMock(return_value=[{'loss': 1, 'result': 'foo result', 'params': {}}])
)
patch_exchange(mocker)
conf = deepcopy(default_conf)
conf.update({'config': 'config.json.example'})
conf.update({'epochs': 1})
conf.update({'mongodb': True})
conf.update({'timerange': None})
conf.update({'spaces': 'all'})
mocker.patch('freqtrade.optimize.hyperopt.hyperopt_optimize_conf', return_value=conf)
mocker.patch('freqtrade.freqtradebot.exchange.validate_pairs', MagicMock())
hyperopt = Hyperopt(conf)
hyperopt.tickerdata_to_dataframe = MagicMock()
hyperopt.start()
mock_mongotrials.assert_called_once()
mock_fmin.assert_called_once()
parallel.assert_called_once()
assert 'Best result:\nfoo result\nwith values:\n{}' in caplog.text
assert dumper.called
# test log_trials_result
# test buy_strategy_generator def populate_buy_trend
# test optimizer if 'ro_t1' in params
def test_format_results(init_hyperopt):
"""
@@ -400,7 +220,7 @@ def test_format_results(init_hyperopt):
('LTC/BTC', 1, 1, 123),
('XPR/BTC', -1, -2, -246)
]
labels = ['currency', 'profit_percent', 'profit_BTC', 'duration']
labels = ['currency', 'profit_percent', 'profit_abs', 'trade_duration']
df = pd.DataFrame.from_records(trades, columns=labels)
result = _HYPEROPT.format_results(df)
@@ -419,20 +239,6 @@ def test_format_results(init_hyperopt):
assert result.find('Total profit 1.00000000 EUR')
def test_signal_handler(mocker, init_hyperopt):
"""
Test Hyperopt.signal_handler()
"""
m = MagicMock()
mocker.patch('sys.exit', m)
mocker.patch('freqtrade.optimize.hyperopt.Hyperopt.save_trials', m)
mocker.patch('freqtrade.optimize.hyperopt.Hyperopt.log_trials_result', m)
hyperopt = _HYPEROPT
hyperopt.signal_handler(signal.SIGTERM, None)
assert m.call_count == 3
def test_has_space(init_hyperopt):
"""
Test Hyperopt.has_space() method
@@ -457,8 +263,8 @@ def test_populate_indicators(init_hyperopt) -> None:
# Check if some indicators are generated. We will not test all of them
assert 'adx' in dataframe
assert 'ao' in dataframe
assert 'cci' in dataframe
assert 'mfi' in dataframe
assert 'rsi' in dataframe
def test_buy_strategy_generator(init_hyperopt) -> None:
@@ -472,44 +278,15 @@ def test_buy_strategy_generator(init_hyperopt) -> None:
populate_buy_trend = _HYPEROPT.buy_strategy_generator(
{
'uptrend_long_ema': {
'enabled': True
},
'macd_below_zero': {
'enabled': True
},
'uptrend_short_ema': {
'enabled': True
},
'mfi': {
'enabled': True,
'value': 20
},
'fastd': {
'enabled': True,
'value': 20
},
'adx': {
'enabled': True,
'value': 20
},
'rsi': {
'enabled': True,
'value': 20
},
'over_sar': {
'enabled': True,
},
'green_candle': {
'enabled': True,
},
'uptrend_sma': {
'enabled': True,
},
'trigger': {
'type': 'lower_bb'
}
'adx-value': 20,
'fastd-value': 20,
'mfi-value': 20,
'rsi-value': 20,
'adx-enabled': True,
'fastd-enabled': True,
'mfi-enabled': True,
'rsi-enabled': True,
'trigger': 'bb_lower'
}
)
result = populate_buy_trend(dataframe)
@@ -530,43 +307,42 @@ def test_generate_optimizer(mocker, init_hyperopt, default_conf) -> None:
trades = [
('POWR/BTC', 0.023117, 0.000233, 100)
]
labels = ['currency', 'profit_percent', 'profit_BTC', 'duration']
labels = ['currency', 'profit_percent', 'profit_abs', 'trade_duration']
backtest_result = pd.DataFrame.from_records(trades, columns=labels)
mocker.patch(
'freqtrade.optimize.hyperopt.Hyperopt.backtest',
MagicMock(return_value=backtest_result)
)
mocker.patch('freqtrade.exchange.validate_pairs', MagicMock())
patch_exchange(mocker)
mocker.patch('freqtrade.optimize.hyperopt.load', MagicMock())
optimizer_param = {
'adx': {'enabled': False},
'fastd': {'enabled': True, 'value': 35.0},
'green_candle': {'enabled': True},
'macd_below_zero': {'enabled': True},
'mfi': {'enabled': False},
'over_sar': {'enabled': False},
'roi_p1': 0.01,
'roi_p2': 0.01,
'roi_p3': 0.1,
'adx-value': 0,
'fastd-value': 35,
'mfi-value': 0,
'rsi-value': 0,
'adx-enabled': False,
'fastd-enabled': True,
'mfi-enabled': False,
'rsi-enabled': False,
'trigger': 'macd_cross_signal',
'roi_t1': 60.0,
'roi_t2': 30.0,
'roi_t3': 20.0,
'rsi': {'enabled': False},
'roi_p1': 0.01,
'roi_p2': 0.01,
'roi_p3': 0.1,
'stoploss': -0.4,
'trigger': {'type': 'macd_cross_signal'},
'uptrend_long_ema': {'enabled': False},
'uptrend_short_ema': {'enabled': True},
'uptrend_sma': {'enabled': True}
}
response_expected = {
'loss': 1.9840569076926293,
'result': ' 1 trades. Avg profit 2.31%. Total profit 0.00023300 BTC '
'(0.0231Σ%). Avg duration 100.0 mins.',
'status': 'ok'
'params': optimizer_param
}
hyperopt = Hyperopt(conf)
generate_optimizer_value = hyperopt.generate_optimizer(optimizer_param)
generate_optimizer_value = hyperopt.generate_optimizer(list(optimizer_param.values()))
assert generate_optimizer_value == response_expected

View File

@@ -1,16 +0,0 @@
# pragma pylint: disable=missing-docstring,W0212
from user_data.hyperopt_conf import hyperopt_optimize_conf
def test_hyperopt_optimize_conf():
hyperopt_conf = hyperopt_optimize_conf()
assert "max_open_trades" in hyperopt_conf
assert "stake_currency" in hyperopt_conf
assert "stake_amount" in hyperopt_conf
assert "minimal_roi" in hyperopt_conf
assert "stoploss" in hyperopt_conf
assert "bid_strategy" in hyperopt_conf
assert "exchange" in hyperopt_conf
assert "pair_whitelist" in hyperopt_conf['exchange']

View File

@@ -3,16 +3,19 @@
import json
import os
import uuid
import arrow
from shutil import copyfile
import arrow
from freqtrade import optimize
from freqtrade.misc import file_dump_json
from freqtrade.optimize.__init__ import make_testdata_path, download_pairs, \
download_backtesting_testdata, load_tickerdata_file, trim_tickerlist, \
load_cached_data_for_updating
from freqtrade.arguments import TimeRange
from freqtrade.tests.conftest import log_has
from freqtrade.misc import file_dump_json
from freqtrade.optimize.__init__ import (download_backtesting_testdata,
download_pairs,
load_cached_data_for_updating,
load_tickerdata_file,
make_testdata_path, trim_tickerlist)
from freqtrade.tests.conftest import get_patched_exchange, log_has
# Change this if modifying UNITTEST/BTC testdatafile
_BTC_UNITTEST_LENGTH = 13681
@@ -49,12 +52,11 @@ def _clean_test_file(file: str) -> None:
os.rename(file_swp, file)
def test_load_data_30min_ticker(ticker_history, mocker, caplog) -> None:
def test_load_data_30min_ticker(ticker_history, mocker, caplog, default_conf) -> None:
"""
Test load_data() with 30 min ticker
"""
mocker.patch('freqtrade.optimize.get_ticker_history', return_value=ticker_history)
mocker.patch('freqtrade.exchange.Exchange.get_ticker_history', return_value=ticker_history)
file = os.path.join(os.path.dirname(__file__), '..', 'testdata', 'UNITTEST_BTC-30m.json')
_backup_file(file, copy_file=True)
optimize.load_data(None, pairs=['UNITTEST/BTC'], ticker_interval='30m')
@@ -63,11 +65,11 @@ def test_load_data_30min_ticker(ticker_history, mocker, caplog) -> None:
_clean_test_file(file)
def test_load_data_5min_ticker(ticker_history, mocker, caplog) -> None:
def test_load_data_5min_ticker(ticker_history, mocker, caplog, default_conf) -> None:
"""
Test load_data() with 5 min ticker
"""
mocker.patch('freqtrade.optimize.get_ticker_history', return_value=ticker_history)
mocker.patch('freqtrade.exchange.Exchange.get_ticker_history', return_value=ticker_history)
file = os.path.join(os.path.dirname(__file__), '..', 'testdata', 'UNITTEST_BTC-5m.json')
_backup_file(file, copy_file=True)
@@ -81,7 +83,7 @@ def test_load_data_1min_ticker(ticker_history, mocker, caplog) -> None:
"""
Test load_data() with 1 min ticker
"""
mocker.patch('freqtrade.optimize.get_ticker_history', return_value=ticker_history)
mocker.patch('freqtrade.exchange.Exchange.get_ticker_history', return_value=ticker_history)
file = os.path.join(os.path.dirname(__file__), '..', 'testdata', 'UNITTEST_BTC-1m.json')
_backup_file(file, copy_file=True)
@@ -91,12 +93,12 @@ def test_load_data_1min_ticker(ticker_history, mocker, caplog) -> None:
_clean_test_file(file)
def test_load_data_with_new_pair_1min(ticker_history, mocker, caplog) -> None:
def test_load_data_with_new_pair_1min(ticker_history, mocker, caplog, default_conf) -> None:
"""
Test load_data() with 1 min ticker
"""
mocker.patch('freqtrade.optimize.get_ticker_history', return_value=ticker_history)
mocker.patch('freqtrade.exchange.Exchange.get_ticker_history', return_value=ticker_history)
exchange = get_patched_exchange(mocker, default_conf)
file = os.path.join(os.path.dirname(__file__), '..', 'testdata', 'MEME_BTC-1m.json')
_backup_file(file)
@@ -114,6 +116,7 @@ def test_load_data_with_new_pair_1min(ticker_history, mocker, caplog) -> None:
optimize.load_data(None,
ticker_interval='1m',
refresh_pairs=True,
exchange=exchange,
pairs=['MEME/BTC'])
assert os.path.isfile(file) is True
assert log_has('Download the pair: "MEME/BTC", Interval: 1m', caplog.record_tuples)
@@ -124,9 +127,9 @@ def test_testdata_path() -> None:
assert os.path.join('freqtrade', 'tests', 'testdata') in make_testdata_path(None)
def test_download_pairs(ticker_history, mocker) -> None:
mocker.patch('freqtrade.optimize.__init__.get_ticker_history', return_value=ticker_history)
def test_download_pairs(ticker_history, mocker, default_conf) -> None:
mocker.patch('freqtrade.exchange.Exchange.get_ticker_history', return_value=ticker_history)
exchange = get_patched_exchange(mocker, default_conf)
file1_1 = os.path.join(os.path.dirname(__file__), '..', 'testdata', 'MEME_BTC-1m.json')
file1_5 = os.path.join(os.path.dirname(__file__), '..', 'testdata', 'MEME_BTC-5m.json')
file2_1 = os.path.join(os.path.dirname(__file__), '..', 'testdata', 'CFI_BTC-1m.json')
@@ -140,7 +143,8 @@ def test_download_pairs(ticker_history, mocker) -> None:
assert os.path.isfile(file1_1) is False
assert os.path.isfile(file2_1) is False
assert download_pairs(None, pairs=['MEME/BTC', 'CFI/BTC'], ticker_interval='1m') is True
assert download_pairs(None, exchange,
pairs=['MEME/BTC', 'CFI/BTC'], ticker_interval='1m') is True
assert os.path.isfile(file1_1) is True
assert os.path.isfile(file2_1) is True
@@ -152,7 +156,8 @@ def test_download_pairs(ticker_history, mocker) -> None:
assert os.path.isfile(file1_5) is False
assert os.path.isfile(file2_5) is False
assert download_pairs(None, pairs=['MEME/BTC', 'CFI/BTC'], ticker_interval='5m') is True
assert download_pairs(None, exchange,
pairs=['MEME/BTC', 'CFI/BTC'], ticker_interval='5m') is True
assert os.path.isfile(file1_5) is True
assert os.path.isfile(file2_5) is True
@@ -265,30 +270,32 @@ def test_load_cached_data_for_updating(mocker) -> None:
assert start_ts is None
def test_download_pairs_exception(ticker_history, mocker, caplog) -> None:
mocker.patch('freqtrade.optimize.__init__.get_ticker_history', return_value=ticker_history)
def test_download_pairs_exception(ticker_history, mocker, caplog, default_conf) -> None:
mocker.patch('freqtrade.exchange.Exchange.get_ticker_history', return_value=ticker_history)
mocker.patch('freqtrade.optimize.__init__.download_backtesting_testdata',
side_effect=BaseException('File Error'))
exchange = get_patched_exchange(mocker, default_conf)
file1_1 = os.path.join(os.path.dirname(__file__), '..', 'testdata', 'MEME_BTC-1m.json')
file1_5 = os.path.join(os.path.dirname(__file__), '..', 'testdata', 'MEME_BTC-5m.json')
_backup_file(file1_1)
_backup_file(file1_5)
download_pairs(None, pairs=['MEME/BTC'], ticker_interval='1m')
download_pairs(None, exchange, pairs=['MEME/BTC'], ticker_interval='1m')
# clean files freshly downloaded
_clean_test_file(file1_1)
_clean_test_file(file1_5)
assert log_has('Failed to download the pair: "MEME/BTC", Interval: 1m', caplog.record_tuples)
def test_download_backtesting_testdata(ticker_history, mocker) -> None:
mocker.patch('freqtrade.optimize.__init__.get_ticker_history', return_value=ticker_history)
def test_download_backtesting_testdata(ticker_history, mocker, default_conf) -> None:
mocker.patch('freqtrade.exchange.Exchange.get_ticker_history', return_value=ticker_history)
exchange = get_patched_exchange(mocker, default_conf)
# Download a 1 min ticker file
file1 = os.path.join(os.path.dirname(__file__), '..', 'testdata', 'XEL_BTC-1m.json')
_backup_file(file1)
download_backtesting_testdata(None, pair="XEL/BTC", tick_interval='1m')
download_backtesting_testdata(None, exchange, pair="XEL/BTC", tick_interval='1m')
assert os.path.isfile(file1) is True
_clean_test_file(file1)
@@ -296,21 +303,21 @@ def test_download_backtesting_testdata(ticker_history, mocker) -> None:
file2 = os.path.join(os.path.dirname(__file__), '..', 'testdata', 'STORJ_BTC-5m.json')
_backup_file(file2)
download_backtesting_testdata(None, pair="STORJ/BTC", tick_interval='5m')
download_backtesting_testdata(None, exchange, pair="STORJ/BTC", tick_interval='5m')
assert os.path.isfile(file2) is True
_clean_test_file(file2)
def test_download_backtesting_testdata2(mocker) -> None:
def test_download_backtesting_testdata2(mocker, default_conf) -> None:
tick = [
[1509836520000, 0.00162008, 0.00162008, 0.00162008, 0.00162008, 108.14853839],
[1509836580000, 0.00161, 0.00161, 0.00161, 0.00161, 82.390199]
]
json_dump_mock = mocker.patch('freqtrade.misc.file_dump_json', return_value=None)
mocker.patch('freqtrade.optimize.__init__.get_ticker_history', return_value=tick)
download_backtesting_testdata(None, pair="UNITTEST/BTC", tick_interval='1m')
download_backtesting_testdata(None, pair="UNITTEST/BTC", tick_interval='3m')
mocker.patch('freqtrade.exchange.Exchange.get_ticker_history', return_value=tick)
exchange = get_patched_exchange(mocker, default_conf)
download_backtesting_testdata(None, exchange, pair="UNITTEST/BTC", tick_interval='1m')
download_backtesting_testdata(None, exchange, pair="UNITTEST/BTC", tick_interval='3m')
assert json_dump_mock.call_count == 2
@@ -326,10 +333,10 @@ def test_load_tickerdata_file() -> None:
def test_init(default_conf, mocker) -> None:
conf = {'exchange': {'pair_whitelist': []}}
mocker.patch('freqtrade.optimize.hyperopt_optimize_conf', return_value=conf)
exchange = get_patched_exchange(mocker, default_conf)
assert {} == optimize.load_data(
'',
exchange=exchange,
pairs=[],
refresh_pairs=True,
ticker_interval=default_conf['ticker_interval']