Remove explicit sell_flag parameter from SellCheckTuple.
This commit is contained in:
parent
bfad4e82ad
commit
961b38636f
@ -851,7 +851,7 @@ class FreqtradeBot(LoggingMixin):
|
|||||||
logger.error(f'Unable to place a stoploss order on exchange. {e}')
|
logger.error(f'Unable to place a stoploss order on exchange. {e}')
|
||||||
logger.warning('Selling the trade forcefully')
|
logger.warning('Selling the trade forcefully')
|
||||||
self.execute_sell(trade, trade.stop_loss, sell_reason=SellCheckTuple(
|
self.execute_sell(trade, trade.stop_loss, sell_reason=SellCheckTuple(
|
||||||
sell_flag=True, sell_type=SellType.EMERGENCY_SELL))
|
sell_type=SellType.EMERGENCY_SELL))
|
||||||
|
|
||||||
except ExchangeError:
|
except ExchangeError:
|
||||||
trade.stoploss_order_id = None
|
trade.stoploss_order_id = None
|
||||||
|
@ -554,7 +554,7 @@ class RPC:
|
|||||||
if not fully_canceled:
|
if not fully_canceled:
|
||||||
# Get current rate and execute sell
|
# Get current rate and execute sell
|
||||||
current_rate = self._freqtrade.get_sell_rate(trade.pair, False)
|
current_rate = self._freqtrade.get_sell_rate(trade.pair, False)
|
||||||
sell_reason = SellCheckTuple(sell_flag=True, sell_type=SellType.FORCE_SELL)
|
sell_reason = SellCheckTuple(sell_type=SellType.FORCE_SELL)
|
||||||
self._freqtrade.execute_sell(trade, current_rate, sell_reason)
|
self._freqtrade.execute_sell(trade, current_rate, sell_reason)
|
||||||
# ---- EOF def _exec_forcesell ----
|
# ---- EOF def _exec_forcesell ----
|
||||||
|
|
||||||
|
@ -58,15 +58,17 @@ class SellCheckTuple(object):
|
|||||||
"""
|
"""
|
||||||
NamedTuple for Sell type + reason
|
NamedTuple for Sell type + reason
|
||||||
"""
|
"""
|
||||||
sell_flag: bool # TODO: Remove?
|
|
||||||
sell_type: SellType
|
sell_type: SellType
|
||||||
sell_reason: Optional[str]
|
sell_reason: Optional[str]
|
||||||
|
|
||||||
def __init__(self, sell_flag: bool, sell_type: SellType, sell_reason: Optional[str] = None):
|
def __init__(self, sell_type: SellType, sell_reason: Optional[str] = None):
|
||||||
self.sell_flag = sell_flag
|
|
||||||
self.sell_type = sell_type
|
self.sell_type = sell_type
|
||||||
self.sell_reason = sell_reason or sell_type.value
|
self.sell_reason = sell_reason or sell_type.value
|
||||||
|
|
||||||
|
@property
|
||||||
|
def sell_flag(self):
|
||||||
|
return self.sell_type != SellType.NONE
|
||||||
|
|
||||||
|
|
||||||
class IStrategy(ABC, HyperStrategyMixin):
|
class IStrategy(ABC, HyperStrategyMixin):
|
||||||
"""
|
"""
|
||||||
@ -593,25 +595,25 @@ class IStrategy(ABC, HyperStrategyMixin):
|
|||||||
# Sell-signal
|
# Sell-signal
|
||||||
# Stoploss
|
# Stoploss
|
||||||
if roi_reached and stoplossflag.sell_type != SellType.STOP_LOSS:
|
if roi_reached and stoplossflag.sell_type != SellType.STOP_LOSS:
|
||||||
logger.debug(f"{trade.pair} - Required profit reached. sell_flag=True, "
|
logger.debug(f"{trade.pair} - Required profit reached. "
|
||||||
f"sell_type=SellType.ROI")
|
f"sell_type=SellType.ROI")
|
||||||
return SellCheckTuple(sell_flag=True, sell_type=SellType.ROI)
|
return SellCheckTuple(sell_type=SellType.ROI)
|
||||||
|
|
||||||
if sell_signal != SellType.NONE:
|
if sell_signal != SellType.NONE:
|
||||||
logger.debug(f"{trade.pair} - Sell signal received. sell_flag=True, "
|
logger.debug(f"{trade.pair} - Sell signal received. "
|
||||||
f"sell_type=SellType.{sell_signal.name}" +
|
f"sell_type=SellType.{sell_signal.name}" +
|
||||||
(f", custom_reason={custom_reason}" if custom_reason else ""))
|
(f", custom_reason={custom_reason}" if custom_reason else ""))
|
||||||
return SellCheckTuple(sell_flag=True, sell_type=sell_signal, sell_reason=custom_reason)
|
return SellCheckTuple(sell_type=sell_signal, sell_reason=custom_reason)
|
||||||
|
|
||||||
if stoplossflag.sell_flag:
|
if stoplossflag.sell_flag:
|
||||||
|
|
||||||
logger.debug(f"{trade.pair} - Stoploss hit. sell_flag=True, "
|
logger.debug(f"{trade.pair} - Stoploss hit. "
|
||||||
f"sell_type={stoplossflag.sell_type}")
|
f"sell_type={stoplossflag.sell_type}")
|
||||||
return stoplossflag
|
return stoplossflag
|
||||||
|
|
||||||
# This one is noisy, commented out...
|
# This one is noisy, commented out...
|
||||||
# logger.debug(f"{trade.pair} - No sell signal. sell_flag=False")
|
# logger.debug(f"{trade.pair} - No sell signal.")
|
||||||
return SellCheckTuple(sell_flag=False, sell_type=SellType.NONE)
|
return SellCheckTuple(sell_type=SellType.NONE)
|
||||||
|
|
||||||
def stop_loss_reached(self, current_rate: float, trade: Trade,
|
def stop_loss_reached(self, current_rate: float, trade: Trade,
|
||||||
current_time: datetime, current_profit: float,
|
current_time: datetime, current_profit: float,
|
||||||
@ -675,9 +677,9 @@ class IStrategy(ABC, HyperStrategyMixin):
|
|||||||
logger.debug(f"{trade.pair} - Trailing stop saved "
|
logger.debug(f"{trade.pair} - Trailing stop saved "
|
||||||
f"{trade.stop_loss - trade.initial_stop_loss:.6f}")
|
f"{trade.stop_loss - trade.initial_stop_loss:.6f}")
|
||||||
|
|
||||||
return SellCheckTuple(sell_flag=True, sell_type=sell_type)
|
return SellCheckTuple(sell_type=sell_type)
|
||||||
|
|
||||||
return SellCheckTuple(sell_flag=False, sell_type=SellType.NONE)
|
return SellCheckTuple(sell_type=SellType.NONE)
|
||||||
|
|
||||||
def min_roi_reached_entry(self, trade_dur: int) -> Tuple[Optional[int], Optional[float]]:
|
def min_roi_reached_entry(self, trade_dur: int) -> Tuple[Optional[int], Optional[float]]:
|
||||||
"""
|
"""
|
||||||
|
@ -1973,7 +1973,7 @@ def test_handle_trade_roi(default_conf, ticker, limit_buy_order_open,
|
|||||||
# if ROI is reached we must sell
|
# if ROI is reached we must sell
|
||||||
patch_get_signal(freqtrade, value=(False, True))
|
patch_get_signal(freqtrade, value=(False, True))
|
||||||
assert freqtrade.handle_trade(trade)
|
assert freqtrade.handle_trade(trade)
|
||||||
assert log_has("ETH/BTC - Required profit reached. sell_flag=True, sell_type=SellType.ROI",
|
assert log_has("ETH/BTC - Required profit reached. sell_type=SellType.ROI",
|
||||||
caplog)
|
caplog)
|
||||||
|
|
||||||
|
|
||||||
@ -2002,7 +2002,7 @@ def test_handle_trade_use_sell_signal(
|
|||||||
|
|
||||||
patch_get_signal(freqtrade, value=(False, True))
|
patch_get_signal(freqtrade, value=(False, True))
|
||||||
assert freqtrade.handle_trade(trade)
|
assert freqtrade.handle_trade(trade)
|
||||||
assert log_has("ETH/BTC - Sell signal received. sell_flag=True, sell_type=SellType.SELL_SIGNAL",
|
assert log_has("ETH/BTC - Sell signal received. sell_type=SellType.SELL_SIGNAL",
|
||||||
caplog)
|
caplog)
|
||||||
|
|
||||||
|
|
||||||
@ -2607,7 +2607,7 @@ def test_execute_sell_up(default_conf, ticker, fee, ticker_sell_up, mocker) -> N
|
|||||||
)
|
)
|
||||||
# Prevented sell ...
|
# Prevented sell ...
|
||||||
freqtrade.execute_sell(trade=trade, limit=ticker_sell_up()['bid'],
|
freqtrade.execute_sell(trade=trade, limit=ticker_sell_up()['bid'],
|
||||||
sell_reason=SellCheckTuple(sell_flag=True, sell_type=SellType.ROI))
|
sell_reason=SellCheckTuple(sell_type=SellType.ROI))
|
||||||
assert rpc_mock.call_count == 0
|
assert rpc_mock.call_count == 0
|
||||||
assert freqtrade.strategy.confirm_trade_exit.call_count == 1
|
assert freqtrade.strategy.confirm_trade_exit.call_count == 1
|
||||||
|
|
||||||
@ -2615,7 +2615,7 @@ def test_execute_sell_up(default_conf, ticker, fee, ticker_sell_up, mocker) -> N
|
|||||||
freqtrade.strategy.confirm_trade_exit = MagicMock(return_value=True)
|
freqtrade.strategy.confirm_trade_exit = MagicMock(return_value=True)
|
||||||
|
|
||||||
freqtrade.execute_sell(trade=trade, limit=ticker_sell_up()['bid'],
|
freqtrade.execute_sell(trade=trade, limit=ticker_sell_up()['bid'],
|
||||||
sell_reason=SellCheckTuple(sell_flag=True, sell_type=SellType.ROI))
|
sell_reason=SellCheckTuple(sell_type=SellType.ROI))
|
||||||
assert freqtrade.strategy.confirm_trade_exit.call_count == 1
|
assert freqtrade.strategy.confirm_trade_exit.call_count == 1
|
||||||
|
|
||||||
assert rpc_mock.call_count == 1
|
assert rpc_mock.call_count == 1
|
||||||
@ -2667,7 +2667,7 @@ def test_execute_sell_down(default_conf, ticker, fee, ticker_sell_down, mocker)
|
|||||||
)
|
)
|
||||||
|
|
||||||
freqtrade.execute_sell(trade=trade, limit=ticker_sell_down()['bid'],
|
freqtrade.execute_sell(trade=trade, limit=ticker_sell_down()['bid'],
|
||||||
sell_reason=SellCheckTuple(sell_flag=True, sell_type=SellType.STOP_LOSS))
|
sell_reason=SellCheckTuple(sell_type=SellType.STOP_LOSS))
|
||||||
|
|
||||||
assert rpc_mock.call_count == 2
|
assert rpc_mock.call_count == 2
|
||||||
last_msg = rpc_mock.call_args_list[-1][0][0]
|
last_msg = rpc_mock.call_args_list[-1][0][0]
|
||||||
@ -2724,7 +2724,7 @@ def test_execute_sell_down_stoploss_on_exchange_dry_run(default_conf, ticker, fe
|
|||||||
|
|
||||||
trade.stop_loss = 0.00001099 * 0.99
|
trade.stop_loss = 0.00001099 * 0.99
|
||||||
freqtrade.execute_sell(trade=trade, limit=ticker_sell_down()['bid'],
|
freqtrade.execute_sell(trade=trade, limit=ticker_sell_down()['bid'],
|
||||||
sell_reason=SellCheckTuple(sell_flag=True, sell_type=SellType.STOP_LOSS))
|
sell_reason=SellCheckTuple(sell_type=SellType.STOP_LOSS))
|
||||||
|
|
||||||
assert rpc_mock.call_count == 2
|
assert rpc_mock.call_count == 2
|
||||||
last_msg = rpc_mock.call_args_list[-1][0][0]
|
last_msg = rpc_mock.call_args_list[-1][0][0]
|
||||||
@ -2776,7 +2776,7 @@ def test_execute_sell_sloe_cancel_exception(mocker, default_conf, ticker, fee, c
|
|||||||
trade.stoploss_order_id = "abcd"
|
trade.stoploss_order_id = "abcd"
|
||||||
|
|
||||||
freqtrade.execute_sell(trade=trade, limit=1234,
|
freqtrade.execute_sell(trade=trade, limit=1234,
|
||||||
sell_reason=SellCheckTuple(sell_flag=True, sell_type=SellType.STOP_LOSS))
|
sell_reason=SellCheckTuple(sell_type=SellType.STOP_LOSS))
|
||||||
assert sellmock.call_count == 1
|
assert sellmock.call_count == 1
|
||||||
assert log_has('Could not cancel stoploss order abcd', caplog)
|
assert log_has('Could not cancel stoploss order abcd', caplog)
|
||||||
|
|
||||||
@ -2826,7 +2826,7 @@ def test_execute_sell_with_stoploss_on_exchange(default_conf, ticker, fee, ticke
|
|||||||
)
|
)
|
||||||
|
|
||||||
freqtrade.execute_sell(trade=trade, limit=ticker_sell_up()['bid'],
|
freqtrade.execute_sell(trade=trade, limit=ticker_sell_up()['bid'],
|
||||||
sell_reason=SellCheckTuple(sell_flag=True, sell_type=SellType.STOP_LOSS))
|
sell_reason=SellCheckTuple(sell_type=SellType.STOP_LOSS))
|
||||||
|
|
||||||
trade = Trade.query.first()
|
trade = Trade.query.first()
|
||||||
assert trade
|
assert trade
|
||||||
@ -2932,7 +2932,7 @@ def test_execute_sell_market_order(default_conf, ticker, fee,
|
|||||||
freqtrade.config['order_types']['sell'] = 'market'
|
freqtrade.config['order_types']['sell'] = 'market'
|
||||||
|
|
||||||
freqtrade.execute_sell(trade=trade, limit=ticker_sell_up()['bid'],
|
freqtrade.execute_sell(trade=trade, limit=ticker_sell_up()['bid'],
|
||||||
sell_reason=SellCheckTuple(sell_flag=True, sell_type=SellType.ROI))
|
sell_reason=SellCheckTuple(sell_type=SellType.ROI))
|
||||||
|
|
||||||
assert not trade.is_open
|
assert not trade.is_open
|
||||||
assert trade.close_profit == 0.0620716
|
assert trade.close_profit == 0.0620716
|
||||||
@ -2986,7 +2986,7 @@ def test_execute_sell_insufficient_funds_error(default_conf, ticker, fee,
|
|||||||
fetch_ticker=ticker_sell_up
|
fetch_ticker=ticker_sell_up
|
||||||
)
|
)
|
||||||
|
|
||||||
sell_reason = SellCheckTuple(sell_flag=True, sell_type=SellType.ROI)
|
sell_reason = SellCheckTuple(sell_type=SellType.ROI)
|
||||||
assert not freqtrade.execute_sell(trade=trade, limit=ticker_sell_up()['bid'],
|
assert not freqtrade.execute_sell(trade=trade, limit=ticker_sell_up()['bid'],
|
||||||
sell_reason=sell_reason)
|
sell_reason=sell_reason)
|
||||||
assert mock_insuf.call_count == 1
|
assert mock_insuf.call_count == 1
|
||||||
@ -3081,7 +3081,7 @@ def test_sell_profit_only_enable_loss(default_conf, limit_buy_order, limit_buy_o
|
|||||||
freqtrade = FreqtradeBot(default_conf)
|
freqtrade = FreqtradeBot(default_conf)
|
||||||
patch_get_signal(freqtrade)
|
patch_get_signal(freqtrade)
|
||||||
freqtrade.strategy.stop_loss_reached = MagicMock(return_value=SellCheckTuple(
|
freqtrade.strategy.stop_loss_reached = MagicMock(return_value=SellCheckTuple(
|
||||||
sell_flag=False, sell_type=SellType.NONE))
|
sell_type=SellType.NONE))
|
||||||
freqtrade.enter_positions()
|
freqtrade.enter_positions()
|
||||||
|
|
||||||
trade = Trade.query.first()
|
trade = Trade.query.first()
|
||||||
@ -3230,7 +3230,7 @@ def test_locked_pairs(default_conf, ticker, fee, ticker_sell_down, mocker, caplo
|
|||||||
)
|
)
|
||||||
|
|
||||||
freqtrade.execute_sell(trade=trade, limit=ticker_sell_down()['bid'],
|
freqtrade.execute_sell(trade=trade, limit=ticker_sell_down()['bid'],
|
||||||
sell_reason=SellCheckTuple(sell_flag=True, sell_type=SellType.STOP_LOSS))
|
sell_reason=SellCheckTuple(sell_type=SellType.STOP_LOSS))
|
||||||
trade.close(ticker_sell_down()['bid'])
|
trade.close(ticker_sell_down()['bid'])
|
||||||
assert freqtrade.strategy.is_pair_locked(trade.pair)
|
assert freqtrade.strategy.is_pair_locked(trade.pair)
|
||||||
|
|
||||||
|
@ -51,8 +51,8 @@ def test_may_execute_sell_stoploss_on_exchange_multi(default_conf, ticker, fee,
|
|||||||
side_effect=[stoploss_order_closed, stoploss_order_open, stoploss_order_open])
|
side_effect=[stoploss_order_closed, stoploss_order_open, stoploss_order_open])
|
||||||
# Sell 3rd trade (not called for the first trade)
|
# Sell 3rd trade (not called for the first trade)
|
||||||
should_sell_mock = MagicMock(side_effect=[
|
should_sell_mock = MagicMock(side_effect=[
|
||||||
SellCheckTuple(sell_flag=False, sell_type=SellType.NONE),
|
SellCheckTuple(sell_type=SellType.NONE),
|
||||||
SellCheckTuple(sell_flag=True, sell_type=SellType.SELL_SIGNAL)]
|
SellCheckTuple(sell_type=SellType.SELL_SIGNAL)]
|
||||||
)
|
)
|
||||||
cancel_order_mock = MagicMock()
|
cancel_order_mock = MagicMock()
|
||||||
mocker.patch('freqtrade.exchange.Binance.stoploss', stoploss)
|
mocker.patch('freqtrade.exchange.Binance.stoploss', stoploss)
|
||||||
@ -156,11 +156,11 @@ def test_forcebuy_last_unlimited(default_conf, ticker, fee, limit_buy_order, moc
|
|||||||
_notify_sell=MagicMock(),
|
_notify_sell=MagicMock(),
|
||||||
)
|
)
|
||||||
should_sell_mock = MagicMock(side_effect=[
|
should_sell_mock = MagicMock(side_effect=[
|
||||||
SellCheckTuple(sell_flag=False, sell_type=SellType.NONE),
|
SellCheckTuple(sell_type=SellType.NONE),
|
||||||
SellCheckTuple(sell_flag=True, sell_type=SellType.SELL_SIGNAL),
|
SellCheckTuple(sell_type=SellType.SELL_SIGNAL),
|
||||||
SellCheckTuple(sell_flag=False, sell_type=SellType.NONE),
|
SellCheckTuple(sell_type=SellType.NONE),
|
||||||
SellCheckTuple(sell_flag=False, sell_type=SellType.NONE),
|
SellCheckTuple(sell_type=SellType.NONE),
|
||||||
SellCheckTuple(sell_flag=None, sell_type=SellType.NONE)]
|
SellCheckTuple(sell_type=SellType.NONE)]
|
||||||
)
|
)
|
||||||
mocker.patch("freqtrade.strategy.interface.IStrategy.should_sell", should_sell_mock)
|
mocker.patch("freqtrade.strategy.interface.IStrategy.should_sell", should_sell_mock)
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user