handle stop loss on exchange added
This commit is contained in:
parent
1dde56790c
commit
fea77824d0
@ -572,6 +572,17 @@ class FreqtradeBot(object):
|
||||
|
||||
trade.update(order)
|
||||
|
||||
# Check if stoploss on exchnage is hit first
|
||||
if self.strategy.stoploss_on_exchange and trade.stoploss_order_id:
|
||||
# Check if stoploss is hit
|
||||
result = self.handle_stoploss_on_exchage(trade)
|
||||
|
||||
# Updating wallets if stoploss is hit
|
||||
if result:
|
||||
self.wallets.update()
|
||||
|
||||
return result
|
||||
|
||||
if trade.is_open and trade.open_order_id is None:
|
||||
# Check if we can sell our current pair
|
||||
result = self.handle_trade(trade)
|
||||
@ -676,6 +687,19 @@ class FreqtradeBot(object):
|
||||
logger.info('Found no sell signals for whitelisted currencies. Trying again..')
|
||||
return False
|
||||
|
||||
def handle_stoploss_on_exchage(self, trade: Trade) -> bool:
|
||||
if not trade.is_open:
|
||||
raise ValueError(f'attempt to handle stoploss on exchnage for a closed trade: {trade}')
|
||||
|
||||
logger.debug('Handling stoploss on exchange %s ...', trade)
|
||||
order = self.exchange.get_order(trade.stoploss_order_id, trade.pair)
|
||||
if order['status'] == 'closed':
|
||||
trade.sell_reason = SellType.STOPLOSS_ON_EXCHNAGE.value
|
||||
trade.update(order)
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
def check_sell(self, trade: Trade, sell_rate: float, buy: bool, sell: bool) -> bool:
|
||||
if self.edge:
|
||||
stoploss = self.edge.stoploss(trade.pair)
|
||||
|
@ -178,7 +178,7 @@ class Trade(_DECL_BASE):
|
||||
# absolute value of the initial stop loss
|
||||
initial_stop_loss = Column(Float, nullable=True, default=0.0)
|
||||
# absolute value of the highest reached price
|
||||
stoploss_order_id = Column(Integer, nullable=True, index=True)
|
||||
stoploss_order_id = Column(String, nullable=True, index=True)
|
||||
max_rate = Column(Float, nullable=True, default=0.0)
|
||||
sell_reason = Column(String, nullable=True)
|
||||
strategy = Column(String, nullable=True)
|
||||
@ -250,6 +250,9 @@ class Trade(_DECL_BASE):
|
||||
self.open_order_id = None
|
||||
elif order_type == 'limit' and order['side'] == 'sell':
|
||||
self.close(order['price'])
|
||||
elif order_type == 'stop_loss_limit':
|
||||
self.stoploss_order_id = None
|
||||
self.close(order['price'])
|
||||
else:
|
||||
raise ValueError(f'Unknown order type: {order_type}')
|
||||
cleanup()
|
||||
|
@ -33,6 +33,7 @@ class SellType(Enum):
|
||||
"""
|
||||
ROI = "roi"
|
||||
STOP_LOSS = "stop_loss"
|
||||
STOPLOSS_ON_EXCHNAGE = "stoploss_on_exchange"
|
||||
TRAILING_STOP_LOSS = "trailing_stop_loss"
|
||||
SELL_SIGNAL = "sell_signal"
|
||||
FORCE_SELL = "force_sell"
|
||||
|
@ -931,7 +931,7 @@ def test_execute_buy_with_stoploss_on_exchange(mocker, default_conf,
|
||||
|
||||
trade = Trade.query.first()
|
||||
assert trade.is_open is True
|
||||
assert trade.stoploss_order_id == 13434334
|
||||
assert trade.stoploss_order_id == '13434334'
|
||||
|
||||
|
||||
def test_process_maybe_execute_buy(mocker, default_conf) -> None:
|
||||
@ -1572,7 +1572,8 @@ def test_execute_sell_with_stoploss_on_exchange(default_conf,
|
||||
get_ticker=ticker_sell_up
|
||||
)
|
||||
|
||||
freqtrade.execute_sell(trade=trade, limit=ticker_sell_up()['bid'], sell_reason=SellType.ROI)
|
||||
freqtrade.execute_sell(trade=trade, limit=ticker_sell_up()['bid'],
|
||||
sell_reason=SellType.SELL_SIGNAL)
|
||||
|
||||
trade = Trade.query.first()
|
||||
assert trade
|
||||
@ -1580,6 +1581,76 @@ def test_execute_sell_with_stoploss_on_exchange(default_conf,
|
||||
assert rpc_mock.call_count == 2
|
||||
|
||||
|
||||
def test_may_execute_sell_after_stoploss_on_exchange_hit(default_conf,
|
||||
ticker, fee,
|
||||
limit_buy_order,
|
||||
markets, mocker) -> None:
|
||||
default_conf['exchange']['name'] = 'binance'
|
||||
rpc_mock = patch_RPCManager(mocker)
|
||||
mocker.patch.multiple(
|
||||
'freqtrade.exchange.Exchange',
|
||||
_load_markets=MagicMock(return_value={}),
|
||||
get_ticker=ticker,
|
||||
get_fee=fee,
|
||||
get_markets=markets
|
||||
)
|
||||
|
||||
stoploss_limit = MagicMock(return_value={
|
||||
'id': 123,
|
||||
'info': {
|
||||
'foo': 'bar'
|
||||
}
|
||||
})
|
||||
|
||||
mocker.patch('freqtrade.exchange.Exchange.symbol_amount_prec', lambda s, x, y: y)
|
||||
mocker.patch('freqtrade.exchange.Exchange.symbol_price_prec', lambda s, x, y: y)
|
||||
mocker.patch('freqtrade.exchange.Exchange.stoploss_limit', stoploss_limit)
|
||||
|
||||
freqtrade = FreqtradeBot(default_conf)
|
||||
freqtrade.strategy.stoploss_on_exchange = True
|
||||
patch_get_signal(freqtrade)
|
||||
|
||||
# Create some test data
|
||||
freqtrade.create_trade()
|
||||
|
||||
trade = Trade.query.first()
|
||||
assert trade
|
||||
assert trade.stoploss_order_id == '123'
|
||||
assert trade.open_order_id is not None
|
||||
|
||||
trade.update(limit_buy_order)
|
||||
|
||||
# Assuming stoploss on exchnage is hit
|
||||
# stoploss_order_id should become None
|
||||
# and trade should be sold at the price of stoploss
|
||||
stoploss_limit_executed = MagicMock(return_value={
|
||||
"id": "123",
|
||||
"timestamp": 1542707426845,
|
||||
"datetime": "2018-11-20T09:50:26.845Z",
|
||||
"lastTradeTimestamp": None,
|
||||
"symbol": "BTC/USDT",
|
||||
"type": "stop_loss_limit",
|
||||
"side": "sell",
|
||||
"price": 1.08801,
|
||||
"amount": 90.99181074,
|
||||
"cost": 99.0000000032274,
|
||||
"average": 1.08801,
|
||||
"filled": 90.99181074,
|
||||
"remaining": 0.0,
|
||||
"status": "closed",
|
||||
"fee": None,
|
||||
"trades": None
|
||||
})
|
||||
mocker.patch('freqtrade.exchange.Exchange.get_order', stoploss_limit_executed)
|
||||
|
||||
freqtrade.process_maybe_execute_sell(trade)
|
||||
assert trade.stoploss_order_id is None
|
||||
assert trade.is_open is False
|
||||
print(trade.sell_reason)
|
||||
assert trade.sell_reason == SellType.STOPLOSS_ON_EXCHNAGE.value
|
||||
assert rpc_mock.call_count == 1
|
||||
|
||||
|
||||
def test_execute_sell_without_conf_sell_up(default_conf, ticker, fee,
|
||||
ticker_sell_up, markets, mocker) -> None:
|
||||
rpc_mock = patch_RPCManager(mocker)
|
||||
|
Loading…
Reference in New Issue
Block a user