Merge branch 'develop' into order_creation

This commit is contained in:
iuvbio 2019-02-21 19:03:29 +01:00
commit bf5d2a68f5
5 changed files with 37 additions and 17 deletions

View File

@ -67,6 +67,7 @@ CONF_SCHEMA = {
}, },
'minProperties': 1 'minProperties': 1
}, },
'amount_reserve_percent': {'type': 'number', 'minimum': 0.0, 'maximum': 0.5},
'stoploss': {'type': 'number', 'maximum': 0, 'exclusiveMaximum': True}, 'stoploss': {'type': 'number', 'maximum': 0, 'exclusiveMaximum': True},
'trailing_stop': {'type': 'boolean'}, 'trailing_stop': {'type': 'boolean'},
'trailing_stop_positive': {'type': 'number', 'minimum': 0, 'maximum': 1}, 'trailing_stop_positive': {'type': 'number', 'minimum': 0, 'maximum': 1},

View File

@ -160,7 +160,6 @@ class Exchange(object):
return self._api.id return self._api.id
def klines(self, pair_interval: Tuple[str, str], copy=True) -> DataFrame: def klines(self, pair_interval: Tuple[str, str], copy=True) -> DataFrame:
# create key tuple
if pair_interval in self._klines: if pair_interval in self._klines:
return self._klines[pair_interval].copy() if copy else self._klines[pair_interval] return self._klines[pair_interval].copy() if copy else self._klines[pair_interval]
else: else:
@ -502,14 +501,10 @@ class Exchange(object):
input_coroutines = [] input_coroutines = []
# Gather corotines to run # Gather coroutines to run
for pair, ticker_interval in set(pair_list): for pair, ticker_interval in set(pair_list):
# Calculating ticker interval in second if (not ((pair, ticker_interval) in self._klines)
interval_in_sec = constants.TICKER_INTERVAL_MINUTES[ticker_interval] * 60 or self._now_is_time_to_refresh(pair, ticker_interval)):
if not ((self._pairs_last_refresh_time.get((pair, ticker_interval), 0)
+ interval_in_sec) >= arrow.utcnow().timestamp
and (pair, ticker_interval) in self._klines):
input_coroutines.append(self._async_get_candle_history(pair, ticker_interval)) input_coroutines.append(self._async_get_candle_history(pair, ticker_interval))
else: else:
logger.debug("Using cached ohlcv data for %s, %s ...", pair, ticker_interval) logger.debug("Using cached ohlcv data for %s, %s ...", pair, ticker_interval)
@ -533,6 +528,13 @@ class Exchange(object):
ticks, tick_interval, fill_missing=True) ticks, tick_interval, fill_missing=True)
return tickers return tickers
def _now_is_time_to_refresh(self, pair: str, ticker_interval: str) -> bool:
# Calculating ticker interval in seconds
interval_in_sec = constants.TICKER_INTERVAL_MINUTES[ticker_interval] * 60
return not ((self._pairs_last_refresh_time.get((pair, ticker_interval), 0)
+ interval_in_sec) >= arrow.utcnow().timestamp)
@retrier_async @retrier_async
async def _async_get_candle_history(self, pair: str, tick_interval: str, async def _async_get_candle_history(self, pair: str, tick_interval: str,
since_ms: Optional[int] = None) -> Tuple[str, str, List]: since_ms: Optional[int] = None) -> Tuple[str, str, List]:

View File

@ -17,7 +17,6 @@ from freqtrade import (DependencyException, OperationalException,
from freqtrade.data.converter import order_book_to_dataframe from freqtrade.data.converter import order_book_to_dataframe
from freqtrade.data.dataprovider import DataProvider from freqtrade.data.dataprovider import DataProvider
from freqtrade.edge import Edge from freqtrade.edge import Edge
from freqtrade.exchange import Exchange
from freqtrade.persistence import Trade from freqtrade.persistence import Trade
from freqtrade.rpc import RPCManager, RPCMessageType from freqtrade.rpc import RPCManager, RPCMessageType
from freqtrade.resolvers import ExchangeResolver, StrategyResolver, PairListResolver from freqtrade.resolvers import ExchangeResolver, StrategyResolver, PairListResolver
@ -57,12 +56,7 @@ class FreqtradeBot(object):
self.rpc: RPCManager = RPCManager(self) self.rpc: RPCManager = RPCManager(self)
exchange_name = self.config.get('exchange', {}).get('name', 'bittrex').title() exchange_name = self.config.get('exchange', {}).get('name', 'bittrex').title()
try: self.exchange = ExchangeResolver(exchange_name, self.config).exchange
self.exchange = ExchangeResolver(exchange_name, self.config).exchange
except ImportError:
logger.info(
f"No {exchange_name} specific subclass found. Using the generic class instead.")
self.exchange = Exchange(self.config)
self.wallets = Wallets(self.exchange) self.wallets = Wallets(self.exchange)
self.dataprovider = DataProvider(self.config, self.exchange) self.dataprovider = DataProvider(self.config, self.exchange)

View File

@ -22,7 +22,12 @@ class ExchangeResolver(IResolver):
Load the custom class from config parameter Load the custom class from config parameter
:param config: configuration dictionary or None :param config: configuration dictionary or None
""" """
self.exchange = self._load_exchange(exchange_name, kwargs={'config': config}) try:
self.exchange = self._load_exchange(exchange_name, kwargs={'config': config})
except ImportError:
logger.info(
f"No {exchange_name} specific subclass found. Using the generic class instead.")
self.exchange = Exchange(config)
def _load_exchange( def _load_exchange(
self, exchange_name: str, kwargs: dict) -> Exchange: self, exchange_name: str, kwargs: dict) -> Exchange:

View File

@ -13,7 +13,8 @@ from pandas import DataFrame
from freqtrade import DependencyException, OperationalException, TemporaryError from freqtrade import DependencyException, OperationalException, TemporaryError
from freqtrade.exchange import API_RETRY_COUNT, Exchange from freqtrade.exchange import API_RETRY_COUNT, Exchange
from freqtrade.tests.conftest import get_patched_exchange, log_has from freqtrade.tests.conftest import get_patched_exchange, log_has, log_has_re
from freqtrade.resolvers.exchange_resolver import ExchangeResolver
# Source: https://stackoverflow.com/questions/29881236/how-to-mock-asyncio-coroutines # Source: https://stackoverflow.com/questions/29881236/how-to-mock-asyncio-coroutines
@ -106,6 +107,23 @@ def test_init_exception(default_conf, mocker):
Exchange(default_conf) Exchange(default_conf)
def test_exchange_resolver(default_conf, mocker, caplog):
mocker.patch('freqtrade.exchange.Exchange._init_ccxt', MagicMock(return_value=MagicMock()))
mocker.patch('freqtrade.exchange.Exchange._load_async_markets', MagicMock())
mocker.patch('freqtrade.exchange.Exchange.validate_pairs', MagicMock())
mocker.patch('freqtrade.exchange.Exchange.validate_timeframes', MagicMock())
exchange = ExchangeResolver('Binance', default_conf).exchange
assert isinstance(exchange, Exchange)
assert log_has_re(r"No .* specific subclass found. Using the generic class instead.",
caplog.record_tuples)
caplog.clear()
exchange = ExchangeResolver('Kraken', default_conf).exchange
assert isinstance(exchange, Exchange)
assert not log_has_re(r"No .* specific subclass found. Using the generic class instead.",
caplog.record_tuples)
def test_symbol_amount_prec(default_conf, mocker): def test_symbol_amount_prec(default_conf, mocker):
''' '''
Test rounds down to 4 Decimal places Test rounds down to 4 Decimal places