refactoring freqai backtesting - remove duplicate code

This commit is contained in:
Wagner Costa Santos 2022-09-01 07:09:23 -03:00
parent 44d3a9140d
commit d6e115178a
2 changed files with 24 additions and 70 deletions

View File

@ -69,6 +69,8 @@ class FreqaiDataKitchen:
self.label_list: List = [] self.label_list: List = []
self.training_features_list: List = [] self.training_features_list: List = []
self.model_filename: str = "" self.model_filename: str = ""
self.backtesting_results_path = Path()
self.backtesting_prediction_folder: str = "backtesting_predictions"
self.live = live self.live = live
self.pair = pair self.pair = pair
@ -808,8 +810,6 @@ class FreqaiDataKitchen:
else: else:
self.full_df = pd.concat([self.full_df, append_df], axis=0) self.full_df = pd.concat([self.full_df, append_df], axis=0)
return append_df
def fill_predictions(self, dataframe): def fill_predictions(self, dataframe):
""" """
Back fill values to before the backtesting range so that the dataframe matches size Back fill values to before the backtesting range so that the dataframe matches size
@ -1070,33 +1070,25 @@ class FreqaiDataKitchen:
self.unique_class_list += list(self.unique_classes[label]) self.unique_class_list += list(self.unique_classes[label])
def save_backtesting_prediction( def save_backtesting_prediction(
self, file_name: str, root_folder: str, append_df: DataFrame self, append_df: DataFrame
) -> None: ) -> None:
""" """
Save prediction dataframe from backtesting to h5 file format Save prediction dataframe from backtesting to h5 file format
:param file_name: h5 file name :param append_df: dataframe for backtesting period
:param root_folder: folder to save h5 file
""" """
backtesting_root = Path( full_predictions_folder = Path(self.full_path / self.backtesting_prediction_folder)
self.full_path if not full_predictions_folder.is_dir():
/ root_folder full_predictions_folder.mkdir(parents=True, exist_ok=True)
)
if not backtesting_root.is_dir():
backtesting_root.mkdir(parents=True, exist_ok=True)
full_file_path = Path(self.full_path / root_folder / file_name) append_df.to_hdf(self.backtesting_results_path, key='append_df', mode='w')
append_df.to_hdf(full_file_path, key='append_df', mode='w')
def get_backtesting_prediction( def get_backtesting_prediction(
self, root_prediction: str, prediction_file_name: str self
) -> DataFrame: ) -> DataFrame:
""" """
Retrive from disk the prediction dataframe Get prediction dataframe from h5 file format
:param prediction_file_name: prediction file full path
:return:
:Dataframe: Backtesting prediction from current backtesting period
""" """
prediction_path = Path(self.full_path / root_prediction / prediction_file_name) append_df = pd.read_hdf(self.backtesting_results_path)
append_df = pd.read_hdf(prediction_path)
return append_df return append_df

View File

@ -231,15 +231,11 @@ class IFreqaiModel(ABC):
f"sub-train-{metadata['pair'].split('/')[0]}_{trained_timestamp_int}" f"sub-train-{metadata['pair'].split('/')[0]}_{trained_timestamp_int}"
) )
if self.backtest_prediction_exists( coin, _ = metadata["pair"].split("/")
metadata["pair"], dk, trained_timestamp=trained_timestamp_int dk.model_filename = f"cb_{coin.lower()}_{trained_timestamp_int}"
):
prediction_filename, root_prediction = self.get_backtesting_prediction_file_name(
metadata["pair"],
dk,
trained_timestamp=int(trained_timestamp.stopts))
append_df = dk.get_backtesting_prediction(root_prediction, prediction_filename) if self.backtest_prediction_exists(dk):
append_df = dk.get_backtesting_prediction()
dk.append_predictions(append_df) dk.append_predictions(append_df)
else: else:
if not self.model_exists( if not self.model_exists(
@ -259,15 +255,7 @@ class IFreqaiModel(ABC):
pred_df, do_preds = self.predict(dataframe_backtest, dk) pred_df, do_preds = self.predict(dataframe_backtest, dk)
append_df = dk.get_predictions_to_append(pred_df, do_preds) append_df = dk.get_predictions_to_append(pred_df, do_preds)
dk.append_predictions(append_df) dk.append_predictions(append_df)
dk.save_backtesting_prediction(append_df)
prediction_file_name, root_prediction = self.get_backtesting_prediction_file_name(
metadata["pair"],
dk,
trained_timestamp_int)
dk.save_backtesting_prediction(prediction_file_name,
root_prediction,
append_df)
dk.fill_predictions(dataframe) dk.fill_predictions(dataframe)
@ -478,11 +466,6 @@ class IFreqaiModel(ABC):
:return: :return:
:boolean: whether the model file exists or not. :boolean: whether the model file exists or not.
""" """
coin, _ = pair.split("/")
if not self.live:
dk.model_filename = model_filename = f"cb_{coin.lower()}_{trained_timestamp}"
path_to_modelfile = Path(dk.data_path / f"{model_filename}_model.joblib") path_to_modelfile = Path(dk.data_path / f"{model_filename}_model.joblib")
file_exists = path_to_modelfile.is_file() file_exists = path_to_modelfile.is_file()
if file_exists and not scanning: if file_exists and not scanning:
@ -661,23 +644,21 @@ class IFreqaiModel(ABC):
def backtest_prediction_exists( def backtest_prediction_exists(
self, self,
pair: str,
dk: FreqaiDataKitchen, dk: FreqaiDataKitchen,
trained_timestamp: int,
scanning: bool = False, scanning: bool = False,
) -> bool: ) -> bool:
""" """
Given a pair and path, check if a backtesting prediction already exists Check if a backtesting prediction already exists
:param pair: pair e.g. BTC/USD :param dk: FreqaiDataKitchen
:param path: path to prediction
:return: :return:
:boolean: whether the prediction file exists or not. :boolean: whether the prediction file exists or not.
""" """
if not self.live: if not self.live:
prediction_file_name, root_prediction = self.get_backtesting_prediction_file_name( prediction_file_name = dk.model_filename
pair, dk, trained_timestamp path_to_predictionfile = Path(dk.full_path /
) dk.backtesting_prediction_folder /
path_to_predictionfile = Path(dk.full_path / root_prediction / prediction_file_name) f"{prediction_file_name}_prediction.h5")
dk.backtesting_results_path = path_to_predictionfile
file_exists = path_to_predictionfile.is_file() file_exists = path_to_predictionfile.is_file()
if file_exists and not scanning: if file_exists and not scanning:
@ -690,25 +671,6 @@ class IFreqaiModel(ABC):
else: else:
return False return False
def get_backtesting_prediction_file_name(
self, pair: str, dk: FreqaiDataKitchen, trained_timestamp: int
):
"""
Given a pair, path and a trained timestamp,
returns the path and name of the predictions file
:param pair: pair e.g. BTC/USD
:param dk: FreqaiDataKitchen
:trained_timestamp: current backtesting timestamp period
:return:
:str: prediction file name
:str: prediction root path
"""
coin, _ = pair.split("/")
prediction_base_filename = f"{coin.lower()}_{trained_timestamp}"
root_prediction = 'backtesting_predictions'
prediction_file_name = f"{prediction_base_filename}_predictions.h5"
return prediction_file_name, root_prediction
# Following methods which are overridden by user made prediction models. # Following methods which are overridden by user made prediction models.
# See freqai/prediction_models/CatboostPredictionModel.py for an example. # See freqai/prediction_models/CatboostPredictionModel.py for an example.