1、新增dp策略

This commit is contained in:
2025-09-16 09:59:38 +08:00
parent 5cd926884d
commit 9a58fec9ca
120 changed files with 69683 additions and 325 deletions

View File

@@ -80,6 +80,15 @@ def calculate_metrics(
else:
calmar_ratio = float("inf")
target_return = 0
downside_returns = df_returns[df_returns < target_return]
downside_deviation = downside_returns.std()
sortino_ratio = 0.0
if downside_deviation > 0:
# 年化超额收益率 / 年化下行波动率
sortino_ratio = np.sqrt(252) * (excess_daily_returns.mean() / downside_deviation)
total_commissions = sum(t.commission for t in trades)
# --- 重新计算交易相关指标 ---
@@ -139,6 +148,7 @@ def calculate_metrics(
"max_drawdown": max_drawdown,
"sharpe_ratio": sharpe_ratio,
"calmar_ratio": calmar_ratio,
"sortino_ratio": sortino_ratio,
"total_trades": len(trades), # All buy and sell trades
"transaction_costs": total_commissions,
"total_realized_pnl": total_realized_pnl, # New

View File

@@ -46,7 +46,7 @@ class GridSearchAnalyzer:
print(f" {self.optimization_metric}: {best_result[self.optimization_metric]:.4f}")
return best_result
def plot_heatmap(self, title: str = "heatmap"):
def plot_heatmap(self, title: str = "heatmap", order_direction: str=None):
"""
绘制两个参数的热力图。
"""
@@ -59,11 +59,15 @@ class GridSearchAnalyzer:
heatmap_matrix = np.zeros((len(y_values), len(x_values)))
max_values = max([item[self.optimization_metric] for item in self.grid_results])
# 填充网格
for item in self.grid_results:
x_idx = x_values.index(item[self.param1_name])
y_idx = y_values.index(item[self.param2_name])
heatmap_matrix[y_idx, x_idx] = item[self.optimization_metric]
if max_values < 0.1:
heatmap_matrix[y_idx, x_idx] = item[self.optimization_metric] * 100
else:
heatmap_matrix[y_idx, x_idx] = item[self.optimization_metric]
print([x_values[0], x_values[-1], y_values[0], y_values[-1]])
fig, ax = plt.subplots(figsize=(10, 8))
@@ -76,7 +80,7 @@ class GridSearchAnalyzer:
ax.set_xlabel(self.param1_name)
ax.set_ylabel(self.param2_name)
ax.set_title(f"{title}: {self.optimization_metric} vs. {self.param1_name} & {self.param2_name}")
ax.set_title(f"{title}: {self.optimization_metric} vs. {self.param1_name} & {self.param2_name}, order={order_direction}")
cbar = fig.colorbar(im, ax=ax)
cbar.set_label(self.optimization_metric)

View File

@@ -166,6 +166,23 @@ class ResultAnalyzer:
# DataFrame 的结构为:['indicator_value', 'realized_pnl']
df = pd.DataFrame({"indicator_value": indi_values, "realized_pnl": pnls})
def remove_extreme(df, col='indicator_value', k=3):
"""IQR 稳健过滤,返回过滤后的 df 和被剔除的行数"""
q1, q3 = df[col].quantile([0.25, 0.75])
iqr = q3 - q1
lower, upper = q1 - k * iqr, q3 + k * iqr
mask = df[col].between(lower, upper)
n_remove = (~mask).sum()
return df[mask].copy(), n_remove
df, n_drop = remove_extreme(df) # 默认 k=2.5
if n_drop:
print(f"指标 '{indicator_name}' 过滤掉 {n_drop} 个极端异常值 "
f"({n_drop / len(df) * 100:.1f}%),剩余 {len(df)} 条样本。")
if df.empty:
print(f"指标 '{indicator_name}' 过滤后无数据,跳过绘图。")
continue
# 确保数据框不为空
if df.empty:
print(f"指标 '{indicator_name}' 的数据框为空,跳过绘图。")