Improve merge_informative_pairs to properly merge correct timeframes

explanation in #4073, closes #4073
This commit is contained in:
Matthias 2021-01-04 13:47:16 +01:00
parent d1804dee6b
commit 07bc0c3fce
2 changed files with 23 additions and 5 deletions

View File

@ -24,15 +24,24 @@ def merge_informative_pair(dataframe: pd.DataFrame, informative: pd.DataFrame,
:param timeframe: Timeframe of the original pair sample. :param timeframe: Timeframe of the original pair sample.
:param timeframe_inf: Timeframe of the informative pair sample. :param timeframe_inf: Timeframe of the informative pair sample.
:param ffill: Forwardfill missing values - optional but usually required :param ffill: Forwardfill missing values - optional but usually required
:return: Merged dataframe
:raise: ValueError if the secondary timeframe is shorter than the dataframe timeframe
""" """
minutes_inf = timeframe_to_minutes(timeframe_inf) minutes_inf = timeframe_to_minutes(timeframe_inf)
minutes = timeframe_to_minutes(timeframe) minutes = timeframe_to_minutes(timeframe)
if minutes >= minutes_inf: if minutes == minutes_inf:
# No need to forwardshift if the timeframes are identical # No need to forwardshift if the timeframes are identical
informative['date_merge'] = informative["date"] informative['date_merge'] = informative["date"]
elif minutes < minutes_inf:
# Subtract "small" timeframe so merging is not delayed by 1 small candle
# Detailed explanation in https://github.com/freqtrade/freqtrade/issues/4073
informative['date_merge'] = (
informative["date"] + pd.to_timedelta(minutes_inf, 'm') - pd.to_timedelta(minutes, 'm')
)
else: else:
informative['date_merge'] = informative["date"] + pd.to_timedelta(minutes_inf, 'm') raise ValueError("Tried to merge a faster timeframe to a slower timeframe."
"This would create new rows, and can throw off your regular indicators.")
# Rename columns to be unique # Rename columns to be unique
informative.columns = [f"{col}_{timeframe_inf}" for col in informative.columns] informative.columns = [f"{col}_{timeframe_inf}" for col in informative.columns]

View File

@ -1,5 +1,6 @@
import numpy as np import numpy as np
import pandas as pd import pandas as pd
import pytest
from freqtrade.strategy import merge_informative_pair, timeframe_to_minutes from freqtrade.strategy import merge_informative_pair, timeframe_to_minutes
@ -47,17 +48,17 @@ def test_merge_informative_pair():
assert 'volume_1h' in result.columns assert 'volume_1h' in result.columns
assert result['volume'].equals(data['volume']) assert result['volume'].equals(data['volume'])
# First 4 rows are empty # First 3 rows are empty
assert result.iloc[0]['date_1h'] is pd.NaT assert result.iloc[0]['date_1h'] is pd.NaT
assert result.iloc[1]['date_1h'] is pd.NaT assert result.iloc[1]['date_1h'] is pd.NaT
assert result.iloc[2]['date_1h'] is pd.NaT assert result.iloc[2]['date_1h'] is pd.NaT
assert result.iloc[3]['date_1h'] is pd.NaT
# Next 4 rows contain the starting date (0:00) # Next 4 rows contain the starting date (0:00)
assert result.iloc[3]['date_1h'] == result.iloc[0]['date']
assert result.iloc[4]['date_1h'] == result.iloc[0]['date'] assert result.iloc[4]['date_1h'] == result.iloc[0]['date']
assert result.iloc[5]['date_1h'] == result.iloc[0]['date'] assert result.iloc[5]['date_1h'] == result.iloc[0]['date']
assert result.iloc[6]['date_1h'] == result.iloc[0]['date'] assert result.iloc[6]['date_1h'] == result.iloc[0]['date']
assert result.iloc[7]['date_1h'] == result.iloc[0]['date']
# Next 4 rows contain the next Hourly date original date row 4 # Next 4 rows contain the next Hourly date original date row 4
assert result.iloc[7]['date_1h'] == result.iloc[4]['date']
assert result.iloc[8]['date_1h'] == result.iloc[4]['date'] assert result.iloc[8]['date_1h'] == result.iloc[4]['date']
@ -86,3 +87,11 @@ def test_merge_informative_pair_same():
# Dates match 1:1 # Dates match 1:1
assert result['date_15m'].equals(result['date']) assert result['date_15m'].equals(result['date'])
def test_merge_informative_pair_lower():
data = generate_test_data('1h', 40)
informative = generate_test_data('15m', 40)
with pytest.raises(ValueError, match=r"Tried to merge a faster timeframe .*"):
merge_informative_pair(data, informative, '1h', '15m', ffill=True)