Skip to content

Commit 6afcc80

Browse files
committed
refactor: move some utils to a separate file
1 parent efdb726 commit 6afcc80

File tree

3 files changed

+65
-54
lines changed

3 files changed

+65
-54
lines changed

freqtrade/data/btanalysis/__init__.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
11
# flake8: noqa: F401
22
from .btanalysis import (
33
BT_DATA_COLUMNS,
4-
analyze_trade_parallelism,
54
delete_backtest_result,
6-
evaluate_result_multi,
75
extract_trades_of_period,
86
find_existing_backtest_stats,
97
get_backtest_market_change,
@@ -27,3 +25,7 @@
2725
trade_list_to_dataframe,
2826
update_backtest_metadata,
2927
)
28+
from .trade_parallelism import (
29+
analyze_trade_parallelism,
30+
evaluate_result_multi,
31+
)

freqtrade/data/btanalysis/btanalysis.py

Lines changed: 1 addition & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
import numpy as np
1414
import pandas as pd
1515

16-
from freqtrade.constants import LAST_BT_RESULT_FN, IntOrInf
16+
from freqtrade.constants import LAST_BT_RESULT_FN
1717
from freqtrade.exceptions import ConfigurationError, OperationalException
1818
from freqtrade.ft_types import BacktestHistoryEntryType, BacktestResultType
1919
from freqtrade.misc import file_dump_json, json_load
@@ -491,57 +491,6 @@ def load_exit_signal_candles(backtest_dir: Path) -> dict[str, dict[str, pd.DataF
491491
return load_backtest_analysis_data(backtest_dir, "exited")
492492

493493

494-
def analyze_trade_parallelism(trades: pd.DataFrame, timeframe: str) -> pd.DataFrame:
495-
"""
496-
Find overlapping trades by expanding each trade once per period it was open
497-
and then counting overlaps.
498-
:param trades: Trades Dataframe - can be loaded from backtest, or created
499-
via trade_list_to_dataframe
500-
:param timeframe: Timeframe used for backtest
501-
:return: dataframe with open-counts per time-period in timeframe
502-
"""
503-
from freqtrade.exchange import timeframe_to_resample_freq
504-
505-
timeframe_freq = timeframe_to_resample_freq(timeframe)
506-
dates = [
507-
pd.Series(
508-
pd.date_range(
509-
row[1]["open_date"],
510-
row[1]["close_date"],
511-
freq=timeframe_freq,
512-
# Exclude right boundary - the date is the candle open date.
513-
inclusive="left",
514-
)
515-
)
516-
for row in trades[["open_date", "close_date"]].iterrows()
517-
]
518-
deltas = [len(x) for x in dates]
519-
dates = pd.Series(pd.concat(dates).values, name="date")
520-
df2 = pd.DataFrame(np.repeat(trades.values, deltas, axis=0), columns=trades.columns)
521-
522-
df2 = pd.concat([dates, df2], axis=1)
523-
df2 = df2.set_index("date")
524-
df_final = df2.resample(timeframe_freq)[["pair"]].count()
525-
df_final = df_final.rename({"pair": "open_trades"}, axis=1)
526-
return df_final
527-
528-
529-
def evaluate_result_multi(
530-
trades: pd.DataFrame, timeframe: str, max_open_trades: IntOrInf
531-
) -> pd.DataFrame:
532-
"""
533-
Find overlapping trades by expanding each trade once per period it was open
534-
and then counting overlaps
535-
:param trades: Trades Dataframe - can be loaded from backtest, or created
536-
via trade_list_to_dataframe
537-
:param timeframe: Frequency used for the backtest
538-
:param max_open_trades: parameter max_open_trades used during backtest run
539-
:return: dataframe with open-counts per time-period in freq
540-
"""
541-
df_final = analyze_trade_parallelism(trades, timeframe)
542-
return df_final[df_final["open_trades"] > max_open_trades]
543-
544-
545494
def trade_list_to_dataframe(trades: list[Trade] | list[LocalTrade]) -> pd.DataFrame:
546495
"""
547496
Convert list of Trade objects to pandas Dataframe
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
import logging
2+
3+
import numpy as np
4+
import pandas as pd
5+
6+
from freqtrade.constants import IntOrInf
7+
8+
9+
logger = logging.getLogger(__name__)
10+
11+
12+
def analyze_trade_parallelism(trades: pd.DataFrame, timeframe: str) -> pd.DataFrame:
13+
"""
14+
Find overlapping trades by expanding each trade once per period it was open
15+
and then counting overlaps.
16+
:param trades: Trades Dataframe - can be loaded from backtest, or created
17+
via trade_list_to_dataframe
18+
:param timeframe: Timeframe used for backtest
19+
:return: dataframe with open-counts per time-period in timeframe
20+
"""
21+
from freqtrade.exchange import timeframe_to_resample_freq
22+
23+
timeframe_freq = timeframe_to_resample_freq(timeframe)
24+
dates = [
25+
pd.Series(
26+
pd.date_range(
27+
row[1]["open_date"],
28+
row[1]["close_date"],
29+
freq=timeframe_freq,
30+
# Exclude right boundary - the date is the candle open date.
31+
inclusive="left",
32+
)
33+
)
34+
for row in trades[["open_date", "close_date"]].iterrows()
35+
]
36+
deltas = [len(x) for x in dates]
37+
dates = pd.Series(pd.concat(dates).values, name="date")
38+
df2 = pd.DataFrame(np.repeat(trades.values, deltas, axis=0), columns=trades.columns)
39+
40+
df2 = pd.concat([dates, df2], axis=1)
41+
df2 = df2.set_index("date")
42+
df_final = df2.resample(timeframe_freq)[["pair"]].count()
43+
df_final = df_final.rename({"pair": "open_trades"}, axis=1)
44+
return df_final
45+
46+
47+
def evaluate_result_multi(
48+
trades: pd.DataFrame, timeframe: str, max_open_trades: IntOrInf
49+
) -> pd.DataFrame:
50+
"""
51+
Find overlapping trades by expanding each trade once per period it was open
52+
and then counting overlaps
53+
:param trades: Trades Dataframe - can be loaded from backtest, or created
54+
via trade_list_to_dataframe
55+
:param timeframe: Frequency used for the backtest
56+
:param max_open_trades: parameter max_open_trades used during backtest run
57+
:return: dataframe with open-counts per time-period in freq
58+
"""
59+
df_final = analyze_trade_parallelism(trades, timeframe)
60+
return df_final[df_final["open_trades"] > max_open_trades]

0 commit comments

Comments
 (0)