Merge pull request #2 from xmatthias/ccxt-async-xmatt

Ccxt async xmatt
This commit is contained in:
misagh 2018-08-02 16:33:02 +02:00 committed by GitHub
commit 7dc440b874
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 107 additions and 6 deletions

View File

@ -13,7 +13,7 @@ addons:
install: install:
- ./install_ta-lib.sh - ./install_ta-lib.sh
- export LD_LIBRARY_PATH=/usr/local/lib:$LD_LIBRARY_PATH - export LD_LIBRARY_PATH=/usr/local/lib:$LD_LIBRARY_PATH
- pip install --upgrade flake8 coveralls pytest-random-order mypy - pip install --upgrade flake8 coveralls pytest-random-order pytest-asyncio mypy
- pip install -r requirements.txt - pip install -r requirements.txt
- pip install -e . - pip install -e .
jobs: jobs:

View File

@ -334,7 +334,7 @@ class Exchange(object):
logger.info("returning cached ticker-data for %s", pair) logger.info("returning cached ticker-data for %s", pair)
return self._cached_ticker[pair] return self._cached_ticker[pair]
async def async_get_tickers_history(self, pairs, tick_interval): async def async_get_tickers_history(self, pairs, tick_interval) -> List[Tuple[str, List]]:
# COMMENTED CODE IS FOR DISCUSSION: where should we close the loop on async ? # COMMENTED CODE IS FOR DISCUSSION: where should we close the loop on async ?
# loop = asyncio.new_event_loop() # loop = asyncio.new_event_loop()
# asyncio.set_event_loop(loop) # asyncio.set_event_loop(loop)

View File

@ -55,7 +55,7 @@ class FreqtradeBot(object):
self.persistence = None self.persistence = None
self.exchange = Exchange(self.config) self.exchange = Exchange(self.config)
self._init_modules() self._init_modules()
self._klines = {} self._klines: Dict[str, List[Dict]] = {}
def _init_modules(self) -> None: def _init_modules(self) -> None:
""" """

View File

@ -6,7 +6,7 @@ import logging
from abc import ABC, abstractmethod from abc import ABC, abstractmethod
from datetime import datetime from datetime import datetime
from enum import Enum from enum import Enum
from typing import Dict, List, NamedTuple, Tuple from typing import Dict, List, NamedTuple, Optional, Tuple
import warnings import warnings
import arrow import arrow
@ -118,7 +118,7 @@ class IStrategy(ABC):
dataframe = self.advise_sell(dataframe, metadata) dataframe = self.advise_sell(dataframe, metadata)
return dataframe return dataframe
def get_signal(self, pair: str, interval: str, ticker_hist: List[Dict]) -> Tuple[bool, bool]: def get_signal(self, pair: str, interval: str, ticker_hist: Optional[List[Dict]]) -> Tuple[bool, bool]:
""" """
Calculates current signal based several technical analysis indicators Calculates current signal based several technical analysis indicators
:param pair: pair in format ANT/BTC :param pair: pair in format ANT/BTC

View File

@ -27,6 +27,20 @@ def ccxt_exceptionhandlers(mocker, default_conf, api_mock, fun, mock_ccxt_fun, *
assert api_mock.__dict__[mock_ccxt_fun].call_count == 1 assert api_mock.__dict__[mock_ccxt_fun].call_count == 1
async def async_ccxt_exception(mocker, default_conf, api_mock, fun, mock_ccxt_fun, **kwargs):
with pytest.raises(TemporaryError):
api_mock.__dict__[mock_ccxt_fun] = MagicMock(side_effect=ccxt.NetworkError)
exchange = get_patched_exchange(mocker, default_conf, api_mock)
await getattr(exchange, fun)(**kwargs)
assert api_mock.__dict__[mock_ccxt_fun].call_count == 1
with pytest.raises(OperationalException):
api_mock.__dict__[mock_ccxt_fun] = MagicMock(side_effect=ccxt.BaseError)
exchange = get_patched_exchange(mocker, default_conf, api_mock)
await getattr(exchange, fun)(**kwargs)
assert api_mock.__dict__[mock_ccxt_fun].call_count == 1
def test_init(default_conf, mocker, caplog): def test_init(default_conf, mocker, caplog):
caplog.set_level(logging.INFO) caplog.set_level(logging.INFO)
get_patched_exchange(mocker, default_conf) get_patched_exchange(mocker, default_conf)
@ -515,6 +529,92 @@ def test_get_ticker(default_conf, mocker):
exchange.get_ticker(pair='ETH/BTC', refresh=True) exchange.get_ticker(pair='ETH/BTC', refresh=True)
@pytest.mark.asyncio
async def test_async_get_ticker_history(default_conf, mocker):
tick = [
[
1511686200000, # unix timestamp ms
1, # open
2, # high
3, # low
4, # close
5, # volume (in quote currency)
]
]
async def async_fetch_ohlcv(pair, timeframe, since):
return tick
exchange = get_patched_exchange(mocker, default_conf)
# Monkey-patch async function
exchange._api_async.fetch_ohlcv = async_fetch_ohlcv
exchange = Exchange(default_conf)
pair = 'ETH/BTC'
res = await exchange.async_get_ticker_history(pair, "5m")
assert type(res) is tuple
assert len(res) == 2
assert res[0] == pair
assert res[1] == tick
await async_ccxt_exception(mocker, default_conf, MagicMock(),
"async_get_ticker_history", "fetch_ohlcv",
pair='ABCD/BTC', tick_interval=default_conf['ticker_interval'])
api_mock = MagicMock()
with pytest.raises(OperationalException, match=r'Could not fetch ticker data*'):
api_mock.fetch_ohlcv = MagicMock(side_effect=ccxt.BaseError)
exchange = get_patched_exchange(mocker, default_conf, api_mock)
await exchange.async_get_ticker_history(pair, "5m")
@pytest.mark.asyncio
async def test_async_get_tickers_history(default_conf, mocker):
tick = [
[
1511686200000, # unix timestamp ms
1, # open
2, # high
3, # low
4, # close
5, # volume (in quote currency)
]
]
async def async_fetch_ohlcv(pair, timeframe, since):
return tick
exchange = get_patched_exchange(mocker, default_conf)
# Monkey-patch async function
exchange._api_async.fetch_ohlcv = async_fetch_ohlcv
exchange = Exchange(default_conf)
pairs = ['ETH/BTC', 'XRP/BTC']
res = await exchange.async_get_tickers_history(pairs, "5m")
assert type(res) is list
assert len(res) == 2
assert type(res[0]) is tuple
assert res[0][0] == pairs[0]
assert res[0][1] == tick
assert res[1][0] == pairs[1]
assert res[1][1] == tick
# await async_ccxt_exception(mocker, default_conf, MagicMock(),
# "async_get_tickers_history", "fetch_ohlcv",
# pairs=pairs, tick_interval=default_conf['ticker_interval'])
# api_mock = MagicMock()
# with pytest.raises(OperationalException, match=r'Could not fetch ticker data*'):
# api_mock.fetch_ohlcv = MagicMock(side_effect=ccxt.BaseError)
# exchange = get_patched_exchange(mocker, default_conf, api_mock)
# await exchange.async_get_tickers_history('ETH/BTC', "5m")
def test_refresh_tickers():
# TODO: Implement test for this
pass
def make_fetch_ohlcv_mock(data): def make_fetch_ohlcv_mock(data):
def fetch_ohlcv_mock(pair, timeframe, since): def fetch_ohlcv_mock(pair, timeframe, since):
if since: if since:

View File

@ -15,6 +15,7 @@ TA-Lib==0.4.17
pytest==3.6.4 pytest==3.6.4
pytest-mock==1.10.0 pytest-mock==1.10.0
pytest-cov==2.5.1 pytest-cov==2.5.1
pytest-asyncio==0.9.0
tabulate==0.8.2 tabulate==0.8.2
coinmarketcap==5.0.3 coinmarketcap==5.0.3