mirror of
https://github.com/freqtrade/freqtrade.git
synced 2024-11-10 10:21:59 +00:00
ruff format: Update test strategies
This commit is contained in:
parent
099b1fc8c4
commit
8c7d80b78e
|
@ -12,7 +12,6 @@ from freqtrade.strategy.interface import IStrategy
|
||||||
|
|
||||||
|
|
||||||
class TestStrategyNoImplements(IStrategy):
|
class TestStrategyNoImplements(IStrategy):
|
||||||
|
|
||||||
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
||||||
return super().populate_indicators(dataframe, metadata)
|
return super().populate_indicators(dataframe, metadata)
|
||||||
|
|
||||||
|
@ -26,9 +25,15 @@ class TestStrategyImplementCustomSell(TestStrategyNoImplementSell):
|
||||||
def populate_exit_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
def populate_exit_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
||||||
return super().populate_exit_trend(dataframe, metadata)
|
return super().populate_exit_trend(dataframe, metadata)
|
||||||
|
|
||||||
def custom_sell(self, pair: str, trade, current_time: datetime,
|
def custom_sell(
|
||||||
current_rate: float, current_profit: float,
|
self,
|
||||||
**kwargs):
|
pair: str,
|
||||||
|
trade,
|
||||||
|
current_time: datetime,
|
||||||
|
current_rate: float,
|
||||||
|
current_profit: float,
|
||||||
|
**kwargs,
|
||||||
|
):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
@ -36,8 +41,9 @@ class TestStrategyImplementBuyTimeout(TestStrategyNoImplementSell):
|
||||||
def populate_exit_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
def populate_exit_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
||||||
return super().populate_exit_trend(dataframe, metadata)
|
return super().populate_exit_trend(dataframe, metadata)
|
||||||
|
|
||||||
def check_buy_timeout(self, pair: str, trade, order: Order,
|
def check_buy_timeout(
|
||||||
current_time: datetime, **kwargs) -> bool:
|
self, pair: str, trade, order: Order, current_time: datetime, **kwargs
|
||||||
|
) -> bool:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
@ -45,6 +51,7 @@ class TestStrategyImplementSellTimeout(TestStrategyNoImplementSell):
|
||||||
def populate_exit_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
def populate_exit_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
||||||
return super().populate_exit_trend(dataframe, metadata)
|
return super().populate_exit_trend(dataframe, metadata)
|
||||||
|
|
||||||
def check_sell_timeout(self, pair: str, trade, order: Order,
|
def check_sell_timeout(
|
||||||
current_time: datetime, **kwargs) -> bool:
|
self, pair: str, trade, order: Order, current_time: datetime, **kwargs
|
||||||
|
) -> bool:
|
||||||
return False
|
return False
|
||||||
|
|
|
@ -6,25 +6,16 @@ from freqtrade.strategy import IStrategy
|
||||||
|
|
||||||
# Dummy strategy - no longer loads but raises an exception.
|
# Dummy strategy - no longer loads but raises an exception.
|
||||||
class TestStrategyLegacyV1(IStrategy):
|
class TestStrategyLegacyV1(IStrategy):
|
||||||
|
minimal_roi = {"40": 0.0, "30": 0.01, "20": 0.02, "0": 0.04}
|
||||||
minimal_roi = {
|
|
||||||
"40": 0.0,
|
|
||||||
"30": 0.01,
|
|
||||||
"20": 0.02,
|
|
||||||
"0": 0.04
|
|
||||||
}
|
|
||||||
stoploss = -0.10
|
stoploss = -0.10
|
||||||
|
|
||||||
timeframe = '5m'
|
timeframe = "5m"
|
||||||
|
|
||||||
def populate_indicators(self, dataframe: DataFrame) -> DataFrame:
|
def populate_indicators(self, dataframe: DataFrame) -> DataFrame:
|
||||||
|
|
||||||
return dataframe
|
return dataframe
|
||||||
|
|
||||||
def populate_buy_trend(self, dataframe: DataFrame) -> DataFrame:
|
def populate_buy_trend(self, dataframe: DataFrame) -> DataFrame:
|
||||||
|
|
||||||
return dataframe
|
return dataframe
|
||||||
|
|
||||||
def populate_sell_trend(self, dataframe: DataFrame) -> DataFrame:
|
def populate_sell_trend(self, dataframe: DataFrame) -> DataFrame:
|
||||||
|
|
||||||
return dataframe
|
return dataframe
|
||||||
|
|
|
@ -25,22 +25,20 @@ 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: DataFrame, period: int,
|
def feature_engineering_expand_all(
|
||||||
metadata: Dict, **kwargs):
|
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, metadata: Dict, **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: DataFrame, metadata: Dict, **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
|
||||||
|
|
||||||
|
@ -52,19 +50,16 @@ class freqai_rl_test_strat(IStrategy):
|
||||||
return dataframe
|
return dataframe
|
||||||
|
|
||||||
def set_freqai_targets(self, dataframe: DataFrame, metadata: Dict, **kwargs):
|
def set_freqai_targets(self, dataframe: DataFrame, metadata: Dict, **kwargs):
|
||||||
|
|
||||||
dataframe["&-action"] = 0
|
dataframe["&-action"] = 0
|
||||||
|
|
||||||
return dataframe
|
return dataframe
|
||||||
|
|
||||||
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
||||||
|
|
||||||
dataframe = self.freqai.start(dataframe, metadata, self)
|
dataframe = self.freqai.start(dataframe, metadata, self)
|
||||||
|
|
||||||
return dataframe
|
return dataframe
|
||||||
|
|
||||||
def populate_entry_trend(self, df: DataFrame, metadata: dict) -> DataFrame:
|
def populate_entry_trend(self, df: DataFrame, metadata: dict) -> DataFrame:
|
||||||
|
|
||||||
enter_long_conditions = [df["do_predict"] == 1, df["&-action"] == 1]
|
enter_long_conditions = [df["do_predict"] == 1, df["&-action"] == 1]
|
||||||
|
|
||||||
if enter_long_conditions:
|
if enter_long_conditions:
|
||||||
|
|
|
@ -57,9 +57,9 @@ 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: DataFrame, period: int,
|
def feature_engineering_expand_all(
|
||||||
metadata: Dict, **kwargs):
|
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)
|
||||||
dataframe["%-adx-period"] = ta.ADX(dataframe, timeperiod=period)
|
dataframe["%-adx-period"] = ta.ADX(dataframe, timeperiod=period)
|
||||||
|
@ -67,7 +67,6 @@ class freqai_test_classifier(IStrategy):
|
||||||
return dataframe
|
return dataframe
|
||||||
|
|
||||||
def feature_engineering_expand_basic(self, dataframe: DataFrame, metadata: Dict, **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"]
|
||||||
dataframe["%-raw_price"] = dataframe["close"]
|
dataframe["%-raw_price"] = dataframe["close"]
|
||||||
|
@ -75,7 +74,6 @@ class freqai_test_classifier(IStrategy):
|
||||||
return dataframe
|
return dataframe
|
||||||
|
|
||||||
def feature_engineering_standard(self, dataframe: DataFrame, metadata: Dict, **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
|
||||||
|
|
||||||
|
@ -83,13 +81,13 @@ class freqai_test_classifier(IStrategy):
|
||||||
|
|
||||||
def set_freqai_targets(self, dataframe: DataFrame, metadata: Dict, **kwargs):
|
def set_freqai_targets(self, dataframe: DataFrame, metadata: Dict, **kwargs):
|
||||||
self.freqai.class_names = ["down", "up"]
|
self.freqai.class_names = ["down", "up"]
|
||||||
dataframe['&s-up_or_down'] = np.where(dataframe["close"].shift(-100) >
|
dataframe["&s-up_or_down"] = np.where(
|
||||||
dataframe["close"], 'up', 'down')
|
dataframe["close"].shift(-100) > dataframe["close"], "up", "down"
|
||||||
|
)
|
||||||
|
|
||||||
return dataframe
|
return dataframe
|
||||||
|
|
||||||
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
||||||
|
|
||||||
self.freqai_info = self.config["freqai"]
|
self.freqai_info = self.config["freqai"]
|
||||||
|
|
||||||
dataframe = self.freqai.start(dataframe, metadata, self)
|
dataframe = self.freqai.start(dataframe, metadata, self)
|
||||||
|
@ -97,15 +95,14 @@ class freqai_test_classifier(IStrategy):
|
||||||
return dataframe
|
return dataframe
|
||||||
|
|
||||||
def populate_entry_trend(self, df: DataFrame, metadata: dict) -> DataFrame:
|
def populate_entry_trend(self, df: DataFrame, metadata: dict) -> DataFrame:
|
||||||
|
enter_long_conditions = [df["&s-up_or_down"] == "up"]
|
||||||
enter_long_conditions = [df['&s-up_or_down'] == 'up']
|
|
||||||
|
|
||||||
if enter_long_conditions:
|
if enter_long_conditions:
|
||||||
df.loc[
|
df.loc[
|
||||||
reduce(lambda x, y: x & y, enter_long_conditions), ["enter_long", "enter_tag"]
|
reduce(lambda x, y: x & y, enter_long_conditions), ["enter_long", "enter_tag"]
|
||||||
] = (1, "long")
|
] = (1, "long")
|
||||||
|
|
||||||
enter_short_conditions = [df['&s-up_or_down'] == 'down']
|
enter_short_conditions = [df["&s-up_or_down"] == "down"]
|
||||||
|
|
||||||
if enter_short_conditions:
|
if enter_short_conditions:
|
||||||
df.loc[
|
df.loc[
|
||||||
|
@ -115,5 +112,4 @@ class freqai_test_classifier(IStrategy):
|
||||||
return df
|
return df
|
||||||
|
|
||||||
def populate_exit_trend(self, df: DataFrame, metadata: dict) -> DataFrame:
|
def populate_exit_trend(self, df: DataFrame, metadata: dict) -> DataFrame:
|
||||||
|
|
||||||
return df
|
return df
|
||||||
|
|
|
@ -44,9 +44,9 @@ 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: DataFrame, period: int,
|
def feature_engineering_expand_all(
|
||||||
metadata: Dict, **kwargs):
|
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)
|
||||||
dataframe["%-adx-period"] = ta.ADX(dataframe, timeperiod=period)
|
dataframe["%-adx-period"] = ta.ADX(dataframe, timeperiod=period)
|
||||||
|
@ -54,7 +54,6 @@ class freqai_test_multimodel_classifier_strat(IStrategy):
|
||||||
return dataframe
|
return dataframe
|
||||||
|
|
||||||
def feature_engineering_expand_basic(self, dataframe: DataFrame, metadata: Dict, **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"]
|
||||||
dataframe["%-raw_price"] = dataframe["close"]
|
dataframe["%-raw_price"] = dataframe["close"]
|
||||||
|
@ -62,24 +61,23 @@ class freqai_test_multimodel_classifier_strat(IStrategy):
|
||||||
return dataframe
|
return dataframe
|
||||||
|
|
||||||
def feature_engineering_standard(self, dataframe: DataFrame, metadata: Dict, **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: DataFrame, metadata: Dict, **kwargs):
|
def set_freqai_targets(self, dataframe: DataFrame, metadata: Dict, **kwargs):
|
||||||
|
dataframe["&s-up_or_down"] = np.where(
|
||||||
|
dataframe["close"].shift(-50) > dataframe["close"], "up", "down"
|
||||||
|
)
|
||||||
|
|
||||||
dataframe['&s-up_or_down'] = np.where(dataframe["close"].shift(-50) >
|
dataframe["&s-up_or_down2"] = np.where(
|
||||||
dataframe["close"], 'up', 'down')
|
dataframe["close"].shift(-50) > dataframe["close"], "up2", "down2"
|
||||||
|
)
|
||||||
dataframe['&s-up_or_down2'] = np.where(dataframe["close"].shift(-50) >
|
|
||||||
dataframe["close"], 'up2', 'down2')
|
|
||||||
|
|
||||||
return dataframe
|
return dataframe
|
||||||
|
|
||||||
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
||||||
|
|
||||||
self.freqai_info = self.config["freqai"]
|
self.freqai_info = self.config["freqai"]
|
||||||
|
|
||||||
dataframe = self.freqai.start(dataframe, metadata, self)
|
dataframe = self.freqai.start(dataframe, metadata, self)
|
||||||
|
@ -89,7 +87,6 @@ class freqai_test_multimodel_classifier_strat(IStrategy):
|
||||||
return dataframe
|
return dataframe
|
||||||
|
|
||||||
def populate_entry_trend(self, df: DataFrame, metadata: dict) -> DataFrame:
|
def populate_entry_trend(self, df: DataFrame, metadata: dict) -> DataFrame:
|
||||||
|
|
||||||
enter_long_conditions = [df["do_predict"] == 1, df["&-s_close"] > df["target_roi"]]
|
enter_long_conditions = [df["do_predict"] == 1, df["&-s_close"] > df["target_roi"]]
|
||||||
|
|
||||||
if enter_long_conditions:
|
if enter_long_conditions:
|
||||||
|
|
|
@ -43,9 +43,9 @@ 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: DataFrame, period: int,
|
def feature_engineering_expand_all(
|
||||||
metadata: Dict, **kwargs):
|
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)
|
||||||
dataframe["%-adx-period"] = ta.ADX(dataframe, timeperiod=period)
|
dataframe["%-adx-period"] = ta.ADX(dataframe, timeperiod=period)
|
||||||
|
@ -53,7 +53,6 @@ class freqai_test_multimodel_strat(IStrategy):
|
||||||
return dataframe
|
return dataframe
|
||||||
|
|
||||||
def feature_engineering_expand_basic(self, dataframe: DataFrame, metadata: Dict, **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"]
|
||||||
dataframe["%-raw_price"] = dataframe["close"]
|
dataframe["%-raw_price"] = dataframe["close"]
|
||||||
|
@ -61,14 +60,12 @@ class freqai_test_multimodel_strat(IStrategy):
|
||||||
return dataframe
|
return dataframe
|
||||||
|
|
||||||
def feature_engineering_standard(self, dataframe: DataFrame, metadata: Dict, **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: DataFrame, metadata: Dict, **kwargs):
|
def set_freqai_targets(self, dataframe: DataFrame, metadata: Dict, **kwargs):
|
||||||
|
|
||||||
dataframe["&-s_close"] = (
|
dataframe["&-s_close"] = (
|
||||||
dataframe["close"]
|
dataframe["close"]
|
||||||
.shift(-self.freqai_info["feature_parameters"]["label_period_candles"])
|
.shift(-self.freqai_info["feature_parameters"]["label_period_candles"])
|
||||||
|
@ -76,15 +73,14 @@ class freqai_test_multimodel_strat(IStrategy):
|
||||||
.mean()
|
.mean()
|
||||||
/ dataframe["close"]
|
/ dataframe["close"]
|
||||||
- 1
|
- 1
|
||||||
)
|
)
|
||||||
|
|
||||||
dataframe["&-s_range"] = (
|
dataframe["&-s_range"] = (
|
||||||
dataframe["close"]
|
dataframe["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()
|
||||||
-
|
- dataframe["close"]
|
||||||
dataframe["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()
|
||||||
|
@ -93,7 +89,6 @@ class freqai_test_multimodel_strat(IStrategy):
|
||||||
return dataframe
|
return dataframe
|
||||||
|
|
||||||
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
||||||
|
|
||||||
self.freqai_info = self.config["freqai"]
|
self.freqai_info = self.config["freqai"]
|
||||||
|
|
||||||
dataframe = self.freqai.start(dataframe, metadata, self)
|
dataframe = self.freqai.start(dataframe, metadata, self)
|
||||||
|
@ -103,7 +98,6 @@ class freqai_test_multimodel_strat(IStrategy):
|
||||||
return dataframe
|
return dataframe
|
||||||
|
|
||||||
def populate_entry_trend(self, df: DataFrame, metadata: dict) -> DataFrame:
|
def populate_entry_trend(self, df: DataFrame, metadata: dict) -> DataFrame:
|
||||||
|
|
||||||
enter_long_conditions = [df["do_predict"] == 1, df["&-s_close"] > df["target_roi"]]
|
enter_long_conditions = [df["do_predict"] == 1, df["&-s_close"] > df["target_roi"]]
|
||||||
|
|
||||||
if enter_long_conditions:
|
if enter_long_conditions:
|
||||||
|
|
|
@ -43,9 +43,9 @@ 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: DataFrame, period: int,
|
def feature_engineering_expand_all(
|
||||||
metadata: Dict, **kwargs):
|
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)
|
||||||
dataframe["%-adx-period"] = ta.ADX(dataframe, timeperiod=period)
|
dataframe["%-adx-period"] = ta.ADX(dataframe, timeperiod=period)
|
||||||
|
@ -53,7 +53,6 @@ class freqai_test_strat(IStrategy):
|
||||||
return dataframe
|
return dataframe
|
||||||
|
|
||||||
def feature_engineering_expand_basic(self, dataframe: DataFrame, metadata: Dict, **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"]
|
||||||
dataframe["%-raw_price"] = dataframe["close"]
|
dataframe["%-raw_price"] = dataframe["close"]
|
||||||
|
@ -61,14 +60,12 @@ class freqai_test_strat(IStrategy):
|
||||||
return dataframe
|
return dataframe
|
||||||
|
|
||||||
def feature_engineering_standard(self, dataframe: DataFrame, metadata: Dict, **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: DataFrame, metadata: Dict, **kwargs):
|
def set_freqai_targets(self, dataframe: DataFrame, metadata: Dict, **kwargs):
|
||||||
|
|
||||||
dataframe["&-s_close"] = (
|
dataframe["&-s_close"] = (
|
||||||
dataframe["close"]
|
dataframe["close"]
|
||||||
.shift(-self.freqai_info["feature_parameters"]["label_period_candles"])
|
.shift(-self.freqai_info["feature_parameters"]["label_period_candles"])
|
||||||
|
@ -76,12 +73,11 @@ class freqai_test_strat(IStrategy):
|
||||||
.mean()
|
.mean()
|
||||||
/ dataframe["close"]
|
/ dataframe["close"]
|
||||||
- 1
|
- 1
|
||||||
)
|
)
|
||||||
|
|
||||||
return dataframe
|
return dataframe
|
||||||
|
|
||||||
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
||||||
|
|
||||||
self.freqai_info = self.config["freqai"]
|
self.freqai_info = self.config["freqai"]
|
||||||
|
|
||||||
dataframe = self.freqai.start(dataframe, metadata, self)
|
dataframe = self.freqai.start(dataframe, metadata, self)
|
||||||
|
@ -91,7 +87,6 @@ class freqai_test_strat(IStrategy):
|
||||||
return dataframe
|
return dataframe
|
||||||
|
|
||||||
def populate_entry_trend(self, df: DataFrame, metadata: dict) -> DataFrame:
|
def populate_entry_trend(self, df: DataFrame, metadata: dict) -> DataFrame:
|
||||||
|
|
||||||
enter_long_conditions = [df["do_predict"] == 1, df["&-s_close"] > df["target_roi"]]
|
enter_long_conditions = [df["do_predict"] == 1, df["&-s_close"] > df["target_roi"]]
|
||||||
|
|
||||||
if enter_long_conditions:
|
if enter_long_conditions:
|
||||||
|
|
|
@ -17,20 +17,18 @@ class HyperoptableStrategy(StrategyTestV3):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
buy_params = {
|
buy_params = {
|
||||||
'buy_rsi': 35,
|
"buy_rsi": 35,
|
||||||
# Intentionally not specified, so "default" is tested
|
# Intentionally not specified, so "default" is tested
|
||||||
# 'buy_plusdi': 0.4
|
# 'buy_plusdi': 0.4
|
||||||
}
|
}
|
||||||
|
|
||||||
sell_params = {
|
sell_params = {"sell_rsi": 74, "sell_minusdi": 0.4}
|
||||||
'sell_rsi': 74,
|
|
||||||
'sell_minusdi': 0.4
|
|
||||||
}
|
|
||||||
|
|
||||||
buy_plusdi = RealParameter(low=0, high=1, default=0.5, space='buy')
|
buy_plusdi = RealParameter(low=0, high=1, default=0.5, space="buy")
|
||||||
sell_rsi = IntParameter(low=50, high=100, default=70, space='sell')
|
sell_rsi = IntParameter(low=50, high=100, default=70, space="sell")
|
||||||
sell_minusdi = DecimalParameter(low=0, high=1, default=0.5001, decimals=3, space='sell',
|
sell_minusdi = DecimalParameter(
|
||||||
load=False)
|
low=0, high=1, default=0.5001, decimals=3, space="sell", load=False
|
||||||
|
)
|
||||||
protection_enabled = BooleanParameter(default=True)
|
protection_enabled = BooleanParameter(default=True)
|
||||||
protection_cooldown_lookback = IntParameter([0, 50], default=30)
|
protection_cooldown_lookback = IntParameter([0, 50], default=30)
|
||||||
|
|
||||||
|
@ -43,10 +41,12 @@ class HyperoptableStrategy(StrategyTestV3):
|
||||||
def protections(self):
|
def protections(self):
|
||||||
prot = []
|
prot = []
|
||||||
if self.protection_enabled.value:
|
if self.protection_enabled.value:
|
||||||
prot.append({
|
prot.append(
|
||||||
"method": "CooldownPeriod",
|
{
|
||||||
"stop_duration_candles": self.protection_cooldown_lookback.value
|
"method": "CooldownPeriod",
|
||||||
})
|
"stop_duration_candles": self.protection_cooldown_lookback.value,
|
||||||
|
}
|
||||||
|
)
|
||||||
return prot
|
return prot
|
||||||
|
|
||||||
bot_loop_started = False
|
bot_loop_started = False
|
||||||
|
@ -60,7 +60,7 @@ class HyperoptableStrategy(StrategyTestV3):
|
||||||
Parameters can also be defined here ...
|
Parameters can also be defined here ...
|
||||||
"""
|
"""
|
||||||
self.bot_started = True
|
self.bot_started = True
|
||||||
self.buy_rsi = IntParameter([0, 50], default=30, space='buy')
|
self.buy_rsi = IntParameter([0, 50], default=30, space="buy")
|
||||||
|
|
||||||
def informative_pairs(self):
|
def informative_pairs(self):
|
||||||
"""
|
"""
|
||||||
|
@ -84,16 +84,14 @@ class HyperoptableStrategy(StrategyTestV3):
|
||||||
"""
|
"""
|
||||||
dataframe.loc[
|
dataframe.loc[
|
||||||
(
|
(
|
||||||
(dataframe['rsi'] < self.buy_rsi.value) &
|
(dataframe["rsi"] < self.buy_rsi.value)
|
||||||
(dataframe['fastd'] < 35) &
|
& (dataframe["fastd"] < 35)
|
||||||
(dataframe['adx'] > 30) &
|
& (dataframe["adx"] > 30)
|
||||||
(dataframe['plus_di'] > self.buy_plusdi.value)
|
& (dataframe["plus_di"] > self.buy_plusdi.value)
|
||||||
) |
|
)
|
||||||
(
|
| ((dataframe["adx"] > 65) & (dataframe["plus_di"] > self.buy_plusdi.value)),
|
||||||
(dataframe['adx'] > 65) &
|
"buy",
|
||||||
(dataframe['plus_di'] > self.buy_plusdi.value)
|
] = 1
|
||||||
),
|
|
||||||
'buy'] = 1
|
|
||||||
|
|
||||||
return dataframe
|
return dataframe
|
||||||
|
|
||||||
|
@ -107,15 +105,13 @@ class HyperoptableStrategy(StrategyTestV3):
|
||||||
dataframe.loc[
|
dataframe.loc[
|
||||||
(
|
(
|
||||||
(
|
(
|
||||||
(qtpylib.crossed_above(dataframe['rsi'], self.sell_rsi.value)) |
|
(qtpylib.crossed_above(dataframe["rsi"], self.sell_rsi.value))
|
||||||
(qtpylib.crossed_above(dataframe['fastd'], 70))
|
| (qtpylib.crossed_above(dataframe["fastd"], 70))
|
||||||
) &
|
)
|
||||||
(dataframe['adx'] > 10) &
|
& (dataframe["adx"] > 10)
|
||||||
(dataframe['minus_di'] > 0)
|
& (dataframe["minus_di"] > 0)
|
||||||
) |
|
)
|
||||||
(
|
| ((dataframe["adx"] > 70) & (dataframe["minus_di"] > self.sell_minusdi.value)),
|
||||||
(dataframe['adx'] > 70) &
|
"sell",
|
||||||
(dataframe['minus_di'] > self.sell_minusdi.value)
|
] = 1
|
||||||
),
|
|
||||||
'sell'] = 1
|
|
||||||
return dataframe
|
return dataframe
|
||||||
|
|
|
@ -15,20 +15,22 @@ class HyperoptableStrategyV2(StrategyTestV2):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
buy_params = {
|
buy_params = {
|
||||||
'buy_rsi': 35,
|
"buy_rsi": 35,
|
||||||
# Intentionally not specified, so "default" is tested
|
# Intentionally not specified, so "default" is tested
|
||||||
# 'buy_plusdi': 0.4
|
# 'buy_plusdi': 0.4
|
||||||
}
|
}
|
||||||
|
|
||||||
sell_params = {
|
sell_params = {
|
||||||
'sell_rsi': 74,
|
# Sell parameters
|
||||||
'sell_minusdi': 0.4
|
"sell_rsi": 74,
|
||||||
|
"sell_minusdi": 0.4,
|
||||||
}
|
}
|
||||||
|
|
||||||
buy_plusdi = RealParameter(low=0, high=1, default=0.5, space='buy')
|
buy_plusdi = RealParameter(low=0, high=1, default=0.5, space="buy")
|
||||||
sell_rsi = IntParameter(low=50, high=100, default=70, space='sell')
|
sell_rsi = IntParameter(low=50, high=100, default=70, space="sell")
|
||||||
sell_minusdi = DecimalParameter(low=0, high=1, default=0.5001, decimals=3, space='sell',
|
sell_minusdi = DecimalParameter(
|
||||||
load=False)
|
low=0, high=1, default=0.5001, decimals=3, space="sell", load=False
|
||||||
|
)
|
||||||
protection_enabled = BooleanParameter(default=True)
|
protection_enabled = BooleanParameter(default=True)
|
||||||
protection_cooldown_lookback = IntParameter([0, 50], default=30)
|
protection_cooldown_lookback = IntParameter([0, 50], default=30)
|
||||||
|
|
||||||
|
@ -36,10 +38,12 @@ class HyperoptableStrategyV2(StrategyTestV2):
|
||||||
def protections(self):
|
def protections(self):
|
||||||
prot = []
|
prot = []
|
||||||
if self.protection_enabled.value:
|
if self.protection_enabled.value:
|
||||||
prot.append({
|
prot.append(
|
||||||
"method": "CooldownPeriod",
|
{
|
||||||
"stop_duration_candles": self.protection_cooldown_lookback.value
|
"method": "CooldownPeriod",
|
||||||
})
|
"stop_duration_candles": self.protection_cooldown_lookback.value,
|
||||||
|
}
|
||||||
|
)
|
||||||
return prot
|
return prot
|
||||||
|
|
||||||
bot_loop_started = False
|
bot_loop_started = False
|
||||||
|
@ -51,4 +55,4 @@ class HyperoptableStrategyV2(StrategyTestV2):
|
||||||
"""
|
"""
|
||||||
Parameters can also be defined here ...
|
Parameters can also be defined here ...
|
||||||
"""
|
"""
|
||||||
self.buy_rsi = IntParameter([0, 50], default=30, space='buy')
|
self.buy_rsi = IntParameter([0, 50], default=30, space="buy")
|
||||||
|
|
|
@ -13,72 +13,73 @@ class InformativeDecoratorTest(IStrategy):
|
||||||
or strategy repository https://github.com/freqtrade/freqtrade-strategies
|
or strategy repository https://github.com/freqtrade/freqtrade-strategies
|
||||||
for samples and inspiration.
|
for samples and inspiration.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
INTERFACE_VERSION = 2
|
INTERFACE_VERSION = 2
|
||||||
stoploss = -0.10
|
stoploss = -0.10
|
||||||
timeframe = '5m'
|
timeframe = "5m"
|
||||||
startup_candle_count: int = 20
|
startup_candle_count: int = 20
|
||||||
|
|
||||||
def informative_pairs(self):
|
def informative_pairs(self):
|
||||||
# Intentionally return 2 tuples, must be converted to 3 in compatibility code
|
# Intentionally return 2 tuples, must be converted to 3 in compatibility code
|
||||||
return [
|
return [
|
||||||
('NEO/USDT', '5m'),
|
("NEO/USDT", "5m"),
|
||||||
('NEO/USDT', '15m', ''),
|
("NEO/USDT", "15m", ""),
|
||||||
('NEO/USDT', '2h', 'futures'),
|
("NEO/USDT", "2h", "futures"),
|
||||||
]
|
]
|
||||||
|
|
||||||
def populate_buy_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
def populate_buy_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
||||||
dataframe['buy'] = 0
|
dataframe["buy"] = 0
|
||||||
return dataframe
|
return dataframe
|
||||||
|
|
||||||
def populate_sell_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
def populate_sell_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
||||||
dataframe['sell'] = 0
|
dataframe["sell"] = 0
|
||||||
return dataframe
|
return dataframe
|
||||||
|
|
||||||
# Decorator stacking test.
|
# Decorator stacking test.
|
||||||
@informative('30m')
|
@informative("30m")
|
||||||
@informative('1h')
|
@informative("1h")
|
||||||
def populate_indicators_1h(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
def populate_indicators_1h(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
||||||
dataframe['rsi'] = 14
|
dataframe["rsi"] = 14
|
||||||
return dataframe
|
return dataframe
|
||||||
|
|
||||||
# Simple informative test.
|
# Simple informative test.
|
||||||
@informative('1h', 'NEO/{stake}')
|
@informative("1h", "NEO/{stake}")
|
||||||
def populate_indicators_neo_1h(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
def populate_indicators_neo_1h(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
||||||
dataframe['rsi'] = 14
|
dataframe["rsi"] = 14
|
||||||
return dataframe
|
return dataframe
|
||||||
|
|
||||||
@informative('1h', '{base}/BTC')
|
@informative("1h", "{base}/BTC")
|
||||||
def populate_indicators_base_1h(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
def populate_indicators_base_1h(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
||||||
dataframe['rsi'] = 14
|
dataframe["rsi"] = 14
|
||||||
return dataframe
|
return dataframe
|
||||||
|
|
||||||
# Quote currency different from stake currency test.
|
# Quote currency different from stake currency test.
|
||||||
@informative('1h', 'ETH/BTC', candle_type='spot')
|
@informative("1h", "ETH/BTC", candle_type="spot")
|
||||||
def populate_indicators_eth_btc_1h(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
def populate_indicators_eth_btc_1h(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
||||||
dataframe['rsi'] = 14
|
dataframe["rsi"] = 14
|
||||||
return dataframe
|
return dataframe
|
||||||
|
|
||||||
# Formatting test.
|
# Formatting test.
|
||||||
@informative('30m', 'NEO/{stake}', '{column}_{BASE}_{QUOTE}_{base}_{quote}_{asset}_{timeframe}')
|
@informative("30m", "NEO/{stake}", "{column}_{BASE}_{QUOTE}_{base}_{quote}_{asset}_{timeframe}")
|
||||||
def populate_indicators_btc_1h_2(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
def populate_indicators_btc_1h_2(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
||||||
dataframe['rsi'] = 14
|
dataframe["rsi"] = 14
|
||||||
return dataframe
|
return dataframe
|
||||||
|
|
||||||
# Custom formatter test
|
# Custom formatter test
|
||||||
@informative('30m', 'ETH/{stake}', fmt=lambda column, **kwargs: column + '_from_callable')
|
@informative("30m", "ETH/{stake}", fmt=lambda column, **kwargs: column + "_from_callable")
|
||||||
def populate_indicators_eth_30m(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
def populate_indicators_eth_30m(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
||||||
dataframe['rsi'] = 14
|
dataframe["rsi"] = 14
|
||||||
return dataframe
|
return dataframe
|
||||||
|
|
||||||
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
||||||
# Strategy timeframe indicators for current pair.
|
# Strategy timeframe indicators for current pair.
|
||||||
dataframe['rsi'] = 14
|
dataframe["rsi"] = 14
|
||||||
# Informative pairs are available in this method.
|
# Informative pairs are available in this method.
|
||||||
dataframe['rsi_less'] = dataframe['rsi'] < dataframe['rsi_1h']
|
dataframe["rsi_less"] = dataframe["rsi"] < dataframe["rsi_1h"]
|
||||||
|
|
||||||
# Mixing manual informative pairs with decorators.
|
# Mixing manual informative pairs with decorators.
|
||||||
informative = self.dp.get_pair_dataframe('NEO/USDT', '5m', '')
|
informative = self.dp.get_pair_dataframe("NEO/USDT", "5m", "")
|
||||||
informative['rsi'] = 14
|
informative["rsi"] = 14
|
||||||
dataframe = merge_informative_pair(dataframe, informative, self.timeframe, '5m', ffill=True)
|
dataframe = merge_informative_pair(dataframe, informative, self.timeframe, "5m", ffill=True)
|
||||||
|
|
||||||
return dataframe
|
return dataframe
|
||||||
|
|
|
@ -10,49 +10,44 @@ class strategy_test_v3_with_lookahead_bias(IStrategy):
|
||||||
INTERFACE_VERSION = 3
|
INTERFACE_VERSION = 3
|
||||||
|
|
||||||
# Minimal ROI designed for the strategy
|
# Minimal ROI designed for the strategy
|
||||||
minimal_roi = {
|
minimal_roi = {"40": 0.0, "30": 0.01, "20": 0.02, "0": 0.04}
|
||||||
"40": 0.0,
|
|
||||||
"30": 0.01,
|
|
||||||
"20": 0.02,
|
|
||||||
"0": 0.04
|
|
||||||
}
|
|
||||||
|
|
||||||
# Optimal stoploss designed for the strategy
|
# Optimal stoploss designed for the strategy
|
||||||
stoploss = -0.10
|
stoploss = -0.10
|
||||||
|
|
||||||
# Optimal timeframe for the strategy
|
# Optimal timeframe for the strategy
|
||||||
timeframe = '5m'
|
timeframe = "5m"
|
||||||
scenario = CategoricalParameter(['no_bias', 'bias1'], default='bias1', space="buy")
|
scenario = CategoricalParameter(["no_bias", "bias1"], default="bias1", space="buy")
|
||||||
|
|
||||||
# Number of candles the strategy requires before producing valid signals
|
# Number of candles the strategy requires before producing valid signals
|
||||||
startup_candle_count: int = 20
|
startup_candle_count: int = 20
|
||||||
|
|
||||||
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
||||||
# bias is introduced here
|
# bias is introduced here
|
||||||
if self.scenario.value != 'no_bias':
|
if self.scenario.value != "no_bias":
|
||||||
ichi = ichimoku(dataframe,
|
ichi = ichimoku(
|
||||||
conversion_line_period=20,
|
dataframe,
|
||||||
base_line_periods=60,
|
conversion_line_period=20,
|
||||||
laggin_span=120,
|
base_line_periods=60,
|
||||||
displacement=30)
|
laggin_span=120,
|
||||||
dataframe['chikou_span'] = ichi['chikou_span']
|
displacement=30,
|
||||||
|
)
|
||||||
|
dataframe["chikou_span"] = ichi["chikou_span"]
|
||||||
|
|
||||||
return dataframe
|
return dataframe
|
||||||
|
|
||||||
def populate_entry_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
def populate_entry_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
||||||
if self.scenario.value == 'no_bias':
|
if self.scenario.value == "no_bias":
|
||||||
dataframe.loc[dataframe['close'].shift(10) < dataframe['close'], 'enter_long'] = 1
|
dataframe.loc[dataframe["close"].shift(10) < dataframe["close"], "enter_long"] = 1
|
||||||
else:
|
else:
|
||||||
dataframe.loc[dataframe['close'].shift(-10) > dataframe['close'], 'enter_long'] = 1
|
dataframe.loc[dataframe["close"].shift(-10) > dataframe["close"], "enter_long"] = 1
|
||||||
|
|
||||||
return dataframe
|
return dataframe
|
||||||
|
|
||||||
def populate_exit_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
def populate_exit_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
||||||
if self.scenario.value == 'no_bias':
|
if self.scenario.value == "no_bias":
|
||||||
dataframe.loc[
|
dataframe.loc[dataframe["close"].shift(10) < dataframe["close"], "exit"] = 1
|
||||||
dataframe['close'].shift(10) < dataframe['close'], 'exit'] = 1
|
|
||||||
else:
|
else:
|
||||||
dataframe.loc[
|
dataframe.loc[dataframe["close"].shift(-10) > dataframe["close"], "exit"] = 1
|
||||||
dataframe['close'].shift(-10) > dataframe['close'], 'exit'] = 1
|
|
||||||
|
|
||||||
return dataframe
|
return dataframe
|
||||||
|
|
|
@ -15,28 +15,24 @@ class StrategyTestV2(IStrategy):
|
||||||
or strategy repository https://github.com/freqtrade/freqtrade-strategies
|
or strategy repository https://github.com/freqtrade/freqtrade-strategies
|
||||||
for samples and inspiration.
|
for samples and inspiration.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
INTERFACE_VERSION = 2
|
INTERFACE_VERSION = 2
|
||||||
|
|
||||||
# Minimal ROI designed for the strategy
|
# Minimal ROI designed for the strategy
|
||||||
minimal_roi = {
|
minimal_roi = {"40": 0.0, "30": 0.01, "20": 0.02, "0": 0.04}
|
||||||
"40": 0.0,
|
|
||||||
"30": 0.01,
|
|
||||||
"20": 0.02,
|
|
||||||
"0": 0.04
|
|
||||||
}
|
|
||||||
|
|
||||||
# Optimal stoploss designed for the strategy
|
# Optimal stoploss designed for the strategy
|
||||||
stoploss = -0.10
|
stoploss = -0.10
|
||||||
|
|
||||||
# Optimal timeframe for the strategy
|
# Optimal timeframe for the strategy
|
||||||
timeframe = '5m'
|
timeframe = "5m"
|
||||||
|
|
||||||
# Optional order type mapping
|
# Optional order type mapping
|
||||||
order_types = {
|
order_types = {
|
||||||
'entry': 'limit',
|
"entry": "limit",
|
||||||
'exit': 'limit',
|
"exit": "limit",
|
||||||
'stoploss': 'limit',
|
"stoploss": "limit",
|
||||||
'stoploss_on_exchange': False
|
"stoploss_on_exchange": False,
|
||||||
}
|
}
|
||||||
|
|
||||||
# Number of candles the strategy requires before producing valid signals
|
# Number of candles the strategy requires before producing valid signals
|
||||||
|
@ -44,8 +40,8 @@ class StrategyTestV2(IStrategy):
|
||||||
|
|
||||||
# Optional time in force for orders
|
# Optional time in force for orders
|
||||||
order_time_in_force = {
|
order_time_in_force = {
|
||||||
'entry': 'gtc',
|
"entry": "gtc",
|
||||||
'exit': 'gtc',
|
"exit": "gtc",
|
||||||
}
|
}
|
||||||
# Test legacy use_sell_signal definition
|
# Test legacy use_sell_signal definition
|
||||||
use_sell_signal = False
|
use_sell_signal = False
|
||||||
|
@ -69,36 +65,36 @@ class StrategyTestV2(IStrategy):
|
||||||
# ------------------------------------
|
# ------------------------------------
|
||||||
|
|
||||||
# ADX
|
# ADX
|
||||||
dataframe['adx'] = ta.ADX(dataframe)
|
dataframe["adx"] = ta.ADX(dataframe)
|
||||||
|
|
||||||
# MACD
|
# MACD
|
||||||
macd = ta.MACD(dataframe)
|
macd = ta.MACD(dataframe)
|
||||||
dataframe['macd'] = macd['macd']
|
dataframe["macd"] = macd["macd"]
|
||||||
dataframe['macdsignal'] = macd['macdsignal']
|
dataframe["macdsignal"] = macd["macdsignal"]
|
||||||
dataframe['macdhist'] = macd['macdhist']
|
dataframe["macdhist"] = macd["macdhist"]
|
||||||
|
|
||||||
# Minus Directional Indicator / Movement
|
# Minus Directional Indicator / Movement
|
||||||
dataframe['minus_di'] = ta.MINUS_DI(dataframe)
|
dataframe["minus_di"] = ta.MINUS_DI(dataframe)
|
||||||
|
|
||||||
# Plus Directional Indicator / Movement
|
# Plus Directional Indicator / Movement
|
||||||
dataframe['plus_di'] = ta.PLUS_DI(dataframe)
|
dataframe["plus_di"] = ta.PLUS_DI(dataframe)
|
||||||
|
|
||||||
# RSI
|
# RSI
|
||||||
dataframe['rsi'] = ta.RSI(dataframe)
|
dataframe["rsi"] = ta.RSI(dataframe)
|
||||||
|
|
||||||
# Stoch fast
|
# Stoch fast
|
||||||
stoch_fast = ta.STOCHF(dataframe)
|
stoch_fast = ta.STOCHF(dataframe)
|
||||||
dataframe['fastd'] = stoch_fast['fastd']
|
dataframe["fastd"] = stoch_fast["fastd"]
|
||||||
dataframe['fastk'] = stoch_fast['fastk']
|
dataframe["fastk"] = stoch_fast["fastk"]
|
||||||
|
|
||||||
# Bollinger bands
|
# Bollinger bands
|
||||||
bollinger = qtpylib.bollinger_bands(qtpylib.typical_price(dataframe), window=20, stds=2)
|
bollinger = qtpylib.bollinger_bands(qtpylib.typical_price(dataframe), window=20, stds=2)
|
||||||
dataframe['bb_lowerband'] = bollinger['lower']
|
dataframe["bb_lowerband"] = bollinger["lower"]
|
||||||
dataframe['bb_middleband'] = bollinger['mid']
|
dataframe["bb_middleband"] = bollinger["mid"]
|
||||||
dataframe['bb_upperband'] = bollinger['upper']
|
dataframe["bb_upperband"] = bollinger["upper"]
|
||||||
|
|
||||||
# EMA - Exponential Moving Average
|
# EMA - Exponential Moving Average
|
||||||
dataframe['ema10'] = ta.EMA(dataframe, timeperiod=10)
|
dataframe["ema10"] = ta.EMA(dataframe, timeperiod=10)
|
||||||
|
|
||||||
return dataframe
|
return dataframe
|
||||||
|
|
||||||
|
@ -111,16 +107,14 @@ class StrategyTestV2(IStrategy):
|
||||||
"""
|
"""
|
||||||
dataframe.loc[
|
dataframe.loc[
|
||||||
(
|
(
|
||||||
(dataframe['rsi'] < 35) &
|
(dataframe["rsi"] < 35)
|
||||||
(dataframe['fastd'] < 35) &
|
& (dataframe["fastd"] < 35)
|
||||||
(dataframe['adx'] > 30) &
|
& (dataframe["adx"] > 30)
|
||||||
(dataframe['plus_di'] > 0.5)
|
& (dataframe["plus_di"] > 0.5)
|
||||||
) |
|
)
|
||||||
(
|
| ((dataframe["adx"] > 65) & (dataframe["plus_di"] > 0.5)),
|
||||||
(dataframe['adx'] > 65) &
|
"buy",
|
||||||
(dataframe['plus_di'] > 0.5)
|
] = 1
|
||||||
),
|
|
||||||
'buy'] = 1
|
|
||||||
|
|
||||||
return dataframe
|
return dataframe
|
||||||
|
|
||||||
|
@ -134,15 +128,13 @@ class StrategyTestV2(IStrategy):
|
||||||
dataframe.loc[
|
dataframe.loc[
|
||||||
(
|
(
|
||||||
(
|
(
|
||||||
(qtpylib.crossed_above(dataframe['rsi'], 70)) |
|
(qtpylib.crossed_above(dataframe["rsi"], 70))
|
||||||
(qtpylib.crossed_above(dataframe['fastd'], 70))
|
| (qtpylib.crossed_above(dataframe["fastd"], 70))
|
||||||
) &
|
)
|
||||||
(dataframe['adx'] > 10) &
|
& (dataframe["adx"] > 10)
|
||||||
(dataframe['minus_di'] > 0)
|
& (dataframe["minus_di"] > 0)
|
||||||
) |
|
)
|
||||||
(
|
| ((dataframe["adx"] > 70) & (dataframe["minus_di"] > 0.5)),
|
||||||
(dataframe['adx'] > 70) &
|
"sell",
|
||||||
(dataframe['minus_di'] > 0.5)
|
] = 1
|
||||||
),
|
|
||||||
'sell'] = 1
|
|
||||||
return dataframe
|
return dataframe
|
||||||
|
|
|
@ -25,15 +25,11 @@ class StrategyTestV3(IStrategy):
|
||||||
or strategy repository https://github.com/freqtrade/freqtrade-strategies
|
or strategy repository https://github.com/freqtrade/freqtrade-strategies
|
||||||
for samples and inspiration.
|
for samples and inspiration.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
INTERFACE_VERSION = 3
|
INTERFACE_VERSION = 3
|
||||||
|
|
||||||
# Minimal ROI designed for the strategy
|
# Minimal ROI designed for the strategy
|
||||||
minimal_roi = {
|
minimal_roi = {"40": 0.0, "30": 0.01, "20": 0.02, "0": 0.04}
|
||||||
"40": 0.0,
|
|
||||||
"30": 0.01,
|
|
||||||
"20": 0.02,
|
|
||||||
"0": 0.04
|
|
||||||
}
|
|
||||||
|
|
||||||
# Optimal max_open_trades for the strategy
|
# Optimal max_open_trades for the strategy
|
||||||
max_open_trades = -1
|
max_open_trades = -1
|
||||||
|
@ -42,14 +38,14 @@ class StrategyTestV3(IStrategy):
|
||||||
stoploss = -0.10
|
stoploss = -0.10
|
||||||
|
|
||||||
# Optimal timeframe for the strategy
|
# Optimal timeframe for the strategy
|
||||||
timeframe = '5m'
|
timeframe = "5m"
|
||||||
|
|
||||||
# Optional order type mapping
|
# Optional order type mapping
|
||||||
order_types = {
|
order_types = {
|
||||||
'entry': 'limit',
|
"entry": "limit",
|
||||||
'exit': 'limit',
|
"exit": "limit",
|
||||||
'stoploss': 'limit',
|
"stoploss": "limit",
|
||||||
'stoploss_on_exchange': False
|
"stoploss_on_exchange": False,
|
||||||
}
|
}
|
||||||
|
|
||||||
# Number of candles the strategy requires before producing valid signals
|
# Number of candles the strategy requires before producing valid signals
|
||||||
|
@ -57,26 +53,24 @@ class StrategyTestV3(IStrategy):
|
||||||
|
|
||||||
# Optional time in force for orders
|
# Optional time in force for orders
|
||||||
order_time_in_force = {
|
order_time_in_force = {
|
||||||
'entry': 'gtc',
|
"entry": "gtc",
|
||||||
'exit': 'gtc',
|
"exit": "gtc",
|
||||||
}
|
}
|
||||||
|
|
||||||
buy_params = {
|
buy_params = {
|
||||||
'buy_rsi': 35,
|
"buy_rsi": 35,
|
||||||
# Intentionally not specified, so "default" is tested
|
# Intentionally not specified, so "default" is tested
|
||||||
# 'buy_plusdi': 0.4
|
# 'buy_plusdi': 0.4
|
||||||
}
|
}
|
||||||
|
|
||||||
sell_params = {
|
sell_params = {"sell_rsi": 74, "sell_minusdi": 0.4}
|
||||||
'sell_rsi': 74,
|
|
||||||
'sell_minusdi': 0.4
|
|
||||||
}
|
|
||||||
|
|
||||||
buy_rsi = IntParameter([0, 50], default=30, space='buy')
|
buy_rsi = IntParameter([0, 50], default=30, space="buy")
|
||||||
buy_plusdi = RealParameter(low=0, high=1, default=0.5, space='buy')
|
buy_plusdi = RealParameter(low=0, high=1, default=0.5, space="buy")
|
||||||
sell_rsi = IntParameter(low=50, high=100, default=70, space='sell')
|
sell_rsi = IntParameter(low=50, high=100, default=70, space="sell")
|
||||||
sell_minusdi = DecimalParameter(low=0, high=1, default=0.5001, decimals=3, space='sell',
|
sell_minusdi = DecimalParameter(
|
||||||
load=False)
|
low=0, high=1, default=0.5001, decimals=3, space="sell", load=False
|
||||||
|
)
|
||||||
protection_enabled = BooleanParameter(default=True)
|
protection_enabled = BooleanParameter(default=True)
|
||||||
protection_cooldown_lookback = IntParameter([0, 50], default=30)
|
protection_cooldown_lookback = IntParameter([0, 50], default=30)
|
||||||
|
|
||||||
|
@ -97,67 +91,61 @@ class StrategyTestV3(IStrategy):
|
||||||
self.bot_started = True
|
self.bot_started = True
|
||||||
|
|
||||||
def informative_pairs(self):
|
def informative_pairs(self):
|
||||||
|
|
||||||
return []
|
return []
|
||||||
|
|
||||||
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
||||||
|
|
||||||
# Momentum Indicator
|
# Momentum Indicator
|
||||||
# ------------------------------------
|
# ------------------------------------
|
||||||
|
|
||||||
# ADX
|
# ADX
|
||||||
dataframe['adx'] = ta.ADX(dataframe)
|
dataframe["adx"] = ta.ADX(dataframe)
|
||||||
|
|
||||||
# MACD
|
# MACD
|
||||||
macd = ta.MACD(dataframe)
|
macd = ta.MACD(dataframe)
|
||||||
dataframe['macd'] = macd['macd']
|
dataframe["macd"] = macd["macd"]
|
||||||
dataframe['macdsignal'] = macd['macdsignal']
|
dataframe["macdsignal"] = macd["macdsignal"]
|
||||||
dataframe['macdhist'] = macd['macdhist']
|
dataframe["macdhist"] = macd["macdhist"]
|
||||||
|
|
||||||
# Minus Directional Indicator / Movement
|
# Minus Directional Indicator / Movement
|
||||||
dataframe['minus_di'] = ta.MINUS_DI(dataframe)
|
dataframe["minus_di"] = ta.MINUS_DI(dataframe)
|
||||||
|
|
||||||
# Plus Directional Indicator / Movement
|
# Plus Directional Indicator / Movement
|
||||||
dataframe['plus_di'] = ta.PLUS_DI(dataframe)
|
dataframe["plus_di"] = ta.PLUS_DI(dataframe)
|
||||||
|
|
||||||
# RSI
|
# RSI
|
||||||
dataframe['rsi'] = ta.RSI(dataframe)
|
dataframe["rsi"] = ta.RSI(dataframe)
|
||||||
|
|
||||||
# Stoch fast
|
# Stoch fast
|
||||||
stoch_fast = ta.STOCHF(dataframe)
|
stoch_fast = ta.STOCHF(dataframe)
|
||||||
dataframe['fastd'] = stoch_fast['fastd']
|
dataframe["fastd"] = stoch_fast["fastd"]
|
||||||
dataframe['fastk'] = stoch_fast['fastk']
|
dataframe["fastk"] = stoch_fast["fastk"]
|
||||||
|
|
||||||
# Bollinger bands
|
# Bollinger bands
|
||||||
bollinger = qtpylib.bollinger_bands(qtpylib.typical_price(dataframe), window=20, stds=2)
|
bollinger = qtpylib.bollinger_bands(qtpylib.typical_price(dataframe), window=20, stds=2)
|
||||||
dataframe['bb_lowerband'] = bollinger['lower']
|
dataframe["bb_lowerband"] = bollinger["lower"]
|
||||||
dataframe['bb_middleband'] = bollinger['mid']
|
dataframe["bb_middleband"] = bollinger["mid"]
|
||||||
dataframe['bb_upperband'] = bollinger['upper']
|
dataframe["bb_upperband"] = bollinger["upper"]
|
||||||
|
|
||||||
# EMA - Exponential Moving Average
|
# EMA - Exponential Moving Average
|
||||||
dataframe['ema10'] = ta.EMA(dataframe, timeperiod=10)
|
dataframe["ema10"] = ta.EMA(dataframe, timeperiod=10)
|
||||||
|
|
||||||
return dataframe
|
return dataframe
|
||||||
|
|
||||||
def populate_entry_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
def populate_entry_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
||||||
|
|
||||||
dataframe.loc[
|
dataframe.loc[
|
||||||
(
|
(
|
||||||
(dataframe['rsi'] < self.buy_rsi.value) &
|
(dataframe["rsi"] < self.buy_rsi.value)
|
||||||
(dataframe['fastd'] < 35) &
|
& (dataframe["fastd"] < 35)
|
||||||
(dataframe['adx'] > 30) &
|
& (dataframe["adx"] > 30)
|
||||||
(dataframe['plus_di'] > self.buy_plusdi.value)
|
& (dataframe["plus_di"] > self.buy_plusdi.value)
|
||||||
) |
|
)
|
||||||
(
|
| ((dataframe["adx"] > 65) & (dataframe["plus_di"] > self.buy_plusdi.value)),
|
||||||
(dataframe['adx'] > 65) &
|
"enter_long",
|
||||||
(dataframe['plus_di'] > self.buy_plusdi.value)
|
] = 1
|
||||||
),
|
|
||||||
'enter_long'] = 1
|
|
||||||
dataframe.loc[
|
dataframe.loc[
|
||||||
(
|
(qtpylib.crossed_below(dataframe["rsi"], self.sell_rsi.value)),
|
||||||
qtpylib.crossed_below(dataframe['rsi'], self.sell_rsi.value)
|
("enter_short", "enter_tag"),
|
||||||
),
|
] = (1, "short_Tag")
|
||||||
('enter_short', 'enter_tag')] = (1, 'short_Tag')
|
|
||||||
|
|
||||||
return dataframe
|
return dataframe
|
||||||
|
|
||||||
|
@ -165,41 +153,53 @@ class StrategyTestV3(IStrategy):
|
||||||
dataframe.loc[
|
dataframe.loc[
|
||||||
(
|
(
|
||||||
(
|
(
|
||||||
(qtpylib.crossed_above(dataframe['rsi'], self.sell_rsi.value)) |
|
(qtpylib.crossed_above(dataframe["rsi"], self.sell_rsi.value))
|
||||||
(qtpylib.crossed_above(dataframe['fastd'], 70))
|
| (qtpylib.crossed_above(dataframe["fastd"], 70))
|
||||||
) &
|
)
|
||||||
(dataframe['adx'] > 10) &
|
& (dataframe["adx"] > 10)
|
||||||
(dataframe['minus_di'] > 0)
|
& (dataframe["minus_di"] > 0)
|
||||||
) |
|
)
|
||||||
(
|
| ((dataframe["adx"] > 70) & (dataframe["minus_di"] > self.sell_minusdi.value)),
|
||||||
(dataframe['adx'] > 70) &
|
"exit_long",
|
||||||
(dataframe['minus_di'] > self.sell_minusdi.value)
|
] = 1
|
||||||
),
|
|
||||||
'exit_long'] = 1
|
|
||||||
|
|
||||||
dataframe.loc[
|
dataframe.loc[
|
||||||
(
|
(qtpylib.crossed_above(dataframe["rsi"], self.buy_rsi.value)),
|
||||||
qtpylib.crossed_above(dataframe['rsi'], self.buy_rsi.value)
|
("exit_short", "exit_tag"),
|
||||||
),
|
] = (1, "short_Tag")
|
||||||
('exit_short', 'exit_tag')] = (1, 'short_Tag')
|
|
||||||
|
|
||||||
return dataframe
|
return dataframe
|
||||||
|
|
||||||
def leverage(self, pair: str, current_time: datetime, current_rate: float,
|
def leverage(
|
||||||
proposed_leverage: float, max_leverage: float, entry_tag: Optional[str],
|
self,
|
||||||
side: str, **kwargs) -> float:
|
pair: str,
|
||||||
|
current_time: datetime,
|
||||||
|
current_rate: float,
|
||||||
|
proposed_leverage: float,
|
||||||
|
max_leverage: float,
|
||||||
|
entry_tag: Optional[str],
|
||||||
|
side: str,
|
||||||
|
**kwargs,
|
||||||
|
) -> float:
|
||||||
# Return 3.0 in all cases.
|
# Return 3.0 in all cases.
|
||||||
# Bot-logic must make sure it's an allowed leverage and eventually adjust accordingly.
|
# Bot-logic must make sure it's an allowed leverage and eventually adjust accordingly.
|
||||||
|
|
||||||
return 3.0
|
return 3.0
|
||||||
|
|
||||||
def adjust_trade_position(self, trade: Trade, current_time: datetime,
|
def adjust_trade_position(
|
||||||
current_rate: float, current_profit: float,
|
self,
|
||||||
min_stake: Optional[float], max_stake: float,
|
trade: Trade,
|
||||||
current_entry_rate: float, current_exit_rate: float,
|
current_time: datetime,
|
||||||
current_entry_profit: float, current_exit_profit: float,
|
current_rate: float,
|
||||||
**kwargs) -> Optional[float]:
|
current_profit: float,
|
||||||
|
min_stake: Optional[float],
|
||||||
|
max_stake: float,
|
||||||
|
current_entry_rate: float,
|
||||||
|
current_exit_rate: float,
|
||||||
|
current_entry_profit: float,
|
||||||
|
current_exit_profit: float,
|
||||||
|
**kwargs,
|
||||||
|
) -> Optional[float]:
|
||||||
if current_profit < -0.0075:
|
if current_profit < -0.0075:
|
||||||
orders = trade.select_filled_orders(trade.entry_side)
|
orders = trade.select_filled_orders(trade.entry_side)
|
||||||
return round(orders[0].stake_amount, 0)
|
return round(orders[0].stake_amount, 0)
|
||||||
|
|
|
@ -17,24 +17,28 @@ class StrategyTestV3CustomEntryPrice(StrategyTestV3):
|
||||||
or strategy repository https://github.com/freqtrade/freqtrade-strategies
|
or strategy repository https://github.com/freqtrade/freqtrade-strategies
|
||||||
for samples and inspiration.
|
for samples and inspiration.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
new_entry_price: float = 0.001
|
new_entry_price: float = 0.001
|
||||||
|
|
||||||
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
||||||
return dataframe
|
return dataframe
|
||||||
|
|
||||||
def populate_entry_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
def populate_entry_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
||||||
|
dataframe.loc[dataframe["volume"] > 0, "enter_long"] = 1
|
||||||
dataframe.loc[
|
|
||||||
dataframe['volume'] > 0,
|
|
||||||
'enter_long'] = 1
|
|
||||||
|
|
||||||
return dataframe
|
return dataframe
|
||||||
|
|
||||||
def populate_exit_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
def populate_exit_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
||||||
return dataframe
|
return dataframe
|
||||||
|
|
||||||
def custom_entry_price(self, pair: str, trade: Optional[Trade], current_time: datetime,
|
def custom_entry_price(
|
||||||
proposed_rate: float,
|
self,
|
||||||
entry_tag: Optional[str], side: str, **kwargs) -> float:
|
pair: str,
|
||||||
|
trade: Optional[Trade],
|
||||||
|
current_time: datetime,
|
||||||
|
proposed_rate: float,
|
||||||
|
entry_tag: Optional[str],
|
||||||
|
side: str,
|
||||||
|
**kwargs,
|
||||||
|
) -> float:
|
||||||
return self.new_entry_price
|
return self.new_entry_price
|
||||||
|
|
|
@ -10,37 +10,33 @@ class strategy_test_v3_recursive_issue(IStrategy):
|
||||||
INTERFACE_VERSION = 3
|
INTERFACE_VERSION = 3
|
||||||
|
|
||||||
# Minimal ROI designed for the strategy
|
# Minimal ROI designed for the strategy
|
||||||
minimal_roi = {
|
minimal_roi = {"0": 0.04}
|
||||||
"0": 0.04
|
|
||||||
}
|
|
||||||
|
|
||||||
# Optimal stoploss designed for the strategy
|
# Optimal stoploss designed for the strategy
|
||||||
stoploss = -0.10
|
stoploss = -0.10
|
||||||
|
|
||||||
# Optimal timeframe for the strategy
|
# Optimal timeframe for the strategy
|
||||||
timeframe = '5m'
|
timeframe = "5m"
|
||||||
scenario = CategoricalParameter(['no_bias', 'bias1', 'bias2'], default='bias1', space="buy")
|
scenario = CategoricalParameter(["no_bias", "bias1", "bias2"], default="bias1", space="buy")
|
||||||
|
|
||||||
# Number of candles the strategy requires before producing valid signals
|
# Number of candles the strategy requires before producing valid signals
|
||||||
startup_candle_count: int = 100
|
startup_candle_count: int = 100
|
||||||
|
|
||||||
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
||||||
# bias is introduced here
|
# bias is introduced here
|
||||||
if self.scenario.value == 'no_bias':
|
if self.scenario.value == "no_bias":
|
||||||
dataframe['rsi'] = ta.RSI(dataframe, timeperiod=14)
|
dataframe["rsi"] = ta.RSI(dataframe, timeperiod=14)
|
||||||
else:
|
else:
|
||||||
dataframe['rsi'] = ta.RSI(dataframe, timeperiod=50)
|
dataframe["rsi"] = ta.RSI(dataframe, timeperiod=50)
|
||||||
|
|
||||||
if self.scenario.value == 'bias2':
|
if self.scenario.value == "bias2":
|
||||||
# Has both bias1 and bias2
|
# Has both bias1 and bias2
|
||||||
dataframe['rsi_lookahead'] = ta.RSI(dataframe, timeperiod=50).shift(-1)
|
dataframe["rsi_lookahead"] = ta.RSI(dataframe, timeperiod=50).shift(-1)
|
||||||
|
|
||||||
return dataframe
|
return dataframe
|
||||||
|
|
||||||
def populate_entry_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
def populate_entry_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
||||||
|
|
||||||
return dataframe
|
return dataframe
|
||||||
|
|
||||||
def populate_exit_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
def populate_exit_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
||||||
|
|
||||||
return dataframe
|
return dataframe
|
||||||
|
|
|
@ -9,33 +9,32 @@ from tests.conftest import create_mock_trades_usdt, log_has
|
||||||
|
|
||||||
|
|
||||||
def test_binance_mig_data_conversion(default_conf_usdt, tmp_path, testdatadir):
|
def test_binance_mig_data_conversion(default_conf_usdt, tmp_path, testdatadir):
|
||||||
|
|
||||||
# call doing nothing (spot mode)
|
# call doing nothing (spot mode)
|
||||||
migrate_binance_futures_data(default_conf_usdt)
|
migrate_binance_futures_data(default_conf_usdt)
|
||||||
default_conf_usdt['trading_mode'] = 'futures'
|
default_conf_usdt["trading_mode"] = "futures"
|
||||||
pair_old = 'XRP_USDT'
|
pair_old = "XRP_USDT"
|
||||||
pair_unified = 'XRP_USDT_USDT'
|
pair_unified = "XRP_USDT_USDT"
|
||||||
futures_src = testdatadir / 'futures'
|
futures_src = testdatadir / "futures"
|
||||||
futures_dst = tmp_path / 'futures'
|
futures_dst = tmp_path / "futures"
|
||||||
futures_dst.mkdir()
|
futures_dst.mkdir()
|
||||||
files = [
|
files = [
|
||||||
'-1h-mark.feather',
|
"-1h-mark.feather",
|
||||||
'-1h-futures.feather',
|
"-1h-futures.feather",
|
||||||
'-8h-funding_rate.feather',
|
"-8h-funding_rate.feather",
|
||||||
'-8h-mark.feather',
|
"-8h-mark.feather",
|
||||||
]
|
]
|
||||||
|
|
||||||
# Copy files to tmpdir and rename to old naming
|
# Copy files to tmpdir and rename to old naming
|
||||||
for file in files:
|
for file in files:
|
||||||
fn_after = futures_dst / f'{pair_old}{file}'
|
fn_after = futures_dst / f"{pair_old}{file}"
|
||||||
shutil.copy(futures_src / f'{pair_unified}{file}', fn_after)
|
shutil.copy(futures_src / f"{pair_unified}{file}", fn_after)
|
||||||
|
|
||||||
default_conf_usdt['datadir'] = tmp_path
|
default_conf_usdt["datadir"] = tmp_path
|
||||||
# Migrate files to unified namings
|
# Migrate files to unified namings
|
||||||
migrate_binance_futures_data(default_conf_usdt)
|
migrate_binance_futures_data(default_conf_usdt)
|
||||||
|
|
||||||
for file in files:
|
for file in files:
|
||||||
fn_after = futures_dst / f'{pair_unified}{file}'
|
fn_after = futures_dst / f"{pair_unified}{file}"
|
||||||
assert fn_after.exists()
|
assert fn_after.exists()
|
||||||
|
|
||||||
|
|
||||||
|
@ -47,19 +46,19 @@ def test_binance_mig_db_conversion(default_conf_usdt, fee, caplog):
|
||||||
create_mock_trades_usdt(fee, None)
|
create_mock_trades_usdt(fee, None)
|
||||||
|
|
||||||
for t in Trade.get_trades():
|
for t in Trade.get_trades():
|
||||||
t.trading_mode = 'FUTURES'
|
t.trading_mode = "FUTURES"
|
||||||
t.exchange = 'binance'
|
t.exchange = "binance"
|
||||||
Trade.commit()
|
Trade.commit()
|
||||||
|
|
||||||
default_conf_usdt['trading_mode'] = 'futures'
|
default_conf_usdt["trading_mode"] = "futures"
|
||||||
migrate_binance_futures_names(default_conf_usdt)
|
migrate_binance_futures_names(default_conf_usdt)
|
||||||
assert log_has('Migrating binance futures pairs in database.', caplog)
|
assert log_has("Migrating binance futures pairs in database.", caplog)
|
||||||
|
|
||||||
|
|
||||||
def test_migration_wrapper(default_conf_usdt, mocker):
|
def test_migration_wrapper(default_conf_usdt, mocker):
|
||||||
default_conf_usdt['trading_mode'] = 'futures'
|
default_conf_usdt["trading_mode"] = "futures"
|
||||||
binmock = mocker.patch('freqtrade.util.migrations.migrate_binance_futures_data')
|
binmock = mocker.patch("freqtrade.util.migrations.migrate_binance_futures_data")
|
||||||
funding_mock = mocker.patch('freqtrade.util.migrations.migrate_funding_fee_timeframe')
|
funding_mock = mocker.patch("freqtrade.util.migrations.migrate_funding_fee_timeframe")
|
||||||
migrate_data(default_conf_usdt)
|
migrate_data(default_conf_usdt)
|
||||||
|
|
||||||
assert binmock.call_count == 1
|
assert binmock.call_count == 1
|
||||||
|
|
|
@ -1,82 +1,82 @@
|
||||||
from freqtrade.util import FtPrecise
|
from freqtrade.util import FtPrecise
|
||||||
|
|
||||||
|
|
||||||
ws = FtPrecise('-1.123e-6')
|
ws = FtPrecise("-1.123e-6")
|
||||||
ws = FtPrecise('-1.123e-6')
|
ws = FtPrecise("-1.123e-6")
|
||||||
xs = FtPrecise('0.00000002')
|
xs = FtPrecise("0.00000002")
|
||||||
ys = FtPrecise('69696900000')
|
ys = FtPrecise("69696900000")
|
||||||
zs = FtPrecise('0')
|
zs = FtPrecise("0")
|
||||||
|
|
||||||
|
|
||||||
def test_FtPrecise():
|
def test_FtPrecise():
|
||||||
assert ys * xs == '1393.938'
|
assert ys * xs == "1393.938"
|
||||||
assert xs * ys == '1393.938'
|
assert xs * ys == "1393.938"
|
||||||
|
|
||||||
assert ys + xs == '69696900000.00000002'
|
assert ys + xs == "69696900000.00000002"
|
||||||
assert xs + ys == '69696900000.00000002'
|
assert xs + ys == "69696900000.00000002"
|
||||||
assert xs - ys == '-69696899999.99999998'
|
assert xs - ys == "-69696899999.99999998"
|
||||||
assert ys - xs == '69696899999.99999998'
|
assert ys - xs == "69696899999.99999998"
|
||||||
assert xs / ys == '0'
|
assert xs / ys == "0"
|
||||||
assert ys / xs == '3484845000000000000'
|
assert ys / xs == "3484845000000000000"
|
||||||
|
|
||||||
assert ws * xs == '-0.00000000000002246'
|
assert ws * xs == "-0.00000000000002246"
|
||||||
assert xs * ws == '-0.00000000000002246'
|
assert xs * ws == "-0.00000000000002246"
|
||||||
|
|
||||||
assert ws + xs == '-0.000001103'
|
assert ws + xs == "-0.000001103"
|
||||||
assert xs + ws == '-0.000001103'
|
assert xs + ws == "-0.000001103"
|
||||||
|
|
||||||
assert xs - ws == '0.000001143'
|
assert xs - ws == "0.000001143"
|
||||||
assert ws - xs == '-0.000001143'
|
assert ws - xs == "-0.000001143"
|
||||||
|
|
||||||
assert xs / ws == '-0.017809439002671415'
|
assert xs / ws == "-0.017809439002671415"
|
||||||
assert ws / xs == '-56.15'
|
assert ws / xs == "-56.15"
|
||||||
|
|
||||||
assert zs * ws == '0'
|
assert zs * ws == "0"
|
||||||
assert zs * xs == '0'
|
assert zs * xs == "0"
|
||||||
assert zs * ys == '0'
|
assert zs * ys == "0"
|
||||||
assert ws * zs == '0'
|
assert ws * zs == "0"
|
||||||
assert xs * zs == '0'
|
assert xs * zs == "0"
|
||||||
assert ys * zs == '0'
|
assert ys * zs == "0"
|
||||||
|
|
||||||
assert zs + ws == '-0.000001123'
|
assert zs + ws == "-0.000001123"
|
||||||
assert zs + xs == '0.00000002'
|
assert zs + xs == "0.00000002"
|
||||||
assert zs + ys == '69696900000'
|
assert zs + ys == "69696900000"
|
||||||
assert ws + zs == '-0.000001123'
|
assert ws + zs == "-0.000001123"
|
||||||
assert xs + zs == '0.00000002'
|
assert xs + zs == "0.00000002"
|
||||||
assert ys + zs == '69696900000'
|
assert ys + zs == "69696900000"
|
||||||
|
|
||||||
assert abs(FtPrecise('-500.1')) == '500.1'
|
assert abs(FtPrecise("-500.1")) == "500.1"
|
||||||
assert abs(FtPrecise('213')) == '213'
|
assert abs(FtPrecise("213")) == "213"
|
||||||
|
|
||||||
assert abs(FtPrecise('-500.1')) == '500.1'
|
assert abs(FtPrecise("-500.1")) == "500.1"
|
||||||
assert -FtPrecise('213') == '-213'
|
assert -FtPrecise("213") == "-213"
|
||||||
|
|
||||||
assert FtPrecise('10.1') % FtPrecise('0.5') == '0.1'
|
assert FtPrecise("10.1") % FtPrecise("0.5") == "0.1"
|
||||||
assert FtPrecise('5550') % FtPrecise('120') == '30'
|
assert FtPrecise("5550") % FtPrecise("120") == "30"
|
||||||
|
|
||||||
assert FtPrecise('-0.0') == FtPrecise('0')
|
assert FtPrecise("-0.0") == FtPrecise("0")
|
||||||
assert FtPrecise('5.534000') == FtPrecise('5.5340')
|
assert FtPrecise("5.534000") == FtPrecise("5.5340")
|
||||||
|
|
||||||
assert min(FtPrecise('-3.1415'), FtPrecise('-2')) == '-3.1415'
|
assert min(FtPrecise("-3.1415"), FtPrecise("-2")) == "-3.1415"
|
||||||
|
|
||||||
assert max(FtPrecise('3.1415'), FtPrecise('-2')) == '3.1415'
|
assert max(FtPrecise("3.1415"), FtPrecise("-2")) == "3.1415"
|
||||||
|
|
||||||
assert FtPrecise('2') > FtPrecise('1.2345')
|
assert FtPrecise("2") > FtPrecise("1.2345")
|
||||||
assert not FtPrecise('-3.1415') > FtPrecise('-2')
|
assert not FtPrecise("-3.1415") > FtPrecise("-2")
|
||||||
assert not FtPrecise('3.1415') > FtPrecise('3.1415')
|
assert not FtPrecise("3.1415") > FtPrecise("3.1415")
|
||||||
assert FtPrecise.string_gt('3.14150000000000000000001', '3.1415')
|
assert FtPrecise.string_gt("3.14150000000000000000001", "3.1415")
|
||||||
|
|
||||||
assert FtPrecise('3.1415') >= FtPrecise('3.1415')
|
assert FtPrecise("3.1415") >= FtPrecise("3.1415")
|
||||||
assert FtPrecise('3.14150000000000000000001') >= FtPrecise('3.1415')
|
assert FtPrecise("3.14150000000000000000001") >= FtPrecise("3.1415")
|
||||||
|
|
||||||
assert not FtPrecise('3.1415') < FtPrecise('3.1415')
|
assert not FtPrecise("3.1415") < FtPrecise("3.1415")
|
||||||
|
|
||||||
assert FtPrecise('3.1415') <= FtPrecise('3.1415')
|
assert FtPrecise("3.1415") <= FtPrecise("3.1415")
|
||||||
assert FtPrecise('3.1415') <= FtPrecise('3.14150000000000000000001')
|
assert FtPrecise("3.1415") <= FtPrecise("3.14150000000000000000001")
|
||||||
|
|
||||||
assert FtPrecise(213) == '213'
|
assert FtPrecise(213) == "213"
|
||||||
assert FtPrecise(-213) == '-213'
|
assert FtPrecise(-213) == "-213"
|
||||||
assert str(FtPrecise(-213)) == '-213'
|
assert str(FtPrecise(-213)) == "-213"
|
||||||
assert FtPrecise(213.2) == '213.2'
|
assert FtPrecise(213.2) == "213.2"
|
||||||
assert float(FtPrecise(213.2)) == 213.2
|
assert float(FtPrecise(213.2)) == 213.2
|
||||||
assert float(FtPrecise(-213.2)) == -213.2
|
assert float(FtPrecise(-213.2)) == -213.2
|
||||||
|
|
|
@ -49,16 +49,18 @@ def test_dt_ts_none():
|
||||||
|
|
||||||
def test_dt_utc():
|
def test_dt_utc():
|
||||||
assert dt_utc(2023, 5, 5) == datetime(2023, 5, 5, tzinfo=timezone.utc)
|
assert dt_utc(2023, 5, 5) == datetime(2023, 5, 5, tzinfo=timezone.utc)
|
||||||
assert dt_utc(2023, 5, 5, 0, 0, 0, 555500) == datetime(2023, 5, 5, 0, 0, 0, 555500,
|
assert dt_utc(2023, 5, 5, 0, 0, 0, 555500) == datetime(
|
||||||
tzinfo=timezone.utc)
|
2023, 5, 5, 0, 0, 0, 555500, tzinfo=timezone.utc
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize('as_ms', [True, False])
|
@pytest.mark.parametrize("as_ms", [True, False])
|
||||||
def test_dt_from_ts(as_ms):
|
def test_dt_from_ts(as_ms):
|
||||||
multi = 1000 if as_ms else 1
|
multi = 1000 if as_ms else 1
|
||||||
assert dt_from_ts(1683244800.0 * multi) == datetime(2023, 5, 5, tzinfo=timezone.utc)
|
assert dt_from_ts(1683244800.0 * multi) == datetime(2023, 5, 5, tzinfo=timezone.utc)
|
||||||
assert dt_from_ts(1683244800.5555 * multi) == datetime(2023, 5, 5, 0, 0, 0, 555500,
|
assert dt_from_ts(1683244800.5555 * multi) == datetime(
|
||||||
tzinfo=timezone.utc)
|
2023, 5, 5, 0, 0, 0, 555500, tzinfo=timezone.utc
|
||||||
|
)
|
||||||
# As int
|
# As int
|
||||||
assert dt_from_ts(1683244800 * multi) == datetime(2023, 5, 5, tzinfo=timezone.utc)
|
assert dt_from_ts(1683244800 * multi) == datetime(2023, 5, 5, tzinfo=timezone.utc)
|
||||||
# As milliseconds
|
# As milliseconds
|
||||||
|
@ -73,18 +75,18 @@ def test_dt_floor_day():
|
||||||
|
|
||||||
|
|
||||||
def test_shorten_date() -> None:
|
def test_shorten_date() -> None:
|
||||||
str_data = '1 day, 2 hours, 3 minutes, 4 seconds ago'
|
str_data = "1 day, 2 hours, 3 minutes, 4 seconds ago"
|
||||||
str_shorten_data = '1 d, 2 h, 3 min, 4 sec ago'
|
str_shorten_data = "1 d, 2 h, 3 min, 4 sec ago"
|
||||||
assert shorten_date(str_data) == str_shorten_data
|
assert shorten_date(str_data) == str_shorten_data
|
||||||
|
|
||||||
|
|
||||||
def test_dt_humanize() -> None:
|
def test_dt_humanize() -> None:
|
||||||
assert dt_humanize_delta(dt_now()) == 'now'
|
assert dt_humanize_delta(dt_now()) == "now"
|
||||||
assert dt_humanize_delta(dt_now() - timedelta(minutes=50)) == '50 minutes ago'
|
assert dt_humanize_delta(dt_now() - timedelta(minutes=50)) == "50 minutes ago"
|
||||||
assert dt_humanize_delta(dt_now() - timedelta(hours=16)) == '16 hours ago'
|
assert dt_humanize_delta(dt_now() - timedelta(hours=16)) == "16 hours ago"
|
||||||
assert dt_humanize_delta(dt_now() - timedelta(hours=16, minutes=30)) == '16 hours ago'
|
assert dt_humanize_delta(dt_now() - timedelta(hours=16, minutes=30)) == "16 hours ago"
|
||||||
assert dt_humanize_delta(dt_now() - timedelta(days=16, hours=10, minutes=25)) == '16 days ago'
|
assert dt_humanize_delta(dt_now() - timedelta(days=16, hours=10, minutes=25)) == "16 days ago"
|
||||||
assert dt_humanize_delta(dt_now() - timedelta(minutes=50)) == '50 minutes ago'
|
assert dt_humanize_delta(dt_now() - timedelta(minutes=50)) == "50 minutes ago"
|
||||||
|
|
||||||
|
|
||||||
def test_format_ms_time() -> None:
|
def test_format_ms_time() -> None:
|
||||||
|
@ -93,20 +95,19 @@ def test_format_ms_time() -> None:
|
||||||
date = format_ms_time(date_in_epoch_ms)
|
date = format_ms_time(date_in_epoch_ms)
|
||||||
assert isinstance(date, str)
|
assert isinstance(date, str)
|
||||||
res = datetime(2018, 4, 10, 18, 2, 1, tzinfo=timezone.utc)
|
res = datetime(2018, 4, 10, 18, 2, 1, tzinfo=timezone.utc)
|
||||||
assert date == res.strftime('%Y-%m-%dT%H:%M:%S')
|
assert date == res.strftime("%Y-%m-%dT%H:%M:%S")
|
||||||
assert date == '2018-04-10T18:02:01'
|
assert date == "2018-04-10T18:02:01"
|
||||||
res = datetime(2017, 12, 13, 8, 2, 1, tzinfo=timezone.utc)
|
res = datetime(2017, 12, 13, 8, 2, 1, tzinfo=timezone.utc)
|
||||||
# Date 2017-12-13 08:02:01
|
# Date 2017-12-13 08:02:01
|
||||||
date_in_epoch_ms = 1513152121000
|
date_in_epoch_ms = 1513152121000
|
||||||
assert format_ms_time(date_in_epoch_ms) == res.strftime('%Y-%m-%dT%H:%M:%S')
|
assert format_ms_time(date_in_epoch_ms) == res.strftime("%Y-%m-%dT%H:%M:%S")
|
||||||
|
|
||||||
|
|
||||||
def test_format_date() -> None:
|
def test_format_date() -> None:
|
||||||
|
|
||||||
date = datetime(2023, 9, 1, 5, 2, 3, 455555, tzinfo=timezone.utc)
|
date = datetime(2023, 9, 1, 5, 2, 3, 455555, tzinfo=timezone.utc)
|
||||||
assert format_date(date) == '2023-09-01 05:02:03'
|
assert format_date(date) == "2023-09-01 05:02:03"
|
||||||
assert format_date(None) == ''
|
assert format_date(None) == ""
|
||||||
|
|
||||||
date = datetime(2021, 9, 30, 22, 59, 3, 455555, tzinfo=timezone.utc)
|
date = datetime(2021, 9, 30, 22, 59, 3, 455555, tzinfo=timezone.utc)
|
||||||
assert format_date(date) == '2021-09-30 22:59:03'
|
assert format_date(date) == "2021-09-30 22:59:03"
|
||||||
assert format_date(None) == ''
|
assert format_date(None) == ""
|
||||||
|
|
|
@ -2,36 +2,35 @@ from freqtrade.util import decimals_per_coin, fmt_coin, round_value
|
||||||
|
|
||||||
|
|
||||||
def test_decimals_per_coin():
|
def test_decimals_per_coin():
|
||||||
assert decimals_per_coin('USDT') == 3
|
assert decimals_per_coin("USDT") == 3
|
||||||
assert decimals_per_coin('EUR') == 3
|
assert decimals_per_coin("EUR") == 3
|
||||||
assert decimals_per_coin('BTC') == 8
|
assert decimals_per_coin("BTC") == 8
|
||||||
assert decimals_per_coin('ETH') == 5
|
assert decimals_per_coin("ETH") == 5
|
||||||
|
|
||||||
|
|
||||||
def test_fmt_coin():
|
def test_fmt_coin():
|
||||||
assert fmt_coin(222.222222, 'USDT') == '222.222 USDT'
|
assert fmt_coin(222.222222, "USDT") == "222.222 USDT"
|
||||||
assert fmt_coin(222.2, 'USDT', keep_trailing_zeros=True) == '222.200 USDT'
|
assert fmt_coin(222.2, "USDT", keep_trailing_zeros=True) == "222.200 USDT"
|
||||||
assert fmt_coin(222.2, 'USDT') == '222.2 USDT'
|
assert fmt_coin(222.2, "USDT") == "222.2 USDT"
|
||||||
assert fmt_coin(222.12745, 'EUR') == '222.127 EUR'
|
assert fmt_coin(222.12745, "EUR") == "222.127 EUR"
|
||||||
assert fmt_coin(0.1274512123, 'BTC') == '0.12745121 BTC'
|
assert fmt_coin(0.1274512123, "BTC") == "0.12745121 BTC"
|
||||||
assert fmt_coin(0.1274512123, 'ETH') == '0.12745 ETH'
|
assert fmt_coin(0.1274512123, "ETH") == "0.12745 ETH"
|
||||||
|
|
||||||
assert fmt_coin(222.222222, 'USDT', False) == '222.222'
|
assert fmt_coin(222.222222, "USDT", False) == "222.222"
|
||||||
assert fmt_coin(222.2, 'USDT', False) == '222.2'
|
assert fmt_coin(222.2, "USDT", False) == "222.2"
|
||||||
assert fmt_coin(222.00, 'USDT', False) == '222'
|
assert fmt_coin(222.00, "USDT", False) == "222"
|
||||||
assert fmt_coin(222.12745, 'EUR', False) == '222.127'
|
assert fmt_coin(222.12745, "EUR", False) == "222.127"
|
||||||
assert fmt_coin(0.1274512123, 'BTC', False) == '0.12745121'
|
assert fmt_coin(0.1274512123, "BTC", False) == "0.12745121"
|
||||||
assert fmt_coin(0.1274512123, 'ETH', False) == '0.12745'
|
assert fmt_coin(0.1274512123, "ETH", False) == "0.12745"
|
||||||
assert fmt_coin(222.2, 'USDT', False, True) == '222.200'
|
assert fmt_coin(222.2, "USDT", False, True) == "222.200"
|
||||||
|
|
||||||
|
|
||||||
def test_round_value():
|
def test_round_value():
|
||||||
|
assert round_value(222.222222, 3) == "222.222"
|
||||||
assert round_value(222.222222, 3) == '222.222'
|
assert round_value(222.2, 3) == "222.2"
|
||||||
assert round_value(222.2, 3) == '222.2'
|
assert round_value(222.00, 3) == "222"
|
||||||
assert round_value(222.00, 3) == '222'
|
assert round_value(222.12745, 3) == "222.127"
|
||||||
assert round_value(222.12745, 3) == '222.127'
|
assert round_value(0.1274512123, 8) == "0.12745121"
|
||||||
assert round_value(0.1274512123, 8) == '0.12745121'
|
assert round_value(0.1274512123, 5) == "0.12745"
|
||||||
assert round_value(0.1274512123, 5) == '0.12745'
|
assert round_value(222.2, 3, True) == "222.200"
|
||||||
assert round_value(222.2, 3, True) == '222.200'
|
assert round_value(222.2, 0, True) == "222"
|
||||||
assert round_value(222.2, 0, True) == '222'
|
|
||||||
|
|
|
@ -4,22 +4,21 @@ from freqtrade.util.migrations import migrate_funding_fee_timeframe
|
||||||
|
|
||||||
|
|
||||||
def test_migrate_funding_rate_timeframe(default_conf_usdt, tmp_path, testdatadir):
|
def test_migrate_funding_rate_timeframe(default_conf_usdt, tmp_path, testdatadir):
|
||||||
|
copytree(testdatadir / "futures", tmp_path / "futures")
|
||||||
copytree(testdatadir / 'futures', tmp_path / 'futures')
|
file_4h = tmp_path / "futures" / "XRP_USDT_USDT-4h-funding_rate.feather"
|
||||||
file_4h = tmp_path / 'futures' / 'XRP_USDT_USDT-4h-funding_rate.feather'
|
file_8h = tmp_path / "futures" / "XRP_USDT_USDT-8h-funding_rate.feather"
|
||||||
file_8h = tmp_path / 'futures' / 'XRP_USDT_USDT-8h-funding_rate.feather'
|
file_1h = tmp_path / "futures" / "XRP_USDT_USDT-1h-futures.feather"
|
||||||
file_1h = tmp_path / 'futures' / 'XRP_USDT_USDT-1h-futures.feather'
|
|
||||||
file_8h.rename(file_4h)
|
file_8h.rename(file_4h)
|
||||||
assert file_1h.exists()
|
assert file_1h.exists()
|
||||||
assert file_4h.exists()
|
assert file_4h.exists()
|
||||||
assert not file_8h.exists()
|
assert not file_8h.exists()
|
||||||
|
|
||||||
default_conf_usdt['datadir'] = tmp_path
|
default_conf_usdt["datadir"] = tmp_path
|
||||||
|
|
||||||
# Inactive on spot trading ...
|
# Inactive on spot trading ...
|
||||||
migrate_funding_fee_timeframe(default_conf_usdt, None)
|
migrate_funding_fee_timeframe(default_conf_usdt, None)
|
||||||
|
|
||||||
default_conf_usdt['trading_mode'] = 'futures'
|
default_conf_usdt["trading_mode"] = "futures"
|
||||||
|
|
||||||
migrate_funding_fee_timeframe(default_conf_usdt, None)
|
migrate_funding_fee_timeframe(default_conf_usdt, None)
|
||||||
|
|
||||||
|
|
|
@ -6,10 +6,8 @@ from freqtrade.util import MeasureTime
|
||||||
|
|
||||||
|
|
||||||
def test_measure_time():
|
def test_measure_time():
|
||||||
|
|
||||||
callback = MagicMock()
|
callback = MagicMock()
|
||||||
with time_machine.travel("2021-09-01 05:00:00 +00:00", tick=False) as t:
|
with time_machine.travel("2021-09-01 05:00:00 +00:00", tick=False) as t:
|
||||||
|
|
||||||
measure = MeasureTime(callback, 5, ttl=60)
|
measure = MeasureTime(callback, 5, ttl=60)
|
||||||
with measure:
|
with measure:
|
||||||
pass
|
pass
|
||||||
|
|
|
@ -4,31 +4,29 @@ from freqtrade.util import PeriodicCache
|
||||||
|
|
||||||
|
|
||||||
def test_ttl_cache():
|
def test_ttl_cache():
|
||||||
|
|
||||||
with time_machine.travel("2021-09-01 05:00:00 +00:00", tick=False) as t:
|
with time_machine.travel("2021-09-01 05:00:00 +00:00", tick=False) as t:
|
||||||
|
|
||||||
cache = PeriodicCache(5, ttl=60)
|
cache = PeriodicCache(5, ttl=60)
|
||||||
cache1h = PeriodicCache(5, ttl=3600)
|
cache1h = PeriodicCache(5, ttl=3600)
|
||||||
|
|
||||||
assert cache.timer() == 1630472400.0
|
assert cache.timer() == 1630472400.0
|
||||||
cache['a'] = 1235
|
cache["a"] = 1235
|
||||||
cache1h['a'] = 555123
|
cache1h["a"] = 555123
|
||||||
assert 'a' in cache
|
assert "a" in cache
|
||||||
assert 'a' in cache1h
|
assert "a" in cache1h
|
||||||
|
|
||||||
t.move_to("2021-09-01 05:00:59 +00:00")
|
t.move_to("2021-09-01 05:00:59 +00:00")
|
||||||
assert 'a' in cache
|
assert "a" in cache
|
||||||
assert 'a' in cache1h
|
assert "a" in cache1h
|
||||||
|
|
||||||
# Cache expired
|
# Cache expired
|
||||||
t.move_to("2021-09-01 05:01:00 +00:00")
|
t.move_to("2021-09-01 05:01:00 +00:00")
|
||||||
assert 'a' not in cache
|
assert "a" not in cache
|
||||||
assert 'a' in cache1h
|
assert "a" in cache1h
|
||||||
|
|
||||||
t.move_to("2021-09-01 05:59:59 +00:00")
|
t.move_to("2021-09-01 05:59:59 +00:00")
|
||||||
assert 'a' not in cache
|
assert "a" not in cache
|
||||||
assert 'a' in cache1h
|
assert "a" in cache1h
|
||||||
|
|
||||||
t.move_to("2021-09-01 06:00:00 +00:00")
|
t.move_to("2021-09-01 06:00:00 +00:00")
|
||||||
assert 'a' not in cache
|
assert "a" not in cache
|
||||||
assert 'a' not in cache1h
|
assert "a" not in cache1h
|
||||||
|
|
|
@ -5,15 +5,16 @@ from freqtrade.util import render_template, render_template_with_fallback
|
||||||
|
|
||||||
def test_render_template_fallback():
|
def test_render_template_fallback():
|
||||||
from jinja2.exceptions import TemplateNotFound
|
from jinja2.exceptions import TemplateNotFound
|
||||||
|
|
||||||
with pytest.raises(TemplateNotFound):
|
with pytest.raises(TemplateNotFound):
|
||||||
val = render_template(
|
val = render_template(
|
||||||
templatefile='subtemplates/indicators_does-not-exist.j2',
|
templatefile="subtemplates/indicators_does-not-exist.j2",
|
||||||
arguments={},
|
arguments={},
|
||||||
)
|
)
|
||||||
|
|
||||||
val = render_template_with_fallback(
|
val = render_template_with_fallback(
|
||||||
templatefile='strategy_subtemplates/indicators_does-not-exist.j2',
|
templatefile="strategy_subtemplates/indicators_does-not-exist.j2",
|
||||||
templatefallbackfile='strategy_subtemplates/indicators_minimal.j2',
|
templatefallbackfile="strategy_subtemplates/indicators_minimal.j2",
|
||||||
)
|
)
|
||||||
assert isinstance(val, str)
|
assert isinstance(val, str)
|
||||||
assert 'if self.dp' in val
|
assert "if self.dp" in val
|
||||||
|
|
Loading…
Reference in New Issue
Block a user