PLUS会员

梅玺交作业

由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="投资策略表现比较")


曲线如下图:

标签

Python数据处理
{link}