Merge branch 'develop' into feat/short

This commit is contained in:
Matthias
2021-08-07 09:42:25 +02:00
46 changed files with 422 additions and 204 deletions

View File

@@ -6,8 +6,8 @@
*/
"stake_currency": "BTC",
"stake_amount": 0.05,
"fiat_display_currency": "USD", // C++-style comment
"amount_reserve_percent" : 0.05, // And more, tabs before this comment
"fiat_display_currency": "USD", // C++-style comment
"amount_reserve_percent": 0.05, // And more, tabs before this comment
"dry_run": false,
"timeframe": "5m",
"trailing_stop": false,
@@ -15,15 +15,15 @@
"trailing_stop_positive_offset": 0.0051,
"trailing_only_offset_is_reached": false,
"minimal_roi": {
"40": 0.0,
"30": 0.01,
"20": 0.02,
"0": 0.04
"40": 0.0,
"30": 0.01,
"20": 0.02,
"0": 0.04
},
"stoploss": -0.10,
"unfilledtimeout": {
"buy": 10,
"sell": 30, // Trailing comma should also be accepted now
"sell": 30, // Trailing comma should also be accepted now
},
"bid_strategy": {
"use_order_book": false,
@@ -34,7 +34,7 @@
"bids_to_ask_delta": 1
}
},
"ask_strategy":{
"ask_strategy": {
"use_order_book": false,
"order_book_min": 1,
"order_book_max": 9
@@ -64,7 +64,9 @@
"key": "your_exchange_key",
"secret": "your_exchange_secret",
"password": "",
"ccxt_config": {"enableRateLimit": true},
"ccxt_config": {
"enableRateLimit": true
},
"ccxt_async_config": {
"enableRateLimit": false,
"rateLimit": 500,
@@ -103,8 +105,8 @@
"remove_pumps": false
},
"telegram": {
// We can now comment out some settings
// "enabled": true,
// We can now comment out some settings
// "enabled": true,
"enabled": false,
"token": "your_telegram_token",
"chat_id": "your_telegram_chat_id"
@@ -124,4 +126,4 @@
},
"strategy": "DefaultStrategy",
"strategy_path": "user_data/strategies/"
}
}

View File

@@ -399,7 +399,7 @@ def test_hyperopt_format_results(hyperopt):
'rejected_signals': 2,
'backtest_start_time': 1619718665,
'backtest_end_time': 1619718665,
}
}
results_metrics = generate_strategy_stats({'XRP/BTC': None}, '', bt_result,
Arrow(2017, 11, 14, 19, 32, 00),
Arrow(2017, 12, 14, 19, 32, 00), market_change=0)
@@ -577,6 +577,7 @@ def test_generate_optimizer(mocker, hyperopt_conf) -> None:
"20.0": 0.02,
"50.0": 0.01,
"110.0": 0},
'protection': {},
'sell': {'sell-adx-enabled': False,
'sell-adx-value': 0,
'sell-fastd-enabled': True,
@@ -592,7 +593,7 @@ def test_generate_optimizer(mocker, hyperopt_conf) -> None:
'trailing_stop_positive': 0.02,
'trailing_stop_positive_offset': 0.07}},
'params_dict': optimizer_param,
'params_not_optimized': {'buy': {}, 'sell': {}},
'params_not_optimized': {'buy': {}, 'protection': {}, 'sell': {}},
'results_metrics': ANY,
'total_profit': 3.1e-08
}
@@ -1002,6 +1003,8 @@ def test_in_strategy_auto_hyperopt(mocker, hyperopt_conf, tmpdir, fee) -> None:
hyperopt_conf.update({
'strategy': 'HyperoptableStrategy',
'user_data_dir': Path(tmpdir),
'hyperopt_random_state': 42,
'spaces': ['all']
})
hyperopt = Hyperopt(hyperopt_conf)
assert isinstance(hyperopt.custom_hyperopt, HyperOptAuto)
@@ -1009,12 +1012,18 @@ def test_in_strategy_auto_hyperopt(mocker, hyperopt_conf, tmpdir, fee) -> None:
assert hyperopt.backtesting.strategy.buy_rsi.in_space is True
assert hyperopt.backtesting.strategy.buy_rsi.value == 35
assert hyperopt.backtesting.strategy.sell_rsi.value == 74
assert hyperopt.backtesting.strategy.protection_cooldown_lookback.value == 30
buy_rsi_range = hyperopt.backtesting.strategy.buy_rsi.range
assert isinstance(buy_rsi_range, range)
# Range from 0 - 50 (inclusive)
assert len(list(buy_rsi_range)) == 51
hyperopt.start()
# All values should've changed.
assert hyperopt.backtesting.strategy.protection_cooldown_lookback.value != 30
assert hyperopt.backtesting.strategy.buy_rsi.value != 35
assert hyperopt.backtesting.strategy.sell_rsi.value != 74
def test_SKDecimal():

View File

@@ -93,7 +93,7 @@ def test_stoploss_guard(mocker, default_conf, fee, caplog):
Trade.query.session.add(generate_mock_trade(
'XRP/BTC', fee.return_value, False, sell_reason=SellType.STOP_LOSS.value,
min_ago_open=200, min_ago_close=30,
))
))
assert not freqtrade.protections.global_stop()
assert not log_has_re(message, caplog)
@@ -150,7 +150,7 @@ def test_stoploss_guard_perpair(mocker, default_conf, fee, caplog, only_per_pair
Trade.query.session.add(generate_mock_trade(
pair, fee.return_value, False, sell_reason=SellType.STOP_LOSS.value,
min_ago_open=200, min_ago_close=30, profit_rate=0.9,
))
))
assert not freqtrade.protections.stop_per_pair(pair)
assert not freqtrade.protections.global_stop()

View File

@@ -139,9 +139,9 @@ def test_fiat_too_many_requests_response(mocker, caplog):
assert length_cryptomap == 0
assert fiat_convert._backoff > datetime.datetime.now().timestamp()
assert log_has(
'Too many requests for Coingecko API, backing off and trying again later.',
caplog
)
'Too many requests for Coingecko API, backing off and trying again later.',
caplog
)
def test_fiat_invalid_response(mocker, caplog):

View File

@@ -942,7 +942,7 @@ def test_api_whitelist(botclient):
"whitelist": ['ETH/BTC', 'LTC/BTC', 'XRP/BTC', 'NEO/BTC'],
"length": 4,
"method": ["StaticPairList"]
}
}
def test_api_forcebuy(botclient, mocker, fee):
@@ -1033,7 +1033,7 @@ def test_api_forcebuy(botclient, mocker, fee):
'buy_tag': None,
'timeframe': 5,
'exchange': 'binance',
}
}
def test_api_forcesell(botclient, mocker, ticker, fee, markets):
@@ -1215,7 +1215,7 @@ def test_api_strategies(botclient):
'DefaultStrategy',
'HyperoptableStrategy',
'TestStrategyLegacy'
]}
]}
def test_api_strategy(botclient):

View File

@@ -4,7 +4,8 @@ import talib.abstract as ta
from pandas import DataFrame
import freqtrade.vendor.qtpylib.indicators as qtpylib
from freqtrade.strategy import DecimalParameter, IntParameter, IStrategy, RealParameter
from freqtrade.strategy import (BooleanParameter, DecimalParameter, IntParameter, IStrategy,
RealParameter)
class HyperoptableStrategy(IStrategy):
@@ -64,6 +65,18 @@ class HyperoptableStrategy(IStrategy):
sell_rsi = IntParameter(low=50, high=100, default=70, space='sell')
sell_minusdi = DecimalParameter(low=0, high=1, default=0.5001, decimals=3, space='sell',
load=False)
protection_enabled = BooleanParameter(default=True)
protection_cooldown_lookback = IntParameter([0, 50], default=30)
@property
def protections(self):
prot = []
if self.protection_enabled.value:
prot.append({
"method": "CooldownPeriod",
"stop_duration_candles": self.protection_cooldown_lookback.value
})
return prot
def informative_pairs(self):
"""

View File

@@ -16,8 +16,8 @@ from freqtrade.exceptions import OperationalException, StrategyError
from freqtrade.optimize.space import SKDecimal
from freqtrade.persistence import PairLocks, Trade
from freqtrade.resolvers import StrategyResolver
from freqtrade.strategy.hyper import (BaseParameter, CategoricalParameter, DecimalParameter,
IntParameter, RealParameter)
from freqtrade.strategy.hyper import (BaseParameter, BooleanParameter, CategoricalParameter,
DecimalParameter, IntParameter, RealParameter)
from freqtrade.strategy.interface import SellCheckTuple
from freqtrade.strategy.strategy_wrapper import strategy_safe_wrapper
from tests.conftest import log_has, log_has_re
@@ -717,6 +717,17 @@ def test_hyperopt_parameters():
assert len(list(catpar.range)) == 3
assert list(catpar.range) == ['buy_rsi', 'buy_macd', 'buy_none']
boolpar = BooleanParameter(default=True, space='buy')
assert boolpar.value is True
assert isinstance(boolpar.get_space(''), Categorical)
assert isinstance(boolpar.range, list)
assert len(list(boolpar.range)) == 1
boolpar.in_space = True
assert len(list(boolpar.range)) == 2
assert list(boolpar.range) == [True, False]
def test_auto_hyperopt_interface(default_conf):
default_conf.update({'strategy': 'HyperoptableStrategy'})
@@ -734,7 +745,8 @@ def test_auto_hyperopt_interface(default_conf):
assert isinstance(all_params, dict)
assert len(all_params['buy']) == 2
assert len(all_params['sell']) == 2
assert all_params['count'] == 4
# Number of Hyperoptable parameters
assert all_params['count'] == 6
strategy.__class__.sell_rsi = IntParameter([0, 10], default=5, space='buy')

View File

@@ -125,7 +125,7 @@ def test_parse_args_backtesting_custom() -> None:
'--strategy-list',
'DefaultStrategy',
'SampleStrategy'
]
]
call_args = Arguments(args).get_parsed_arg()
assert call_args['config'] == ['test_conf.json']
assert call_args['verbosity'] == 0

View File

@@ -1130,17 +1130,17 @@ def test_pairlist_resolving_fallback(mocker):
@pytest.mark.parametrize("setting", [
("ask_strategy", "use_sell_signal", True,
None, "use_sell_signal", False),
("ask_strategy", "sell_profit_only", True,
None, "sell_profit_only", False),
("ask_strategy", "sell_profit_offset", 0.1,
None, "sell_profit_offset", 0.01),
("ask_strategy", "ignore_roi_if_buy_signal", True,
None, "ignore_roi_if_buy_signal", False),
("ask_strategy", "ignore_buying_expired_candle_after", 5,
None, "ignore_buying_expired_candle_after", 6),
])
("ask_strategy", "use_sell_signal", True,
None, "use_sell_signal", False),
("ask_strategy", "sell_profit_only", True,
None, "sell_profit_only", False),
("ask_strategy", "sell_profit_offset", 0.1,
None, "sell_profit_offset", 0.01),
("ask_strategy", "ignore_roi_if_buy_signal", True,
None, "ignore_roi_if_buy_signal", False),
("ask_strategy", "ignore_buying_expired_candle_after", 5,
None, "ignore_buying_expired_candle_after", 6),
])
def test_process_temporary_deprecated_settings(mocker, default_conf, setting, caplog):
patched_configuration_load_config_file(mocker, default_conf)
@@ -1180,10 +1180,10 @@ def test_process_temporary_deprecated_settings(mocker, default_conf, setting, ca
@pytest.mark.parametrize("setting", [
("experimental", "use_sell_signal", False),
("experimental", "sell_profit_only", True),
("experimental", "ignore_roi_if_buy_signal", True),
])
("experimental", "use_sell_signal", False),
("experimental", "sell_profit_only", True),
("experimental", "ignore_roi_if_buy_signal", True),
])
def test_process_removed_settings(mocker, default_conf, setting):
patched_configuration_load_config_file(mocker, default_conf)
@@ -1330,7 +1330,7 @@ def test_process_removed_setting(mocker, default_conf, caplog):
'sectionB', 'somesetting')
def test_process_deprecated_ticker_interval(mocker, default_conf, caplog):
def test_process_deprecated_ticker_interval(default_conf, caplog):
message = "DEPRECATED: Please use 'timeframe' instead of 'ticker_interval."
config = deepcopy(default_conf)
process_temporary_deprecated_settings(config)
@@ -1352,6 +1352,17 @@ def test_process_deprecated_ticker_interval(mocker, default_conf, caplog):
process_temporary_deprecated_settings(config)
def test_process_deprecated_protections(default_conf, caplog):
message = "DEPRECATED: Setting 'protections' in the configuration is deprecated."
config = deepcopy(default_conf)
process_temporary_deprecated_settings(config)
assert not log_has(message, caplog)
config['protections'] = []
process_temporary_deprecated_settings(config)
assert log_has(message, caplog)
def test_flat_vars_to_nested_dict(caplog):
test_args = {