diff --git a/tests/strategy/strats/broken_strats/broken_futures_strategies.py b/tests/strategy/strats/broken_strats/broken_futures_strategies.py index bb7ce2b32..b2131e63e 100644 --- a/tests/strategy/strats/broken_strats/broken_futures_strategies.py +++ b/tests/strategy/strats/broken_strats/broken_futures_strategies.py @@ -12,7 +12,6 @@ from freqtrade.strategy.interface import IStrategy class TestStrategyNoImplements(IStrategy): - def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame: return super().populate_indicators(dataframe, metadata) @@ -26,9 +25,15 @@ class TestStrategyImplementCustomSell(TestStrategyNoImplementSell): def populate_exit_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame: return super().populate_exit_trend(dataframe, metadata) - def custom_sell(self, pair: str, trade, current_time: datetime, - current_rate: float, current_profit: float, - **kwargs): + def custom_sell( + self, + pair: str, + trade, + current_time: datetime, + current_rate: float, + current_profit: float, + **kwargs, + ): return False @@ -36,8 +41,9 @@ class TestStrategyImplementBuyTimeout(TestStrategyNoImplementSell): def populate_exit_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame: return super().populate_exit_trend(dataframe, metadata) - def check_buy_timeout(self, pair: str, trade, order: Order, - current_time: datetime, **kwargs) -> bool: + def check_buy_timeout( + self, pair: str, trade, order: Order, current_time: datetime, **kwargs + ) -> bool: return False @@ -45,6 +51,7 @@ class TestStrategyImplementSellTimeout(TestStrategyNoImplementSell): def populate_exit_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame: return super().populate_exit_trend(dataframe, metadata) - def check_sell_timeout(self, pair: str, trade, order: Order, - current_time: datetime, **kwargs) -> bool: + def check_sell_timeout( + self, pair: str, trade, order: Order, current_time: datetime, **kwargs + ) -> bool: return False diff --git a/tests/strategy/strats/broken_strats/legacy_strategy_v1.py b/tests/strategy/strats/broken_strats/legacy_strategy_v1.py index f3b8c2696..b0d7a2ae6 100644 --- a/tests/strategy/strats/broken_strats/legacy_strategy_v1.py +++ b/tests/strategy/strats/broken_strats/legacy_strategy_v1.py @@ -6,25 +6,16 @@ from freqtrade.strategy import IStrategy # Dummy strategy - no longer loads but raises an exception. 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 - timeframe = '5m' + timeframe = "5m" def populate_indicators(self, dataframe: DataFrame) -> DataFrame: - return dataframe def populate_buy_trend(self, dataframe: DataFrame) -> DataFrame: - return dataframe def populate_sell_trend(self, dataframe: DataFrame) -> DataFrame: - return dataframe diff --git a/tests/strategy/strats/freqai_rl_test_strat.py b/tests/strategy/strats/freqai_rl_test_strat.py index 2bf4aaa30..359ac764d 100644 --- a/tests/strategy/strats/freqai_rl_test_strat.py +++ b/tests/strategy/strats/freqai_rl_test_strat.py @@ -25,22 +25,20 @@ class freqai_rl_test_strat(IStrategy): startup_candle_count: int = 300 can_short = False - def feature_engineering_expand_all(self, dataframe: DataFrame, period: int, - metadata: Dict, **kwargs): - + def feature_engineering_expand_all( + self, dataframe: DataFrame, period: int, metadata: Dict, **kwargs + ): dataframe["%-rsi-period"] = ta.RSI(dataframe, timeperiod=period) return dataframe def feature_engineering_expand_basic(self, dataframe: DataFrame, metadata: Dict, **kwargs): - dataframe["%-pct-change"] = dataframe["close"].pct_change() dataframe["%-raw_volume"] = dataframe["volume"] return dataframe def feature_engineering_standard(self, dataframe: DataFrame, metadata: Dict, **kwargs): - dataframe["%-day_of_week"] = dataframe["date"].dt.dayofweek dataframe["%-hour_of_day"] = dataframe["date"].dt.hour @@ -52,19 +50,16 @@ class freqai_rl_test_strat(IStrategy): return dataframe def set_freqai_targets(self, dataframe: DataFrame, metadata: Dict, **kwargs): - dataframe["&-action"] = 0 return dataframe def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame: - dataframe = self.freqai.start(dataframe, metadata, self) return dataframe def populate_entry_trend(self, df: DataFrame, metadata: dict) -> DataFrame: - enter_long_conditions = [df["do_predict"] == 1, df["&-action"] == 1] if enter_long_conditions: diff --git a/tests/strategy/strats/freqai_test_classifier.py b/tests/strategy/strats/freqai_test_classifier.py index a68a87b2a..ab8ab87cb 100644 --- a/tests/strategy/strats/freqai_test_classifier.py +++ b/tests/strategy/strats/freqai_test_classifier.py @@ -57,9 +57,9 @@ class freqai_test_classifier(IStrategy): informative_pairs.append((pair, tf)) return informative_pairs - def feature_engineering_expand_all(self, dataframe: DataFrame, period: int, - metadata: Dict, **kwargs): - + def feature_engineering_expand_all( + self, dataframe: DataFrame, period: int, metadata: Dict, **kwargs + ): dataframe["%-rsi-period"] = ta.RSI(dataframe, timeperiod=period) dataframe["%-mfi-period"] = ta.MFI(dataframe, timeperiod=period) dataframe["%-adx-period"] = ta.ADX(dataframe, timeperiod=period) @@ -67,7 +67,6 @@ class freqai_test_classifier(IStrategy): return dataframe def feature_engineering_expand_basic(self, dataframe: DataFrame, metadata: Dict, **kwargs): - dataframe["%-pct-change"] = dataframe["close"].pct_change() dataframe["%-raw_volume"] = dataframe["volume"] dataframe["%-raw_price"] = dataframe["close"] @@ -75,7 +74,6 @@ class freqai_test_classifier(IStrategy): return dataframe def feature_engineering_standard(self, dataframe: DataFrame, metadata: Dict, **kwargs): - dataframe["%-day_of_week"] = dataframe["date"].dt.dayofweek dataframe["%-hour_of_day"] = dataframe["date"].dt.hour @@ -83,13 +81,13 @@ class freqai_test_classifier(IStrategy): def set_freqai_targets(self, dataframe: DataFrame, metadata: Dict, **kwargs): self.freqai.class_names = ["down", "up"] - dataframe['&s-up_or_down'] = np.where(dataframe["close"].shift(-100) > - dataframe["close"], 'up', 'down') + dataframe["&s-up_or_down"] = np.where( + dataframe["close"].shift(-100) > dataframe["close"], "up", "down" + ) return dataframe def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame: - self.freqai_info = self.config["freqai"] dataframe = self.freqai.start(dataframe, metadata, self) @@ -97,15 +95,14 @@ class freqai_test_classifier(IStrategy): return 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: df.loc[ reduce(lambda x, y: x & y, enter_long_conditions), ["enter_long", "enter_tag"] ] = (1, "long") - enter_short_conditions = [df['&s-up_or_down'] == 'down'] + enter_short_conditions = [df["&s-up_or_down"] == "down"] if enter_short_conditions: df.loc[ @@ -115,5 +112,4 @@ class freqai_test_classifier(IStrategy): return df def populate_exit_trend(self, df: DataFrame, metadata: dict) -> DataFrame: - return df diff --git a/tests/strategy/strats/freqai_test_multimodel_classifier_strat.py b/tests/strategy/strats/freqai_test_multimodel_classifier_strat.py index b2ddc21e3..ef32edf2a 100644 --- a/tests/strategy/strats/freqai_test_multimodel_classifier_strat.py +++ b/tests/strategy/strats/freqai_test_multimodel_classifier_strat.py @@ -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) - def feature_engineering_expand_all(self, dataframe: DataFrame, period: int, - metadata: Dict, **kwargs): - + def feature_engineering_expand_all( + self, dataframe: DataFrame, period: int, metadata: Dict, **kwargs + ): dataframe["%-rsi-period"] = ta.RSI(dataframe, timeperiod=period) dataframe["%-mfi-period"] = ta.MFI(dataframe, timeperiod=period) dataframe["%-adx-period"] = ta.ADX(dataframe, timeperiod=period) @@ -54,7 +54,6 @@ class freqai_test_multimodel_classifier_strat(IStrategy): return dataframe def feature_engineering_expand_basic(self, dataframe: DataFrame, metadata: Dict, **kwargs): - dataframe["%-pct-change"] = dataframe["close"].pct_change() dataframe["%-raw_volume"] = dataframe["volume"] dataframe["%-raw_price"] = dataframe["close"] @@ -62,24 +61,23 @@ class freqai_test_multimodel_classifier_strat(IStrategy): return dataframe def feature_engineering_standard(self, dataframe: DataFrame, metadata: Dict, **kwargs): - dataframe["%-day_of_week"] = dataframe["date"].dt.dayofweek dataframe["%-hour_of_day"] = dataframe["date"].dt.hour return dataframe def set_freqai_targets(self, dataframe: 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["close"], 'up', 'down') - - dataframe['&s-up_or_down2'] = np.where(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 def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame: - self.freqai_info = self.config["freqai"] dataframe = self.freqai.start(dataframe, metadata, self) @@ -89,7 +87,6 @@ class freqai_test_multimodel_classifier_strat(IStrategy): return dataframe def populate_entry_trend(self, df: DataFrame, metadata: dict) -> DataFrame: - enter_long_conditions = [df["do_predict"] == 1, df["&-s_close"] > df["target_roi"]] if enter_long_conditions: diff --git a/tests/strategy/strats/freqai_test_multimodel_strat.py b/tests/strategy/strats/freqai_test_multimodel_strat.py index 5b09598a5..46df7e275 100644 --- a/tests/strategy/strats/freqai_test_multimodel_strat.py +++ b/tests/strategy/strats/freqai_test_multimodel_strat.py @@ -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) - def feature_engineering_expand_all(self, dataframe: DataFrame, period: int, - metadata: Dict, **kwargs): - + def feature_engineering_expand_all( + self, dataframe: DataFrame, period: int, metadata: Dict, **kwargs + ): dataframe["%-rsi-period"] = ta.RSI(dataframe, timeperiod=period) dataframe["%-mfi-period"] = ta.MFI(dataframe, timeperiod=period) dataframe["%-adx-period"] = ta.ADX(dataframe, timeperiod=period) @@ -53,7 +53,6 @@ class freqai_test_multimodel_strat(IStrategy): return dataframe def feature_engineering_expand_basic(self, dataframe: DataFrame, metadata: Dict, **kwargs): - dataframe["%-pct-change"] = dataframe["close"].pct_change() dataframe["%-raw_volume"] = dataframe["volume"] dataframe["%-raw_price"] = dataframe["close"] @@ -61,14 +60,12 @@ class freqai_test_multimodel_strat(IStrategy): return dataframe def feature_engineering_standard(self, dataframe: DataFrame, metadata: Dict, **kwargs): - dataframe["%-day_of_week"] = dataframe["date"].dt.dayofweek dataframe["%-hour_of_day"] = dataframe["date"].dt.hour return dataframe def set_freqai_targets(self, dataframe: DataFrame, metadata: Dict, **kwargs): - dataframe["&-s_close"] = ( dataframe["close"] .shift(-self.freqai_info["feature_parameters"]["label_period_candles"]) @@ -76,15 +73,14 @@ class freqai_test_multimodel_strat(IStrategy): .mean() / dataframe["close"] - 1 - ) + ) dataframe["&-s_range"] = ( dataframe["close"] .shift(-self.freqai_info["feature_parameters"]["label_period_candles"]) .rolling(self.freqai_info["feature_parameters"]["label_period_candles"]) .max() - - - dataframe["close"] + - dataframe["close"] .shift(-self.freqai_info["feature_parameters"]["label_period_candles"]) .rolling(self.freqai_info["feature_parameters"]["label_period_candles"]) .min() @@ -93,7 +89,6 @@ class freqai_test_multimodel_strat(IStrategy): return dataframe def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame: - self.freqai_info = self.config["freqai"] dataframe = self.freqai.start(dataframe, metadata, self) @@ -103,7 +98,6 @@ class freqai_test_multimodel_strat(IStrategy): return dataframe def populate_entry_trend(self, df: DataFrame, metadata: dict) -> DataFrame: - enter_long_conditions = [df["do_predict"] == 1, df["&-s_close"] > df["target_roi"]] if enter_long_conditions: diff --git a/tests/strategy/strats/freqai_test_strat.py b/tests/strategy/strats/freqai_test_strat.py index 6db308406..90c4642ba 100644 --- a/tests/strategy/strats/freqai_test_strat.py +++ b/tests/strategy/strats/freqai_test_strat.py @@ -43,9 +43,9 @@ class freqai_test_strat(IStrategy): ) max_roi_time_long = IntParameter(0, 800, default=400, space="sell", optimize=False, load=True) - def feature_engineering_expand_all(self, dataframe: DataFrame, period: int, - metadata: Dict, **kwargs): - + def feature_engineering_expand_all( + self, dataframe: DataFrame, period: int, metadata: Dict, **kwargs + ): dataframe["%-rsi-period"] = ta.RSI(dataframe, timeperiod=period) dataframe["%-mfi-period"] = ta.MFI(dataframe, timeperiod=period) dataframe["%-adx-period"] = ta.ADX(dataframe, timeperiod=period) @@ -53,7 +53,6 @@ class freqai_test_strat(IStrategy): return dataframe def feature_engineering_expand_basic(self, dataframe: DataFrame, metadata: Dict, **kwargs): - dataframe["%-pct-change"] = dataframe["close"].pct_change() dataframe["%-raw_volume"] = dataframe["volume"] dataframe["%-raw_price"] = dataframe["close"] @@ -61,14 +60,12 @@ class freqai_test_strat(IStrategy): return dataframe def feature_engineering_standard(self, dataframe: DataFrame, metadata: Dict, **kwargs): - dataframe["%-day_of_week"] = dataframe["date"].dt.dayofweek dataframe["%-hour_of_day"] = dataframe["date"].dt.hour return dataframe def set_freqai_targets(self, dataframe: DataFrame, metadata: Dict, **kwargs): - dataframe["&-s_close"] = ( dataframe["close"] .shift(-self.freqai_info["feature_parameters"]["label_period_candles"]) @@ -76,12 +73,11 @@ class freqai_test_strat(IStrategy): .mean() / dataframe["close"] - 1 - ) + ) return dataframe def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame: - self.freqai_info = self.config["freqai"] dataframe = self.freqai.start(dataframe, metadata, self) @@ -91,7 +87,6 @@ class freqai_test_strat(IStrategy): return dataframe def populate_entry_trend(self, df: DataFrame, metadata: dict) -> DataFrame: - enter_long_conditions = [df["do_predict"] == 1, df["&-s_close"] > df["target_roi"]] if enter_long_conditions: diff --git a/tests/strategy/strats/hyperoptable_strategy.py b/tests/strategy/strats/hyperoptable_strategy.py index d05e8ead2..bc71ed3ae 100644 --- a/tests/strategy/strats/hyperoptable_strategy.py +++ b/tests/strategy/strats/hyperoptable_strategy.py @@ -17,20 +17,18 @@ class HyperoptableStrategy(StrategyTestV3): """ buy_params = { - 'buy_rsi': 35, + "buy_rsi": 35, # Intentionally not specified, so "default" is tested # 'buy_plusdi': 0.4 } - sell_params = { - 'sell_rsi': 74, - 'sell_minusdi': 0.4 - } + sell_params = {"sell_rsi": 74, "sell_minusdi": 0.4} - buy_plusdi = RealParameter(low=0, high=1, default=0.5, space='buy') - 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', - load=False) + buy_plusdi = RealParameter(low=0, high=1, default=0.5, space="buy") + 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", load=False + ) protection_enabled = BooleanParameter(default=True) protection_cooldown_lookback = IntParameter([0, 50], default=30) @@ -43,10 +41,12 @@ class HyperoptableStrategy(StrategyTestV3): def protections(self): prot = [] if self.protection_enabled.value: - prot.append({ - "method": "CooldownPeriod", - "stop_duration_candles": self.protection_cooldown_lookback.value - }) + prot.append( + { + "method": "CooldownPeriod", + "stop_duration_candles": self.protection_cooldown_lookback.value, + } + ) return prot bot_loop_started = False @@ -60,7 +60,7 @@ class HyperoptableStrategy(StrategyTestV3): Parameters can also be defined here ... """ 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): """ @@ -84,16 +84,14 @@ class HyperoptableStrategy(StrategyTestV3): """ dataframe.loc[ ( - (dataframe['rsi'] < self.buy_rsi.value) & - (dataframe['fastd'] < 35) & - (dataframe['adx'] > 30) & - (dataframe['plus_di'] > self.buy_plusdi.value) - ) | - ( - (dataframe['adx'] > 65) & - (dataframe['plus_di'] > self.buy_plusdi.value) - ), - 'buy'] = 1 + (dataframe["rsi"] < self.buy_rsi.value) + & (dataframe["fastd"] < 35) + & (dataframe["adx"] > 30) + & (dataframe["plus_di"] > self.buy_plusdi.value) + ) + | ((dataframe["adx"] > 65) & (dataframe["plus_di"] > self.buy_plusdi.value)), + "buy", + ] = 1 return dataframe @@ -107,15 +105,13 @@ class HyperoptableStrategy(StrategyTestV3): dataframe.loc[ ( ( - (qtpylib.crossed_above(dataframe['rsi'], self.sell_rsi.value)) | - (qtpylib.crossed_above(dataframe['fastd'], 70)) - ) & - (dataframe['adx'] > 10) & - (dataframe['minus_di'] > 0) - ) | - ( - (dataframe['adx'] > 70) & - (dataframe['minus_di'] > self.sell_minusdi.value) - ), - 'sell'] = 1 + (qtpylib.crossed_above(dataframe["rsi"], self.sell_rsi.value)) + | (qtpylib.crossed_above(dataframe["fastd"], 70)) + ) + & (dataframe["adx"] > 10) + & (dataframe["minus_di"] > 0) + ) + | ((dataframe["adx"] > 70) & (dataframe["minus_di"] > self.sell_minusdi.value)), + "sell", + ] = 1 return dataframe diff --git a/tests/strategy/strats/hyperoptable_strategy_v2.py b/tests/strategy/strats/hyperoptable_strategy_v2.py index 94a15b456..650c587f5 100644 --- a/tests/strategy/strats/hyperoptable_strategy_v2.py +++ b/tests/strategy/strats/hyperoptable_strategy_v2.py @@ -15,20 +15,22 @@ class HyperoptableStrategyV2(StrategyTestV2): """ buy_params = { - 'buy_rsi': 35, + "buy_rsi": 35, # Intentionally not specified, so "default" is tested # 'buy_plusdi': 0.4 } sell_params = { - 'sell_rsi': 74, - 'sell_minusdi': 0.4 + # Sell parameters + "sell_rsi": 74, + "sell_minusdi": 0.4, } - buy_plusdi = RealParameter(low=0, high=1, default=0.5, space='buy') - 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', - load=False) + buy_plusdi = RealParameter(low=0, high=1, default=0.5, space="buy") + 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", load=False + ) protection_enabled = BooleanParameter(default=True) protection_cooldown_lookback = IntParameter([0, 50], default=30) @@ -36,10 +38,12 @@ class HyperoptableStrategyV2(StrategyTestV2): def protections(self): prot = [] if self.protection_enabled.value: - prot.append({ - "method": "CooldownPeriod", - "stop_duration_candles": self.protection_cooldown_lookback.value - }) + prot.append( + { + "method": "CooldownPeriod", + "stop_duration_candles": self.protection_cooldown_lookback.value, + } + ) return prot bot_loop_started = False @@ -51,4 +55,4 @@ class HyperoptableStrategyV2(StrategyTestV2): """ 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") diff --git a/tests/strategy/strats/informative_decorator_strategy.py b/tests/strategy/strats/informative_decorator_strategy.py index f34eddc69..7414981e3 100644 --- a/tests/strategy/strats/informative_decorator_strategy.py +++ b/tests/strategy/strats/informative_decorator_strategy.py @@ -13,72 +13,73 @@ class InformativeDecoratorTest(IStrategy): or strategy repository https://github.com/freqtrade/freqtrade-strategies for samples and inspiration. """ + INTERFACE_VERSION = 2 stoploss = -0.10 - timeframe = '5m' + timeframe = "5m" startup_candle_count: int = 20 def informative_pairs(self): # Intentionally return 2 tuples, must be converted to 3 in compatibility code return [ - ('NEO/USDT', '5m'), - ('NEO/USDT', '15m', ''), - ('NEO/USDT', '2h', 'futures'), - ] + ("NEO/USDT", "5m"), + ("NEO/USDT", "15m", ""), + ("NEO/USDT", "2h", "futures"), + ] def populate_buy_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame: - dataframe['buy'] = 0 + dataframe["buy"] = 0 return dataframe def populate_sell_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame: - dataframe['sell'] = 0 + dataframe["sell"] = 0 return dataframe # Decorator stacking test. - @informative('30m') - @informative('1h') + @informative("30m") + @informative("1h") def populate_indicators_1h(self, dataframe: DataFrame, metadata: dict) -> DataFrame: - dataframe['rsi'] = 14 + dataframe["rsi"] = 14 return dataframe # Simple informative test. - @informative('1h', 'NEO/{stake}') + @informative("1h", "NEO/{stake}") def populate_indicators_neo_1h(self, dataframe: DataFrame, metadata: dict) -> DataFrame: - dataframe['rsi'] = 14 + dataframe["rsi"] = 14 return dataframe - @informative('1h', '{base}/BTC') + @informative("1h", "{base}/BTC") def populate_indicators_base_1h(self, dataframe: DataFrame, metadata: dict) -> DataFrame: - dataframe['rsi'] = 14 + dataframe["rsi"] = 14 return dataframe # 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: - dataframe['rsi'] = 14 + dataframe["rsi"] = 14 return dataframe # 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: - dataframe['rsi'] = 14 + dataframe["rsi"] = 14 return dataframe # 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: - dataframe['rsi'] = 14 + dataframe["rsi"] = 14 return dataframe def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame: # Strategy timeframe indicators for current pair. - dataframe['rsi'] = 14 + dataframe["rsi"] = 14 # 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. - informative = self.dp.get_pair_dataframe('NEO/USDT', '5m', '') - informative['rsi'] = 14 - dataframe = merge_informative_pair(dataframe, informative, self.timeframe, '5m', ffill=True) + informative = self.dp.get_pair_dataframe("NEO/USDT", "5m", "") + informative["rsi"] = 14 + dataframe = merge_informative_pair(dataframe, informative, self.timeframe, "5m", ffill=True) return dataframe diff --git a/tests/strategy/strats/lookahead_bias/strategy_test_v3_with_lookahead_bias.py b/tests/strategy/strats/lookahead_bias/strategy_test_v3_with_lookahead_bias.py index e50d5d17b..618b401bb 100644 --- a/tests/strategy/strats/lookahead_bias/strategy_test_v3_with_lookahead_bias.py +++ b/tests/strategy/strats/lookahead_bias/strategy_test_v3_with_lookahead_bias.py @@ -10,49 +10,44 @@ class strategy_test_v3_with_lookahead_bias(IStrategy): INTERFACE_VERSION = 3 # Minimal ROI designed for the strategy - 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} # Optimal stoploss designed for the strategy stoploss = -0.10 # Optimal timeframe for the strategy - timeframe = '5m' - scenario = CategoricalParameter(['no_bias', 'bias1'], default='bias1', space="buy") + timeframe = "5m" + scenario = CategoricalParameter(["no_bias", "bias1"], default="bias1", space="buy") # Number of candles the strategy requires before producing valid signals startup_candle_count: int = 20 def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame: # bias is introduced here - if self.scenario.value != 'no_bias': - ichi = ichimoku(dataframe, - conversion_line_period=20, - base_line_periods=60, - laggin_span=120, - displacement=30) - dataframe['chikou_span'] = ichi['chikou_span'] + if self.scenario.value != "no_bias": + ichi = ichimoku( + dataframe, + conversion_line_period=20, + base_line_periods=60, + laggin_span=120, + displacement=30, + ) + dataframe["chikou_span"] = ichi["chikou_span"] return dataframe def populate_entry_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame: - if self.scenario.value == 'no_bias': - dataframe.loc[dataframe['close'].shift(10) < dataframe['close'], 'enter_long'] = 1 + if self.scenario.value == "no_bias": + dataframe.loc[dataframe["close"].shift(10) < dataframe["close"], "enter_long"] = 1 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 def populate_exit_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame: - if self.scenario.value == 'no_bias': - dataframe.loc[ - dataframe['close'].shift(10) < dataframe['close'], 'exit'] = 1 + if self.scenario.value == "no_bias": + dataframe.loc[dataframe["close"].shift(10) < dataframe["close"], "exit"] = 1 else: - dataframe.loc[ - dataframe['close'].shift(-10) > dataframe['close'], 'exit'] = 1 + dataframe.loc[dataframe["close"].shift(-10) > dataframe["close"], "exit"] = 1 return dataframe diff --git a/tests/strategy/strats/strategy_test_v2.py b/tests/strategy/strats/strategy_test_v2.py index 9e1c47575..58473e9c0 100644 --- a/tests/strategy/strats/strategy_test_v2.py +++ b/tests/strategy/strats/strategy_test_v2.py @@ -15,28 +15,24 @@ class StrategyTestV2(IStrategy): or strategy repository https://github.com/freqtrade/freqtrade-strategies for samples and inspiration. """ + INTERFACE_VERSION = 2 # Minimal ROI designed for the strategy - 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} # Optimal stoploss designed for the strategy stoploss = -0.10 # Optimal timeframe for the strategy - timeframe = '5m' + timeframe = "5m" # Optional order type mapping order_types = { - 'entry': 'limit', - 'exit': 'limit', - 'stoploss': 'limit', - 'stoploss_on_exchange': False + "entry": "limit", + "exit": "limit", + "stoploss": "limit", + "stoploss_on_exchange": False, } # Number of candles the strategy requires before producing valid signals @@ -44,8 +40,8 @@ class StrategyTestV2(IStrategy): # Optional time in force for orders order_time_in_force = { - 'entry': 'gtc', - 'exit': 'gtc', + "entry": "gtc", + "exit": "gtc", } # Test legacy use_sell_signal definition use_sell_signal = False @@ -69,36 +65,36 @@ class StrategyTestV2(IStrategy): # ------------------------------------ # ADX - dataframe['adx'] = ta.ADX(dataframe) + dataframe["adx"] = ta.ADX(dataframe) # MACD macd = ta.MACD(dataframe) - dataframe['macd'] = macd['macd'] - dataframe['macdsignal'] = macd['macdsignal'] - dataframe['macdhist'] = macd['macdhist'] + dataframe["macd"] = macd["macd"] + dataframe["macdsignal"] = macd["macdsignal"] + dataframe["macdhist"] = macd["macdhist"] # Minus Directional Indicator / Movement - dataframe['minus_di'] = ta.MINUS_DI(dataframe) + dataframe["minus_di"] = ta.MINUS_DI(dataframe) # Plus Directional Indicator / Movement - dataframe['plus_di'] = ta.PLUS_DI(dataframe) + dataframe["plus_di"] = ta.PLUS_DI(dataframe) # RSI - dataframe['rsi'] = ta.RSI(dataframe) + dataframe["rsi"] = ta.RSI(dataframe) # Stoch fast stoch_fast = ta.STOCHF(dataframe) - dataframe['fastd'] = stoch_fast['fastd'] - dataframe['fastk'] = stoch_fast['fastk'] + dataframe["fastd"] = stoch_fast["fastd"] + dataframe["fastk"] = stoch_fast["fastk"] # Bollinger bands bollinger = qtpylib.bollinger_bands(qtpylib.typical_price(dataframe), window=20, stds=2) - dataframe['bb_lowerband'] = bollinger['lower'] - dataframe['bb_middleband'] = bollinger['mid'] - dataframe['bb_upperband'] = bollinger['upper'] + dataframe["bb_lowerband"] = bollinger["lower"] + dataframe["bb_middleband"] = bollinger["mid"] + dataframe["bb_upperband"] = bollinger["upper"] # EMA - Exponential Moving Average - dataframe['ema10'] = ta.EMA(dataframe, timeperiod=10) + dataframe["ema10"] = ta.EMA(dataframe, timeperiod=10) return dataframe @@ -111,16 +107,14 @@ class StrategyTestV2(IStrategy): """ dataframe.loc[ ( - (dataframe['rsi'] < 35) & - (dataframe['fastd'] < 35) & - (dataframe['adx'] > 30) & - (dataframe['plus_di'] > 0.5) - ) | - ( - (dataframe['adx'] > 65) & - (dataframe['plus_di'] > 0.5) - ), - 'buy'] = 1 + (dataframe["rsi"] < 35) + & (dataframe["fastd"] < 35) + & (dataframe["adx"] > 30) + & (dataframe["plus_di"] > 0.5) + ) + | ((dataframe["adx"] > 65) & (dataframe["plus_di"] > 0.5)), + "buy", + ] = 1 return dataframe @@ -134,15 +128,13 @@ class StrategyTestV2(IStrategy): dataframe.loc[ ( ( - (qtpylib.crossed_above(dataframe['rsi'], 70)) | - (qtpylib.crossed_above(dataframe['fastd'], 70)) - ) & - (dataframe['adx'] > 10) & - (dataframe['minus_di'] > 0) - ) | - ( - (dataframe['adx'] > 70) & - (dataframe['minus_di'] > 0.5) - ), - 'sell'] = 1 + (qtpylib.crossed_above(dataframe["rsi"], 70)) + | (qtpylib.crossed_above(dataframe["fastd"], 70)) + ) + & (dataframe["adx"] > 10) + & (dataframe["minus_di"] > 0) + ) + | ((dataframe["adx"] > 70) & (dataframe["minus_di"] > 0.5)), + "sell", + ] = 1 return dataframe diff --git a/tests/strategy/strats/strategy_test_v3.py b/tests/strategy/strats/strategy_test_v3.py index cfb0def81..71404242a 100644 --- a/tests/strategy/strats/strategy_test_v3.py +++ b/tests/strategy/strats/strategy_test_v3.py @@ -25,15 +25,11 @@ class StrategyTestV3(IStrategy): or strategy repository https://github.com/freqtrade/freqtrade-strategies for samples and inspiration. """ + INTERFACE_VERSION = 3 # Minimal ROI designed for the strategy - 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} # Optimal max_open_trades for the strategy max_open_trades = -1 @@ -42,14 +38,14 @@ class StrategyTestV3(IStrategy): stoploss = -0.10 # Optimal timeframe for the strategy - timeframe = '5m' + timeframe = "5m" # Optional order type mapping order_types = { - 'entry': 'limit', - 'exit': 'limit', - 'stoploss': 'limit', - 'stoploss_on_exchange': False + "entry": "limit", + "exit": "limit", + "stoploss": "limit", + "stoploss_on_exchange": False, } # Number of candles the strategy requires before producing valid signals @@ -57,26 +53,24 @@ class StrategyTestV3(IStrategy): # Optional time in force for orders order_time_in_force = { - 'entry': 'gtc', - 'exit': 'gtc', + "entry": "gtc", + "exit": "gtc", } buy_params = { - 'buy_rsi': 35, + "buy_rsi": 35, # Intentionally not specified, so "default" is tested # 'buy_plusdi': 0.4 } - sell_params = { - 'sell_rsi': 74, - 'sell_minusdi': 0.4 - } + sell_params = {"sell_rsi": 74, "sell_minusdi": 0.4} - buy_rsi = IntParameter([0, 50], default=30, 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_minusdi = DecimalParameter(low=0, high=1, default=0.5001, decimals=3, space='sell', - load=False) + buy_rsi = IntParameter([0, 50], default=30, 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_minusdi = DecimalParameter( + low=0, high=1, default=0.5001, decimals=3, space="sell", load=False + ) protection_enabled = BooleanParameter(default=True) protection_cooldown_lookback = IntParameter([0, 50], default=30) @@ -97,67 +91,61 @@ class StrategyTestV3(IStrategy): self.bot_started = True def informative_pairs(self): - return [] def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame: - # Momentum Indicator # ------------------------------------ # ADX - dataframe['adx'] = ta.ADX(dataframe) + dataframe["adx"] = ta.ADX(dataframe) # MACD macd = ta.MACD(dataframe) - dataframe['macd'] = macd['macd'] - dataframe['macdsignal'] = macd['macdsignal'] - dataframe['macdhist'] = macd['macdhist'] + dataframe["macd"] = macd["macd"] + dataframe["macdsignal"] = macd["macdsignal"] + dataframe["macdhist"] = macd["macdhist"] # Minus Directional Indicator / Movement - dataframe['minus_di'] = ta.MINUS_DI(dataframe) + dataframe["minus_di"] = ta.MINUS_DI(dataframe) # Plus Directional Indicator / Movement - dataframe['plus_di'] = ta.PLUS_DI(dataframe) + dataframe["plus_di"] = ta.PLUS_DI(dataframe) # RSI - dataframe['rsi'] = ta.RSI(dataframe) + dataframe["rsi"] = ta.RSI(dataframe) # Stoch fast stoch_fast = ta.STOCHF(dataframe) - dataframe['fastd'] = stoch_fast['fastd'] - dataframe['fastk'] = stoch_fast['fastk'] + dataframe["fastd"] = stoch_fast["fastd"] + dataframe["fastk"] = stoch_fast["fastk"] # Bollinger bands bollinger = qtpylib.bollinger_bands(qtpylib.typical_price(dataframe), window=20, stds=2) - dataframe['bb_lowerband'] = bollinger['lower'] - dataframe['bb_middleband'] = bollinger['mid'] - dataframe['bb_upperband'] = bollinger['upper'] + dataframe["bb_lowerband"] = bollinger["lower"] + dataframe["bb_middleband"] = bollinger["mid"] + dataframe["bb_upperband"] = bollinger["upper"] # EMA - Exponential Moving Average - dataframe['ema10'] = ta.EMA(dataframe, timeperiod=10) + dataframe["ema10"] = ta.EMA(dataframe, timeperiod=10) return dataframe def populate_entry_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame: - dataframe.loc[ ( - (dataframe['rsi'] < self.buy_rsi.value) & - (dataframe['fastd'] < 35) & - (dataframe['adx'] > 30) & - (dataframe['plus_di'] > self.buy_plusdi.value) - ) | - ( - (dataframe['adx'] > 65) & - (dataframe['plus_di'] > self.buy_plusdi.value) - ), - 'enter_long'] = 1 + (dataframe["rsi"] < self.buy_rsi.value) + & (dataframe["fastd"] < 35) + & (dataframe["adx"] > 30) + & (dataframe["plus_di"] > self.buy_plusdi.value) + ) + | ((dataframe["adx"] > 65) & (dataframe["plus_di"] > self.buy_plusdi.value)), + "enter_long", + ] = 1 dataframe.loc[ - ( - qtpylib.crossed_below(dataframe['rsi'], self.sell_rsi.value) - ), - ('enter_short', 'enter_tag')] = (1, 'short_Tag') + (qtpylib.crossed_below(dataframe["rsi"], self.sell_rsi.value)), + ("enter_short", "enter_tag"), + ] = (1, "short_Tag") return dataframe @@ -165,41 +153,53 @@ class StrategyTestV3(IStrategy): dataframe.loc[ ( ( - (qtpylib.crossed_above(dataframe['rsi'], self.sell_rsi.value)) | - (qtpylib.crossed_above(dataframe['fastd'], 70)) - ) & - (dataframe['adx'] > 10) & - (dataframe['minus_di'] > 0) - ) | - ( - (dataframe['adx'] > 70) & - (dataframe['minus_di'] > self.sell_minusdi.value) - ), - 'exit_long'] = 1 + (qtpylib.crossed_above(dataframe["rsi"], self.sell_rsi.value)) + | (qtpylib.crossed_above(dataframe["fastd"], 70)) + ) + & (dataframe["adx"] > 10) + & (dataframe["minus_di"] > 0) + ) + | ((dataframe["adx"] > 70) & (dataframe["minus_di"] > self.sell_minusdi.value)), + "exit_long", + ] = 1 dataframe.loc[ - ( - qtpylib.crossed_above(dataframe['rsi'], self.buy_rsi.value) - ), - ('exit_short', 'exit_tag')] = (1, 'short_Tag') + (qtpylib.crossed_above(dataframe["rsi"], self.buy_rsi.value)), + ("exit_short", "exit_tag"), + ] = (1, "short_Tag") return dataframe - def leverage(self, pair: str, current_time: datetime, current_rate: float, - proposed_leverage: float, max_leverage: float, entry_tag: Optional[str], - side: str, **kwargs) -> float: + def leverage( + self, + 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. # Bot-logic must make sure it's an allowed leverage and eventually adjust accordingly. return 3.0 - def adjust_trade_position(self, trade: Trade, current_time: datetime, - current_rate: 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]: - + def adjust_trade_position( + self, + trade: Trade, + current_time: datetime, + current_rate: 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: orders = trade.select_filled_orders(trade.entry_side) return round(orders[0].stake_amount, 0) diff --git a/tests/strategy/strats/strategy_test_v3_custom_entry_price.py b/tests/strategy/strats/strategy_test_v3_custom_entry_price.py index 607ff6e1e..956766d14 100644 --- a/tests/strategy/strats/strategy_test_v3_custom_entry_price.py +++ b/tests/strategy/strats/strategy_test_v3_custom_entry_price.py @@ -17,24 +17,28 @@ class StrategyTestV3CustomEntryPrice(StrategyTestV3): or strategy repository https://github.com/freqtrade/freqtrade-strategies for samples and inspiration. """ + new_entry_price: float = 0.001 def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame: return 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 def populate_exit_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame: return dataframe - def custom_entry_price(self, pair: str, trade: Optional[Trade], current_time: datetime, - proposed_rate: float, - entry_tag: Optional[str], side: str, **kwargs) -> float: - + def custom_entry_price( + self, + pair: str, + trade: Optional[Trade], + current_time: datetime, + proposed_rate: float, + entry_tag: Optional[str], + side: str, + **kwargs, + ) -> float: return self.new_entry_price diff --git a/tests/strategy/strats/strategy_test_v3_recursive_issue.py b/tests/strategy/strats/strategy_test_v3_recursive_issue.py index b3074113d..d03486886 100644 --- a/tests/strategy/strats/strategy_test_v3_recursive_issue.py +++ b/tests/strategy/strats/strategy_test_v3_recursive_issue.py @@ -10,37 +10,33 @@ class strategy_test_v3_recursive_issue(IStrategy): INTERFACE_VERSION = 3 # Minimal ROI designed for the strategy - minimal_roi = { - "0": 0.04 - } + minimal_roi = {"0": 0.04} # Optimal stoploss designed for the strategy stoploss = -0.10 # Optimal timeframe for the strategy - timeframe = '5m' - scenario = CategoricalParameter(['no_bias', 'bias1', 'bias2'], default='bias1', space="buy") + timeframe = "5m" + scenario = CategoricalParameter(["no_bias", "bias1", "bias2"], default="bias1", space="buy") # Number of candles the strategy requires before producing valid signals startup_candle_count: int = 100 def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame: # bias is introduced here - if self.scenario.value == 'no_bias': - dataframe['rsi'] = ta.RSI(dataframe, timeperiod=14) + if self.scenario.value == "no_bias": + dataframe["rsi"] = ta.RSI(dataframe, timeperiod=14) 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 - dataframe['rsi_lookahead'] = ta.RSI(dataframe, timeperiod=50).shift(-1) + dataframe["rsi_lookahead"] = ta.RSI(dataframe, timeperiod=50).shift(-1) return dataframe def populate_entry_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame: - return dataframe def populate_exit_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame: - return dataframe diff --git a/tests/utils/test_binance_mig.py b/tests/utils/test_binance_mig.py index d7447a4d3..f700ff73a 100644 --- a/tests/utils/test_binance_mig.py +++ b/tests/utils/test_binance_mig.py @@ -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): - # call doing nothing (spot mode) migrate_binance_futures_data(default_conf_usdt) - default_conf_usdt['trading_mode'] = 'futures' - pair_old = 'XRP_USDT' - pair_unified = 'XRP_USDT_USDT' - futures_src = testdatadir / 'futures' - futures_dst = tmp_path / 'futures' + default_conf_usdt["trading_mode"] = "futures" + pair_old = "XRP_USDT" + pair_unified = "XRP_USDT_USDT" + futures_src = testdatadir / "futures" + futures_dst = tmp_path / "futures" futures_dst.mkdir() files = [ - '-1h-mark.feather', - '-1h-futures.feather', - '-8h-funding_rate.feather', - '-8h-mark.feather', + "-1h-mark.feather", + "-1h-futures.feather", + "-8h-funding_rate.feather", + "-8h-mark.feather", ] # Copy files to tmpdir and rename to old naming for file in files: - fn_after = futures_dst / f'{pair_old}{file}' - shutil.copy(futures_src / f'{pair_unified}{file}', fn_after) + fn_after = futures_dst / f"{pair_old}{file}" + 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_binance_futures_data(default_conf_usdt) for file in files: - fn_after = futures_dst / f'{pair_unified}{file}' + fn_after = futures_dst / f"{pair_unified}{file}" 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) for t in Trade.get_trades(): - t.trading_mode = 'FUTURES' - t.exchange = 'binance' + t.trading_mode = "FUTURES" + t.exchange = "binance" Trade.commit() - default_conf_usdt['trading_mode'] = 'futures' + default_conf_usdt["trading_mode"] = "futures" 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): - default_conf_usdt['trading_mode'] = 'futures' - binmock = mocker.patch('freqtrade.util.migrations.migrate_binance_futures_data') - funding_mock = mocker.patch('freqtrade.util.migrations.migrate_funding_fee_timeframe') + default_conf_usdt["trading_mode"] = "futures" + binmock = mocker.patch("freqtrade.util.migrations.migrate_binance_futures_data") + funding_mock = mocker.patch("freqtrade.util.migrations.migrate_funding_fee_timeframe") migrate_data(default_conf_usdt) assert binmock.call_count == 1 diff --git a/tests/utils/test_ccxt_precise.py b/tests/utils/test_ccxt_precise.py index 5542ac8d2..536a66182 100644 --- a/tests/utils/test_ccxt_precise.py +++ b/tests/utils/test_ccxt_precise.py @@ -1,82 +1,82 @@ from freqtrade.util import FtPrecise -ws = FtPrecise('-1.123e-6') -ws = FtPrecise('-1.123e-6') -xs = FtPrecise('0.00000002') -ys = FtPrecise('69696900000') -zs = FtPrecise('0') +ws = FtPrecise("-1.123e-6") +ws = FtPrecise("-1.123e-6") +xs = FtPrecise("0.00000002") +ys = FtPrecise("69696900000") +zs = FtPrecise("0") def test_FtPrecise(): - assert ys * xs == '1393.938' - assert xs * ys == '1393.938' + assert ys * xs == "1393.938" + assert xs * ys == "1393.938" - assert ys + xs == '69696900000.00000002' - assert xs + ys == '69696900000.00000002' - assert xs - ys == '-69696899999.99999998' - assert ys - xs == '69696899999.99999998' - assert xs / ys == '0' - assert ys / xs == '3484845000000000000' + assert ys + xs == "69696900000.00000002" + assert xs + ys == "69696900000.00000002" + assert xs - ys == "-69696899999.99999998" + assert ys - xs == "69696899999.99999998" + assert xs / ys == "0" + assert ys / xs == "3484845000000000000" - assert ws * xs == '-0.00000000000002246' - assert xs * ws == '-0.00000000000002246' + assert ws * xs == "-0.00000000000002246" + assert xs * ws == "-0.00000000000002246" - assert ws + xs == '-0.000001103' - assert xs + ws == '-0.000001103' + assert ws + xs == "-0.000001103" + assert xs + ws == "-0.000001103" - assert xs - ws == '0.000001143' - assert ws - xs == '-0.000001143' + assert xs - ws == "0.000001143" + assert ws - xs == "-0.000001143" - assert xs / ws == '-0.017809439002671415' - assert ws / xs == '-56.15' + assert xs / ws == "-0.017809439002671415" + assert ws / xs == "-56.15" - assert zs * ws == '0' - assert zs * xs == '0' - assert zs * ys == '0' - assert ws * zs == '0' - assert xs * zs == '0' - assert ys * zs == '0' + assert zs * ws == "0" + assert zs * xs == "0" + assert zs * ys == "0" + assert ws * zs == "0" + assert xs * zs == "0" + assert ys * zs == "0" - assert zs + ws == '-0.000001123' - assert zs + xs == '0.00000002' - assert zs + ys == '69696900000' - assert ws + zs == '-0.000001123' - assert xs + zs == '0.00000002' - assert ys + zs == '69696900000' + assert zs + ws == "-0.000001123" + assert zs + xs == "0.00000002" + assert zs + ys == "69696900000" + assert ws + zs == "-0.000001123" + assert xs + zs == "0.00000002" + assert ys + zs == "69696900000" - assert abs(FtPrecise('-500.1')) == '500.1' - assert abs(FtPrecise('213')) == '213' + assert abs(FtPrecise("-500.1")) == "500.1" + assert abs(FtPrecise("213")) == "213" - assert abs(FtPrecise('-500.1')) == '500.1' - assert -FtPrecise('213') == '-213' + assert abs(FtPrecise("-500.1")) == "500.1" + assert -FtPrecise("213") == "-213" - assert FtPrecise('10.1') % FtPrecise('0.5') == '0.1' - assert FtPrecise('5550') % FtPrecise('120') == '30' + assert FtPrecise("10.1") % FtPrecise("0.5") == "0.1" + assert FtPrecise("5550") % FtPrecise("120") == "30" - assert FtPrecise('-0.0') == FtPrecise('0') - assert FtPrecise('5.534000') == FtPrecise('5.5340') + assert FtPrecise("-0.0") == FtPrecise("0") + 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 not FtPrecise('-3.1415') > FtPrecise('-2') - assert not FtPrecise('3.1415') > FtPrecise('3.1415') - assert FtPrecise.string_gt('3.14150000000000000000001', '3.1415') + assert FtPrecise("2") > FtPrecise("1.2345") + assert not FtPrecise("-3.1415") > FtPrecise("-2") + assert not FtPrecise("3.1415") > FtPrecise("3.1415") + assert FtPrecise.string_gt("3.14150000000000000000001", "3.1415") - assert FtPrecise('3.1415') >= FtPrecise('3.1415') - assert FtPrecise('3.14150000000000000000001') >= FtPrecise('3.1415') + assert FtPrecise("3.1415") >= 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.14150000000000000000001') + assert FtPrecise("3.1415") <= FtPrecise("3.1415") + assert FtPrecise("3.1415") <= FtPrecise("3.14150000000000000000001") - assert FtPrecise(213) == '213' - assert FtPrecise(-213) == '-213' - assert str(FtPrecise(-213)) == '-213' - assert FtPrecise(213.2) == '213.2' + assert FtPrecise(213) == "213" + assert FtPrecise(-213) == "-213" + assert str(FtPrecise(-213)) == "-213" + assert FtPrecise(213.2) == "213.2" assert float(FtPrecise(213.2)) == 213.2 assert float(FtPrecise(-213.2)) == -213.2 diff --git a/tests/utils/test_datetime_helpers.py b/tests/utils/test_datetime_helpers.py index 5e1ce4190..d17d2ec5a 100644 --- a/tests/utils/test_datetime_helpers.py +++ b/tests/utils/test_datetime_helpers.py @@ -49,16 +49,18 @@ def test_dt_ts_none(): def test_dt_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, - tzinfo=timezone.utc) + assert dt_utc(2023, 5, 5, 0, 0, 0, 555500) == datetime( + 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): 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.5555 * multi) == datetime(2023, 5, 5, 0, 0, 0, 555500, - tzinfo=timezone.utc) + assert dt_from_ts(1683244800.5555 * multi) == datetime( + 2023, 5, 5, 0, 0, 0, 555500, tzinfo=timezone.utc + ) # As int assert dt_from_ts(1683244800 * multi) == datetime(2023, 5, 5, tzinfo=timezone.utc) # As milliseconds @@ -73,18 +75,18 @@ def test_dt_floor_day(): def test_shorten_date() -> None: - str_data = '1 day, 2 hours, 3 minutes, 4 seconds ago' - str_shorten_data = '1 d, 2 h, 3 min, 4 sec ago' + str_data = "1 day, 2 hours, 3 minutes, 4 seconds ago" + str_shorten_data = "1 d, 2 h, 3 min, 4 sec ago" assert shorten_date(str_data) == str_shorten_data def test_dt_humanize() -> None: - 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(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(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()) == "now" + 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, 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(minutes=50)) == "50 minutes ago" def test_format_ms_time() -> None: @@ -93,20 +95,19 @@ def test_format_ms_time() -> None: date = format_ms_time(date_in_epoch_ms) assert isinstance(date, str) res = datetime(2018, 4, 10, 18, 2, 1, tzinfo=timezone.utc) - assert date == res.strftime('%Y-%m-%dT%H:%M:%S') - assert date == '2018-04-10T18:02:01' + assert date == res.strftime("%Y-%m-%dT%H:%M:%S") + assert date == "2018-04-10T18:02:01" res = datetime(2017, 12, 13, 8, 2, 1, tzinfo=timezone.utc) # Date 2017-12-13 08:02:01 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: - 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(None) == '' + assert format_date(date) == "2023-09-01 05:02:03" + assert format_date(None) == "" 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(None) == '' + assert format_date(date) == "2021-09-30 22:59:03" + assert format_date(None) == "" diff --git a/tests/utils/test_formatters.py b/tests/utils/test_formatters.py index 2a989ce81..ab86e224c 100644 --- a/tests/utils/test_formatters.py +++ b/tests/utils/test_formatters.py @@ -2,36 +2,35 @@ from freqtrade.util import decimals_per_coin, fmt_coin, round_value def test_decimals_per_coin(): - assert decimals_per_coin('USDT') == 3 - assert decimals_per_coin('EUR') == 3 - assert decimals_per_coin('BTC') == 8 - assert decimals_per_coin('ETH') == 5 + assert decimals_per_coin("USDT") == 3 + assert decimals_per_coin("EUR") == 3 + assert decimals_per_coin("BTC") == 8 + assert decimals_per_coin("ETH") == 5 def test_fmt_coin(): - 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') == '222.2 USDT' - assert fmt_coin(222.12745, 'EUR') == '222.127 EUR' - assert fmt_coin(0.1274512123, 'BTC') == '0.12745121 BTC' - assert fmt_coin(0.1274512123, 'ETH') == '0.12745 ETH' + 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") == "222.2 USDT" + assert fmt_coin(222.12745, "EUR") == "222.127 EUR" + assert fmt_coin(0.1274512123, "BTC") == "0.12745121 BTC" + assert fmt_coin(0.1274512123, "ETH") == "0.12745 ETH" - assert fmt_coin(222.222222, 'USDT', False) == '222.222' - assert fmt_coin(222.2, 'USDT', False) == '222.2' - assert fmt_coin(222.00, 'USDT', False) == '222' - assert fmt_coin(222.12745, 'EUR', False) == '222.127' - assert fmt_coin(0.1274512123, 'BTC', False) == '0.12745121' - assert fmt_coin(0.1274512123, 'ETH', False) == '0.12745' - assert fmt_coin(222.2, 'USDT', False, True) == '222.200' + assert fmt_coin(222.222222, "USDT", False) == "222.222" + assert fmt_coin(222.2, "USDT", False) == "222.2" + assert fmt_coin(222.00, "USDT", False) == "222" + assert fmt_coin(222.12745, "EUR", False) == "222.127" + assert fmt_coin(0.1274512123, "BTC", False) == "0.12745121" + assert fmt_coin(0.1274512123, "ETH", False) == "0.12745" + assert fmt_coin(222.2, "USDT", False, True) == "222.200" def test_round_value(): - - assert round_value(222.222222, 3) == '222.222' - assert round_value(222.2, 3) == '222.2' - assert round_value(222.00, 3) == '222' - assert round_value(222.12745, 3) == '222.127' - assert round_value(0.1274512123, 8) == '0.12745121' - assert round_value(0.1274512123, 5) == '0.12745' - assert round_value(222.2, 3, True) == '222.200' - assert round_value(222.2, 0, True) == '222' + assert round_value(222.222222, 3) == "222.222" + assert round_value(222.2, 3) == "222.2" + assert round_value(222.00, 3) == "222" + assert round_value(222.12745, 3) == "222.127" + assert round_value(0.1274512123, 8) == "0.12745121" + assert round_value(0.1274512123, 5) == "0.12745" + assert round_value(222.2, 3, True) == "222.200" + assert round_value(222.2, 0, True) == "222" diff --git a/tests/utils/test_funding_rate_migration.py b/tests/utils/test_funding_rate_migration.py index ccb8435cf..094ee1562 100644 --- a/tests/utils/test_funding_rate_migration.py +++ b/tests/utils/test_funding_rate_migration.py @@ -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): - - copytree(testdatadir / 'futures', tmp_path / 'futures') - 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_1h = tmp_path / 'futures' / 'XRP_USDT_USDT-1h-futures.feather' + copytree(testdatadir / "futures", tmp_path / "futures") + 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_1h = tmp_path / "futures" / "XRP_USDT_USDT-1h-futures.feather" file_8h.rename(file_4h) assert file_1h.exists() assert file_4h.exists() assert not file_8h.exists() - default_conf_usdt['datadir'] = tmp_path + default_conf_usdt["datadir"] = tmp_path # Inactive on spot trading ... 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) diff --git a/tests/utils/test_measure_time.py b/tests/utils/test_measure_time.py index dac509907..2d44a3254 100644 --- a/tests/utils/test_measure_time.py +++ b/tests/utils/test_measure_time.py @@ -6,10 +6,8 @@ from freqtrade.util import MeasureTime def test_measure_time(): - callback = MagicMock() with time_machine.travel("2021-09-01 05:00:00 +00:00", tick=False) as t: - measure = MeasureTime(callback, 5, ttl=60) with measure: pass diff --git a/tests/utils/test_periodiccache.py b/tests/utils/test_periodiccache.py index a8931d6a2..684e7755d 100644 --- a/tests/utils/test_periodiccache.py +++ b/tests/utils/test_periodiccache.py @@ -4,31 +4,29 @@ from freqtrade.util import PeriodicCache def test_ttl_cache(): - with time_machine.travel("2021-09-01 05:00:00 +00:00", tick=False) as t: - cache = PeriodicCache(5, ttl=60) cache1h = PeriodicCache(5, ttl=3600) assert cache.timer() == 1630472400.0 - cache['a'] = 1235 - cache1h['a'] = 555123 - assert 'a' in cache - assert 'a' in cache1h + cache["a"] = 1235 + cache1h["a"] = 555123 + assert "a" in cache + assert "a" in cache1h t.move_to("2021-09-01 05:00:59 +00:00") - assert 'a' in cache - assert 'a' in cache1h + assert "a" in cache + assert "a" in cache1h # Cache expired t.move_to("2021-09-01 05:01:00 +00:00") - assert 'a' not in cache - assert 'a' in cache1h + assert "a" not in cache + assert "a" in cache1h t.move_to("2021-09-01 05:59:59 +00:00") - assert 'a' not in cache - assert 'a' in cache1h + assert "a" not in cache + assert "a" in cache1h t.move_to("2021-09-01 06:00:00 +00:00") - assert 'a' not in cache - assert 'a' not in cache1h + assert "a" not in cache + assert "a" not in cache1h diff --git a/tests/utils/test_rendering_utils.py b/tests/utils/test_rendering_utils.py index e03307ff1..f42c77dea 100644 --- a/tests/utils/test_rendering_utils.py +++ b/tests/utils/test_rendering_utils.py @@ -5,15 +5,16 @@ from freqtrade.util import render_template, render_template_with_fallback def test_render_template_fallback(): from jinja2.exceptions import TemplateNotFound + with pytest.raises(TemplateNotFound): val = render_template( - templatefile='subtemplates/indicators_does-not-exist.j2', + templatefile="subtemplates/indicators_does-not-exist.j2", arguments={}, ) val = render_template_with_fallback( - templatefile='strategy_subtemplates/indicators_does-not-exist.j2', - templatefallbackfile='strategy_subtemplates/indicators_minimal.j2', + templatefile="strategy_subtemplates/indicators_does-not-exist.j2", + templatefallbackfile="strategy_subtemplates/indicators_minimal.j2", ) assert isinstance(val, str) - assert 'if self.dp' in val + assert "if self.dp" in val