Move "freqai.lock" to backend to simplify user interface
This commit is contained in:
parent
a5e96881f4
commit
3a9ec76c91
184
docs/freqai.md
184
docs/freqai.md
@ -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
|
||||||
|
|
||||||
|
@ -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)
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user