Merge branch 'develop' into kraken_support
This commit is contained in:
commit
dd2522d8d0
@ -3,6 +3,7 @@
|
|||||||
"stake_currency": "BTC",
|
"stake_currency": "BTC",
|
||||||
"stake_amount": 0.05,
|
"stake_amount": 0.05,
|
||||||
"fiat_display_currency": "USD",
|
"fiat_display_currency": "USD",
|
||||||
|
"amount_reserve_percent" : 0.05,
|
||||||
"dry_run": false,
|
"dry_run": false,
|
||||||
"ticker_interval": "5m",
|
"ticker_interval": "5m",
|
||||||
"trailing_stop": false,
|
"trailing_stop": false,
|
||||||
|
@ -16,6 +16,7 @@ Mandatory Parameters are marked as **Required**.
|
|||||||
| `max_open_trades` | 3 | **Required.** Number of trades open your bot will have. If -1 then it is ignored (i.e. potentially unlimited open trades)
|
| `max_open_trades` | 3 | **Required.** Number of trades open your bot will have. If -1 then it is ignored (i.e. potentially unlimited open trades)
|
||||||
| `stake_currency` | BTC | **Required.** Crypto-currency used for trading.
|
| `stake_currency` | BTC | **Required.** Crypto-currency used for trading.
|
||||||
| `stake_amount` | 0.05 | **Required.** Amount of crypto-currency your bot will use for each trade. Per default, the bot will use (0.05 BTC x 3) = 0.15 BTC in total will be always engaged. Set it to `"unlimited"` to allow the bot to use all available balance.
|
| `stake_amount` | 0.05 | **Required.** Amount of crypto-currency your bot will use for each trade. Per default, the bot will use (0.05 BTC x 3) = 0.15 BTC in total will be always engaged. Set it to `"unlimited"` to allow the bot to use all available balance.
|
||||||
|
| `amount_reserve_percent` | 0.05 | Reserve some amount in min pair stake amount. Default is 5%. The bot will reserve `amount_reserve_percent` + stop-loss value when calculating min pair stake amount in order to avoid possible trade refusals.
|
||||||
| `ticker_interval` | [1m, 5m, 30m, 1h, 1d] | The ticker interval to use (1min, 5 min, 30 min, 1 hour or 1 day). Default is 5 minutes. [Strategy Override](#parameters-in-strategy).
|
| `ticker_interval` | [1m, 5m, 30m, 1h, 1d] | The ticker interval to use (1min, 5 min, 30 min, 1 hour or 1 day). Default is 5 minutes. [Strategy Override](#parameters-in-strategy).
|
||||||
| `fiat_display_currency` | USD | **Required.** Fiat currency used to show your profits. More information below.
|
| `fiat_display_currency` | USD | **Required.** Fiat currency used to show your profits. More information below.
|
||||||
| `dry_run` | true | **Required.** Define if the bot must be in Dry-run or production mode.
|
| `dry_run` | true | **Required.** Define if the bot must be in Dry-run or production mode.
|
||||||
|
@ -211,19 +211,11 @@ class FreqtradeBot(object):
|
|||||||
self.state = State.STOPPED
|
self.state = State.STOPPED
|
||||||
return state_changed
|
return state_changed
|
||||||
|
|
||||||
def get_target_bid(self, pair: str, ticker: Dict[str, float]) -> float:
|
def get_target_bid(self, pair: str) -> float:
|
||||||
"""
|
"""
|
||||||
Calculates bid target between current ask price and last price
|
Calculates bid target between current ask price and last price
|
||||||
:param ticker: Ticker to use for getting Ask and Last Price
|
|
||||||
:return: float: Price
|
:return: float: Price
|
||||||
"""
|
"""
|
||||||
if ticker['ask'] < ticker['last']:
|
|
||||||
ticker_rate = ticker['ask']
|
|
||||||
else:
|
|
||||||
balance = self.config['bid_strategy']['ask_last_balance']
|
|
||||||
ticker_rate = ticker['ask'] + balance * (ticker['last'] - ticker['ask'])
|
|
||||||
|
|
||||||
used_rate = ticker_rate
|
|
||||||
config_bid_strategy = self.config.get('bid_strategy', {})
|
config_bid_strategy = self.config.get('bid_strategy', {})
|
||||||
if 'use_order_book' in config_bid_strategy and\
|
if 'use_order_book' in config_bid_strategy and\
|
||||||
config_bid_strategy.get('use_order_book', False):
|
config_bid_strategy.get('use_order_book', False):
|
||||||
@ -233,15 +225,16 @@ class FreqtradeBot(object):
|
|||||||
logger.debug('order_book %s', order_book)
|
logger.debug('order_book %s', order_book)
|
||||||
# top 1 = index 0
|
# top 1 = index 0
|
||||||
order_book_rate = order_book['bids'][order_book_top - 1][0]
|
order_book_rate = order_book['bids'][order_book_top - 1][0]
|
||||||
# if ticker has lower rate, then use ticker ( usefull if down trending )
|
|
||||||
logger.info('...top %s order book buy rate %0.8f', order_book_top, order_book_rate)
|
logger.info('...top %s order book buy rate %0.8f', order_book_top, order_book_rate)
|
||||||
if ticker_rate < order_book_rate:
|
used_rate = order_book_rate
|
||||||
logger.info('...using ticker rate instead %0.8f', ticker_rate)
|
|
||||||
used_rate = ticker_rate
|
|
||||||
else:
|
|
||||||
used_rate = order_book_rate
|
|
||||||
else:
|
else:
|
||||||
logger.info('Using Last Ask / Last Price')
|
logger.info('Using Last Ask / Last Price')
|
||||||
|
ticker = self.exchange.get_ticker(pair)
|
||||||
|
if ticker['ask'] < ticker['last']:
|
||||||
|
ticker_rate = ticker['ask']
|
||||||
|
else:
|
||||||
|
balance = self.config['bid_strategy']['ask_last_balance']
|
||||||
|
ticker_rate = ticker['ask'] + balance * (ticker['last'] - ticker['ask'])
|
||||||
used_rate = ticker_rate
|
used_rate = ticker_rate
|
||||||
|
|
||||||
return used_rate
|
return used_rate
|
||||||
@ -304,7 +297,8 @@ class FreqtradeBot(object):
|
|||||||
if not min_stake_amounts:
|
if not min_stake_amounts:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
amount_reserve_percent = 1 - 0.05 # reserve 5% + stoploss
|
# reserve some percent defined in config (5% default) + stoploss
|
||||||
|
amount_reserve_percent = 1.0 - self.config.get('amount_reserve_percent', 0.05)
|
||||||
if self.strategy.stoploss is not None:
|
if self.strategy.stoploss is not None:
|
||||||
amount_reserve_percent += self.strategy.stoploss
|
amount_reserve_percent += self.strategy.stoploss
|
||||||
# it should not be more than 50%
|
# it should not be more than 50%
|
||||||
@ -387,7 +381,7 @@ class FreqtradeBot(object):
|
|||||||
buy_limit_requested = price
|
buy_limit_requested = price
|
||||||
else:
|
else:
|
||||||
# Calculate amount
|
# Calculate amount
|
||||||
buy_limit_requested = self.get_target_bid(pair, self.exchange.get_ticker(pair))
|
buy_limit_requested = self.get_target_bid(pair)
|
||||||
|
|
||||||
min_stake_amount = self._get_min_pair_stake_amount(pair_s, buy_limit_requested)
|
min_stake_amount = self._get_min_pair_stake_amount(pair_s, buy_limit_requested)
|
||||||
if min_stake_amount is not None and min_stake_amount > stake_amount:
|
if min_stake_amount is not None and min_stake_amount > stake_amount:
|
||||||
@ -587,7 +581,6 @@ class FreqtradeBot(object):
|
|||||||
raise ValueError(f'Attempt to handle closed trade: {trade}')
|
raise ValueError(f'Attempt to handle closed trade: {trade}')
|
||||||
|
|
||||||
logger.debug('Handling %s ...', trade)
|
logger.debug('Handling %s ...', trade)
|
||||||
sell_rate = self.exchange.get_ticker(trade.pair)['bid']
|
|
||||||
|
|
||||||
(buy, sell) = (False, False)
|
(buy, sell) = (False, False)
|
||||||
experimental = self.config.get('experimental', {})
|
experimental = self.config.get('experimental', {})
|
||||||
@ -607,18 +600,15 @@ class FreqtradeBot(object):
|
|||||||
|
|
||||||
for i in range(order_book_min, order_book_max + 1):
|
for i in range(order_book_min, order_book_max + 1):
|
||||||
order_book_rate = order_book['asks'][i - 1][0]
|
order_book_rate = order_book['asks'][i - 1][0]
|
||||||
|
|
||||||
# if orderbook has higher rate (high profit),
|
|
||||||
# use orderbook, otherwise just use bids rate
|
|
||||||
logger.info(' order book asks top %s: %0.8f', i, order_book_rate)
|
logger.info(' order book asks top %s: %0.8f', i, order_book_rate)
|
||||||
if sell_rate < order_book_rate:
|
sell_rate = order_book_rate
|
||||||
sell_rate = order_book_rate
|
|
||||||
|
|
||||||
if self.check_sell(trade, sell_rate, buy, sell):
|
if self.check_sell(trade, sell_rate, buy, sell):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
else:
|
else:
|
||||||
logger.debug('checking sell')
|
logger.debug('checking sell')
|
||||||
|
sell_rate = self.exchange.get_ticker(trade.pair)['bid']
|
||||||
if self.check_sell(trade, sell_rate, buy, sell):
|
if self.check_sell(trade, sell_rate, buy, sell):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
@ -841,22 +841,27 @@ def test_process_informative_pairs_added(default_conf, ticker, markets, mocker)
|
|||||||
def test_balance_fully_ask_side(mocker, default_conf) -> None:
|
def test_balance_fully_ask_side(mocker, default_conf) -> None:
|
||||||
default_conf['bid_strategy']['ask_last_balance'] = 0.0
|
default_conf['bid_strategy']['ask_last_balance'] = 0.0
|
||||||
freqtrade = get_patched_freqtradebot(mocker, default_conf)
|
freqtrade = get_patched_freqtradebot(mocker, default_conf)
|
||||||
|
mocker.patch('freqtrade.exchange.Exchange.get_ticker',
|
||||||
|
MagicMock(return_value={'ask': 20, 'last': 10}))
|
||||||
|
|
||||||
assert freqtrade.get_target_bid('ETH/BTC', {'ask': 20, 'last': 10}) == 20
|
assert freqtrade.get_target_bid('ETH/BTC') == 20
|
||||||
|
|
||||||
|
|
||||||
def test_balance_fully_last_side(mocker, default_conf) -> None:
|
def test_balance_fully_last_side(mocker, default_conf) -> None:
|
||||||
default_conf['bid_strategy']['ask_last_balance'] = 1.0
|
default_conf['bid_strategy']['ask_last_balance'] = 1.0
|
||||||
freqtrade = get_patched_freqtradebot(mocker, default_conf)
|
freqtrade = get_patched_freqtradebot(mocker, default_conf)
|
||||||
|
mocker.patch('freqtrade.exchange.Exchange.get_ticker',
|
||||||
|
MagicMock(return_value={'ask': 20, 'last': 10}))
|
||||||
|
|
||||||
assert freqtrade.get_target_bid('ETH/BTC', {'ask': 20, 'last': 10}) == 10
|
assert freqtrade.get_target_bid('ETH/BTC') == 10
|
||||||
|
|
||||||
|
|
||||||
def test_balance_bigger_last_ask(mocker, default_conf) -> None:
|
def test_balance_bigger_last_ask(mocker, default_conf) -> None:
|
||||||
default_conf['bid_strategy']['ask_last_balance'] = 1.0
|
default_conf['bid_strategy']['ask_last_balance'] = 1.0
|
||||||
freqtrade = get_patched_freqtradebot(mocker, default_conf)
|
freqtrade = get_patched_freqtradebot(mocker, default_conf)
|
||||||
|
mocker.patch('freqtrade.exchange.Exchange.get_ticker',
|
||||||
assert freqtrade.get_target_bid('ETH/BTC', {'ask': 5, 'last': 10}) == 5
|
MagicMock(return_value={'ask': 5, 'last': 10}))
|
||||||
|
assert freqtrade.get_target_bid('ETH/BTC') == 5
|
||||||
|
|
||||||
|
|
||||||
def test_execute_buy(mocker, default_conf, fee, markets, limit_buy_order) -> None:
|
def test_execute_buy(mocker, default_conf, fee, markets, limit_buy_order) -> None:
|
||||||
@ -2813,10 +2818,13 @@ def test_order_book_bid_strategy1(mocker, default_conf, order_book_l2, markets)
|
|||||||
instead of the ask rate
|
instead of the ask rate
|
||||||
"""
|
"""
|
||||||
patch_exchange(mocker)
|
patch_exchange(mocker)
|
||||||
|
ticker_mock = MagicMock(return_value={'ask': 0.045, 'last': 0.046})
|
||||||
mocker.patch.multiple(
|
mocker.patch.multiple(
|
||||||
'freqtrade.exchange.Exchange',
|
'freqtrade.exchange.Exchange',
|
||||||
get_markets=markets,
|
get_markets=markets,
|
||||||
get_order_book=order_book_l2
|
get_order_book=order_book_l2,
|
||||||
|
get_ticker=ticker_mock,
|
||||||
|
|
||||||
)
|
)
|
||||||
default_conf['exchange']['name'] = 'binance'
|
default_conf['exchange']['name'] = 'binance'
|
||||||
default_conf['bid_strategy']['use_order_book'] = True
|
default_conf['bid_strategy']['use_order_book'] = True
|
||||||
@ -2825,7 +2833,8 @@ def test_order_book_bid_strategy1(mocker, default_conf, order_book_l2, markets)
|
|||||||
default_conf['telegram']['enabled'] = False
|
default_conf['telegram']['enabled'] = False
|
||||||
|
|
||||||
freqtrade = FreqtradeBot(default_conf)
|
freqtrade = FreqtradeBot(default_conf)
|
||||||
assert freqtrade.get_target_bid('ETH/BTC', {'ask': 0.045, 'last': 0.046}) == 0.043935
|
assert freqtrade.get_target_bid('ETH/BTC') == 0.043935
|
||||||
|
assert ticker_mock.call_count == 0
|
||||||
|
|
||||||
|
|
||||||
def test_order_book_bid_strategy2(mocker, default_conf, order_book_l2, markets) -> None:
|
def test_order_book_bid_strategy2(mocker, default_conf, order_book_l2, markets) -> None:
|
||||||
@ -2834,10 +2843,13 @@ def test_order_book_bid_strategy2(mocker, default_conf, order_book_l2, markets)
|
|||||||
instead of the order book rate (even if enabled)
|
instead of the order book rate (even if enabled)
|
||||||
"""
|
"""
|
||||||
patch_exchange(mocker)
|
patch_exchange(mocker)
|
||||||
|
ticker_mock = MagicMock(return_value={'ask': 0.042, 'last': 0.046})
|
||||||
mocker.patch.multiple(
|
mocker.patch.multiple(
|
||||||
'freqtrade.exchange.Exchange',
|
'freqtrade.exchange.Exchange',
|
||||||
get_markets=markets,
|
get_markets=markets,
|
||||||
get_order_book=order_book_l2
|
get_order_book=order_book_l2,
|
||||||
|
get_ticker=ticker_mock,
|
||||||
|
|
||||||
)
|
)
|
||||||
default_conf['exchange']['name'] = 'binance'
|
default_conf['exchange']['name'] = 'binance'
|
||||||
default_conf['bid_strategy']['use_order_book'] = True
|
default_conf['bid_strategy']['use_order_book'] = True
|
||||||
@ -2846,29 +2858,9 @@ def test_order_book_bid_strategy2(mocker, default_conf, order_book_l2, markets)
|
|||||||
default_conf['telegram']['enabled'] = False
|
default_conf['telegram']['enabled'] = False
|
||||||
|
|
||||||
freqtrade = FreqtradeBot(default_conf)
|
freqtrade = FreqtradeBot(default_conf)
|
||||||
assert freqtrade.get_target_bid('ETH/BTC', {'ask': 0.042, 'last': 0.046}) == 0.042
|
# ordrebook shall be used even if tickers would be lower.
|
||||||
|
assert freqtrade.get_target_bid('ETH/BTC', ) != 0.042
|
||||||
|
assert ticker_mock.call_count == 0
|
||||||
def test_order_book_bid_strategy3(default_conf, mocker, order_book_l2, markets) -> None:
|
|
||||||
"""
|
|
||||||
test if function get_target_bid will return ask rate instead
|
|
||||||
of the order book rate
|
|
||||||
"""
|
|
||||||
patch_exchange(mocker)
|
|
||||||
mocker.patch.multiple(
|
|
||||||
'freqtrade.exchange.Exchange',
|
|
||||||
get_markets=markets,
|
|
||||||
get_order_book=order_book_l2
|
|
||||||
)
|
|
||||||
default_conf['exchange']['name'] = 'binance'
|
|
||||||
default_conf['bid_strategy']['use_order_book'] = True
|
|
||||||
default_conf['bid_strategy']['order_book_top'] = 1
|
|
||||||
default_conf['bid_strategy']['ask_last_balance'] = 0
|
|
||||||
default_conf['telegram']['enabled'] = False
|
|
||||||
|
|
||||||
freqtrade = FreqtradeBot(default_conf)
|
|
||||||
|
|
||||||
assert freqtrade.get_target_bid('ETH/BTC', {'ask': 0.03, 'last': 0.029}) == 0.03
|
|
||||||
|
|
||||||
|
|
||||||
def test_check_depth_of_market_buy(default_conf, mocker, order_book_l2, markets) -> None:
|
def test_check_depth_of_market_buy(default_conf, mocker, order_book_l2, markets) -> None:
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
ccxt==1.18.234
|
ccxt==1.18.243
|
||||||
SQLAlchemy==1.2.17
|
SQLAlchemy==1.2.18
|
||||||
python-telegram-bot==11.1.0
|
python-telegram-bot==11.1.0
|
||||||
arrow==0.13.1
|
arrow==0.13.1
|
||||||
cachetools==3.1.0
|
cachetools==3.1.0
|
||||||
@ -9,7 +9,7 @@ wrapt==1.11.1
|
|||||||
numpy==1.16.1
|
numpy==1.16.1
|
||||||
pandas==0.24.1
|
pandas==0.24.1
|
||||||
scikit-learn==0.20.2
|
scikit-learn==0.20.2
|
||||||
joblib==0.13.1
|
joblib==0.13.2
|
||||||
scipy==1.2.1
|
scipy==1.2.1
|
||||||
jsonschema==2.6.0
|
jsonschema==2.6.0
|
||||||
TA-Lib==0.4.17
|
TA-Lib==0.4.17
|
||||||
|
Loading…
Reference in New Issue
Block a user