Merge branch 'develop' into order_creation
This commit is contained in:
commit
bf5d2a68f5
@ -67,6 +67,7 @@ CONF_SCHEMA = {
|
||||
},
|
||||
'minProperties': 1
|
||||
},
|
||||
'amount_reserve_percent': {'type': 'number', 'minimum': 0.0, 'maximum': 0.5},
|
||||
'stoploss': {'type': 'number', 'maximum': 0, 'exclusiveMaximum': True},
|
||||
'trailing_stop': {'type': 'boolean'},
|
||||
'trailing_stop_positive': {'type': 'number', 'minimum': 0, 'maximum': 1},
|
||||
|
@ -160,7 +160,6 @@ class Exchange(object):
|
||||
return self._api.id
|
||||
|
||||
def klines(self, pair_interval: Tuple[str, str], copy=True) -> DataFrame:
|
||||
# create key tuple
|
||||
if pair_interval in self._klines:
|
||||
return self._klines[pair_interval].copy() if copy else self._klines[pair_interval]
|
||||
else:
|
||||
@ -502,14 +501,10 @@ class Exchange(object):
|
||||
|
||||
input_coroutines = []
|
||||
|
||||
# Gather corotines to run
|
||||
# Gather coroutines to run
|
||||
for pair, ticker_interval in set(pair_list):
|
||||
# Calculating ticker interval in second
|
||||
interval_in_sec = constants.TICKER_INTERVAL_MINUTES[ticker_interval] * 60
|
||||
|
||||
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):
|
||||
if (not ((pair, ticker_interval) in self._klines)
|
||||
or self._now_is_time_to_refresh(pair, ticker_interval)):
|
||||
input_coroutines.append(self._async_get_candle_history(pair, ticker_interval))
|
||||
else:
|
||||
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)
|
||||
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
|
||||
async def _async_get_candle_history(self, pair: str, tick_interval: str,
|
||||
since_ms: Optional[int] = None) -> Tuple[str, str, List]:
|
||||
|
@ -17,7 +17,6 @@ from freqtrade import (DependencyException, OperationalException,
|
||||
from freqtrade.data.converter import order_book_to_dataframe
|
||||
from freqtrade.data.dataprovider import DataProvider
|
||||
from freqtrade.edge import Edge
|
||||
from freqtrade.exchange import Exchange
|
||||
from freqtrade.persistence import Trade
|
||||
from freqtrade.rpc import RPCManager, RPCMessageType
|
||||
from freqtrade.resolvers import ExchangeResolver, StrategyResolver, PairListResolver
|
||||
@ -57,12 +56,7 @@ class FreqtradeBot(object):
|
||||
self.rpc: RPCManager = RPCManager(self)
|
||||
|
||||
exchange_name = self.config.get('exchange', {}).get('name', 'bittrex').title()
|
||||
try:
|
||||
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.exchange = ExchangeResolver(exchange_name, self.config).exchange
|
||||
|
||||
self.wallets = Wallets(self.exchange)
|
||||
self.dataprovider = DataProvider(self.config, self.exchange)
|
||||
|
@ -22,7 +22,12 @@ class ExchangeResolver(IResolver):
|
||||
Load the custom class from config parameter
|
||||
: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(
|
||||
self, exchange_name: str, kwargs: dict) -> Exchange:
|
||||
|
@ -13,7 +13,8 @@ from pandas import DataFrame
|
||||
|
||||
from freqtrade import DependencyException, OperationalException, TemporaryError
|
||||
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
|
||||
@ -106,6 +107,23 @@ def test_init_exception(default_conf, mocker):
|
||||
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):
|
||||
'''
|
||||
Test rounds down to 4 Decimal places
|
||||
|
Loading…
Reference in New Issue
Block a user