From 5da60b718dee0f60772c081b7406af982555bb13 Mon Sep 17 00:00:00 2001 From: robcaulk Date: Sat, 4 Feb 2023 13:47:11 +0100 Subject: [PATCH 1/4] pass metadata dictionary to feature_engineering_* and set_freqai_targets functions. Add doc --- docs/freqai-feature-engineering.md | 29 ++++++++++++++++++++ freqtrade/freqai/data_kitchen.py | 14 ++++++---- freqtrade/templates/FreqaiExampleStrategy.py | 16 +++++++++++ 3 files changed, 54 insertions(+), 5 deletions(-) diff --git a/docs/freqai-feature-engineering.md b/docs/freqai-feature-engineering.md index 6c8c5bb46..759c81289 100644 --- a/docs/freqai-feature-engineering.md +++ b/docs/freqai-feature-engineering.md @@ -28,6 +28,10 @@ It is advisable to start from the template `feature_engineering_*` functions in All features must be prepended with `%` to be recognized by FreqAI internals. + Access metadata such as the current pair/timeframe/period with: + + `metadata["pair"]` `metadata["tf"]` `metadata["period"]` + :param df: strategy dataframe which will receive the features :param period: period of the indicator - usage example: dataframe["%-ema-period"] = ta.EMA(dataframe, timeperiod=period) @@ -75,6 +79,10 @@ It is advisable to start from the template `feature_engineering_*` functions in Features defined here will *not* be automatically duplicated on user defined `indicator_periods_candles` + Access metadata such as the current pair/timeframe with: + + `metadata["pair"]` `metadata["tf"]` + All features must be prepended with `%` to be recognized by FreqAI internals. :param df: strategy dataframe which will receive the features @@ -98,6 +106,10 @@ It is advisable to start from the template `feature_engineering_*` functions in This function is a good place for any feature that should not be auto-expanded upon (e.g. day of the week). + Access metadata such as the current pair with: + + `metadata["pair"]` + All features must be prepended with `%` to be recognized by FreqAI internals. :param df: strategy dataframe which will receive the features @@ -113,6 +125,10 @@ It is advisable to start from the template `feature_engineering_*` functions in Required function to set the targets for the model. All targets must be prepended with `&` to be recognized by the FreqAI internals. + Access metadata such as the current pair with: + + `metadata["pair"]` + :param df: strategy dataframe which will receive the targets usage example: dataframe["&-target"] = dataframe["close"].shift(-1) / dataframe["close"] """ @@ -161,6 +177,19 @@ You can ask for each of the defined features to be included also for informative In total, the number of features the user of the presented example strat has created is: length of `include_timeframes` * no. features in `feature_engineering_expand_*()` * length of `include_corr_pairlist` * no. `include_shifted_candles` * length of `indicator_periods_candles` $= 3 * 3 * 3 * 2 * 2 = 108$. + + ### Gain finer control over `feature_engineering_*` functions with `metadata` + + All `feature_engineering_*` and `set_freqai_targets()` functions are passed a `metadata` dictionary which contains information about the `pair`, `tf` (timeframe), and `period` that FreqAI is automating for feature building. As such, a user can use `metadata` inside `feature_engineering_*` functions as criteria for blocking/reserving features for certain timeframes, periods, pairs etc. + + ```py +def feature_engineering_expand_all(self, dataframe, period, **kwargs): + if metadata["tf"] == "1h": + dataframe["%-roc-period"] = ta.ROC(dataframe, timeperiod=period) +``` + +This will block `ta.ROC()` from being added to any timeframes other than `"1h"`. + ### Returning additional info from training Important metrics can be returned to the strategy at the end of each model training by assigning them to `dk.data['extra_returns_per_train']['my_new_value'] = XYZ` inside the custom prediction model class. diff --git a/freqtrade/freqai/data_kitchen.py b/freqtrade/freqai/data_kitchen.py index 6f4a8c2b3..361a4146f 100644 --- a/freqtrade/freqai/data_kitchen.py +++ b/freqtrade/freqai/data_kitchen.py @@ -1247,17 +1247,21 @@ class FreqaiDataKitchen: tfs: List[str] = self.freqai_config["feature_parameters"].get("include_timeframes") for tf in tfs: + metadata = {"pair": pair, "tf": tf} informative_df = self.get_pair_data_for_features( pair, tf, strategy, corr_dataframes, base_dataframes, is_corr_pairs) informative_copy = informative_df.copy() for t in self.freqai_config["feature_parameters"]["indicator_periods_candles"]: + metadata["period"] = t df_features = strategy.feature_engineering_expand_all( - informative_copy.copy(), t) + informative_copy.copy(), t, metadata=metadata) suffix = f"{t}" informative_df = self.merge_features(informative_df, df_features, tf, tf, suffix) - generic_df = strategy.feature_engineering_expand_basic(informative_copy.copy()) + metadata.pop("period") + generic_df = strategy.feature_engineering_expand_basic( + informative_copy.copy(), metadata=metadata) suffix = "gen" informative_df = self.merge_features(informative_df, generic_df, tf, tf, suffix) @@ -1326,8 +1330,8 @@ class FreqaiDataKitchen: "include_corr_pairlist", []) dataframe = self.populate_features(dataframe.copy(), pair, strategy, corr_dataframes, base_dataframes) - - dataframe = strategy.feature_engineering_standard(dataframe.copy()) + metadata = {"pair": pair} + dataframe = strategy.feature_engineering_standard(dataframe.copy(), metadata=metadata) # ensure corr pairs are always last for corr_pair in corr_pairs: if pair == corr_pair: @@ -1336,7 +1340,7 @@ class FreqaiDataKitchen: dataframe = self.populate_features(dataframe.copy(), corr_pair, strategy, corr_dataframes, base_dataframes, True) - dataframe = strategy.set_freqai_targets(dataframe.copy()) + dataframe = strategy.set_freqai_targets(dataframe.copy(), metadata=metadata) self.get_unique_classes_from_labels(dataframe) diff --git a/freqtrade/templates/FreqaiExampleStrategy.py b/freqtrade/templates/FreqaiExampleStrategy.py index 8e34d733e..a4e86fbf9 100644 --- a/freqtrade/templates/FreqaiExampleStrategy.py +++ b/freqtrade/templates/FreqaiExampleStrategy.py @@ -58,6 +58,10 @@ class FreqaiExampleStrategy(IStrategy): All features must be prepended with `%` to be recognized by FreqAI internals. + Access metadata such as the current pair/timeframe/period with: + + `metadata["pair"]` `metadata["tf"]` `metadata["period"]` + More details on how these config defined parameters accelerate feature engineering in the documentation at: @@ -114,6 +118,10 @@ class FreqaiExampleStrategy(IStrategy): All features must be prepended with `%` to be recognized by FreqAI internals. + Access metadata such as the current pair/timeframe with: + + `metadata["pair"]` `metadata["tf"]` + More details on how these config defined parameters accelerate feature engineering in the documentation at: @@ -144,6 +152,10 @@ class FreqaiExampleStrategy(IStrategy): All features must be prepended with `%` to be recognized by FreqAI internals. + Access metadata such as the current pair with: + + `metadata["pair"]` + More details about feature engineering available: https://www.freqtrade.io/en/latest/freqai-feature-engineering @@ -161,6 +173,10 @@ class FreqaiExampleStrategy(IStrategy): Required function to set the targets for the model. All targets must be prepended with `&` to be recognized by the FreqAI internals. + Access metadata such as the current pair with: + + `metadata["pair"]` + More details about feature engineering available: https://www.freqtrade.io/en/latest/freqai-feature-engineering From e569f6f6dfcb169f94b7fc7cfd7fec5bcf8cc3e4 Mon Sep 17 00:00:00 2001 From: robcaulk Date: Sat, 4 Feb 2023 16:53:17 +0100 Subject: [PATCH 2/4] add explicit metadata argument to example strat, include it with backtesting --- docs/freqai-feature-engineering.md | 10 +++++----- freqtrade/freqai/data_kitchen.py | 2 -- freqtrade/freqai/freqai_interface.py | 6 ++++-- freqtrade/templates/FreqaiExampleStrategy.py | 12 ++++++------ 4 files changed, 15 insertions(+), 15 deletions(-) diff --git a/docs/freqai-feature-engineering.md b/docs/freqai-feature-engineering.md index 759c81289..7cd5c88e6 100644 --- a/docs/freqai-feature-engineering.md +++ b/docs/freqai-feature-engineering.md @@ -16,7 +16,7 @@ Meanwhile, high level feature engineering is handled within `"feature_parameters It is advisable to start from the template `feature_engineering_*` functions in the source provided example strategy (found in `templates/FreqaiExampleStrategy.py`) to ensure that the feature definitions are following the correct conventions. Here is an example of how to set the indicators and labels in the strategy: ```python - def feature_engineering_expand_all(self, dataframe, period, **kwargs): + def feature_engineering_expand_all(self, dataframe, period, metadata, **kwargs): """ *Only functional with FreqAI enabled strategies* This function will automatically expand the defined features on the config defined @@ -66,7 +66,7 @@ It is advisable to start from the template `feature_engineering_*` functions in return dataframe - def feature_engineering_expand_basic(self, dataframe, **kwargs): + def feature_engineering_expand_basic(self, dataframe, metadata, **kwargs): """ *Only functional with FreqAI enabled strategies* This function will automatically expand the defined features on the config defined @@ -94,7 +94,7 @@ It is advisable to start from the template `feature_engineering_*` functions in dataframe["%-raw_price"] = dataframe["close"] return dataframe - def feature_engineering_standard(self, dataframe, **kwargs): + def feature_engineering_standard(self, dataframe, metadata, **kwargs): """ *Only functional with FreqAI enabled strategies* This optional function will be called once with the dataframe of the base timeframe. @@ -119,7 +119,7 @@ It is advisable to start from the template `feature_engineering_*` functions in dataframe["%-hour_of_day"] = (dataframe["date"].dt.hour + 1) / 25 return dataframe - def set_freqai_targets(self, dataframe, **kwargs): + def set_freqai_targets(self, dataframe, metadata, **kwargs): """ *Only functional with FreqAI enabled strategies* Required function to set the targets for the model. @@ -183,7 +183,7 @@ In total, the number of features the user of the presented example strat has cre All `feature_engineering_*` and `set_freqai_targets()` functions are passed a `metadata` dictionary which contains information about the `pair`, `tf` (timeframe), and `period` that FreqAI is automating for feature building. As such, a user can use `metadata` inside `feature_engineering_*` functions as criteria for blocking/reserving features for certain timeframes, periods, pairs etc. ```py -def feature_engineering_expand_all(self, dataframe, period, **kwargs): +def feature_engineering_expand_all(self, dataframe, period, metadata, **kwargs): if metadata["tf"] == "1h": dataframe["%-roc-period"] = ta.ROC(dataframe, timeperiod=period) ``` diff --git a/freqtrade/freqai/data_kitchen.py b/freqtrade/freqai/data_kitchen.py index 361a4146f..70e5549f9 100644 --- a/freqtrade/freqai/data_kitchen.py +++ b/freqtrade/freqai/data_kitchen.py @@ -1253,13 +1253,11 @@ class FreqaiDataKitchen: informative_copy = informative_df.copy() for t in self.freqai_config["feature_parameters"]["indicator_periods_candles"]: - metadata["period"] = t df_features = strategy.feature_engineering_expand_all( informative_copy.copy(), t, metadata=metadata) suffix = f"{t}" informative_df = self.merge_features(informative_df, df_features, tf, tf, suffix) - metadata.pop("period") generic_df = strategy.feature_engineering_expand_basic( informative_copy.copy(), metadata=metadata) suffix = "gen" diff --git a/freqtrade/freqai/freqai_interface.py b/freqtrade/freqai/freqai_interface.py index 34928f7c2..00342cc6b 100644 --- a/freqtrade/freqai/freqai_interface.py +++ b/freqtrade/freqai/freqai_interface.py @@ -324,9 +324,11 @@ class IFreqaiModel(ABC): populate_indicators = False dataframe_base_train = dataframe.loc[dataframe["date"] < tr_train.stopdt, :] - dataframe_base_train = strategy.set_freqai_targets(dataframe_base_train) + dataframe_base_train = strategy.set_freqai_targets( + dataframe_base_train, metadata=metadata) dataframe_base_backtest = dataframe.loc[dataframe["date"] < tr_backtest.stopdt, :] - dataframe_base_backtest = strategy.set_freqai_targets(dataframe_base_backtest) + dataframe_base_backtest = strategy.set_freqai_targets( + dataframe_base_backtest, metadata=metadata) dataframe_train = dk.slice_dataframe(tr_train, dataframe_base_train) dataframe_backtest = dk.slice_dataframe(tr_backtest, dataframe_base_backtest) diff --git a/freqtrade/templates/FreqaiExampleStrategy.py b/freqtrade/templates/FreqaiExampleStrategy.py index a4e86fbf9..acf6cfde6 100644 --- a/freqtrade/templates/FreqaiExampleStrategy.py +++ b/freqtrade/templates/FreqaiExampleStrategy.py @@ -46,7 +46,7 @@ class FreqaiExampleStrategy(IStrategy): std_dev_multiplier_sell = CategoricalParameter( [0.75, 1, 1.25, 1.5, 1.75], space="sell", default=1.25, optimize=True) - def feature_engineering_expand_all(self, dataframe, period, **kwargs): + def feature_engineering_expand_all(self, dataframe, period, metadata, **kwargs): """ *Only functional with FreqAI enabled strategies* This function will automatically expand the defined features on the config defined @@ -58,9 +58,9 @@ class FreqaiExampleStrategy(IStrategy): All features must be prepended with `%` to be recognized by FreqAI internals. - Access metadata such as the current pair/timeframe/period with: + Access metadata such as the current pair/timeframe with: - `metadata["pair"]` `metadata["tf"]` `metadata["period"]` + `metadata["pair"]` `metadata["tf"]` More details on how these config defined parameters accelerate feature engineering in the documentation at: @@ -103,7 +103,7 @@ class FreqaiExampleStrategy(IStrategy): return dataframe - def feature_engineering_expand_basic(self, dataframe, **kwargs): + def feature_engineering_expand_basic(self, dataframe, metadata, **kwargs): """ *Only functional with FreqAI enabled strategies* This function will automatically expand the defined features on the config defined @@ -138,7 +138,7 @@ class FreqaiExampleStrategy(IStrategy): dataframe["%-raw_price"] = dataframe["close"] return dataframe - def feature_engineering_standard(self, dataframe, **kwargs): + def feature_engineering_standard(self, dataframe, metadata, **kwargs): """ *Only functional with FreqAI enabled strategies* This optional function will be called once with the dataframe of the base timeframe. @@ -167,7 +167,7 @@ class FreqaiExampleStrategy(IStrategy): dataframe["%-hour_of_day"] = dataframe["date"].dt.hour return dataframe - def set_freqai_targets(self, dataframe, **kwargs): + def set_freqai_targets(self, dataframe, metadata, **kwargs): """ *Only functional with FreqAI enabled strategies* Required function to set the targets for the model. From 0dd2472385766f76d392fe136365812ecf2ea99e Mon Sep 17 00:00:00 2001 From: robcaulk Date: Sat, 4 Feb 2023 16:56:36 +0100 Subject: [PATCH 3/4] add metadata param to docstrings --- docs/freqai-feature-engineering.md | 4 ++++ freqtrade/strategy/interface.py | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/docs/freqai-feature-engineering.md b/docs/freqai-feature-engineering.md index 7cd5c88e6..9f2696628 100644 --- a/docs/freqai-feature-engineering.md +++ b/docs/freqai-feature-engineering.md @@ -34,6 +34,7 @@ It is advisable to start from the template `feature_engineering_*` functions in :param df: strategy dataframe which will receive the features :param period: period of the indicator - usage example: + :param metadata: metadata of current pair dataframe["%-ema-period"] = ta.EMA(dataframe, timeperiod=period) """ @@ -86,6 +87,7 @@ It is advisable to start from the template `feature_engineering_*` functions in All features must be prepended with `%` to be recognized by FreqAI internals. :param df: strategy dataframe which will receive the features + :param metadata: metadata of current pair dataframe["%-pct-change"] = dataframe["close"].pct_change() dataframe["%-ema-200"] = ta.EMA(dataframe, timeperiod=200) """ @@ -113,6 +115,7 @@ It is advisable to start from the template `feature_engineering_*` functions in All features must be prepended with `%` to be recognized by FreqAI internals. :param df: strategy dataframe which will receive the features + :param metadata: metadata of current pair usage example: dataframe["%-day_of_week"] = (dataframe["date"].dt.dayofweek + 1) / 7 """ dataframe["%-day_of_week"] = (dataframe["date"].dt.dayofweek + 1) / 7 @@ -130,6 +133,7 @@ It is advisable to start from the template `feature_engineering_*` functions in `metadata["pair"]` :param df: strategy dataframe which will receive the targets + :param metadata: metadata of current pair usage example: dataframe["&-target"] = dataframe["close"].shift(-1) / dataframe["close"] """ dataframe["&-s_close"] = ( diff --git a/freqtrade/strategy/interface.py b/freqtrade/strategy/interface.py index fce4e629e..8ec46c91b 100644 --- a/freqtrade/strategy/interface.py +++ b/freqtrade/strategy/interface.py @@ -636,6 +636,7 @@ class IStrategy(ABC, HyperStrategyMixin): :param df: strategy dataframe which will receive the features :param period: period of the indicator - usage example: + :param metadata: metadata of current pair dataframe["%-ema-period"] = ta.EMA(dataframe, timeperiod=period) """ return dataframe @@ -663,6 +664,7 @@ class IStrategy(ABC, HyperStrategyMixin): https://www.freqtrade.io/en/latest/freqai-feature-engineering/#defining-the-features :param df: strategy dataframe which will receive the features + :param metadata: metadata of current pair dataframe["%-pct-change"] = dataframe["close"].pct_change() dataframe["%-ema-200"] = ta.EMA(dataframe, timeperiod=200) """ @@ -687,6 +689,7 @@ class IStrategy(ABC, HyperStrategyMixin): https://www.freqtrade.io/en/latest/freqai-feature-engineering :param df: strategy dataframe which will receive the features + :param metadata: metadata of current pair usage example: dataframe["%-day_of_week"] = (dataframe["date"].dt.dayofweek + 1) / 7 """ return dataframe @@ -702,6 +705,7 @@ class IStrategy(ABC, HyperStrategyMixin): https://www.freqtrade.io/en/latest/freqai-feature-engineering :param df: strategy dataframe which will receive the targets + :param metadata: metadata of current pair usage example: dataframe["&-target"] = dataframe["close"].shift(-1) / dataframe["close"] """ return dataframe From 801714a5884977bc9efb30868dadf2bf4c4b6afc Mon Sep 17 00:00:00 2001 From: Matthias Date: Sat, 4 Feb 2023 20:04:16 +0100 Subject: [PATCH 4/4] Update function signatures in all templates add typehints to help the user's editor suggest the right things. --- freqtrade/strategy/interface.py | 18 +++++++-------- .../templates/FreqaiExampleHybridStrategy.py | 22 ++++++++++++------- freqtrade/templates/FreqaiExampleStrategy.py | 22 ++++++++++++------- tests/strategy/strats/freqai_rl_test_strat.py | 10 +++++---- .../strategy/strats/freqai_test_classifier.py | 10 +++++---- ...freqai_test_multimodel_classifier_strat.py | 10 +++++---- .../strats/freqai_test_multimodel_strat.py | 10 +++++---- tests/strategy/strats/freqai_test_strat.py | 10 +++++---- 8 files changed, 67 insertions(+), 45 deletions(-) diff --git a/freqtrade/strategy/interface.py b/freqtrade/strategy/interface.py index 8ec46c91b..70d656199 100644 --- a/freqtrade/strategy/interface.py +++ b/freqtrade/strategy/interface.py @@ -614,8 +614,8 @@ class IStrategy(ABC, HyperStrategyMixin): """ return df - def feature_engineering_expand_all(self, dataframe: DataFrame, - period: int, **kwargs): + def feature_engineering_expand_all(self, dataframe: DataFrame, period: int, + metadata: Dict, **kwargs): """ *Only functional with FreqAI enabled strategies* This function will automatically expand the defined features on the config defined @@ -634,14 +634,14 @@ class IStrategy(ABC, HyperStrategyMixin): https://www.freqtrade.io/en/latest/freqai-feature-engineering/#defining-the-features - :param df: strategy dataframe which will receive the features + :param dataframe: strategy dataframe which will receive the features :param period: period of the indicator - usage example: :param metadata: metadata of current pair dataframe["%-ema-period"] = ta.EMA(dataframe, timeperiod=period) """ return dataframe - def feature_engineering_expand_basic(self, dataframe: DataFrame, **kwargs): + def feature_engineering_expand_basic(self, dataframe: DataFrame, metadata: Dict, **kwargs): """ *Only functional with FreqAI enabled strategies* This function will automatically expand the defined features on the config defined @@ -663,14 +663,14 @@ class IStrategy(ABC, HyperStrategyMixin): https://www.freqtrade.io/en/latest/freqai-feature-engineering/#defining-the-features - :param df: strategy dataframe which will receive the features + :param dataframe: strategy dataframe which will receive the features :param metadata: metadata of current pair dataframe["%-pct-change"] = dataframe["close"].pct_change() dataframe["%-ema-200"] = ta.EMA(dataframe, timeperiod=200) """ return dataframe - def feature_engineering_standard(self, dataframe: DataFrame, **kwargs): + def feature_engineering_standard(self, dataframe: DataFrame, metadata: Dict, **kwargs): """ *Only functional with FreqAI enabled strategies* This optional function will be called once with the dataframe of the base timeframe. @@ -688,13 +688,13 @@ class IStrategy(ABC, HyperStrategyMixin): https://www.freqtrade.io/en/latest/freqai-feature-engineering - :param df: strategy dataframe which will receive the features + :param dataframe: strategy dataframe which will receive the features :param metadata: metadata of current pair usage example: dataframe["%-day_of_week"] = (dataframe["date"].dt.dayofweek + 1) / 7 """ return dataframe - def set_freqai_targets(self, dataframe, **kwargs): + def set_freqai_targets(self, dataframe: DataFrame, metadata: Dict, **kwargs): """ *Only functional with FreqAI enabled strategies* Required function to set the targets for the model. @@ -704,7 +704,7 @@ class IStrategy(ABC, HyperStrategyMixin): https://www.freqtrade.io/en/latest/freqai-feature-engineering - :param df: strategy dataframe which will receive the targets + :param dataframe: strategy dataframe which will receive the targets :param metadata: metadata of current pair usage example: dataframe["&-target"] = dataframe["close"].shift(-1) / dataframe["close"] """ diff --git a/freqtrade/templates/FreqaiExampleHybridStrategy.py b/freqtrade/templates/FreqaiExampleHybridStrategy.py index c5dbe8dbd..ee574fda3 100644 --- a/freqtrade/templates/FreqaiExampleHybridStrategy.py +++ b/freqtrade/templates/FreqaiExampleHybridStrategy.py @@ -1,4 +1,5 @@ import logging +from typing import Dict import numpy as np import pandas as pd @@ -95,7 +96,8 @@ class FreqaiExampleHybridStrategy(IStrategy): short_rsi = IntParameter(low=51, high=100, default=70, space='sell', optimize=True, load=True) exit_short_rsi = IntParameter(low=1, high=50, default=30, space='buy', optimize=True, load=True) - def feature_engineering_expand_all(self, dataframe, period, **kwargs): + def feature_engineering_expand_all(self, dataframe: DataFrame, period: int, + metadata: Dict, **kwargs): """ *Only functional with FreqAI enabled strategies* This function will automatically expand the defined features on the config defined @@ -114,8 +116,9 @@ class FreqaiExampleHybridStrategy(IStrategy): https://www.freqtrade.io/en/latest/freqai-feature-engineering/#defining-the-features - :param df: strategy dataframe which will receive the features + :param dataframe: strategy dataframe which will receive the features :param period: period of the indicator - usage example: + :param metadata: metadata of current pair dataframe["%-ema-period"] = ta.EMA(dataframe, timeperiod=period) """ @@ -148,7 +151,7 @@ class FreqaiExampleHybridStrategy(IStrategy): return dataframe - def feature_engineering_expand_basic(self, dataframe, **kwargs): + def feature_engineering_expand_basic(self, dataframe: DataFrame, metadata: Dict, **kwargs): """ *Only functional with FreqAI enabled strategies* This function will automatically expand the defined features on the config defined @@ -170,7 +173,8 @@ class FreqaiExampleHybridStrategy(IStrategy): https://www.freqtrade.io/en/latest/freqai-feature-engineering/#defining-the-features - :param df: strategy dataframe which will receive the features + :param dataframe: strategy dataframe which will receive the features + :param metadata: metadata of current pair dataframe["%-pct-change"] = dataframe["close"].pct_change() dataframe["%-ema-200"] = ta.EMA(dataframe, timeperiod=200) """ @@ -179,7 +183,7 @@ class FreqaiExampleHybridStrategy(IStrategy): dataframe["%-raw_price"] = dataframe["close"] return dataframe - def feature_engineering_standard(self, dataframe, **kwargs): + def feature_engineering_standard(self, dataframe: DataFrame, metadata: Dict, **kwargs): """ *Only functional with FreqAI enabled strategies* This optional function will be called once with the dataframe of the base timeframe. @@ -197,14 +201,15 @@ class FreqaiExampleHybridStrategy(IStrategy): https://www.freqtrade.io/en/latest/freqai-feature-engineering - :param df: strategy dataframe which will receive the features + :param dataframe: strategy dataframe which will receive the features + :param metadata: metadata of current pair usage example: dataframe["%-day_of_week"] = (dataframe["date"].dt.dayofweek + 1) / 7 """ dataframe["%-day_of_week"] = dataframe["date"].dt.dayofweek dataframe["%-hour_of_day"] = dataframe["date"].dt.hour return dataframe - def set_freqai_targets(self, dataframe, **kwargs): + def set_freqai_targets(self, dataframe: DataFrame, metadata: Dict, **kwargs): """ *Only functional with FreqAI enabled strategies* Required function to set the targets for the model. @@ -214,7 +219,8 @@ class FreqaiExampleHybridStrategy(IStrategy): https://www.freqtrade.io/en/latest/freqai-feature-engineering - :param df: strategy dataframe which will receive the targets + :param dataframe: strategy dataframe which will receive the targets + :param metadata: metadata of current pair usage example: dataframe["&-target"] = dataframe["close"].shift(-1) / dataframe["close"] """ dataframe['&s-up_or_down'] = np.where(dataframe["close"].shift(-50) > diff --git a/freqtrade/templates/FreqaiExampleStrategy.py b/freqtrade/templates/FreqaiExampleStrategy.py index acf6cfde6..0093c7f7a 100644 --- a/freqtrade/templates/FreqaiExampleStrategy.py +++ b/freqtrade/templates/FreqaiExampleStrategy.py @@ -1,5 +1,6 @@ import logging from functools import reduce +from typing import Dict import talib.abstract as ta from pandas import DataFrame @@ -46,7 +47,8 @@ class FreqaiExampleStrategy(IStrategy): std_dev_multiplier_sell = CategoricalParameter( [0.75, 1, 1.25, 1.5, 1.75], space="sell", default=1.25, optimize=True) - def feature_engineering_expand_all(self, dataframe, period, metadata, **kwargs): + def feature_engineering_expand_all(self, dataframe: DataFrame, period: int, + metadata: Dict, **kwargs): """ *Only functional with FreqAI enabled strategies* This function will automatically expand the defined features on the config defined @@ -69,8 +71,9 @@ class FreqaiExampleStrategy(IStrategy): https://www.freqtrade.io/en/latest/freqai-feature-engineering/#defining-the-features - :param df: strategy dataframe which will receive the features + :param dataframe: strategy dataframe which will receive the features :param period: period of the indicator - usage example: + :param metadata: metadata of current pair dataframe["%-ema-period"] = ta.EMA(dataframe, timeperiod=period) """ @@ -103,7 +106,7 @@ class FreqaiExampleStrategy(IStrategy): return dataframe - def feature_engineering_expand_basic(self, dataframe, metadata, **kwargs): + def feature_engineering_expand_basic(self, dataframe: DataFrame, metadata: Dict, **kwargs): """ *Only functional with FreqAI enabled strategies* This function will automatically expand the defined features on the config defined @@ -129,7 +132,8 @@ class FreqaiExampleStrategy(IStrategy): https://www.freqtrade.io/en/latest/freqai-feature-engineering/#defining-the-features - :param df: strategy dataframe which will receive the features + :param dataframe: strategy dataframe which will receive the features + :param metadata: metadata of current pair dataframe["%-pct-change"] = dataframe["close"].pct_change() dataframe["%-ema-200"] = ta.EMA(dataframe, timeperiod=200) """ @@ -138,7 +142,7 @@ class FreqaiExampleStrategy(IStrategy): dataframe["%-raw_price"] = dataframe["close"] return dataframe - def feature_engineering_standard(self, dataframe, metadata, **kwargs): + def feature_engineering_standard(self, dataframe: DataFrame, metadata: Dict, **kwargs): """ *Only functional with FreqAI enabled strategies* This optional function will be called once with the dataframe of the base timeframe. @@ -160,14 +164,15 @@ class FreqaiExampleStrategy(IStrategy): https://www.freqtrade.io/en/latest/freqai-feature-engineering - :param df: strategy dataframe which will receive the features + :param dataframe: strategy dataframe which will receive the features + :param metadata: metadata of current pair usage example: dataframe["%-day_of_week"] = (dataframe["date"].dt.dayofweek + 1) / 7 """ dataframe["%-day_of_week"] = dataframe["date"].dt.dayofweek dataframe["%-hour_of_day"] = dataframe["date"].dt.hour return dataframe - def set_freqai_targets(self, dataframe, metadata, **kwargs): + def set_freqai_targets(self, dataframe: DataFrame, metadata: Dict, **kwargs): """ *Only functional with FreqAI enabled strategies* Required function to set the targets for the model. @@ -181,7 +186,8 @@ class FreqaiExampleStrategy(IStrategy): https://www.freqtrade.io/en/latest/freqai-feature-engineering - :param df: strategy dataframe which will receive the targets + :param dataframe: strategy dataframe which will receive the targets + :param metadata: metadata of current pair usage example: dataframe["&-target"] = dataframe["close"].shift(-1) / dataframe["close"] """ dataframe["&-s_close"] = ( diff --git a/tests/strategy/strats/freqai_rl_test_strat.py b/tests/strategy/strats/freqai_rl_test_strat.py index 6fa926fc9..2bf4aaa30 100644 --- a/tests/strategy/strats/freqai_rl_test_strat.py +++ b/tests/strategy/strats/freqai_rl_test_strat.py @@ -1,5 +1,6 @@ import logging from functools import reduce +from typing import Dict import talib.abstract as ta from pandas import DataFrame @@ -24,20 +25,21 @@ class freqai_rl_test_strat(IStrategy): startup_candle_count: int = 300 can_short = False - def feature_engineering_expand_all(self, dataframe, period, **kwargs): + def feature_engineering_expand_all(self, dataframe: DataFrame, period: int, + metadata: Dict, **kwargs): dataframe["%-rsi-period"] = ta.RSI(dataframe, timeperiod=period) return dataframe - def feature_engineering_expand_basic(self, dataframe: DataFrame, **kwargs): + def feature_engineering_expand_basic(self, dataframe: DataFrame, metadata: Dict, **kwargs): dataframe["%-pct-change"] = dataframe["close"].pct_change() dataframe["%-raw_volume"] = dataframe["volume"] return dataframe - def feature_engineering_standard(self, dataframe, **kwargs): + def feature_engineering_standard(self, dataframe: DataFrame, metadata: Dict, **kwargs): dataframe["%-day_of_week"] = dataframe["date"].dt.dayofweek dataframe["%-hour_of_day"] = dataframe["date"].dt.hour @@ -49,7 +51,7 @@ class freqai_rl_test_strat(IStrategy): return dataframe - def set_freqai_targets(self, dataframe, **kwargs): + def set_freqai_targets(self, dataframe: DataFrame, metadata: Dict, **kwargs): dataframe["&-action"] = 0 diff --git a/tests/strategy/strats/freqai_test_classifier.py b/tests/strategy/strats/freqai_test_classifier.py index 02427ab59..61b9f0c37 100644 --- a/tests/strategy/strats/freqai_test_classifier.py +++ b/tests/strategy/strats/freqai_test_classifier.py @@ -1,5 +1,6 @@ import logging from functools import reduce +from typing import Dict import numpy as np import talib.abstract as ta @@ -56,7 +57,8 @@ class freqai_test_classifier(IStrategy): informative_pairs.append((pair, tf)) return informative_pairs - def feature_engineering_expand_all(self, dataframe, period, **kwargs): + def feature_engineering_expand_all(self, dataframe: DataFrame, period: int, + metadata: Dict, **kwargs): dataframe["%-rsi-period"] = ta.RSI(dataframe, timeperiod=period) dataframe["%-mfi-period"] = ta.MFI(dataframe, timeperiod=period) @@ -64,7 +66,7 @@ class freqai_test_classifier(IStrategy): return dataframe - def feature_engineering_expand_basic(self, dataframe: DataFrame, **kwargs): + def feature_engineering_expand_basic(self, dataframe: DataFrame, metadata: Dict, **kwargs): dataframe["%-pct-change"] = dataframe["close"].pct_change() dataframe["%-raw_volume"] = dataframe["volume"] @@ -72,14 +74,14 @@ class freqai_test_classifier(IStrategy): return dataframe - def feature_engineering_standard(self, dataframe, **kwargs): + def feature_engineering_standard(self, dataframe: DataFrame, metadata: Dict, **kwargs): dataframe["%-day_of_week"] = dataframe["date"].dt.dayofweek dataframe["%-hour_of_day"] = dataframe["date"].dt.hour return dataframe - def set_freqai_targets(self, dataframe, **kwargs): + def set_freqai_targets(self, dataframe: DataFrame, metadata: Dict, **kwargs): dataframe['&s-up_or_down'] = np.where(dataframe["close"].shift(-100) > dataframe["close"], 'up', 'down') diff --git a/tests/strategy/strats/freqai_test_multimodel_classifier_strat.py b/tests/strategy/strats/freqai_test_multimodel_classifier_strat.py index 65f2e4540..b2ddc21e3 100644 --- a/tests/strategy/strats/freqai_test_multimodel_classifier_strat.py +++ b/tests/strategy/strats/freqai_test_multimodel_classifier_strat.py @@ -1,5 +1,6 @@ import logging from functools import reduce +from typing import Dict import numpy as np import talib.abstract as ta @@ -43,7 +44,8 @@ class freqai_test_multimodel_classifier_strat(IStrategy): ) max_roi_time_long = IntParameter(0, 800, default=400, space="sell", optimize=False, load=True) - def feature_engineering_expand_all(self, dataframe, period, **kwargs): + def feature_engineering_expand_all(self, dataframe: DataFrame, period: int, + metadata: Dict, **kwargs): dataframe["%-rsi-period"] = ta.RSI(dataframe, timeperiod=period) dataframe["%-mfi-period"] = ta.MFI(dataframe, timeperiod=period) @@ -51,7 +53,7 @@ class freqai_test_multimodel_classifier_strat(IStrategy): return dataframe - def feature_engineering_expand_basic(self, dataframe: DataFrame, **kwargs): + def feature_engineering_expand_basic(self, dataframe: DataFrame, metadata: Dict, **kwargs): dataframe["%-pct-change"] = dataframe["close"].pct_change() dataframe["%-raw_volume"] = dataframe["volume"] @@ -59,14 +61,14 @@ class freqai_test_multimodel_classifier_strat(IStrategy): return dataframe - def feature_engineering_standard(self, dataframe, **kwargs): + def feature_engineering_standard(self, dataframe: DataFrame, metadata: Dict, **kwargs): dataframe["%-day_of_week"] = dataframe["date"].dt.dayofweek dataframe["%-hour_of_day"] = dataframe["date"].dt.hour return dataframe - def set_freqai_targets(self, dataframe, **kwargs): + def set_freqai_targets(self, dataframe: DataFrame, metadata: Dict, **kwargs): dataframe['&s-up_or_down'] = np.where(dataframe["close"].shift(-50) > dataframe["close"], 'up', 'down') diff --git a/tests/strategy/strats/freqai_test_multimodel_strat.py b/tests/strategy/strats/freqai_test_multimodel_strat.py index 5c9712629..5b09598a5 100644 --- a/tests/strategy/strats/freqai_test_multimodel_strat.py +++ b/tests/strategy/strats/freqai_test_multimodel_strat.py @@ -1,5 +1,6 @@ import logging from functools import reduce +from typing import Dict import talib.abstract as ta from pandas import DataFrame @@ -42,7 +43,8 @@ class freqai_test_multimodel_strat(IStrategy): ) max_roi_time_long = IntParameter(0, 800, default=400, space="sell", optimize=False, load=True) - def feature_engineering_expand_all(self, dataframe, period, **kwargs): + def feature_engineering_expand_all(self, dataframe: DataFrame, period: int, + metadata: Dict, **kwargs): dataframe["%-rsi-period"] = ta.RSI(dataframe, timeperiod=period) dataframe["%-mfi-period"] = ta.MFI(dataframe, timeperiod=period) @@ -50,7 +52,7 @@ class freqai_test_multimodel_strat(IStrategy): return dataframe - def feature_engineering_expand_basic(self, dataframe: DataFrame, **kwargs): + def feature_engineering_expand_basic(self, dataframe: DataFrame, metadata: Dict, **kwargs): dataframe["%-pct-change"] = dataframe["close"].pct_change() dataframe["%-raw_volume"] = dataframe["volume"] @@ -58,14 +60,14 @@ class freqai_test_multimodel_strat(IStrategy): return dataframe - def feature_engineering_standard(self, dataframe, **kwargs): + def feature_engineering_standard(self, dataframe: DataFrame, metadata: Dict, **kwargs): dataframe["%-day_of_week"] = dataframe["date"].dt.dayofweek dataframe["%-hour_of_day"] = dataframe["date"].dt.hour return dataframe - def set_freqai_targets(self, dataframe, **kwargs): + def set_freqai_targets(self, dataframe: DataFrame, metadata: Dict, **kwargs): dataframe["&-s_close"] = ( dataframe["close"] diff --git a/tests/strategy/strats/freqai_test_strat.py b/tests/strategy/strats/freqai_test_strat.py index b52c95908..6db308406 100644 --- a/tests/strategy/strats/freqai_test_strat.py +++ b/tests/strategy/strats/freqai_test_strat.py @@ -1,5 +1,6 @@ import logging from functools import reduce +from typing import Dict import talib.abstract as ta from pandas import DataFrame @@ -42,7 +43,8 @@ class freqai_test_strat(IStrategy): ) max_roi_time_long = IntParameter(0, 800, default=400, space="sell", optimize=False, load=True) - def feature_engineering_expand_all(self, dataframe, period, **kwargs): + def feature_engineering_expand_all(self, dataframe: DataFrame, period: int, + metadata: Dict, **kwargs): dataframe["%-rsi-period"] = ta.RSI(dataframe, timeperiod=period) dataframe["%-mfi-period"] = ta.MFI(dataframe, timeperiod=period) @@ -50,7 +52,7 @@ class freqai_test_strat(IStrategy): return dataframe - def feature_engineering_expand_basic(self, dataframe: DataFrame, **kwargs): + def feature_engineering_expand_basic(self, dataframe: DataFrame, metadata: Dict, **kwargs): dataframe["%-pct-change"] = dataframe["close"].pct_change() dataframe["%-raw_volume"] = dataframe["volume"] @@ -58,14 +60,14 @@ class freqai_test_strat(IStrategy): return dataframe - def feature_engineering_standard(self, dataframe, **kwargs): + def feature_engineering_standard(self, dataframe: DataFrame, metadata: Dict, **kwargs): dataframe["%-day_of_week"] = dataframe["date"].dt.dayofweek dataframe["%-hour_of_day"] = dataframe["date"].dt.hour return dataframe - def set_freqai_targets(self, dataframe, **kwargs): + def set_freqai_targets(self, dataframe: DataFrame, metadata: Dict, **kwargs): dataframe["&-s_close"] = ( dataframe["close"]