Merge pull request #8109 from freqtrade/add-metadata-to-feature-engineering

Pass metadata dictionary to feature_engineering_* and set_freqai_targets()
This commit is contained in:
Matthias 2023-02-05 09:56:21 +01:00 committed by GitHub
commit a7fec1f871
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 135 additions and 56 deletions

View File

@ -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: 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 ```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* *Only functional with FreqAI enabled strategies*
This function will automatically expand the defined features on the config defined This function will automatically expand the defined features on the config defined
@ -28,8 +28,13 @@ It is advisable to start from the template `feature_engineering_*` functions in
All features must be prepended with `%` to be recognized by FreqAI internals. 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 df: strategy dataframe which will receive the features
:param period: period of the indicator - usage example: :param period: period of the indicator - usage example:
:param metadata: metadata of current pair
dataframe["%-ema-period"] = ta.EMA(dataframe, timeperiod=period) dataframe["%-ema-period"] = ta.EMA(dataframe, timeperiod=period)
""" """
@ -62,7 +67,7 @@ It is advisable to start from the template `feature_engineering_*` functions in
return dataframe 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* *Only functional with FreqAI enabled strategies*
This function will automatically expand the defined features on the config defined This function will automatically expand the defined features on the config defined
@ -75,9 +80,14 @@ It is advisable to start from the template `feature_engineering_*` functions in
Features defined here will *not* be automatically duplicated on user defined Features defined here will *not* be automatically duplicated on user defined
`indicator_periods_candles` `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. All features must be prepended with `%` to be recognized by FreqAI internals.
:param df: strategy dataframe which will receive 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["%-pct-change"] = dataframe["close"].pct_change()
dataframe["%-ema-200"] = ta.EMA(dataframe, timeperiod=200) dataframe["%-ema-200"] = ta.EMA(dataframe, timeperiod=200)
""" """
@ -86,7 +96,7 @@ It is advisable to start from the template `feature_engineering_*` functions in
dataframe["%-raw_price"] = dataframe["close"] dataframe["%-raw_price"] = dataframe["close"]
return dataframe return dataframe
def feature_engineering_standard(self, dataframe, **kwargs): def feature_engineering_standard(self, dataframe, metadata, **kwargs):
""" """
*Only functional with FreqAI enabled strategies* *Only functional with FreqAI enabled strategies*
This optional function will be called once with the dataframe of the base timeframe. This optional function will be called once with the dataframe of the base timeframe.
@ -98,22 +108,32 @@ 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 This function is a good place for any feature that should not be auto-expanded upon
(e.g. day of the week). (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. All features must be prepended with `%` to be recognized by FreqAI internals.
:param df: strategy dataframe which will receive the features :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 usage example: dataframe["%-day_of_week"] = (dataframe["date"].dt.dayofweek + 1) / 7
""" """
dataframe["%-day_of_week"] = (dataframe["date"].dt.dayofweek + 1) / 7 dataframe["%-day_of_week"] = (dataframe["date"].dt.dayofweek + 1) / 7
dataframe["%-hour_of_day"] = (dataframe["date"].dt.hour + 1) / 25 dataframe["%-hour_of_day"] = (dataframe["date"].dt.hour + 1) / 25
return dataframe return dataframe
def set_freqai_targets(self, dataframe, **kwargs): def set_freqai_targets(self, dataframe, metadata, **kwargs):
""" """
*Only functional with FreqAI enabled strategies* *Only functional with FreqAI enabled strategies*
Required function to set the targets for the model. Required function to set the targets for the model.
All targets must be prepended with `&` to be recognized by the FreqAI internals. 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 :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"] usage example: dataframe["&-target"] = dataframe["close"].shift(-1) / dataframe["close"]
""" """
dataframe["&-s_close"] = ( dataframe["&-s_close"] = (
@ -161,6 +181,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` 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$. $= 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, metadata, **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 ### 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. 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.

View File

@ -1247,17 +1247,19 @@ class FreqaiDataKitchen:
tfs: List[str] = self.freqai_config["feature_parameters"].get("include_timeframes") tfs: List[str] = self.freqai_config["feature_parameters"].get("include_timeframes")
for tf in tfs: for tf in tfs:
metadata = {"pair": pair, "tf": tf}
informative_df = self.get_pair_data_for_features( informative_df = self.get_pair_data_for_features(
pair, tf, strategy, corr_dataframes, base_dataframes, is_corr_pairs) pair, tf, strategy, corr_dataframes, base_dataframes, is_corr_pairs)
informative_copy = informative_df.copy() informative_copy = informative_df.copy()
for t in self.freqai_config["feature_parameters"]["indicator_periods_candles"]: for t in self.freqai_config["feature_parameters"]["indicator_periods_candles"]:
df_features = strategy.feature_engineering_expand_all( df_features = strategy.feature_engineering_expand_all(
informative_copy.copy(), t) informative_copy.copy(), t, metadata=metadata)
suffix = f"{t}" suffix = f"{t}"
informative_df = self.merge_features(informative_df, df_features, tf, tf, suffix) informative_df = self.merge_features(informative_df, df_features, tf, tf, suffix)
generic_df = strategy.feature_engineering_expand_basic(informative_copy.copy()) generic_df = strategy.feature_engineering_expand_basic(
informative_copy.copy(), metadata=metadata)
suffix = "gen" suffix = "gen"
informative_df = self.merge_features(informative_df, generic_df, tf, tf, suffix) informative_df = self.merge_features(informative_df, generic_df, tf, tf, suffix)
@ -1326,8 +1328,8 @@ class FreqaiDataKitchen:
"include_corr_pairlist", []) "include_corr_pairlist", [])
dataframe = self.populate_features(dataframe.copy(), pair, strategy, dataframe = self.populate_features(dataframe.copy(), pair, strategy,
corr_dataframes, base_dataframes) corr_dataframes, base_dataframes)
metadata = {"pair": pair}
dataframe = strategy.feature_engineering_standard(dataframe.copy()) dataframe = strategy.feature_engineering_standard(dataframe.copy(), metadata=metadata)
# ensure corr pairs are always last # ensure corr pairs are always last
for corr_pair in corr_pairs: for corr_pair in corr_pairs:
if pair == corr_pair: if pair == corr_pair:
@ -1336,7 +1338,7 @@ class FreqaiDataKitchen:
dataframe = self.populate_features(dataframe.copy(), corr_pair, strategy, dataframe = self.populate_features(dataframe.copy(), corr_pair, strategy,
corr_dataframes, base_dataframes, True) 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) self.get_unique_classes_from_labels(dataframe)

View File

@ -324,9 +324,11 @@ class IFreqaiModel(ABC):
populate_indicators = False populate_indicators = False
dataframe_base_train = dataframe.loc[dataframe["date"] < tr_train.stopdt, :] 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 = 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_train = dk.slice_dataframe(tr_train, dataframe_base_train)
dataframe_backtest = dk.slice_dataframe(tr_backtest, dataframe_base_backtest) dataframe_backtest = dk.slice_dataframe(tr_backtest, dataframe_base_backtest)

View File

@ -614,8 +614,8 @@ class IStrategy(ABC, HyperStrategyMixin):
""" """
return df return df
def feature_engineering_expand_all(self, dataframe: DataFrame, def feature_engineering_expand_all(self, dataframe: DataFrame, period: int,
period: int, **kwargs): metadata: Dict, **kwargs):
""" """
*Only functional with FreqAI enabled strategies* *Only functional with FreqAI enabled strategies*
This function will automatically expand the defined features on the config defined This function will automatically expand the defined features on the config defined
@ -634,13 +634,14 @@ class IStrategy(ABC, HyperStrategyMixin):
https://www.freqtrade.io/en/latest/freqai-feature-engineering/#defining-the-features 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 period: period of the indicator - usage example:
:param metadata: metadata of current pair
dataframe["%-ema-period"] = ta.EMA(dataframe, timeperiod=period) dataframe["%-ema-period"] = ta.EMA(dataframe, timeperiod=period)
""" """
return dataframe 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* *Only functional with FreqAI enabled strategies*
This function will automatically expand the defined features on the config defined This function will automatically expand the defined features on the config defined
@ -662,13 +663,14 @@ class IStrategy(ABC, HyperStrategyMixin):
https://www.freqtrade.io/en/latest/freqai-feature-engineering/#defining-the-features 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["%-pct-change"] = dataframe["close"].pct_change()
dataframe["%-ema-200"] = ta.EMA(dataframe, timeperiod=200) dataframe["%-ema-200"] = ta.EMA(dataframe, timeperiod=200)
""" """
return dataframe 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* *Only functional with FreqAI enabled strategies*
This optional function will be called once with the dataframe of the base timeframe. This optional function will be called once with the dataframe of the base timeframe.
@ -686,12 +688,13 @@ class IStrategy(ABC, HyperStrategyMixin):
https://www.freqtrade.io/en/latest/freqai-feature-engineering 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 usage example: dataframe["%-day_of_week"] = (dataframe["date"].dt.dayofweek + 1) / 7
""" """
return dataframe 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* *Only functional with FreqAI enabled strategies*
Required function to set the targets for the model. Required function to set the targets for the model.
@ -701,7 +704,8 @@ class IStrategy(ABC, HyperStrategyMixin):
https://www.freqtrade.io/en/latest/freqai-feature-engineering 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"] usage example: dataframe["&-target"] = dataframe["close"].shift(-1) / dataframe["close"]
""" """
return dataframe return dataframe

View File

@ -1,4 +1,5 @@
import logging import logging
from typing import Dict
import numpy as np import numpy as np
import pandas as pd 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) 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) 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* *Only functional with FreqAI enabled strategies*
This function will automatically expand the defined features on the config defined 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 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 period: period of the indicator - usage example:
:param metadata: metadata of current pair
dataframe["%-ema-period"] = ta.EMA(dataframe, timeperiod=period) dataframe["%-ema-period"] = ta.EMA(dataframe, timeperiod=period)
""" """
@ -148,7 +151,7 @@ class FreqaiExampleHybridStrategy(IStrategy):
return dataframe 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* *Only functional with FreqAI enabled strategies*
This function will automatically expand the defined features on the config defined 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 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["%-pct-change"] = dataframe["close"].pct_change()
dataframe["%-ema-200"] = ta.EMA(dataframe, timeperiod=200) dataframe["%-ema-200"] = ta.EMA(dataframe, timeperiod=200)
""" """
@ -179,7 +183,7 @@ class FreqaiExampleHybridStrategy(IStrategy):
dataframe["%-raw_price"] = dataframe["close"] dataframe["%-raw_price"] = dataframe["close"]
return dataframe 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* *Only functional with FreqAI enabled strategies*
This optional function will be called once with the dataframe of the base timeframe. 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 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 usage example: dataframe["%-day_of_week"] = (dataframe["date"].dt.dayofweek + 1) / 7
""" """
dataframe["%-day_of_week"] = dataframe["date"].dt.dayofweek dataframe["%-day_of_week"] = dataframe["date"].dt.dayofweek
dataframe["%-hour_of_day"] = dataframe["date"].dt.hour dataframe["%-hour_of_day"] = dataframe["date"].dt.hour
return dataframe 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* *Only functional with FreqAI enabled strategies*
Required function to set the targets for the model. 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 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"] usage example: dataframe["&-target"] = dataframe["close"].shift(-1) / dataframe["close"]
""" """
dataframe['&s-up_or_down'] = np.where(dataframe["close"].shift(-50) > dataframe['&s-up_or_down'] = np.where(dataframe["close"].shift(-50) >

View File

@ -1,5 +1,6 @@
import logging import logging
from functools import reduce from functools import reduce
from typing import Dict
import talib.abstract as ta import talib.abstract as ta
from pandas import DataFrame from pandas import DataFrame
@ -46,7 +47,8 @@ class FreqaiExampleStrategy(IStrategy):
std_dev_multiplier_sell = CategoricalParameter( std_dev_multiplier_sell = CategoricalParameter(
[0.75, 1, 1.25, 1.5, 1.75], space="sell", default=1.25, optimize=True) [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: DataFrame, period: int,
metadata: Dict, **kwargs):
""" """
*Only functional with FreqAI enabled strategies* *Only functional with FreqAI enabled strategies*
This function will automatically expand the defined features on the config defined This function will automatically expand the defined features on the config defined
@ -58,6 +60,10 @@ class FreqaiExampleStrategy(IStrategy):
All features must be prepended with `%` to be recognized by FreqAI internals. 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 More details on how these config defined parameters accelerate feature engineering
in the documentation at: in the documentation at:
@ -65,8 +71,9 @@ class FreqaiExampleStrategy(IStrategy):
https://www.freqtrade.io/en/latest/freqai-feature-engineering/#defining-the-features 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 period: period of the indicator - usage example:
:param metadata: metadata of current pair
dataframe["%-ema-period"] = ta.EMA(dataframe, timeperiod=period) dataframe["%-ema-period"] = ta.EMA(dataframe, timeperiod=period)
""" """
@ -99,7 +106,7 @@ class FreqaiExampleStrategy(IStrategy):
return dataframe 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* *Only functional with FreqAI enabled strategies*
This function will automatically expand the defined features on the config defined This function will automatically expand the defined features on the config defined
@ -114,6 +121,10 @@ class FreqaiExampleStrategy(IStrategy):
All features must be prepended with `%` to be recognized by FreqAI internals. 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 More details on how these config defined parameters accelerate feature engineering
in the documentation at: in the documentation at:
@ -121,7 +132,8 @@ class FreqaiExampleStrategy(IStrategy):
https://www.freqtrade.io/en/latest/freqai-feature-engineering/#defining-the-features 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["%-pct-change"] = dataframe["close"].pct_change()
dataframe["%-ema-200"] = ta.EMA(dataframe, timeperiod=200) dataframe["%-ema-200"] = ta.EMA(dataframe, timeperiod=200)
""" """
@ -130,7 +142,7 @@ class FreqaiExampleStrategy(IStrategy):
dataframe["%-raw_price"] = dataframe["close"] dataframe["%-raw_price"] = dataframe["close"]
return dataframe 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* *Only functional with FreqAI enabled strategies*
This optional function will be called once with the dataframe of the base timeframe. This optional function will be called once with the dataframe of the base timeframe.
@ -144,28 +156,38 @@ class FreqaiExampleStrategy(IStrategy):
All features must be prepended with `%` to be recognized by FreqAI internals. 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: More details about feature engineering available:
https://www.freqtrade.io/en/latest/freqai-feature-engineering 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 usage example: dataframe["%-day_of_week"] = (dataframe["date"].dt.dayofweek + 1) / 7
""" """
dataframe["%-day_of_week"] = dataframe["date"].dt.dayofweek dataframe["%-day_of_week"] = dataframe["date"].dt.dayofweek
dataframe["%-hour_of_day"] = dataframe["date"].dt.hour dataframe["%-hour_of_day"] = dataframe["date"].dt.hour
return dataframe 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* *Only functional with FreqAI enabled strategies*
Required function to set the targets for the model. Required function to set the targets for the model.
All targets must be prepended with `&` to be recognized by the FreqAI internals. 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: More details about feature engineering available:
https://www.freqtrade.io/en/latest/freqai-feature-engineering 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"] usage example: dataframe["&-target"] = dataframe["close"].shift(-1) / dataframe["close"]
""" """
dataframe["&-s_close"] = ( dataframe["&-s_close"] = (

View File

@ -1,5 +1,6 @@
import logging import logging
from functools import reduce from functools import reduce
from typing import Dict
import talib.abstract as ta import talib.abstract as ta
from pandas import DataFrame from pandas import DataFrame
@ -24,20 +25,21 @@ class freqai_rl_test_strat(IStrategy):
startup_candle_count: int = 300 startup_candle_count: int = 300
can_short = False 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) dataframe["%-rsi-period"] = ta.RSI(dataframe, timeperiod=period)
return dataframe 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["%-pct-change"] = dataframe["close"].pct_change()
dataframe["%-raw_volume"] = dataframe["volume"] dataframe["%-raw_volume"] = dataframe["volume"]
return dataframe 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["%-day_of_week"] = dataframe["date"].dt.dayofweek
dataframe["%-hour_of_day"] = dataframe["date"].dt.hour dataframe["%-hour_of_day"] = dataframe["date"].dt.hour
@ -49,7 +51,7 @@ class freqai_rl_test_strat(IStrategy):
return dataframe return dataframe
def set_freqai_targets(self, dataframe, **kwargs): def set_freqai_targets(self, dataframe: DataFrame, metadata: Dict, **kwargs):
dataframe["&-action"] = 0 dataframe["&-action"] = 0

View File

@ -1,5 +1,6 @@
import logging import logging
from functools import reduce from functools import reduce
from typing import Dict
import numpy as np import numpy as np
import talib.abstract as ta import talib.abstract as ta
@ -56,7 +57,8 @@ class freqai_test_classifier(IStrategy):
informative_pairs.append((pair, tf)) informative_pairs.append((pair, tf))
return informative_pairs 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["%-rsi-period"] = ta.RSI(dataframe, timeperiod=period)
dataframe["%-mfi-period"] = ta.MFI(dataframe, timeperiod=period) dataframe["%-mfi-period"] = ta.MFI(dataframe, timeperiod=period)
@ -64,7 +66,7 @@ class freqai_test_classifier(IStrategy):
return dataframe 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["%-pct-change"] = dataframe["close"].pct_change()
dataframe["%-raw_volume"] = dataframe["volume"] dataframe["%-raw_volume"] = dataframe["volume"]
@ -72,14 +74,14 @@ class freqai_test_classifier(IStrategy):
return dataframe 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["%-day_of_week"] = dataframe["date"].dt.dayofweek
dataframe["%-hour_of_day"] = dataframe["date"].dt.hour dataframe["%-hour_of_day"] = dataframe["date"].dt.hour
return dataframe 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['&s-up_or_down'] = np.where(dataframe["close"].shift(-100) >
dataframe["close"], 'up', 'down') dataframe["close"], 'up', 'down')

View File

@ -1,5 +1,6 @@
import logging import logging
from functools import reduce from functools import reduce
from typing import Dict
import numpy as np import numpy as np
import talib.abstract as ta 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) 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["%-rsi-period"] = ta.RSI(dataframe, timeperiod=period)
dataframe["%-mfi-period"] = ta.MFI(dataframe, timeperiod=period) dataframe["%-mfi-period"] = ta.MFI(dataframe, timeperiod=period)
@ -51,7 +53,7 @@ class freqai_test_multimodel_classifier_strat(IStrategy):
return dataframe 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["%-pct-change"] = dataframe["close"].pct_change()
dataframe["%-raw_volume"] = dataframe["volume"] dataframe["%-raw_volume"] = dataframe["volume"]
@ -59,14 +61,14 @@ class freqai_test_multimodel_classifier_strat(IStrategy):
return dataframe 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["%-day_of_week"] = dataframe["date"].dt.dayofweek
dataframe["%-hour_of_day"] = dataframe["date"].dt.hour dataframe["%-hour_of_day"] = dataframe["date"].dt.hour
return dataframe 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['&s-up_or_down'] = np.where(dataframe["close"].shift(-50) >
dataframe["close"], 'up', 'down') dataframe["close"], 'up', 'down')

View File

@ -1,5 +1,6 @@
import logging import logging
from functools import reduce from functools import reduce
from typing import Dict
import talib.abstract as ta import talib.abstract as ta
from pandas import DataFrame 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) 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["%-rsi-period"] = ta.RSI(dataframe, timeperiod=period)
dataframe["%-mfi-period"] = ta.MFI(dataframe, timeperiod=period) dataframe["%-mfi-period"] = ta.MFI(dataframe, timeperiod=period)
@ -50,7 +52,7 @@ class freqai_test_multimodel_strat(IStrategy):
return dataframe 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["%-pct-change"] = dataframe["close"].pct_change()
dataframe["%-raw_volume"] = dataframe["volume"] dataframe["%-raw_volume"] = dataframe["volume"]
@ -58,14 +60,14 @@ class freqai_test_multimodel_strat(IStrategy):
return dataframe 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["%-day_of_week"] = dataframe["date"].dt.dayofweek
dataframe["%-hour_of_day"] = dataframe["date"].dt.hour dataframe["%-hour_of_day"] = dataframe["date"].dt.hour
return dataframe return dataframe
def set_freqai_targets(self, dataframe, **kwargs): def set_freqai_targets(self, dataframe: DataFrame, metadata: Dict, **kwargs):
dataframe["&-s_close"] = ( dataframe["&-s_close"] = (
dataframe["close"] dataframe["close"]

View File

@ -1,5 +1,6 @@
import logging import logging
from functools import reduce from functools import reduce
from typing import Dict
import talib.abstract as ta import talib.abstract as ta
from pandas import DataFrame 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) 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["%-rsi-period"] = ta.RSI(dataframe, timeperiod=period)
dataframe["%-mfi-period"] = ta.MFI(dataframe, timeperiod=period) dataframe["%-mfi-period"] = ta.MFI(dataframe, timeperiod=period)
@ -50,7 +52,7 @@ class freqai_test_strat(IStrategy):
return dataframe 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["%-pct-change"] = dataframe["close"].pct_change()
dataframe["%-raw_volume"] = dataframe["volume"] dataframe["%-raw_volume"] = dataframe["volume"]
@ -58,14 +60,14 @@ class freqai_test_strat(IStrategy):
return dataframe 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["%-day_of_week"] = dataframe["date"].dt.dayofweek
dataframe["%-hour_of_day"] = dataframe["date"].dt.hour dataframe["%-hour_of_day"] = dataframe["date"].dt.hour
return dataframe return dataframe
def set_freqai_targets(self, dataframe, **kwargs): def set_freqai_targets(self, dataframe: DataFrame, metadata: Dict, **kwargs):
dataframe["&-s_close"] = ( dataframe["&-s_close"] = (
dataframe["close"] dataframe["close"]