2018-11-30 19:42:16 +00:00
|
|
|
"""
|
|
|
|
Dataprovider
|
|
|
|
Responsible to provide data to the bot
|
|
|
|
including Klines, tickers, historic data
|
|
|
|
Common Interface for bot and strategy to access data.
|
|
|
|
"""
|
|
|
|
import logging
|
2018-12-17 05:52:13 +00:00
|
|
|
from pathlib import Path
|
2018-12-30 06:15:21 +00:00
|
|
|
from typing import List, Tuple
|
2018-11-30 19:42:16 +00:00
|
|
|
|
2018-12-02 08:16:35 +00:00
|
|
|
from pandas import DataFrame
|
|
|
|
|
2018-12-17 05:52:13 +00:00
|
|
|
from freqtrade.data.history import load_pair_history
|
2018-12-25 13:23:59 +00:00
|
|
|
from freqtrade.exchange import Exchange
|
|
|
|
from freqtrade.state import RunMode
|
2018-11-30 19:42:16 +00:00
|
|
|
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
|
|
|
2019-07-14 18:05:28 +00:00
|
|
|
class DataProvider():
|
2018-11-30 19:42:16 +00:00
|
|
|
|
2018-12-02 08:16:35 +00:00
|
|
|
def __init__(self, config: dict, exchange: Exchange) -> None:
|
|
|
|
self._config = config
|
|
|
|
self._exchange = exchange
|
2018-11-30 19:42:16 +00:00
|
|
|
|
2019-01-22 05:55:40 +00:00
|
|
|
def refresh(self,
|
|
|
|
pairlist: List[Tuple[str, str]],
|
|
|
|
helping_pairs: List[Tuple[str, str]] = None) -> None:
|
2018-11-30 19:42:16 +00:00
|
|
|
"""
|
|
|
|
Refresh data, called with each cycle
|
|
|
|
"""
|
2019-01-22 05:55:40 +00:00
|
|
|
if helping_pairs:
|
|
|
|
self._exchange.refresh_latest_ohlcv(pairlist + helping_pairs)
|
|
|
|
else:
|
|
|
|
self._exchange.refresh_latest_ohlcv(pairlist)
|
2018-11-30 19:42:16 +00:00
|
|
|
|
2018-12-26 13:23:21 +00:00
|
|
|
@property
|
2019-01-21 19:19:34 +00:00
|
|
|
def available_pairs(self) -> List[Tuple[str, str]]:
|
2018-12-26 13:23:21 +00:00
|
|
|
"""
|
2019-04-07 13:14:40 +00:00
|
|
|
Return a list of tuples containing pair, ticker_interval for which data is currently cached.
|
2018-12-26 13:23:21 +00:00
|
|
|
Should be whitelist + open trades.
|
|
|
|
"""
|
|
|
|
return list(self._exchange._klines.keys())
|
|
|
|
|
2019-04-07 13:14:40 +00:00
|
|
|
def ohlcv(self, pair: str, ticker_interval: str = None, copy: bool = True) -> DataFrame:
|
2018-11-30 19:42:16 +00:00
|
|
|
"""
|
2018-12-02 08:16:35 +00:00
|
|
|
get ohlcv data for the given pair as DataFrame
|
2018-12-29 07:47:14 +00:00
|
|
|
Please check `available_pairs` to verify which pairs are currently cached.
|
2018-12-25 12:37:15 +00:00
|
|
|
:param pair: pair to get the data for
|
2019-04-07 13:14:40 +00:00
|
|
|
:param ticker_interval: ticker_interval to get pair for
|
2018-12-25 12:37:15 +00:00
|
|
|
:param copy: copy dataframe before returning.
|
|
|
|
Use false only for RO operations (where the dataframe is not modified)
|
2018-11-30 19:42:16 +00:00
|
|
|
"""
|
2018-12-29 08:13:20 +00:00
|
|
|
if self.runmode in (RunMode.DRY_RUN, RunMode.LIVE):
|
2019-04-07 13:14:40 +00:00
|
|
|
if ticker_interval:
|
|
|
|
pairtick = (pair, ticker_interval)
|
2018-12-30 06:15:21 +00:00
|
|
|
else:
|
|
|
|
pairtick = (pair, self._config['ticker_interval'])
|
|
|
|
|
|
|
|
return self._exchange.klines(pairtick, copy=copy)
|
2018-12-29 08:13:20 +00:00
|
|
|
else:
|
2018-12-29 12:00:50 +00:00
|
|
|
return DataFrame()
|
2018-11-30 19:42:16 +00:00
|
|
|
|
2018-12-17 05:52:13 +00:00
|
|
|
def historic_ohlcv(self, pair: str, ticker_interval: str) -> DataFrame:
|
2018-11-30 19:42:16 +00:00
|
|
|
"""
|
2019-01-26 18:16:33 +00:00
|
|
|
get stored historic ohlcv data
|
2018-12-30 06:15:21 +00:00
|
|
|
:param pair: pair to get the data for
|
2019-04-07 13:14:40 +00:00
|
|
|
:param ticker_interval: ticker_interval to get pair for
|
2018-11-30 19:42:16 +00:00
|
|
|
"""
|
2018-12-17 05:52:13 +00:00
|
|
|
return load_pair_history(pair=pair,
|
|
|
|
ticker_interval=ticker_interval,
|
|
|
|
refresh_pairs=False,
|
2018-12-25 12:20:25 +00:00
|
|
|
datadir=Path(self._config['datadir']) if self._config.get(
|
2018-12-17 05:52:13 +00:00
|
|
|
'datadir') else None
|
|
|
|
)
|
2018-11-30 19:42:16 +00:00
|
|
|
|
2018-12-02 08:16:35 +00:00
|
|
|
def ticker(self, pair: str):
|
|
|
|
"""
|
|
|
|
Return last ticker data
|
|
|
|
"""
|
2018-12-26 13:58:16 +00:00
|
|
|
# TODO: Implement me
|
2018-11-30 19:42:16 +00:00
|
|
|
pass
|
|
|
|
|
2019-07-14 18:05:28 +00:00
|
|
|
def orderbook(self, pair: str, maximum: int):
|
2018-12-02 08:16:35 +00:00
|
|
|
"""
|
|
|
|
return latest orderbook data
|
2019-07-14 18:05:28 +00:00
|
|
|
:param pair: pair to get the data for
|
|
|
|
:param maximum: Maximum number of orderbook entries to query
|
|
|
|
:return: dict including bids/asks with a total of `maximum` entries.
|
2018-12-02 08:16:35 +00:00
|
|
|
"""
|
2019-07-14 18:05:28 +00:00
|
|
|
return self._exchange.get_order_book(pair, maximum)
|
2018-12-02 20:57:30 +00:00
|
|
|
|
|
|
|
@property
|
2018-12-25 13:23:59 +00:00
|
|
|
def runmode(self) -> RunMode:
|
2018-12-02 20:57:30 +00:00
|
|
|
"""
|
|
|
|
Get runmode of the bot
|
2018-12-29 08:13:20 +00:00
|
|
|
can be "live", "dry-run", "backtest", "edgecli", "hyperopt" or "other".
|
2018-12-02 20:57:30 +00:00
|
|
|
"""
|
2018-12-25 13:35:48 +00:00
|
|
|
return RunMode(self._config.get('runmode', RunMode.OTHER))
|