experimental depth of market check prior to buying
This commit is contained in:
parent
9f827979bd
commit
fff2b81c10
@ -89,6 +89,7 @@ strategy parameters with real exchange data.
|
|||||||
- [x] [separated unfilled orders timeout](docs/configuration.md)
|
- [x] [separated unfilled orders timeout](docs/configuration.md)
|
||||||
- [x] [option to disable buying](docs/configuration.md)
|
- [x] [option to disable buying](docs/configuration.md)
|
||||||
- [x] [option to get a buy price based on %](docs/configuration.md)
|
- [x] [option to get a buy price based on %](docs/configuration.md)
|
||||||
|
- [x] [option to check depth of market before buying](docs/configuration.md)
|
||||||
|
|
||||||
### Drawbacks
|
### Drawbacks
|
||||||
|
|
||||||
|
@ -47,7 +47,9 @@
|
|||||||
"experimental": {
|
"experimental": {
|
||||||
"use_sell_signal": false,
|
"use_sell_signal": false,
|
||||||
"sell_profit_only": false,
|
"sell_profit_only": false,
|
||||||
"sell_fullfilled_at_roi": false
|
"sell_fullfilled_at_roi": false,
|
||||||
|
"check_depth_of_market": true,
|
||||||
|
"dom_bids_asks_delta": 1.5
|
||||||
},
|
},
|
||||||
"telegram": {
|
"telegram": {
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
|
@ -52,7 +52,9 @@
|
|||||||
"experimental": {
|
"experimental": {
|
||||||
"use_sell_signal": false,
|
"use_sell_signal": false,
|
||||||
"sell_profit_only": false,
|
"sell_profit_only": false,
|
||||||
"sell_fullfilled_at_roi": false
|
"sell_fullfilled_at_roi": false,
|
||||||
|
"check_depth_of_market": true,
|
||||||
|
"dom_bids_asks_delta": 1.5
|
||||||
},
|
},
|
||||||
"telegram": {
|
"telegram": {
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
|
@ -40,6 +40,8 @@ The table below will list all configuration parameters.
|
|||||||
| `experimental.use_sell_signal` | false | No | Use your sell strategy in addition of the `minimal_roi`.
|
| `experimental.use_sell_signal` | false | No | Use your sell strategy in addition of the `minimal_roi`.
|
||||||
| `experimental.sell_profit_only` | false | No | waits until you have made a positive profit before taking a sell decision.
|
| `experimental.sell_profit_only` | false | No | waits until you have made a positive profit before taking a sell decision.
|
||||||
| `experimental.sell_fullfilled_at_roi` | false | No | automatically creates a sell order based on `minimal_roi` once a buy order has been fullfilled.
|
| `experimental.sell_fullfilled_at_roi` | false | No | automatically creates a sell order based on `minimal_roi` once a buy order has been fullfilled.
|
||||||
|
| `experimental.check_depth_of_market` | false | No | checks order book depth by comparing total size of bids and total size of asks. [More information below](docs/configuration.md#understanding-experimentalcheck_depth_of_market).
|
||||||
|
| `experimental.dom_bids_asks_delta` | 0 | No | the difference of total size bids vs total size asks to indicate a buy signal. [More information below](docs/configuration.md#understanding-experimentalcheck_depth_of_market).
|
||||||
| `telegram.enabled` | true | Yes | Enable or not the usage of Telegram.
|
| `telegram.enabled` | true | Yes | Enable or not the usage of Telegram.
|
||||||
| `telegram.token` | token | No | Your Telegram bot token. Only required if `telegram.enabled` is `true`.
|
| `telegram.token` | token | No | Your Telegram bot token. Only required if `telegram.enabled` is `true`.
|
||||||
| `telegram.chat_id` | chat_id | No | Your personal Telegram account id. Only required if `telegram.enabled` is `true`.
|
| `telegram.chat_id` | chat_id | No | Your personal Telegram account id. Only required if `telegram.enabled` is `true`.
|
||||||
@ -91,6 +93,9 @@ Most of the strategy files already include the optimal `stoploss` value. This pa
|
|||||||
### Understanding ask_strategy.use_book_order
|
### Understanding ask_strategy.use_book_order
|
||||||
`ask_strategy.use_book_order` loads the exchange book order and sets the askng price based on the `book_order_top` value. If the `book_order_min` is set to 3 and `book_order_max` is set to 10, then the bot will search between top 3rd and 10th asking prices from the top of the book order will be selected as the bidding price for the trade.
|
`ask_strategy.use_book_order` loads the exchange book order and sets the askng price based on the `book_order_top` value. If the `book_order_min` is set to 3 and `book_order_max` is set to 10, then the bot will search between top 3rd and 10th asking prices from the top of the book order will be selected as the bidding price for the trade.
|
||||||
|
|
||||||
|
### Understanding experimental.check_depth_of_market
|
||||||
|
`experimental.check_depth_of_market` loads the exchange book order of a pair and calculates the total size of bids and asks. If the difference of the total size of bids and asks reaches the `experimental.dom_bids_asks_delta` then a buy signal is triggered. Do note that `experimental.check_depth_of_market` will only be executed after the strategy triggers a buy signal.
|
||||||
|
|
||||||
### What are the valid values for exchange.name?
|
### What are the valid values for exchange.name?
|
||||||
Freqtrade is based on [CCXT library](https://github.com/ccxt/ccxt) that supports 115+ cryptocurrency exchange markets and trading APIs. The complete up-to-date list can be found in the [CCXT repo homepage](https://github.com/ccxt/ccxt/tree/master/python). However, the bot was thoroughly tested with only Bittrex and Binance.
|
Freqtrade is based on [CCXT library](https://github.com/ccxt/ccxt) that supports 115+ cryptocurrency exchange markets and trading APIs. The complete up-to-date list can be found in the [CCXT repo homepage](https://github.com/ccxt/ccxt/tree/master/python). However, the bot was thoroughly tested with only Bittrex and Binance.
|
||||||
|
|
||||||
|
@ -11,7 +11,7 @@ import pandas as pd
|
|||||||
from pandas import DataFrame, to_datetime
|
from pandas import DataFrame, to_datetime
|
||||||
|
|
||||||
from freqtrade import constants
|
from freqtrade import constants
|
||||||
from freqtrade.exchange import get_fee, get_ticker_history
|
from freqtrade.exchange import get_fee, get_ticker_history, get_order_book
|
||||||
from freqtrade.persistence import Trade
|
from freqtrade.persistence import Trade
|
||||||
from freqtrade.strategy.resolver import StrategyResolver, IStrategy
|
from freqtrade.strategy.resolver import StrategyResolver, IStrategy
|
||||||
|
|
||||||
@ -108,7 +108,7 @@ class Analyze(object):
|
|||||||
dataframe = self.parse_ticker_dataframe(ticker_history)
|
dataframe = self.parse_ticker_dataframe(ticker_history)
|
||||||
# eliminate partials for known exchanges that sends partial candles
|
# eliminate partials for known exchanges that sends partial candles
|
||||||
if self.config['exchange']['name'] in ['binance']:
|
if self.config['exchange']['name'] in ['binance']:
|
||||||
logger.info('eliminating partial candle')
|
logger.debug('eliminating partial candle')
|
||||||
dataframe.drop(dataframe.tail(1).index, inplace=True) # eliminate partial candle
|
dataframe.drop(dataframe.tail(1).index, inplace=True) # eliminate partial candle
|
||||||
dataframe = self.populate_indicators(dataframe, pair)
|
dataframe = self.populate_indicators(dataframe, pair)
|
||||||
dataframe = self.populate_buy_trend(dataframe, pair)
|
dataframe = self.populate_buy_trend(dataframe, pair)
|
||||||
@ -122,6 +122,7 @@ class Analyze(object):
|
|||||||
:param interval: Interval to use (in min)
|
:param interval: Interval to use (in min)
|
||||||
:return: (Buy, Sell) A bool-tuple indicating buy/sell signal
|
:return: (Buy, Sell) A bool-tuple indicating buy/sell signal
|
||||||
"""
|
"""
|
||||||
|
logger.info('Checking signal for %s', pair)
|
||||||
ticker_hist = get_ticker_history(pair, interval)
|
ticker_hist = get_ticker_history(pair, interval)
|
||||||
if not ticker_hist:
|
if not ticker_hist:
|
||||||
logger.warning('Empty ticker history for pair %s', pair)
|
logger.warning('Empty ticker history for pair %s', pair)
|
||||||
@ -271,7 +272,7 @@ class Analyze(object):
|
|||||||
break
|
break
|
||||||
return sell_rate
|
return sell_rate
|
||||||
|
|
||||||
def order_book_to_dataframe(data: list) -> DataFrame:
|
def order_book_to_dataframe(self, data: list) -> DataFrame:
|
||||||
"""
|
"""
|
||||||
Gets order book list, returns dataframe with below format
|
Gets order book list, returns dataframe with below format
|
||||||
-------------------------------------------------------------------
|
-------------------------------------------------------------------
|
||||||
@ -292,8 +293,3 @@ class Analyze(object):
|
|||||||
keys=['b_sum', 'b_size', 'bids', 'asks', 'a_size', 'a_sum'])
|
keys=['b_sum', 'b_size', 'bids', 'asks', 'a_size', 'a_sum'])
|
||||||
|
|
||||||
return frame
|
return frame
|
||||||
|
|
||||||
def order_book_dom() -> DataFrame:
|
|
||||||
# https://stackoverflow.com/questions/36835793/pandas-group-by-consecutive-ranges
|
|
||||||
return DataFrame
|
|
||||||
|
|
||||||
|
@ -93,7 +93,9 @@ CONF_SCHEMA = {
|
|||||||
'properties': {
|
'properties': {
|
||||||
'use_sell_signal': {'type': 'boolean'},
|
'use_sell_signal': {'type': 'boolean'},
|
||||||
'sell_profit_only': {'type': 'boolean'},
|
'sell_profit_only': {'type': 'boolean'},
|
||||||
'sell_fullfilled_at_roi': {'type': 'boolean'}
|
'sell_fullfilled_at_roi': {'type': 'boolean'},
|
||||||
|
'check_depth_of_market': {'type': 'boolean'},
|
||||||
|
'dom_bids_asks_delta': {'type': 'number', 'minimum': 0}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
'telegram': {
|
'telegram': {
|
||||||
|
@ -195,7 +195,6 @@ class FreqtradeBot(object):
|
|||||||
:param key: sort key (defaults to 'quoteVolume')
|
:param key: sort key (defaults to 'quoteVolume')
|
||||||
:return: List of pairs
|
:return: List of pairs
|
||||||
"""
|
"""
|
||||||
|
|
||||||
if not exchange.exchange_has('fetchTickers'):
|
if not exchange.exchange_has('fetchTickers'):
|
||||||
raise OperationalException(
|
raise OperationalException(
|
||||||
'Exchange does not support dynamic whitelist.'
|
'Exchange does not support dynamic whitelist.'
|
||||||
@ -264,7 +263,7 @@ class FreqtradeBot(object):
|
|||||||
if 'use_book_order' in self.config['bid_strategy'] and self.config['bid_strategy'].get('use_book_order', False):
|
if 'use_book_order' in self.config['bid_strategy'] and self.config['bid_strategy'].get('use_book_order', False):
|
||||||
logger.info('Getting price from Order Book')
|
logger.info('Getting price from Order Book')
|
||||||
orderBook_top = self.config.get('bid_strategy', {}).get('book_order_top', 1)
|
orderBook_top = self.config.get('bid_strategy', {}).get('book_order_top', 1)
|
||||||
orderBook = exchange.get_order_book(pair, orderBook_top)
|
orderBook = exchange.get_order_book(pair, orderBook_top)
|
||||||
# top 1 = index 0
|
# top 1 = index 0
|
||||||
orderBook_rate = orderBook['bids'][orderBook_top - 1][0]
|
orderBook_rate = orderBook['bids'][orderBook_top - 1][0]
|
||||||
orderBook_rate = orderBook_rate + 0.00000001
|
orderBook_rate = orderBook_rate + 0.00000001
|
||||||
@ -327,6 +326,19 @@ class FreqtradeBot(object):
|
|||||||
break
|
break
|
||||||
else:
|
else:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
# order book depth of market
|
||||||
|
if self.config.get('experimental', {}).get('check_depth_of_market', False) \
|
||||||
|
and (self.config.get('experimental', {}).get('dom_bids_asks_delta', 0) > 0):
|
||||||
|
logger.info('depth of market check for %s', pair)
|
||||||
|
orderBook = exchange.get_order_book(pair, 1000)
|
||||||
|
orderBook_df = self.analyze.order_book_to_dataframe(orderBook)
|
||||||
|
orderBook_bids = orderBook_df['b_size'].sum()
|
||||||
|
orderBook_asks = orderBook_df['a_size'].sum()
|
||||||
|
logger.info('bids: %s, asks: %s, delta: %s', orderBook_bids, orderBook_asks, orderBook_bids / orderBook_asks)
|
||||||
|
if (orderBook_bids / orderBook_asks) < self.config.get('experimental', {}).get('dom_bids_asks_delta', 0):
|
||||||
|
return False
|
||||||
|
|
||||||
pair_s = pair.replace('_', '/')
|
pair_s = pair.replace('_', '/')
|
||||||
pair_url = exchange.get_pair_detail_url(pair)
|
pair_url = exchange.get_pair_detail_url(pair)
|
||||||
# Calculate amount
|
# Calculate amount
|
||||||
|
Loading…
Reference in New Issue
Block a user