Some improvements to backtest summary metrics
This commit is contained in:
@@ -194,6 +194,7 @@ def text_table_strategy(strategy_results, stake_currency: str, title: str):
|
|||||||
|
|
||||||
|
|
||||||
def text_table_add_metrics(strat_results: dict) -> None:
|
def text_table_add_metrics(strat_results: dict) -> None:
|
||||||
|
stake = strat_results["stake_currency"]
|
||||||
if len(strat_results["trades"]) > 0:
|
if len(strat_results["trades"]) > 0:
|
||||||
best_trade = max(strat_results["trades"], key=lambda x: x["profit_ratio"])
|
best_trade = max(strat_results["trades"], key=lambda x: x["profit_ratio"])
|
||||||
worst_trade = min(strat_results["trades"], key=lambda x: x["profit_ratio"])
|
worst_trade = min(strat_results["trades"], key=lambda x: x["profit_ratio"])
|
||||||
@@ -202,23 +203,19 @@ def text_table_add_metrics(strat_results: dict) -> None:
|
|||||||
[
|
[
|
||||||
("", ""), # Empty line to improve readability
|
("", ""), # Empty line to improve readability
|
||||||
(
|
(
|
||||||
"Long / Short",
|
"Long / Short trades",
|
||||||
f"{strat_results.get('trade_count_long', 'total_trades')} / "
|
f"{strat_results.get('trade_count_long', 'total_trades')} / "
|
||||||
f"{strat_results.get('trade_count_short', 0)}",
|
f"{strat_results.get('trade_count_short', 0)}",
|
||||||
),
|
),
|
||||||
("Total profit Long %", f"{strat_results['profit_total_long']:.2%}"),
|
|
||||||
("Total profit Short %", f"{strat_results['profit_total_short']:.2%}"),
|
|
||||||
(
|
(
|
||||||
"Absolute profit Long",
|
"Long / Short profit %",
|
||||||
fmt_coin(
|
f"{strat_results['profit_total_long']:.2%} / "
|
||||||
strat_results["profit_total_long_abs"], strat_results["stake_currency"]
|
f"{strat_results['profit_total_short']:.2%}",
|
||||||
),
|
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
"Absolute profit Short",
|
f"Long / Short profit {stake}",
|
||||||
fmt_coin(
|
f"{strat_results['profit_total_long_abs']:.{decimals_per_coin(stake)}f} / "
|
||||||
strat_results["profit_total_short_abs"], strat_results["stake_currency"]
|
f"{strat_results['profit_total_short_abs']:.{decimals_per_coin(stake)}f}",
|
||||||
),
|
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
if strat_results.get("trade_count_short", 0) > 0
|
if strat_results.get("trade_count_short", 0) > 0
|
||||||
@@ -231,27 +228,34 @@ def text_table_add_metrics(strat_results: dict) -> None:
|
|||||||
drawdown_metrics.append(
|
drawdown_metrics.append(
|
||||||
("Max % of account underwater", f"{strat_results['max_relative_drawdown']:.2%}")
|
("Max % of account underwater", f"{strat_results['max_relative_drawdown']:.2%}")
|
||||||
)
|
)
|
||||||
|
drawdown_account = (
|
||||||
|
strat_results["max_drawdown_account"]
|
||||||
|
if "max_drawdown_account" in strat_results
|
||||||
|
else strat_results["max_drawdown"]
|
||||||
|
)
|
||||||
drawdown_metrics.extend(
|
drawdown_metrics.extend(
|
||||||
[
|
[
|
||||||
(
|
(
|
||||||
("Absolute Drawdown (Account)", f"{strat_results['max_drawdown_account']:.2%}")
|
"Absolute drawdown",
|
||||||
if "max_drawdown_account" in strat_results
|
f"{fmt_coin(strat_results['max_drawdown_abs'], stake)} "
|
||||||
else ("Drawdown", f"{strat_results['max_drawdown']:.2%}")
|
f"({drawdown_account:.2%})",
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
"Absolute Drawdown",
|
"Drawdown duration",
|
||||||
fmt_coin(strat_results["max_drawdown_abs"], strat_results["stake_currency"]),
|
strat_results["drawdown_duration"]
|
||||||
|
if "drawdown_duration" in strat_results
|
||||||
|
else "N/A",
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
"Drawdown high",
|
"Profit at drawdown start",
|
||||||
fmt_coin(strat_results["max_drawdown_high"], strat_results["stake_currency"]),
|
fmt_coin(strat_results["max_drawdown_high"], stake),
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
"Drawdown low",
|
"Profit at drawdown end",
|
||||||
fmt_coin(strat_results["max_drawdown_low"], strat_results["stake_currency"]),
|
fmt_coin(strat_results["max_drawdown_low"], stake),
|
||||||
),
|
),
|
||||||
("Drawdown Start", strat_results["drawdown_start"]),
|
("Drawdown start", strat_results["drawdown_start"]),
|
||||||
("Drawdown End", strat_results["drawdown_end"]),
|
("Drawdown end", strat_results["drawdown_end"]),
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -299,15 +303,15 @@ def text_table_add_metrics(strat_results: dict) -> None:
|
|||||||
),
|
),
|
||||||
(
|
(
|
||||||
"Starting balance",
|
"Starting balance",
|
||||||
fmt_coin(strat_results["starting_balance"], strat_results["stake_currency"]),
|
fmt_coin(strat_results["starting_balance"], stake),
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
"Final balance",
|
"Final balance",
|
||||||
fmt_coin(strat_results["final_balance"], strat_results["stake_currency"]),
|
fmt_coin(strat_results["final_balance"], stake),
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
"Absolute profit ",
|
"Absolute profit ",
|
||||||
fmt_coin(strat_results["profit_total_abs"], strat_results["stake_currency"]),
|
fmt_coin(strat_results["profit_total_abs"], stake),
|
||||||
),
|
),
|
||||||
("Total profit %", f"{strat_results['profit_total']:.2%}"),
|
("Total profit %", f"{strat_results['profit_total']:.2%}"),
|
||||||
("CAGR %", f"{strat_results['cagr']:.2%}" if "cagr" in strat_results else "N/A"),
|
("CAGR %", f"{strat_results['cagr']:.2%}" if "cagr" in strat_results else "N/A"),
|
||||||
@@ -335,16 +339,16 @@ def text_table_add_metrics(strat_results: dict) -> None:
|
|||||||
"Avg. daily profit",
|
"Avg. daily profit",
|
||||||
fmt_coin(
|
fmt_coin(
|
||||||
(strat_results["profit_total_abs"] / strat_results["backtest_days"]),
|
(strat_results["profit_total_abs"] / strat_results["backtest_days"]),
|
||||||
strat_results["stake_currency"],
|
stake,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
"Avg. stake amount",
|
"Avg. stake amount",
|
||||||
fmt_coin(strat_results["avg_stake_amount"], strat_results["stake_currency"]),
|
fmt_coin(strat_results["avg_stake_amount"], stake),
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
"Total trade volume",
|
"Total trade volume",
|
||||||
fmt_coin(strat_results["total_volume"], strat_results["stake_currency"]),
|
fmt_coin(strat_results["total_volume"], stake),
|
||||||
),
|
),
|
||||||
*short_metrics,
|
*short_metrics,
|
||||||
("", ""), # Empty line to improve readability
|
("", ""), # Empty line to improve readability
|
||||||
@@ -362,11 +366,11 @@ def text_table_add_metrics(strat_results: dict) -> None:
|
|||||||
("Worst trade", f"{worst_trade['pair']} {worst_trade['profit_ratio']:.2%}"),
|
("Worst trade", f"{worst_trade['pair']} {worst_trade['profit_ratio']:.2%}"),
|
||||||
(
|
(
|
||||||
"Best day",
|
"Best day",
|
||||||
fmt_coin(strat_results["backtest_best_day_abs"], strat_results["stake_currency"]),
|
fmt_coin(strat_results["backtest_best_day_abs"], stake),
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
"Worst day",
|
"Worst day",
|
||||||
fmt_coin(strat_results["backtest_worst_day_abs"], strat_results["stake_currency"]),
|
fmt_coin(strat_results["backtest_worst_day_abs"], stake),
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
"Days win/draw/lose",
|
"Days win/draw/lose",
|
||||||
@@ -404,17 +408,17 @@ def text_table_add_metrics(strat_results: dict) -> None:
|
|||||||
),
|
),
|
||||||
*entry_adjustment_metrics,
|
*entry_adjustment_metrics,
|
||||||
("", ""), # Empty line to improve readability
|
("", ""), # Empty line to improve readability
|
||||||
("Min balance", fmt_coin(strat_results["csum_min"], strat_results["stake_currency"])),
|
("Min balance", fmt_coin(strat_results["csum_min"], stake)),
|
||||||
("Max balance", fmt_coin(strat_results["csum_max"], strat_results["stake_currency"])),
|
("Max balance", fmt_coin(strat_results["csum_max"], stake)),
|
||||||
*drawdown_metrics,
|
*drawdown_metrics,
|
||||||
("Market change", f"{strat_results['market_change']:.2%}"),
|
("Market change", f"{strat_results['market_change']:.2%}"),
|
||||||
]
|
]
|
||||||
print_rich_table(metrics, ["Metric", "Value"], summary="SUMMARY METRICS", justify="left")
|
print_rich_table(metrics, ["Metric", "Value"], summary="SUMMARY METRICS", justify="left")
|
||||||
|
|
||||||
else:
|
else:
|
||||||
start_balance = fmt_coin(strat_results["starting_balance"], strat_results["stake_currency"])
|
start_balance = fmt_coin(strat_results["starting_balance"], stake)
|
||||||
stake_amount = (
|
stake_amount = (
|
||||||
fmt_coin(strat_results["stake_amount"], strat_results["stake_currency"])
|
fmt_coin(strat_results["stake_amount"], stake)
|
||||||
if strat_results["stake_amount"] != UNLIMITED_STAKE_AMOUNT
|
if strat_results["stake_amount"] != UNLIMITED_STAKE_AMOUNT
|
||||||
else "unlimited"
|
else "unlimited"
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -627,6 +627,7 @@ def generate_strategy_stats(
|
|||||||
underwater = calculate_max_drawdown(
|
underwater = calculate_max_drawdown(
|
||||||
results, value_col="profit_abs", starting_balance=start_balance, relative=True
|
results, value_col="profit_abs", starting_balance=start_balance, relative=True
|
||||||
)
|
)
|
||||||
|
drawdown_duration = drawdown.low_date - drawdown.high_date
|
||||||
|
|
||||||
strat_stats.update(
|
strat_stats.update(
|
||||||
{
|
{
|
||||||
@@ -637,6 +638,8 @@ def generate_strategy_stats(
|
|||||||
"drawdown_start_ts": drawdown.high_date.timestamp() * 1000,
|
"drawdown_start_ts": drawdown.high_date.timestamp() * 1000,
|
||||||
"drawdown_end": drawdown.low_date.strftime(DATETIME_PRINT_FORMAT),
|
"drawdown_end": drawdown.low_date.strftime(DATETIME_PRINT_FORMAT),
|
||||||
"drawdown_end_ts": drawdown.low_date.timestamp() * 1000,
|
"drawdown_end_ts": drawdown.low_date.timestamp() * 1000,
|
||||||
|
"drawdown_duration": drawdown_duration,
|
||||||
|
"drawdown_duration_s": drawdown_duration.total_seconds(),
|
||||||
"max_drawdown_low": drawdown.low_value,
|
"max_drawdown_low": drawdown.low_value,
|
||||||
"max_drawdown_high": drawdown.high_value,
|
"max_drawdown_high": drawdown.high_value,
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user