Merge pull request #1454 from freqtrade/feat/interpolate_missing
interpolate missing candles
This commit is contained in:
@@ -5,13 +5,19 @@ import logging
|
||||
import pandas as pd
|
||||
from pandas import DataFrame, to_datetime
|
||||
|
||||
from freqtrade.constants import TICKER_INTERVAL_MINUTES
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def parse_ticker_dataframe(ticker: list) -> DataFrame:
|
||||
def parse_ticker_dataframe(ticker: list, ticker_interval: str,
|
||||
fill_missing: 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 fill_missing: fill up missing candles with 0 candles
|
||||
(see ohlcv_fill_up_missing_data for details)
|
||||
:return: DataFrame
|
||||
"""
|
||||
logger.debug("Parsing tickerlist to dataframe")
|
||||
@@ -33,7 +39,41 @@ def parse_ticker_dataframe(ticker: list) -> DataFrame:
|
||||
})
|
||||
frame.drop(frame.tail(1).index, inplace=True) # eliminate partial candle
|
||||
logger.debug('Dropping last candle')
|
||||
return frame
|
||||
|
||||
if fill_missing:
|
||||
return ohlcv_fill_up_missing_data(frame, ticker_interval)
|
||||
else:
|
||||
return frame
|
||||
|
||||
|
||||
def ohlcv_fill_up_missing_data(dataframe: DataFrame, ticker_interval: 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
|
||||
|
||||
"""
|
||||
ohlc_dict = {
|
||||
'open': 'first',
|
||||
'high': 'max',
|
||||
'low': 'min',
|
||||
'close': 'last',
|
||||
'volume': 'sum'
|
||||
}
|
||||
tick_mins = TICKER_INTERVAL_MINUTES[ticker_interval]
|
||||
# Resample to create "NAN" values
|
||||
df = dataframe.resample(f'{tick_mins}min', on='date').agg(ohlc_dict)
|
||||
|
||||
# Forwardfill close for missing columns
|
||||
df['close'] = df['close'].fillna(method='ffill')
|
||||
# Use close for "open, high, low"
|
||||
df.loc[:, ['open', 'high', 'low']] = df[['open', 'high', 'low']].fillna(
|
||||
value={'open': df['close'],
|
||||
'high': df['close'],
|
||||
'low': df['close'],
|
||||
})
|
||||
df.reset_index(inplace=True)
|
||||
logger.debug(f"Missing data fillup: before: {len(dataframe)} - after: {len(df)}")
|
||||
return df
|
||||
|
||||
|
||||
def order_book_to_dataframe(bids: list, asks: list) -> DataFrame:
|
||||
|
@@ -82,6 +82,7 @@ def load_pair_history(pair: str,
|
||||
timerange: TimeRange = TimeRange(None, None, 0, 0),
|
||||
refresh_pairs: bool = False,
|
||||
exchange: Optional[Exchange] = None,
|
||||
fill_up_missing: bool = True
|
||||
) -> DataFrame:
|
||||
"""
|
||||
Loads cached ticker history for the given pair.
|
||||
@@ -111,7 +112,7 @@ def load_pair_history(pair: str,
|
||||
logger.warning('Missing data at end for pair %s, data ends at %s',
|
||||
pair,
|
||||
arrow.get(pairdata[-1][0] // 1000).strftime('%Y-%m-%d %H:%M:%S'))
|
||||
return parse_ticker_dataframe(pairdata)
|
||||
return parse_ticker_dataframe(pairdata, ticker_interval, fill_up_missing)
|
||||
else:
|
||||
logger.warning('No data for pair: "%s", Interval: %s. '
|
||||
'Use --refresh-pairs-cached to download the data',
|
||||
@@ -124,7 +125,8 @@ def load_data(datadir: Optional[Path],
|
||||
pairs: List[str],
|
||||
refresh_pairs: bool = False,
|
||||
exchange: Optional[Exchange] = None,
|
||||
timerange: TimeRange = TimeRange(None, None, 0, 0)) -> Dict[str, DataFrame]:
|
||||
timerange: TimeRange = TimeRange(None, None, 0, 0),
|
||||
fill_up_missing: bool = True) -> Dict[str, DataFrame]:
|
||||
"""
|
||||
Loads ticker history data for a list of pairs the given parameters
|
||||
:return: dict(<pair>:<tickerlist>)
|
||||
@@ -135,7 +137,8 @@ def load_data(datadir: Optional[Path],
|
||||
hist = load_pair_history(pair=pair, ticker_interval=ticker_interval,
|
||||
datadir=datadir, timerange=timerange,
|
||||
refresh_pairs=refresh_pairs,
|
||||
exchange=exchange)
|
||||
exchange=exchange,
|
||||
fill_up_missing=fill_up_missing)
|
||||
if hist is not None:
|
||||
result[pair] = hist
|
||||
return result
|
||||
|
Reference in New Issue
Block a user