Move "freqai.lock" to backend to simplify user interface

This commit is contained in:
Matthias 2022-08-14 17:19:50 +02:00
parent a5e96881f4
commit 3a9ec76c91
6 changed files with 323 additions and 331 deletions

View File

@ -177,8 +177,6 @@ The user interface is isolated to the typical config file. A typical FreqAI conf
Features are added by the user inside the `populate_any_indicators()` method of the strategy Features are added by the user inside the `populate_any_indicators()` method of the strategy
by prepending indicators with `%` and labels are added by prepending `&`. by prepending indicators with `%` and labels are added by prepending `&`.
There are some important components/structures that the user *must* include when building their feature set. There are some important components/structures that the user *must* include when building their feature set.
As shown below, `with self.freqai.lock:` must be used to ensure thread safety - especially when using third
party libraries for indicator construction such as TA-lib.
Another structure to consider is the location of the labels at the bottom of the example function (below `if set_generalized_indicators:`). Another structure to consider is the location of the labels at the bottom of the example function (below `if set_generalized_indicators:`).
This is where the user will add single features and labels to their feature set to avoid duplication from This is where the user will add single features and labels to their feature set to avoid duplication from
various configuration parameters which multiply the feature set such as `include_timeframes`. various configuration parameters which multiply the feature set such as `include_timeframes`.
@ -203,69 +201,68 @@ various configuration parameters which multiply the feature set such as `include
coint = pair.split('/')[0] coint = pair.split('/')[0]
with self.freqai.lock: if informative is None:
if informative is None: informative = self.dp.get_pair_dataframe(pair, tf)
informative = self.dp.get_pair_dataframe(pair, tf)
# first loop is automatically duplicating indicators for time periods # first loop is automatically duplicating indicators for time periods
for t in self.freqai_info["feature_parameters"]["indicator_periods_candles"]: for t in self.freqai_info["feature_parameters"]["indicator_periods_candles"]:
t = int(t) t = int(t)
informative[f"%-{coin}rsi-period_{t}"] = ta.RSI(informative, timeperiod=t) informative[f"%-{coin}rsi-period_{t}"] = ta.RSI(informative, timeperiod=t)
informative[f"%-{coin}mfi-period_{t}"] = ta.MFI(informative, timeperiod=t) informative[f"%-{coin}mfi-period_{t}"] = ta.MFI(informative, timeperiod=t)
informative[f"%-{coin}adx-period_{t}"] = ta.ADX(informative, window=t) informative[f"%-{coin}adx-period_{t}"] = ta.ADX(informative, window=t)
bollinger = qtpylib.bollinger_bands( bollinger = qtpylib.bollinger_bands(
qtpylib.typical_price(informative), window=t, stds=2.2 qtpylib.typical_price(informative), window=t, stds=2.2
) )
informative[f"{coin}bb_lowerband-period_{t}"] = bollinger["lower"] informative[f"{coin}bb_lowerband-period_{t}"] = bollinger["lower"]
informative[f"{coin}bb_middleband-period_{t}"] = bollinger["mid"] informative[f"{coin}bb_middleband-period_{t}"] = bollinger["mid"]
informative[f"{coin}bb_upperband-period_{t}"] = bollinger["upper"] informative[f"{coin}bb_upperband-period_{t}"] = bollinger["upper"]
informative[f"%-{coin}bb_width-period_{t}"] = ( informative[f"%-{coin}bb_width-period_{t}"] = (
informative[f"{coin}bb_upperband-period_{t}"] informative[f"{coin}bb_upperband-period_{t}"]
- informative[f"{coin}bb_lowerband-period_{t}"] - informative[f"{coin}bb_lowerband-period_{t}"]
) / informative[f"{coin}bb_middleband-period_{t}"] ) / informative[f"{coin}bb_middleband-period_{t}"]
informative[f"%-{coin}close-bb_lower-period_{t}"] = ( informative[f"%-{coin}close-bb_lower-period_{t}"] = (
informative["close"] / informative[f"{coin}bb_lowerband-period_{t}"] informative["close"] / informative[f"{coin}bb_lowerband-period_{t}"]
) )
informative[f"%-{coin}relative_volume-period_{t}"] = ( informative[f"%-{coin}relative_volume-period_{t}"] = (
informative["volume"] / informative["volume"].rolling(t).mean() informative["volume"] / informative["volume"].rolling(t).mean()
) )
indicators = [col for col in informative if col.startswith("%")] indicators = [col for col in informative if col.startswith("%")]
# This loop duplicates and shifts all indicators to add a sense of recency to data # This loop duplicates and shifts all indicators to add a sense of recency to data
for n in range(self.freqai_info["feature_parameters"]["include_shifted_candles"] + 1): for n in range(self.freqai_info["feature_parameters"]["include_shifted_candles"] + 1):
if n == 0: if n == 0:
continue continue
informative_shift = informative[indicators].shift(n) informative_shift = informative[indicators].shift(n)
informative_shift = informative_shift.add_suffix("_shift-" + str(n)) informative_shift = informative_shift.add_suffix("_shift-" + str(n))
informative = pd.concat((informative, informative_shift), axis=1) informative = pd.concat((informative, informative_shift), axis=1)
df = merge_informative_pair(df, informative, self.config["timeframe"], tf, ffill=True) df = merge_informative_pair(df, informative, self.config["timeframe"], tf, ffill=True)
skip_columns = [ skip_columns = [
(s + "_" + tf) for s in ["date", "open", "high", "low", "close", "volume"] (s + "_" + tf) for s in ["date", "open", "high", "low", "close", "volume"]
] ]
df = df.drop(columns=skip_columns) df = df.drop(columns=skip_columns)
# Add generalized indicators here (because in live, it will call this # Add generalized indicators here (because in live, it will call this
# function to populate indicators during training). Notice how we ensure not to # function to populate indicators during training). Notice how we ensure not to
# add them multiple times # add them multiple times
if set_generalized_indicators: if set_generalized_indicators:
df["%-day_of_week"] = (df["date"].dt.dayofweek + 1) / 7 df["%-day_of_week"] = (df["date"].dt.dayofweek + 1) / 7
df["%-hour_of_day"] = (df["date"].dt.hour + 1) / 25 df["%-hour_of_day"] = (df["date"].dt.hour + 1) / 25
# user adds targets here by prepending them with &- (see convention below) # user adds targets here by prepending them with &- (see convention below)
# If user wishes to use multiple targets, a multioutput prediction model # If user wishes to use multiple targets, a multioutput prediction model
# needs to be used such as templates/CatboostPredictionMultiModel.py # needs to be used such as templates/CatboostPredictionMultiModel.py
df["&-s_close"] = ( df["&-s_close"] = (
df["close"] df["close"]
.shift(-self.freqai_info["feature_parameters"]["label_period_candles"]) .shift(-self.freqai_info["feature_parameters"]["label_period_candles"])
.rolling(self.freqai_info["feature_parameters"]["label_period_candles"]) .rolling(self.freqai_info["feature_parameters"]["label_period_candles"])
.mean() .mean()
/ df["close"] / df["close"]
- 1 - 1
) )
return df return df
``` ```
@ -430,48 +427,47 @@ The FreqAI strategy requires the user to include the following lines of code in
coin = pair.split('/')[0] coin = pair.split('/')[0]
with self.freqai.lock: if informative is None:
if informative is None: informative = self.dp.get_pair_dataframe(pair, tf)
informative = self.dp.get_pair_dataframe(pair, tf)
# first loop is automatically duplicating indicators for time periods # first loop is automatically duplicating indicators for time periods
for t in self.freqai_info["feature_parameters"]["indicator_periods_candles"]: for t in self.freqai_info["feature_parameters"]["indicator_periods_candles"]:
t = int(t) t = int(t)
informative[f"%-{coin}rsi-period_{t}"] = ta.RSI(informative, timeperiod=t) informative[f"%-{coin}rsi-period_{t}"] = ta.RSI(informative, timeperiod=t)
informative[f"%-{coin}mfi-period_{t}"] = ta.MFI(informative, timeperiod=t) informative[f"%-{coin}mfi-period_{t}"] = ta.MFI(informative, timeperiod=t)
informative[f"%-{coin}adx-period_{t}"] = ta.ADX(informative, window=t) informative[f"%-{coin}adx-period_{t}"] = ta.ADX(informative, window=t)
indicators = [col for col in informative if col.startswith("%")] indicators = [col for col in informative if col.startswith("%")]
# This loop duplicates and shifts all indicators to add a sense of recency to data # This loop duplicates and shifts all indicators to add a sense of recency to data
for n in range(self.freqai_info["feature_parameters"]["include_shifted_candles"] + 1): for n in range(self.freqai_info["feature_parameters"]["include_shifted_candles"] + 1):
if n == 0: if n == 0:
continue continue
informative_shift = informative[indicators].shift(n) informative_shift = informative[indicators].shift(n)
informative_shift = informative_shift.add_suffix("_shift-" + str(n)) informative_shift = informative_shift.add_suffix("_shift-" + str(n))
informative = pd.concat((informative, informative_shift), axis=1) informative = pd.concat((informative, informative_shift), axis=1)
df = merge_informative_pair(df, informative, self.config["timeframe"], tf, ffill=True) df = merge_informative_pair(df, informative, self.config["timeframe"], tf, ffill=True)
skip_columns = [ skip_columns = [
(s + "_" + tf) for s in ["date", "open", "high", "low", "close", "volume"] (s + "_" + tf) for s in ["date", "open", "high", "low", "close", "volume"]
] ]
df = df.drop(columns=skip_columns) df = df.drop(columns=skip_columns)
# Add generalized indicators here (because in live, it will call this # Add generalized indicators here (because in live, it will call this
# function to populate indicators during training). Notice how we ensure not to # function to populate indicators during training). Notice how we ensure not to
# add them multiple times # add them multiple times
if set_generalized_indicators: if set_generalized_indicators:
# user adds targets here by prepending them with &- (see convention below) # user adds targets here by prepending them with &- (see convention below)
# If user wishes to use multiple targets, a multioutput prediction model # If user wishes to use multiple targets, a multioutput prediction model
# needs to be used such as templates/CatboostPredictionMultiModel.py # needs to be used such as templates/CatboostPredictionMultiModel.py
df["&-s_close"] = ( df["&-s_close"] = (
df["close"] df["close"]
.shift(-self.freqai_info["feature_parameters"]["label_period_candles"]) .shift(-self.freqai_info["feature_parameters"]["label_period_candles"])
.rolling(self.freqai_info["feature_parameters"]["label_period_candles"]) .rolling(self.freqai_info["feature_parameters"]["label_period_candles"])
.mean() .mean()
/ df["close"] / df["close"]
- 1 - 1
) )
return df return df

View File

@ -961,23 +961,25 @@ class FreqaiDataKitchen:
for tf in tfs: for tf in tfs:
if tf == tfs[-1]: if tf == tfs[-1]:
sgi = True # doing this last allows user to use all tf raw prices in labels sgi = True # doing this last allows user to use all tf raw prices in labels
dataframe = strategy.populate_any_indicators( with strategy.freqai.lock:
pair, dataframe = strategy.populate_any_indicators(
dataframe.copy(), pair,
tf, dataframe.copy(),
informative=base_dataframes[tf], tf,
set_generalized_indicators=sgi informative=base_dataframes[tf],
) set_generalized_indicators=sgi
if pairs: )
for i in pairs: with strategy.freqai.lock:
if pair in i: if pairs:
continue # dont repeat anything from whitelist for i in pairs:
dataframe = strategy.populate_any_indicators( if pair in i:
i, continue # dont repeat anything from whitelist
dataframe.copy(), dataframe = strategy.populate_any_indicators(
tf, i,
informative=corr_dataframes[i][tf] dataframe.copy(),
) tf,
informative=corr_dataframes[i][tf]
)
self.get_unique_classes_from_labels(dataframe) self.get_unique_classes_from_labels(dataframe)

View File

@ -82,99 +82,98 @@ class FreqaiExampleStrategy(IStrategy):
coin = pair.split('/')[0] coin = pair.split('/')[0]
with self.freqai.lock: if informative is None:
if informative is None: informative = self.dp.get_pair_dataframe(pair, tf)
informative = self.dp.get_pair_dataframe(pair, tf)
# first loop is automatically duplicating indicators for time periods # first loop is automatically duplicating indicators for time periods
for t in self.freqai_info["feature_parameters"]["indicator_periods_candles"]: for t in self.freqai_info["feature_parameters"]["indicator_periods_candles"]:
t = int(t) t = int(t)
informative[f"%-{coin}rsi-period_{t}"] = ta.RSI(informative, timeperiod=t) informative[f"%-{coin}rsi-period_{t}"] = ta.RSI(informative, timeperiod=t)
informative[f"%-{coin}mfi-period_{t}"] = ta.MFI(informative, timeperiod=t) informative[f"%-{coin}mfi-period_{t}"] = ta.MFI(informative, timeperiod=t)
informative[f"%-{coin}adx-period_{t}"] = ta.ADX(informative, window=t) informative[f"%-{coin}adx-period_{t}"] = ta.ADX(informative, window=t)
informative[f"%-{coin}sma-period_{t}"] = ta.SMA(informative, timeperiod=t) informative[f"%-{coin}sma-period_{t}"] = ta.SMA(informative, timeperiod=t)
informative[f"%-{coin}ema-period_{t}"] = ta.EMA(informative, timeperiod=t) informative[f"%-{coin}ema-period_{t}"] = ta.EMA(informative, timeperiod=t)
informative[f"%-{coin}mfi-period_{t}"] = ta.MFI(informative, timeperiod=t) informative[f"%-{coin}mfi-period_{t}"] = ta.MFI(informative, timeperiod=t)
bollinger = qtpylib.bollinger_bands( bollinger = qtpylib.bollinger_bands(
qtpylib.typical_price(informative), window=t, stds=2.2 qtpylib.typical_price(informative), window=t, stds=2.2
) )
informative[f"{coin}bb_lowerband-period_{t}"] = bollinger["lower"] informative[f"{coin}bb_lowerband-period_{t}"] = bollinger["lower"]
informative[f"{coin}bb_middleband-period_{t}"] = bollinger["mid"] informative[f"{coin}bb_middleband-period_{t}"] = bollinger["mid"]
informative[f"{coin}bb_upperband-period_{t}"] = bollinger["upper"] informative[f"{coin}bb_upperband-period_{t}"] = bollinger["upper"]
informative[f"%-{coin}bb_width-period_{t}"] = ( informative[f"%-{coin}bb_width-period_{t}"] = (
informative[f"{coin}bb_upperband-period_{t}"] informative[f"{coin}bb_upperband-period_{t}"]
- informative[f"{coin}bb_lowerband-period_{t}"] - informative[f"{coin}bb_lowerband-period_{t}"]
) / informative[f"{coin}bb_middleband-period_{t}"] ) / informative[f"{coin}bb_middleband-period_{t}"]
informative[f"%-{coin}close-bb_lower-period_{t}"] = ( informative[f"%-{coin}close-bb_lower-period_{t}"] = (
informative["close"] / informative[f"{coin}bb_lowerband-period_{t}"] informative["close"] / informative[f"{coin}bb_lowerband-period_{t}"]
) )
informative[f"%-{coin}roc-period_{t}"] = ta.ROC(informative, timeperiod=t) informative[f"%-{coin}roc-period_{t}"] = ta.ROC(informative, timeperiod=t)
informative[f"%-{coin}relative_volume-period_{t}"] = ( informative[f"%-{coin}relative_volume-period_{t}"] = (
informative["volume"] / informative["volume"].rolling(t).mean() informative["volume"] / informative["volume"].rolling(t).mean()
) )
informative[f"%-{coin}pct-change"] = informative["close"].pct_change() informative[f"%-{coin}pct-change"] = informative["close"].pct_change()
informative[f"%-{coin}raw_volume"] = informative["volume"] informative[f"%-{coin}raw_volume"] = informative["volume"]
informative[f"%-{coin}raw_price"] = informative["close"] informative[f"%-{coin}raw_price"] = informative["close"]
indicators = [col for col in informative if col.startswith("%")] indicators = [col for col in informative if col.startswith("%")]
# This loop duplicates and shifts all indicators to add a sense of recency to data # This loop duplicates and shifts all indicators to add a sense of recency to data
for n in range(self.freqai_info["feature_parameters"]["include_shifted_candles"] + 1): for n in range(self.freqai_info["feature_parameters"]["include_shifted_candles"] + 1):
if n == 0: if n == 0:
continue continue
informative_shift = informative[indicators].shift(n) informative_shift = informative[indicators].shift(n)
informative_shift = informative_shift.add_suffix("_shift-" + str(n)) informative_shift = informative_shift.add_suffix("_shift-" + str(n))
informative = pd.concat((informative, informative_shift), axis=1) informative = pd.concat((informative, informative_shift), axis=1)
df = merge_informative_pair(df, informative, self.config["timeframe"], tf, ffill=True) df = merge_informative_pair(df, informative, self.config["timeframe"], tf, ffill=True)
skip_columns = [ skip_columns = [
(s + "_" + tf) for s in ["date", "open", "high", "low", "close", "volume"] (s + "_" + tf) for s in ["date", "open", "high", "low", "close", "volume"]
] ]
df = df.drop(columns=skip_columns) df = df.drop(columns=skip_columns)
# Add generalized indicators here (because in live, it will call this # Add generalized indicators here (because in live, it will call this
# function to populate indicators during training). Notice how we ensure not to # function to populate indicators during training). Notice how we ensure not to
# add them multiple times # add them multiple times
if set_generalized_indicators: if set_generalized_indicators:
df["%-day_of_week"] = (df["date"].dt.dayofweek + 1) / 7 df["%-day_of_week"] = (df["date"].dt.dayofweek + 1) / 7
df["%-hour_of_day"] = (df["date"].dt.hour + 1) / 25 df["%-hour_of_day"] = (df["date"].dt.hour + 1) / 25
# user adds targets here by prepending them with &- (see convention below) # user adds targets here by prepending them with &- (see convention below)
df["&-s_close"] = ( df["&-s_close"] = (
df["close"] df["close"]
.shift(-self.freqai_info["feature_parameters"]["label_period_candles"]) .shift(-self.freqai_info["feature_parameters"]["label_period_candles"])
.rolling(self.freqai_info["feature_parameters"]["label_period_candles"]) .rolling(self.freqai_info["feature_parameters"]["label_period_candles"])
.mean() .mean()
/ df["close"] / df["close"]
- 1 - 1
) )
# Classifiers are typically set up with strings as targets: # Classifiers are typically set up with strings as targets:
# df['&s-up_or_down'] = np.where( df["close"].shift(-100) > # df['&s-up_or_down'] = np.where( df["close"].shift(-100) >
# df["close"], 'up', 'down') # df["close"], 'up', 'down')
# If user wishes to use multiple targets, they can add more by # If user wishes to use multiple targets, they can add more by
# appending more columns with '&'. User should keep in mind that multi targets # appending more columns with '&'. User should keep in mind that multi targets
# requires a multioutput prediction model such as # requires a multioutput prediction model such as
# templates/CatboostPredictionMultiModel.py, # templates/CatboostPredictionMultiModel.py,
# df["&-s_range"] = ( # df["&-s_range"] = (
# df["close"] # df["close"]
# .shift(-self.freqai_info["feature_parameters"]["label_period_candles"]) # .shift(-self.freqai_info["feature_parameters"]["label_period_candles"])
# .rolling(self.freqai_info["feature_parameters"]["label_period_candles"]) # .rolling(self.freqai_info["feature_parameters"]["label_period_candles"])
# .max() # .max()
# - # -
# df["close"] # df["close"]
# .shift(-self.freqai_info["feature_parameters"]["label_period_candles"]) # .shift(-self.freqai_info["feature_parameters"]["label_period_candles"])
# .rolling(self.freqai_info["feature_parameters"]["label_period_candles"]) # .rolling(self.freqai_info["feature_parameters"]["label_period_candles"])
# .min() # .min()
# ) # )
return df return df
@ -252,12 +251,11 @@ class FreqaiExampleStrategy(IStrategy):
"prediction" + entry_tag not in pair_dict[pair] "prediction" + entry_tag not in pair_dict[pair]
or pair_dict[pair]['extras']["prediction" + entry_tag] == 0 or pair_dict[pair]['extras']["prediction" + entry_tag] == 0
): ):
with self.freqai.lock: pair_dict[pair]['extras']["prediction" + entry_tag] = abs(trade_candle["&-s_close"])
pair_dict[pair]['extras']["prediction" + entry_tag] = abs(trade_candle["&-s_close"]) if not follow_mode:
if not follow_mode: self.freqai.dd.save_drawer_to_disk()
self.freqai.dd.save_drawer_to_disk() else:
else: self.freqai.dd.save_follower_dict_to_disk()
self.freqai.dd.save_follower_dict_to_disk()
roi_price = pair_dict[pair]['extras']["prediction" + entry_tag] roi_price = pair_dict[pair]['extras']["prediction" + entry_tag]
roi_time = self.max_roi_time_long.value roi_time = self.max_roi_time_long.value
@ -296,12 +294,11 @@ class FreqaiExampleStrategy(IStrategy):
else: else:
pair_dict = self.freqai.dd.follower_dict pair_dict = self.freqai.dd.follower_dict
with self.freqai.lock: pair_dict[pair]['extras']["prediction" + entry_tag] = 0
pair_dict[pair]['extras']["prediction" + entry_tag] = 0 if not follow_mode:
if not follow_mode: self.freqai.dd.save_drawer_to_disk()
self.freqai.dd.save_drawer_to_disk() else:
else: self.freqai.dd.save_follower_dict_to_disk()
self.freqai.dd.save_follower_dict_to_disk()
return True return True

View File

@ -63,48 +63,47 @@ class freqai_test_classifier(IStrategy):
coin = pair.split('/')[0] coin = pair.split('/')[0]
with self.freqai.lock: if informative is None:
if informative is None: informative = self.dp.get_pair_dataframe(pair, tf)
informative = self.dp.get_pair_dataframe(pair, tf)
# first loop is automatically duplicating indicators for time periods # first loop is automatically duplicating indicators for time periods
for t in self.freqai_info["feature_parameters"]["indicator_periods_candles"]: for t in self.freqai_info["feature_parameters"]["indicator_periods_candles"]:
t = int(t) t = int(t)
informative[f"%-{coin}rsi-period_{t}"] = ta.RSI(informative, timeperiod=t) informative[f"%-{coin}rsi-period_{t}"] = ta.RSI(informative, timeperiod=t)
informative[f"%-{coin}mfi-period_{t}"] = ta.MFI(informative, timeperiod=t) informative[f"%-{coin}mfi-period_{t}"] = ta.MFI(informative, timeperiod=t)
informative[f"%-{coin}adx-period_{t}"] = ta.ADX(informative, window=t) informative[f"%-{coin}adx-period_{t}"] = ta.ADX(informative, window=t)
informative[f"%-{coin}pct-change"] = informative["close"].pct_change() informative[f"%-{coin}pct-change"] = informative["close"].pct_change()
informative[f"%-{coin}raw_volume"] = informative["volume"] informative[f"%-{coin}raw_volume"] = informative["volume"]
informative[f"%-{coin}raw_price"] = informative["close"] informative[f"%-{coin}raw_price"] = informative["close"]
indicators = [col for col in informative if col.startswith("%")] indicators = [col for col in informative if col.startswith("%")]
# This loop duplicates and shifts all indicators to add a sense of recency to data # This loop duplicates and shifts all indicators to add a sense of recency to data
for n in range(self.freqai_info["feature_parameters"]["include_shifted_candles"] + 1): for n in range(self.freqai_info["feature_parameters"]["include_shifted_candles"] + 1):
if n == 0: if n == 0:
continue continue
informative_shift = informative[indicators].shift(n) informative_shift = informative[indicators].shift(n)
informative_shift = informative_shift.add_suffix("_shift-" + str(n)) informative_shift = informative_shift.add_suffix("_shift-" + str(n))
informative = pd.concat((informative, informative_shift), axis=1) informative = pd.concat((informative, informative_shift), axis=1)
df = merge_informative_pair(df, informative, self.config["timeframe"], tf, ffill=True) df = merge_informative_pair(df, informative, self.config["timeframe"], tf, ffill=True)
skip_columns = [ skip_columns = [
(s + "_" + tf) for s in ["date", "open", "high", "low", "close", "volume"] (s + "_" + tf) for s in ["date", "open", "high", "low", "close", "volume"]
] ]
df = df.drop(columns=skip_columns) df = df.drop(columns=skip_columns)
# Add generalized indicators here (because in live, it will call this # Add generalized indicators here (because in live, it will call this
# function to populate indicators during training). Notice how we ensure not to # function to populate indicators during training). Notice how we ensure not to
# add them multiple times # add them multiple times
if set_generalized_indicators: if set_generalized_indicators:
df["%-day_of_week"] = (df["date"].dt.dayofweek + 1) / 7 df["%-day_of_week"] = (df["date"].dt.dayofweek + 1) / 7
df["%-hour_of_day"] = (df["date"].dt.hour + 1) / 25 df["%-hour_of_day"] = (df["date"].dt.hour + 1) / 25
# user adds targets here by prepending them with &- (see convention below) # user adds targets here by prepending them with &- (see convention below)
# If user wishes to use multiple targets, a multioutput prediction model # If user wishes to use multiple targets, a multioutput prediction model
# needs to be used such as templates/CatboostPredictionMultiModel.py # needs to be used such as templates/CatboostPredictionMultiModel.py
df['&s-up_or_down'] = np.where(df["close"].shift(-100) > df["close"], 'up', 'down') df['&s-up_or_down'] = np.where(df["close"].shift(-100) > df["close"], 'up', 'down')
return df return df

View File

@ -62,67 +62,66 @@ class freqai_test_multimodel_strat(IStrategy):
coin = pair.split('/')[0] coin = pair.split('/')[0]
with self.freqai.lock: if informative is None:
if informative is None: informative = self.dp.get_pair_dataframe(pair, tf)
informative = self.dp.get_pair_dataframe(pair, tf)
# first loop is automatically duplicating indicators for time periods # first loop is automatically duplicating indicators for time periods
for t in self.freqai_info["feature_parameters"]["indicator_periods_candles"]: for t in self.freqai_info["feature_parameters"]["indicator_periods_candles"]:
t = int(t) t = int(t)
informative[f"%-{coin}rsi-period_{t}"] = ta.RSI(informative, timeperiod=t) informative[f"%-{coin}rsi-period_{t}"] = ta.RSI(informative, timeperiod=t)
informative[f"%-{coin}mfi-period_{t}"] = ta.MFI(informative, timeperiod=t) informative[f"%-{coin}mfi-period_{t}"] = ta.MFI(informative, timeperiod=t)
informative[f"%-{coin}adx-period_{t}"] = ta.ADX(informative, window=t) informative[f"%-{coin}adx-period_{t}"] = ta.ADX(informative, window=t)
informative[f"%-{coin}pct-change"] = informative["close"].pct_change() informative[f"%-{coin}pct-change"] = informative["close"].pct_change()
informative[f"%-{coin}raw_volume"] = informative["volume"] informative[f"%-{coin}raw_volume"] = informative["volume"]
informative[f"%-{coin}raw_price"] = informative["close"] informative[f"%-{coin}raw_price"] = informative["close"]
indicators = [col for col in informative if col.startswith("%")] indicators = [col for col in informative if col.startswith("%")]
# This loop duplicates and shifts all indicators to add a sense of recency to data # This loop duplicates and shifts all indicators to add a sense of recency to data
for n in range(self.freqai_info["feature_parameters"]["include_shifted_candles"] + 1): for n in range(self.freqai_info["feature_parameters"]["include_shifted_candles"] + 1):
if n == 0: if n == 0:
continue continue
informative_shift = informative[indicators].shift(n) informative_shift = informative[indicators].shift(n)
informative_shift = informative_shift.add_suffix("_shift-" + str(n)) informative_shift = informative_shift.add_suffix("_shift-" + str(n))
informative = pd.concat((informative, informative_shift), axis=1) informative = pd.concat((informative, informative_shift), axis=1)
df = merge_informative_pair(df, informative, self.config["timeframe"], tf, ffill=True) df = merge_informative_pair(df, informative, self.config["timeframe"], tf, ffill=True)
skip_columns = [ skip_columns = [
(s + "_" + tf) for s in ["date", "open", "high", "low", "close", "volume"] (s + "_" + tf) for s in ["date", "open", "high", "low", "close", "volume"]
] ]
df = df.drop(columns=skip_columns) df = df.drop(columns=skip_columns)
# Add generalized indicators here (because in live, it will call this # Add generalized indicators here (because in live, it will call this
# function to populate indicators during training). Notice how we ensure not to # function to populate indicators during training). Notice how we ensure not to
# add them multiple times # add them multiple times
if set_generalized_indicators: if set_generalized_indicators:
df["%-day_of_week"] = (df["date"].dt.dayofweek + 1) / 7 df["%-day_of_week"] = (df["date"].dt.dayofweek + 1) / 7
df["%-hour_of_day"] = (df["date"].dt.hour + 1) / 25 df["%-hour_of_day"] = (df["date"].dt.hour + 1) / 25
# user adds targets here by prepending them with &- (see convention below) # user adds targets here by prepending them with &- (see convention below)
# If user wishes to use multiple targets, a multioutput prediction model # If user wishes to use multiple targets, a multioutput prediction model
# needs to be used such as templates/CatboostPredictionMultiModel.py # needs to be used such as templates/CatboostPredictionMultiModel.py
df["&-s_close"] = ( df["&-s_close"] = (
df["close"] df["close"]
.shift(-self.freqai_info["feature_parameters"]["label_period_candles"]) .shift(-self.freqai_info["feature_parameters"]["label_period_candles"])
.rolling(self.freqai_info["feature_parameters"]["label_period_candles"]) .rolling(self.freqai_info["feature_parameters"]["label_period_candles"])
.mean() .mean()
/ df["close"] / df["close"]
- 1 - 1
) )
df["&-s_range"] = ( df["&-s_range"] = (
df["close"] df["close"]
.shift(-self.freqai_info["feature_parameters"]["label_period_candles"]) .shift(-self.freqai_info["feature_parameters"]["label_period_candles"])
.rolling(self.freqai_info["feature_parameters"]["label_period_candles"]) .rolling(self.freqai_info["feature_parameters"]["label_period_candles"])
.max() .max()
- -
df["close"] df["close"]
.shift(-self.freqai_info["feature_parameters"]["label_period_candles"]) .shift(-self.freqai_info["feature_parameters"]["label_period_candles"])
.rolling(self.freqai_info["feature_parameters"]["label_period_candles"]) .rolling(self.freqai_info["feature_parameters"]["label_period_candles"])
.min() .min()
) )
return df return df

View File

@ -62,55 +62,54 @@ class freqai_test_strat(IStrategy):
coin = pair.split('/')[0] coin = pair.split('/')[0]
with self.freqai.lock: if informative is None:
if informative is None: informative = self.dp.get_pair_dataframe(pair, tf)
informative = self.dp.get_pair_dataframe(pair, tf)
# first loop is automatically duplicating indicators for time periods # first loop is automatically duplicating indicators for time periods
for t in self.freqai_info["feature_parameters"]["indicator_periods_candles"]: for t in self.freqai_info["feature_parameters"]["indicator_periods_candles"]:
t = int(t) t = int(t)
informative[f"%-{coin}rsi-period_{t}"] = ta.RSI(informative, timeperiod=t) informative[f"%-{coin}rsi-period_{t}"] = ta.RSI(informative, timeperiod=t)
informative[f"%-{coin}mfi-period_{t}"] = ta.MFI(informative, timeperiod=t) informative[f"%-{coin}mfi-period_{t}"] = ta.MFI(informative, timeperiod=t)
informative[f"%-{coin}adx-period_{t}"] = ta.ADX(informative, window=t) informative[f"%-{coin}adx-period_{t}"] = ta.ADX(informative, window=t)
informative[f"%-{coin}pct-change"] = informative["close"].pct_change() informative[f"%-{coin}pct-change"] = informative["close"].pct_change()
informative[f"%-{coin}raw_volume"] = informative["volume"] informative[f"%-{coin}raw_volume"] = informative["volume"]
informative[f"%-{coin}raw_price"] = informative["close"] informative[f"%-{coin}raw_price"] = informative["close"]
indicators = [col for col in informative if col.startswith("%")] indicators = [col for col in informative if col.startswith("%")]
# This loop duplicates and shifts all indicators to add a sense of recency to data # This loop duplicates and shifts all indicators to add a sense of recency to data
for n in range(self.freqai_info["feature_parameters"]["include_shifted_candles"] + 1): for n in range(self.freqai_info["feature_parameters"]["include_shifted_candles"] + 1):
if n == 0: if n == 0:
continue continue
informative_shift = informative[indicators].shift(n) informative_shift = informative[indicators].shift(n)
informative_shift = informative_shift.add_suffix("_shift-" + str(n)) informative_shift = informative_shift.add_suffix("_shift-" + str(n))
informative = pd.concat((informative, informative_shift), axis=1) informative = pd.concat((informative, informative_shift), axis=1)
df = merge_informative_pair(df, informative, self.config["timeframe"], tf, ffill=True) df = merge_informative_pair(df, informative, self.config["timeframe"], tf, ffill=True)
skip_columns = [ skip_columns = [
(s + "_" + tf) for s in ["date", "open", "high", "low", "close", "volume"] (s + "_" + tf) for s in ["date", "open", "high", "low", "close", "volume"]
] ]
df = df.drop(columns=skip_columns) df = df.drop(columns=skip_columns)
# Add generalized indicators here (because in live, it will call this # Add generalized indicators here (because in live, it will call this
# function to populate indicators during training). Notice how we ensure not to # function to populate indicators during training). Notice how we ensure not to
# add them multiple times # add them multiple times
if set_generalized_indicators: if set_generalized_indicators:
df["%-day_of_week"] = (df["date"].dt.dayofweek + 1) / 7 df["%-day_of_week"] = (df["date"].dt.dayofweek + 1) / 7
df["%-hour_of_day"] = (df["date"].dt.hour + 1) / 25 df["%-hour_of_day"] = (df["date"].dt.hour + 1) / 25
# user adds targets here by prepending them with &- (see convention below) # user adds targets here by prepending them with &- (see convention below)
# If user wishes to use multiple targets, a multioutput prediction model # If user wishes to use multiple targets, a multioutput prediction model
# needs to be used such as templates/CatboostPredictionMultiModel.py # needs to be used such as templates/CatboostPredictionMultiModel.py
df["&-s_close"] = ( df["&-s_close"] = (
df["close"] df["close"]
.shift(-self.freqai_info["feature_parameters"]["label_period_candles"]) .shift(-self.freqai_info["feature_parameters"]["label_period_candles"])
.rolling(self.freqai_info["feature_parameters"]["label_period_candles"]) .rolling(self.freqai_info["feature_parameters"]["label_period_candles"])
.mean() .mean()
/ df["close"] / df["close"]
- 1 - 1
) )
return df return df