Correctly handle identical timerame merges
This commit is contained in:
parent
7bc8927914
commit
cc684c5141
@ -518,10 +518,10 @@ class SampleStrategy(IStrategy):
|
||||
|
||||
# Use the helper function merge_informative_pair to safely merge the pair
|
||||
# Automatically renames the columns and merges a shorter timeframe dataframe and a longer timeframe informative pair
|
||||
# FFill to have the 1d value available in every row throughout the day.
|
||||
# Without this, comparisons would only work once per day.
|
||||
# use ffill to have the 1d value available in every row throughout the day.
|
||||
# Without this, comparisons between columns of the original and the informative pair would only work once per day.
|
||||
# Full documentation of this method, see below
|
||||
dataframe = merge_informative_pair(dataframe, informative_pairs, inf_tf, ffill=True)
|
||||
dataframe = merge_informative_pair(dataframe, informative_pairs, self.timeframe, inf_tf, ffill=True)
|
||||
|
||||
# Calculate rsi of the original dataframe (5m timeframe)
|
||||
dataframe['rsi'] = ta.RSI(dataframe, timeperiod=14)
|
||||
@ -589,6 +589,7 @@ All columns of the informative dataframe will be available on the returning data
|
||||
# This is necessary since the data is always the "open date"
|
||||
# and a 15m candle starting at 12:15 should not know the close of the 1h candle from 12:00 to 13:00
|
||||
minutes = timeframe_to_minutes(inf_tf)
|
||||
# Only do this if the timeframes are different:
|
||||
informative['date_merge'] = informative["date"] + pd.to_timedelta(minutes, 'm')
|
||||
|
||||
# Combine the 2 dataframes
|
||||
|
@ -3,7 +3,7 @@ from freqtrade.exchange import timeframe_to_minutes
|
||||
|
||||
|
||||
def merge_informative_pair(dataframe: pd.DataFrame, informative: pd.DataFrame,
|
||||
timeframe_inf: str, ffill: bool = True) -> pd.DataFrame:
|
||||
timeframe: str, timeframe_inf: str, ffill: bool = True) -> pd.DataFrame:
|
||||
"""
|
||||
Correctly merge informative samples to the original dataframe, avoiding lookahead bias.
|
||||
|
||||
@ -20,13 +20,18 @@ def merge_informative_pair(dataframe: pd.DataFrame, informative: pd.DataFrame,
|
||||
|
||||
:param dataframe: Original dataframe
|
||||
:param informative: Informative pair, most likely loaded via dp.get_pair_dataframe
|
||||
:param timeframe: Timeframe of the original pair sample.
|
||||
:param timeframe_inf: Timeframe of the informative pair sample.
|
||||
:param ffill: Forwardfill missing values - optional but usually required
|
||||
"""
|
||||
# Rename columns to be unique
|
||||
|
||||
minutes = timeframe_to_minutes(timeframe_inf)
|
||||
informative['date_merge'] = informative["date"] + pd.to_timedelta(minutes, 'm')
|
||||
minutes_inf = timeframe_to_minutes(timeframe_inf)
|
||||
if timeframe == timeframe_inf:
|
||||
# No need to forwardshift if the timeframes are identical
|
||||
informative['date_merge'] = informative["date"]
|
||||
else:
|
||||
informative['date_merge'] = informative["date"] + pd.to_timedelta(minutes_inf, 'm')
|
||||
|
||||
informative.columns = [f"{col}_{timeframe_inf}" for col in informative.columns]
|
||||
|
||||
|
@ -28,7 +28,7 @@ def test_merge_informative_pair():
|
||||
data = generate_test_data('15m', 40)
|
||||
informative = generate_test_data('1h', 40)
|
||||
|
||||
result = merge_informative_pair(data, informative, '1h', ffill=True)
|
||||
result = merge_informative_pair(data, informative, '15m', '1h', ffill=True)
|
||||
assert isinstance(result, pd.DataFrame)
|
||||
assert len(result) == len(data)
|
||||
assert 'date' in result.columns
|
||||
@ -59,3 +59,30 @@ def test_merge_informative_pair():
|
||||
assert result.iloc[7]['date_1h'] == result.iloc[0]['date']
|
||||
# Next 4 rows contain the next Hourly date original date row 4
|
||||
assert result.iloc[8]['date_1h'] == result.iloc[4]['date']
|
||||
|
||||
|
||||
def test_merge_informative_pair_same():
|
||||
data = generate_test_data('15m', 40)
|
||||
informative = generate_test_data('15m', 40)
|
||||
|
||||
result = merge_informative_pair(data, informative, '15m', '15m', ffill=True)
|
||||
assert isinstance(result, pd.DataFrame)
|
||||
assert len(result) == len(data)
|
||||
assert 'date' in result.columns
|
||||
assert result['date'].equals(data['date'])
|
||||
assert 'date_15m' in result.columns
|
||||
|
||||
assert 'open' in result.columns
|
||||
assert 'open_15m' in result.columns
|
||||
assert result['open'].equals(data['open'])
|
||||
|
||||
assert 'close' in result.columns
|
||||
assert 'close_15m' in result.columns
|
||||
assert result['close'].equals(data['close'])
|
||||
|
||||
assert 'volume' in result.columns
|
||||
assert 'volume_15m' in result.columns
|
||||
assert result['volume'].equals(data['volume'])
|
||||
|
||||
# Dates match 1:1
|
||||
assert result['date_15m'].equals(result['date'])
|
||||
|
Loading…
Reference in New Issue
Block a user