Add threading lock object for /forcesell

Protects against stoploss_on_exchange order recreation
in case of /forcesell (it's a timing issue, so may or may not happen).
This commit is contained in:
Matthias 2020-01-22 20:50:09 +01:00
parent 58ceda4b90
commit aad10ceee3
2 changed files with 30 additions and 23 deletions

View File

@ -7,6 +7,7 @@ import traceback
from datetime import datetime from datetime import datetime
from math import isclose from math import isclose
from os import getpid from os import getpid
from threading import Lock
from typing import Any, Dict, List, Optional, Tuple from typing import Any, Dict, List, Optional, Tuple
import arrow import arrow
@ -27,7 +28,6 @@ from freqtrade.state import State
from freqtrade.strategy.interface import IStrategy, SellType from freqtrade.strategy.interface import IStrategy, SellType
from freqtrade.wallets import Wallets from freqtrade.wallets import Wallets
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@ -92,6 +92,8 @@ class FreqtradeBot:
# the initial state of the bot. # the initial state of the bot.
# Keep this at the end of this initialization method. # Keep this at the end of this initialization method.
self.rpc: RPCManager = RPCManager(self) self.rpc: RPCManager = RPCManager(self)
# Protect sell-logic from forcesell and viceversa
self._sell_lock = Lock()
def cleanup(self) -> None: def cleanup(self) -> None:
""" """
@ -132,6 +134,10 @@ class FreqtradeBot:
self.dataprovider.refresh(self._create_pair_whitelist(self.active_pair_whitelist), self.dataprovider.refresh(self._create_pair_whitelist(self.active_pair_whitelist),
self.strategy.informative_pairs()) self.strategy.informative_pairs())
# Protect from collisions with forcesell.
# Without this, freqtrade my try to recreate stoploss_on_exchange orders
# while selling is in process, since telegram messages arrive in an different thread.
with self._sell_lock:
# First process current opened trades (positions) # First process current opened trades (positions)
self.exit_positions(trades) self.exit_positions(trades)

View File

@ -420,6 +420,7 @@ class RPC:
if self._freqtrade.state != State.RUNNING: if self._freqtrade.state != State.RUNNING:
raise RPCException('trader is not running') raise RPCException('trader is not running')
with self._freqtrade._sell_lock:
if trade_id == 'all': if trade_id == 'all':
# Execute sell for all open orders # Execute sell for all open orders
for trade in Trade.get_open_trades(): for trade in Trade.get_open_trades():