experimental depth of market check prior to buying

This commit is contained in:
Nullart 2018-06-27 21:47:29 +08:00
parent 9f827979bd
commit fff2b81c10
7 changed files with 33 additions and 13 deletions

View File

@ -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

View File

@ -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,

View File

@ -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,

View File

@ -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.

View File

@ -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

View File

@ -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': {

View File

@ -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.'
@ -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