sell_signal -> exit_signal

This commit is contained in:
Sam Germain 2022-01-04 23:01:57 -06:00
parent 93e332e506
commit 19692ff4e8
17 changed files with 45 additions and 45 deletions

View File

@ -275,7 +275,7 @@ A backtesting result will look like that:
|:-------------------|--------:|------:|-------:|--------:|
| trailing_stop_loss | 205 | 150 | 0 | 55 |
| stop_loss | 166 | 0 | 0 | 166 |
| sell_signal | 56 | 36 | 0 | 20 |
| exit_signal | 56 | 36 | 0 | 20 |
| force_sell | 2 | 0 | 0 | 2 |
====================================================== LEFT OPEN TRADES REPORT ======================================================
| Pair | Buys | Avg Profit % | Cum Profit % | Tot Profit BTC | Tot Profit % | Avg Duration | Win Draw Loss Win% |
@ -357,7 +357,7 @@ Hence, keep in mind that your performance is an integral mix of all different el
### Sell reasons table
The 2nd table contains a recap of sell reasons.
This table can tell you which area needs some additional work (e.g. all or many of the `sell_signal` trades are losses, so you should work on improving the sell signal, or consider disabling it).
This table can tell you which area needs some additional work (e.g. all or many of the `exit_signal` trades are losses, so you should work on improving the sell signal, or consider disabling it).
### Left open trades table

View File

@ -98,7 +98,7 @@ def custom_sell(self, pair: str, trade: Trade, current_time: datetime, current_r
dataframe, _ = self.dp.get_analyzed_dataframe(pair, self.timeframe)
last_candle = dataframe.iloc[-1].squeeze()
if trade.enter_tag == 'buy_signal_rsi' and last_candle['rsi'] > 80:
return 'sell_signal_rsi'
return 'exit_signal_rsi'
return None
```

View File

@ -557,7 +557,7 @@ class AwesomeStrategy(IStrategy):
:param time_in_force: Time in force. Defaults to GTC (Good-til-cancelled).
:param exit_reason: Sell reason.
Can be any of ['roi', 'stop_loss', 'stoploss_on_exchange', 'trailing_stop_loss',
'sell_signal', 'force_sell', 'emergency_sell']
'exit_signal', 'force_sell', 'emergency_sell']
:param current_time: datetime object, containing the current datetime
:param **kwargs: Ensure to keep this here so updates to this won't break your strategy.
:return bool: When True is returned, then the sell-order is placed on the exchange.

View File

@ -86,7 +86,7 @@ Example configuration showing the different settings:
"roi": "silent",
"emergency_sell": "on",
"force_sell": "on",
"sell_signal": "silent",
"exit_signal": "silent",
"trailing_stop_loss": "on",
"stop_loss": "on",
"stoploss_on_exchange": "on",

View File

@ -9,7 +9,7 @@ class ExitType(Enum):
STOP_LOSS = "stop_loss"
STOPLOSS_ON_EXCHANGE = "stoploss_on_exchange"
TRAILING_STOP_LOSS = "trailing_stop_loss"
EXIT_SIGNAL = "sell_signal"
EXIT_SIGNAL = "exit_signal"
FORCE_SELL = "force_sell"
EMERGENCY_SELL = "emergency_sell"
CUSTOM_SELL = "custom_sell"

View File

@ -346,7 +346,7 @@ class PairHistory(BaseModel):
data: List[Any]
length: int
buy_signals: int
sell_signals: int
exit_signals: int
enter_long_signals: int
exit_long_signals: int
enter_short_signals: int

View File

@ -958,7 +958,7 @@ class RPC:
'data': dataframe.values.tolist(),
'length': len(dataframe),
'buy_signals': signals['enter_long'], # Deprecated
'sell_signals': signals['exit_long'], # Deprecated
'exit_signals': signals['exit_long'], # Deprecated
'enter_long_signals': signals['enter_long'],
'exit_long_signals': signals['exit_long'],
'enter_short_signals': signals['enter_short'],

View File

@ -693,7 +693,7 @@ class Telegram(RPCHandler):
'stop_loss': 'Stoploss',
'trailing_stop_loss': 'Trail. Stop',
'stoploss_on_exchange': 'Stoploss',
'sell_signal': 'Sell Signal',
'exit_signal': 'Sell Signal',
'force_sell': 'Forcesell',
'emergency_sell': 'Emergency Sell',
}

View File

@ -275,7 +275,7 @@ class IStrategy(ABC, HyperStrategyMixin):
:param time_in_force: Time in force. Defaults to GTC (Good-til-cancelled).
:param exit_reason: Exit reason.
Can be any of ['roi', 'stop_loss', 'stoploss_on_exchange', 'trailing_stop_loss',
'sell_signal', 'force_sell', 'emergency_sell']
'exit_signal', 'force_sell', 'emergency_sell']
:param current_time: datetime object, containing the current datetime
:param **kwargs: Ensure to keep this here so updates to this won't break your strategy.
:return bool: When True, then the sell-order/exit_short-order is placed on the exchange.
@ -784,7 +784,7 @@ class IStrategy(ABC, HyperStrategyMixin):
and self.min_roi_reached(trade=trade, current_profit=current_profit,
current_time=date))
sell_signal = ExitType.NONE
exit_signal = ExitType.NONE
custom_reason = ''
# use provided rate in backtesting, not high/low.
current_rate = rate
@ -795,14 +795,14 @@ class IStrategy(ABC, HyperStrategyMixin):
pass
elif self.use_exit_signal and not enter:
if exit_:
sell_signal = ExitType.EXIT_SIGNAL
exit_signal = ExitType.EXIT_SIGNAL
else:
trade_type = "exit_short" if trade.is_short else "sell"
custom_reason = strategy_safe_wrapper(self.custom_sell, default_retval=False)(
pair=trade.pair, trade=trade, current_time=date, current_rate=current_rate,
current_profit=current_profit)
if custom_reason:
sell_signal = ExitType.CUSTOM_SELL
exit_signal = ExitType.CUSTOM_SELL
if isinstance(custom_reason, str):
if len(custom_reason) > CUSTOM_SELL_MAX_LENGTH:
logger.warning(f'Custom {trade_type} reason returned from '
@ -811,11 +811,11 @@ class IStrategy(ABC, HyperStrategyMixin):
custom_reason = custom_reason[:CUSTOM_SELL_MAX_LENGTH]
else:
custom_reason = None
if sell_signal in (ExitType.CUSTOM_SELL, ExitType.EXIT_SIGNAL):
if exit_signal in (ExitType.CUSTOM_SELL, ExitType.EXIT_SIGNAL):
logger.debug(f"{trade.pair} - Sell signal received. "
f"exit_type=ExitType.{sell_signal.name}" +
f"exit_type=ExitType.{exit_signal.name}" +
(f", custom_reason={custom_reason}" if custom_reason else ""))
return SellCheckTuple(exit_type=sell_signal, exit_reason=custom_reason)
return SellCheckTuple(exit_type=exit_signal, exit_reason=custom_reason)
# Sequence:
# Exit-signal

View File

@ -122,7 +122,7 @@ def confirm_trade_exit(self, pair: str, trade: 'Trade', order_type: str, amount:
:param time_in_force: Time in force. Defaults to GTC (Good-til-cancelled).
:param exit_reason: Sell reason.
Can be any of ['roi', 'stop_loss', 'stoploss_on_exchange', 'trailing_stop_loss',
'sell_signal', 'force_sell', 'emergency_sell']
'exit_signal', 'force_sell', 'emergency_sell']
:param current_time: datetime object, containing the current datetime
:param **kwargs: Ensure to keep this here so updates to this won't break your strategy.
:return bool: When True is returned, then the sell-order is placed on the exchange.

View File

@ -103,7 +103,7 @@ def mock_trade_2(fee, is_short: bool):
strategy='StrategyTestV3',
timeframe=5,
enter_tag='TEST1',
exit_reason='sell_signal',
exit_reason='exit_signal',
open_date=datetime.now(tz=timezone.utc) - timedelta(minutes=20),
close_date=datetime.now(tz=timezone.utc) - timedelta(minutes=2),
is_short=is_short
@ -400,7 +400,7 @@ def short_trade(fee):
open_order_id='dry_run_exit_short_12345',
strategy='DefaultStrategy',
timeframe=5,
exit_reason='sell_signal', # TODO-lev: Update to exit/close reason
exit_reason='exit_signal', # TODO-lev: Update to exit/close reason
open_date=datetime.now(tz=timezone.utc) - timedelta(minutes=20),
# close_date=datetime.now(tz=timezone.utc) - timedelta(minutes=2),
is_short=True
@ -489,7 +489,7 @@ def leverage_trade(fee):
open_order_id='dry_run_leverage_buy_12368',
strategy='DefaultStrategy',
timeframe=5,
exit_reason='sell_signal',
exit_reason='exit_signal',
open_date=datetime.now(tz=timezone.utc) - timedelta(minutes=300),
close_date=datetime.now(tz=timezone.utc),
interest_rate=0.0005

View File

@ -89,7 +89,7 @@ def mock_trade_usdt_2(fee):
open_order_id='dry_run_sell_12345',
strategy='StrategyTestV2',
timeframe=5,
exit_reason='sell_signal',
exit_reason='exit_signal',
open_date=datetime.now(tz=timezone.utc) - timedelta(minutes=20),
close_date=datetime.now(tz=timezone.utc) - timedelta(minutes=2),
)

View File

@ -391,7 +391,7 @@ def test_process_expectancy(mocker, edge_conf, fee, risk_reward_ratio, expectanc
'trade_duration': '',
'open_rate': 17,
'close_rate': 17,
'exit_type': 'sell_signal'},
'exit_type': 'exit_signal'},
{'pair': 'TEST/BTC',
'stoploss': -0.9,
@ -402,7 +402,7 @@ def test_process_expectancy(mocker, edge_conf, fee, risk_reward_ratio, expectanc
'trade_duration': '',
'open_rate': 20,
'close_rate': 20,
'exit_type': 'sell_signal'},
'exit_type': 'exit_signal'},
{'pair': 'TEST/BTC',
'stoploss': -0.9,
@ -413,7 +413,7 @@ def test_process_expectancy(mocker, edge_conf, fee, risk_reward_ratio, expectanc
'trade_duration': '',
'open_rate': 26,
'close_rate': 34,
'exit_type': 'sell_signal'}
'exit_type': 'exit_signal'}
]
trades_df = DataFrame(trades)
@ -457,7 +457,7 @@ def test_process_expectancy_remove_pumps(mocker, edge_conf, fee,):
'trade_duration': '',
'open_rate': 17,
'close_rate': 15,
'exit_type': 'sell_signal'},
'exit_type': 'exit_signal'},
{'pair': 'TEST/BTC',
'stoploss': -0.9,
@ -470,7 +470,7 @@ def test_process_expectancy_remove_pumps(mocker, edge_conf, fee,):
'trade_duration': '',
'open_rate': 20,
'close_rate': 10,
'exit_type': 'sell_signal'},
'exit_type': 'exit_signal'},
{'pair': 'TEST/BTC',
'stoploss': -0.9,
'profit_percent': '',
@ -482,7 +482,7 @@ def test_process_expectancy_remove_pumps(mocker, edge_conf, fee,):
'trade_duration': '',
'open_rate': 20,
'close_rate': 10,
'exit_type': 'sell_signal'},
'exit_type': 'exit_signal'},
{'pair': 'TEST/BTC',
'stoploss': -0.9,
'profit_percent': '',
@ -494,7 +494,7 @@ def test_process_expectancy_remove_pumps(mocker, edge_conf, fee,):
'trade_duration': '',
'open_rate': 20,
'close_rate': 10,
'exit_type': 'sell_signal'},
'exit_type': 'exit_signal'},
{'pair': 'TEST/BTC',
'stoploss': -0.9,
'profit_percent': '',
@ -506,7 +506,7 @@ def test_process_expectancy_remove_pumps(mocker, edge_conf, fee,):
'trade_duration': '',
'open_rate': 20,
'close_rate': 10,
'exit_type': 'sell_signal'},
'exit_type': 'exit_signal'},
{'pair': 'TEST/BTC',
'stoploss': -0.9,
@ -519,7 +519,7 @@ def test_process_expectancy_remove_pumps(mocker, edge_conf, fee,):
'trade_duration': '',
'open_rate': 26,
'close_rate': 134,
'exit_type': 'sell_signal'}
'exit_type': 'exit_signal'}
]
trades_df = DataFrame(trades)
@ -551,7 +551,7 @@ def test_process_expectancy_only_wins(mocker, edge_conf, fee,):
'trade_duration': '',
'open_rate': 15,
'close_rate': 17,
'exit_type': 'sell_signal'},
'exit_type': 'exit_signal'},
{'pair': 'TEST/BTC',
'stoploss': -0.9,
'profit_percent': '',
@ -563,7 +563,7 @@ def test_process_expectancy_only_wins(mocker, edge_conf, fee,):
'trade_duration': '',
'open_rate': 10,
'close_rate': 20,
'exit_type': 'sell_signal'},
'exit_type': 'exit_signal'},
{'pair': 'TEST/BTC',
'stoploss': -0.9,
'profit_percent': '',
@ -575,7 +575,7 @@ def test_process_expectancy_only_wins(mocker, edge_conf, fee,):
'trade_duration': '',
'open_rate': 26,
'close_rate': 134,
'exit_type': 'sell_signal'}
'exit_type': 'exit_signal'}
]
trades_df = DataFrame(trades)

View File

@ -973,7 +973,7 @@ def test_exit_reason_performance_handle_2(mocker, default_conf, markets, fee):
res = rpc._rpc_exit_reason_performance(None)
assert len(res) == 2
assert res[0]['exit_reason'] == 'sell_signal'
assert res[0]['exit_reason'] == 'exit_signal'
assert res[0]['count'] == 1
assert prec_satoshi(res[0]['profit_pct'], 0.5)
assert res[1]['exit_reason'] == 'roi'
@ -984,7 +984,7 @@ def test_exit_reason_performance_handle_2(mocker, default_conf, markets, fee):
res = rpc._rpc_exit_reason_performance('ETC/BTC')
assert len(res) == 1
assert res[0]['count'] == 1
assert res[0]['exit_reason'] == 'sell_signal'
assert res[0]['exit_reason'] == 'exit_signal'
assert prec_satoshi(res[0]['profit_pct'], 0.5)
@ -1046,7 +1046,7 @@ def test_mix_tag_performance_handle_2(mocker, default_conf, markets, fee):
res = rpc._rpc_mix_tag_performance(None)
assert len(res) == 2
assert res[0]['mix_tag'] == 'TEST1 sell_signal'
assert res[0]['mix_tag'] == 'TEST1 exit_signal'
assert res[0]['count'] == 1
assert prec_satoshi(res[0]['profit_pct'], 0.5)
assert res[1]['mix_tag'] == 'Other roi'
@ -1058,7 +1058,7 @@ def test_mix_tag_performance_handle_2(mocker, default_conf, markets, fee):
assert len(res) == 1
assert res[0]['count'] == 1
assert res[0]['mix_tag'] == 'TEST1 sell_signal'
assert res[0]['mix_tag'] == 'TEST1 exit_signal'
assert prec_satoshi(res[0]['profit_pct'], 0.5)

View File

@ -2091,7 +2091,7 @@ def test_send_msg_sell_notification_no_fiat(
({'profit_percent': 1.0, 'exit_reason': 'roi'}, "\N{EIGHT SPOKED ASTERISK}"),
({'profit_percent': 0.0, 'exit_reason': 'roi'}, "\N{EIGHT SPOKED ASTERISK}"),
({'profit_percent': -5.0, 'exit_reason': 'stop_loss'}, "\N{WARNING SIGN}"),
({'profit_percent': -2.0, 'exit_reason': 'sell_signal'}, "\N{CROSS MARK}"),
({'profit_percent': -2.0, 'exit_reason': 'exit_signal'}, "\N{CROSS MARK}"),
])
def test__sell_emoji(default_conf, mocker, msg, expected):
del default_conf['fiat_display_currency']

View File

@ -69,22 +69,22 @@ def test_returns_latest_signal(ohlcv_history):
mocked_history.loc[1, 'enter_long'] = 0
mocked_history.loc[1, 'enter_short'] = 1
mocked_history.loc[1, 'exit_short'] = 0
mocked_history.loc[1, 'enter_tag'] = 'sell_signal_01'
mocked_history.loc[1, 'enter_tag'] = 'exit_signal_01'
assert _STRATEGY.get_entry_signal(
'ETH/BTC', '5m', mocked_history) == (SignalDirection.SHORT, 'sell_signal_01')
'ETH/BTC', '5m', mocked_history) == (SignalDirection.SHORT, 'exit_signal_01')
assert _STRATEGY.get_exit_signal('ETH/BTC', '5m', mocked_history) == (False, False, None)
assert _STRATEGY.get_exit_signal('ETH/BTC', '5m', mocked_history, True) == (True, False, None)
mocked_history.loc[1, 'enter_short'] = 0
mocked_history.loc[1, 'exit_short'] = 1
mocked_history.loc[1, 'exit_tag'] = 'sell_signal_02'
mocked_history.loc[1, 'exit_tag'] = 'exit_signal_02'
assert _STRATEGY.get_entry_signal(
'ETH/BTC', '5m', mocked_history) == (None, None)
assert _STRATEGY.get_exit_signal(
'ETH/BTC', '5m', mocked_history) == (False, False, 'sell_signal_02')
'ETH/BTC', '5m', mocked_history) == (False, False, 'exit_signal_02')
assert _STRATEGY.get_exit_signal(
'ETH/BTC', '5m', mocked_history, True) == (False, True, 'sell_signal_02')
'ETH/BTC', '5m', mocked_history, True) == (False, True, 'exit_signal_02')
def test_analyze_pair_empty(default_conf, mocker, caplog, ohlcv_history):

View File

@ -1966,7 +1966,7 @@ def test_handle_trade(
freqtrade.wallets.update()
patch_get_signal(freqtrade, enter_long=False, exit_short=is_short,
exit_long=not is_short, exit_tag='sell_signal1')
exit_long=not is_short, exit_tag='exit_signal1')
assert freqtrade.handle_trade(trade) is True
assert trade.open_order_id == exit_order['id']
@ -1977,7 +1977,7 @@ def test_handle_trade(
assert trade.close_profit == close_profit
assert trade.calc_profit() == 5.685
assert trade.close_date is not None
assert trade.exit_reason == 'sell_signal1'
assert trade.exit_reason == 'exit_signal1'
@pytest.mark.parametrize("is_short", [False, True])