梅玺交作业
由bqmfycsy创建,最终由bqmfycsy 被浏览 5 用户
原始SQL调整:
context.sql = f"""
select
date,
instrument,
pct_rank_by(date,total_market_cap) as score1,
pct_rank_by(date,turn) as score2,
pct_rank_by(date,close/m_lag(close, 1)) as score3,
{n1}*score1+{n2}*score2+{n3}*score3 as score,
from
cn_stock_prefactors
where
is_risk_warning=0
and
list_days>365
and
list_sector < 3
and
pe_ttm>0
"""
加入超参搜索:
line_styles = ['-', '--', '-.', ':']
markers = ['o', 's', '^', 'D', 'v']
count = 0
max_sharp = 0
best_arg = []
df_all = []
arg_dic = {}
for i in range(1,10):
for j in range (1, 10):
if i+j<=10:
performance = run(i, j, 10-i-j)
arg_dic[count] = f"{i}-{j}-{10-i-j}"
# performance.render()
raw_perf=performance.raw_perf
total_return = (raw_perf['portfolio_value'].iloc[-1] / raw_perf['portfolio_value'][0]) - 1
annual_return = (1 + total_return) ** (252 / len(raw_perf)) - 1
# 最大回撤
max_drawdown = (raw_perf['portfolio_value'] / raw_perf['portfolio_value'].cummax() - 1).min()
# 夏普比率(假设无风险利率=0)
annualized_return = raw_perf['returns'].mean() * 252 # 简单年化
# 或:annualized_return = (1 + raw_perf['returns'].mean())**252 - 1 # 复利年化
annualized_vol = raw_perf['returns'].std() * np.sqrt(252)
sharp_ratio = annualized_return / annualized_vol
df_result = raw_perf[['date', 'portfolio_value']].copy()
df_all.append(df_result)
count = count + 1
print(f"第{count}轮参数:{i},{j},{10-i-j},夏普比率:{sharp_ratio}")
if sharp_ratio > max_sharp:
best_arg = [i,j,10-i-j]
max_sharp = sharp_ratio
print(f"最佳参数:{best_arg[0]},{best_arg[1]},{best_arg[2]},最大夏普比率:{max_sharp}")
绘制曲线:
def plot_multiple_portfolios(df_all, arg_dic, title='Portfolio Value Comparison'):
"""
在同一个图表中绘制多个投资组合的价值曲线
参数:
df_all -- 包含多个DataFrame的列表,每个DataFrame应包含'date'和'portfolio_value'列
arg_dic -- 参数字典,键为索引,值为参数字符串
title -- 图表标题
"""
# 检查输入数据
if not df_all:
print("错误: df_all 列表为空!")
return
# 创建图表
fig, ax = plt.subplots(figsize=(12, 12))
# 获取组合数量
count = len(df_all)
print(f"要绘制的组合数量: {count}")
# 设置颜色、线型和标记
colors = plt.cm.tab10(np.linspace(0, 1, min(count, 10))) # 最多10种颜色
line_styles = ['-', '--', '-.', ':'] * 2 # 重复使用线型
markers = ['o', 's', '^', 'D', 'v', '<', '>', 'p', '*', 'X'] # 多种标记
# 调试信息
print("\n===== 调试信息开始 =====")
# 遍历每个DataFrame并绘制
for i in range(count):
df = df_all[i]
if 'date' in df.columns and df.index.name == 'date':
# 保留列中的日期,删除索引名称
df = df.reset_index(drop=True)
print(f"组合 {i}: 已解决日期列/索引冲突 - 保留列中的日期")
elif df.index.name == 'date' and 'date' not in df.columns:
# 如果索引是日期但没有日期列,将索引转为列
df = df.reset_index()
print(f"组合 {i}: 已解决日期索引问题 - 将索引转为列")
# 确保日期格式正确
try:
if not pd.api.types.is_datetime64_any_dtype(df['date']):
df['date'] = pd.to_datetime(df['date'])
except Exception as e:
print(f"索引 {i} 的日期转换错误: {e}")
continue
# 排序确保时间序列正确
df = df.sort_values('date')
# 提取数据
dates = df['date']
values = df['portfolio_value']
# 获取参数标签
arg_str = arg_dic.get(i, f"组合{i+1}")
# 调试打印
print(f"\n组合 {i+1}/{count}:")
print(f" 参数: {arg_str}")
print(f" 日期范围: {dates.min().strftime('%Y-%m-%d')} 到 {dates.max().strftime('%Y-%m-%d')}")
print(f" 净值范围: {values.min():.2f} 到 {values.max():.2f}")
print(f" 数据点数: {len(df)}")
# 绘制曲线
ax.plot(
dates,
values,
label=f'{arg_str}',
color=colors[i % len(colors)],
linestyle=line_styles[i % len(line_styles)],
marker=markers[i % len(markers)] if len(df) < 50 else None,
markersize=5,
linewidth=2
)
print("===== 调试信息结束 =====\n")
# 如果没有成功绘制任何曲线
if not ax.lines:
print("错误: 没有成功绘制任何曲线!")
plt.close(fig)
return
# 设置日期格式
ax.xaxis.set_major_formatter(mdates.DateFormatter('%Y-%m-%d'))
ax.xaxis.set_major_locator(mdates.AutoDateLocator())
# 自动旋转日期标签
fig.autofmt_xdate()
# 添加标签和标题
ax.set_xlabel('Date', fontsize=12)
ax.set_ylabel('Portfolio Value', fontsize=12)
ax.set_title(title, fontsize=14)
# 添加网格
ax.grid(True, linestyle='--', alpha=0.7)
# 添加图例
handles, labels = ax.get_legend_handles_labels()
if handles:
ax.legend(handles, labels, fontsize=10, loc='best')
print(f"图例已添加,包含 {len(handles)} 个项目")
else:
print("警告: 没有找到任何图例项目!")
# 优化布局
plt.tight_layout()
# 显示图表
plt.show()
# 返回图表对象以便进一步操作
return fig, ax
plot_multiple_portfolios(df_all, arg_dic, title="投资策略表现比较")
曲线如下图: