SellType -> ExitType

This commit is contained in:
Sam Germain
2022-01-04 22:56:15 -06:00
parent f5805543ed
commit e9d3903827
22 changed files with 211 additions and 211 deletions

View File

@@ -13,7 +13,7 @@ from pandas import DataFrame
from freqtrade.configuration import TimeRange
from freqtrade.constants import DATETIME_PRINT_FORMAT, UNLIMITED_STAKE_AMOUNT
from freqtrade.data.history import get_timerange, load_data, refresh_data
from freqtrade.enums import RunMode, SellType
from freqtrade.enums import RunMode, ExitType
from freqtrade.exceptions import OperationalException
from freqtrade.exchange.exchange import timeframe_to_seconds
from freqtrade.plugins.pairlist.pairlist_helpers import expand_pairlist
@@ -454,7 +454,7 @@ class Edge:
if stop_index <= sell_index:
exit_index = open_trade_index + stop_index
exit_type = SellType.STOP_LOSS
exit_type = ExitType.STOP_LOSS
exit_price = stop_price
elif stop_index > sell_index:
# If exit is SELL then we exit at the next candle
@@ -464,7 +464,7 @@ class Edge:
if len(ohlc_columns) - 1 < exit_index:
break
exit_type = SellType.SELL_SIGNAL
exit_type = ExitType.SELL_SIGNAL
exit_price = ohlc_columns[exit_index, 0]
trade = {'pair': pair,

View File

@@ -5,7 +5,7 @@ from freqtrade.enums.collateral import Collateral
from freqtrade.enums.ordertypevalue import OrderTypeValues
from freqtrade.enums.rpcmessagetype import RPCMessageType
from freqtrade.enums.runmode import NON_UTIL_MODES, OPTIMIZE_MODES, TRADING_MODES, RunMode
from freqtrade.enums.selltype import SellType
from freqtrade.enums.exittype import ExitType
from freqtrade.enums.signaltype import SignalDirection, SignalTagType, SignalType
from freqtrade.enums.state import State
from freqtrade.enums.tradingmode import TradingMode

View File

@@ -1,7 +1,7 @@
from enum import Enum
class SellType(Enum):
class ExitType(Enum):
"""
Enum to distinguish between sell reasons
"""

View File

@@ -17,7 +17,7 @@ from freqtrade.configuration import validate_config_consistency
from freqtrade.data.converter import order_book_to_dataframe
from freqtrade.data.dataprovider import DataProvider
from freqtrade.edge import Edge
from freqtrade.enums import (Collateral, RPCMessageType, SellType, SignalDirection, State,
from freqtrade.enums import (Collateral, RPCMessageType, ExitType, SignalDirection, State,
TradingMode)
from freqtrade.exceptions import (DependencyException, ExchangeError, InsufficientFundsError,
InvalidOrderException, PricingError)
@@ -915,7 +915,7 @@ class FreqtradeBot(LoggingMixin):
logger.error(f'Unable to place a stoploss order on exchange. {e}')
logger.warning('Exiting the trade forcefully')
self.execute_trade_exit(trade, trade.stop_loss, exit_reason=SellCheckTuple(
sell_type=SellType.EMERGENCY_SELL))
sell_type=ExitType.EMERGENCY_SELL))
except ExchangeError:
trade.stoploss_order_id = None
@@ -947,7 +947,7 @@ class FreqtradeBot(LoggingMixin):
# We check if stoploss order is fulfilled
if stoploss_order and stoploss_order['status'] in ('closed', 'triggered'):
# TODO-lev: Update to exit reason
trade.exit_reason = SellType.STOPLOSS_ON_EXCHANGE.value
trade.exit_reason = ExitType.STOPLOSS_ON_EXCHANGE.value
self.update_trade_state(trade, trade.stoploss_order_id, stoploss_order,
stoploss_order=True)
# Lock pair for one candle to prevent immediate rebuys
@@ -1102,7 +1102,7 @@ class FreqtradeBot(LoggingMixin):
try:
self.execute_trade_exit(
trade, order.get('price'),
exit_reason=SellCheckTuple(sell_type=SellType.EMERGENCY_SELL))
exit_reason=SellCheckTuple(sell_type=ExitType.EMERGENCY_SELL))
except DependencyException as exception:
logger.warning(
f'Unable to emergency sell trade {trade.pair}: {exception}')
@@ -1284,7 +1284,7 @@ class FreqtradeBot(LoggingMixin):
trade.open_date
)
exit_type = 'sell' # TODO-lev: Update to exit
if exit_reason.sell_type in (SellType.STOP_LOSS, SellType.TRAILING_STOP_LOSS):
if exit_reason.sell_type in (ExitType.STOP_LOSS, ExitType.TRAILING_STOP_LOSS):
exit_type = 'stoploss'
# if stoploss is on exchange and we are on dry_run mode,
@@ -1314,7 +1314,7 @@ class FreqtradeBot(LoggingMixin):
logger.exception(f"Could not cancel stoploss order {trade.stoploss_order_id}")
order_type = ordertype or self.strategy.order_types[exit_type]
if exit_reason.sell_type == SellType.EMERGENCY_SELL:
if exit_reason.sell_type == ExitType.EMERGENCY_SELL:
# Emergency sells (default to market!)
order_type = self.strategy.order_types.get("emergencysell", "market")

View File

@@ -17,7 +17,7 @@ from freqtrade.data import history
from freqtrade.data.btanalysis import trade_list_to_dataframe
from freqtrade.data.converter import trim_dataframe, trim_dataframes
from freqtrade.data.dataprovider import DataProvider
from freqtrade.enums import BacktestState, CandleType, SellType, TradingMode
from freqtrade.enums import BacktestState, CandleType, ExitType, TradingMode
from freqtrade.exceptions import DependencyException, OperationalException
from freqtrade.exchange import timeframe_to_minutes, timeframe_to_seconds
from freqtrade.mixins import LoggingMixin
@@ -314,7 +314,7 @@ class Backtesting:
Get close rate for backtesting result
"""
# Special handling if high or low hit STOP_LOSS or ROI
if sell.sell_type in (SellType.STOP_LOSS, SellType.TRAILING_STOP_LOSS):
if sell.sell_type in (ExitType.STOP_LOSS, ExitType.TRAILING_STOP_LOSS):
if trade.stop_loss > sell_row[HIGH_IDX]:
# our stoploss was already higher than candle high,
# possibly due to a cancelled trade exit.
@@ -324,7 +324,7 @@ class Backtesting:
# Special case: trailing triggers within same candle as trade opened. Assume most
# pessimistic price movement, which is moving just enough to arm stoploss and
# immediately going down to stop price.
if sell.sell_type == SellType.TRAILING_STOP_LOSS and trade_dur == 0:
if sell.sell_type == ExitType.TRAILING_STOP_LOSS and trade_dur == 0:
if (
not self.strategy.use_custom_stoploss and self.strategy.trailing_stop
and self.strategy.trailing_only_offset_is_reached
@@ -345,7 +345,7 @@ class Backtesting:
# Set close_rate to stoploss
return trade.stop_loss
elif sell.sell_type == (SellType.ROI):
elif sell.sell_type == (ExitType.ROI):
roi_entry, roi = self.strategy.min_roi_reached_entry(trade_dur)
if roi is not None and roi_entry is not None:
if roi == -1 and roi_entry % self.timeframe_min == 0:
@@ -395,7 +395,7 @@ class Backtesting:
closerate = self._get_close_rate(sell_row, trade, sell, trade_dur)
# call the custom exit price,with default value as previous closerate
current_profit = trade.calc_profit_ratio(closerate)
if sell.sell_type in (SellType.SELL_SIGNAL, SellType.CUSTOM_SELL):
if sell.sell_type in (ExitType.SELL_SIGNAL, ExitType.CUSTOM_SELL):
# Custom exit pricing only for sell-signals
closerate = strategy_safe_wrapper(self.strategy.custom_exit_price,
default_retval=closerate)(
@@ -542,7 +542,7 @@ class Backtesting:
sell_row = data[pair][-1]
trade.close_date = sell_row[DATE_IDX].to_pydatetime()
trade.exit_reason = SellType.FORCE_SELL.value
trade.exit_reason = ExitType.FORCE_SELL.value
trade.close(sell_row[OPEN_IDX], show_msg=False)
LocalTrade.close_bt_trade(trade)
# Deepcopy object to have wallets update correctly

View File

@@ -14,7 +14,7 @@ from sqlalchemy.pool import StaticPool
from sqlalchemy.sql.schema import UniqueConstraint
from freqtrade.constants import DATETIME_PRINT_FORMAT, NON_OPEN_EXCHANGE_STATES
from freqtrade.enums import SellType, TradingMode
from freqtrade.enums import ExitType, TradingMode
from freqtrade.exceptions import DependencyException, OperationalException
from freqtrade.leverage import interest
from freqtrade.misc import safe_value_fallback
@@ -575,7 +575,7 @@ class LocalTrade():
elif order_type in ('stop_loss_limit', 'stop-loss', 'stop-loss-limit', 'stop'):
self.stoploss_order_id = None
self.close_rate_requested = self.stop_loss
self.exit_reason = SellType.STOPLOSS_ON_EXCHANGE.value
self.exit_reason = ExitType.STOPLOSS_ON_EXCHANGE.value
if self.is_open:
logger.info(f'{order_type.upper()} is hit for {self}.')
self.close(safe_value_fallback(order, 'average', 'price'))

View File

@@ -3,7 +3,7 @@ import logging
from datetime import datetime, timedelta
from typing import Any, Dict
from freqtrade.enums import SellType
from freqtrade.enums import ExitType
from freqtrade.persistence import Trade
from freqtrade.plugins.protections import IProtection, ProtectionReturn
@@ -44,8 +44,8 @@ class StoplossGuard(IProtection):
# filters = [
# Trade.is_open.is_(False),
# Trade.close_date > look_back_until,
# or_(Trade.exit_reason == SellType.STOP_LOSS.value,
# and_(Trade.exit_reason == SellType.TRAILING_STOP_LOSS.value,
# or_(Trade.exit_reason == ExitType.STOP_LOSS.value,
# and_(Trade.exit_reason == ExitType.TRAILING_STOP_LOSS.value,
# Trade.close_profit < 0))
# ]
# if pair:
@@ -55,8 +55,8 @@ class StoplossGuard(IProtection):
trades1 = Trade.get_trades_proxy(pair=pair, is_open=False, close_date=look_back_until)
trades = [trade for trade in trades1 if (str(trade.exit_reason) in (
SellType.TRAILING_STOP_LOSS.value, SellType.STOP_LOSS.value,
SellType.STOPLOSS_ON_EXCHANGE.value)
ExitType.TRAILING_STOP_LOSS.value, ExitType.STOP_LOSS.value,
ExitType.STOPLOSS_ON_EXCHANGE.value)
and trade.close_profit and trade.close_profit < 0)]
if len(trades) < self._trade_limit:

View File

@@ -17,7 +17,7 @@ from freqtrade import __version__
from freqtrade.configuration.timerange import TimeRange
from freqtrade.constants import CANCEL_REASON, DATETIME_PRINT_FORMAT
from freqtrade.data.history import load_data
from freqtrade.enums import SellType, State
from freqtrade.enums import ExitType, State
from freqtrade.exceptions import ExchangeError, PricingError
from freqtrade.exchange import timeframe_to_minutes, timeframe_to_msecs
from freqtrade.loggers import bufferHandler
@@ -672,7 +672,7 @@ class RPC:
closing_side = "buy" if trade.is_short else "sell"
current_rate = self._freqtrade.exchange.get_rate(
trade.pair, refresh=False, side=closing_side)
exit_reason = SellCheckTuple(sell_type=SellType.FORCE_SELL)
exit_reason = SellCheckTuple(sell_type=ExitType.FORCE_SELL)
order_type = ordertype or self._freqtrade.strategy.order_types.get(
"forcesell", self._freqtrade.strategy.order_types["sell"])

View File

@@ -13,7 +13,7 @@ from pandas import DataFrame
from freqtrade.constants import ListPairsWithTimeframes
from freqtrade.data.dataprovider import DataProvider
from freqtrade.enums import CandleType, SellType, SignalDirection, SignalTagType, SignalType
from freqtrade.enums import CandleType, ExitType, SignalDirection, SignalTagType, SignalType
from freqtrade.exceptions import OperationalException, StrategyError
from freqtrade.exchange import timeframe_to_minutes, timeframe_to_seconds
from freqtrade.exchange.exchange import timeframe_to_next_date
@@ -34,16 +34,16 @@ class SellCheckTuple:
"""
NamedTuple for Sell type + reason
"""
sell_type: SellType
sell_type: ExitType
exit_reason: str = ''
def __init__(self, sell_type: SellType, exit_reason: str = ''):
def __init__(self, sell_type: ExitType, exit_reason: str = ''):
self.sell_type = sell_type
self.exit_reason = exit_reason or sell_type.value
@property
def sell_flag(self):
return self.sell_type != SellType.NONE
return self.sell_type != ExitType.NONE
class IStrategy(ABC, HyperStrategyMixin):
@@ -784,7 +784,7 @@ class IStrategy(ABC, HyperStrategyMixin):
and self.min_roi_reached(trade=trade, current_profit=current_profit,
current_time=date))
sell_signal = SellType.NONE
sell_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 = SellType.SELL_SIGNAL
sell_signal = ExitType.SELL_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 = SellType.CUSTOM_SELL
sell_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,9 +811,9 @@ class IStrategy(ABC, HyperStrategyMixin):
custom_reason = custom_reason[:CUSTOM_SELL_MAX_LENGTH]
else:
custom_reason = None
if sell_signal in (SellType.CUSTOM_SELL, SellType.SELL_SIGNAL):
if sell_signal in (ExitType.CUSTOM_SELL, ExitType.SELL_SIGNAL):
logger.debug(f"{trade.pair} - Sell signal received. "
f"sell_type=SellType.{sell_signal.name}" +
f"sell_type=ExitType.{sell_signal.name}" +
(f", custom_reason={custom_reason}" if custom_reason else ""))
return SellCheckTuple(sell_type=sell_signal, exit_reason=custom_reason)
@@ -821,9 +821,9 @@ class IStrategy(ABC, HyperStrategyMixin):
# Exit-signal
# ROI (if not stoploss)
# Stoploss
if roi_reached and stoplossflag.sell_type != SellType.STOP_LOSS:
logger.debug(f"{trade.pair} - Required profit reached. sell_type=SellType.ROI")
return SellCheckTuple(sell_type=SellType.ROI)
if roi_reached and stoplossflag.sell_type != ExitType.STOP_LOSS:
logger.debug(f"{trade.pair} - Required profit reached. sell_type=ExitType.ROI")
return SellCheckTuple(sell_type=ExitType.ROI)
if stoplossflag.sell_flag:
@@ -832,7 +832,7 @@ class IStrategy(ABC, HyperStrategyMixin):
# This one is noisy, commented out...
# logger.debug(f"{trade.pair} - No exit signal.")
return SellCheckTuple(sell_type=SellType.NONE)
return SellCheckTuple(sell_type=ExitType.NONE)
def stop_loss_reached(self, current_rate: float, trade: Trade,
current_time: datetime, current_profit: float,
@@ -896,11 +896,11 @@ class IStrategy(ABC, HyperStrategyMixin):
if ((sl_higher_short or sl_lower_long) and
(not self.order_types.get('stoploss_on_exchange') or self.config['dry_run'])):
sell_type = SellType.STOP_LOSS
sell_type = ExitType.STOP_LOSS
# If initial stoploss is not the same as current one then it is trailing.
if trade.initial_stop_loss != trade.stop_loss:
sell_type = SellType.TRAILING_STOP_LOSS
sell_type = ExitType.TRAILING_STOP_LOSS
logger.debug(
f"{trade.pair} - HIT STOP: current price at "
f"{((high if trade.is_short else low) or current_rate):.6f}, "
@@ -917,7 +917,7 @@ class IStrategy(ABC, HyperStrategyMixin):
return SellCheckTuple(sell_type=sell_type)
return SellCheckTuple(sell_type=SellType.NONE)
return SellCheckTuple(sell_type=ExitType.NONE)
def min_roi_reached_entry(self, trade_dur: int) -> Tuple[Optional[int], Optional[float]]:
"""