*breaking change* simplify user strat by consolidating feature loops into backend

This commit is contained in:
robcaulk 2022-07-21 12:24:22 +02:00
parent e7337728bf
commit 8f86b0deaa
5 changed files with 42 additions and 72 deletions

View File

@ -368,32 +368,15 @@ The Freqai strategy requires the user to include the following lines of code in
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame: def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
self.freqai_info = self.config["freqai"] self.freqai_info = self.config["freqai"]
self.pair = metadata["pair"]
sgi = True
# the following loops are necessary for building the features
# indicated by the user in the configuration file.
# All indicators must be populated by populate_any_indicators() for live functionality # All indicators must be populated by populate_any_indicators() for live functionality
# to work correctly. # to work correctly.
for tf in self.freqai_info["feature_parameters"]["include_timeframes"]:
dataframe = self.populate_any_indicators(
metadata,
self.pair,
dataframe.copy(),
tf,
coin=self.pair.split("/")[0] + "-",
set_generalized_indicators=sgi,
)
sgi = False
for pair in self.freqai_info["feature_parameters"]["include_corr_pairlist"]:
if metadata["pair"] in pair:
continue # do not include whitelisted pair twice if it is in corr_pairlist
dataframe = self.populate_any_indicators(
metadata, pair, dataframe.copy(), tf, coin=pair.split("/")[0] + "-"
)
# the model will return 4 values, its prediction, an indication of whether or not the # the model will return all labels created by user in `populate_any_indicators`
# prediction should be accepted, the target mean/std values from the labels used during # (& appended targets), an indication of whether or not the prediction should be accepted,
# each training period. # the target mean/std values for each of the labels created by user in
# `populate_any_indicators()` for each training period.
dataframe = self.model.bridge.start(dataframe, metadata, self) dataframe = self.model.bridge.start(dataframe, metadata, self)
return dataframe return dataframe

View File

@ -1043,7 +1043,12 @@ class FreqaiDataKitchen:
# return corr_dataframes, base_dataframes # return corr_dataframes, base_dataframes
def use_strategy_to_populate_indicators( def use_strategy_to_populate_indicators(
self, strategy: IStrategy, corr_dataframes: dict, base_dataframes: dict, pair: str self,
strategy: IStrategy,
corr_dataframes: dict = {},
base_dataframes: dict = {},
pair: str = "",
prediction_dataframe: DataFrame = pd.DataFrame(),
) -> DataFrame: ) -> DataFrame:
""" """
Use the user defined strategy for populating indicators during Use the user defined strategy for populating indicators during
@ -1058,16 +1063,31 @@ class FreqaiDataKitchen:
:returns: :returns:
dataframe: DataFrame = dataframe containing populated indicators dataframe: DataFrame = dataframe containing populated indicators
""" """
dataframe = base_dataframes[self.config["timeframe"]].copy()
# for prediction dataframe creation, we let dataprovider handle everything in the strategy
# so we create empty dictionaries, which allows us to pass None to
# `populate_any_indicators()`. Signaling we want the dp to give us the live dataframe.
tfs = self.freqai_config.get("feature_parameters", {}).get("include_timeframes")
pairs = self.freqai_config.get("feature_parameters", {}).get("include_corr_pairlist", []) pairs = self.freqai_config.get("feature_parameters", {}).get("include_corr_pairlist", [])
if not prediction_dataframe.empty:
dataframe = prediction_dataframe.copy()
for tf in tfs:
base_dataframes[tf] = None
for p in pairs:
if p not in corr_dataframes:
corr_dataframes[p] = {}
corr_dataframes[p][tf] = None
else:
dataframe = base_dataframes[self.config["timeframe"]].copy()
sgi = True sgi = True
for tf in self.freqai_config.get("feature_parameters", {}).get("include_timeframes"): for tf in tfs:
dataframe = strategy.populate_any_indicators( dataframe = strategy.populate_any_indicators(
pair, pair,
pair, pair,
dataframe.copy(), dataframe.copy(),
tf, tf,
base_dataframes[tf], informative=base_dataframes[tf],
coin=pair.split("/")[0] + "-", coin=pair.split("/")[0] + "-",
set_generalized_indicators=sgi, set_generalized_indicators=sgi,
) )
@ -1081,7 +1101,7 @@ class FreqaiDataKitchen:
i, i,
dataframe.copy(), dataframe.copy(),
tf, tf,
corr_dataframes[i][tf], informative=corr_dataframes[i][tf],
coin=i.split("/")[0] + "-", coin=i.split("/")[0] + "-",
) )

View File

@ -281,6 +281,10 @@ class IFreqaiModel(ABC):
# load the model and associated data into the data kitchen # load the model and associated data into the data kitchen
self.model = dk.load_data(coin=metadata["pair"]) self.model = dk.load_data(coin=metadata["pair"])
dataframe = self.dk.use_strategy_to_populate_indicators(
strategy, prediction_dataframe=dataframe, pair=metadata["pair"]
)
if not self.model: if not self.model:
logger.warning( logger.warning(
f"No model ready for {metadata['pair']}, returning null values to strategy." f"No model ready for {metadata['pair']}, returning null values to strategy."

View File

@ -171,32 +171,15 @@ class FreqaiExampleStrategy(IStrategy):
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame: def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
self.freqai_info = self.config["freqai"] self.freqai_info = self.config["freqai"]
self.pair = metadata["pair"]
sgi = True
# the following loops are necessary for building the features
# indicated by the user in the configuration file.
# All indicators must be populated by populate_any_indicators() for live functionality # All indicators must be populated by populate_any_indicators() for live functionality
# to work correctly. # to work correctly.
for tf in self.freqai_info["feature_parameters"]["include_timeframes"]:
dataframe = self.populate_any_indicators(
metadata,
self.pair,
dataframe.copy(),
tf,
coin=self.pair.split("/")[0] + "-",
set_generalized_indicators=sgi,
)
sgi = False
for pair in self.freqai_info["feature_parameters"]["include_corr_pairlist"]:
if metadata["pair"] in pair:
continue # do not include whitelisted pair twice if it is in corr_pairlist
dataframe = self.populate_any_indicators(
metadata, pair, dataframe.copy(), tf, coin=pair.split("/")[0] + "-"
)
# the model will return 4 values, its prediction, an indication of whether or not the # the model will return all labels created by user in `populate_any_indicators`
# prediction should be accepted, the target mean/std values from the labels used during # (& appended targets), an indication of whether or not the prediction should be accepted,
# each training period. # the target mean/std values for each of the labels created by user in
# `populate_any_indicators()` for each training period.
dataframe = self.model.bridge.start(dataframe, metadata, self) dataframe = self.model.bridge.start(dataframe, metadata, self)
dataframe["target_roi"] = dataframe["&-s_close_mean"] + dataframe["&-s_close_std"] * 1.25 dataframe["target_roi"] = dataframe["&-s_close_mean"] + dataframe["&-s_close_std"] * 1.25

View File

@ -140,29 +140,9 @@ class freqai_test_strat(IStrategy):
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame: def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
self.freqai_info = self.config["freqai"] self.freqai_info = self.config["freqai"]
self.pair = metadata["pair"]
sgi = True
# the following loops are necessary for building the features
# indicated by the user in the configuration file.
# All indicators must be populated by populate_any_indicators() for live functionality # All indicators must be populated by populate_any_indicators() for live functionality
# to work correctly. # to work correctly.
for tf in self.freqai_info["feature_parameters"]["include_timeframes"]:
dataframe = self.populate_any_indicators(
metadata,
self.pair,
dataframe.copy(),
tf,
coin=self.pair.split("/")[0] + "-",
set_generalized_indicators=sgi,
)
sgi = False
for pair in self.freqai_info["feature_parameters"]["include_corr_pairlist"]:
if metadata["pair"] in pair:
continue # do not include whitelisted pair twice if it is in corr_pairlist
dataframe = self.populate_any_indicators(
metadata, pair, dataframe.copy(), tf, coin=pair.split("/")[0] + "-"
)
# the model will return 4 values, its prediction, an indication of whether or not the # the model will return 4 values, its prediction, an indication of whether or not the
# prediction should be accepted, the target mean/std values from the labels used during # prediction should be accepted, the target mean/std values from the labels used during
# each training period. # each training period.