stoploss on exchange added as a parameter to order_types

This commit is contained in:
misagh 2018-11-25 17:22:56 +01:00
parent e4744c1ba4
commit 3e29fbb17a
7 changed files with 37 additions and 32 deletions

View File

@ -109,7 +109,8 @@ CONF_SCHEMA = {
'properties': { 'properties': {
'buy': {'type': 'string', 'enum': ORDERTYPE_POSSIBILITIES}, 'buy': {'type': 'string', 'enum': ORDERTYPE_POSSIBILITIES},
'sell': {'type': 'string', 'enum': ORDERTYPE_POSSIBILITIES}, 'sell': {'type': 'string', 'enum': ORDERTYPE_POSSIBILITIES},
'stoploss': {'type': 'string', 'enum': ORDERTYPE_POSSIBILITIES} 'stoploss': {'type': 'string', 'enum': ORDERTYPE_POSSIBILITIES},
'stoploss_on_exchange': {'type': 'boolean'}
}, },
'required': ['buy', 'sell', 'stoploss'] 'required': ['buy', 'sell', 'stoploss']
}, },

View File

@ -227,6 +227,12 @@ class Exchange(object):
raise OperationalException( raise OperationalException(
f'Exchange {self.name} does not support market orders.') f'Exchange {self.name} does not support market orders.')
if order_types.get('stoploss_on_exchange', False):
if self.name is not 'Binance':
raise OperationalException(
'On exchange stoploss is not supported for %s.' % self.name
)
def exchange_has(self, endpoint: str) -> bool: def exchange_has(self, endpoint: str) -> bool:
""" """
Checks if exchange implements a specific API endpoint. Checks if exchange implements a specific API endpoint.

View File

@ -54,7 +54,6 @@ class FreqtradeBot(object):
# Init objects # Init objects
self.config = config self.config = config
self.strategy: IStrategy = StrategyResolver(self.config).strategy self.strategy: IStrategy = StrategyResolver(self.config).strategy
self.check_strategy_config_consistency(config, self.strategy)
self.rpc: RPCManager = RPCManager(self) self.rpc: RPCManager = RPCManager(self)
self.persistence = None self.persistence = None
@ -68,16 +67,6 @@ class FreqtradeBot(object):
self.active_pair_whitelist: List[str] = self.config['exchange']['pair_whitelist'] self.active_pair_whitelist: List[str] = self.config['exchange']['pair_whitelist']
self._init_modules() self._init_modules()
def check_strategy_config_consistency(self, config, strategy: IStrategy) -> None:
"""
checks if config is compatible with the given strategy
"""
# Stoploss on exchange is only implemented for binance
if strategy.stoploss_on_exchange and config.get('exchange') is not 'binance':
raise OperationalException(
'On exchange stoploss is not supported for %s.' % config['exchange']['name']
)
def _init_modules(self) -> None: def _init_modules(self) -> None:
""" """
Initializes all modules and updates the config Initializes all modules and updates the config
@ -567,7 +556,7 @@ class FreqtradeBot(object):
trade.update(order) trade.update(order)
if self.strategy.stoploss_on_exchange: if self.strategy.order_types.get('stoploss_on_exchange'):
result = self.handle_stoploss_on_exchange(trade) result = self.handle_stoploss_on_exchange(trade)
if result: if result:
self.wallets.update() self.wallets.update()
@ -844,7 +833,7 @@ class FreqtradeBot(object):
sell_type = 'stoploss' sell_type = 'stoploss'
# First cancelling stoploss on exchange ... # First cancelling stoploss on exchange ...
if self.strategy.stoploss_on_exchange and trade.stoploss_order_id: if self.strategy.order_types.get('stoploss_on_exchange') and trade.stoploss_order_id:
self.exchange.cancel_order(trade.stoploss_order_id, trade.pair) self.exchange.cancel_order(trade.stoploss_order_id, trade.pair)
# Execute sell and update trade record # Execute sell and update trade record

View File

@ -32,7 +32,8 @@ class DefaultStrategy(IStrategy):
order_types = { order_types = {
'buy': 'limit', 'buy': 'limit',
'sell': 'limit', 'sell': 'limit',
'stoploss': 'limit' 'stoploss': 'limit',
'stoploss_on_exchange': False
} }
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame: def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:

View File

@ -68,11 +68,6 @@ class IStrategy(ABC):
# associated stoploss # associated stoploss
stoploss: float stoploss: float
# if the stoploss should be on exchange.
# if this is True then a stoploss order will be placed
# immediately after a successful buy order.
stoploss_on_exchange: bool = False
# associated ticker interval # associated ticker interval
ticker_interval: str ticker_interval: str
@ -80,7 +75,8 @@ class IStrategy(ABC):
order_types: Dict = { order_types: Dict = {
'buy': 'limit', 'buy': 'limit',
'sell': 'limit', 'sell': 'limit',
'stoploss': 'limit' 'stoploss': 'limit',
'stoploss_on_exchange': False
} }
# run "populate_indicators" only for new candle # run "populate_indicators" only for new candle
@ -228,7 +224,7 @@ class IStrategy(ABC):
current_rate = low or rate current_rate = low or rate
current_profit = trade.calc_profit_percent(current_rate) current_profit = trade.calc_profit_percent(current_rate)
if self.stoploss_on_exchange: if self.order_types.get('stoploss_on_exchange'):
stoplossflag = SellCheckTuple(sell_flag=False, sell_type=SellType.NONE) stoplossflag = SellCheckTuple(sell_flag=False, sell_type=SellType.NONE)
else: else:
stoplossflag = self.stop_loss_reached(current_rate=current_rate, trade=trade, stoplossflag = self.stop_loss_reached(current_rate=current_rate, trade=trade,

View File

@ -362,7 +362,14 @@ def test_validate_order_types(default_conf, mocker):
mocker.patch('freqtrade.exchange.Exchange._init_ccxt', MagicMock(return_value=api_mock)) mocker.patch('freqtrade.exchange.Exchange._init_ccxt', MagicMock(return_value=api_mock))
mocker.patch('freqtrade.exchange.Exchange._load_markets', MagicMock(return_value={})) mocker.patch('freqtrade.exchange.Exchange._load_markets', MagicMock(return_value={}))
mocker.patch('freqtrade.exchange.Exchange.validate_timeframes', MagicMock()) mocker.patch('freqtrade.exchange.Exchange.validate_timeframes', MagicMock())
default_conf['order_types'] = {'buy': 'limit', 'sell': 'limit', 'stoploss': 'market'} mocker.patch('freqtrade.exchange.Exchange.name', 'Bittrex')
default_conf['order_types'] = {
'buy': 'limit',
'sell': 'limit',
'stoploss': 'market',
'stoploss_on_exchange': False
}
Exchange(default_conf) Exchange(default_conf)
type(api_mock).has = PropertyMock(return_value={'createMarketOrder': False}) type(api_mock).has = PropertyMock(return_value={'createMarketOrder': False})
@ -374,6 +381,17 @@ def test_validate_order_types(default_conf, mocker):
match=r'Exchange .* does not support market orders.'): match=r'Exchange .* does not support market orders.'):
Exchange(default_conf) Exchange(default_conf)
default_conf['order_types'] = {
'buy': 'limit',
'sell': 'limit',
'stoploss': 'limit',
'stoploss_on_exchange': True
}
with pytest.raises(OperationalException,
match=r'On exchange stoploss is not supported for .*'):
Exchange(default_conf)
def test_validate_order_types_not_in_config(default_conf, mocker): def test_validate_order_types_not_in_config(default_conf, mocker):
api_mock = MagicMock() api_mock = MagicMock()

View File

@ -893,7 +893,7 @@ def test_add_stoploss_on_exchange(mocker, default_conf, limit_buy_order) -> None
mocker.patch('freqtrade.exchange.Exchange.stoploss_limit', stoploss_limit) mocker.patch('freqtrade.exchange.Exchange.stoploss_limit', stoploss_limit)
freqtrade = FreqtradeBot(default_conf) freqtrade = FreqtradeBot(default_conf)
freqtrade.strategy.stoploss_on_exchange = True freqtrade.strategy.order_types['stoploss_on_exchange'] = True
trade = MagicMock() trade = MagicMock()
trade.open_order_id = None trade.open_order_id = None
@ -1595,7 +1595,7 @@ def test_execute_sell_with_stoploss_on_exchange(default_conf,
mocker.patch('freqtrade.exchange.Exchange.cancel_order', cancel_order) mocker.patch('freqtrade.exchange.Exchange.cancel_order', cancel_order)
freqtrade = FreqtradeBot(default_conf) freqtrade = FreqtradeBot(default_conf)
freqtrade.strategy.stoploss_on_exchange = True freqtrade.strategy.order_types['stoploss_on_exchange'] = True
patch_get_signal(freqtrade) patch_get_signal(freqtrade)
# Create some test data # Create some test data
@ -1647,7 +1647,7 @@ def test_may_execute_sell_after_stoploss_on_exchange_hit(default_conf,
mocker.patch('freqtrade.exchange.Exchange.stoploss_limit', stoploss_limit) mocker.patch('freqtrade.exchange.Exchange.stoploss_limit', stoploss_limit)
freqtrade = FreqtradeBot(default_conf) freqtrade = FreqtradeBot(default_conf)
freqtrade.strategy.stoploss_on_exchange = True freqtrade.strategy.order_types['stoploss_on_exchange'] = True
patch_get_signal(freqtrade) patch_get_signal(freqtrade)
# Create some test data # Create some test data
@ -2516,9 +2516,3 @@ def test_startup_messages(default_conf, mocker):
default_conf['dynamic_whitelist'] = 20 default_conf['dynamic_whitelist'] = 20
freqtrade = get_patched_freqtradebot(mocker, default_conf) freqtrade = get_patched_freqtradebot(mocker, default_conf)
assert freqtrade.state is State.RUNNING assert freqtrade.state is State.RUNNING
def test_check_consistency(default_conf, mocker, caplog):
mocker.patch('freqtrade.freqtradebot.IStrategy.stoploss_on_exchange', True)
with pytest.raises(OperationalException):
FreqtradeBot(default_conf)