mirror of
https://github.com/freqtrade/freqtrade.git
synced 2026-01-26 00:40:23 +00:00
Merge pull request #11899 from mrpabloyeah/add-current-drawdown-in-telegram-profit-command
Add current drawdown in telegram profit command
This commit is contained in:
@@ -174,12 +174,18 @@ def calculate_underwater(
|
|||||||
|
|
||||||
@dataclass()
|
@dataclass()
|
||||||
class DrawDownResult:
|
class DrawDownResult:
|
||||||
|
# Max drawdown fields
|
||||||
drawdown_abs: float = 0.0
|
drawdown_abs: float = 0.0
|
||||||
high_date: pd.Timestamp = None
|
high_date: pd.Timestamp = None
|
||||||
low_date: pd.Timestamp = None
|
low_date: pd.Timestamp = None
|
||||||
high_value: float = 0.0
|
high_value: float = 0.0
|
||||||
low_value: float = 0.0
|
low_value: float = 0.0
|
||||||
relative_account_drawdown: float = 0.0
|
relative_account_drawdown: float = 0.0
|
||||||
|
# Current drawdown fields
|
||||||
|
current_high_date: pd.Timestamp = None
|
||||||
|
current_high_value: float = 0.0
|
||||||
|
current_drawdown_abs: float = 0.0
|
||||||
|
current_relative_account_drawdown: float = 0.0
|
||||||
|
|
||||||
|
|
||||||
def calculate_max_drawdown(
|
def calculate_max_drawdown(
|
||||||
@@ -191,29 +197,31 @@ def calculate_max_drawdown(
|
|||||||
relative: bool = False,
|
relative: bool = False,
|
||||||
) -> DrawDownResult:
|
) -> DrawDownResult:
|
||||||
"""
|
"""
|
||||||
Calculate max drawdown and the corresponding close dates
|
Calculate max drawdown and current drawdown with corresponding dates
|
||||||
:param trades: DataFrame containing trades (requires columns close_date and profit_ratio)
|
:param trades: DataFrame containing trades (requires columns close_date and profit_abs)
|
||||||
:param date_col: Column in DataFrame to use for dates (defaults to 'close_date')
|
:param date_col: Column in DataFrame to use for dates (defaults to 'close_date')
|
||||||
:param value_col: Column in DataFrame to use for values (defaults to 'profit_abs')
|
:param value_col: Column in DataFrame to use for values (defaults to 'profit_abs')
|
||||||
:param starting_balance: Portfolio starting balance - properly calculate relative drawdown.
|
:param starting_balance: Portfolio starting balance - properly calculate relative drawdown.
|
||||||
|
:param relative: If True, use relative drawdown for max calculation instead of absolute
|
||||||
:return: DrawDownResult object
|
:return: DrawDownResult object
|
||||||
with absolute max drawdown, high and low time and high and low value,
|
with absolute max drawdown, high and low time and high and low value,
|
||||||
and the relative account drawdown
|
relative account drawdown, and current drawdown information.
|
||||||
:raise: ValueError if trade-dataframe was found empty.
|
:raise: ValueError if trade-dataframe was found empty.
|
||||||
"""
|
"""
|
||||||
if len(trades) == 0:
|
if len(trades) == 0:
|
||||||
raise ValueError("Trade dataframe empty.")
|
raise ValueError("Trade dataframe empty.")
|
||||||
|
|
||||||
profit_results = trades.sort_values(date_col).reset_index(drop=True)
|
profit_results = trades.sort_values(date_col).reset_index(drop=True)
|
||||||
max_drawdown_df = _calc_drawdown_series(
|
max_drawdown_df = _calc_drawdown_series(
|
||||||
profit_results, date_col=date_col, value_col=value_col, starting_balance=starting_balance
|
profit_results, date_col=date_col, value_col=value_col, starting_balance=starting_balance
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Calculate maximum drawdown
|
||||||
idxmin = (
|
idxmin = (
|
||||||
max_drawdown_df["drawdown_relative"].idxmax()
|
max_drawdown_df["drawdown_relative"].idxmax()
|
||||||
if relative
|
if relative
|
||||||
else max_drawdown_df["drawdown"].idxmin()
|
else max_drawdown_df["drawdown"].idxmin()
|
||||||
)
|
)
|
||||||
|
|
||||||
high_idx = max_drawdown_df.iloc[: idxmin + 1]["high_value"].idxmax()
|
high_idx = max_drawdown_df.iloc[: idxmin + 1]["high_value"].idxmax()
|
||||||
high_date = profit_results.loc[high_idx, date_col]
|
high_date = profit_results.loc[high_idx, date_col]
|
||||||
low_date = profit_results.loc[idxmin, date_col]
|
low_date = profit_results.loc[idxmin, date_col]
|
||||||
@@ -221,13 +229,27 @@ def calculate_max_drawdown(
|
|||||||
low_val = max_drawdown_df.loc[idxmin, "cumulative"]
|
low_val = max_drawdown_df.loc[idxmin, "cumulative"]
|
||||||
max_drawdown_rel = max_drawdown_df.loc[idxmin, "drawdown_relative"]
|
max_drawdown_rel = max_drawdown_df.loc[idxmin, "drawdown_relative"]
|
||||||
|
|
||||||
|
# Calculate current drawdown
|
||||||
|
current_high_idx = max_drawdown_df["high_value"].iloc[:-1].idxmax()
|
||||||
|
current_high_date = profit_results.loc[current_high_idx, date_col]
|
||||||
|
current_high_value = max_drawdown_df.iloc[-1]["high_value"]
|
||||||
|
current_cumulative = max_drawdown_df.iloc[-1]["cumulative"]
|
||||||
|
current_drawdown_abs = current_high_value - current_cumulative
|
||||||
|
current_drawdown_relative = max_drawdown_df.iloc[-1]["drawdown_relative"]
|
||||||
|
|
||||||
return DrawDownResult(
|
return DrawDownResult(
|
||||||
|
# Max drawdown
|
||||||
drawdown_abs=abs(max_drawdown_df.loc[idxmin, "drawdown"]),
|
drawdown_abs=abs(max_drawdown_df.loc[idxmin, "drawdown"]),
|
||||||
high_date=high_date,
|
high_date=high_date,
|
||||||
low_date=low_date,
|
low_date=low_date,
|
||||||
high_value=high_val,
|
high_value=high_val,
|
||||||
low_value=low_val,
|
low_value=low_val,
|
||||||
relative_account_drawdown=max_drawdown_rel,
|
relative_account_drawdown=max_drawdown_rel,
|
||||||
|
# Current drawdown
|
||||||
|
current_high_date=current_high_date,
|
||||||
|
current_high_value=current_high_value,
|
||||||
|
current_drawdown_abs=current_drawdown_abs,
|
||||||
|
current_relative_account_drawdown=current_drawdown_relative,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -163,6 +163,11 @@ class Profit(BaseModel):
|
|||||||
max_drawdown_start_timestamp: int
|
max_drawdown_start_timestamp: int
|
||||||
max_drawdown_end: str
|
max_drawdown_end: str
|
||||||
max_drawdown_end_timestamp: int
|
max_drawdown_end_timestamp: int
|
||||||
|
current_drawdown: float
|
||||||
|
current_drawdown_abs: float
|
||||||
|
current_drawdown_high: float
|
||||||
|
current_drawdown_start: str
|
||||||
|
current_drawdown_start_timestamp: int
|
||||||
trading_volume: float | None = None
|
trading_volume: float | None = None
|
||||||
bot_start_timestamp: int
|
bot_start_timestamp: int
|
||||||
bot_start_date: str
|
bot_start_date: str
|
||||||
|
|||||||
@@ -681,6 +681,11 @@ class RPC:
|
|||||||
"max_drawdown_end_timestamp": dt_ts_def(drawdown.low_date),
|
"max_drawdown_end_timestamp": dt_ts_def(drawdown.low_date),
|
||||||
"drawdown_high": drawdown.high_value,
|
"drawdown_high": drawdown.high_value,
|
||||||
"drawdown_low": drawdown.low_value,
|
"drawdown_low": drawdown.low_value,
|
||||||
|
"current_drawdown": drawdown.current_relative_account_drawdown,
|
||||||
|
"current_drawdown_abs": drawdown.current_drawdown_abs,
|
||||||
|
"current_drawdown_high": drawdown.current_high_value,
|
||||||
|
"current_drawdown_start": format_date(drawdown.current_high_date),
|
||||||
|
"current_drawdown_start_timestamp": dt_ts_def(drawdown.current_high_date),
|
||||||
"trading_volume": trading_volume,
|
"trading_volume": trading_volume,
|
||||||
"bot_start_timestamp": dt_ts_def(bot_start, 0),
|
"bot_start_timestamp": dt_ts_def(bot_start, 0),
|
||||||
"bot_start_date": format_date(bot_start),
|
"bot_start_date": format_date(bot_start),
|
||||||
|
|||||||
@@ -1085,6 +1085,10 @@ class Telegram(RPCHandler):
|
|||||||
f"({fmt_coin(stats['drawdown_high'], stake_cur)})`\n"
|
f"({fmt_coin(stats['drawdown_high'], stake_cur)})`\n"
|
||||||
f" to `{stats['max_drawdown_end']} "
|
f" to `{stats['max_drawdown_end']} "
|
||||||
f"({fmt_coin(stats['drawdown_low'], stake_cur)})`\n"
|
f"({fmt_coin(stats['drawdown_low'], stake_cur)})`\n"
|
||||||
|
f"*Current Drawdown:* `{stats['current_drawdown']:.2%} "
|
||||||
|
f"({fmt_coin(stats['current_drawdown_abs'], stake_cur)})`\n"
|
||||||
|
f" from `{stats['current_drawdown_start']} "
|
||||||
|
f"({fmt_coin(stats['current_drawdown_high'], stake_cur)})`\n"
|
||||||
)
|
)
|
||||||
await self._send_msg(
|
await self._send_msg(
|
||||||
markdown_msg,
|
markdown_msg,
|
||||||
|
|||||||
@@ -1332,6 +1332,11 @@ def test_api_profit(botclient, mocker, ticker, fee, markets, is_short, expected)
|
|||||||
"max_drawdown_start_timestamp": ANY,
|
"max_drawdown_start_timestamp": ANY,
|
||||||
"max_drawdown_end": ANY,
|
"max_drawdown_end": ANY,
|
||||||
"max_drawdown_end_timestamp": ANY,
|
"max_drawdown_end_timestamp": ANY,
|
||||||
|
"current_drawdown": ANY,
|
||||||
|
"current_drawdown_abs": ANY,
|
||||||
|
"current_drawdown_high": ANY,
|
||||||
|
"current_drawdown_start": ANY,
|
||||||
|
"current_drawdown_start_timestamp": ANY,
|
||||||
"trading_volume": expected["trading_volume"],
|
"trading_volume": expected["trading_volume"],
|
||||||
"bot_start_timestamp": 0,
|
"bot_start_timestamp": 0,
|
||||||
"bot_start_date": "",
|
"bot_start_date": "",
|
||||||
|
|||||||
Reference in New Issue
Block a user