diff --git a/config/hashing.py b/config/hashing.py index 1e8b7f2..f62ea6d 100644 --- a/config/hashing.py +++ b/config/hashing.py @@ -20,6 +20,7 @@ def hash_data_config(data_config: dict) -> str: data_config["target_asset"].path + data_config["target_asset"].file_name, data_config["load_non_target_asset"], + data_config["start_date"], hash_feature_extractors(data_config["own_features"]), hash_feature_extractors(data_config["other_features"]), hash_feature_extractors(data_config["exogenous_features"]), diff --git a/config/presets.py b/config/presets.py index 421b21d..f54cc40 100644 --- a/config/presets.py +++ b/config/presets.py @@ -14,6 +14,7 @@ def get_default_config() -> RawConfig: meta_models = ["LogisticRegression_two_class", "LGBM"] return RawConfig( + start_date=None, dimensionality_reduction_ratio=0.5, n_features_to_select=50, initial_window_size=3800, diff --git a/config/types.py b/config/types.py index e52d7e3..daabe3c 100644 --- a/config/types.py +++ b/config/types.py @@ -11,6 +11,7 @@ from transformations.base import Transformation # RawConfig is needed to ensure we can declare config presets here with static typing, we then convert it to Config class RawConfig(BaseModel): + start_date: Optional[str] dimensionality_reduction_ratio: float n_features_to_select: int initial_window_size: int @@ -40,9 +41,9 @@ class RawConfig(BaseModel): @dataclass class Config: + start_date: Optional[str] initial_window_size: int retrain_every: int - assets: DataCollection target_asset: DataSource other_assets: DataCollection diff --git a/data_loader/load.py b/data_loader/load.py index 2ae292a..e32a27e 100644 --- a/data_loader/load.py +++ b/data_loader/load.py @@ -33,6 +33,7 @@ def __load_data( own_features: list[tuple[str, FeatureExtractor, list[int]]], other_features: list[tuple[str, FeatureExtractor, list[int]]], exogenous_features: list[tuple[str, FeatureExtractor, list[int]]], + start_date: Optional[str], ) -> tuple[XDataFrame, ReturnSeries]: """ Loads asset data from the specified path. @@ -98,6 +99,9 @@ def __load_data( X = pd.concat([df.reindex(X[0].index) for df in X], axis=1).fillna(0.0) X.index = pd.DatetimeIndex(X.index) + if start_date is not None: + X = X[start_date:] + df_target_asset_only_returns = df_target_asset_only_returns[start_date:] ## Create target returns = df_target_asset_only_returns[target_asset.file_name + "_returns"] diff --git a/data_loader/process.py b/data_loader/process.py index 25d2183..9a0ab1d 100644 --- a/data_loader/process.py +++ b/data_loader/process.py @@ -18,4 +18,4 @@ def check_data(X: XDataFrame, config: Config) -> bool: def has_enough_samples_to_train(X: XDataFrame, config: Config) -> bool: first_valid_index = get_first_valid_return_index(X.iloc[:, 0]) samples_to_train = len(X) - first_valid_index - return samples_to_train > (config.initial_window_size * 2) + 100 + return samples_to_train > config.retrain_every * 3 + config.initial_window_size diff --git a/run_inference.py b/run_inference.py index c683cfe..87aca6f 100644 --- a/run_inference.py +++ b/run_inference.py @@ -39,6 +39,7 @@ def __inference(config: Config, pipeline_outcome: PipelineOutcome): own_features=config.own_features, other_features=config.other_features, exogenous_features=config.exogenous_features, + start_date=config.start_date, ) assert check_data(X, config) == True, "Data is not valid. Cancelling Inference." diff --git a/run_pipeline.py b/run_pipeline.py index fa997e2..0f73081 100644 --- a/run_pipeline.py +++ b/run_pipeline.py @@ -59,6 +59,7 @@ def run_training(config: Config) -> PipelineOutcome: own_features=config.own_features, other_features=config.other_features, exogenous_features=config.exogenous_features, + start_date=config.start_date, ) assert check_data(X, config) == True, "Data is not valid."