enter_tag can be used to determine roi
This commit is contained in:
parent
9029833c8c
commit
0310d1cdf2
@ -138,7 +138,7 @@ CONF_SCHEMA = {
|
|||||||
'minimal_roi': {
|
'minimal_roi': {
|
||||||
'type': 'object',
|
'type': 'object',
|
||||||
'patternProperties': {
|
'patternProperties': {
|
||||||
'^[0-9.]+$': {'type': 'number'}
|
'^[0-9a-zA-Z.]+$': {'type': ['number', 'dict']}
|
||||||
},
|
},
|
||||||
'minProperties': 1
|
'minProperties': 1
|
||||||
},
|
},
|
||||||
|
@ -932,7 +932,16 @@ class FreqtradeBot(LoggingMixin):
|
|||||||
logger.debug('checking exit')
|
logger.debug('checking exit')
|
||||||
exit_rate = self.exchange.get_rate(
|
exit_rate = self.exchange.get_rate(
|
||||||
trade.pair, side='exit', is_short=trade.is_short, refresh=True)
|
trade.pair, side='exit', is_short=trade.is_short, refresh=True)
|
||||||
if self._check_and_execute_exit(trade, exit_rate, enter, exit_, exit_tag):
|
|
||||||
|
enter_tag = # TODO
|
||||||
|
if self._check_and_execute_exit(
|
||||||
|
trade=trade,
|
||||||
|
exit_rate=exit_rate,
|
||||||
|
enter=enter,
|
||||||
|
exit_=exit_,
|
||||||
|
enter_tag=enter_tag,
|
||||||
|
exit_tag=exit_tag,
|
||||||
|
):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
logger.debug(f'Found no {exit_signal_type} signal for %s.', trade)
|
logger.debug(f'Found no {exit_signal_type} signal for %s.', trade)
|
||||||
@ -1089,8 +1098,15 @@ class FreqtradeBot(LoggingMixin):
|
|||||||
logger.warning(f"Could not create trailing stoploss order "
|
logger.warning(f"Could not create trailing stoploss order "
|
||||||
f"for pair {trade.pair}.")
|
f"for pair {trade.pair}.")
|
||||||
|
|
||||||
def _check_and_execute_exit(self, trade: Trade, exit_rate: float,
|
def _check_and_execute_exit(
|
||||||
enter: bool, exit_: bool, exit_tag: Optional[str]) -> bool:
|
self,
|
||||||
|
trade: Trade,
|
||||||
|
exit_rate: float,
|
||||||
|
enter: bool,
|
||||||
|
exit_: bool,
|
||||||
|
enter_tag: Optional[str],
|
||||||
|
exit_tag: Optional[str],
|
||||||
|
) -> bool:
|
||||||
"""
|
"""
|
||||||
Check and execute trade exit
|
Check and execute trade exit
|
||||||
"""
|
"""
|
||||||
@ -1100,7 +1116,8 @@ class FreqtradeBot(LoggingMixin):
|
|||||||
datetime.now(timezone.utc),
|
datetime.now(timezone.utc),
|
||||||
enter=enter,
|
enter=enter,
|
||||||
exit_=exit_,
|
exit_=exit_,
|
||||||
force_stoploss=self.edge.stoploss(trade.pair) if self.edge else 0
|
force_stoploss=self.edge.stoploss(trade.pair) if self.edge else 0,
|
||||||
|
enter_tag=enter_tag,
|
||||||
)
|
)
|
||||||
|
|
||||||
if should_exit.exit_flag:
|
if should_exit.exit_flag:
|
||||||
|
@ -143,8 +143,14 @@ class StrategyResolver(IResolver):
|
|||||||
# Sort and apply type conversions
|
# Sort and apply type conversions
|
||||||
if hasattr(strategy, 'minimal_roi'):
|
if hasattr(strategy, 'minimal_roi'):
|
||||||
strategy.minimal_roi = dict(sorted(
|
strategy.minimal_roi = dict(sorted(
|
||||||
{int(key): value for (key, value) in strategy.minimal_roi.items()}.items(),
|
{
|
||||||
key=lambda t: t[0]))
|
{int(k): v for (k, v) in value.items()}
|
||||||
|
if type(value is dict)
|
||||||
|
else int(key): value
|
||||||
|
for (key, value) in strategy.minimal_roi.items()
|
||||||
|
}.items(),
|
||||||
|
key=lambda t: t[0]
|
||||||
|
))
|
||||||
if hasattr(strategy, 'stoploss'):
|
if hasattr(strategy, 'stoploss'):
|
||||||
strategy.stoploss = float(strategy.stoploss)
|
strategy.stoploss = float(strategy.stoploss)
|
||||||
return strategy
|
return strategy
|
||||||
|
@ -160,7 +160,7 @@ class ShowConfig(BaseModel):
|
|||||||
available_capital: Optional[float]
|
available_capital: Optional[float]
|
||||||
stake_currency_decimals: int
|
stake_currency_decimals: int
|
||||||
max_open_trades: int
|
max_open_trades: int
|
||||||
minimal_roi: Dict[str, Any]
|
minimal_roi: Dict[str, Union[Dict[str, float], float]]
|
||||||
stoploss: Optional[float]
|
stoploss: Optional[float]
|
||||||
trailing_stop: Optional[bool]
|
trailing_stop: Optional[bool]
|
||||||
trailing_stop_positive: Optional[float]
|
trailing_stop_positive: Optional[float]
|
||||||
|
@ -843,7 +843,7 @@ class IStrategy(ABC, HyperStrategyMixin):
|
|||||||
def should_exit(self, trade: Trade, rate: float, current_time: datetime, *,
|
def should_exit(self, trade: Trade, rate: float, current_time: datetime, *,
|
||||||
enter: bool, exit_: bool,
|
enter: bool, exit_: bool,
|
||||||
low: float = None, high: float = None,
|
low: float = None, high: float = None,
|
||||||
force_stoploss: float = 0) -> ExitCheckTuple:
|
force_stoploss: float = 0, enter_tag: Optional[str] = None) -> ExitCheckTuple:
|
||||||
"""
|
"""
|
||||||
This function evaluates if one of the conditions required to trigger an exit order
|
This function evaluates if one of the conditions required to trigger an exit order
|
||||||
has been reached, which can either be a stop-loss, ROI or exit-signal.
|
has been reached, which can either be a stop-loss, ROI or exit-signal.
|
||||||
@ -868,9 +868,15 @@ class IStrategy(ABC, HyperStrategyMixin):
|
|||||||
current_profit = trade.calc_profit_ratio(current_rate)
|
current_profit = trade.calc_profit_ratio(current_rate)
|
||||||
|
|
||||||
# if enter signal and ignore_roi is set, we don't need to evaluate min_roi.
|
# if enter signal and ignore_roi is set, we don't need to evaluate min_roi.
|
||||||
roi_reached = (not (enter and self.ignore_roi_if_entry_signal)
|
roi_reached = (
|
||||||
and self.min_roi_reached(trade=trade, current_profit=current_profit,
|
not (enter and self.ignore_roi_if_entry_signal) and
|
||||||
current_time=current_time))
|
self.min_roi_reached(
|
||||||
|
trade=trade,
|
||||||
|
current_profit=current_profit,
|
||||||
|
current_time=current_time,
|
||||||
|
enter_tag=enter_tag,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
exit_signal = ExitType.NONE
|
exit_signal = ExitType.NONE
|
||||||
custom_reason = ''
|
custom_reason = ''
|
||||||
@ -1007,20 +1013,31 @@ class IStrategy(ABC, HyperStrategyMixin):
|
|||||||
|
|
||||||
return ExitCheckTuple(exit_type=ExitType.NONE)
|
return ExitCheckTuple(exit_type=ExitType.NONE)
|
||||||
|
|
||||||
def min_roi_reached_entry(self, trade_dur: int) -> Tuple[Optional[int], Optional[float]]:
|
def min_roi_reached_entry(
|
||||||
|
self,
|
||||||
|
trade_dur: int,
|
||||||
|
enter_tag: Optional[str] = None,
|
||||||
|
) -> Tuple[Optional[int], Optional[float]]:
|
||||||
"""
|
"""
|
||||||
Based on trade duration defines the ROI entry that may have been reached.
|
Based on trade duration defines the ROI entry that may have been reached.
|
||||||
:param trade_dur: trade duration in minutes
|
:param trade_dur: trade duration in minutes
|
||||||
:return: minimal ROI entry value or None if none proper ROI entry was found.
|
:return: minimal ROI entry value or None if none proper ROI entry was found.
|
||||||
"""
|
"""
|
||||||
|
minimal_roi = self.minimal_roi[enter_tag] if enter_tag else self.minimal_roi
|
||||||
# Get highest entry in ROI dict where key <= trade-duration
|
# Get highest entry in ROI dict where key <= trade-duration
|
||||||
roi_list = list(filter(lambda x: x <= trade_dur, self.minimal_roi.keys()))
|
roi_list = list(filter(lambda x: x <= trade_dur, minimal_roi.keys()))
|
||||||
if not roi_list:
|
if not roi_list:
|
||||||
return None, None
|
return None, None
|
||||||
roi_entry = max(roi_list)
|
roi_entry = max(roi_list)
|
||||||
return roi_entry, self.minimal_roi[roi_entry]
|
return roi_entry, minimal_roi[roi_entry]
|
||||||
|
|
||||||
def min_roi_reached(self, trade: Trade, current_profit: float, current_time: datetime) -> bool:
|
def min_roi_reached(
|
||||||
|
self,
|
||||||
|
trade: Trade,
|
||||||
|
current_profit: float,
|
||||||
|
current_time: datetime,
|
||||||
|
enter_tag: Optional[str] = None,
|
||||||
|
) -> bool:
|
||||||
"""
|
"""
|
||||||
Based on trade duration, current profit of the trade and ROI configuration,
|
Based on trade duration, current profit of the trade and ROI configuration,
|
||||||
decides whether bot should exit.
|
decides whether bot should exit.
|
||||||
@ -1029,7 +1046,7 @@ class IStrategy(ABC, HyperStrategyMixin):
|
|||||||
"""
|
"""
|
||||||
# Check if time matches and current rate is above threshold
|
# Check if time matches and current rate is above threshold
|
||||||
trade_dur = int((current_time.timestamp() - trade.open_date_utc.timestamp()) // 60)
|
trade_dur = int((current_time.timestamp() - trade.open_date_utc.timestamp()) // 60)
|
||||||
_, roi = self.min_roi_reached_entry(trade_dur)
|
_, roi = self.min_roi_reached_entry(trade_dur, enter_tag)
|
||||||
if roi is None:
|
if roi is None:
|
||||||
return False
|
return False
|
||||||
else:
|
else:
|
||||||
|
Loading…
Reference in New Issue
Block a user