diff --git a/freqtrade/misc.py b/freqtrade/misc.py index cbebf99eb..bd4f17d05 100644 --- a/freqtrade/misc.py +++ b/freqtrade/misc.py @@ -3,6 +3,7 @@ Various tool function for Freqtrade and scripts """ import gzip import logging +from io import StringIO from pathlib import Path from typing import Any, Dict, Iterator, List, Mapping, Optional, TextIO, Union from urllib.parse import urlparse @@ -231,7 +232,7 @@ def json_to_dataframe(data: str) -> pd.DataFrame: :param data: A JSON string :returns: A pandas DataFrame from the JSON string """ - dataframe = pd.read_json(data, orient='split') + dataframe = pd.read_json(StringIO(data), orient='split') if 'date' in dataframe.columns: dataframe['date'] = pd.to_datetime(dataframe['date'], unit='ms', utc=True) diff --git a/freqtrade/optimize/analysis/lookahead.py b/freqtrade/optimize/analysis/lookahead.py index 924e43e07..9fa4235e7 100755 --- a/freqtrade/optimize/analysis/lookahead.py +++ b/freqtrade/optimize/analysis/lookahead.py @@ -94,8 +94,8 @@ class LookaheadAnalysis(BaseAnalysis): # compare_df now comprises tuples with [1] having either 'self' or 'other' if 'other' in col_name[1]: continue - self_value = compare_df_row[col_idx] - other_value = compare_df_row[col_idx + 1] + self_value = compare_df_row.iloc[col_idx] + other_value = compare_df_row.iloc[col_idx + 1] # output differences if self_value != other_value: diff --git a/freqtrade/optimize/hyperopt_tools.py b/freqtrade/optimize/hyperopt_tools.py index 6bbf3c15d..ee03aae1a 100644 --- a/freqtrade/optimize/hyperopt_tools.py +++ b/freqtrade/optimize/hyperopt_tools.py @@ -429,14 +429,18 @@ class HyperoptTools: trials = trials.drop(columns=['Total profit']) if print_colorized: + trials2 = trials.astype(str) for i in range(len(trials)): if trials.loc[i]['is_profit']: for j in range(len(trials.loc[i]) - 3): - trials.iat[i, j] = f"{Fore.GREEN}{str(trials.loc[i][j])}{Fore.RESET}" + trials2.iat[i, j] = f"{Fore.GREEN}{str(trials.iloc[i, j])}{Fore.RESET}" if trials.loc[i]['is_best'] and highlight_best: for j in range(len(trials.loc[i]) - 3): - trials.iat[i, j] = f"{Style.BRIGHT}{str(trials.loc[i][j])}{Style.RESET_ALL}" - + trials2.iat[i, j] = ( + f"{Style.BRIGHT}{str(trials.iloc[i, j])}{Style.RESET_ALL}" + ) + trials = trials2 + del trials2 trials = trials.drop(columns=['is_initial_point', 'is_best', 'is_profit', 'is_random']) if remove_header > 0: table = tabulate.tabulate( diff --git a/freqtrade/optimize/optimize_reports/optimize_reports.py b/freqtrade/optimize/optimize_reports/optimize_reports.py index b68fc708e..2ca6ee947 100644 --- a/freqtrade/optimize/optimize_reports/optimize_reports.py +++ b/freqtrade/optimize/optimize_reports/optimize_reports.py @@ -219,8 +219,10 @@ def _get_resample_from_period(period: str) -> str: raise ValueError(f"Period {period} is not supported.") -def generate_periodic_breakdown_stats(trade_list: List, period: str) -> List[Dict[str, Any]]: - results = DataFrame.from_records(trade_list) +def generate_periodic_breakdown_stats( + trade_list: Union[List, DataFrame], period: str) -> List[Dict[str, Any]]: + + results = trade_list if not isinstance(trade_list, list) else DataFrame.from_records(trade_list) if len(results) == 0: return [] results['close_date'] = to_datetime(results['close_date'], utc=True) diff --git a/freqtrade/strategy/interface.py b/freqtrade/strategy/interface.py index cbe6afc26..651ca14bf 100644 --- a/freqtrade/strategy/interface.py +++ b/freqtrade/strategy/interface.py @@ -1006,7 +1006,7 @@ class IStrategy(ABC, HyperStrategyMixin): exit_ = latest.get(SignalType.EXIT_LONG.value, 0) == 1 exit_tag = latest.get(SignalTagType.EXIT_TAG.value, None) # Tags can be None, which does not resolve to False. - exit_tag = exit_tag if isinstance(exit_tag, str) else None + exit_tag = exit_tag if isinstance(exit_tag, str) and exit_tag != 'nan' else None logger.debug(f"exit-trigger: {latest['date']} (pair={pair}) " f"enter={enter} exit={exit_}") @@ -1038,17 +1038,17 @@ class IStrategy(ABC, HyperStrategyMixin): exit_short = latest.get(SignalType.EXIT_SHORT.value, 0) == 1 enter_signal: Optional[SignalDirection] = None - enter_tag_value: Optional[str] = None + enter_tag: Optional[str] = None if enter_long == 1 and not any([exit_long, enter_short]): enter_signal = SignalDirection.LONG - enter_tag_value = latest.get(SignalTagType.ENTER_TAG.value, None) + enter_tag = latest.get(SignalTagType.ENTER_TAG.value, None) if (self.config.get('trading_mode', TradingMode.SPOT) != TradingMode.SPOT and self.can_short and enter_short == 1 and not any([exit_short, enter_long])): enter_signal = SignalDirection.SHORT - enter_tag_value = latest.get(SignalTagType.ENTER_TAG.value, None) + enter_tag = latest.get(SignalTagType.ENTER_TAG.value, None) - enter_tag_value = enter_tag_value if isinstance(enter_tag_value, str) else None + enter_tag = enter_tag if isinstance(enter_tag, str) and enter_tag != 'nan' else None timeframe_seconds = timeframe_to_seconds(timeframe) @@ -1058,11 +1058,11 @@ class IStrategy(ABC, HyperStrategyMixin): timeframe_seconds=timeframe_seconds, enter=bool(enter_signal) ): - return None, enter_tag_value + return None, enter_tag logger.debug(f"entry trigger: {latest['date']} (pair={pair}) " - f"enter={enter_long} enter_tag_value={enter_tag_value}") - return enter_signal, enter_tag_value + f"enter={enter_long} enter_tag_value={enter_tag}") + return enter_signal, enter_tag def ignore_expired_candle( self, diff --git a/requirements.txt b/requirements.txt index 64b0cb6f8..146f468a6 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,5 +1,5 @@ numpy==1.26.1 -pandas==2.0.3 +pandas==2.1.2 pandas-ta==0.3.14b ccxt==4.1.31 diff --git a/tests/data/test_converter.py b/tests/data/test_converter.py index 74bb8d9f9..ebee4a3be 100644 --- a/tests/data/test_converter.py +++ b/tests/data/test_converter.py @@ -50,8 +50,8 @@ def test_trades_to_ohlcv(trades_history_df, caplog): assert 'high' in df.columns assert 'low' in df.columns assert 'close' in df.columns - assert df.loc[:, 'high'][0] == 0.019627 - assert df.loc[:, 'low'][0] == 0.019626 + assert df.iloc[0, :]['high'] == 0.019627 + assert df.iloc[0, :]['low'] == 0.019626 def test_ohlcv_fill_up_missing_data(testdatadir, caplog):