Skip to content

Commit

Permalink
Merge pull request #2522 from freqtrade/replace_tickerinterval
Browse files Browse the repository at this point in the history
Replace tickerinterval
  • Loading branch information
hroff-1902 committed Nov 13, 2019
2 parents 1d7fb2f + 6ac73f7 commit baea06e
Show file tree
Hide file tree
Showing 24 changed files with 198 additions and 197 deletions.
8 changes: 4 additions & 4 deletions docs/strategy-customization.md
Original file line number Diff line number Diff line change
Expand Up @@ -314,9 +314,9 @@ Please always check the mode of operation to select the correct method to get da
#### Possible options for DataProvider

- `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.
- `historic_ohlcv(pair, ticker_interval)` - 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).
- `ohlcv(pair, timeframe)` - Currently cached ticker data for the pair, returns DataFrame or empty DataFrame.
- `historic_ohlcv(pair, timeframe)` - Returns historical data stored on disk.
- `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.
- `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.
Expand All @@ -327,7 +327,7 @@ Please always check the mode of operation to select the correct method to get da
if self.dp:
inf_pair, inf_timeframe = self.informative_pairs()[0]
informative = self.dp.get_pair_dataframe(pair=inf_pair,
ticker_interval=inf_timeframe)
timeframe=inf_timeframe)
```

!!! Warning "Warning about backtesting"
Expand Down
4 changes: 2 additions & 2 deletions docs/strategy_analysis_example.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ from pathlib import Path
# Customize these according to your needs.

# Define some constants
ticker_interval = "5m"
timeframe = "5m"
# Name of the strategy class
strategy_name = 'SampleStrategy'
# Path to user data
Expand All @@ -29,7 +29,7 @@ pair = "BTC_USDT"
from freqtrade.data.history import load_pair_history

candles = load_pair_history(datadir=data_location,
ticker_interval=ticker_interval,
timeframe=timeframe,
pair=pair)

# Confirm success
Expand Down
6 changes: 3 additions & 3 deletions freqtrade/configuration/timerange.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,12 +39,12 @@ def subtract_start(self, seconds) -> None:
if self.startts:
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:
"""
Adjust startts by <startup_candles> candles.
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 min_date: Minimum data date loaded. Key kriterium to decide if start-time
has to be moved
Expand All @@ -55,7 +55,7 @@ def adjust_start_if_necessary(self, ticker_interval_secs: int, startup_candles:
# 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.",
startup_candles)
self.startts = (min_date.timestamp + ticker_interval_secs * startup_candles)
self.startts = (min_date.timestamp + timeframe_secs * startup_candles)
self.starttype = 'date'

@staticmethod
Expand Down
4 changes: 2 additions & 2 deletions freqtrade/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
DRY_RUN_WALLET = 999.9
MATH_CLOSE_PREC = 1e-14 # Precision used for float comparisons

TICKER_INTERVALS = [
TIMEFRAMES = [
'1m', '3m', '5m', '15m', '30m',
'1h', '2h', '4h', '6h', '8h', '12h',
'1d', '3d', '1w',
Expand Down Expand Up @@ -57,7 +57,7 @@
'type': 'object',
'properties': {
'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_amount': {
"type": ["number", "string"],
Expand Down
6 changes: 3 additions & 3 deletions freqtrade/data/btanalysis.py
Original file line number Diff line number Diff line change
Expand Up @@ -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.
"""
from freqtrade.exchange import timeframe_to_minutes
ticker_minutes = timeframe_to_minutes(timeframe)
# Resample to ticker_interval to make sure trades match candles
_trades_sum = trades.resample(f'{ticker_minutes}min', on='close_time')[['profitperc']].sum()
timeframe_minutes = timeframe_to_minutes(timeframe)
# Resample to timeframe to make sure trades match candles
_trades_sum = trades.resample(f'{timeframe_minutes}min', on='close_time')[['profitperc']].sum()
df.loc[:, col_name] = _trades_sum.cumsum()
# Set first value to 0
df.loc[df.iloc[0].name, col_name] = 0
Expand Down
10 changes: 5 additions & 5 deletions freqtrade/data/converter.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,13 @@
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,
drop_incomplete: bool = True) -> 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_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 fill_missing: fill up missing candles with 0 candles
(see ohlcv_fill_up_missing_data for details)
Expand Down Expand Up @@ -52,12 +52,12 @@ def parse_ticker_dataframe(ticker: list, ticker_interval: str, pair: str, *,
logger.debug('Dropping last candle')

if fill_missing:
return ohlcv_fill_up_missing_data(frame, ticker_interval, pair)
return ohlcv_fill_up_missing_data(frame, timeframe, pair)
else:
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,
using the previous close as price for "open", "high" "low" and "close", volume is set to 0
Expand All @@ -72,7 +72,7 @@ def ohlcv_fill_up_missing_data(dataframe: DataFrame, ticker_interval: str, pair:
'close': 'last',
'volume': 'sum'
}
ticker_minutes = timeframe_to_minutes(ticker_interval)
ticker_minutes = timeframe_to_minutes(timeframe)
# Resample to create "NAN" values
df = dataframe.resample(f'{ticker_minutes}min', on='date').agg(ohlc_dict)

Expand Down
25 changes: 13 additions & 12 deletions freqtrade/data/dataprovider.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,52 +37,53 @@ def refresh(self,
@property
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.
"""
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
Please use the `available_pairs` method to verify which pairs are currently cached.
: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.
Use False only for read-only operations (where the dataframe is not modified)
"""
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)
else:
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
: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,
ticker_interval=ticker_interval or self._config['ticker_interval'],
timeframe=timeframe or self._config['ticker_interval'],
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
on the runmode.
: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):
# Get live ohlcv data.
data = self.ohlcv(pair=pair, ticker_interval=ticker_interval)
data = self.ohlcv(pair=pair, timeframe=timeframe)
else:
# 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:
logger.warning(f"No data found for ({pair}, {ticker_interval}).")
logger.warning(f"No data found for ({pair}, {timeframe}).")
return data

def market(self, pair: str) -> Optional[Dict[str, Any]]:
Expand Down

0 comments on commit baea06e

Please sign in to comment.