feat: add wallet based metrics to backtest output
This commit is contained in:
@@ -289,7 +289,7 @@ def text_table_add_metrics(strat_results: dict) -> None:
|
||||
)
|
||||
wallet_metrics: list[tuple[str, str]] = [
|
||||
(
|
||||
"Min/Max balance realized",
|
||||
"Min/Max balance (realized)",
|
||||
f"{fmt_coin(strat_results['csum_min'], stake)} / "
|
||||
f"{fmt_coin(strat_results['csum_max'], stake)}",
|
||||
),
|
||||
@@ -298,22 +298,38 @@ def text_table_add_metrics(strat_results: dict) -> None:
|
||||
wallet_metrics.extend(
|
||||
[
|
||||
(
|
||||
"Min/Max balance unrealized",
|
||||
"Min/Max balance (unrealized)",
|
||||
f"{fmt_coin(wallet_stats['low_balance'], stake)} / "
|
||||
f"{fmt_coin(wallet_stats['high_balance'], stake)}",
|
||||
),
|
||||
(
|
||||
"Min/Max balance dates",
|
||||
"Min/Max balance dates (unrealized)",
|
||||
f"{wallet_stats['low_date']} / {wallet_stats['high_date']}",
|
||||
),
|
||||
]
|
||||
)
|
||||
if "sharpe" in wallet_stats:
|
||||
wallet_metrics.append(
|
||||
(
|
||||
"Sharpe ratio balance",
|
||||
f"{wallet_stats['sharpe']:.2f}",
|
||||
)
|
||||
# Assume that if sharpe is there, all others are there as well.
|
||||
wallet_metrics.extend(
|
||||
[
|
||||
(
|
||||
"Sharpe (unrealized)",
|
||||
f"{wallet_stats['sharpe']:.2f}",
|
||||
),
|
||||
(
|
||||
"Sortino (unrealized)",
|
||||
f"{wallet_stats['sortino']:.2f}",
|
||||
),
|
||||
(
|
||||
"Calmar (unrealized)",
|
||||
f"{wallet_stats['calmar']:.2f}",
|
||||
),
|
||||
(
|
||||
"Max drawdown (unrealized)",
|
||||
f"{fmt_coin(wallet_stats['max_drawdown_abs'], stake)} "
|
||||
f"({wallet_stats['max_drawdown_account']:.2%})",
|
||||
),
|
||||
]
|
||||
)
|
||||
|
||||
# Newly added fields should be ignored if they are missing in strat_results. hyperopt-show
|
||||
|
||||
@@ -10,13 +10,16 @@ from freqtrade.constants import BACKTEST_BREAKDOWNS, DATETIME_PRINT_FORMAT
|
||||
from freqtrade.data.metrics import (
|
||||
calculate_cagr,
|
||||
calculate_calmar,
|
||||
calculate_calmar_from_balance,
|
||||
calculate_csum,
|
||||
calculate_expectancy,
|
||||
calculate_market_change,
|
||||
calculate_max_drawdown,
|
||||
calculate_max_drawdown_from_balance,
|
||||
calculate_sharpe,
|
||||
calculate_sharpe_from_balance,
|
||||
calculate_sortino,
|
||||
calculate_sortino_from_balance,
|
||||
calculate_sqn,
|
||||
)
|
||||
from freqtrade.ft_types import (
|
||||
@@ -61,12 +64,43 @@ def generate_wallet_stats(wallet_df: DataFrame, stake_currency: str) -> dict[str
|
||||
low_date = wallet.loc[low_idx, "date"]
|
||||
high_date = wallet.loc[high_idx, "date"]
|
||||
sharpe = calculate_sharpe_from_balance(wallet)
|
||||
sortino = calculate_sortino_from_balance(wallet)
|
||||
calmar = calculate_calmar_from_balance(wallet)
|
||||
try:
|
||||
drawdown = calculate_max_drawdown_from_balance(wallet)
|
||||
except ValueError:
|
||||
drawdown = None
|
||||
|
||||
return {
|
||||
"start_balance": start_balance,
|
||||
"end_balance": end_balance,
|
||||
"high_balance": high_balance,
|
||||
"low_balance": low_balance,
|
||||
"sharpe": sharpe,
|
||||
"sortino": sortino,
|
||||
"calmar": calmar,
|
||||
"max_drawdown_account": drawdown.relative_account_drawdown if drawdown else 0.0,
|
||||
"max_drawdown_abs": drawdown.drawdown_abs if drawdown else 0.0,
|
||||
"drawdown_start": (
|
||||
drawdown.high_date.strftime(DATETIME_PRINT_FORMAT)
|
||||
if drawdown and drawdown.high_date is not None
|
||||
else None
|
||||
),
|
||||
"drawdown_start_ts": (
|
||||
int(drawdown.high_date.timestamp() * 1000)
|
||||
if drawdown and drawdown.high_date is not None
|
||||
else None
|
||||
),
|
||||
"drawdown_end": (
|
||||
drawdown.low_date.strftime(DATETIME_PRINT_FORMAT)
|
||||
if drawdown and drawdown.low_date is not None
|
||||
else None
|
||||
),
|
||||
"drawdown_end_ts": (
|
||||
int(drawdown.low_date.timestamp() * 1000)
|
||||
if drawdown and drawdown.low_date is not None
|
||||
else None
|
||||
),
|
||||
"low_date": low_date.strftime(DATETIME_PRINT_FORMAT),
|
||||
"low_ts": int(low_date.timestamp() * 1000),
|
||||
"high_date": high_date.strftime(DATETIME_PRINT_FORMAT),
|
||||
|
||||
Reference in New Issue
Block a user