Candle_type to enum

This commit is contained in:
Matthias 2021-12-03 12:23:35 +01:00
parent a87e256737
commit f9cf59bb4d
6 changed files with 53 additions and 59 deletions

View File

@ -11,6 +11,7 @@ import pandas as pd
from pandas import DataFrame, to_datetime from pandas import DataFrame, to_datetime
from freqtrade.constants import DEFAULT_DATAFRAME_COLUMNS, DEFAULT_TRADES_COLUMNS, TradeList from freqtrade.constants import DEFAULT_DATAFRAME_COLUMNS, DEFAULT_TRADES_COLUMNS, TradeList
from freqtrade.enums.candletype import CandleType
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@ -266,7 +267,7 @@ def convert_ohlcv_format(
convert_from: str, convert_from: str,
convert_to: str, convert_to: str,
erase: bool, erase: bool,
candle_type: str = '' candle_type: CandleType = CandleType.SPOT_
): ):
""" """
Convert OHLCV from one format to another Convert OHLCV from one format to another

View File

@ -51,7 +51,7 @@ class HDF5DataHandler(IDataHandler):
for the specified timeframe for the specified timeframe
:param datadir: Directory to search for ohlcv files :param datadir: Directory to search for ohlcv files
:param timeframe: Timeframe to search pairs for :param timeframe: Timeframe to search pairs for
:param candle_type: Any of the enum CandleType (must match your trading mode!) :param candle_type: Any of the enum CandleType (must match trading mode!)
:return: List of Pairs :return: List of Pairs
""" """
candle = "" candle = ""
@ -69,14 +69,14 @@ class HDF5DataHandler(IDataHandler):
pair: str, pair: str,
timeframe: str, timeframe: str,
data: pd.DataFrame, data: pd.DataFrame,
candle_type: str = '' candle_type: CandleType = CandleType.SPOT_
) -> None: ) -> None:
""" """
Store data in hdf5 file. Store data in hdf5 file.
:param pair: Pair - used to generate filename :param pair: Pair - used to generate filename
:param timeframe: Timeframe - used to generate filename :param timeframe: Timeframe - used to generate filename
:param data: Dataframe containing OHLCV data :param data: Dataframe containing OHLCV data
:param candle_type: '', mark, index, premiumIndex, or funding_rate :param candle_type: Any of the enum CandleType (must match trading mode!)
:return: None :return: None
""" """
key = self._pair_ohlcv_key(pair, timeframe) key = self._pair_ohlcv_key(pair, timeframe)
@ -90,7 +90,9 @@ class HDF5DataHandler(IDataHandler):
) )
def _ohlcv_load(self, pair: str, timeframe: str, def _ohlcv_load(self, pair: str, timeframe: str,
timerange: Optional[TimeRange] = None, candle_type: str = '') -> pd.DataFrame: timerange: Optional[TimeRange] = None,
candle_type: CandleType = CandleType.SPOT_
) -> pd.DataFrame:
""" """
Internal method used to load data for one pair from disk. Internal method used to load data for one pair from disk.
Implements the loading and conversion to a Pandas dataframe. Implements the loading and conversion to a Pandas dataframe.
@ -100,7 +102,7 @@ class HDF5DataHandler(IDataHandler):
:param timerange: Limit data to be loaded to this timerange. :param timerange: Limit data to be loaded to this timerange.
Optionally implemented by subclasses to avoid loading Optionally implemented by subclasses to avoid loading
all data where possible. all data where possible.
:param candle_type: '', mark, index, premiumIndex, or funding_rate :param candle_type: Any of the enum CandleType (must match trading mode!)
:return: DataFrame with ohlcv data, or empty DataFrame :return: DataFrame with ohlcv data, or empty DataFrame
""" """
key = self._pair_ohlcv_key(pair, timeframe) key = self._pair_ohlcv_key(pair, timeframe)
@ -133,14 +135,14 @@ class HDF5DataHandler(IDataHandler):
pair: str, pair: str,
timeframe: str, timeframe: str,
data: pd.DataFrame, data: pd.DataFrame,
candle_type: str = '' candle_type: CandleType
) -> None: ) -> None:
""" """
Append data to existing data structures Append data to existing data structures
:param pair: Pair :param pair: Pair
:param timeframe: Timeframe this ohlcv data is for :param timeframe: Timeframe this ohlcv data is for
:param data: Data to append. :param data: Data to append.
:param candle_type: '', mark, index, premiumIndex, or funding_rate :param candle_type: Any of the enum CandleType (must match trading mode!)
""" """
raise NotImplementedError() raise NotImplementedError()

View File

@ -12,6 +12,7 @@ from freqtrade.constants import DEFAULT_DATAFRAME_COLUMNS
from freqtrade.data.converter import (clean_ohlcv_dataframe, ohlcv_to_dataframe, from freqtrade.data.converter import (clean_ohlcv_dataframe, ohlcv_to_dataframe,
trades_remove_duplicates, trades_to_ohlcv) trades_remove_duplicates, trades_to_ohlcv)
from freqtrade.data.history.idatahandler import IDataHandler, get_datahandler from freqtrade.data.history.idatahandler import IDataHandler, get_datahandler
from freqtrade.enums.candletype import CandleType
from freqtrade.exceptions import OperationalException from freqtrade.exceptions import OperationalException
from freqtrade.exchange import Exchange from freqtrade.exchange import Exchange
from freqtrade.misc import format_ms_time from freqtrade.misc import format_ms_time
@ -29,7 +30,7 @@ def load_pair_history(pair: str,
startup_candles: int = 0, startup_candles: int = 0,
data_format: str = None, data_format: str = None,
data_handler: IDataHandler = None, data_handler: IDataHandler = None,
candle_type: str = '' candle_type: CandleType = CandleType.SPOT
) -> DataFrame: ) -> DataFrame:
""" """
Load cached ohlcv history for the given pair. Load cached ohlcv history for the given pair.
@ -44,7 +45,7 @@ def load_pair_history(pair: str,
:param startup_candles: Additional candles to load at the start of the period :param startup_candles: Additional candles to load at the start of the period
:param data_handler: Initialized data-handler to use. :param data_handler: Initialized data-handler to use.
Will be initialized from data_format if not set Will be initialized from data_format if not set
:param candle_type: '', mark, index, premiumIndex, or funding_rate :param candle_type: Any of the enum CandleType (must match trading mode!)
:return: DataFrame with ohlcv data, or empty DataFrame :return: DataFrame with ohlcv data, or empty DataFrame
""" """
data_handler = get_datahandler(datadir, data_format, data_handler) data_handler = get_datahandler(datadir, data_format, data_handler)
@ -67,7 +68,7 @@ def load_data(datadir: Path,
startup_candles: int = 0, startup_candles: int = 0,
fail_without_data: bool = False, fail_without_data: bool = False,
data_format: str = 'json', data_format: str = 'json',
candle_type: str = '' candle_type: CandleType = CandleType.SPOT
) -> Dict[str, DataFrame]: ) -> Dict[str, DataFrame]:
""" """
Load ohlcv history data for a list of pairs. Load ohlcv history data for a list of pairs.
@ -80,7 +81,7 @@ def load_data(datadir: Path,
:param startup_candles: Additional candles to load at the start of the period :param startup_candles: Additional candles to load at the start of the period
:param fail_without_data: Raise OperationalException if no data is found. :param fail_without_data: Raise OperationalException if no data is found.
:param data_format: Data format which should be used. Defaults to json :param data_format: Data format which should be used. Defaults to json
:param candle_type: '', mark, index, premiumIndex, or funding_rate :param candle_type: Any of the enum CandleType (must match trading mode!)
:return: dict(<pair>:<Dataframe>) :return: dict(<pair>:<Dataframe>)
""" """
result: Dict[str, DataFrame] = {} result: Dict[str, DataFrame] = {}
@ -111,7 +112,7 @@ def refresh_data(datadir: Path,
exchange: Exchange, exchange: Exchange,
data_format: str = None, data_format: str = None,
timerange: Optional[TimeRange] = None, timerange: Optional[TimeRange] = None,
candle_type: str = '' candle_type: CandleType = CandleType.SPOT
) -> None: ) -> None:
""" """
Refresh ohlcv history data for a list of pairs. Refresh ohlcv history data for a list of pairs.
@ -122,7 +123,7 @@ def refresh_data(datadir: Path,
:param exchange: Exchange object :param exchange: Exchange object
:param data_format: dataformat to use :param data_format: dataformat to use
:param timerange: Limit data to be loaded to this timerange :param timerange: Limit data to be loaded to this timerange
:param candle_type: '', mark, index, premiumIndex, or funding_rate :param candle_type: Any of the enum CandleType (must match trading mode!)
""" """
data_handler = get_datahandler(datadir, data_format) data_handler = get_datahandler(datadir, data_format)
for idx, pair in enumerate(pairs): for idx, pair in enumerate(pairs):
@ -138,7 +139,7 @@ def _load_cached_data_for_updating(
timeframe: str, timeframe: str,
timerange: Optional[TimeRange], timerange: Optional[TimeRange],
data_handler: IDataHandler, data_handler: IDataHandler,
candle_type: str = '' candle_type: CandleType = CandleType.SPOT
) -> Tuple[DataFrame, Optional[int]]: ) -> Tuple[DataFrame, Optional[int]]:
""" """
Load cached data to download more data. Load cached data to download more data.
@ -177,7 +178,8 @@ def _download_pair_history(pair: str, *,
new_pairs_days: int = 30, new_pairs_days: int = 30,
data_handler: IDataHandler = None, data_handler: IDataHandler = None,
timerange: Optional[TimeRange] = None, timerange: Optional[TimeRange] = None,
candle_type: str = '') -> bool: candle_type: CandleType = CandleType.SPOT
) -> bool:
""" """
Download latest candles from the exchange for the pair and timeframe passed in parameters Download latest candles from the exchange for the pair and timeframe passed in parameters
The data is downloaded starting from the last correct data that The data is downloaded starting from the last correct data that
@ -189,7 +191,7 @@ def _download_pair_history(pair: str, *,
:param pair: pair to download :param pair: pair to download
:param timeframe: Timeframe (e.g "5m") :param timeframe: Timeframe (e.g "5m")
:param timerange: range of time to download :param timerange: range of time to download
:param candle_type: '', mark, index, premiumIndex, or funding_rate :param candle_type: Any of the enum CandleType (must match trading mode!)
:return: bool with success state :return: bool with success state
""" """
data_handler = get_datahandler(datadir, data_handler=data_handler) data_handler = get_datahandler(datadir, data_handler=data_handler)
@ -249,7 +251,8 @@ def refresh_backtest_ohlcv_data(exchange: Exchange, pairs: List[str], timeframes
datadir: Path, timerange: Optional[TimeRange] = None, datadir: Path, timerange: Optional[TimeRange] = None,
new_pairs_days: int = 30, erase: bool = False, new_pairs_days: int = 30, erase: bool = False,
data_format: str = None, data_format: str = None,
candle_type: str = '') -> List[str]: candle_type: CandleType = CandleType.SPOT
) -> List[str]:
""" """
Refresh stored ohlcv data for backtesting and hyperopt operations. Refresh stored ohlcv data for backtesting and hyperopt operations.
Used by freqtrade download-data subcommand. Used by freqtrade download-data subcommand.
@ -382,7 +385,7 @@ def convert_trades_to_ohlcv(
erase: bool = False, erase: bool = False,
data_format_ohlcv: str = 'json', data_format_ohlcv: str = 'json',
data_format_trades: str = 'jsongz', data_format_trades: str = 'jsongz',
candle_type: str = '' candle_type: CandleType = CandleType.SPOT
) -> None: ) -> None:
""" """
Convert stored trades data to ohlcv data Convert stored trades data to ohlcv data

View File

@ -59,7 +59,7 @@ class IDataHandler(ABC):
for the specified timeframe for the specified timeframe
:param datadir: Directory to search for ohlcv files :param datadir: Directory to search for ohlcv files
:param timeframe: Timeframe to search pairs for :param timeframe: Timeframe to search pairs for
:param candle_type: Any of the enum CandleType (must match your trading mode!) :param candle_type: Any of the enum CandleType (must match trading mode!)
:return: List of Pairs :return: List of Pairs
""" """
@ -69,21 +69,20 @@ class IDataHandler(ABC):
pair: str, pair: str,
timeframe: str, timeframe: str,
data: DataFrame, data: DataFrame,
candle_type: str = '' candle_type: CandleType = CandleType.SPOT_
) -> None: ) -> None:
""" """
Store ohlcv data. Store ohlcv data.
:param pair: Pair - used to generate filename :param pair: Pair - used to generate filename
:param timeframe: Timeframe - used to generate filename :param timeframe: Timeframe - used to generate filename
:param data: Dataframe containing OHLCV data :param data: Dataframe containing OHLCV data
:param candle_type: '', mark, index, premiumIndex, or funding_rate :param candle_type: Any of the enum CandleType (must match trading mode!)
:return: None :return: None
""" """
@abstractmethod @abstractmethod
def _ohlcv_load(self, pair: str, timeframe: str, def _ohlcv_load(self, pair: str, timeframe: str, timerange: Optional[TimeRange] = None,
timerange: Optional[TimeRange] = None, candle_type: CandleType = CandleType.SPOT_
candle_type: str = ''
) -> DataFrame: ) -> DataFrame:
""" """
Internal method used to load data for one pair from disk. Internal method used to load data for one pair from disk.
@ -94,16 +93,17 @@ class IDataHandler(ABC):
:param timerange: Limit data to be loaded to this timerange. :param timerange: Limit data to be loaded to this timerange.
Optionally implemented by subclasses to avoid loading Optionally implemented by subclasses to avoid loading
all data where possible. all data where possible.
:param candle_type: '', mark, index, premiumIndex, or funding_rate :param candle_type: Any of the enum CandleType (must match trading mode!)
:return: DataFrame with ohlcv data, or empty DataFrame :return: DataFrame with ohlcv data, or empty DataFrame
""" """
def ohlcv_purge(self, pair: str, timeframe: str, candle_type: str = '') -> bool: def ohlcv_purge(
self, pair: str, timeframe: str, candle_type: CandleType = CandleType.SPOT_) -> bool:
""" """
Remove data for this pair Remove data for this pair
:param pair: Delete data for this pair. :param pair: Delete data for this pair.
:param timeframe: Timeframe (e.g. "5m") :param timeframe: Timeframe (e.g. "5m")
:param candle_type: '', mark, index, premiumIndex, or funding_rate :param candle_type: Any of the enum CandleType (must match trading mode!)
:return: True when deleted, false if file did not exist. :return: True when deleted, false if file did not exist.
""" """
filename = self._pair_data_filename(self._datadir, pair, timeframe, candle_type) filename = self._pair_data_filename(self._datadir, pair, timeframe, candle_type)
@ -118,14 +118,14 @@ class IDataHandler(ABC):
pair: str, pair: str,
timeframe: str, timeframe: str,
data: DataFrame, data: DataFrame,
candle_type: str = '' candle_type: CandleType
) -> None: ) -> None:
""" """
Append data to existing data structures Append data to existing data structures
:param pair: Pair :param pair: Pair
:param timeframe: Timeframe this ohlcv data is for :param timeframe: Timeframe this ohlcv data is for
:param data: Data to append. :param data: Data to append.
:param candle_type: '', mark, index, premiumIndex, or funding_rate :param candle_type: Any of the enum CandleType (must match trading mode!)
""" """
@abstractclassmethod @abstractclassmethod
@ -200,14 +200,15 @@ class IDataHandler(ABC):
datadir: Path, datadir: Path,
pair: str, pair: str,
timeframe: str, timeframe: str,
candle_type: str = '' candle_type: CandleType
) -> Path: ) -> Path:
pair_s = misc.pair_to_filename(pair) pair_s = misc.pair_to_filename(pair)
if candle_type: candle = ""
if candle_type not in (CandleType.SPOT, CandleType.SPOT_):
datadir = datadir.joinpath('futures') datadir = datadir.joinpath('futures')
candle_type = f"-{candle_type}" candle = f"-{candle_type}"
filename = datadir.joinpath( filename = datadir.joinpath(
f'{pair_s}-{timeframe}{candle_type}.{cls._get_file_extension()}') f'{pair_s}-{timeframe}{candle}.{cls._get_file_extension()}')
return filename return filename
@classmethod @classmethod
@ -232,7 +233,7 @@ class IDataHandler(ABC):
drop_incomplete: bool = True, drop_incomplete: bool = True,
startup_candles: int = 0, startup_candles: int = 0,
warn_no_data: bool = True, warn_no_data: bool = True,
candle_type: str = '' candle_type: CandleType = CandleType.SPOT_
) -> DataFrame: ) -> DataFrame:
""" """
Load cached candle (OHLCV) data for the given pair. Load cached candle (OHLCV) data for the given pair.
@ -244,7 +245,7 @@ class IDataHandler(ABC):
:param drop_incomplete: Drop last candle assuming it may be incomplete. :param drop_incomplete: Drop last candle assuming it may be incomplete.
:param startup_candles: Additional candles to load at the start of the period :param startup_candles: Additional candles to load at the start of the period
:param warn_no_data: Log a warning message when no data is found :param warn_no_data: Log a warning message when no data is found
:param candle_type: '', mark, index, premiumIndex, or funding_rate :param candle_type: Any of the enum CandleType (must match trading mode!)
:return: DataFrame with ohlcv data, or empty DataFrame :return: DataFrame with ohlcv data, or empty DataFrame
""" """
# Fix startup period # Fix startup period

View File

@ -52,7 +52,7 @@ class JsonDataHandler(IDataHandler):
for the specified timeframe for the specified timeframe
:param datadir: Directory to search for ohlcv files :param datadir: Directory to search for ohlcv files
:param timeframe: Timeframe to search pairs for :param timeframe: Timeframe to search pairs for
:param candle_type: Any of the enum CandleType (must match your trading mode!) :param candle_type: Any of the enum CandleType (must match trading mode!)
:return: List of Pairs :return: List of Pairs
""" """
candle = "" candle = ""
@ -70,7 +70,7 @@ class JsonDataHandler(IDataHandler):
pair: str, pair: str,
timeframe: str, timeframe: str,
data: DataFrame, data: DataFrame,
candle_type: str = '' candle_type: CandleType = CandleType.SPOT_
) -> None: ) -> None:
""" """
Store data in json format "values". Store data in json format "values".
@ -79,7 +79,7 @@ class JsonDataHandler(IDataHandler):
:param pair: Pair - used to generate filename :param pair: Pair - used to generate filename
:param timeframe: Timeframe - used to generate filename :param timeframe: Timeframe - used to generate filename
:param data: Dataframe containing OHLCV data :param data: Dataframe containing OHLCV data
:param candle_type: '', mark, index, premiumIndex, or funding_rate :param candle_type: Any of the enum CandleType (must match trading mode!)
:return: None :return: None
""" """
filename = self._pair_data_filename(self._datadir, pair, timeframe, candle_type) filename = self._pair_data_filename(self._datadir, pair, timeframe, candle_type)
@ -95,7 +95,7 @@ class JsonDataHandler(IDataHandler):
def _ohlcv_load(self, pair: str, timeframe: str, def _ohlcv_load(self, pair: str, timeframe: str,
timerange: Optional[TimeRange] = None, timerange: Optional[TimeRange] = None,
candle_type: str = '' candle_type: CandleType = CandleType.SPOT_
) -> DataFrame: ) -> DataFrame:
""" """
Internal method used to load data for one pair from disk. Internal method used to load data for one pair from disk.
@ -106,7 +106,7 @@ class JsonDataHandler(IDataHandler):
:param timerange: Limit data to be loaded to this timerange. :param timerange: Limit data to be loaded to this timerange.
Optionally implemented by subclasses to avoid loading Optionally implemented by subclasses to avoid loading
all data where possible. all data where possible.
:param candle_type: '', mark, index, premiumIndex, or funding_rate :param candle_type: Any of the enum CandleType (must match trading mode!)
:return: DataFrame with ohlcv data, or empty DataFrame :return: DataFrame with ohlcv data, or empty DataFrame
""" """
filename = self._pair_data_filename(self._datadir, pair, timeframe, candle_type=candle_type) filename = self._pair_data_filename(self._datadir, pair, timeframe, candle_type=candle_type)
@ -126,33 +126,19 @@ class JsonDataHandler(IDataHandler):
infer_datetime_format=True) infer_datetime_format=True)
return pairdata return pairdata
def ohlcv_purge(self, pair: str, timeframe: str, candle_type: str = '') -> bool:
"""
Remove data for this pair
:param pair: Delete data for this pair.
:param timeframe: Timeframe (e.g. "5m")
:param candle_type: '', mark, index, premiumIndex, or funding_rate
:return: True when deleted, false if file did not exist.
"""
filename = self._pair_data_filename(self._datadir, pair, timeframe, candle_type=candle_type)
if filename.exists():
filename.unlink()
return True
return False
def ohlcv_append( def ohlcv_append(
self, self,
pair: str, pair: str,
timeframe: str, timeframe: str,
data: DataFrame, data: DataFrame,
candle_type: str = '' candle_type: CandleType
) -> None: ) -> None:
""" """
Append data to existing data structures Append data to existing data structures
:param pair: Pair :param pair: Pair
:param timeframe: Timeframe this ohlcv data is for :param timeframe: Timeframe this ohlcv data is for
:param data: Data to append. :param data: Data to append.
:param candle_type: '', mark, index, premiumIndex, or funding_rate :param candle_type: Any of the enum CandleType (must match trading mode!)
""" """
raise NotImplementedError() raise NotImplementedError()

View File

@ -24,6 +24,7 @@ from freqtrade.data.history.history_utils import (_download_pair_history, _downl
validate_backtest_data) validate_backtest_data)
from freqtrade.data.history.idatahandler import IDataHandler, get_datahandler, get_datahandlerclass from freqtrade.data.history.idatahandler import IDataHandler, get_datahandler, get_datahandlerclass
from freqtrade.data.history.jsondatahandler import JsonDataHandler, JsonGzDataHandler from freqtrade.data.history.jsondatahandler import JsonDataHandler, JsonGzDataHandler
from freqtrade.enums.candletype import CandleType
from freqtrade.exchange import timeframe_to_minutes from freqtrade.exchange import timeframe_to_minutes
from freqtrade.misc import file_dump_json from freqtrade.misc import file_dump_json
from freqtrade.resolvers import StrategyResolver from freqtrade.resolvers import StrategyResolver
@ -809,9 +810,9 @@ def test_jsondatahandler_trades_purge(mocker, testdatadir):
def test_datahandler_ohlcv_append(datahandler, testdatadir, ): def test_datahandler_ohlcv_append(datahandler, testdatadir, ):
dh = get_datahandler(testdatadir, datahandler) dh = get_datahandler(testdatadir, datahandler)
with pytest.raises(NotImplementedError): with pytest.raises(NotImplementedError):
dh.ohlcv_append('UNITTEST/ETH', '5m', DataFrame()) dh.ohlcv_append('UNITTEST/ETH', '5m', DataFrame(), CandleType.SPOT)
with pytest.raises(NotImplementedError): with pytest.raises(NotImplementedError):
dh.ohlcv_append('UNITTEST/ETH', '5m', DataFrame(), candle_type='mark') dh.ohlcv_append('UNITTEST/ETH', '5m', DataFrame(), CandleType.MARK)
@pytest.mark.parametrize('datahandler', AVAILABLE_DATAHANDLERS) @pytest.mark.parametrize('datahandler', AVAILABLE_DATAHANDLERS)