mirror of
https://github.com/Arianhgh/fx-quant-research.git
synced 2026-08-08 00:17:44 +00:00
61 lines
2.2 KiB
Python
61 lines
2.2 KiB
Python
"""Simple strategy performance metrics.
|
|
|
|
Scores a ``signal`` column against forward returns: total return, annualized
|
|
Sharpe, win rate and max drawdown.
|
|
"""
|
|
import numpy as np
|
|
|
|
|
|
def compute_performance_metrics(data, signal_col="signal", forecast_periods=12,
|
|
annualization=24 * 365, verbose=True):
|
|
"""Compute strategy performance from a signal column and forward returns.
|
|
|
|
Parameters
|
|
----------
|
|
data : pd.DataFrame
|
|
Must contain a ``close`` column and ``signal_col`` (values in {-1, 0, 1}).
|
|
forecast_periods : int
|
|
Holding horizon (in bars) used to compute the forward return.
|
|
annualization : float
|
|
Factor applied under the square root when annualizing the Sharpe ratio.
|
|
|
|
Returns
|
|
-------
|
|
dict
|
|
total_return, sharpe_ratio, win_rate, max_drawdown and the augmented frame.
|
|
"""
|
|
df = data.copy()
|
|
|
|
# Forward return over the forecast horizon.
|
|
df["future_return"] = df["close"].pct_change(periods=forecast_periods).shift(-forecast_periods)
|
|
|
|
# Strategy return: signal * future return (long: +return, short: -return).
|
|
df["strategy_return"] = df[signal_col] * df["future_return"]
|
|
df = df.dropna(subset=["strategy_return"])
|
|
|
|
# Cumulative return.
|
|
df["cumulative_return"] = (1 + df["strategy_return"]).cumprod() - 1
|
|
|
|
total_return = df["cumulative_return"].iloc[-1] if len(df) else float("nan")
|
|
sharpe_ratio = (
|
|
df["strategy_return"].mean() / df["strategy_return"].std() * np.sqrt(annualization)
|
|
if df["strategy_return"].std() else float("nan")
|
|
)
|
|
active = df[df["strategy_return"] != 0]
|
|
win_rate = len(df[df["strategy_return"] > 0]) / len(active) if len(active) else float("nan")
|
|
max_drawdown = (df["cumulative_return"].cummax() - df["cumulative_return"]).max()
|
|
|
|
if verbose:
|
|
print(f"Total Return: {total_return:.2%}")
|
|
print(f"Sharpe Ratio: {sharpe_ratio:.2f}")
|
|
print(f"Win Rate: {win_rate:.2%}")
|
|
print(f"Max Drawdown: {max_drawdown:.2%}")
|
|
|
|
return {
|
|
"total_return": total_return,
|
|
"sharpe_ratio": sharpe_ratio,
|
|
"win_rate": win_rate,
|
|
"max_drawdown": max_drawdown,
|
|
"data": df,
|
|
}
|