Merge branch 'develop' into stoploss_market

This commit is contained in:
Matthias 2020-01-23 19:35:05 +01:00
commit 1d141cd406
3 changed files with 44 additions and 43 deletions

View File

@ -7,6 +7,7 @@ import traceback
from datetime import datetime
from math import isclose
from os import getpid
from threading import Lock
from typing import Any, Dict, List, Optional, Tuple
import arrow
@ -27,7 +28,6 @@ from freqtrade.state import State
from freqtrade.strategy.interface import IStrategy, SellType
from freqtrade.wallets import Wallets
logger = logging.getLogger(__name__)
@ -92,6 +92,8 @@ class FreqtradeBot:
# the initial state of the bot.
# Keep this at the end of this initialization method.
self.rpc: RPCManager = RPCManager(self)
# Protect sell-logic from forcesell and viceversa
self._sell_lock = Lock()
def cleanup(self) -> None:
"""
@ -132,6 +134,10 @@ class FreqtradeBot:
self.dataprovider.refresh(self._create_pair_whitelist(self.active_pair_whitelist),
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)
self.exit_positions(trades)

View File

@ -420,11 +420,13 @@ class RPC:
if self._freqtrade.state != State.RUNNING:
raise RPCException('trader is not running')
with self._freqtrade._sell_lock:
if trade_id == 'all':
# Execute sell for all open orders
for trade in Trade.get_open_trades():
_exec_forcesell(trade)
Trade.session.flush()
self._freqtrade.wallets.update()
return {'result': 'Created sell orders for all open trades.'}
# Query for trade
@ -437,6 +439,7 @@ class RPC:
_exec_forcesell(trade)
Trade.session.flush()
self._freqtrade.wallets.update()
return {'result': f'Created sell order for trade {trade_id}.'}
def _rpc_forcebuy(self, pair: str, price: Optional[float]) -> Optional[Trade]:

View File

@ -906,30 +906,22 @@ def test_process_informative_pairs_added(default_conf, ticker, mocker) -> None:
assert ("ETH/BTC", default_conf["ticker_interval"]) in refresh_mock.call_args[0][0]
def test_balance_fully_ask_side(mocker, default_conf) -> None:
default_conf['bid_strategy']['ask_last_balance'] = 0.0
@pytest.mark.parametrize("ask,last,last_ab,expected", [
(20, 10, 0.0, 20), # Full ask side
(20, 10, 1.0, 10), # Full last side
(20, 10, 0.5, 15), # Between ask and last
(20, 10, 0.7, 13), # Between ask and last
(20, 10, 0.3, 17), # Between ask and last
(5, 10, 1.0, 5), # last bigger than ask
(5, 10, 0.5, 5), # last bigger than ask
])
def test_get_buy_rate(mocker, default_conf, ask, last, last_ab, expected) -> None:
default_conf['bid_strategy']['ask_last_balance'] = last_ab
freqtrade = get_patched_freqtradebot(mocker, default_conf)
mocker.patch('freqtrade.exchange.Exchange.fetch_ticker',
MagicMock(return_value={'ask': 20, 'last': 10}))
MagicMock(return_value={'ask': ask, 'last': last}))
assert freqtrade.get_buy_rate('ETH/BTC') == 20
def test_balance_fully_last_side(mocker, default_conf) -> None:
default_conf['bid_strategy']['ask_last_balance'] = 1.0
freqtrade = get_patched_freqtradebot(mocker, default_conf)
mocker.patch('freqtrade.exchange.Exchange.fetch_ticker',
MagicMock(return_value={'ask': 20, 'last': 10}))
assert freqtrade.get_buy_rate('ETH/BTC') == 10
def test_balance_bigger_last_ask(mocker, default_conf) -> None:
default_conf['bid_strategy']['ask_last_balance'] = 1.0
freqtrade = get_patched_freqtradebot(mocker, default_conf)
mocker.patch('freqtrade.exchange.Exchange.fetch_ticker',
MagicMock(return_value={'ask': 5, 'last': 10}))
assert freqtrade.get_buy_rate('ETH/BTC') == 5
assert freqtrade.get_buy_rate('ETH/BTC') == expected
def test_execute_buy(mocker, default_conf, fee, limit_buy_order) -> None: