Merge pull request #2522 from freqtrade/replace_tickerinterval

Replace tickerinterval
This commit is contained in:
hroff-1902 2019-11-13 13:50:07 +03:00 committed by GitHub
commit baea06eac7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
24 changed files with 198 additions and 197 deletions

View File

@ -314,9 +314,9 @@ Please always check the mode of operation to select the correct method to get da
#### Possible options for DataProvider #### Possible options for DataProvider
- `available_pairs` - Property with tuples listing cached pairs with their intervals (pair, interval). - `available_pairs` - Property with tuples listing cached pairs with their intervals (pair, interval).
- `ohlcv(pair, ticker_interval)` - Currently cached ticker data for the pair, returns DataFrame or empty DataFrame. - `ohlcv(pair, timeframe)` - Currently cached ticker data for the pair, returns DataFrame or empty DataFrame.
- `historic_ohlcv(pair, ticker_interval)` - Returns historical data stored on disk. - `historic_ohlcv(pair, timeframe)` - Returns historical data stored on disk.
- `get_pair_dataframe(pair, ticker_interval)` - This is a universal method, which returns either historical data (for backtesting) or cached live data (for the Dry-Run and Live-Run modes). - `get_pair_dataframe(pair, timeframe)` - This is a universal method, which returns either historical data (for backtesting) or cached live data (for the Dry-Run and Live-Run modes).
- `orderbook(pair, maximum)` - Returns latest orderbook data for the pair, a dict with bids/asks with a total of `maximum` entries. - `orderbook(pair, maximum)` - Returns latest orderbook data for the pair, a dict with bids/asks with a total of `maximum` entries.
- `market(pair)` - Returns market data for the pair: fees, limits, precisions, activity flag, etc. See [ccxt documentation](https://github.com/ccxt/ccxt/wiki/Manual#markets) for more details on Market data structure. - `market(pair)` - Returns market data for the pair: fees, limits, precisions, activity flag, etc. See [ccxt documentation](https://github.com/ccxt/ccxt/wiki/Manual#markets) for more details on Market data structure.
- `runmode` - Property containing the current runmode. - `runmode` - Property containing the current runmode.
@ -327,7 +327,7 @@ Please always check the mode of operation to select the correct method to get da
if self.dp: if self.dp:
inf_pair, inf_timeframe = self.informative_pairs()[0] inf_pair, inf_timeframe = self.informative_pairs()[0]
informative = self.dp.get_pair_dataframe(pair=inf_pair, informative = self.dp.get_pair_dataframe(pair=inf_pair,
ticker_interval=inf_timeframe) timeframe=inf_timeframe)
``` ```
!!! Warning "Warning about backtesting" !!! Warning "Warning about backtesting"

View File

@ -10,7 +10,7 @@ from pathlib import Path
# Customize these according to your needs. # Customize these according to your needs.
# Define some constants # Define some constants
ticker_interval = "5m" timeframe = "5m"
# Name of the strategy class # Name of the strategy class
strategy_name = 'SampleStrategy' strategy_name = 'SampleStrategy'
# Path to user data # Path to user data
@ -29,7 +29,7 @@ pair = "BTC_USDT"
from freqtrade.data.history import load_pair_history from freqtrade.data.history import load_pair_history
candles = load_pair_history(datadir=data_location, candles = load_pair_history(datadir=data_location,
ticker_interval=ticker_interval, timeframe=timeframe,
pair=pair) pair=pair)
# Confirm success # Confirm success

View File

@ -39,12 +39,12 @@ class TimeRange:
if self.startts: if self.startts:
self.startts = self.startts - seconds self.startts = self.startts - seconds
def adjust_start_if_necessary(self, ticker_interval_secs: int, startup_candles: int, def adjust_start_if_necessary(self, timeframe_secs: int, startup_candles: int,
min_date: arrow.Arrow) -> None: min_date: arrow.Arrow) -> None:
""" """
Adjust startts by <startup_candles> candles. Adjust startts by <startup_candles> candles.
Applies only if no startup-candles have been available. Applies only if no startup-candles have been available.
:param ticker_interval_secs: Ticker interval in seconds e.g. `timeframe_to_seconds('5m')` :param timeframe_secs: Ticker timeframe in seconds e.g. `timeframe_to_seconds('5m')`
:param startup_candles: Number of candles to move start-date forward :param startup_candles: Number of candles to move start-date forward
:param min_date: Minimum data date loaded. Key kriterium to decide if start-time :param min_date: Minimum data date loaded. Key kriterium to decide if start-time
has to be moved has to be moved
@ -55,7 +55,7 @@ class TimeRange:
# If no startts was defined, or backtest-data starts at the defined backtest-date # If no startts was defined, or backtest-data starts at the defined backtest-date
logger.warning("Moving start-date by %s candles to account for startup time.", logger.warning("Moving start-date by %s candles to account for startup time.",
startup_candles) startup_candles)
self.startts = (min_date.timestamp + ticker_interval_secs * startup_candles) self.startts = (min_date.timestamp + timeframe_secs * startup_candles)
self.starttype = 'date' self.starttype = 'date'
@staticmethod @staticmethod

View File

@ -24,7 +24,7 @@ AVAILABLE_PAIRLISTS = ['StaticPairList', 'VolumePairList']
DRY_RUN_WALLET = 999.9 DRY_RUN_WALLET = 999.9
MATH_CLOSE_PREC = 1e-14 # Precision used for float comparisons MATH_CLOSE_PREC = 1e-14 # Precision used for float comparisons
TICKER_INTERVALS = [ TIMEFRAMES = [
'1m', '3m', '5m', '15m', '30m', '1m', '3m', '5m', '15m', '30m',
'1h', '2h', '4h', '6h', '8h', '12h', '1h', '2h', '4h', '6h', '8h', '12h',
'1d', '3d', '1w', '1d', '3d', '1w',
@ -57,7 +57,7 @@ CONF_SCHEMA = {
'type': 'object', 'type': 'object',
'properties': { 'properties': {
'max_open_trades': {'type': 'integer', 'minimum': -1}, 'max_open_trades': {'type': 'integer', 'minimum': -1},
'ticker_interval': {'type': 'string', 'enum': TICKER_INTERVALS}, 'ticker_interval': {'type': 'string', 'enum': TIMEFRAMES},
'stake_currency': {'type': 'string', 'enum': ['BTC', 'XBT', 'ETH', 'USDT', 'EUR', 'USD']}, 'stake_currency': {'type': 'string', 'enum': ['BTC', 'XBT', 'ETH', 'USDT', 'EUR', 'USD']},
'stake_amount': { 'stake_amount': {
"type": ["number", "string"], "type": ["number", "string"],

View File

@ -178,9 +178,9 @@ def create_cum_profit(df: pd.DataFrame, trades: pd.DataFrame, col_name: str,
:return: Returns df with one additional column, col_name, containing the cumulative profit. :return: Returns df with one additional column, col_name, containing the cumulative profit.
""" """
from freqtrade.exchange import timeframe_to_minutes from freqtrade.exchange import timeframe_to_minutes
ticker_minutes = timeframe_to_minutes(timeframe) timeframe_minutes = timeframe_to_minutes(timeframe)
# Resample to ticker_interval to make sure trades match candles # Resample to timeframe to make sure trades match candles
_trades_sum = trades.resample(f'{ticker_minutes}min', on='close_time')[['profitperc']].sum() _trades_sum = trades.resample(f'{timeframe_minutes}min', on='close_time')[['profitperc']].sum()
df.loc[:, col_name] = _trades_sum.cumsum() df.loc[:, col_name] = _trades_sum.cumsum()
# Set first value to 0 # Set first value to 0
df.loc[df.iloc[0].name, col_name] = 0 df.loc[df.iloc[0].name, col_name] = 0

View File

@ -10,13 +10,13 @@ from pandas import DataFrame, to_datetime
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
def parse_ticker_dataframe(ticker: list, ticker_interval: str, pair: str, *, def parse_ticker_dataframe(ticker: list, timeframe: str, pair: str, *,
fill_missing: bool = True, fill_missing: bool = True,
drop_incomplete: bool = True) -> DataFrame: drop_incomplete: bool = True) -> DataFrame:
""" """
Converts a ticker-list (format ccxt.fetch_ohlcv) to a Dataframe Converts a ticker-list (format ccxt.fetch_ohlcv) to a Dataframe
:param ticker: ticker list, as returned by exchange.async_get_candle_history :param ticker: ticker list, as returned by exchange.async_get_candle_history
:param ticker_interval: ticker_interval (e.g. 5m). Used to fill up eventual missing data :param timeframe: timeframe (e.g. 5m). Used to fill up eventual missing data
:param pair: Pair this data is for (used to warn if fillup was necessary) :param pair: Pair this data is for (used to warn if fillup was necessary)
:param fill_missing: fill up missing candles with 0 candles :param fill_missing: fill up missing candles with 0 candles
(see ohlcv_fill_up_missing_data for details) (see ohlcv_fill_up_missing_data for details)
@ -52,12 +52,12 @@ def parse_ticker_dataframe(ticker: list, ticker_interval: str, pair: str, *,
logger.debug('Dropping last candle') logger.debug('Dropping last candle')
if fill_missing: if fill_missing:
return ohlcv_fill_up_missing_data(frame, ticker_interval, pair) return ohlcv_fill_up_missing_data(frame, timeframe, pair)
else: else:
return frame return frame
def ohlcv_fill_up_missing_data(dataframe: DataFrame, ticker_interval: str, pair: str) -> DataFrame: def ohlcv_fill_up_missing_data(dataframe: DataFrame, timeframe: str, pair: str) -> DataFrame:
""" """
Fills up missing data with 0 volume rows, Fills up missing data with 0 volume rows,
using the previous close as price for "open", "high" "low" and "close", volume is set to 0 using the previous close as price for "open", "high" "low" and "close", volume is set to 0
@ -72,7 +72,7 @@ def ohlcv_fill_up_missing_data(dataframe: DataFrame, ticker_interval: str, pair:
'close': 'last', 'close': 'last',
'volume': 'sum' 'volume': 'sum'
} }
ticker_minutes = timeframe_to_minutes(ticker_interval) ticker_minutes = timeframe_to_minutes(timeframe)
# Resample to create "NAN" values # Resample to create "NAN" values
df = dataframe.resample(f'{ticker_minutes}min', on='date').agg(ohlc_dict) df = dataframe.resample(f'{ticker_minutes}min', on='date').agg(ohlc_dict)

View File

@ -37,52 +37,53 @@ class DataProvider:
@property @property
def available_pairs(self) -> List[Tuple[str, str]]: def available_pairs(self) -> List[Tuple[str, str]]:
""" """
Return a list of tuples containing pair, ticker_interval for which data is currently cached. Return a list of tuples containing (pair, timeframe) for which data is currently cached.
Should be whitelist + open trades. Should be whitelist + open trades.
""" """
return list(self._exchange._klines.keys()) return list(self._exchange._klines.keys())
def ohlcv(self, pair: str, ticker_interval: str = None, copy: bool = True) -> DataFrame: def ohlcv(self, pair: str, timeframe: str = None, copy: bool = True) -> DataFrame:
""" """
Get ohlcv data for the given pair as DataFrame Get ohlcv data for the given pair as DataFrame
Please use the `available_pairs` method to verify which pairs are currently cached. Please use the `available_pairs` method to verify which pairs are currently cached.
:param pair: pair to get the data for :param pair: pair to get the data for
:param ticker_interval: ticker interval to get data for :param timeframe: Ticker timeframe to get data for
:param copy: copy dataframe before returning if True. :param copy: copy dataframe before returning if True.
Use False only for read-only operations (where the dataframe is not modified) Use False only for read-only operations (where the dataframe is not modified)
""" """
if self.runmode in (RunMode.DRY_RUN, RunMode.LIVE): if self.runmode in (RunMode.DRY_RUN, RunMode.LIVE):
return self._exchange.klines((pair, ticker_interval or self._config['ticker_interval']), return self._exchange.klines((pair, timeframe or self._config['ticker_interval']),
copy=copy) copy=copy)
else: else:
return DataFrame() return DataFrame()
def historic_ohlcv(self, pair: str, ticker_interval: str = None) -> DataFrame: def historic_ohlcv(self, pair: str, timeframe: str = None) -> DataFrame:
""" """
Get stored historic ohlcv data Get stored historic ohlcv data
:param pair: pair to get the data for :param pair: pair to get the data for
:param ticker_interval: ticker interval to get data for :param timeframe: timeframe to get data for
""" """
return load_pair_history(pair=pair, return load_pair_history(pair=pair,
ticker_interval=ticker_interval or self._config['ticker_interval'], timeframe=timeframe or self._config['ticker_interval'],
datadir=Path(self._config['datadir']) datadir=Path(self._config['datadir'])
) )
def get_pair_dataframe(self, pair: str, ticker_interval: str = None) -> DataFrame: def get_pair_dataframe(self, pair: str, timeframe: str = None) -> DataFrame:
""" """
Return pair ohlcv data, either live or cached historical -- depending Return pair ohlcv data, either live or cached historical -- depending
on the runmode. on the runmode.
:param pair: pair to get the data for :param pair: pair to get the data for
:param ticker_interval: ticker interval to get data for :param timeframe: timeframe to get data for
:return: Dataframe for this pair
""" """
if self.runmode in (RunMode.DRY_RUN, RunMode.LIVE): if self.runmode in (RunMode.DRY_RUN, RunMode.LIVE):
# Get live ohlcv data. # Get live ohlcv data.
data = self.ohlcv(pair=pair, ticker_interval=ticker_interval) data = self.ohlcv(pair=pair, timeframe=timeframe)
else: else:
# Get historic ohlcv data (cached on disk). # Get historic ohlcv data (cached on disk).
data = self.historic_ohlcv(pair=pair, ticker_interval=ticker_interval) data = self.historic_ohlcv(pair=pair, timeframe=timeframe)
if len(data) == 0: if len(data) == 0:
logger.warning(f"No data found for ({pair}, {ticker_interval}).") logger.warning(f"No data found for ({pair}, {timeframe}).")
return data return data
def market(self, pair: str) -> Optional[Dict[str, Any]]: def market(self, pair: str) -> Optional[Dict[str, Any]]:

View File

@ -63,13 +63,13 @@ def trim_dataframe(df: DataFrame, timerange: TimeRange) -> DataFrame:
return df return df
def load_tickerdata_file(datadir: Path, pair: str, ticker_interval: str, def load_tickerdata_file(datadir: Path, pair: str, timeframe: str,
timerange: Optional[TimeRange] = None) -> Optional[list]: timerange: Optional[TimeRange] = None) -> Optional[list]:
""" """
Load a pair from file, either .json.gz or .json Load a pair from file, either .json.gz or .json
:return: tickerlist or None if unsuccessful :return: tickerlist or None if unsuccessful
""" """
filename = pair_data_filename(datadir, pair, ticker_interval) filename = pair_data_filename(datadir, pair, timeframe)
pairdata = misc.file_load_json(filename) pairdata = misc.file_load_json(filename)
if not pairdata: if not pairdata:
return [] return []
@ -80,11 +80,11 @@ def load_tickerdata_file(datadir: Path, pair: str, ticker_interval: str,
def store_tickerdata_file(datadir: Path, pair: str, def store_tickerdata_file(datadir: Path, pair: str,
ticker_interval: str, data: list, is_zip: bool = False): timeframe: str, data: list, is_zip: bool = False):
""" """
Stores tickerdata to file Stores tickerdata to file
""" """
filename = pair_data_filename(datadir, pair, ticker_interval) filename = pair_data_filename(datadir, pair, timeframe)
misc.file_dump_json(filename, data, is_zip=is_zip) misc.file_dump_json(filename, data, is_zip=is_zip)
@ -121,7 +121,7 @@ def _validate_pairdata(pair, pairdata, timerange: TimeRange):
def load_pair_history(pair: str, def load_pair_history(pair: str,
ticker_interval: str, timeframe: str,
datadir: Path, datadir: Path,
timerange: Optional[TimeRange] = None, timerange: Optional[TimeRange] = None,
refresh_pairs: bool = False, refresh_pairs: bool = False,
@ -133,7 +133,7 @@ def load_pair_history(pair: str,
""" """
Loads cached ticker history for the given pair. Loads cached ticker history for the given pair.
:param pair: Pair to load data for :param pair: Pair to load data for
:param ticker_interval: Ticker-interval (e.g. "5m") :param timeframe: Ticker timeframe (e.g. "5m")
:param datadir: Path to the data storage location. :param datadir: Path to the data storage location.
:param timerange: Limit data to be loaded to this timerange :param timerange: Limit data to be loaded to this timerange
:param refresh_pairs: Refresh pairs from exchange. :param refresh_pairs: Refresh pairs from exchange.
@ -147,34 +147,34 @@ def load_pair_history(pair: str,
timerange_startup = deepcopy(timerange) timerange_startup = deepcopy(timerange)
if startup_candles > 0 and timerange_startup: if startup_candles > 0 and timerange_startup:
timerange_startup.subtract_start(timeframe_to_seconds(ticker_interval) * startup_candles) timerange_startup.subtract_start(timeframe_to_seconds(timeframe) * startup_candles)
# The user forced the refresh of pairs # The user forced the refresh of pairs
if refresh_pairs: if refresh_pairs:
download_pair_history(datadir=datadir, download_pair_history(datadir=datadir,
exchange=exchange, exchange=exchange,
pair=pair, pair=pair,
ticker_interval=ticker_interval, timeframe=timeframe,
timerange=timerange) timerange=timerange)
pairdata = load_tickerdata_file(datadir, pair, ticker_interval, timerange=timerange_startup) pairdata = load_tickerdata_file(datadir, pair, timeframe, timerange=timerange_startup)
if pairdata: if pairdata:
if timerange_startup: if timerange_startup:
_validate_pairdata(pair, pairdata, timerange_startup) _validate_pairdata(pair, pairdata, timerange_startup)
return parse_ticker_dataframe(pairdata, ticker_interval, pair=pair, return parse_ticker_dataframe(pairdata, timeframe, pair=pair,
fill_missing=fill_up_missing, fill_missing=fill_up_missing,
drop_incomplete=drop_incomplete) drop_incomplete=drop_incomplete)
else: else:
logger.warning( logger.warning(
f'No history data for pair: "{pair}", interval: {ticker_interval}. ' f'No history data for pair: "{pair}", timeframe: {timeframe}. '
'Use `freqtrade download-data` to download the data' 'Use `freqtrade download-data` to download the data'
) )
return None return None
def load_data(datadir: Path, def load_data(datadir: Path,
ticker_interval: str, timeframe: str,
pairs: List[str], pairs: List[str],
refresh_pairs: bool = False, refresh_pairs: bool = False,
exchange: Optional[Exchange] = None, exchange: Optional[Exchange] = None,
@ -186,7 +186,7 @@ def load_data(datadir: Path,
""" """
Loads ticker history data for a list of pairs Loads ticker history data for a list of pairs
:param datadir: Path to the data storage location. :param datadir: Path to the data storage location.
:param ticker_interval: Ticker-interval (e.g. "5m") :param timeframe: Ticker Timeframe (e.g. "5m")
:param pairs: List of pairs to load :param pairs: List of pairs to load
:param refresh_pairs: Refresh pairs from exchange. :param refresh_pairs: Refresh pairs from exchange.
(Note: Requires exchange to be passed as well.) (Note: Requires exchange to be passed as well.)
@ -206,7 +206,7 @@ def load_data(datadir: Path,
logger.info(f'Using indicator startup period: {startup_candles} ...') logger.info(f'Using indicator startup period: {startup_candles} ...')
for pair in pairs: for pair in pairs:
hist = load_pair_history(pair=pair, ticker_interval=ticker_interval, hist = load_pair_history(pair=pair, timeframe=timeframe,
datadir=datadir, timerange=timerange, datadir=datadir, timerange=timerange,
refresh_pairs=refresh_pairs, refresh_pairs=refresh_pairs,
exchange=exchange, exchange=exchange,
@ -220,9 +220,9 @@ def load_data(datadir: Path,
return result return result
def pair_data_filename(datadir: Path, pair: str, ticker_interval: str) -> Path: def pair_data_filename(datadir: Path, pair: str, timeframe: str) -> Path:
pair_s = pair.replace("/", "_") pair_s = pair.replace("/", "_")
filename = datadir.joinpath(f'{pair_s}-{ticker_interval}.json') filename = datadir.joinpath(f'{pair_s}-{timeframe}.json')
return filename return filename
@ -232,7 +232,7 @@ def pair_trades_filename(datadir: Path, pair: str) -> Path:
return filename return filename
def _load_cached_data_for_updating(datadir: Path, pair: str, ticker_interval: str, def _load_cached_data_for_updating(datadir: Path, pair: str, timeframe: str,
timerange: Optional[TimeRange]) -> Tuple[List[Any], timerange: Optional[TimeRange]) -> Tuple[List[Any],
Optional[int]]: Optional[int]]:
""" """
@ -250,12 +250,12 @@ def _load_cached_data_for_updating(datadir: Path, pair: str, ticker_interval: st
if timerange.starttype == 'date': if timerange.starttype == 'date':
since_ms = timerange.startts * 1000 since_ms = timerange.startts * 1000
elif timerange.stoptype == 'line': elif timerange.stoptype == 'line':
num_minutes = timerange.stopts * timeframe_to_minutes(ticker_interval) num_minutes = timerange.stopts * timeframe_to_minutes(timeframe)
since_ms = arrow.utcnow().shift(minutes=num_minutes).timestamp * 1000 since_ms = arrow.utcnow().shift(minutes=num_minutes).timestamp * 1000
# read the cached file # read the cached file
# Intentionally don't pass timerange in - since we need to load the full dataset. # Intentionally don't pass timerange in - since we need to load the full dataset.
data = load_tickerdata_file(datadir, pair, ticker_interval) data = load_tickerdata_file(datadir, pair, timeframe)
# remove the last item, could be incomplete candle # remove the last item, could be incomplete candle
if data: if data:
data.pop() data.pop()
@ -276,18 +276,18 @@ def _load_cached_data_for_updating(datadir: Path, pair: str, ticker_interval: st
def download_pair_history(datadir: Path, def download_pair_history(datadir: Path,
exchange: Optional[Exchange], exchange: Optional[Exchange],
pair: str, pair: str,
ticker_interval: str = '5m', timeframe: str = '5m',
timerange: Optional[TimeRange] = None) -> bool: timerange: Optional[TimeRange] = None) -> bool:
""" """
Download the latest ticker intervals from the exchange for the pair 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 ticker interval data that The data is downloaded starting from the last correct data that
exists in a cache. If timerange starts earlier than the data in the cache, exists in a cache. If timerange starts earlier than the data in the cache,
the full data will be redownloaded the full data will be redownloaded
Based on @Rybolov work: https://github.com/rybolov/freqtrade-data Based on @Rybolov work: https://github.com/rybolov/freqtrade-data
:param pair: pair to download :param pair: pair to download
:param ticker_interval: ticker interval :param timeframe: Ticker Timeframe (e.g 5m)
:param timerange: range of time to download :param timerange: range of time to download
:return: bool with success state :return: bool with success state
""" """
@ -298,17 +298,17 @@ def download_pair_history(datadir: Path,
try: try:
logger.info( logger.info(
f'Download history data for pair: "{pair}", interval: {ticker_interval} ' f'Download history data for pair: "{pair}", timeframe: {timeframe} '
f'and store in {datadir}.' f'and store in {datadir}.'
) )
data, since_ms = _load_cached_data_for_updating(datadir, pair, ticker_interval, timerange) data, since_ms = _load_cached_data_for_updating(datadir, pair, timeframe, timerange)
logger.debug("Current Start: %s", misc.format_ms_time(data[1][0]) if data else 'None') logger.debug("Current Start: %s", misc.format_ms_time(data[1][0]) if data else 'None')
logger.debug("Current End: %s", misc.format_ms_time(data[-1][0]) if data else 'None') logger.debug("Current End: %s", misc.format_ms_time(data[-1][0]) if data else 'None')
# Default since_ms to 30 days if nothing is given # Default since_ms to 30 days if nothing is given
new_data = exchange.get_historic_ohlcv(pair=pair, ticker_interval=ticker_interval, new_data = exchange.get_historic_ohlcv(pair=pair, timeframe=timeframe,
since_ms=since_ms if since_ms since_ms=since_ms if since_ms
else else
int(arrow.utcnow().shift( int(arrow.utcnow().shift(
@ -318,12 +318,12 @@ def download_pair_history(datadir: Path,
logger.debug("New Start: %s", misc.format_ms_time(data[0][0])) logger.debug("New Start: %s", misc.format_ms_time(data[0][0]))
logger.debug("New End: %s", misc.format_ms_time(data[-1][0])) logger.debug("New End: %s", misc.format_ms_time(data[-1][0]))
store_tickerdata_file(datadir, pair, ticker_interval, data=data) store_tickerdata_file(datadir, pair, timeframe, data=data)
return True return True
except Exception as e: except Exception as e:
logger.error( logger.error(
f'Failed to download history data for pair: "{pair}", interval: {ticker_interval}. ' f'Failed to download history data for pair: "{pair}", timeframe: {timeframe}. '
f'Error: {e}' f'Error: {e}'
) )
return False return False
@ -343,17 +343,17 @@ def refresh_backtest_ohlcv_data(exchange: Exchange, pairs: List[str], timeframes
pairs_not_available.append(pair) pairs_not_available.append(pair)
logger.info(f"Skipping pair {pair}...") logger.info(f"Skipping pair {pair}...")
continue continue
for ticker_interval in timeframes: for timeframe in timeframes:
dl_file = pair_data_filename(dl_path, pair, ticker_interval) dl_file = pair_data_filename(dl_path, pair, timeframe)
if erase and dl_file.exists(): if erase and dl_file.exists():
logger.info( logger.info(
f'Deleting existing data for pair {pair}, interval {ticker_interval}.') f'Deleting existing data for pair {pair}, interval {timeframe}.')
dl_file.unlink() dl_file.unlink()
logger.info(f'Downloading pair {pair}, interval {ticker_interval}.') logger.info(f'Downloading pair {pair}, interval {timeframe}.')
download_pair_history(datadir=dl_path, exchange=exchange, download_pair_history(datadir=dl_path, exchange=exchange,
pair=pair, ticker_interval=str(ticker_interval), pair=pair, timeframe=str(timeframe),
timerange=timerange) timerange=timerange)
return pairs_not_available return pairs_not_available
@ -459,7 +459,7 @@ def get_timeframe(data: Dict[str, DataFrame]) -> Tuple[arrow.Arrow, arrow.Arrow]
def validate_backtest_data(data: DataFrame, pair: str, min_date: datetime, def validate_backtest_data(data: DataFrame, pair: str, min_date: datetime,
max_date: datetime, ticker_interval_mins: int) -> bool: max_date: datetime, timeframe_mins: int) -> bool:
""" """
Validates preprocessed backtesting data for missing values and shows warnings about it that. Validates preprocessed backtesting data for missing values and shows warnings about it that.
@ -467,10 +467,10 @@ def validate_backtest_data(data: DataFrame, pair: str, min_date: datetime,
:param pair: pair used for log output. :param pair: pair used for log output.
:param min_date: start-date of the data :param min_date: start-date of the data
:param max_date: end-date of the data :param max_date: end-date of the data
:param ticker_interval_mins: ticker interval in minutes :param timeframe_mins: ticker Timeframe in minutes
""" """
# total difference in minutes / interval-minutes # total difference in minutes / timeframe-minutes
expected_frames = int((max_date - min_date).total_seconds() // 60 // ticker_interval_mins) expected_frames = int((max_date - min_date).total_seconds() // 60 // timeframe_mins)
found_missing = False found_missing = False
dflen = len(data) dflen = len(data)
if dflen < expected_frames: if dflen < expected_frames:

View File

@ -97,7 +97,7 @@ class Edge:
data = history.load_data( data = history.load_data(
datadir=Path(self.config['datadir']), datadir=Path(self.config['datadir']),
pairs=pairs, pairs=pairs,
ticker_interval=self.strategy.ticker_interval, timeframe=self.strategy.ticker_interval,
refresh_pairs=self._refresh_pairs, refresh_pairs=self._refresh_pairs,
exchange=self.exchange, exchange=self.exchange,
timerange=self._timerange, timerange=self._timerange,

View File

@ -536,40 +536,40 @@ class Exchange:
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]
def get_historic_ohlcv(self, pair: str, ticker_interval: str, def get_historic_ohlcv(self, pair: str, timeframe: str,
since_ms: int) -> List: since_ms: int) -> List:
""" """
Gets candle history using asyncio and returns the list of candles. Gets candle history using asyncio and returns the list of candles.
Handles all async doing. Handles all async doing.
Async over one pair, assuming we get `_ohlcv_candle_limit` candles per call. Async over one pair, assuming we get `_ohlcv_candle_limit` candles per call.
:param pair: Pair to download :param pair: Pair to download
:param ticker_interval: Interval to get :param timeframe: Ticker Timeframe to get
:param since_ms: Timestamp in milliseconds to get history from :param since_ms: Timestamp in milliseconds to get history from
:returns List of tickers :returns List of tickers
""" """
return asyncio.get_event_loop().run_until_complete( return asyncio.get_event_loop().run_until_complete(
self._async_get_historic_ohlcv(pair=pair, ticker_interval=ticker_interval, self._async_get_historic_ohlcv(pair=pair, timeframe=timeframe,
since_ms=since_ms)) since_ms=since_ms))
async def _async_get_historic_ohlcv(self, pair: str, async def _async_get_historic_ohlcv(self, pair: str,
ticker_interval: str, timeframe: str,
since_ms: int) -> List: since_ms: int) -> List:
one_call = timeframe_to_msecs(ticker_interval) * self._ohlcv_candle_limit one_call = timeframe_to_msecs(timeframe) * self._ohlcv_candle_limit
logger.debug( logger.debug(
"one_call: %s msecs (%s)", "one_call: %s msecs (%s)",
one_call, one_call,
arrow.utcnow().shift(seconds=one_call // 1000).humanize(only_distance=True) arrow.utcnow().shift(seconds=one_call // 1000).humanize(only_distance=True)
) )
input_coroutines = [self._async_get_candle_history( input_coroutines = [self._async_get_candle_history(
pair, ticker_interval, since) for since in pair, timeframe, since) for since in
range(since_ms, arrow.utcnow().timestamp * 1000, one_call)] range(since_ms, arrow.utcnow().timestamp * 1000, one_call)]
tickers = await asyncio.gather(*input_coroutines, return_exceptions=True) tickers = await asyncio.gather(*input_coroutines, return_exceptions=True)
# Combine tickers # Combine tickers
data: List = [] data: List = []
for p, ticker_interval, ticker in tickers: for p, timeframe, ticker in tickers:
if p == pair: if p == pair:
data.extend(ticker) data.extend(ticker)
# Sort data again after extending the result - above calls return in "async order" # Sort data again after extending the result - above calls return in "async order"
@ -589,14 +589,14 @@ class Exchange:
input_coroutines = [] input_coroutines = []
# Gather coroutines to run # Gather coroutines to run
for pair, ticker_interval in set(pair_list): for pair, timeframe in set(pair_list):
if (not ((pair, ticker_interval) in self._klines) if (not ((pair, timeframe) in self._klines)
or self._now_is_time_to_refresh(pair, ticker_interval)): or self._now_is_time_to_refresh(pair, timeframe)):
input_coroutines.append(self._async_get_candle_history(pair, ticker_interval)) input_coroutines.append(self._async_get_candle_history(pair, timeframe))
else: else:
logger.debug( logger.debug(
"Using cached ohlcv data for pair %s, interval %s ...", "Using cached ohlcv data for pair %s, timeframe %s ...",
pair, ticker_interval pair, timeframe
) )
tickers = asyncio.get_event_loop().run_until_complete( tickers = asyncio.get_event_loop().run_until_complete(
@ -608,40 +608,40 @@ class Exchange:
logger.warning("Async code raised an exception: %s", res.__class__.__name__) logger.warning("Async code raised an exception: %s", res.__class__.__name__)
continue continue
pair = res[0] pair = res[0]
ticker_interval = res[1] timeframe = res[1]
ticks = res[2] ticks = res[2]
# keeping last candle time as last refreshed time of the pair # keeping last candle time as last refreshed time of the pair
if ticks: if ticks:
self._pairs_last_refresh_time[(pair, ticker_interval)] = ticks[-1][0] // 1000 self._pairs_last_refresh_time[(pair, timeframe)] = ticks[-1][0] // 1000
# keeping parsed dataframe in cache # keeping parsed dataframe in cache
self._klines[(pair, ticker_interval)] = parse_ticker_dataframe( self._klines[(pair, timeframe)] = parse_ticker_dataframe(
ticks, ticker_interval, pair=pair, fill_missing=True, ticks, timeframe, pair=pair, fill_missing=True,
drop_incomplete=self._ohlcv_partial_candle) drop_incomplete=self._ohlcv_partial_candle)
return tickers return tickers
def _now_is_time_to_refresh(self, pair: str, ticker_interval: str) -> bool: def _now_is_time_to_refresh(self, pair: str, timeframe: str) -> bool:
# Calculating ticker interval in seconds # Calculating ticker interval in seconds
interval_in_sec = timeframe_to_seconds(ticker_interval) interval_in_sec = timeframe_to_seconds(timeframe)
return not ((self._pairs_last_refresh_time.get((pair, ticker_interval), 0) return not ((self._pairs_last_refresh_time.get((pair, timeframe), 0)
+ interval_in_sec) >= arrow.utcnow().timestamp) + interval_in_sec) >= arrow.utcnow().timestamp)
@retrier_async @retrier_async
async def _async_get_candle_history(self, pair: str, ticker_interval: str, async def _async_get_candle_history(self, pair: str, timeframe: str,
since_ms: Optional[int] = None) -> Tuple[str, str, List]: since_ms: Optional[int] = None) -> Tuple[str, str, List]:
""" """
Asynchronously gets candle histories using fetch_ohlcv Asynchronously gets candle histories using fetch_ohlcv
returns tuple: (pair, ticker_interval, ohlcv_list) returns tuple: (pair, timeframe, ohlcv_list)
""" """
try: try:
# fetch ohlcv asynchronously # fetch ohlcv asynchronously
s = '(' + arrow.get(since_ms // 1000).isoformat() + ') ' if since_ms is not None else '' s = '(' + arrow.get(since_ms // 1000).isoformat() + ') ' if since_ms is not None else ''
logger.debug( logger.debug(
"Fetching pair %s, interval %s, since %s %s...", "Fetching pair %s, interval %s, since %s %s...",
pair, ticker_interval, since_ms, s pair, timeframe, since_ms, s
) )
data = await self._api_async.fetch_ohlcv(pair, timeframe=ticker_interval, data = await self._api_async.fetch_ohlcv(pair, timeframe=timeframe,
since=since_ms) since=since_ms)
# Because some exchange sort Tickers ASC and other DESC. # Because some exchange sort Tickers ASC and other DESC.
@ -653,9 +653,9 @@ class Exchange:
data = sorted(data, key=lambda x: x[0]) data = sorted(data, key=lambda x: x[0])
except IndexError: except IndexError:
logger.exception("Error loading %s. Result was %s.", pair, data) logger.exception("Error loading %s. Result was %s.", pair, data)
return pair, ticker_interval, [] return pair, timeframe, []
logger.debug("Done fetching pair %s, interval %s ...", pair, ticker_interval) logger.debug("Done fetching pair %s, interval %s ...", pair, timeframe)
return pair, ticker_interval, data return pair, timeframe, data
except ccxt.NotSupported as e: except ccxt.NotSupported as e:
raise OperationalException( raise OperationalException(
@ -802,7 +802,6 @@ class Exchange:
Handles all async doing. Handles all async doing.
Async over one pair, assuming we get `_ohlcv_candle_limit` candles per call. Async over one pair, assuming we get `_ohlcv_candle_limit` candles per call.
:param pair: Pair to download :param pair: Pair to download
:param ticker_interval: Interval to get
:param since: Timestamp in milliseconds to get history from :param since: Timestamp in milliseconds to get history from
:param until: Timestamp in milliseconds. Defaults to current timestamp if not defined. :param until: Timestamp in milliseconds. Defaults to current timestamp if not defined.
:param from_id: Download data starting with ID (if id is known) :param from_id: Download data starting with ID (if id is known)
@ -958,27 +957,27 @@ def available_exchanges(ccxt_module=None) -> List[str]:
return [x for x in exchanges if not is_exchange_bad(x)] return [x for x in exchanges if not is_exchange_bad(x)]
def timeframe_to_seconds(ticker_interval: str) -> int: def timeframe_to_seconds(timeframe: str) -> int:
""" """
Translates the timeframe interval value written in the human readable Translates the timeframe interval value written in the human readable
form ('1m', '5m', '1h', '1d', '1w', etc.) to the number form ('1m', '5m', '1h', '1d', '1w', etc.) to the number
of seconds for one timeframe interval. of seconds for one timeframe interval.
""" """
return ccxt.Exchange.parse_timeframe(ticker_interval) return ccxt.Exchange.parse_timeframe(timeframe)
def timeframe_to_minutes(ticker_interval: str) -> int: def timeframe_to_minutes(timeframe: str) -> int:
""" """
Same as timeframe_to_seconds, but returns minutes. Same as timeframe_to_seconds, but returns minutes.
""" """
return ccxt.Exchange.parse_timeframe(ticker_interval) // 60 return ccxt.Exchange.parse_timeframe(timeframe) // 60
def timeframe_to_msecs(ticker_interval: str) -> int: def timeframe_to_msecs(timeframe: str) -> int:
""" """
Same as timeframe_to_seconds, but returns milliseconds. Same as timeframe_to_seconds, but returns milliseconds.
""" """
return ccxt.Exchange.parse_timeframe(ticker_interval) * 1000 return ccxt.Exchange.parse_timeframe(timeframe) * 1000
def timeframe_to_prev_date(timeframe: str, date: datetime = None) -> datetime: def timeframe_to_prev_date(timeframe: str, date: datetime = None) -> datetime:

View File

@ -83,8 +83,8 @@ class Backtesting:
if "ticker_interval" not in self.config: if "ticker_interval" not in self.config:
raise OperationalException("Ticker-interval needs to be set in either configuration " raise OperationalException("Ticker-interval needs to be set in either configuration "
"or as cli argument `--ticker-interval 5m`") "or as cli argument `--ticker-interval 5m`")
self.ticker_interval = str(self.config.get('ticker_interval')) self.timeframe = str(self.config.get('ticker_interval'))
self.ticker_interval_mins = timeframe_to_minutes(self.ticker_interval) self.timeframe_mins = timeframe_to_minutes(self.timeframe)
# Get maximum required startup period # Get maximum required startup period
self.required_startup = max([strat.startup_candle_count for strat in self.strategylist]) self.required_startup = max([strat.startup_candle_count for strat in self.strategylist])
@ -108,7 +108,7 @@ class Backtesting:
data = history.load_data( data = history.load_data(
datadir=Path(self.config['datadir']), datadir=Path(self.config['datadir']),
pairs=self.config['exchange']['pair_whitelist'], pairs=self.config['exchange']['pair_whitelist'],
ticker_interval=self.ticker_interval, timeframe=self.timeframe,
timerange=timerange, timerange=timerange,
startup_candles=self.required_startup, startup_candles=self.required_startup,
fail_without_data=True, fail_without_data=True,
@ -121,7 +121,7 @@ class Backtesting:
min_date.isoformat(), max_date.isoformat(), (max_date - min_date).days min_date.isoformat(), max_date.isoformat(), (max_date - min_date).days
) )
# Adjust startts forward if not enough data is available # Adjust startts forward if not enough data is available
timerange.adjust_start_if_necessary(timeframe_to_seconds(self.ticker_interval), timerange.adjust_start_if_necessary(timeframe_to_seconds(self.timeframe),
self.required_startup, min_date) self.required_startup, min_date)
return data, timerange return data, timerange
@ -375,7 +375,7 @@ class Backtesting:
lock_pair_until: Dict = {} lock_pair_until: Dict = {}
# Indexes per pair, so some pairs are allowed to have a missing start. # Indexes per pair, so some pairs are allowed to have a missing start.
indexes: Dict = {} indexes: Dict = {}
tmp = start_date + timedelta(minutes=self.ticker_interval_mins) tmp = start_date + timedelta(minutes=self.timeframe_mins)
# Loop timerange and get candle for each pair at that point in time # Loop timerange and get candle for each pair at that point in time
while tmp < end_date: while tmp < end_date:
@ -427,7 +427,7 @@ class Backtesting:
lock_pair_until[pair] = end_date.datetime lock_pair_until[pair] = end_date.datetime
# Move time one configured time_interval ahead. # Move time one configured time_interval ahead.
tmp += timedelta(minutes=self.ticker_interval_mins) tmp += timedelta(minutes=self.timeframe_mins)
return DataFrame.from_records(trades, columns=BacktestResult._fields) return DataFrame.from_records(trades, columns=BacktestResult._fields)
def start(self) -> None: def start(self) -> None:

View File

@ -106,10 +106,10 @@ class IHyperOpt(ABC):
roi_t_alpha = 1.0 roi_t_alpha = 1.0
roi_p_alpha = 1.0 roi_p_alpha = 1.0
ticker_interval_mins = timeframe_to_minutes(IHyperOpt.ticker_interval) timeframe_mins = timeframe_to_minutes(IHyperOpt.ticker_interval)
# We define here limits for the ROI space parameters automagically adapted to the # We define here limits for the ROI space parameters automagically adapted to the
# ticker_interval used by the bot: # timeframe used by the bot:
# #
# * 'roi_t' (limits for the time intervals in the ROI tables) components # * 'roi_t' (limits for the time intervals in the ROI tables) components
# are scaled linearly. # are scaled linearly.
@ -117,8 +117,8 @@ class IHyperOpt(ABC):
# #
# The scaling is designed so that it maps exactly to the legacy Freqtrade roi_space() # The scaling is designed so that it maps exactly to the legacy Freqtrade roi_space()
# method for the 5m ticker interval. # method for the 5m ticker interval.
roi_t_scale = ticker_interval_mins / 5 roi_t_scale = timeframe_mins / 5
roi_p_scale = math.log1p(ticker_interval_mins) / math.log1p(5) roi_p_scale = math.log1p(timeframe_mins) / math.log1p(5)
roi_limits = { roi_limits = {
'roi_t1_min': int(10 * roi_t_scale * roi_t_alpha), 'roi_t1_min': int(10 * roi_t_scale * roi_t_alpha),
'roi_t1_max': int(120 * roi_t_scale * roi_t_alpha), 'roi_t1_max': int(120 * roi_t_scale * roi_t_alpha),

View File

@ -39,7 +39,7 @@ def init_plotscript(config):
tickers = history.load_data( tickers = history.load_data(
datadir=Path(str(config.get("datadir"))), datadir=Path(str(config.get("datadir"))),
pairs=pairs, pairs=pairs,
ticker_interval=config.get('ticker_interval', '5m'), timeframe=config.get('ticker_interval', '5m'),
timerange=timerange, timerange=timerange,
) )
@ -300,12 +300,12 @@ def generate_profit_graph(pairs: str, tickers: Dict[str, pd.DataFrame],
return fig return fig
def generate_plot_filename(pair, ticker_interval) -> str: def generate_plot_filename(pair, timeframe) -> str:
""" """
Generate filenames per pair/ticker_interval to be used for storing plots Generate filenames per pair/timeframe to be used for storing plots
""" """
pair_name = pair.replace("/", "_") pair_name = pair.replace("/", "_")
file_name = 'freqtrade-plot-' + pair_name + '-' + ticker_interval + '.html' file_name = 'freqtrade-plot-' + pair_name + '-' + timeframe + '.html'
logger.info('Generate plot file for %s', pair) logger.info('Generate plot file for %s', pair)
@ -316,8 +316,9 @@ def store_plot_file(fig, filename: str, directory: Path, auto_open: bool = False
""" """
Generate a plot html file from pre populated fig plotly object Generate a plot html file from pre populated fig plotly object
:param fig: Plotly Figure to plot :param fig: Plotly Figure to plot
:param pair: Pair to plot (used as filename and Plot title) :param filename: Name to store the file as
:param ticker_interval: Used as part of the filename :param directory: Directory to store the file in
:param auto_open: Automatically open files saved
:return: None :return: None
""" """
directory.mkdir(parents=True, exist_ok=True) directory.mkdir(parents=True, exist_ok=True)

View File

@ -56,7 +56,7 @@ def test_extract_trades_of_period(testdatadir):
# 2018-11-14 06:07:00 # 2018-11-14 06:07:00
timerange = TimeRange('date', None, 1510639620, 0) timerange = TimeRange('date', None, 1510639620, 0)
data = load_pair_history(pair=pair, ticker_interval='1m', data = load_pair_history(pair=pair, timeframe='1m',
datadir=testdatadir, timerange=timerange) datadir=testdatadir, timerange=timerange)
trades = DataFrame( trades = DataFrame(
@ -122,7 +122,7 @@ def test_combine_tickers_with_mean(testdatadir):
pairs = ["ETH/BTC", "ADA/BTC"] pairs = ["ETH/BTC", "ADA/BTC"]
tickers = load_data(datadir=testdatadir, tickers = load_data(datadir=testdatadir,
pairs=pairs, pairs=pairs,
ticker_interval='5m' timeframe='5m'
) )
df = combine_tickers_with_mean(tickers) df = combine_tickers_with_mean(tickers)
assert isinstance(df, DataFrame) assert isinstance(df, DataFrame)
@ -136,7 +136,7 @@ def test_create_cum_profit(testdatadir):
bt_data = load_backtest_data(filename) bt_data = load_backtest_data(filename)
timerange = TimeRange.parse_timerange("20180110-20180112") timerange = TimeRange.parse_timerange("20180110-20180112")
df = load_pair_history(pair="TRX/BTC", ticker_interval='5m', df = load_pair_history(pair="TRX/BTC", timeframe='5m',
datadir=testdatadir, timerange=timerange) datadir=testdatadir, timerange=timerange)
cum_profits = create_cum_profit(df.set_index('date'), cum_profits = create_cum_profit(df.set_index('date'),
@ -154,7 +154,7 @@ def test_create_cum_profit1(testdatadir):
bt_data.loc[:, 'close_time'] = bt_data.loc[:, 'close_time'] + DateOffset(seconds=20) bt_data.loc[:, 'close_time'] = bt_data.loc[:, 'close_time'] + DateOffset(seconds=20)
timerange = TimeRange.parse_timerange("20180110-20180112") timerange = TimeRange.parse_timerange("20180110-20180112")
df = load_pair_history(pair="TRX/BTC", ticker_interval='5m', df = load_pair_history(pair="TRX/BTC", timeframe='5m',
datadir=testdatadir, timerange=timerange) datadir=testdatadir, timerange=timerange)
cum_profits = create_cum_profit(df.set_index('date'), cum_profits = create_cum_profit(df.set_index('date'),

View File

@ -23,7 +23,7 @@ def test_parse_ticker_dataframe(ticker_history_list, caplog):
def test_ohlcv_fill_up_missing_data(testdatadir, caplog): def test_ohlcv_fill_up_missing_data(testdatadir, caplog):
data = load_pair_history(datadir=testdatadir, data = load_pair_history(datadir=testdatadir,
ticker_interval='1m', timeframe='1m',
pair='UNITTEST/BTC', pair='UNITTEST/BTC',
fill_up_missing=False) fill_up_missing=False)
caplog.set_level(logging.DEBUG) caplog.set_level(logging.DEBUG)
@ -42,7 +42,7 @@ def test_ohlcv_fill_up_missing_data(testdatadir, caplog):
def test_ohlcv_fill_up_missing_data2(caplog): def test_ohlcv_fill_up_missing_data2(caplog):
ticker_interval = '5m' timeframe = '5m'
ticks = [[ ticks = [[
1511686200000, # 8:50:00 1511686200000, # 8:50:00
8.794e-05, # open 8.794e-05, # open
@ -78,10 +78,10 @@ def test_ohlcv_fill_up_missing_data2(caplog):
] ]
# Generate test-data without filling missing # Generate test-data without filling missing
data = parse_ticker_dataframe(ticks, ticker_interval, pair="UNITTEST/BTC", fill_missing=False) data = parse_ticker_dataframe(ticks, timeframe, pair="UNITTEST/BTC", fill_missing=False)
assert len(data) == 3 assert len(data) == 3
caplog.set_level(logging.DEBUG) caplog.set_level(logging.DEBUG)
data2 = ohlcv_fill_up_missing_data(data, ticker_interval, "UNITTEST/BTC") data2 = ohlcv_fill_up_missing_data(data, timeframe, "UNITTEST/BTC")
assert len(data2) == 4 assert len(data2) == 4
# 3rd candle has been filled # 3rd candle has been filled
row = data2.loc[2, :] row = data2.loc[2, :]
@ -99,7 +99,7 @@ def test_ohlcv_fill_up_missing_data2(caplog):
def test_ohlcv_drop_incomplete(caplog): def test_ohlcv_drop_incomplete(caplog):
ticker_interval = '1d' timeframe = '1d'
ticks = [[ ticks = [[
1559750400000, # 2019-06-04 1559750400000, # 2019-06-04
8.794e-05, # open 8.794e-05, # open
@ -134,13 +134,13 @@ def test_ohlcv_drop_incomplete(caplog):
] ]
] ]
caplog.set_level(logging.DEBUG) caplog.set_level(logging.DEBUG)
data = parse_ticker_dataframe(ticks, ticker_interval, pair="UNITTEST/BTC", data = parse_ticker_dataframe(ticks, timeframe, pair="UNITTEST/BTC",
fill_missing=False, drop_incomplete=False) fill_missing=False, drop_incomplete=False)
assert len(data) == 4 assert len(data) == 4
assert not log_has("Dropping last candle", caplog) assert not log_has("Dropping last candle", caplog)
# Drop last candle # Drop last candle
data = parse_ticker_dataframe(ticks, ticker_interval, pair="UNITTEST/BTC", data = parse_ticker_dataframe(ticks, timeframe, pair="UNITTEST/BTC",
fill_missing=False, drop_incomplete=True) fill_missing=False, drop_incomplete=True)
assert len(data) == 3 assert len(data) == 3

View File

@ -9,32 +9,32 @@ from tests.conftest import get_patched_exchange
def test_ohlcv(mocker, default_conf, ticker_history): def test_ohlcv(mocker, default_conf, ticker_history):
default_conf["runmode"] = RunMode.DRY_RUN default_conf["runmode"] = RunMode.DRY_RUN
ticker_interval = default_conf["ticker_interval"] timeframe = default_conf["ticker_interval"]
exchange = get_patched_exchange(mocker, default_conf) exchange = get_patched_exchange(mocker, default_conf)
exchange._klines[("XRP/BTC", ticker_interval)] = ticker_history exchange._klines[("XRP/BTC", timeframe)] = ticker_history
exchange._klines[("UNITTEST/BTC", ticker_interval)] = ticker_history exchange._klines[("UNITTEST/BTC", timeframe)] = ticker_history
dp = DataProvider(default_conf, exchange) dp = DataProvider(default_conf, exchange)
assert dp.runmode == RunMode.DRY_RUN assert dp.runmode == RunMode.DRY_RUN
assert ticker_history.equals(dp.ohlcv("UNITTEST/BTC", ticker_interval)) assert ticker_history.equals(dp.ohlcv("UNITTEST/BTC", timeframe))
assert isinstance(dp.ohlcv("UNITTEST/BTC", ticker_interval), DataFrame) assert isinstance(dp.ohlcv("UNITTEST/BTC", timeframe), DataFrame)
assert dp.ohlcv("UNITTEST/BTC", ticker_interval) is not ticker_history assert dp.ohlcv("UNITTEST/BTC", timeframe) is not ticker_history
assert dp.ohlcv("UNITTEST/BTC", ticker_interval, copy=False) is ticker_history assert dp.ohlcv("UNITTEST/BTC", timeframe, copy=False) is ticker_history
assert not dp.ohlcv("UNITTEST/BTC", ticker_interval).empty assert not dp.ohlcv("UNITTEST/BTC", timeframe).empty
assert dp.ohlcv("NONESENSE/AAA", ticker_interval).empty assert dp.ohlcv("NONESENSE/AAA", timeframe).empty
# Test with and without parameter # Test with and without parameter
assert dp.ohlcv("UNITTEST/BTC", ticker_interval).equals(dp.ohlcv("UNITTEST/BTC")) assert dp.ohlcv("UNITTEST/BTC", timeframe).equals(dp.ohlcv("UNITTEST/BTC"))
default_conf["runmode"] = RunMode.LIVE default_conf["runmode"] = RunMode.LIVE
dp = DataProvider(default_conf, exchange) dp = DataProvider(default_conf, exchange)
assert dp.runmode == RunMode.LIVE assert dp.runmode == RunMode.LIVE
assert isinstance(dp.ohlcv("UNITTEST/BTC", ticker_interval), DataFrame) assert isinstance(dp.ohlcv("UNITTEST/BTC", timeframe), DataFrame)
default_conf["runmode"] = RunMode.BACKTEST default_conf["runmode"] = RunMode.BACKTEST
dp = DataProvider(default_conf, exchange) dp = DataProvider(default_conf, exchange)
assert dp.runmode == RunMode.BACKTEST assert dp.runmode == RunMode.BACKTEST
assert dp.ohlcv("UNITTEST/BTC", ticker_interval).empty assert dp.ohlcv("UNITTEST/BTC", timeframe).empty
def test_historic_ohlcv(mocker, default_conf, ticker_history): def test_historic_ohlcv(mocker, default_conf, ticker_history):
@ -45,7 +45,7 @@ def test_historic_ohlcv(mocker, default_conf, ticker_history):
data = dp.historic_ohlcv("UNITTEST/BTC", "5m") data = dp.historic_ohlcv("UNITTEST/BTC", "5m")
assert isinstance(data, DataFrame) assert isinstance(data, DataFrame)
assert historymock.call_count == 1 assert historymock.call_count == 1
assert historymock.call_args_list[0][1]["ticker_interval"] == "5m" assert historymock.call_args_list[0][1]["timeframe"] == "5m"
def test_get_pair_dataframe(mocker, default_conf, ticker_history): def test_get_pair_dataframe(mocker, default_conf, ticker_history):

View File

@ -64,20 +64,20 @@ def _clean_test_file(file: Path) -> None:
def test_load_data_30min_ticker(mocker, caplog, default_conf, testdatadir) -> None: def test_load_data_30min_ticker(mocker, caplog, default_conf, testdatadir) -> None:
ld = history.load_pair_history(pair='UNITTEST/BTC', ticker_interval='30m', datadir=testdatadir) ld = history.load_pair_history(pair='UNITTEST/BTC', timeframe='30m', datadir=testdatadir)
assert isinstance(ld, DataFrame) assert isinstance(ld, DataFrame)
assert not log_has( assert not log_has(
'Download history data for pair: "UNITTEST/BTC", interval: 30m ' 'Download history data for pair: "UNITTEST/BTC", timeframe: 30m '
'and store in None.', caplog 'and store in None.', caplog
) )
def test_load_data_7min_ticker(mocker, caplog, default_conf, testdatadir) -> None: def test_load_data_7min_ticker(mocker, caplog, default_conf, testdatadir) -> None:
ld = history.load_pair_history(pair='UNITTEST/BTC', ticker_interval='7m', datadir=testdatadir) ld = history.load_pair_history(pair='UNITTEST/BTC', timeframe='7m', datadir=testdatadir)
assert not isinstance(ld, DataFrame) assert not isinstance(ld, DataFrame)
assert ld is None assert ld is None
assert log_has( assert log_has(
'No history data for pair: "UNITTEST/BTC", interval: 7m. ' 'No history data for pair: "UNITTEST/BTC", timeframe: 7m. '
'Use `freqtrade download-data` to download the data', caplog 'Use `freqtrade download-data` to download the data', caplog
) )
@ -86,7 +86,7 @@ def test_load_data_1min_ticker(ticker_history, mocker, caplog, testdatadir) -> N
mocker.patch('freqtrade.exchange.Exchange.get_historic_ohlcv', return_value=ticker_history) mocker.patch('freqtrade.exchange.Exchange.get_historic_ohlcv', return_value=ticker_history)
file = testdatadir / 'UNITTEST_BTC-1m.json' file = testdatadir / 'UNITTEST_BTC-1m.json'
_backup_file(file, copy_file=True) _backup_file(file, copy_file=True)
history.load_data(datadir=testdatadir, ticker_interval='1m', pairs=['UNITTEST/BTC']) history.load_data(datadir=testdatadir, timeframe='1m', pairs=['UNITTEST/BTC'])
assert file.is_file() assert file.is_file()
assert not log_has( assert not log_has(
'Download history data for pair: "UNITTEST/BTC", interval: 1m ' 'Download history data for pair: "UNITTEST/BTC", interval: 1m '
@ -99,7 +99,7 @@ def test_load_data_startup_candles(mocker, caplog, default_conf, testdatadir) ->
ltfmock = mocker.patch('freqtrade.data.history.load_tickerdata_file', ltfmock = mocker.patch('freqtrade.data.history.load_tickerdata_file',
MagicMock(return_value=None)) MagicMock(return_value=None))
timerange = TimeRange('date', None, 1510639620, 0) timerange = TimeRange('date', None, 1510639620, 0)
history.load_pair_history(pair='UNITTEST/BTC', ticker_interval='1m', history.load_pair_history(pair='UNITTEST/BTC', timeframe='1m',
datadir=testdatadir, timerange=timerange, datadir=testdatadir, timerange=timerange,
startup_candles=20, startup_candles=20,
) )
@ -122,28 +122,28 @@ def test_load_data_with_new_pair_1min(ticker_history_list, mocker, caplog,
_backup_file(file) _backup_file(file)
# do not download a new pair if refresh_pairs isn't set # do not download a new pair if refresh_pairs isn't set
history.load_pair_history(datadir=testdatadir, history.load_pair_history(datadir=testdatadir,
ticker_interval='1m', timeframe='1m',
pair='MEME/BTC') pair='MEME/BTC')
assert not file.is_file() assert not file.is_file()
assert log_has( assert log_has(
'No history data for pair: "MEME/BTC", interval: 1m. ' 'No history data for pair: "MEME/BTC", timeframe: 1m. '
'Use `freqtrade download-data` to download the data', caplog 'Use `freqtrade download-data` to download the data', caplog
) )
# download a new pair if refresh_pairs is set # download a new pair if refresh_pairs is set
history.load_pair_history(datadir=testdatadir, history.load_pair_history(datadir=testdatadir,
ticker_interval='1m', timeframe='1m',
refresh_pairs=True, refresh_pairs=True,
exchange=exchange, exchange=exchange,
pair='MEME/BTC') pair='MEME/BTC')
assert file.is_file() assert file.is_file()
assert log_has_re( assert log_has_re(
'Download history data for pair: "MEME/BTC", interval: 1m ' 'Download history data for pair: "MEME/BTC", timeframe: 1m '
'and store in .*', caplog 'and store in .*', caplog
) )
with pytest.raises(OperationalException, match=r'Exchange needs to be initialized when.*'): with pytest.raises(OperationalException, match=r'Exchange needs to be initialized when.*'):
history.load_pair_history(datadir=testdatadir, history.load_pair_history(datadir=testdatadir,
ticker_interval='1m', timeframe='1m',
refresh_pairs=True, refresh_pairs=True,
exchange=None, exchange=None,
pair='MEME/BTC') pair='MEME/BTC')
@ -269,10 +269,10 @@ def test_download_pair_history(ticker_history_list, mocker, default_conf, testda
assert download_pair_history(datadir=testdatadir, exchange=exchange, assert download_pair_history(datadir=testdatadir, exchange=exchange,
pair='MEME/BTC', pair='MEME/BTC',
ticker_interval='1m') timeframe='1m')
assert download_pair_history(datadir=testdatadir, exchange=exchange, assert download_pair_history(datadir=testdatadir, exchange=exchange,
pair='CFI/BTC', pair='CFI/BTC',
ticker_interval='1m') timeframe='1m')
assert not exchange._pairs_last_refresh_time assert not exchange._pairs_last_refresh_time
assert file1_1.is_file() assert file1_1.is_file()
assert file2_1.is_file() assert file2_1.is_file()
@ -286,10 +286,10 @@ def test_download_pair_history(ticker_history_list, mocker, default_conf, testda
assert download_pair_history(datadir=testdatadir, exchange=exchange, assert download_pair_history(datadir=testdatadir, exchange=exchange,
pair='MEME/BTC', pair='MEME/BTC',
ticker_interval='5m') timeframe='5m')
assert download_pair_history(datadir=testdatadir, exchange=exchange, assert download_pair_history(datadir=testdatadir, exchange=exchange,
pair='CFI/BTC', pair='CFI/BTC',
ticker_interval='5m') timeframe='5m')
assert not exchange._pairs_last_refresh_time assert not exchange._pairs_last_refresh_time
assert file1_5.is_file() assert file1_5.is_file()
assert file2_5.is_file() assert file2_5.is_file()
@ -307,8 +307,8 @@ def test_download_pair_history2(mocker, default_conf, testdatadir) -> None:
json_dump_mock = mocker.patch('freqtrade.misc.file_dump_json', return_value=None) json_dump_mock = mocker.patch('freqtrade.misc.file_dump_json', return_value=None)
mocker.patch('freqtrade.exchange.Exchange.get_historic_ohlcv', return_value=tick) mocker.patch('freqtrade.exchange.Exchange.get_historic_ohlcv', return_value=tick)
exchange = get_patched_exchange(mocker, default_conf) exchange = get_patched_exchange(mocker, default_conf)
download_pair_history(testdatadir, exchange, pair="UNITTEST/BTC", ticker_interval='1m') download_pair_history(testdatadir, exchange, pair="UNITTEST/BTC", timeframe='1m')
download_pair_history(testdatadir, exchange, pair="UNITTEST/BTC", ticker_interval='3m') download_pair_history(testdatadir, exchange, pair="UNITTEST/BTC", timeframe='3m')
assert json_dump_mock.call_count == 2 assert json_dump_mock.call_count == 2
@ -326,12 +326,12 @@ def test_download_backtesting_data_exception(ticker_history, mocker, caplog,
assert not download_pair_history(datadir=testdatadir, exchange=exchange, assert not download_pair_history(datadir=testdatadir, exchange=exchange,
pair='MEME/BTC', pair='MEME/BTC',
ticker_interval='1m') timeframe='1m')
# clean files freshly downloaded # clean files freshly downloaded
_clean_test_file(file1_1) _clean_test_file(file1_1)
_clean_test_file(file1_5) _clean_test_file(file1_5)
assert log_has( assert log_has(
'Failed to download history data for pair: "MEME/BTC", interval: 1m. ' 'Failed to download history data for pair: "MEME/BTC", timeframe: 1m. '
'Error: File Error', caplog 'Error: File Error', caplog
) )
@ -369,7 +369,7 @@ def test_load_partial_missing(testdatadir, caplog) -> None:
caplog.clear() caplog.clear()
start = arrow.get('2018-01-10T00:00:00') start = arrow.get('2018-01-10T00:00:00')
end = arrow.get('2018-02-20T00:00:00') end = arrow.get('2018-02-20T00:00:00')
tickerdata = history.load_data(datadir=testdatadir, ticker_interval='5m', tickerdata = history.load_data(datadir=testdatadir, timeframe='5m',
pairs=['UNITTEST/BTC'], pairs=['UNITTEST/BTC'],
timerange=TimeRange('date', 'date', timerange=TimeRange('date', 'date',
start.timestamp, end.timestamp)) start.timestamp, end.timestamp))
@ -390,7 +390,7 @@ def test_init(default_conf, mocker) -> None:
exchange=exchange, exchange=exchange,
pairs=[], pairs=[],
refresh_pairs=True, refresh_pairs=True,
ticker_interval=default_conf['ticker_interval'] timeframe=default_conf['ticker_interval']
) )
@ -449,7 +449,7 @@ def test_trim_tickerlist(testdatadir) -> None:
def test_trim_dataframe(testdatadir) -> None: def test_trim_dataframe(testdatadir) -> None:
data = history.load_data( data = history.load_data(
datadir=testdatadir, datadir=testdatadir,
ticker_interval='1m', timeframe='1m',
pairs=['UNITTEST/BTC'] pairs=['UNITTEST/BTC']
)['UNITTEST/BTC'] )['UNITTEST/BTC']
min_date = int(data.iloc[0]['date'].timestamp()) min_date = int(data.iloc[0]['date'].timestamp())
@ -517,7 +517,7 @@ def test_get_timeframe(default_conf, mocker, testdatadir) -> None:
data = strategy.tickerdata_to_dataframe( data = strategy.tickerdata_to_dataframe(
history.load_data( history.load_data(
datadir=testdatadir, datadir=testdatadir,
ticker_interval='1m', timeframe='1m',
pairs=['UNITTEST/BTC'] pairs=['UNITTEST/BTC']
) )
) )
@ -533,7 +533,7 @@ def test_validate_backtest_data_warn(default_conf, mocker, caplog, testdatadir)
data = strategy.tickerdata_to_dataframe( data = strategy.tickerdata_to_dataframe(
history.load_data( history.load_data(
datadir=testdatadir, datadir=testdatadir,
ticker_interval='1m', timeframe='1m',
pairs=['UNITTEST/BTC'], pairs=['UNITTEST/BTC'],
fill_up_missing=False fill_up_missing=False
) )
@ -556,7 +556,7 @@ def test_validate_backtest_data(default_conf, mocker, caplog, testdatadir) -> No
data = strategy.tickerdata_to_dataframe( data = strategy.tickerdata_to_dataframe(
history.load_data( history.load_data(
datadir=testdatadir, datadir=testdatadir,
ticker_interval='5m', timeframe='5m',
pairs=['UNITTEST/BTC'], pairs=['UNITTEST/BTC'],
timerange=timerange timerange=timerange
) )
@ -669,10 +669,10 @@ def test_convert_trades_to_ohlcv(mocker, default_conf, testdatadir, caplog):
file5 = testdatadir / 'XRP_ETH-5m.json' file5 = testdatadir / 'XRP_ETH-5m.json'
# Compare downloaded dataset with converted dataset # Compare downloaded dataset with converted dataset
dfbak_1m = history.load_pair_history(datadir=testdatadir, dfbak_1m = history.load_pair_history(datadir=testdatadir,
ticker_interval="1m", timeframe="1m",
pair=pair) pair=pair)
dfbak_5m = history.load_pair_history(datadir=testdatadir, dfbak_5m = history.load_pair_history(datadir=testdatadir,
ticker_interval="5m", timeframe="5m",
pair=pair) pair=pair)
_backup_file(file1, copy_file=True) _backup_file(file1, copy_file=True)
@ -686,10 +686,10 @@ def test_convert_trades_to_ohlcv(mocker, default_conf, testdatadir, caplog):
assert log_has("Deleting existing data for pair XRP/ETH, interval 1m.", caplog) assert log_has("Deleting existing data for pair XRP/ETH, interval 1m.", caplog)
# Load new data # Load new data
df_1m = history.load_pair_history(datadir=testdatadir, df_1m = history.load_pair_history(datadir=testdatadir,
ticker_interval="1m", timeframe="1m",
pair=pair) pair=pair)
df_5m = history.load_pair_history(datadir=testdatadir, df_5m = history.load_pair_history(datadir=testdatadir,
ticker_interval="5m", timeframe="5m",
pair=pair) pair=pair)
assert df_1m.equals(dfbak_1m) assert df_1m.equals(dfbak_1m)

View File

@ -255,7 +255,7 @@ def test_edge_heartbeat_calculate(mocker, edge_conf):
assert edge.calculate() is False assert edge.calculate() is False
def mocked_load_data(datadir, pairs=[], ticker_interval='0m', refresh_pairs=False, def mocked_load_data(datadir, pairs=[], timeframe='0m', refresh_pairs=False,
timerange=None, exchange=None, *args, **kwargs): timerange=None, exchange=None, *args, **kwargs):
hz = 0.1 hz = 0.1
base = 0.001 base = 0.001

View File

@ -1047,8 +1047,8 @@ def test_get_historic_ohlcv(default_conf, mocker, caplog, exchange_name):
] ]
pair = 'ETH/BTC' pair = 'ETH/BTC'
async def mock_candle_hist(pair, ticker_interval, since_ms): async def mock_candle_hist(pair, timeframe, since_ms):
return pair, ticker_interval, tick return pair, timeframe, tick
exchange._async_get_candle_history = Mock(wraps=mock_candle_hist) exchange._async_get_candle_history = Mock(wraps=mock_candle_hist)
# one_call calculation * 1.8 should do 2 calls # one_call calculation * 1.8 should do 2 calls
@ -1107,7 +1107,7 @@ def test_refresh_latest_ohlcv(mocker, default_conf, caplog) -> None:
exchange.refresh_latest_ohlcv([('IOTA/ETH', '5m'), ('XRP/ETH', '5m')]) exchange.refresh_latest_ohlcv([('IOTA/ETH', '5m'), ('XRP/ETH', '5m')])
assert exchange._api_async.fetch_ohlcv.call_count == 2 assert exchange._api_async.fetch_ohlcv.call_count == 2
assert log_has(f"Using cached ohlcv data for pair {pairs[0][0]}, interval {pairs[0][1]} ...", assert log_has(f"Using cached ohlcv data for pair {pairs[0][0]}, timeframe {pairs[0][1]} ...",
caplog) caplog)
@ -1143,7 +1143,7 @@ async def test__async_get_candle_history(default_conf, mocker, caplog, exchange_
# exchange = Exchange(default_conf) # exchange = Exchange(default_conf)
await async_ccxt_exception(mocker, default_conf, MagicMock(), await async_ccxt_exception(mocker, default_conf, MagicMock(),
"_async_get_candle_history", "fetch_ohlcv", "_async_get_candle_history", "fetch_ohlcv",
pair='ABCD/BTC', ticker_interval=default_conf['ticker_interval']) pair='ABCD/BTC', timeframe=default_conf['ticker_interval'])
api_mock = MagicMock() api_mock = MagicMock()
with pytest.raises(OperationalException, match=r'Could not fetch ticker data*'): with pytest.raises(OperationalException, match=r'Could not fetch ticker data*'):

View File

@ -7,7 +7,7 @@ from freqtrade.exchange import timeframe_to_minutes
from freqtrade.strategy.interface import SellType from freqtrade.strategy.interface import SellType
ticker_start_time = arrow.get(2018, 10, 3) ticker_start_time = arrow.get(2018, 10, 3)
tests_ticker_interval = '1h' tests_timeframe = '1h'
class BTrade(NamedTuple): class BTrade(NamedTuple):
@ -36,7 +36,7 @@ class BTContainer(NamedTuple):
def _get_frame_time_from_offset(offset): def _get_frame_time_from_offset(offset):
return ticker_start_time.shift(minutes=(offset * timeframe_to_minutes(tests_ticker_interval)) return ticker_start_time.shift(minutes=(offset * timeframe_to_minutes(tests_timeframe))
).datetime ).datetime

View File

@ -9,7 +9,7 @@ from freqtrade.optimize.backtesting import Backtesting
from freqtrade.strategy.interface import SellType from freqtrade.strategy.interface import SellType
from tests.conftest import patch_exchange from tests.conftest import patch_exchange
from tests.optimize import (BTContainer, BTrade, _build_backtest_dataframe, from tests.optimize import (BTContainer, BTrade, _build_backtest_dataframe,
_get_frame_time_from_offset, tests_ticker_interval) _get_frame_time_from_offset, tests_timeframe)
# Test 0: Sell with signal sell in candle 3 # Test 0: Sell with signal sell in candle 3
# Test with Stop-loss at 1% # Test with Stop-loss at 1%
@ -293,7 +293,7 @@ def test_backtest_results(default_conf, fee, mocker, caplog, data) -> None:
""" """
default_conf["stoploss"] = data.stop_loss default_conf["stoploss"] = data.stop_loss
default_conf["minimal_roi"] = data.roi default_conf["minimal_roi"] = data.roi
default_conf["ticker_interval"] = tests_ticker_interval default_conf["ticker_interval"] = tests_timeframe
default_conf["trailing_stop"] = data.trailing_stop default_conf["trailing_stop"] = data.trailing_stop
default_conf["trailing_only_offset_is_reached"] = data.trailing_only_offset_is_reached default_conf["trailing_only_offset_is_reached"] = data.trailing_only_offset_is_reached
# Only add this to configuration If it's necessary # Only add this to configuration If it's necessary

View File

@ -50,7 +50,7 @@ def trim_dictlist(dict_list, num):
def load_data_test(what, testdatadir): def load_data_test(what, testdatadir):
timerange = TimeRange.parse_timerange('1510694220-1510700340') timerange = TimeRange.parse_timerange('1510694220-1510700340')
pair = history.load_tickerdata_file(testdatadir, ticker_interval='1m', pair = history.load_tickerdata_file(testdatadir, timeframe='1m',
pair='UNITTEST/BTC', timerange=timerange) pair='UNITTEST/BTC', timerange=timerange)
datalen = len(pair) datalen = len(pair)
@ -116,7 +116,7 @@ def simple_backtest(config, contour, num_results, mocker, testdatadir) -> None:
assert len(results) == num_results assert len(results) == num_results
def mocked_load_data(datadir, pairs=[], ticker_interval='0m', refresh_pairs=False, def mocked_load_data(datadir, pairs=[], timeframe='0m', refresh_pairs=False,
timerange=None, exchange=None, live=False, *args, **kwargs): timerange=None, exchange=None, live=False, *args, **kwargs):
tickerdata = history.load_tickerdata_file(datadir, 'UNITTEST/BTC', '1m', timerange=timerange) tickerdata = history.load_tickerdata_file(datadir, 'UNITTEST/BTC', '1m', timerange=timerange)
pairdata = {'UNITTEST/BTC': parse_ticker_dataframe(tickerdata, '1m', pair="UNITTEST/BTC", pairdata = {'UNITTEST/BTC': parse_ticker_dataframe(tickerdata, '1m', pair="UNITTEST/BTC",
@ -126,14 +126,14 @@ def mocked_load_data(datadir, pairs=[], ticker_interval='0m', refresh_pairs=Fals
# use for mock ccxt.fetch_ohlvc' # use for mock ccxt.fetch_ohlvc'
def _load_pair_as_ticks(pair, tickfreq): def _load_pair_as_ticks(pair, tickfreq):
ticks = history.load_tickerdata_file(None, ticker_interval=tickfreq, pair=pair) ticks = history.load_tickerdata_file(None, timeframe=tickfreq, pair=pair)
ticks = ticks[-201:] ticks = ticks[-201:]
return ticks return ticks
# FIX: fixturize this? # FIX: fixturize this?
def _make_backtest_conf(mocker, datadir, conf=None, pair='UNITTEST/BTC', record=None): def _make_backtest_conf(mocker, datadir, conf=None, pair='UNITTEST/BTC', record=None):
data = history.load_data(datadir=datadir, ticker_interval='1m', pairs=[pair]) data = history.load_data(datadir=datadir, timeframe='1m', pairs=[pair])
data = trim_dictlist(data, -201) data = trim_dictlist(data, -201)
patch_exchange(mocker) patch_exchange(mocker)
backtesting = Backtesting(conf) backtesting = Backtesting(conf)
@ -307,7 +307,7 @@ def test_backtesting_init(mocker, default_conf, order_types) -> None:
get_fee = mocker.patch('freqtrade.exchange.Exchange.get_fee', MagicMock(return_value=0.5)) get_fee = mocker.patch('freqtrade.exchange.Exchange.get_fee', MagicMock(return_value=0.5))
backtesting = Backtesting(default_conf) backtesting = Backtesting(default_conf)
assert backtesting.config == default_conf assert backtesting.config == default_conf
assert backtesting.ticker_interval == '5m' assert backtesting.timeframe == '5m'
assert callable(backtesting.strategy.tickerdata_to_dataframe) assert callable(backtesting.strategy.tickerdata_to_dataframe)
assert callable(backtesting.strategy.advise_buy) assert callable(backtesting.strategy.advise_buy)
assert callable(backtesting.strategy.advise_sell) assert callable(backtesting.strategy.advise_sell)
@ -522,7 +522,7 @@ def test_backtest(default_conf, fee, mocker, testdatadir) -> None:
backtesting = Backtesting(default_conf) backtesting = Backtesting(default_conf)
pair = 'UNITTEST/BTC' pair = 'UNITTEST/BTC'
timerange = TimeRange('date', None, 1517227800, 0) timerange = TimeRange('date', None, 1517227800, 0)
data = history.load_data(datadir=testdatadir, ticker_interval='5m', pairs=['UNITTEST/BTC'], data = history.load_data(datadir=testdatadir, timeframe='5m', pairs=['UNITTEST/BTC'],
timerange=timerange) timerange=timerange)
data_processed = backtesting.strategy.tickerdata_to_dataframe(data) data_processed = backtesting.strategy.tickerdata_to_dataframe(data)
min_date, max_date = get_timeframe(data_processed) min_date, max_date = get_timeframe(data_processed)
@ -576,9 +576,9 @@ def test_backtest_1min_ticker_interval(default_conf, fee, mocker, testdatadir) -
patch_exchange(mocker) patch_exchange(mocker)
backtesting = Backtesting(default_conf) backtesting = Backtesting(default_conf)
# Run a backtesting for an exiting 1min ticker_interval # Run a backtesting for an exiting 1min timeframe
timerange = TimeRange.parse_timerange('1510688220-1510700340') timerange = TimeRange.parse_timerange('1510688220-1510700340')
data = history.load_data(datadir=testdatadir, ticker_interval='1m', pairs=['UNITTEST/BTC'], data = history.load_data(datadir=testdatadir, timeframe='1m', pairs=['UNITTEST/BTC'],
timerange=timerange) timerange=timerange)
processed = backtesting.strategy.tickerdata_to_dataframe(data) processed = backtesting.strategy.tickerdata_to_dataframe(data)
min_date, max_date = get_timeframe(processed) min_date, max_date = get_timeframe(processed)
@ -688,7 +688,7 @@ def test_backtest_multi_pair(default_conf, fee, mocker, tres, pair, testdatadir)
patch_exchange(mocker) patch_exchange(mocker)
pairs = ['ADA/BTC', 'DASH/BTC', 'ETH/BTC', 'LTC/BTC', 'NXT/BTC'] pairs = ['ADA/BTC', 'DASH/BTC', 'ETH/BTC', 'LTC/BTC', 'NXT/BTC']
data = history.load_data(datadir=testdatadir, ticker_interval='5m', pairs=pairs) data = history.load_data(datadir=testdatadir, timeframe='5m', pairs=pairs)
# Only use 500 lines to increase performance # Only use 500 lines to increase performance
data = trim_dictlist(data, -500) data = trim_dictlist(data, -500)

View File

@ -64,7 +64,7 @@ def test_add_indicators(default_conf, testdatadir, caplog):
pair = "UNITTEST/BTC" pair = "UNITTEST/BTC"
timerange = TimeRange(None, 'line', 0, -1000) timerange = TimeRange(None, 'line', 0, -1000)
data = history.load_pair_history(pair=pair, ticker_interval='1m', data = history.load_pair_history(pair=pair, timeframe='1m',
datadir=testdatadir, timerange=timerange) datadir=testdatadir, timerange=timerange)
indicators1 = ["ema10"] indicators1 = ["ema10"]
indicators2 = ["macd"] indicators2 = ["macd"]
@ -129,7 +129,7 @@ def test_generate_candlestick_graph_no_signals_no_trades(default_conf, mocker, t
pair = "UNITTEST/BTC" pair = "UNITTEST/BTC"
timerange = TimeRange(None, 'line', 0, -1000) timerange = TimeRange(None, 'line', 0, -1000)
data = history.load_pair_history(pair=pair, ticker_interval='1m', data = history.load_pair_history(pair=pair, timeframe='1m',
datadir=testdatadir, timerange=timerange) datadir=testdatadir, timerange=timerange)
data['buy'] = 0 data['buy'] = 0
data['sell'] = 0 data['sell'] = 0
@ -164,7 +164,7 @@ def test_generate_candlestick_graph_no_trades(default_conf, mocker, testdatadir)
MagicMock(side_effect=fig_generating_mock)) MagicMock(side_effect=fig_generating_mock))
pair = 'UNITTEST/BTC' pair = 'UNITTEST/BTC'
timerange = TimeRange(None, 'line', 0, -1000) timerange = TimeRange(None, 'line', 0, -1000)
data = history.load_pair_history(pair=pair, ticker_interval='1m', data = history.load_pair_history(pair=pair, timeframe='1m',
datadir=testdatadir, timerange=timerange) datadir=testdatadir, timerange=timerange)
# Generate buy/sell signals and indicators # Generate buy/sell signals and indicators
@ -228,7 +228,7 @@ def test_add_profit(testdatadir):
bt_data = load_backtest_data(filename) bt_data = load_backtest_data(filename)
timerange = TimeRange.parse_timerange("20180110-20180112") timerange = TimeRange.parse_timerange("20180110-20180112")
df = history.load_pair_history(pair="TRX/BTC", ticker_interval='5m', df = history.load_pair_history(pair="TRX/BTC", timeframe='5m',
datadir=testdatadir, timerange=timerange) datadir=testdatadir, timerange=timerange)
fig = generate_empty_figure() fig = generate_empty_figure()
@ -251,7 +251,7 @@ def test_generate_profit_graph(testdatadir):
tickers = history.load_data(datadir=testdatadir, tickers = history.load_data(datadir=testdatadir,
pairs=pairs, pairs=pairs,
ticker_interval='5m', timeframe='5m',
timerange=timerange timerange=timerange
) )
trades = trades[trades['pair'].isin(pairs)] trades = trades[trades['pair'].isin(pairs)]

View File

@ -26,7 +26,7 @@
"# Customize these according to your needs.\n", "# Customize these according to your needs.\n",
"\n", "\n",
"# Define some constants\n", "# Define some constants\n",
"ticker_interval = \"5m\"\n", "timeframe = \"5m\"\n",
"# Name of the strategy class\n", "# Name of the strategy class\n",
"strategy_name = 'SampleStrategy'\n", "strategy_name = 'SampleStrategy'\n",
"# Path to user data\n", "# Path to user data\n",
@ -49,7 +49,7 @@
"from freqtrade.data.history import load_pair_history\n", "from freqtrade.data.history import load_pair_history\n",
"\n", "\n",
"candles = load_pair_history(datadir=data_location,\n", "candles = load_pair_history(datadir=data_location,\n",
" ticker_interval=ticker_interval,\n", " timeframe=timeframe,\n",
" pair=pair)\n", " pair=pair)\n",
"\n", "\n",
"# Confirm success\n", "# Confirm success\n",