Merge branch 'develop' into renaming-forceentry-forceexit
This commit is contained in:
@@ -826,8 +826,9 @@ def test_download_data_trades(mocker, caplog):
|
||||
]
|
||||
with pytest.raises(OperationalException,
|
||||
match="Trade download not supported for futures."):
|
||||
|
||||
start_download_data(get_args(args))
|
||||
pargs = get_args(args)
|
||||
pargs['config'] = None
|
||||
start_download_data(pargs)
|
||||
|
||||
|
||||
def test_start_convert_trades(mocker, caplog):
|
||||
|
@@ -6,7 +6,7 @@ from freqtrade.persistence.models import Order, Trade
|
||||
MOCK_TRADE_COUNT = 6
|
||||
|
||||
|
||||
def enter_side(is_short: bool):
|
||||
def entry_side(is_short: bool):
|
||||
return "sell" if is_short else "buy"
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ def mock_order_1(is_short: bool):
|
||||
'id': f'1234_{direc(is_short)}',
|
||||
'symbol': 'ETH/BTC',
|
||||
'status': 'closed',
|
||||
'side': enter_side(is_short),
|
||||
'side': entry_side(is_short),
|
||||
'type': 'limit',
|
||||
'price': 0.123,
|
||||
'average': 0.123,
|
||||
@@ -50,7 +50,7 @@ def mock_trade_1(fee, is_short: bool):
|
||||
timeframe=5,
|
||||
is_short=is_short
|
||||
)
|
||||
o = Order.parse_from_ccxt_object(mock_order_1(is_short), 'ETH/BTC', enter_side(is_short))
|
||||
o = Order.parse_from_ccxt_object(mock_order_1(is_short), 'ETH/BTC', entry_side(is_short))
|
||||
trade.orders.append(o)
|
||||
return trade
|
||||
|
||||
@@ -60,7 +60,7 @@ def mock_order_2(is_short: bool):
|
||||
'id': f'1235_{direc(is_short)}',
|
||||
'symbol': 'ETC/BTC',
|
||||
'status': 'closed',
|
||||
'side': enter_side(is_short),
|
||||
'side': entry_side(is_short),
|
||||
'type': 'limit',
|
||||
'price': 0.123,
|
||||
'amount': 123.0,
|
||||
@@ -109,7 +109,7 @@ def mock_trade_2(fee, is_short: bool):
|
||||
close_date=datetime.now(tz=timezone.utc) - timedelta(minutes=2),
|
||||
is_short=is_short
|
||||
)
|
||||
o = Order.parse_from_ccxt_object(mock_order_2(is_short), 'ETC/BTC', enter_side(is_short))
|
||||
o = Order.parse_from_ccxt_object(mock_order_2(is_short), 'ETC/BTC', entry_side(is_short))
|
||||
trade.orders.append(o)
|
||||
o = Order.parse_from_ccxt_object(mock_order_2_sell(is_short), 'ETC/BTC', exit_side(is_short))
|
||||
trade.orders.append(o)
|
||||
@@ -121,7 +121,7 @@ def mock_order_3(is_short: bool):
|
||||
'id': f'41231a12a_{direc(is_short)}',
|
||||
'symbol': 'XRP/BTC',
|
||||
'status': 'closed',
|
||||
'side': enter_side(is_short),
|
||||
'side': entry_side(is_short),
|
||||
'type': 'limit',
|
||||
'price': 0.05,
|
||||
'amount': 123.0,
|
||||
@@ -169,7 +169,7 @@ def mock_trade_3(fee, is_short: bool):
|
||||
close_date=datetime.now(tz=timezone.utc),
|
||||
is_short=is_short
|
||||
)
|
||||
o = Order.parse_from_ccxt_object(mock_order_3(is_short), 'XRP/BTC', enter_side(is_short))
|
||||
o = Order.parse_from_ccxt_object(mock_order_3(is_short), 'XRP/BTC', entry_side(is_short))
|
||||
trade.orders.append(o)
|
||||
o = Order.parse_from_ccxt_object(mock_order_3_sell(is_short), 'XRP/BTC', exit_side(is_short))
|
||||
trade.orders.append(o)
|
||||
@@ -181,7 +181,7 @@ def mock_order_4(is_short: bool):
|
||||
'id': f'prod_buy_{direc(is_short)}_12345',
|
||||
'symbol': 'ETC/BTC',
|
||||
'status': 'open',
|
||||
'side': enter_side(is_short),
|
||||
'side': entry_side(is_short),
|
||||
'type': 'limit',
|
||||
'price': 0.123,
|
||||
'amount': 123.0,
|
||||
@@ -210,7 +210,7 @@ def mock_trade_4(fee, is_short: bool):
|
||||
timeframe=5,
|
||||
is_short=is_short
|
||||
)
|
||||
o = Order.parse_from_ccxt_object(mock_order_4(is_short), 'ETC/BTC', enter_side(is_short))
|
||||
o = Order.parse_from_ccxt_object(mock_order_4(is_short), 'ETC/BTC', entry_side(is_short))
|
||||
trade.orders.append(o)
|
||||
return trade
|
||||
|
||||
@@ -220,7 +220,7 @@ def mock_order_5(is_short: bool):
|
||||
'id': f'prod_buy_{direc(is_short)}_3455',
|
||||
'symbol': 'XRP/BTC',
|
||||
'status': 'closed',
|
||||
'side': enter_side(is_short),
|
||||
'side': entry_side(is_short),
|
||||
'type': 'limit',
|
||||
'price': 0.123,
|
||||
'amount': 123.0,
|
||||
@@ -264,7 +264,7 @@ def mock_trade_5(fee, is_short: bool):
|
||||
timeframe=5,
|
||||
is_short=is_short
|
||||
)
|
||||
o = Order.parse_from_ccxt_object(mock_order_5(is_short), 'XRP/BTC', enter_side(is_short))
|
||||
o = Order.parse_from_ccxt_object(mock_order_5(is_short), 'XRP/BTC', entry_side(is_short))
|
||||
trade.orders.append(o)
|
||||
o = Order.parse_from_ccxt_object(mock_order_5_stoploss(is_short), 'XRP/BTC', 'stoploss')
|
||||
trade.orders.append(o)
|
||||
@@ -276,7 +276,7 @@ def mock_order_6(is_short: bool):
|
||||
'id': f'prod_buy_{direc(is_short)}_6',
|
||||
'symbol': 'LTC/BTC',
|
||||
'status': 'closed',
|
||||
'side': enter_side(is_short),
|
||||
'side': entry_side(is_short),
|
||||
'type': 'limit',
|
||||
'price': 0.15,
|
||||
'amount': 2.0,
|
||||
@@ -320,7 +320,7 @@ def mock_trade_6(fee, is_short: bool):
|
||||
timeframe=5,
|
||||
is_short=is_short
|
||||
)
|
||||
o = Order.parse_from_ccxt_object(mock_order_6(is_short), 'LTC/BTC', enter_side(is_short))
|
||||
o = Order.parse_from_ccxt_object(mock_order_6(is_short), 'LTC/BTC', entry_side(is_short))
|
||||
trade.orders.append(o)
|
||||
o = Order.parse_from_ccxt_object(mock_order_6_sell(is_short), 'LTC/BTC', exit_side(is_short))
|
||||
trade.orders.append(o)
|
||||
|
@@ -821,7 +821,7 @@ def test_backtest_results(default_conf, fee, mocker, caplog, data: BTContainer)
|
||||
if data.trailing_stop_positive is not None:
|
||||
default_conf["trailing_stop_positive"] = data.trailing_stop_positive
|
||||
default_conf["trailing_stop_positive_offset"] = data.trailing_stop_positive_offset
|
||||
default_conf["use_sell_signal"] = data.use_exit_signal
|
||||
default_conf["use_exit_signal"] = data.use_exit_signal
|
||||
|
||||
mocker.patch("freqtrade.exchange.Exchange.get_fee", return_value=0.0)
|
||||
mocker.patch("freqtrade.exchange.Exchange.get_min_pair_stake_amount", return_value=0.00001)
|
||||
|
@@ -504,7 +504,7 @@ def test_backtesting_pairlist_list(default_conf, mocker, caplog, testdatadir, ti
|
||||
|
||||
|
||||
def test_backtest__enter_trade(default_conf, fee, mocker) -> None:
|
||||
default_conf['use_sell_signal'] = False
|
||||
default_conf['use_exit_signal'] = False
|
||||
mocker.patch('freqtrade.exchange.Exchange.get_fee', fee)
|
||||
mocker.patch("freqtrade.exchange.Exchange.get_min_pair_stake_amount", return_value=0.00001)
|
||||
mocker.patch("freqtrade.exchange.Exchange.get_max_pair_stake_amount", return_value=float('inf'))
|
||||
@@ -563,7 +563,7 @@ def test_backtest__enter_trade(default_conf, fee, mocker) -> None:
|
||||
|
||||
|
||||
def test_backtest__enter_trade_futures(default_conf_usdt, fee, mocker) -> None:
|
||||
default_conf_usdt['use_sell_signal'] = False
|
||||
default_conf_usdt['use_exit_signal'] = False
|
||||
mocker.patch('freqtrade.exchange.Exchange.get_fee', fee)
|
||||
mocker.patch("freqtrade.exchange.Exchange.get_min_pair_stake_amount", return_value=0.00001)
|
||||
mocker.patch("freqtrade.exchange.Exchange.get_max_pair_stake_amount", return_value=float('inf'))
|
||||
@@ -645,7 +645,7 @@ def test_backtest__enter_trade_futures(default_conf_usdt, fee, mocker) -> None:
|
||||
|
||||
|
||||
def test_backtest__get_sell_trade_entry(default_conf, fee, mocker) -> None:
|
||||
default_conf['use_sell_signal'] = False
|
||||
default_conf['use_exit_signal'] = False
|
||||
mocker.patch('freqtrade.exchange.Exchange.get_fee', fee)
|
||||
mocker.patch("freqtrade.exchange.Exchange.get_min_pair_stake_amount", return_value=0.00001)
|
||||
mocker.patch("freqtrade.exchange.Exchange.get_max_pair_stake_amount", return_value=float('inf'))
|
||||
@@ -740,7 +740,7 @@ def test_backtest__get_sell_trade_entry(default_conf, fee, mocker) -> None:
|
||||
|
||||
|
||||
def test_backtest_one(default_conf, fee, mocker, testdatadir) -> None:
|
||||
default_conf['use_sell_signal'] = False
|
||||
default_conf['use_exit_signal'] = False
|
||||
mocker.patch('freqtrade.exchange.Exchange.get_fee', fee)
|
||||
mocker.patch("freqtrade.exchange.Exchange.get_min_pair_stake_amount", return_value=0.00001)
|
||||
mocker.patch("freqtrade.exchange.Exchange.get_max_pair_stake_amount", return_value=float('inf'))
|
||||
@@ -807,7 +807,7 @@ def test_backtest_one(default_conf, fee, mocker, testdatadir) -> None:
|
||||
|
||||
|
||||
def test_backtest_1min_timeframe(default_conf, fee, mocker, testdatadir) -> None:
|
||||
default_conf['use_sell_signal'] = False
|
||||
default_conf['use_exit_signal'] = False
|
||||
mocker.patch('freqtrade.exchange.Exchange.get_fee', fee)
|
||||
mocker.patch("freqtrade.exchange.Exchange.get_min_pair_stake_amount", return_value=0.00001)
|
||||
mocker.patch("freqtrade.exchange.Exchange.get_max_pair_stake_amount", return_value=float('inf'))
|
||||
@@ -833,7 +833,7 @@ def test_backtest_1min_timeframe(default_conf, fee, mocker, testdatadir) -> None
|
||||
|
||||
|
||||
def test_backtest_trim_no_data_left(default_conf, fee, mocker, testdatadir) -> None:
|
||||
default_conf['use_sell_signal'] = False
|
||||
default_conf['use_exit_signal'] = False
|
||||
mocker.patch('freqtrade.exchange.Exchange.get_fee', fee)
|
||||
mocker.patch("freqtrade.exchange.Exchange.get_min_pair_stake_amount", return_value=0.00001)
|
||||
mocker.patch("freqtrade.exchange.Exchange.get_max_pair_stake_amount", return_value=float('inf'))
|
||||
@@ -878,7 +878,7 @@ def test_processed(default_conf, mocker, testdatadir) -> None:
|
||||
|
||||
|
||||
def test_backtest_dataprovider_analyzed_df(default_conf, fee, mocker, testdatadir) -> None:
|
||||
default_conf['use_sell_signal'] = False
|
||||
default_conf['use_exit_signal'] = False
|
||||
mocker.patch('freqtrade.exchange.Exchange.get_fee', fee)
|
||||
mocker.patch("freqtrade.exchange.Exchange.get_min_pair_stake_amount", return_value=0.00001)
|
||||
mocker.patch("freqtrade.exchange.Exchange.get_max_pair_stake_amount", return_value=100000)
|
||||
@@ -1151,10 +1151,10 @@ def test_backtest_start_timerange(default_conf, mocker, caplog, testdatadir):
|
||||
def test_backtest_start_multi_strat(default_conf, mocker, caplog, testdatadir):
|
||||
|
||||
default_conf.update({
|
||||
"use_sell_signal": True,
|
||||
"sell_profit_only": False,
|
||||
"sell_profit_offset": 0.0,
|
||||
"ignore_roi_if_buy_signal": False,
|
||||
"use_exit_signal": True,
|
||||
"exit_profit_only": False,
|
||||
"exit_profit_offset": 0.0,
|
||||
"ignore_roi_if_entry_signal": False,
|
||||
})
|
||||
patch_exchange(mocker)
|
||||
backtestmock = MagicMock(return_value={
|
||||
@@ -1228,10 +1228,10 @@ def test_backtest_start_multi_strat(default_conf, mocker, caplog, testdatadir):
|
||||
@pytest.mark.filterwarnings("ignore:deprecated")
|
||||
def test_backtest_start_multi_strat_nomock(default_conf, mocker, caplog, testdatadir, capsys):
|
||||
default_conf.update({
|
||||
"use_sell_signal": True,
|
||||
"sell_profit_only": False,
|
||||
"sell_profit_offset": 0.0,
|
||||
"ignore_roi_if_buy_signal": False,
|
||||
"use_exit_signal": True,
|
||||
"exit_profit_only": False,
|
||||
"exit_profit_offset": 0.0,
|
||||
"ignore_roi_if_entry_signal": False,
|
||||
})
|
||||
patch_exchange(mocker)
|
||||
result1 = pd.DataFrame({'pair': ['XRP/BTC', 'LTC/BTC'],
|
||||
@@ -1346,10 +1346,10 @@ def test_backtest_start_nomock_futures(default_conf_usdt, mocker,
|
||||
default_conf_usdt.update({
|
||||
"trading_mode": "futures",
|
||||
"margin_mode": "isolated",
|
||||
"use_sell_signal": True,
|
||||
"sell_profit_only": False,
|
||||
"sell_profit_offset": 0.0,
|
||||
"ignore_roi_if_buy_signal": False,
|
||||
"use_exit_signal": True,
|
||||
"exit_profit_only": False,
|
||||
"exit_profit_offset": 0.0,
|
||||
"ignore_roi_if_entry_signal": False,
|
||||
"strategy": CURRENT_TEST_STRATEGY,
|
||||
})
|
||||
patch_exchange(mocker)
|
||||
@@ -1450,10 +1450,10 @@ def test_backtest_start_multi_strat_nomock_detail(default_conf, mocker,
|
||||
caplog, testdatadir, capsys):
|
||||
# Tests detail-data loading
|
||||
default_conf.update({
|
||||
"use_sell_signal": True,
|
||||
"sell_profit_only": False,
|
||||
"sell_profit_offset": 0.0,
|
||||
"ignore_roi_if_buy_signal": False,
|
||||
"use_exit_signal": True,
|
||||
"exit_profit_only": False,
|
||||
"exit_profit_offset": 0.0,
|
||||
"ignore_roi_if_entry_signal": False,
|
||||
})
|
||||
patch_exchange(mocker)
|
||||
result1 = pd.DataFrame({'pair': ['XRP/BTC', 'LTC/BTC'],
|
||||
@@ -1557,10 +1557,10 @@ def test_backtest_start_multi_strat_nomock_detail(default_conf, mocker,
|
||||
def test_backtest_start_multi_strat_caching(default_conf, mocker, caplog, testdatadir, run_id,
|
||||
start_delta, cache):
|
||||
default_conf.update({
|
||||
"use_sell_signal": True,
|
||||
"sell_profit_only": False,
|
||||
"sell_profit_offset": 0.0,
|
||||
"ignore_roi_if_buy_signal": False,
|
||||
"use_exit_signal": True,
|
||||
"exit_profit_only": False,
|
||||
"exit_profit_offset": 0.0,
|
||||
"ignore_roi_if_entry_signal": False,
|
||||
})
|
||||
patch_exchange(mocker)
|
||||
backtestmock = MagicMock(return_value={
|
||||
|
@@ -14,7 +14,7 @@ from tests.conftest import patch_exchange
|
||||
|
||||
|
||||
def test_backtest_position_adjustment(default_conf, fee, mocker, testdatadir) -> None:
|
||||
default_conf['use_sell_signal'] = False
|
||||
default_conf['use_exit_signal'] = False
|
||||
mocker.patch('freqtrade.exchange.Exchange.get_fee', fee)
|
||||
mocker.patch("freqtrade.exchange.Exchange.get_min_pair_stake_amount", return_value=0.00001)
|
||||
mocker.patch("freqtrade.exchange.Exchange.get_max_pair_stake_amount", return_value=float('inf'))
|
||||
|
@@ -50,6 +50,8 @@ class StrategyTestV2(IStrategy):
|
||||
'entry': 'gtc',
|
||||
'exit': 'gtc',
|
||||
}
|
||||
# Test legacy use_sell_signal definition
|
||||
use_sell_signal = False
|
||||
|
||||
# By default this strategy does not use Position Adjustments
|
||||
position_adjustment_enable = False
|
||||
|
@@ -183,7 +183,7 @@ class StrategyTestV3(IStrategy):
|
||||
current_profit: float, min_stake: float, max_stake: float, **kwargs):
|
||||
|
||||
if current_profit < -0.0075:
|
||||
orders = trade.select_filled_orders(trade.enter_side)
|
||||
orders = trade.select_filled_orders(trade.entry_side)
|
||||
return round(orders[0].cost, 0)
|
||||
|
||||
return None
|
||||
|
@@ -143,16 +143,6 @@ def test_strategy_can_short(caplog, default_conf):
|
||||
assert isinstance(strat, IStrategy)
|
||||
|
||||
|
||||
def test_strategy_implements_populate_entry(caplog, default_conf):
|
||||
caplog.set_level(logging.INFO)
|
||||
default_conf.update({
|
||||
'strategy': "StrategyTestV2",
|
||||
})
|
||||
default_conf['trading_mode'] = 'futures'
|
||||
with pytest.raises(OperationalException, match="`populate_entry_trend` must be implemented."):
|
||||
StrategyResolver.load_strategy(default_conf)
|
||||
|
||||
|
||||
def test_strategy_override_minimal_roi(caplog, default_conf):
|
||||
caplog.set_level(logging.INFO)
|
||||
default_conf.update({
|
||||
@@ -310,50 +300,50 @@ def test_strategy_override_order_tif(caplog, default_conf):
|
||||
StrategyResolver.load_strategy(default_conf)
|
||||
|
||||
|
||||
def test_strategy_override_use_sell_signal(caplog, default_conf):
|
||||
def test_strategy_override_use_exit_signal(caplog, default_conf):
|
||||
caplog.set_level(logging.INFO)
|
||||
default_conf.update({
|
||||
'strategy': CURRENT_TEST_STRATEGY,
|
||||
})
|
||||
strategy = StrategyResolver.load_strategy(default_conf)
|
||||
assert strategy.use_sell_signal
|
||||
assert isinstance(strategy.use_sell_signal, bool)
|
||||
assert strategy.use_exit_signal
|
||||
assert isinstance(strategy.use_exit_signal, bool)
|
||||
# must be inserted to configuration
|
||||
assert 'use_sell_signal' in default_conf
|
||||
assert default_conf['use_sell_signal']
|
||||
assert 'use_exit_signal' in default_conf
|
||||
assert default_conf['use_exit_signal']
|
||||
|
||||
default_conf.update({
|
||||
'strategy': CURRENT_TEST_STRATEGY,
|
||||
'use_sell_signal': False,
|
||||
'use_exit_signal': False,
|
||||
})
|
||||
strategy = StrategyResolver.load_strategy(default_conf)
|
||||
|
||||
assert not strategy.use_sell_signal
|
||||
assert isinstance(strategy.use_sell_signal, bool)
|
||||
assert log_has("Override strategy 'use_sell_signal' with value in config file: False.", caplog)
|
||||
assert not strategy.use_exit_signal
|
||||
assert isinstance(strategy.use_exit_signal, bool)
|
||||
assert log_has("Override strategy 'use_exit_signal' with value in config file: False.", caplog)
|
||||
|
||||
|
||||
def test_strategy_override_use_sell_profit_only(caplog, default_conf):
|
||||
def test_strategy_override_use_exit_profit_only(caplog, default_conf):
|
||||
caplog.set_level(logging.INFO)
|
||||
default_conf.update({
|
||||
'strategy': CURRENT_TEST_STRATEGY,
|
||||
})
|
||||
strategy = StrategyResolver.load_strategy(default_conf)
|
||||
assert not strategy.sell_profit_only
|
||||
assert isinstance(strategy.sell_profit_only, bool)
|
||||
assert not strategy.exit_profit_only
|
||||
assert isinstance(strategy.exit_profit_only, bool)
|
||||
# must be inserted to configuration
|
||||
assert 'sell_profit_only' in default_conf
|
||||
assert not default_conf['sell_profit_only']
|
||||
assert 'exit_profit_only' in default_conf
|
||||
assert not default_conf['exit_profit_only']
|
||||
|
||||
default_conf.update({
|
||||
'strategy': CURRENT_TEST_STRATEGY,
|
||||
'sell_profit_only': True,
|
||||
'exit_profit_only': True,
|
||||
})
|
||||
strategy = StrategyResolver.load_strategy(default_conf)
|
||||
|
||||
assert strategy.sell_profit_only
|
||||
assert isinstance(strategy.sell_profit_only, bool)
|
||||
assert log_has("Override strategy 'sell_profit_only' with value in config file: True.", caplog)
|
||||
assert strategy.exit_profit_only
|
||||
assert isinstance(strategy.exit_profit_only, bool)
|
||||
assert log_has("Override strategy 'exit_profit_only' with value in config file: True.", caplog)
|
||||
|
||||
|
||||
@pytest.mark.filterwarnings("ignore:deprecated")
|
||||
@@ -391,7 +381,22 @@ def test_deprecate_populate_indicators(result, default_conf):
|
||||
|
||||
|
||||
@pytest.mark.filterwarnings("ignore:deprecated")
|
||||
def test_missing_implements(default_conf):
|
||||
def test_missing_implements(default_conf, caplog):
|
||||
|
||||
default_location = Path(__file__).parent / "strats"
|
||||
default_conf.update({'strategy': 'StrategyTestV2',
|
||||
'strategy_path': default_location})
|
||||
StrategyResolver.load_strategy(default_conf)
|
||||
|
||||
log_has_re(r"DEPRECATED: .*use_sell_signal.*use_exit_signal.", caplog)
|
||||
|
||||
default_conf['trading_mode'] = 'futures'
|
||||
with pytest.raises(OperationalException,
|
||||
match=r"DEPRECATED: .*use_sell_signal.*use_exit_signal."):
|
||||
StrategyResolver.load_strategy(default_conf)
|
||||
|
||||
default_conf['trading_mode'] = 'spot'
|
||||
|
||||
default_location = Path(__file__).parent / "strats/broken_strats"
|
||||
default_conf.update({'strategy': 'TestStrategyNoImplements',
|
||||
'strategy_path': default_location})
|
||||
|
@@ -868,15 +868,15 @@ def test_validate_tsl(default_conf):
|
||||
|
||||
def test_validate_edge2(edge_conf):
|
||||
edge_conf.update({
|
||||
"use_sell_signal": True,
|
||||
"use_exit_signal": True,
|
||||
})
|
||||
# Passes test
|
||||
validate_config_consistency(edge_conf)
|
||||
|
||||
edge_conf.update({
|
||||
"use_sell_signal": False,
|
||||
"use_exit_signal": False,
|
||||
})
|
||||
with pytest.raises(OperationalException, match="Edge requires `use_sell_signal` to be True, "
|
||||
with pytest.raises(OperationalException, match="Edge requires `use_exit_signal` to be True, "
|
||||
"otherwise no sells will happen."):
|
||||
validate_config_consistency(edge_conf)
|
||||
|
||||
@@ -1238,14 +1238,8 @@ 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),
|
||||
("webhook", "webhookbuy", 'testWEbhook',
|
||||
"webhook", "webhookentry", 'testWEbhook'),
|
||||
("ask_strategy", "ignore_buying_expired_candle_after", 5,
|
||||
None, "ignore_buying_expired_candle_after", 6),
|
||||
])
|
||||
|
@@ -25,7 +25,7 @@ from freqtrade.worker import Worker
|
||||
from tests.conftest import (create_mock_trades, get_patched_freqtradebot, get_patched_worker,
|
||||
log_has, log_has_re, patch_edge, patch_exchange, patch_get_signal,
|
||||
patch_wallet, patch_whitelist)
|
||||
from tests.conftest_trades import (MOCK_TRADE_COUNT, enter_side, exit_side, mock_order_1,
|
||||
from tests.conftest_trades import (MOCK_TRADE_COUNT, entry_side, exit_side, mock_order_1,
|
||||
mock_order_2, mock_order_2_sell, mock_order_3, mock_order_3_sell,
|
||||
mock_order_4, mock_order_5_stoploss, mock_order_6_sell)
|
||||
|
||||
@@ -303,7 +303,7 @@ def test_create_trade(default_conf_usdt, ticker_usdt, limit_order,
|
||||
|
||||
# Simulate fulfilled LIMIT_BUY order for trade
|
||||
oobj = Order.parse_from_ccxt_object(
|
||||
limit_order[enter_side(is_short)], 'ADA/USDT', enter_side(is_short))
|
||||
limit_order[entry_side(is_short)], 'ADA/USDT', entry_side(is_short))
|
||||
trade.update_trade(oobj)
|
||||
|
||||
assert trade.open_rate == open_rate
|
||||
@@ -341,7 +341,7 @@ def test_create_trade_minimal_amount(
|
||||
) -> None:
|
||||
patch_RPCManager(mocker)
|
||||
patch_exchange(mocker)
|
||||
enter_mock = MagicMock(return_value=limit_order_open[enter_side(is_short)])
|
||||
enter_mock = MagicMock(return_value=limit_order_open[entry_side(is_short)])
|
||||
mocker.patch.multiple(
|
||||
'freqtrade.exchange.Exchange',
|
||||
fetch_ticker=ticker_usdt,
|
||||
@@ -537,8 +537,8 @@ def test_process_trade_creation(default_conf_usdt, ticker_usdt, limit_order, lim
|
||||
mocker.patch.multiple(
|
||||
'freqtrade.exchange.Exchange',
|
||||
fetch_ticker=ticker_usdt,
|
||||
create_order=MagicMock(return_value=limit_order_open[enter_side(is_short)]),
|
||||
fetch_order=MagicMock(return_value=limit_order[enter_side(is_short)]),
|
||||
create_order=MagicMock(return_value=limit_order_open[entry_side(is_short)]),
|
||||
fetch_order=MagicMock(return_value=limit_order[entry_side(is_short)]),
|
||||
get_fee=fee,
|
||||
)
|
||||
freqtrade = FreqtradeBot(default_conf_usdt)
|
||||
@@ -751,8 +751,8 @@ def test_execute_entry(mocker, default_conf_usdt, fee, limit_order,
|
||||
(10 - (2 / 1)) / (1 - (0.01 + 0.0006)) = 8.085708510208207
|
||||
"""
|
||||
# TODO: Split this test into multiple tests to improve readability
|
||||
open_order = limit_order_open[enter_side(is_short)]
|
||||
order = limit_order[enter_side(is_short)]
|
||||
open_order = limit_order_open[entry_side(is_short)]
|
||||
order = limit_order[entry_side(is_short)]
|
||||
default_conf_usdt['trading_mode'] = trading_mode
|
||||
default_conf_usdt['liquidation_buffer'] = liq_buffer
|
||||
leverage = 1.0 if trading_mode == 'spot' else 5.0
|
||||
@@ -975,7 +975,7 @@ def test_execute_entry_confirm_error(mocker, default_conf_usdt, fee, limit_order
|
||||
'ask': 2.2,
|
||||
'last': 1.9
|
||||
}),
|
||||
create_order=MagicMock(return_value=limit_order[enter_side(is_short)]),
|
||||
create_order=MagicMock(return_value=limit_order[entry_side(is_short)]),
|
||||
get_rate=MagicMock(return_value=0.11),
|
||||
get_min_pair_stake_amount=MagicMock(return_value=1),
|
||||
get_fee=fee,
|
||||
@@ -986,11 +986,11 @@ def test_execute_entry_confirm_error(mocker, default_conf_usdt, fee, limit_order
|
||||
freqtrade.strategy.confirm_trade_entry = MagicMock(side_effect=ValueError)
|
||||
assert freqtrade.execute_entry(pair, stake_amount)
|
||||
|
||||
limit_order[enter_side(is_short)]['id'] = '222'
|
||||
limit_order[entry_side(is_short)]['id'] = '222'
|
||||
freqtrade.strategy.confirm_trade_entry = MagicMock(side_effect=Exception)
|
||||
assert freqtrade.execute_entry(pair, stake_amount)
|
||||
|
||||
limit_order[enter_side(is_short)]['id'] = '2223'
|
||||
limit_order[entry_side(is_short)]['id'] = '2223'
|
||||
freqtrade.strategy.confirm_trade_entry = MagicMock(return_value=True)
|
||||
assert freqtrade.execute_entry(pair, stake_amount)
|
||||
|
||||
@@ -1010,7 +1010,7 @@ def test_execute_entry_min_leverage(mocker, default_conf_usdt, fee, limit_order,
|
||||
'ask': 2.2,
|
||||
'last': 1.9
|
||||
}),
|
||||
create_order=MagicMock(return_value=limit_order[enter_side(is_short)]),
|
||||
create_order=MagicMock(return_value=limit_order[entry_side(is_short)]),
|
||||
get_rate=MagicMock(return_value=0.11),
|
||||
# Minimum stake-amount is ~5$
|
||||
get_maintenance_ratio_and_amt=MagicMock(return_value=(0.0, 0.0)),
|
||||
@@ -1032,7 +1032,7 @@ def test_execute_entry_min_leverage(mocker, default_conf_usdt, fee, limit_order,
|
||||
def test_add_stoploss_on_exchange(mocker, default_conf_usdt, limit_order, is_short) -> None:
|
||||
patch_RPCManager(mocker)
|
||||
patch_exchange(mocker)
|
||||
order = limit_order[enter_side(is_short)]
|
||||
order = limit_order[entry_side(is_short)]
|
||||
mocker.patch('freqtrade.freqtradebot.FreqtradeBot.handle_trade', MagicMock(return_value=True))
|
||||
mocker.patch('freqtrade.exchange.Exchange.fetch_order', return_value=order)
|
||||
mocker.patch('freqtrade.exchange.Exchange.get_trades_for_order', return_value=[])
|
||||
@@ -1062,7 +1062,7 @@ def test_add_stoploss_on_exchange(mocker, default_conf_usdt, limit_order, is_sho
|
||||
def test_handle_stoploss_on_exchange(mocker, default_conf_usdt, fee, caplog, is_short,
|
||||
limit_order) -> None:
|
||||
stoploss = MagicMock(return_value={'id': 13434334})
|
||||
enter_order = limit_order[enter_side(is_short)]
|
||||
enter_order = limit_order[entry_side(is_short)]
|
||||
exit_order = limit_order[exit_side(is_short)]
|
||||
patch_RPCManager(mocker)
|
||||
patch_exchange(mocker)
|
||||
@@ -1217,7 +1217,7 @@ def test_handle_stoploss_on_exchange(mocker, default_conf_usdt, fee, caplog, is_
|
||||
def test_handle_sle_cancel_cant_recreate(mocker, default_conf_usdt, fee, caplog, is_short,
|
||||
limit_order) -> None:
|
||||
# Sixth case: stoploss order was cancelled but couldn't create new one
|
||||
enter_order = limit_order[enter_side(is_short)]
|
||||
enter_order = limit_order[entry_side(is_short)]
|
||||
exit_order = limit_order[exit_side(is_short)]
|
||||
patch_RPCManager(mocker)
|
||||
patch_exchange(mocker)
|
||||
@@ -1260,7 +1260,7 @@ def test_handle_sle_cancel_cant_recreate(mocker, default_conf_usdt, fee, caplog,
|
||||
def test_create_stoploss_order_invalid_order(
|
||||
mocker, default_conf_usdt, caplog, fee, is_short, limit_order, limit_order_open
|
||||
):
|
||||
open_order = limit_order_open[enter_side(is_short)]
|
||||
open_order = limit_order_open[entry_side(is_short)]
|
||||
order = limit_order[exit_side(is_short)]
|
||||
rpc_mock = patch_RPCManager(mocker)
|
||||
patch_exchange(mocker)
|
||||
@@ -1325,7 +1325,7 @@ def test_create_stoploss_order_insufficient_funds(
|
||||
'last': 1.9
|
||||
}),
|
||||
create_order=MagicMock(side_effect=[
|
||||
limit_order[enter_side(is_short)],
|
||||
limit_order[entry_side(is_short)],
|
||||
exit_order,
|
||||
]),
|
||||
get_fee=fee,
|
||||
@@ -1364,7 +1364,7 @@ def test_handle_stoploss_on_exchange_trailing(
|
||||
mocker, default_conf_usdt, fee, is_short, bid, ask, limit_order, stop_price, amt, hang_price
|
||||
) -> None:
|
||||
# When trailing stoploss is set
|
||||
enter_order = limit_order[enter_side(is_short)]
|
||||
enter_order = limit_order[entry_side(is_short)]
|
||||
exit_order = limit_order[exit_side(is_short)]
|
||||
stoploss = MagicMock(return_value={'id': 13434334})
|
||||
patch_RPCManager(mocker)
|
||||
@@ -1485,7 +1485,7 @@ def test_handle_stoploss_on_exchange_trailing(
|
||||
def test_handle_stoploss_on_exchange_trailing_error(
|
||||
mocker, default_conf_usdt, fee, caplog, limit_order, is_short
|
||||
) -> None:
|
||||
enter_order = limit_order[enter_side(is_short)]
|
||||
enter_order = limit_order[entry_side(is_short)]
|
||||
exit_order = limit_order[exit_side(is_short)]
|
||||
# When trailing stoploss is set
|
||||
stoploss = MagicMock(return_value={'id': 13434334})
|
||||
@@ -1593,7 +1593,7 @@ def test_stoploss_on_exchange_price_rounding(
|
||||
def test_handle_stoploss_on_exchange_custom_stop(
|
||||
mocker, default_conf_usdt, fee, is_short, limit_order
|
||||
) -> None:
|
||||
enter_order = limit_order[enter_side(is_short)]
|
||||
enter_order = limit_order[entry_side(is_short)]
|
||||
exit_order = limit_order[exit_side(is_short)]
|
||||
# When trailing stoploss is set
|
||||
stoploss = MagicMock(return_value={'id': 13434334})
|
||||
@@ -1860,10 +1860,10 @@ def test_exit_positions(mocker, default_conf_usdt, limit_order, is_short, caplog
|
||||
|
||||
mocker.patch('freqtrade.freqtradebot.FreqtradeBot.handle_trade', MagicMock(return_value=True))
|
||||
mocker.patch('freqtrade.exchange.Exchange.fetch_order',
|
||||
return_value=limit_order[enter_side(is_short)])
|
||||
return_value=limit_order[entry_side(is_short)])
|
||||
mocker.patch('freqtrade.exchange.Exchange.get_trades_for_order', return_value=[])
|
||||
mocker.patch('freqtrade.freqtradebot.FreqtradeBot.get_real_amount',
|
||||
return_value=limit_order[enter_side(is_short)]['amount'])
|
||||
return_value=limit_order[entry_side(is_short)]['amount'])
|
||||
|
||||
trade = MagicMock()
|
||||
trade.is_short = is_short
|
||||
@@ -1886,7 +1886,7 @@ def test_exit_positions(mocker, default_conf_usdt, limit_order, is_short, caplog
|
||||
@pytest.mark.parametrize("is_short", [False, True])
|
||||
def test_exit_positions_exception(mocker, default_conf_usdt, limit_order, caplog, is_short) -> None:
|
||||
freqtrade = get_patched_freqtradebot(mocker, default_conf_usdt)
|
||||
order = limit_order[enter_side(is_short)]
|
||||
order = limit_order[entry_side(is_short)]
|
||||
mocker.patch('freqtrade.exchange.Exchange.fetch_order', return_value=order)
|
||||
|
||||
trade = MagicMock()
|
||||
@@ -1909,7 +1909,7 @@ def test_exit_positions_exception(mocker, default_conf_usdt, limit_order, caplog
|
||||
@pytest.mark.parametrize("is_short", [False, True])
|
||||
def test_update_trade_state(mocker, default_conf_usdt, limit_order, is_short, caplog) -> None:
|
||||
freqtrade = get_patched_freqtradebot(mocker, default_conf_usdt)
|
||||
order = limit_order[enter_side(is_short)]
|
||||
order = limit_order[entry_side(is_short)]
|
||||
|
||||
mocker.patch('freqtrade.freqtradebot.FreqtradeBot.handle_trade', MagicMock(return_value=True))
|
||||
mocker.patch('freqtrade.exchange.Exchange.fetch_order', return_value=order)
|
||||
@@ -1930,7 +1930,7 @@ def test_update_trade_state(mocker, default_conf_usdt, limit_order, is_short, ca
|
||||
leverage=1,
|
||||
)
|
||||
trade.orders.append(Order(
|
||||
ft_order_side=enter_side(is_short),
|
||||
ft_order_side=entry_side(is_short),
|
||||
price=0.01,
|
||||
order_id=order_id,
|
||||
|
||||
@@ -1980,7 +1980,7 @@ def test_update_trade_state_withorderdict(
|
||||
default_conf_usdt, trades_for_order, limit_order, fee, mocker, initial_amount,
|
||||
has_rounding_fee, is_short, caplog
|
||||
):
|
||||
order = limit_order[enter_side(is_short)]
|
||||
order = limit_order[entry_side(is_short)]
|
||||
trades_for_order[0]['amount'] = initial_amount
|
||||
order_id = "oid_123456"
|
||||
order['id'] = order_id
|
||||
@@ -2006,7 +2006,7 @@ def test_update_trade_state_withorderdict(
|
||||
)
|
||||
trade.orders.append(
|
||||
Order(
|
||||
ft_order_side=enter_side(is_short),
|
||||
ft_order_side=entry_side(is_short),
|
||||
ft_pair=trade.pair,
|
||||
ft_is_open=True,
|
||||
order_id=order_id,
|
||||
@@ -2026,7 +2026,7 @@ def test_update_trade_state_withorderdict(
|
||||
@pytest.mark.parametrize("is_short", [False, True])
|
||||
def test_update_trade_state_exception(mocker, default_conf_usdt, is_short, limit_order,
|
||||
caplog) -> None:
|
||||
order = limit_order[enter_side(is_short)]
|
||||
order = limit_order[entry_side(is_short)]
|
||||
freqtrade = get_patched_freqtradebot(mocker, default_conf_usdt)
|
||||
mocker.patch('freqtrade.exchange.Exchange.fetch_order', return_value=order)
|
||||
|
||||
@@ -2107,7 +2107,7 @@ def test_handle_trade(
|
||||
default_conf_usdt, limit_order_open, limit_order, fee, mocker, is_short, close_profit
|
||||
) -> None:
|
||||
open_order = limit_order_open[exit_side(is_short)]
|
||||
enter_order = limit_order[enter_side(is_short)]
|
||||
enter_order = limit_order[entry_side(is_short)]
|
||||
exit_order = limit_order[exit_side(is_short)]
|
||||
patch_RPCManager(mocker)
|
||||
patch_exchange(mocker)
|
||||
@@ -2134,7 +2134,7 @@ def test_handle_trade(
|
||||
assert trade
|
||||
|
||||
time.sleep(0.01) # Race condition fix
|
||||
oobj = Order.parse_from_ccxt_object(enter_order, enter_order['symbol'], enter_side(is_short))
|
||||
oobj = Order.parse_from_ccxt_object(enter_order, enter_order['symbol'], entry_side(is_short))
|
||||
trade.update_trade(oobj)
|
||||
assert trade.is_open is True
|
||||
freqtrade.wallets.update()
|
||||
@@ -2235,7 +2235,7 @@ def test_handle_overlapping_signals(
|
||||
def test_handle_trade_roi(default_conf_usdt, ticker_usdt, limit_order_open, fee, mocker, caplog,
|
||||
is_short) -> None:
|
||||
|
||||
open_order = limit_order_open[enter_side(is_short)]
|
||||
open_order = limit_order_open[entry_side(is_short)]
|
||||
|
||||
caplog.set_level(logging.DEBUG)
|
||||
|
||||
@@ -2273,14 +2273,14 @@ def test_handle_trade_roi(default_conf_usdt, ticker_usdt, limit_order_open, fee,
|
||||
|
||||
|
||||
@pytest.mark.parametrize("is_short", [False, True])
|
||||
def test_handle_trade_use_sell_signal(
|
||||
def test_handle_trade_use_exit_signal(
|
||||
default_conf_usdt, ticker_usdt, limit_order_open, fee, mocker, caplog, is_short
|
||||
) -> None:
|
||||
|
||||
enter_open_order = limit_order_open[exit_side(is_short)]
|
||||
exit_open_order = limit_order_open[enter_side(is_short)]
|
||||
exit_open_order = limit_order_open[entry_side(is_short)]
|
||||
|
||||
# use_sell_signal is True buy default
|
||||
# use_exit_signal is True buy default
|
||||
caplog.set_level(logging.DEBUG)
|
||||
patch_RPCManager(mocker)
|
||||
mocker.patch.multiple(
|
||||
@@ -2320,7 +2320,7 @@ def test_close_trade(
|
||||
) -> None:
|
||||
open_order = limit_order_open[exit_side(is_short)]
|
||||
enter_order = limit_order[exit_side(is_short)]
|
||||
exit_order = limit_order[enter_side(is_short)]
|
||||
exit_order = limit_order[entry_side(is_short)]
|
||||
patch_RPCManager(mocker)
|
||||
patch_exchange(mocker)
|
||||
mocker.patch.multiple(
|
||||
@@ -2766,7 +2766,7 @@ def test_check_handle_timedout_partial_fee(
|
||||
assert trades[0].amount == (limit_buy_order_old_partial['amount'] -
|
||||
limit_buy_order_old_partial['remaining']) - 0.023
|
||||
assert trades[0].open_order_id is None
|
||||
assert trades[0].fee_updated(open_trade.enter_side)
|
||||
assert trades[0].fee_updated(open_trade.entry_side)
|
||||
assert pytest.approx(trades[0].fee_open) == 0.001
|
||||
|
||||
|
||||
@@ -2853,8 +2853,8 @@ def test_check_handle_timedout_exception(default_conf_usdt, ticker_usdt, open_tr
|
||||
def test_handle_cancel_enter(mocker, caplog, default_conf_usdt, limit_order, is_short) -> None:
|
||||
patch_RPCManager(mocker)
|
||||
patch_exchange(mocker)
|
||||
l_order = limit_order[enter_side(is_short)]
|
||||
cancel_buy_order = deepcopy(limit_order[enter_side(is_short)])
|
||||
l_order = limit_order[entry_side(is_short)]
|
||||
cancel_buy_order = deepcopy(limit_order[entry_side(is_short)])
|
||||
cancel_buy_order['status'] = 'canceled'
|
||||
del cancel_buy_order['filled']
|
||||
|
||||
@@ -2868,7 +2868,7 @@ def test_handle_cancel_enter(mocker, caplog, default_conf_usdt, limit_order, is_
|
||||
trade.pair = 'LTC/USDT'
|
||||
trade.open_rate = 200
|
||||
trade.is_short = False
|
||||
trade.enter_side = "buy"
|
||||
trade.entry_side = "buy"
|
||||
l_order['filled'] = 0.0
|
||||
l_order['status'] = 'open'
|
||||
reason = CANCEL_REASON['TIMEOUT']
|
||||
@@ -2896,7 +2896,7 @@ def test_handle_cancel_enter(mocker, caplog, default_conf_usdt, limit_order, is_
|
||||
assert log_has_re(r"Order .* for .* not cancelled.", caplog)
|
||||
# min_pair_stake empty should not crash
|
||||
mocker.patch('freqtrade.exchange.Exchange.get_min_pair_stake_amount', return_value=None)
|
||||
assert not freqtrade.handle_cancel_enter(trade, limit_order[enter_side(is_short)], reason)
|
||||
assert not freqtrade.handle_cancel_enter(trade, limit_order[entry_side(is_short)], reason)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("is_short", [False, True])
|
||||
@@ -2915,11 +2915,11 @@ def test_handle_cancel_enter_exchanges(mocker, caplog, default_conf_usdt, is_sho
|
||||
reason = CANCEL_REASON['TIMEOUT']
|
||||
trade = MagicMock()
|
||||
trade.pair = 'LTC/ETH'
|
||||
trade.enter_side = "sell" if is_short else "buy"
|
||||
trade.entry_side = "sell" if is_short else "buy"
|
||||
assert freqtrade.handle_cancel_enter(trade, limit_buy_order_canceled_empty, reason)
|
||||
assert cancel_order_mock.call_count == 0
|
||||
assert log_has_re(
|
||||
f'{trade.enter_side.capitalize()} order fully cancelled. '
|
||||
f'{trade.entry_side.capitalize()} order fully cancelled. '
|
||||
r'Removing .* from database\.',
|
||||
caplog
|
||||
)
|
||||
@@ -2937,7 +2937,7 @@ def test_handle_cancel_enter_corder_empty(mocker, default_conf_usdt, limit_order
|
||||
cancelorder) -> None:
|
||||
patch_RPCManager(mocker)
|
||||
patch_exchange(mocker)
|
||||
l_order = limit_order[enter_side(is_short)]
|
||||
l_order = limit_order[entry_side(is_short)]
|
||||
cancel_order_mock = MagicMock(return_value=cancelorder)
|
||||
mocker.patch.multiple(
|
||||
'freqtrade.exchange.Exchange',
|
||||
@@ -2949,9 +2949,9 @@ def test_handle_cancel_enter_corder_empty(mocker, default_conf_usdt, limit_order
|
||||
|
||||
trade = MagicMock()
|
||||
trade.pair = 'LTC/USDT'
|
||||
trade.enter_side = "buy"
|
||||
trade.entry_side = "buy"
|
||||
trade.open_rate = 200
|
||||
trade.enter_side = "buy"
|
||||
trade.entry_side = "buy"
|
||||
l_order['filled'] = 0.0
|
||||
l_order['status'] = 'open'
|
||||
reason = CANCEL_REASON['TIMEOUT']
|
||||
@@ -3637,12 +3637,12 @@ def test_execute_trade_exit_insufficient_funds_error(default_conf_usdt, ticker_u
|
||||
(False, 0.10, 0.22, True, False, ExitType.EXIT_SIGNAL.value, False),
|
||||
(False, 0.10, 0.22, True, False, ExitType.EXIT_SIGNAL.value, True),
|
||||
])
|
||||
def test_sell_profit_only(
|
||||
def test_exit_profit_only(
|
||||
default_conf_usdt, limit_order, limit_order_open, is_short,
|
||||
fee, mocker, profit_only, bid, ask, handle_first, handle_second, exit_type) -> None:
|
||||
patch_RPCManager(mocker)
|
||||
patch_exchange(mocker)
|
||||
eside = enter_side(is_short)
|
||||
eside = entry_side(is_short)
|
||||
mocker.patch.multiple(
|
||||
'freqtrade.exchange.Exchange',
|
||||
fetch_ticker=MagicMock(return_value={
|
||||
@@ -3657,9 +3657,9 @@ def test_sell_profit_only(
|
||||
get_fee=fee,
|
||||
)
|
||||
default_conf_usdt.update({
|
||||
'use_sell_signal': True,
|
||||
'sell_profit_only': profit_only,
|
||||
'sell_profit_offset': 0.1,
|
||||
'use_exit_signal': True,
|
||||
'exit_profit_only': profit_only,
|
||||
'exit_profit_offset': 0.1,
|
||||
})
|
||||
freqtrade = FreqtradeBot(default_conf_usdt)
|
||||
patch_get_signal(freqtrade, enter_short=is_short, enter_long=not is_short)
|
||||
@@ -3679,7 +3679,7 @@ def test_sell_profit_only(
|
||||
assert freqtrade.handle_trade(trade) is handle_first
|
||||
|
||||
if handle_second:
|
||||
freqtrade.strategy.sell_profit_offset = 0.0
|
||||
freqtrade.strategy.exit_profit_offset = 0.0
|
||||
assert freqtrade.handle_trade(trade) is True
|
||||
|
||||
|
||||
@@ -3799,11 +3799,11 @@ def test_locked_pairs(default_conf_usdt, ticker_usdt, fee,
|
||||
|
||||
|
||||
@pytest.mark.parametrize("is_short", [False, True])
|
||||
def test_ignore_roi_if_buy_signal(default_conf_usdt, limit_order, limit_order_open, is_short,
|
||||
fee, mocker) -> None:
|
||||
def test_ignore_roi_if_entry_signal(default_conf_usdt, limit_order, limit_order_open, is_short,
|
||||
fee, mocker) -> None:
|
||||
patch_RPCManager(mocker)
|
||||
patch_exchange(mocker)
|
||||
eside = enter_side(is_short)
|
||||
eside = entry_side(is_short)
|
||||
mocker.patch.multiple(
|
||||
'freqtrade.exchange.Exchange',
|
||||
fetch_ticker=MagicMock(return_value={
|
||||
@@ -3817,7 +3817,7 @@ def test_ignore_roi_if_buy_signal(default_conf_usdt, limit_order, limit_order_op
|
||||
]),
|
||||
get_fee=fee,
|
||||
)
|
||||
default_conf_usdt['ignore_roi_if_buy_signal'] = True
|
||||
default_conf_usdt['ignore_roi_if_entry_signal'] = True
|
||||
|
||||
freqtrade = FreqtradeBot(default_conf_usdt)
|
||||
patch_get_signal(freqtrade, enter_short=is_short, enter_long=not is_short)
|
||||
@@ -3863,7 +3863,7 @@ def test_trailing_stop_loss(default_conf_usdt, limit_order_open,
|
||||
'last': 2.0
|
||||
}),
|
||||
create_order=MagicMock(side_effect=[
|
||||
limit_order_open[enter_side(is_short)],
|
||||
limit_order_open[entry_side(is_short)],
|
||||
{'id': 1234553382},
|
||||
]),
|
||||
get_fee=fee,
|
||||
@@ -3921,10 +3921,10 @@ def test_trailing_stop_loss_positive(
|
||||
default_conf_usdt, limit_order, limit_order_open,
|
||||
offset, fee, caplog, mocker, trail_if_reached, second_sl, is_short
|
||||
) -> None:
|
||||
enter_price = limit_order[enter_side(is_short)]['price']
|
||||
enter_price = limit_order[entry_side(is_short)]['price']
|
||||
patch_RPCManager(mocker)
|
||||
patch_exchange(mocker)
|
||||
eside = enter_side(is_short)
|
||||
eside = entry_side(is_short)
|
||||
mocker.patch.multiple(
|
||||
'freqtrade.exchange.Exchange',
|
||||
fetch_ticker=MagicMock(return_value={
|
||||
@@ -4016,11 +4016,11 @@ def test_trailing_stop_loss_positive(
|
||||
|
||||
|
||||
@pytest.mark.parametrize("is_short", [False, True])
|
||||
def test_disable_ignore_roi_if_buy_signal(default_conf_usdt, limit_order, limit_order_open,
|
||||
is_short, fee, mocker) -> None:
|
||||
def test_disable_ignore_roi_if_entry_signal(default_conf_usdt, limit_order, limit_order_open,
|
||||
is_short, fee, mocker) -> None:
|
||||
patch_RPCManager(mocker)
|
||||
patch_exchange(mocker)
|
||||
eside = enter_side(is_short)
|
||||
eside = entry_side(is_short)
|
||||
mocker.patch.multiple(
|
||||
'freqtrade.exchange.Exchange',
|
||||
fetch_ticker=MagicMock(return_value={
|
||||
@@ -4037,7 +4037,7 @@ def test_disable_ignore_roi_if_buy_signal(default_conf_usdt, limit_order, limit_
|
||||
_is_dry_limit_order_filled=MagicMock(return_value=False),
|
||||
)
|
||||
default_conf_usdt['exit_pricing'] = {
|
||||
'ignore_roi_if_buy_signal': False
|
||||
'ignore_roi_if_entry_signal': False
|
||||
}
|
||||
freqtrade = FreqtradeBot(default_conf_usdt)
|
||||
patch_get_signal(freqtrade, enter_short=is_short, enter_long=not is_short)
|
||||
@@ -4424,7 +4424,7 @@ def test_order_book_depth_of_market(
|
||||
mocker.patch.multiple(
|
||||
'freqtrade.exchange.Exchange',
|
||||
fetch_ticker=ticker_usdt,
|
||||
create_order=MagicMock(return_value=limit_order_open[enter_side(is_short)]),
|
||||
create_order=MagicMock(return_value=limit_order_open[entry_side(is_short)]),
|
||||
get_fee=fee,
|
||||
)
|
||||
|
||||
@@ -4449,7 +4449,7 @@ def test_order_book_depth_of_market(
|
||||
|
||||
# Simulate fulfilled LIMIT_BUY order for trade
|
||||
oobj = Order.parse_from_ccxt_object(
|
||||
limit_order_open[enter_side(is_short)], 'ADA/USDT', enter_side(is_short))
|
||||
limit_order_open[entry_side(is_short)], 'ADA/USDT', entry_side(is_short))
|
||||
trade.update_trade(oobj)
|
||||
|
||||
assert trade.open_rate == ticker_usdt.return_value[ticker_side]
|
||||
@@ -4638,7 +4638,7 @@ def test_cancel_all_open_orders(mocker, default_conf_usdt, fee, limit_order, lim
|
||||
side_effect=[
|
||||
ExchangeError(),
|
||||
limit_order[exit_side(is_short)],
|
||||
limit_order_open[enter_side(is_short)],
|
||||
limit_order_open[entry_side(is_short)],
|
||||
limit_order_open[exit_side(is_short)],
|
||||
]
|
||||
)
|
||||
@@ -4751,7 +4751,7 @@ def test_update_closed_trades_without_assigned_fees(mocker, default_conf_usdt, f
|
||||
for trade in trades:
|
||||
if trade.is_open:
|
||||
# Exclude Trade 4 - as the order is still open.
|
||||
if trade.select_order(enter_side(is_short), False):
|
||||
if trade.select_order(entry_side(is_short), False):
|
||||
assert trade.fee_open_cost is not None
|
||||
assert trade.fee_open_currency is not None
|
||||
else:
|
||||
@@ -5008,7 +5008,7 @@ def test_update_funding_fees(
|
||||
# SETUP
|
||||
time_machine.move_to("2021-09-01 00:00:00 +00:00")
|
||||
|
||||
open_order = limit_order_open[enter_side(is_short)]
|
||||
open_order = limit_order_open[entry_side(is_short)]
|
||||
open_exit_order = limit_order_open[exit_side(is_short)]
|
||||
bid = 0.11
|
||||
enter_rate_mock = MagicMock(return_value=bid)
|
||||
|
@@ -76,7 +76,7 @@ def test_init_dryrun_db(default_conf, tmpdir):
|
||||
@pytest.mark.parametrize('is_short', [False, True])
|
||||
@pytest.mark.usefixtures("init_persistence")
|
||||
def test_enter_exit_side(fee, is_short):
|
||||
enter_side, exit_side = ("sell", "buy") if is_short else ("buy", "sell")
|
||||
entry_side, exit_side = ("sell", "buy") if is_short else ("buy", "sell")
|
||||
trade = Trade(
|
||||
id=2,
|
||||
pair='ADA/USDT',
|
||||
@@ -92,7 +92,7 @@ def test_enter_exit_side(fee, is_short):
|
||||
leverage=2.0,
|
||||
trading_mode=margin
|
||||
)
|
||||
assert trade.enter_side == enter_side
|
||||
assert trade.entry_side == entry_side
|
||||
assert trade.exit_side == exit_side
|
||||
assert trade.trade_direction == 'short' if is_short else 'long'
|
||||
|
||||
@@ -456,7 +456,7 @@ def test_update_limit_order(fee, caplog, limit_buy_order_usdt, limit_sell_order_
|
||||
|
||||
enter_order = limit_sell_order_usdt if is_short else limit_buy_order_usdt
|
||||
exit_order = limit_buy_order_usdt if is_short else limit_sell_order_usdt
|
||||
enter_side, exit_side = ("sell", "buy") if is_short else ("buy", "sell")
|
||||
entry_side, exit_side = ("sell", "buy") if is_short else ("buy", "sell")
|
||||
|
||||
trade = Trade(
|
||||
id=2,
|
||||
@@ -479,13 +479,13 @@ def test_update_limit_order(fee, caplog, limit_buy_order_usdt, limit_sell_order_
|
||||
assert trade.close_date is None
|
||||
|
||||
trade.open_order_id = 'something'
|
||||
oobj = Order.parse_from_ccxt_object(enter_order, 'ADA/USDT', enter_side)
|
||||
oobj = Order.parse_from_ccxt_object(enter_order, 'ADA/USDT', entry_side)
|
||||
trade.update_trade(oobj)
|
||||
assert trade.open_order_id is None
|
||||
assert trade.open_rate == open_rate
|
||||
assert trade.close_profit is None
|
||||
assert trade.close_date is None
|
||||
assert log_has_re(f"LIMIT_{enter_side.upper()} has been fulfilled for "
|
||||
assert log_has_re(f"LIMIT_{entry_side.upper()} has been fulfilled for "
|
||||
r"Trade\(id=2, pair=ADA/USDT, amount=30.00000000, "
|
||||
f"is_short={is_short}, leverage={lev}, open_rate={open_rate}0000000, "
|
||||
r"open_since=.*\).",
|
||||
@@ -2135,19 +2135,19 @@ def test_select_order(fee, is_short):
|
||||
trades = Trade.get_trades().all()
|
||||
|
||||
# Open buy order, no sell order
|
||||
order = trades[0].select_order(trades[0].enter_side, True)
|
||||
order = trades[0].select_order(trades[0].entry_side, True)
|
||||
assert order is None
|
||||
order = trades[0].select_order(trades[0].enter_side, False)
|
||||
order = trades[0].select_order(trades[0].entry_side, False)
|
||||
assert order is not None
|
||||
order = trades[0].select_order(trades[0].exit_side, None)
|
||||
assert order is None
|
||||
|
||||
# closed buy order, and open sell order
|
||||
order = trades[1].select_order(trades[1].enter_side, True)
|
||||
order = trades[1].select_order(trades[1].entry_side, True)
|
||||
assert order is None
|
||||
order = trades[1].select_order(trades[1].enter_side, False)
|
||||
order = trades[1].select_order(trades[1].entry_side, False)
|
||||
assert order is not None
|
||||
order = trades[1].select_order(trades[1].enter_side, None)
|
||||
order = trades[1].select_order(trades[1].entry_side, None)
|
||||
assert order is not None
|
||||
order = trades[1].select_order(trades[1].exit_side, True)
|
||||
assert order is None
|
||||
@@ -2155,15 +2155,15 @@ def test_select_order(fee, is_short):
|
||||
assert order is not None
|
||||
|
||||
# Has open buy order
|
||||
order = trades[3].select_order(trades[3].enter_side, True)
|
||||
order = trades[3].select_order(trades[3].entry_side, True)
|
||||
assert order is not None
|
||||
order = trades[3].select_order(trades[3].enter_side, False)
|
||||
order = trades[3].select_order(trades[3].entry_side, False)
|
||||
assert order is None
|
||||
|
||||
# Open sell order
|
||||
order = trades[4].select_order(trades[4].enter_side, True)
|
||||
order = trades[4].select_order(trades[4].entry_side, True)
|
||||
assert order is None
|
||||
order = trades[4].select_order(trades[4].enter_side, False)
|
||||
order = trades[4].select_order(trades[4].entry_side, False)
|
||||
assert order is not None
|
||||
|
||||
trades[4].orders[1].ft_order_side = trades[4].exit_side
|
||||
@@ -2386,7 +2386,7 @@ def test_recalc_trade_from_orders_ignores_bad_orders(fee, is_short):
|
||||
o1_cost = o1_amount * o1_rate
|
||||
o1_fee_cost = o1_cost * fee.return_value
|
||||
o1_trade_val = o1_cost - o1_fee_cost if is_short else o1_cost + o1_fee_cost
|
||||
enter_side = "sell" if is_short else "buy"
|
||||
entry_side = "sell" if is_short else "buy"
|
||||
exit_side = "buy" if is_short else "sell"
|
||||
|
||||
trade = Trade(
|
||||
@@ -2402,16 +2402,16 @@ def test_recalc_trade_from_orders_ignores_bad_orders(fee, is_short):
|
||||
is_short=is_short,
|
||||
leverage=1.0,
|
||||
)
|
||||
trade.update_fee(o1_fee_cost, 'BNB', fee.return_value, enter_side)
|
||||
trade.update_fee(o1_fee_cost, 'BNB', fee.return_value, entry_side)
|
||||
# Check with 1 order
|
||||
order1 = Order(
|
||||
ft_order_side=enter_side,
|
||||
ft_order_side=entry_side,
|
||||
ft_pair=trade.pair,
|
||||
ft_is_open=False,
|
||||
status="closed",
|
||||
symbol=trade.pair,
|
||||
order_type="market",
|
||||
side=enter_side,
|
||||
side=entry_side,
|
||||
price=o1_rate,
|
||||
average=o1_rate,
|
||||
filled=o1_amount,
|
||||
@@ -2432,13 +2432,13 @@ def test_recalc_trade_from_orders_ignores_bad_orders(fee, is_short):
|
||||
assert trade.nr_of_successful_entries == 1
|
||||
|
||||
order2 = Order(
|
||||
ft_order_side=enter_side,
|
||||
ft_order_side=entry_side,
|
||||
ft_pair=trade.pair,
|
||||
ft_is_open=True,
|
||||
status="open",
|
||||
symbol=trade.pair,
|
||||
order_type="market",
|
||||
side=enter_side,
|
||||
side=entry_side,
|
||||
price=o1_rate,
|
||||
average=o1_rate,
|
||||
filled=o1_amount,
|
||||
@@ -2460,13 +2460,13 @@ def test_recalc_trade_from_orders_ignores_bad_orders(fee, is_short):
|
||||
|
||||
# Let's try with some other orders
|
||||
order3 = Order(
|
||||
ft_order_side=enter_side,
|
||||
ft_order_side=entry_side,
|
||||
ft_pair=trade.pair,
|
||||
ft_is_open=False,
|
||||
status="cancelled",
|
||||
symbol=trade.pair,
|
||||
order_type="market",
|
||||
side=enter_side,
|
||||
side=entry_side,
|
||||
price=1,
|
||||
average=2,
|
||||
filled=0,
|
||||
@@ -2487,13 +2487,13 @@ def test_recalc_trade_from_orders_ignores_bad_orders(fee, is_short):
|
||||
assert trade.nr_of_successful_entries == 1
|
||||
|
||||
order4 = Order(
|
||||
ft_order_side=enter_side,
|
||||
ft_order_side=entry_side,
|
||||
ft_pair=trade.pair,
|
||||
ft_is_open=False,
|
||||
status="closed",
|
||||
symbol=trade.pair,
|
||||
order_type="market",
|
||||
side=enter_side,
|
||||
side=entry_side,
|
||||
price=o1_rate,
|
||||
average=o1_rate,
|
||||
filled=o1_amount,
|
||||
@@ -2542,13 +2542,13 @@ def test_recalc_trade_from_orders_ignores_bad_orders(fee, is_short):
|
||||
|
||||
# Check with 1 order
|
||||
order_noavg = Order(
|
||||
ft_order_side=enter_side,
|
||||
ft_order_side=entry_side,
|
||||
ft_pair=trade.pair,
|
||||
ft_is_open=False,
|
||||
status="closed",
|
||||
symbol=trade.pair,
|
||||
order_type="market",
|
||||
side=enter_side,
|
||||
side=entry_side,
|
||||
price=o1_rate,
|
||||
average=None,
|
||||
filled=o1_amount,
|
||||
|
File diff suppressed because one or more lines are too long
2
tests/testdata/backtest-result_new.json
vendored
2
tests/testdata/backtest-result_new.json
vendored
File diff suppressed because one or more lines are too long
10
tests/testdata/strategy_SampleStrategy.fthypt
vendored
10
tests/testdata/strategy_SampleStrategy.fthypt
vendored
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user