mirror of
https://github.com/freqtrade/freqtrade.git
synced 2025-12-17 05:11:15 +00:00
Add current drawdown in telegram profit command
This commit is contained in:
@@ -231,6 +231,49 @@ def calculate_max_drawdown(
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def calculate_current_drawdown(trades: pd.DataFrame, starting_balance: float):
|
||||||
|
"""
|
||||||
|
Calculates the current drawdown (loss from historical maximum) based on closed trades.
|
||||||
|
|
||||||
|
:param trades: DataFrame containing trades (requires columns close_date_dt and profit_abs)
|
||||||
|
:param starting_balance: Initial account balance
|
||||||
|
:return: DrawDownResult object including:
|
||||||
|
- drawdown_abs: Drawdown in absolute terms
|
||||||
|
- relative_account_drawdown: Drawdown relative to max balance
|
||||||
|
- high_value: Maximum profit reached
|
||||||
|
- high_date: Date when the max profit was reached
|
||||||
|
"""
|
||||||
|
|
||||||
|
if len(trades) == 0:
|
||||||
|
raise ValueError("Trade dataframe empty.")
|
||||||
|
|
||||||
|
# Sort trades by close date
|
||||||
|
sorted_df = trades.sort_values("close_date_dt").reset_index(drop=True)
|
||||||
|
|
||||||
|
# Calculate cumulative profit
|
||||||
|
cum_profit = sorted_df["profit_abs"].cumsum()
|
||||||
|
|
||||||
|
# Find historical maximum profit and its date
|
||||||
|
max_profit_idx = cum_profit.idxmax()
|
||||||
|
max_profit = cum_profit.iloc[max_profit_idx]
|
||||||
|
max_date = sorted_df.iloc[max_profit_idx]["close_date_dt"]
|
||||||
|
|
||||||
|
# Calculate current and max balance
|
||||||
|
current_balance = starting_balance + cum_profit.iloc[-1]
|
||||||
|
max_balance = starting_balance + max_profit
|
||||||
|
|
||||||
|
# Calculate drawdown
|
||||||
|
drawdown_abs = max_balance - current_balance
|
||||||
|
drawdown_relative = drawdown_abs / max_balance
|
||||||
|
|
||||||
|
return DrawDownResult(
|
||||||
|
drawdown_abs=drawdown_abs,
|
||||||
|
relative_account_drawdown=drawdown_relative,
|
||||||
|
high_value=max_profit,
|
||||||
|
high_date=max_date,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def calculate_csum(trades: pd.DataFrame, starting_balance: float = 0) -> tuple[float, float]:
|
def calculate_csum(trades: pd.DataFrame, starting_balance: float = 0) -> tuple[float, float]:
|
||||||
"""
|
"""
|
||||||
Calculate min/max cumsum of trades, to show if the wallet/stake amount ratio is sane
|
Calculate min/max cumsum of trades, to show if the wallet/stake amount ratio is sane
|
||||||
|
|||||||
@@ -19,7 +19,12 @@ from freqtrade import __version__
|
|||||||
from freqtrade.configuration.timerange import TimeRange
|
from freqtrade.configuration.timerange import TimeRange
|
||||||
from freqtrade.constants import CANCEL_REASON, DEFAULT_DATAFRAME_COLUMNS, Config
|
from freqtrade.constants import CANCEL_REASON, DEFAULT_DATAFRAME_COLUMNS, Config
|
||||||
from freqtrade.data.history import load_data
|
from freqtrade.data.history import load_data
|
||||||
from freqtrade.data.metrics import DrawDownResult, calculate_expectancy, calculate_max_drawdown
|
from freqtrade.data.metrics import (
|
||||||
|
DrawDownResult,
|
||||||
|
calculate_current_drawdown,
|
||||||
|
calculate_expectancy,
|
||||||
|
calculate_max_drawdown,
|
||||||
|
)
|
||||||
from freqtrade.enums import (
|
from freqtrade.enums import (
|
||||||
CandleType,
|
CandleType,
|
||||||
ExitCheckTuple,
|
ExitCheckTuple,
|
||||||
@@ -612,17 +617,23 @@ class RPC:
|
|||||||
|
|
||||||
expectancy, expectancy_ratio = calculate_expectancy(trades_df)
|
expectancy, expectancy_ratio = calculate_expectancy(trades_df)
|
||||||
|
|
||||||
drawdown = DrawDownResult()
|
max_drawdown = DrawDownResult()
|
||||||
|
current_drawdown = DrawDownResult()
|
||||||
|
|
||||||
if len(trades_df) > 0:
|
if len(trades_df) > 0:
|
||||||
try:
|
try:
|
||||||
drawdown = calculate_max_drawdown(
|
max_drawdown = calculate_max_drawdown(
|
||||||
trades_df,
|
trades_df,
|
||||||
value_col="profit_abs",
|
value_col="profit_abs",
|
||||||
date_col="close_date_dt",
|
date_col="close_date_dt",
|
||||||
starting_balance=starting_balance,
|
starting_balance=starting_balance,
|
||||||
)
|
)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
# ValueError if no losing trade.
|
pass
|
||||||
|
|
||||||
|
try:
|
||||||
|
current_drawdown = calculate_current_drawdown(trades_df, starting_balance)
|
||||||
|
except ValueError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
profit_all_fiat = (
|
profit_all_fiat = (
|
||||||
@@ -673,14 +684,19 @@ class RPC:
|
|||||||
"winrate": winrate,
|
"winrate": winrate,
|
||||||
"expectancy": expectancy,
|
"expectancy": expectancy,
|
||||||
"expectancy_ratio": expectancy_ratio,
|
"expectancy_ratio": expectancy_ratio,
|
||||||
"max_drawdown": drawdown.relative_account_drawdown,
|
"max_drawdown": max_drawdown.relative_account_drawdown,
|
||||||
"max_drawdown_abs": drawdown.drawdown_abs,
|
"max_drawdown_abs": max_drawdown.drawdown_abs,
|
||||||
"max_drawdown_start": format_date(drawdown.high_date),
|
"max_drawdown_start": format_date(max_drawdown.high_date),
|
||||||
"max_drawdown_start_timestamp": dt_ts_def(drawdown.high_date),
|
"max_drawdown_start_timestamp": dt_ts_def(max_drawdown.high_date),
|
||||||
"max_drawdown_end": format_date(drawdown.low_date),
|
"max_drawdown_end": format_date(max_drawdown.low_date),
|
||||||
"max_drawdown_end_timestamp": dt_ts_def(drawdown.low_date),
|
"max_drawdown_end_timestamp": dt_ts_def(max_drawdown.low_date),
|
||||||
"drawdown_high": drawdown.high_value,
|
"drawdown_high": max_drawdown.high_value,
|
||||||
"drawdown_low": drawdown.low_value,
|
"drawdown_low": max_drawdown.low_value,
|
||||||
|
"current_drawdown": current_drawdown.relative_account_drawdown,
|
||||||
|
"current_drawdown_abs": current_drawdown.drawdown_abs,
|
||||||
|
"current_drawdown_high": current_drawdown.high_value,
|
||||||
|
"current_drawdown_start": format_date(current_drawdown.high_date),
|
||||||
|
"current_drawdown_start_timestamp": dt_ts_def(current_drawdown.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,
|
||||||
|
|||||||
Reference in New Issue
Block a user