Merge branch 'develop' into stoploss_market

This commit is contained in:
Matthias 2020-01-22 20:51:52 +01:00
commit bc4c469797
11 changed files with 38 additions and 27 deletions

View File

@ -2,6 +2,7 @@
# Downloaded from https://www.lfd.uci.edu/~gohlke/pythonlibs/#ta-lib
# Invoke-WebRequest -Uri "https://download.lfd.uci.edu/pythonlibs/xxxxxxx/TA_Lib-0.4.17-cp37-cp37m-win_amd64.whl" -OutFile "TA_Lib-0.4.17-cp37-cp37m-win_amd64.whl"
python -m pip install --upgrade pip
pip install build_helpers\TA_Lib-0.4.17-cp37-cp37m-win_amd64.whl
pip install -r requirements-dev.txt

View File

@ -63,8 +63,7 @@ class FreqtradeBot:
self.exchange = ExchangeResolver.load_exchange(self.config['exchange']['name'], self.config)
persistence.init(self.config.get('db_url', None),
clean_open_orders=self.config.get('dry_run', False))
persistence.init(self.config.get('db_url', None), clean_open_orders=self.config['dry_run'])
self.wallets = Wallets(self.config, self.exchange)
@ -219,7 +218,7 @@ class FreqtradeBot:
return trades_created
def get_target_bid(self, pair: str, tick: Dict = None) -> float:
def get_buy_rate(self, pair: str, tick: Dict = None) -> float:
"""
Calculates bid target between current ask price and last price
:return: float: Price
@ -436,7 +435,7 @@ class FreqtradeBot:
buy_limit_requested = price
else:
# Calculate price
buy_limit_requested = self.get_target_bid(pair)
buy_limit_requested = self.get_buy_rate(pair)
min_stake_amount = self._get_min_pair_stake_amount(pair, buy_limit_requested)
if min_stake_amount is not None and min_stake_amount > stake_amount:
@ -926,7 +925,7 @@ class FreqtradeBot:
# if stoploss is on exchange and we are on dry_run mode,
# we consider the sell price stop price
if self.config.get('dry_run', False) and sell_type == 'stoploss' \
if self.config['dry_run'] and sell_type == 'stoploss' \
and self.strategy.order_types['stoploss_on_exchange']:
limit = trade.stop_loss

View File

@ -70,7 +70,7 @@ def generate_text_table_sell_reason(data: Dict[str, Dict], results: DataFrame) -
for reason, count in results['sell_reason'].value_counts().iteritems():
result = results.loc[results['sell_reason'] == reason]
profit = len(result[result['profit_abs'] >= 0])
loss = len(result[results['profit_abs'] < 0])
loss = len(result[result['profit_abs'] < 0])
profit_mean = round(result['profit_percent'].mean() * 100.0, 2)
tabular_data.append([reason.value, count, profit, loss, profit_mean])
return tabulate(tabular_data, headers=headers, tablefmt="pipe")

View File

@ -88,7 +88,7 @@ class RPC:
"""
config = self._freqtrade.config
val = {
'dry_run': config.get('dry_run', False),
'dry_run': config['dry_run'],
'stake_currency': config['stake_currency'],
'stake_amount': config['stake_amount'],
'minimal_roi': config['minimal_roi'].copy(),
@ -337,7 +337,7 @@ class RPC:
'stake': stake_currency,
})
if total == 0.0:
if self._freqtrade.config.get('dry_run', False):
if self._freqtrade.config['dry_run']:
raise RPCException('Running in Dry Run, balances are not available.')
else:
raise RPCException('All balances are zero.')
@ -351,7 +351,7 @@ class RPC:
'symbol': symbol,
'value': value,
'stake': stake_currency,
'note': 'Simulated balances' if self._freqtrade.config.get('dry_run', False) else ''
'note': 'Simulated balances' if self._freqtrade.config['dry_run'] else ''
}
def _rpc_start(self) -> Dict[str, str]:

View File

@ -62,7 +62,7 @@ class RPCManager:
logger.error(f"Message type {msg['type']} not implemented by handler {mod.name}.")
def startup_messages(self, config, pairlist) -> None:
if config.get('dry_run', False):
if config['dry_run']:
self.send_msg({
'type': RPCMessageType.WARNING_NOTIFICATION,
'status': 'Dry run is enabled. All trades are simulated.'

View File

@ -389,9 +389,11 @@ class IStrategy(ABC):
trade.adjust_stop_loss(high or current_rate, stop_loss_value)
# evaluate if the stoploss was hit if stoploss is not on exchange
# in Dry-Run, this handles stoploss logic as well, as the logic will not be different to
# regular stoploss handling.
if ((self.stoploss is not None) and
(trade.stop_loss >= current_rate) and
(not self.order_types.get('stoploss_on_exchange'))):
(not self.order_types.get('stoploss_on_exchange') or self.config['dry_run'])):
sell_type = SellType.STOP_LOSS

View File

@ -27,7 +27,8 @@ class SampleHyperOptLoss(IHyperOptLoss):
Defines the default loss function for hyperopt
This is intended to give you some inspiration for your own loss function.
The Function needs to return a number (float) - which becomes for better backtest results.
The Function needs to return a number (float) - which becomes smaller for better backtest
results.
"""
@staticmethod

View File

@ -1,6 +1,6 @@
# requirements without requirements installable via conda
# mainly used for Raspberry pi installs
ccxt==1.21.56
ccxt==1.21.76
SQLAlchemy==1.3.12
python-telegram-bot==12.3.0
arrow==0.15.5

View File

@ -8,7 +8,7 @@ flake8==3.7.9
flake8-type-annotations==0.1.0
flake8-tidy-imports==4.0.0
mypy==0.761
pytest==5.3.2
pytest==5.3.3
pytest-asyncio==0.10.0
pytest-cov==2.8.1
pytest-mock==2.0.0

View File

@ -323,7 +323,7 @@ def test_load_dry_run(default_conf, mocker, config_value, expected, arglist) ->
configuration = Configuration(Arguments(arglist).get_parsed_arg())
validated_conf = configuration.load_config()
assert validated_conf.get('dry_run') is expected
assert validated_conf['dry_run'] is expected
def test_load_custom_strategy(default_conf, mocker) -> None:

View File

@ -912,7 +912,7 @@ def test_balance_fully_ask_side(mocker, default_conf) -> None:
mocker.patch('freqtrade.exchange.Exchange.fetch_ticker',
MagicMock(return_value={'ask': 20, 'last': 10}))
assert freqtrade.get_target_bid('ETH/BTC') == 20
assert freqtrade.get_buy_rate('ETH/BTC') == 20
def test_balance_fully_last_side(mocker, default_conf) -> None:
@ -921,7 +921,7 @@ def test_balance_fully_last_side(mocker, default_conf) -> None:
mocker.patch('freqtrade.exchange.Exchange.fetch_ticker',
MagicMock(return_value={'ask': 20, 'last': 10}))
assert freqtrade.get_target_bid('ETH/BTC') == 10
assert freqtrade.get_buy_rate('ETH/BTC') == 10
def test_balance_bigger_last_ask(mocker, default_conf) -> None:
@ -929,7 +929,7 @@ def test_balance_bigger_last_ask(mocker, default_conf) -> None:
freqtrade = get_patched_freqtradebot(mocker, default_conf)
mocker.patch('freqtrade.exchange.Exchange.fetch_ticker',
MagicMock(return_value={'ask': 5, 'last': 10}))
assert freqtrade.get_target_bid('ETH/BTC') == 5
assert freqtrade.get_buy_rate('ETH/BTC') == 5
def test_execute_buy(mocker, default_conf, fee, limit_buy_order) -> None:
@ -938,10 +938,10 @@ def test_execute_buy(mocker, default_conf, fee, limit_buy_order) -> None:
freqtrade = FreqtradeBot(default_conf)
stake_amount = 2
bid = 0.11
get_bid = MagicMock(return_value=bid)
buy_rate_mock = MagicMock(return_value=bid)
mocker.patch.multiple(
'freqtrade.freqtradebot.FreqtradeBot',
get_target_bid=get_bid,
get_buy_rate=buy_rate_mock,
_get_min_pair_stake_amount=MagicMock(return_value=1)
)
buy_mm = MagicMock(return_value={'id': limit_buy_order['id']})
@ -958,7 +958,7 @@ def test_execute_buy(mocker, default_conf, fee, limit_buy_order) -> None:
pair = 'ETH/BTC'
assert freqtrade.execute_buy(pair, stake_amount)
assert get_bid.call_count == 1
assert buy_rate_mock.call_count == 1
assert buy_mm.call_count == 1
call_args = buy_mm.call_args_list[0][1]
assert call_args['pair'] == pair
@ -975,8 +975,8 @@ def test_execute_buy(mocker, default_conf, fee, limit_buy_order) -> None:
# Test calling with price
fix_price = 0.06
assert freqtrade.execute_buy(pair, stake_amount, fix_price)
# Make sure get_target_bid wasn't called again
assert get_bid.call_count == 1
# Make sure get_buy_rate wasn't called again
assert buy_rate_mock.call_count == 1
assert buy_mm.call_count == 2
call_args = buy_mm.call_args_list[1][1]
@ -1319,6 +1319,14 @@ def test_handle_stoploss_on_exchange_trailing(mocker, default_conf, fee, caplog,
order_types=freqtrade.strategy.order_types,
stop_price=0.00002344 * 0.95)
# price fell below stoploss, so dry-run sells trade.
mocker.patch('freqtrade.exchange.Exchange.fetch_ticker', MagicMock(return_value={
'bid': 0.00002144,
'ask': 0.00002146,
'last': 0.00002144
}))
assert freqtrade.handle_trade(trade) is True
def test_handle_stoploss_on_exchange_trailing_error(mocker, default_conf, fee, caplog,
limit_buy_order, limit_sell_order) -> None:
@ -3495,7 +3503,7 @@ def test_order_book_depth_of_market_high_delta(default_conf, ticker, limit_buy_o
def test_order_book_bid_strategy1(mocker, default_conf, order_book_l2) -> None:
"""
test if function get_target_bid will return the order book price
test if function get_buy_rate will return the order book price
instead of the ask rate
"""
patch_exchange(mocker)
@ -3513,13 +3521,13 @@ def test_order_book_bid_strategy1(mocker, default_conf, order_book_l2) -> None:
default_conf['telegram']['enabled'] = False
freqtrade = FreqtradeBot(default_conf)
assert freqtrade.get_target_bid('ETH/BTC') == 0.043935
assert freqtrade.get_buy_rate('ETH/BTC') == 0.043935
assert ticker_mock.call_count == 0
def test_order_book_bid_strategy2(mocker, default_conf, order_book_l2) -> None:
"""
test if function get_target_bid will return the ask rate (since its value is lower)
test if function get_buy_rate will return the ask rate (since its value is lower)
instead of the order book rate (even if enabled)
"""
patch_exchange(mocker)
@ -3538,7 +3546,7 @@ def test_order_book_bid_strategy2(mocker, default_conf, order_book_l2) -> None:
freqtrade = FreqtradeBot(default_conf)
# orderbook shall be used even if tickers would be lower.
assert freqtrade.get_target_bid('ETH/BTC') != 0.042
assert freqtrade.get_buy_rate('ETH/BTC') != 0.042
assert ticker_mock.call_count == 0