merged
This commit is contained in:
@@ -356,21 +356,31 @@ def test_generate_text_table(default_conf, mocker):
|
||||
|
||||
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],
|
||||
'cum profit %': [30, 30],
|
||||
'total profit BTC': [0.6, 0.6],
|
||||
'trade_duration': [10, 30],
|
||||
'profit': [2, 0],
|
||||
'loss': [0, 0]
|
||||
}
|
||||
)
|
||||
|
||||
result_str = (
|
||||
"""| pair | buy count | avg profit % | cum profit % | total profit BTC | avg duration | profit | loss |
|
||||
"""| pair | buy count | avg profit % | cum profit % | total profit BTC | avg duration | profit | loss |
|
||||
|:--------|------------:|---------------:|---------------:|-------------------:|---------------:|---------:|-------:|
|
||||
| ETH/BTC | 2 | 15.00 | 30.00 | 0.60000000 | 20.0 | 2 | 0 |
|
||||
| TOTAL | 2 | 15.00 | 30.00 | 0.60000000 | 20.0 | 2 | 0 |"""
|
||||
)
|
||||
#
|
||||
# print()
|
||||
# print(backtesting._generate_text_table(data={'ETH/BTC': {}}, results=results))
|
||||
#
|
||||
# print()
|
||||
# print()
|
||||
# print(result_str)
|
||||
|
||||
assert backtesting._generate_text_table(data={'ETH/BTC': {}}, results=results) == result_str
|
||||
|
||||
|
||||
@@ -469,6 +479,7 @@ 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:
|
||||
@@ -491,6 +502,7 @@ 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:
|
||||
@@ -512,7 +524,7 @@ 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]]
|
||||
tests = [['raise', 18], ['lower', 0], ['sine', 16]]
|
||||
for [contour, numres] in tests:
|
||||
simple_backtest(default_conf, contour, numres, mocker)
|
||||
|
||||
@@ -572,7 +584,10 @@ def test_backtest_alternate_buy_sell(default_conf, fee, mocker):
|
||||
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):
|
||||
@@ -584,22 +599,30 @@ def test_backtest_record(default_conf, fee, mocker):
|
||||
'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_index": [1, 119, 153, 185],
|
||||
"close_index": [118, 151, 184, 199],
|
||||
"trade_duration": [123, 34, 31, 14]})
|
||||
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
|
||||
|
||||
@@ -23,8 +23,6 @@ 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())
|
||||
_HYPEROPT = Hyperopt(default_conf)
|
||||
_HYPEROPT_INITIALIZED = True
|
||||
@@ -63,9 +61,11 @@ 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())
|
||||
|
||||
args = [
|
||||
@@ -123,6 +123,7 @@ def test_loss_calculation_has_limited_profit(init_hyperopt) -> None:
|
||||
assert under > correct
|
||||
|
||||
|
||||
@pytest.mark.skip(reason="no way of currently testing this")
|
||||
def test_log_results_if_loss_improves(init_hyperopt, capsys) -> None:
|
||||
hyperopt = _HYPEROPT
|
||||
hyperopt.current_best_loss = 2
|
||||
@@ -135,7 +136,9 @@ def test_log_results_if_loss_improves(init_hyperopt, capsys) -> None:
|
||||
}
|
||||
)
|
||||
out, err = capsys.readouterr()
|
||||
assert ' 1/2: foo. Loss 1.00000'in out
|
||||
with capsys.disabled():
|
||||
print("out is: {}".format(out))
|
||||
assert ' 1/2: foo. Loss 1.00000'in out
|
||||
|
||||
|
||||
def test_no_log_if_loss_does_not_improve(init_hyperopt, caplog) -> None:
|
||||
@@ -182,7 +185,6 @@ def test_fmin_best_results(mocker, init_hyperopt, default_conf, caplog) -> None:
|
||||
|
||||
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'})
|
||||
@@ -227,7 +229,6 @@ def test_fmin_throw_value_error(mocker, init_hyperopt, default_conf, caplog) ->
|
||||
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'})
|
||||
@@ -253,7 +254,6 @@ def test_resuming_previous_hyperopt_results_succeeds(mocker, init_hyperopt, defa
|
||||
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'})
|
||||
|
||||
@@ -270,7 +270,6 @@ def test_resuming_previous_hyperopt_results_succeeds(mocker, init_hyperopt, defa
|
||||
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'})
|
||||
@@ -348,7 +347,6 @@ def test_start_calls_fmin(mocker, init_hyperopt, default_conf) -> None:
|
||||
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'})
|
||||
|
||||
@@ -360,35 +358,6 @@ def test_start_calls_fmin(mocker, init_hyperopt, default_conf) -> None:
|
||||
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)
|
||||
)
|
||||
|
||||
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()
|
||||
|
||||
|
||||
# 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):
|
||||
"""
|
||||
Test Hyperopt.format_results()
|
||||
@@ -400,7 +369,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)
|
||||
@@ -530,7 +499,7 @@ 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(
|
||||
|
||||
@@ -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']
|
||||
@@ -326,8 +326,6 @@ 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)
|
||||
assert {} == optimize.load_data(
|
||||
'',
|
||||
pairs=[],
|
||||
|
||||
@@ -13,6 +13,7 @@ from jsonschema import ValidationError
|
||||
|
||||
from freqtrade.arguments import Arguments
|
||||
from freqtrade.configuration import Configuration
|
||||
from freqtrade.constants import DEFAULT_DB_PROD_URL, DEFAULT_DB_DRYRUN_URL
|
||||
from freqtrade.tests.conftest import log_has
|
||||
from freqtrade import OperationalException
|
||||
|
||||
@@ -140,6 +141,43 @@ def test_load_config_with_params(default_conf, mocker) -> None:
|
||||
assert validated_conf.get('strategy_path') == '/some/path'
|
||||
assert validated_conf.get('db_url') == 'sqlite:///someurl'
|
||||
|
||||
conf = default_conf.copy()
|
||||
conf["dry_run"] = False
|
||||
del conf["db_url"]
|
||||
mocker.patch('freqtrade.configuration.open', mocker.mock_open(
|
||||
read_data=json.dumps(conf)
|
||||
))
|
||||
|
||||
arglist = [
|
||||
'--dynamic-whitelist', '10',
|
||||
'--strategy', 'TestStrategy',
|
||||
'--strategy-path', '/some/path'
|
||||
]
|
||||
args = Arguments(arglist, '').get_parsed_arg()
|
||||
|
||||
configuration = Configuration(args)
|
||||
validated_conf = configuration.load_config()
|
||||
assert validated_conf.get('db_url') == DEFAULT_DB_PROD_URL
|
||||
|
||||
# Test dry=run with ProdURL
|
||||
conf = default_conf.copy()
|
||||
conf["dry_run"] = True
|
||||
conf["db_url"] = DEFAULT_DB_PROD_URL
|
||||
mocker.patch('freqtrade.configuration.open', mocker.mock_open(
|
||||
read_data=json.dumps(conf)
|
||||
))
|
||||
|
||||
arglist = [
|
||||
'--dynamic-whitelist', '10',
|
||||
'--strategy', 'TestStrategy',
|
||||
'--strategy-path', '/some/path'
|
||||
]
|
||||
args = Arguments(arglist, '').get_parsed_arg()
|
||||
|
||||
configuration = Configuration(args)
|
||||
validated_conf = configuration.load_config()
|
||||
assert validated_conf.get('db_url') == DEFAULT_DB_DRYRUN_URL
|
||||
|
||||
|
||||
def test_load_custom_strategy(default_conf, mocker) -> None:
|
||||
"""
|
||||
@@ -310,7 +348,6 @@ def test_hyperopt_with_arguments(mocker, default_conf, caplog) -> None:
|
||||
arglist = [
|
||||
'hyperopt',
|
||||
'--epochs', '10',
|
||||
'--use-mongodb',
|
||||
'--spaces', 'all',
|
||||
]
|
||||
|
||||
@@ -324,10 +361,6 @@ def test_hyperopt_with_arguments(mocker, default_conf, caplog) -> None:
|
||||
assert log_has('Parameter --epochs detected ...', caplog.record_tuples)
|
||||
assert log_has('Will run Hyperopt with for 10 epochs ...', caplog.record_tuples)
|
||||
|
||||
assert 'mongodb' in config
|
||||
assert config['mongodb'] is True
|
||||
assert log_has('Parameter --use-mongodb detected ...', caplog.record_tuples)
|
||||
|
||||
assert 'spaces' in config
|
||||
assert config['spaces'] == ['all']
|
||||
assert log_has('Parameter -s/--spaces detected: [\'all\']', caplog.record_tuples)
|
||||
|
||||
@@ -40,7 +40,8 @@ def test_pair_convertion_object():
|
||||
assert pair_convertion.price == 30000.123
|
||||
|
||||
|
||||
def test_fiat_convert_is_supported():
|
||||
def test_fiat_convert_is_supported(mocker):
|
||||
patch_coinmarketcap(mocker)
|
||||
fiat_convert = CryptoToFiatConverter()
|
||||
assert fiat_convert._is_supported_fiat(fiat='USD') is True
|
||||
assert fiat_convert._is_supported_fiat(fiat='usd') is True
|
||||
@@ -48,7 +49,9 @@ def test_fiat_convert_is_supported():
|
||||
assert fiat_convert._is_supported_fiat(fiat='ABC') is False
|
||||
|
||||
|
||||
def test_fiat_convert_add_pair():
|
||||
def test_fiat_convert_add_pair(mocker):
|
||||
patch_coinmarketcap(mocker)
|
||||
|
||||
fiat_convert = CryptoToFiatConverter()
|
||||
|
||||
pair_len = len(fiat_convert._pairs)
|
||||
@@ -70,11 +73,8 @@ def test_fiat_convert_add_pair():
|
||||
|
||||
|
||||
def test_fiat_convert_find_price(mocker):
|
||||
api_mock = MagicMock(return_value={
|
||||
'price_usd': 12345.0,
|
||||
'price_eur': 13000.2
|
||||
})
|
||||
mocker.patch('freqtrade.fiat_convert.Market.ticker', api_mock)
|
||||
patch_coinmarketcap(mocker)
|
||||
|
||||
fiat_convert = CryptoToFiatConverter()
|
||||
|
||||
with pytest.raises(ValueError, match=r'The fiat ABC is not supported.'):
|
||||
@@ -92,17 +92,15 @@ def test_fiat_convert_find_price(mocker):
|
||||
|
||||
def test_fiat_convert_unsupported_crypto(mocker, caplog):
|
||||
mocker.patch('freqtrade.fiat_convert.CryptoToFiatConverter._cryptomap', return_value=[])
|
||||
patch_coinmarketcap(mocker)
|
||||
fiat_convert = CryptoToFiatConverter()
|
||||
assert fiat_convert._find_price(crypto_symbol='CRYPTO_123', fiat_symbol='EUR') == 0.0
|
||||
assert log_has('unsupported crypto-symbol CRYPTO_123 - returning 0.0', caplog.record_tuples)
|
||||
|
||||
|
||||
def test_fiat_convert_get_price(mocker):
|
||||
api_mock = MagicMock(return_value={
|
||||
'price_usd': 28000.0,
|
||||
'price_eur': 15000.0
|
||||
})
|
||||
mocker.patch('freqtrade.fiat_convert.Market.ticker', api_mock)
|
||||
patch_coinmarketcap(mocker)
|
||||
|
||||
mocker.patch('freqtrade.fiat_convert.CryptoToFiatConverter._find_price', return_value=28000.0)
|
||||
|
||||
fiat_convert = CryptoToFiatConverter()
|
||||
@@ -172,8 +170,9 @@ def test_fiat_init_network_exception(mocker):
|
||||
assert length_cryptomap == 0
|
||||
|
||||
|
||||
def test_fiat_convert_without_network():
|
||||
def test_fiat_convert_without_network(mocker):
|
||||
# Because CryptoToFiatConverter is a Singleton we reset the value of _coinmarketcap
|
||||
patch_coinmarketcap(mocker)
|
||||
|
||||
fiat_convert = CryptoToFiatConverter()
|
||||
|
||||
@@ -186,6 +185,7 @@ def test_fiat_convert_without_network():
|
||||
|
||||
|
||||
def test_convert_amount(mocker):
|
||||
patch_coinmarketcap(mocker)
|
||||
mocker.patch('freqtrade.fiat_convert.CryptoToFiatConverter.get_price', return_value=12345.0)
|
||||
|
||||
fiat_convert = CryptoToFiatConverter()
|
||||
|
||||
Reference in New Issue
Block a user