Merge branch 'develop' into dev-merge-rl

This commit is contained in:
robcaulk
2022-09-22 19:46:50 +02:00
121 changed files with 1525 additions and 564 deletions

View File

@@ -2282,7 +2282,7 @@ def tickers():
@pytest.fixture
def result(testdatadir):
def dataframe_1m(testdatadir):
with (testdatadir / 'UNITTEST_BTC-1m.json').open('r') as data_file:
return ohlcv_to_dataframe(json.load(data_file), '1m', pair="UNITTEST/BTC",
fill_missing=True)

View File

@@ -18,8 +18,8 @@ from tests.conftest import log_has, log_has_re
from tests.data.test_history import _clean_test_file
def test_dataframe_correct_columns(result):
assert result.columns.tolist() == ['date', 'open', 'high', 'low', 'close', 'volume']
def test_dataframe_correct_columns(dataframe_1m):
assert dataframe_1m.columns.tolist() == ['date', 'open', 'high', 'low', 'close', 'volume']
def test_ohlcv_to_dataframe(ohlcv_history_list, caplog):

View File

@@ -23,7 +23,7 @@ from tests.exchange.test_exchange import ccxt_exceptionhandlers
def test_stoploss_order_binance(default_conf, mocker, limitratio, expected, side, trademode):
api_mock = MagicMock()
order_id = 'test_prod_buy_{}'.format(randint(0, 10 ** 6))
order_type = 'stop_loss_limit' if trademode == TradingMode.SPOT else 'stop'
order_type = 'stop_loss_limit' if trademode == TradingMode.SPOT else 'limit'
api_mock.create_order = MagicMock(return_value={
'id': order_id,
@@ -45,12 +45,15 @@ def test_stoploss_order_binance(default_conf, mocker, limitratio, expected, side
amount=1,
stop_price=190,
side=side,
order_types={'stoploss_on_exchange_limit_ratio': 1.05},
order_types={'stoploss': 'limit', 'stoploss_on_exchange_limit_ratio': 1.05},
leverage=1.0
)
api_mock.create_order.reset_mock()
order_types = {} if limitratio is None else {'stoploss_on_exchange_limit_ratio': limitratio}
order_types = {'stoploss': 'limit'}
if limitratio is not None:
order_types.update({'stoploss_on_exchange_limit_ratio': limitratio})
order = exchange.stoploss(
pair='ETH/BTC',
amount=1,

View File

@@ -297,7 +297,7 @@ class TestCCXTExchange():
def test_ccxt__async_get_candle_history(self, exchange):
exchange, exchangename = exchange
# For some weired reason, this test returns random lengths for bittrex.
if not exchange._ft_has['ohlcv_has_history'] or exchangename in ('bittrex', 'gateio'):
if not exchange._ft_has['ohlcv_has_history'] or exchangename in ('bittrex'):
return
pair = EXCHANGES[exchangename]['pair']
timeframe = EXCHANGES[exchangename]['timeframe']

View File

@@ -472,7 +472,7 @@ def test_load_leverage_tiers_okx(default_conf, mocker, markets, tmpdir, caplog,
api_mock.fetch_market_leverage_tiers.call_count == 0
# 2 day passes ...
time_machine.move_to(datetime.now() + timedelta(days=2))
time_machine.move_to(datetime.now() + timedelta(weeks=5))
exchange.load_leverage_tiers()
assert log_has(logmsg, caplog)

View File

@@ -8,6 +8,7 @@ import pytest
from freqtrade.configuration import TimeRange
from freqtrade.data.dataprovider import DataProvider
from freqtrade.freqai.data_kitchen import FreqaiDataKitchen
from freqtrade.plugins.pairlistmanager import PairListManager
from tests.conftest import get_patched_exchange, log_has_re
from tests.freqai.conftest import get_patched_freqai_strategy
@@ -127,6 +128,7 @@ def test_extract_data_and_train_model_MultiTargets(mocker, freqai_conf, model):
@pytest.mark.parametrize('model', [
'LightGBMClassifier',
'CatboostClassifier',
'XGBoostClassifier',
])
def test_extract_data_and_train_model_Classifiers(mocker, freqai_conf, model):
if is_arm() and model == 'CatboostClassifier':
@@ -342,3 +344,62 @@ def test_principal_component_analysis(mocker, freqai_conf):
assert Path(freqai.dk.data_path / f"{freqai.dk.model_filename}_pca_object.pkl")
shutil.rmtree(Path(freqai.dk.full_path))
def test_plot_feature_importance(mocker, freqai_conf):
from freqtrade.freqai.utils import plot_feature_importance
freqai_conf.update({"timerange": "20180110-20180130"})
freqai_conf.get("freqai", {}).get("feature_parameters", {}).update(
{"princpial_component_analysis": "true"})
strategy = get_patched_freqai_strategy(mocker, freqai_conf)
exchange = get_patched_exchange(mocker, freqai_conf)
strategy.dp = DataProvider(freqai_conf, exchange)
strategy.freqai_info = freqai_conf.get("freqai", {})
freqai = strategy.freqai
freqai.live = True
freqai.dk = FreqaiDataKitchen(freqai_conf)
timerange = TimeRange.parse_timerange("20180110-20180130")
freqai.dd.load_all_pair_histories(timerange, freqai.dk)
freqai.dd.pair_dict = MagicMock()
data_load_timerange = TimeRange.parse_timerange("20180110-20180130")
new_timerange = TimeRange.parse_timerange("20180120-20180130")
freqai.extract_data_and_train_model(
new_timerange, "ADA/BTC", strategy, freqai.dk, data_load_timerange)
model = freqai.dd.load_data("ADA/BTC", freqai.dk)
plot_feature_importance(model, "ADA/BTC", freqai.dk)
assert Path(freqai.dk.data_path / f"{freqai.dk.model_filename}.html")
shutil.rmtree(Path(freqai.dk.full_path))
@pytest.mark.parametrize('timeframes,corr_pairs', [
(['5m'], ['ADA/BTC', 'DASH/BTC']),
(['5m'], ['ADA/BTC', 'DASH/BTC', 'ETH/USDT']),
(['5m', '15m'], ['ADA/BTC', 'DASH/BTC', 'ETH/USDT']),
])
def test_freqai_informative_pairs(mocker, freqai_conf, timeframes, corr_pairs):
freqai_conf['freqai']['feature_parameters'].update({
'include_timeframes': timeframes,
'include_corr_pairlist': corr_pairs,
})
strategy = get_patched_freqai_strategy(mocker, freqai_conf)
exchange = get_patched_exchange(mocker, freqai_conf)
pairlists = PairListManager(exchange, freqai_conf)
strategy.dp = DataProvider(freqai_conf, exchange, pairlists)
pairlist = strategy.dp.current_whitelist()
pairs_a = strategy.informative_pairs()
assert len(pairs_a) == 0
pairs_b = strategy.gather_informative_pairs()
# we expect unique pairs * timeframes
assert len(pairs_b) == len(set(pairlist + corr_pairs)) * len(timeframes)

View File

@@ -922,6 +922,45 @@ def test_in_strategy_auto_hyperopt_with_parallel(mocker, hyperopt_conf, tmpdir,
hyperopt.start()
def test_in_strategy_auto_hyperopt_per_epoch(mocker, hyperopt_conf, tmpdir, fee) -> None:
patch_exchange(mocker)
mocker.patch('freqtrade.exchange.Exchange.get_fee', fee)
(Path(tmpdir) / 'hyperopt_results').mkdir(parents=True)
hyperopt_conf.update({
'strategy': 'HyperoptableStrategy',
'user_data_dir': Path(tmpdir),
'hyperopt_random_state': 42,
'spaces': ['all'],
'epochs': 3,
'analyze_per_epoch': True,
})
go = mocker.patch('freqtrade.optimize.hyperopt.Hyperopt.generate_optimizer',
return_value={
'loss': 0.05,
'results_explanation': 'foo result', 'params': {},
'results_metrics': generate_result_metrics(),
})
hyperopt = Hyperopt(hyperopt_conf)
hyperopt.backtesting.exchange.get_max_leverage = MagicMock(return_value=1.0)
assert isinstance(hyperopt.custom_hyperopt, HyperOptAuto)
assert isinstance(hyperopt.backtesting.strategy.buy_rsi, IntParameter)
assert hyperopt.backtesting.strategy.bot_loop_started is True
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()
# backtesting should be called 3 times (once per epoch)
assert go.call_count == 3
def test_SKDecimal():
space = SKDecimal(1, 2, decimals=2)
assert 1.5 in space

View File

@@ -467,6 +467,10 @@ def test_VolumePairList_refresh_empty(mocker, markets_empty, whitelist_conf):
{"method": "RangeStabilityFilter", "lookback_days": 10,
"max_rate_of_change": 0.01, "refresh_period": 1440}],
"BTC", []), # All removed because of max_rate_of_change being 0.017
([{"method": "StaticPairList"},
{"method": "RangeStabilityFilter", "lookback_days": 10,
"min_rate_of_change": 0.018, "max_rate_of_change": 0.02, "refresh_period": 1440}],
"BTC", []), # All removed - limits are above the highest change_rate
([{"method": "StaticPairList"},
{"method": "VolatilityFilter", "lookback_days": 3,
"min_volatility": 0.002, "max_volatility": 0.004, "refresh_period": 1440}],

View File

@@ -82,6 +82,21 @@ def test_send_msg_telegram_disabled(mocker, default_conf, caplog) -> None:
assert telegram_mock.call_count == 0
def test_send_msg_telegram_error(mocker, default_conf, caplog) -> None:
mocker.patch('freqtrade.rpc.telegram.Telegram._init', MagicMock())
mocker.patch('freqtrade.rpc.telegram.Telegram.send_msg', side_effect=ValueError())
freqtradebot = get_patched_freqtradebot(mocker, default_conf)
rpc_manager = RPCManager(freqtradebot)
rpc_manager.send_msg({
'type': RPCMessageType.STATUS,
'status': 'test'
})
assert log_has("Sending rpc message: {'type': status, 'status': 'test'}", caplog)
assert log_has("Exception occurred within RPC module telegram", caplog)
def test_process_msg_queue(mocker, default_conf, caplog) -> None:
telegram_mock = mocker.patch('freqtrade.rpc.telegram.Telegram.send_msg')
mocker.patch('freqtrade.rpc.telegram.Telegram._init')

View File

@@ -959,6 +959,7 @@ def test_telegram_forceexit_handle(default_conf, update, ticker, fee,
'gain': 'profit',
'leverage': 1.0,
'limit': 1.173e-05,
'order_rate': 1.173e-05,
'amount': 91.07468123,
'order_type': 'limit',
'open_rate': 1.098e-05,
@@ -1031,6 +1032,7 @@ def test_telegram_force_exit_down_handle(default_conf, update, ticker, fee,
'gain': 'loss',
'leverage': 1.0,
'limit': 1.043e-05,
'order_rate': 1.043e-05,
'amount': 91.07468123,
'order_type': 'limit',
'open_rate': 1.098e-05,
@@ -1092,6 +1094,7 @@ def test_forceexit_all_handle(default_conf, update, ticker, fee, mocker) -> None
'pair': 'ETH/BTC',
'gain': 'loss',
'leverage': 1.0,
'order_rate': 1.099e-05,
'limit': 1.099e-05,
'amount': 91.07468123,
'order_type': 'limit',
@@ -1744,7 +1747,7 @@ def test_send_msg_enter_notification(default_conf, mocker, caplog, message_type,
'exchange': 'Binance',
'pair': 'ETH/BTC',
'leverage': leverage,
'limit': 1.099e-05,
'open_rate': 1.099e-05,
'order_type': 'limit',
'direction': enter,
'stake_amount': 0.01465333,
@@ -1915,7 +1918,7 @@ def test_send_msg_sell_notification(default_conf, mocker) -> None:
'leverage': 1.0,
'direction': 'Long',
'gain': 'loss',
'limit': 3.201e-05,
'order_rate': 3.201e-05,
'amount': 1333.3333333333335,
'order_type': 'market',
'open_rate': 7.5e-05,
@@ -1950,7 +1953,7 @@ def test_send_msg_sell_notification(default_conf, mocker) -> None:
'pair': 'KEY/ETH',
'direction': 'Long',
'gain': 'loss',
'limit': 3.201e-05,
'order_rate': 3.201e-05,
'amount': 1333.3333333333335,
'order_type': 'market',
'open_rate': 7.5e-05,
@@ -1989,7 +1992,7 @@ def test_send_msg_sell_notification(default_conf, mocker) -> None:
'pair': 'KEY/ETH',
'direction': 'Long',
'gain': 'loss',
'limit': 3.201e-05,
'order_rate': 3.201e-05,
'amount': 1333.3333333333335,
'order_type': 'market',
'open_rate': 7.5e-05,
@@ -2162,7 +2165,7 @@ def test_send_msg_buy_notification_no_fiat(
'exchange': 'Binance',
'pair': 'ETH/BTC',
'leverage': leverage,
'limit': 1.099e-05,
'open_rate': 1.099e-05,
'order_type': 'limit',
'direction': enter,
'stake_amount': 0.01465333,
@@ -2205,7 +2208,7 @@ def test_send_msg_sell_notification_no_fiat(
'gain': 'loss',
'leverage': leverage,
'direction': direction,
'limit': 3.201e-05,
'order_rate': 3.201e-05,
'amount': 1333.3333333333335,
'order_type': 'limit',
'open_rate': 7.5e-05,

View File

@@ -43,19 +43,6 @@ class freqai_test_multimodel_strat(IStrategy):
)
max_roi_time_long = IntParameter(0, 800, default=400, space="sell", optimize=False, load=True)
def informative_pairs(self):
whitelist_pairs = self.dp.current_whitelist()
corr_pairs = self.config["freqai"]["feature_parameters"]["include_corr_pairlist"]
informative_pairs = []
for tf in self.config["freqai"]["feature_parameters"]["include_timeframes"]:
for pair in whitelist_pairs:
informative_pairs.append((pair, tf))
for pair in corr_pairs:
if pair in whitelist_pairs:
continue # avoid duplication
informative_pairs.append((pair, tf))
return informative_pairs
def populate_any_indicators(
self, pair, df, tf, informative=None, set_generalized_indicators=False
):

View File

@@ -43,19 +43,6 @@ class freqai_test_strat(IStrategy):
)
max_roi_time_long = IntParameter(0, 800, default=400, space="sell", optimize=False, load=True)
def informative_pairs(self):
whitelist_pairs = self.dp.current_whitelist()
corr_pairs = self.config["freqai"]["feature_parameters"]["include_corr_pairlist"]
informative_pairs = []
for tf in self.config["freqai"]["feature_parameters"]["include_timeframes"]:
for pair in whitelist_pairs:
informative_pairs.append((pair, tf))
for pair in corr_pairs:
if pair in whitelist_pairs:
continue # avoid duplication
informative_pairs.append((pair, tf))
return informative_pairs
def populate_any_indicators(
self, pair, df, tf, informative=None, set_generalized_indicators=False
):

View File

@@ -21,14 +21,14 @@ def test_strategy_test_v3_structure():
(True, 'short'),
(False, 'long'),
])
def test_strategy_test_v3(result, fee, is_short, side):
def test_strategy_test_v3(dataframe_1m, fee, is_short, side):
strategy = StrategyTestV3({})
metadata = {'pair': 'ETH/BTC'}
assert type(strategy.minimal_roi) is dict
assert type(strategy.stoploss) is float
assert type(strategy.timeframe) is str
indicators = strategy.populate_indicators(result, metadata)
indicators = strategy.populate_indicators(dataframe_1m, metadata)
assert type(indicators) is DataFrame
assert type(strategy.populate_buy_trend(indicators, metadata)) is DataFrame
assert type(strategy.populate_sell_trend(indicators, metadata)) is DataFrame

View File

@@ -53,7 +53,7 @@ def test_search_all_strategies_with_failed():
assert len(strategies) == 0
def test_load_strategy(default_conf, result):
def test_load_strategy(default_conf, dataframe_1m):
default_conf.update({'strategy': 'SampleStrategy',
'strategy_path': str(Path(__file__).parents[2] / 'freqtrade/templates')
})
@@ -61,22 +61,22 @@ def test_load_strategy(default_conf, result):
assert isinstance(strategy.__source__, str)
assert 'class SampleStrategy' in strategy.__source__
assert isinstance(strategy.__file__, str)
assert 'rsi' in strategy.advise_indicators(result, {'pair': 'ETH/BTC'})
assert 'rsi' in strategy.advise_indicators(dataframe_1m, {'pair': 'ETH/BTC'})
def test_load_strategy_base64(result, caplog, default_conf):
def test_load_strategy_base64(dataframe_1m, caplog, default_conf):
filepath = Path(__file__).parents[2] / 'freqtrade/templates/sample_strategy.py'
encoded_string = urlsafe_b64encode(filepath.read_bytes()).decode("utf-8")
default_conf.update({'strategy': 'SampleStrategy:{}'.format(encoded_string)})
strategy = StrategyResolver.load_strategy(default_conf)
assert 'rsi' in strategy.advise_indicators(result, {'pair': 'ETH/BTC'})
assert 'rsi' in strategy.advise_indicators(dataframe_1m, {'pair': 'ETH/BTC'})
# Make sure strategy was loaded from base64 (using temp directory)!!
assert log_has_re(r"Using resolved strategy SampleStrategy from '"
r".*(/|\\).*(/|\\)SampleStrategy\.py'\.\.\.", caplog)
def test_load_strategy_invalid_directory(result, caplog, default_conf):
def test_load_strategy_invalid_directory(caplog, default_conf):
default_conf['strategy'] = 'StrategyTestV3'
extra_dir = Path.cwd() / 'some/path'
with pytest.raises(OperationalException):
@@ -104,7 +104,7 @@ def test_load_strategy_noname(default_conf):
@pytest.mark.filterwarnings("ignore:deprecated")
@pytest.mark.parametrize('strategy_name', ['StrategyTestV2'])
def test_strategy_pre_v3(result, default_conf, strategy_name):
def test_strategy_pre_v3(dataframe_1m, default_conf, strategy_name):
default_conf.update({'strategy': strategy_name})
strategy = StrategyResolver.load_strategy(default_conf)
@@ -118,7 +118,7 @@ def test_strategy_pre_v3(result, default_conf, strategy_name):
assert strategy.timeframe == '5m'
assert default_conf['timeframe'] == '5m'
df_indicators = strategy.advise_indicators(result, metadata=metadata)
df_indicators = strategy.advise_indicators(dataframe_1m, metadata=metadata)
assert 'adx' in df_indicators
dataframe = strategy.advise_entry(df_indicators, metadata=metadata)
@@ -417,24 +417,24 @@ def test_call_deprecated_function(default_conf):
StrategyResolver.load_strategy(default_conf)
def test_strategy_interface_versioning(result, default_conf):
def test_strategy_interface_versioning(dataframe_1m, default_conf):
default_conf.update({'strategy': 'StrategyTestV2'})
strategy = StrategyResolver.load_strategy(default_conf)
metadata = {'pair': 'ETH/BTC'}
assert strategy.INTERFACE_VERSION == 2
indicator_df = strategy.advise_indicators(result, metadata=metadata)
indicator_df = strategy.advise_indicators(dataframe_1m, metadata=metadata)
assert isinstance(indicator_df, DataFrame)
assert 'adx' in indicator_df.columns
enterdf = strategy.advise_entry(result, metadata=metadata)
enterdf = strategy.advise_entry(dataframe_1m, metadata=metadata)
assert isinstance(enterdf, DataFrame)
assert 'buy' not in enterdf.columns
assert 'enter_long' in enterdf.columns
exitdf = strategy.advise_exit(result, metadata=metadata)
exitdf = strategy.advise_exit(dataframe_1m, metadata=metadata)
assert isinstance(exitdf, DataFrame)
assert 'sell' not in exitdf
assert 'exit_long' in exitdf

View File

@@ -1427,6 +1427,7 @@ def test_handle_stoploss_on_exchange_trailing(
trade.is_open = True
trade.open_order_id = None
trade.stoploss_order_id = 100
trade.stoploss_last_update = arrow.utcnow().shift(minutes=-20).datetime
stoploss_order_hanging = MagicMock(return_value={
'id': 100,
@@ -1456,7 +1457,7 @@ def test_handle_stoploss_on_exchange_trailing(
)
cancel_order_mock = MagicMock()
stoploss_order_mock = MagicMock(return_value={'id': 13434334})
stoploss_order_mock = MagicMock(return_value={'id': 'so1'})
mocker.patch('freqtrade.exchange.Binance.cancel_stoploss_order', cancel_order_mock)
mocker.patch('freqtrade.exchange.Binance.stoploss', stoploss_order_mock)
@@ -1569,6 +1570,7 @@ def test_handle_stoploss_on_exchange_trailing_error(
assert stoploss.call_count == 1
# Fail creating stoploss order
trade.stoploss_last_update = arrow.utcnow().shift(minutes=-601).datetime
caplog.clear()
cancel_mock = mocker.patch("freqtrade.exchange.Binance.cancel_stoploss_order", MagicMock())
mocker.patch("freqtrade.exchange.Binance.stoploss", side_effect=ExchangeError())
@@ -1657,6 +1659,7 @@ def test_handle_stoploss_on_exchange_custom_stop(
trade.is_open = True
trade.open_order_id = None
trade.stoploss_order_id = 100
trade.stoploss_last_update = arrow.utcnow().shift(minutes=-601).datetime
stoploss_order_hanging = MagicMock(return_value={
'id': 100,
@@ -1685,7 +1688,7 @@ def test_handle_stoploss_on_exchange_custom_stop(
)
cancel_order_mock = MagicMock()
stoploss_order_mock = MagicMock(return_value={'id': 13434334})
stoploss_order_mock = MagicMock(return_value={'id': 'so1'})
mocker.patch('freqtrade.exchange.Binance.cancel_stoploss_order', cancel_order_mock)
mocker.patch('freqtrade.exchange.Binance.stoploss', stoploss_order_mock)
@@ -1727,8 +1730,7 @@ def test_handle_stoploss_on_exchange_custom_stop(
assert freqtrade.handle_trade(trade) is True
def test_tsl_on_exchange_compatible_with_edge(mocker, edge_conf, fee, caplog,
limit_order) -> None:
def test_tsl_on_exchange_compatible_with_edge(mocker, edge_conf, fee, limit_order) -> None:
enter_order = limit_order['buy']
exit_order = limit_order['sell']
@@ -1784,6 +1786,7 @@ def test_tsl_on_exchange_compatible_with_edge(mocker, edge_conf, fee, caplog,
trade.is_open = True
trade.open_order_id = None
trade.stoploss_order_id = 100
trade.stoploss_last_update = arrow.utcnow()
stoploss_order_hanging = MagicMock(return_value={
'id': 100,
@@ -3253,6 +3256,7 @@ def test_execute_trade_exit_up(default_conf_usdt, ticker_usdt, fee, ticker_usdt_
'pair': 'ETH/USDT',
'gain': 'profit',
'limit': 2.0 if is_short else 2.2,
'order_rate': 2.0 if is_short else 2.2,
'amount': pytest.approx(amt),
'order_type': 'limit',
'buy_tag': None,
@@ -3318,6 +3322,7 @@ def test_execute_trade_exit_down(default_conf_usdt, ticker_usdt, fee, ticker_usd
'leverage': 1.0,
'gain': 'loss',
'limit': 2.2 if is_short else 2.01,
'order_rate': 2.2 if is_short else 2.01,
'amount': pytest.approx(29.70297029) if is_short else 30.0,
'order_type': 'limit',
'buy_tag': None,
@@ -3402,6 +3407,7 @@ def test_execute_trade_exit_custom_exit_price(
'leverage': 1.0,
'gain': profit_or_loss,
'limit': limit,
'order_rate': limit,
'amount': pytest.approx(amount),
'order_type': 'limit',
'buy_tag': None,
@@ -3473,6 +3479,7 @@ def test_execute_trade_exit_down_stoploss_on_exchange_dry_run(
'leverage': 1.0,
'gain': 'loss',
'limit': 2.02 if is_short else 1.98,
'order_rate': 2.02 if is_short else 1.98,
'amount': pytest.approx(29.70297029 if is_short else 30.0),
'order_type': 'limit',
'buy_tag': None,
@@ -3738,6 +3745,7 @@ def test_execute_trade_exit_market_order(
'leverage': 1.0,
'gain': profit_or_loss,
'limit': limit,
'order_rate': limit,
'amount': pytest.approx(amount),
'order_type': 'market',
'buy_tag': None,

View File

@@ -521,4 +521,4 @@ def test_dca_exiting(default_conf_usdt, ticker_usdt, fee, mocker, caplog) -> Non
assert trade.orders[-1].ft_order_side == 'sell'
assert pytest.approx(trade.stake_amount) == 40.198
assert trade.is_open
assert log_has_re('Amount to sell is 0.0 due to exchange limits - not selling.', caplog)
assert log_has_re('Amount to exit is 0.0 due to exchange limits - not exiting.', caplog)

View File

@@ -184,8 +184,8 @@ def test_render_template_fallback(mocker):
templatefile='subtemplates/indicators_does-not-exist.j2',)
val = render_template_with_fallback(
templatefile='subtemplates/indicators_does-not-exist.j2',
templatefallbackfile='subtemplates/indicators_minimal.j2',
templatefile='strategy_subtemplates/indicators_does-not-exist.j2',
templatefallbackfile='strategy_subtemplates/indicators_minimal.j2',
)
assert isinstance(val, str)
assert 'if self.dp' in val