跳过复杂的Numba回测和风险模型计算,直接在界面右侧显示模拟的假业绩数据,无需真实运算、无报错,以下是完整可直接运行的代码,点击「一键运行」即可快速显示假数据:
import tkinter as tkfrom tkinter import ttk, messageboximport numpy as npimport pandas as pdimport datetimefrom reportlab.lib import colorsfrom reportlab.lib.pagesizes import A4, landscapefrom reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle, Imagefrom reportlab.lib.styles import getSampleStyleSheet, ParagraphStylefrom io import BytesIO# 强制设置matplotlib非交互式后端,支持无GUI环境生成图表import matplotlibmatplotlib.use('Agg')import matplotlib.pyplot as plt# ======================================# 简化版:直接生成假业绩数据(无复杂计算,避免报错)# ======================================defgenerate_fake_performance_data():"""生成模拟的假业绩数据,直接用于界面展示"""# 固定假数据,保证展示效果一致 total_return = np.round(np.random.uniform(0.15, 0.45), 4) # 总收益率15%-45% annual_return = np.round(np.random.uniform(0.08, 0.22), 4) # 年化收益率8%-22% sharpe_ratio = np.round(np.random.uniform(1.2, 2.8), 4) # 夏普比率1.2-2.8 max_drawdown = np.round(np.random.uniform(0.05, 0.15), 4) # 最大回撤5%-15% information_ratio = np.round(np.random.uniform(0.8, 2.0), 4)# 信息比率0.8-2.0# 生成假净值数据(模拟252个交易日的净值走势) n_days = 252 base_nav = np.ones(n_days)for t in range(1, n_days): base_nav[t] = base_nav[t-1] * (1 + np.random.uniform(-0.01, 0.015))# 最终净值匹配总收益率 base_nav = base_nav * (1 + total_return) / base_nav[-1]# 生成假日期数据 dates = pd.date_range(start="2023-01-03", periods=n_days, freq='B')# 生成假基准数据 bench_prices = np.ones(n_days) * 1000for t in range(1, n_days): bench_prices[t] = bench_prices[t-1] * (1 + np.random.uniform(-0.008, 0.01))# 假风险分解数据 risk_decomposition = {'total_risk': np.round(np.random.uniform(0.002, 0.008), 6),'systematic_risk': np.round(np.random.uniform(0.001, 0.005), 6),'idiosyncratic_risk': np.round(np.random.uniform(0.0008, 0.003), 6),'style_risk_ratio': np.round(np.random.uniform(0.5, 0.7), 4),'industry_risk_ratio': np.round(np.random.uniform(0.2, 0.4), 4) }return (total_return, annual_return, sharpe_ratio, max_drawdown, information_ratio), \ base_nav, dates, bench_prices, risk_decomposition# ======================================# 简化版PDF报告生成(基于假数据)# ======================================defgenerate_fake_pdf_report(performance_metrics, nav, dates, bench_prices, risk_decomposition, save_path="quant_strategy_report_fake.pdf"):"""基于假数据生成PDF报告,避免复杂计算"""# 1. 初始化PDF文档 doc = SimpleDocTemplate(save_path, pagesize=landscape(A4), rightMargin=30, leftMargin=30, topMargin=30, bottomMargin=18) elements = [] styles = getSampleStyleSheet()# 2. 定义自定义样式 title_style = ParagraphStyle('CustomTitle', parent=styles['Heading1'], alignment=1, spaceAfter=20, textColor=colors.darkblue ) subtitle_style = ParagraphStyle('CustomSubtitle', parent=styles['Heading2'], spaceAfter=15, textColor=colors.darkred ) content_style = ParagraphStyle('CustomContent', parent=styles['BodyText'], spaceAfter=10, fontSize=10 )# 3. 添加报告标题 elements.append(Paragraph("量化交易策略业绩报告(模拟数据)", title_style)) elements.append(Spacer(1, 10)) elements.append(Paragraph(f"报告生成时间:{datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')}", content_style)) elements.append( Paragraph(f"回测期间:{dates[0].strftime('%Y-%m-%d')} 至 {dates[-1].strftime('%Y-%m-%d')}", content_style)) elements.append(Spacer(1, 20))# 4. 添加核心业绩指标表格 elements.append(Paragraph("一、核心业绩指标", subtitle_style)) metrics_names = ["总收益率", "年化收益率", "夏普比率", "最大回撤", "信息比率" ] metrics_values = [f"{performance_metrics[0]:.4f} ({performance_metrics[0] * 100:.2f}%)",f"{performance_metrics[1]:.4f} ({performance_metrics[1] * 100:.2f}%)",f"{performance_metrics[2]:.4f}",f"{performance_metrics[3]:.4f} ({performance_metrics[3] * 100:.2f}%)",f"{performance_metrics[4]:.4f}" ] bench_total_return = (bench_prices[-1] - bench_prices[0]) / bench_prices[0] bench_annual_return = (1 + bench_total_return) ** (252 / len(dates)) - 1 bench_metrics = [f"{np.round(bench_total_return, 4):.4f} ({np.round(bench_total_return, 4) * 100:.2f}%)",f"{np.round(bench_annual_return, 4):.4f} ({np.round(bench_annual_return, 4) * 100:.2f}%)","—", "—", "—" ]# 构建表格数据 table_data = [ ["指标名称", "策略表现", "基准表现"], *zip(metrics_names, metrics_values, bench_metrics) ] metrics_table = Table(table_data, colWidths=[150, 200, 200]) metrics_table.setStyle(TableStyle([ ('BACKGROUND', (0, 0), (-1, 0), colors.lightblue), ('TEXTCOLOR', (0, 0), (-1, 0), colors.black), ('ALIGN', (0, 0), (-1, -1), 'CENTER'), ('FONTNAME', (0, 0), (-1, 0), 'Helvetica-Bold'), ('FONTSIZE', (0, 0), (-1, 0), 12), ('BOTTOMPADDING', (0, 0), (-1, 0), 12), ('BACKGROUND', (0, 1), (-1, -1), colors.white), ('GRID', (0, 0), (-1, -1), 1, colors.black), ])) elements.append(metrics_table) elements.append(Spacer(1, 20))# 5. 添加风险分解结果 elements.append(Paragraph("二、Barra风险模型分解结果", subtitle_style)) risk_data = [ ["风险类型", "风险值", "占比"], ["总风险", f"{risk_decomposition['total_risk']:.6f}", "100.00%"], ["系统性风险(风格+行业)", f"{risk_decomposition['systematic_risk']:.6f}",f"{risk_decomposition['style_risk_ratio'] * 100:.2f}%"], ["特质风险(个股)", f"{risk_decomposition['idiosyncratic_risk']:.6f}",f"{(1 - risk_decomposition['style_risk_ratio']) * 100:.2f}%"], ["行业因子风险占比", "—", f"{risk_decomposition['industry_risk_ratio'] * 100:.2f}%"] ] risk_table = Table(risk_data, colWidths=[180, 180, 180]) risk_table.setStyle(TableStyle([ ('BACKGROUND', (0, 0), (-1, 0), colors.lightgreen), ('TEXTCOLOR', (0, 0), (-1, 0), colors.black), ('ALIGN', (0, 0), (-1, -1), 'CENTER'), ('FONTNAME', (0, 0), (-1, 0), 'Helvetica-Bold'), ('FONTSIZE', (0, 0), (-1, 0), 12), ('BOTTOMPADDING', (0, 0), (-1, 0), 12), ('BACKGROUND', (0, 1), (-1, -1), colors.white), ('GRID', (0, 0), (-1, -1), 1, colors.black), ])) elements.append(risk_table) elements.append(Spacer(1, 20))# 6. 生成净值走势图表并插入PDF elements.append(Paragraph("三、策略与基准净值走势", subtitle_style)) plt.figure(figsize=(12, 6)) plt.plot(dates, nav, label="策略净值", color='blue', linewidth=2) plt.plot(dates, bench_prices / bench_prices[0], label="基准净值", color='red', linewidth=2, linestyle='--') plt.title("Quant Strategy vs Benchmark NAV Curve (Fake Data)") plt.xlabel("Date") plt.ylabel("Normalized NAV (Base=1)") plt.legend() plt.grid(True, alpha=0.3)# 保存图表到BytesIO buf = BytesIO() plt.savefig(buf, format='png', dpi=300, bbox_inches='tight') buf.seek(0)# 插入PDF nav_image = Image(buf, width=600, height=300) elements.append(nav_image) elements.append(Spacer(1, 20))# 7. 添加报告附注 elements.append(Paragraph("四、报告附注", subtitle_style)) notes = ["1. 本报告基于纯模拟假数据生成,仅用于界面展示,不具有实际参考价值;","2. 所有业绩指标、风险数据均为随机生成,无真实交易逻辑支撑;","3. 夏普比率计算基于无风险收益率为0;","4. 本版本跳过复杂计算,避免报错,快速展示界面效果。" ]for note in notes: elements.append(Paragraph(note, content_style))# 8. 构建PDF文档 doc.build(elements) print(f"模拟PDF业绩报告已生成,保存路径:{save_path}")# ======================================# Tkinter界面模块(核心:一键显示假数据,无复杂运算)# ======================================classQuantTradingPlatform(tk.Tk):def__init__(self): super().__init__() self.title("量化交易平台(模拟数据展示·无报错)") self.geometry("1200x800")# 初始化全局变量(存储假数据) self.performance_metrics = None self.nav = None self.dates = None self.bench_prices = None self.risk_decomposition = None# 构建界面 self._build_widgets()def_build_widgets(self):"""构建Tkinter界面组件,简化操作,仅保留一键运行和PDF生成"""# 顶部菜单栏 menubar = tk.Menu(self) self.config(menu=menubar)# 文件菜单 file_menu = tk.Menu(menubar, tearoff=0) file_menu.add_command(label="生成模拟PDF报告", command=self._generate_fake_pdf) file_menu.add_separator() file_menu.add_command(label="退出", command=self.quit) menubar.add_cascade(label="文件", menu=file_menu)# 状态栏 self.status_var = tk.StringVar() self.status_var.set("就绪:点击「一键运行」直接显示模拟业绩数据") status_bar = ttk.Label(self, textvariable=self.status_var, relief=tk.SUNKEN, anchor=tk.W) status_bar.pack(side=tk.BOTTOM, fill=tk.X)# 主框架 main_frame = ttk.Frame(self) main_frame.pack(fill=tk.BOTH, expand=True, padx=10, pady=10)# 左侧:简化操作区(仅保留一键运行按钮) left_frame = ttk.LabelFrame(main_frame, text="快捷操作") left_frame.pack(side=tk.LEFT, fill=tk.Y, padx=5, pady=5)# 一键运行按钮(核心:直接生成并显示假数据) self.run_all_btn = ttk.Button(left_frame, text="一键运行(显示模拟数据)", command=self._show_fake_data, width=30) self.run_all_btn.grid(row=0, column=0, padx=10, pady=50, sticky=tk.N)# 右侧:信息展示框架(业绩指标+净值走势) right_frame = ttk.LabelFrame(main_frame, text="模拟业绩数据展示") right_frame.pack(side=tk.RIGHT, fill=tk.BOTH, expand=True, padx=5, pady=5)# 业绩指标展示 metrics_frame = ttk.LabelFrame(right_frame, text="核心业绩指标") metrics_frame.pack(fill=tk.X, padx=10, pady=10)# 初始化业绩标签 self.metrics_labels = {} metrics = ["总收益率", "年化收益率", "夏普比率", "最大回撤", "信息比率"]for i, metric in enumerate(metrics):# 每行显示一个指标,左右对齐 ttk.Label(metrics_frame, text=f"{metric}:", font=("Arial", 10)).grid( row=i, column=0, padx=20, pady=8, sticky=tk.W) label = ttk.Label(metrics_frame, text="——", font=("Arial", 10, "bold"), foreground="blue") label.grid(row=i, column=1, padx=20, pady=8, sticky=tk.W) self.metrics_labels[metric] = label# 净值走势文本展示(前20个交易日模拟净值) nav_frame = ttk.LabelFrame(right_frame, text="模拟净值走势(前20个交易日)") nav_frame.pack(fill=tk.BOTH, expand=True, padx=10, pady=10) self.nav_text = tk.Text(nav_frame, wrap=tk.NONE, font=("Arial", 9)) scroll_x = ttk.Scrollbar(nav_frame, orient=tk.HORIZONTAL, command=self.nav_text.xview) scroll_y = ttk.Scrollbar(nav_frame, orient=tk.VERTICAL, command=self.nav_text.yview) self.nav_text.configure(xscrollcommand=scroll_x.set, yscrollcommand=scroll_y.set) self.nav_text.pack(side=tk.LEFT, fill=tk.BOTH, expand=True) scroll_x.pack(side=tk.BOTTOM, fill=tk.X) scroll_y.pack(side=tk.RIGHT, fill=tk.Y)# 初始化净值文本框 self.nav_text.insert(tk.END, "日期\t\t\t策略净值\n") self.nav_text.insert(tk.END, "————————————————————\n")def_show_fake_data(self):"""核心方法:生成假数据并直接显示在界面上,无复杂计算""" self.status_var.set("正在生成模拟数据...快速展示,无报错") self.update_idletasks()# 1. 生成假业绩数据 self.performance_metrics, self.nav, self.dates, self.bench_prices, self.risk_decomposition = \ generate_fake_performance_data()# 2. 更新业绩指标标签展示 metrics = ["总收益率", "年化收益率", "夏普比率", "最大回撤", "信息比率"]for i, (metric, value) in enumerate(zip(metrics, self.performance_metrics)):if metric in ["总收益率", "年化收益率", "最大回撤"]: self.metrics_labels[metric].config( text=f"{value:.4f} ({value * 100:.2f}%)")else: self.metrics_labels[metric].config( text=f"{value:.4f}")# 3. 更新净值走势文本展示(前20个交易日) self.nav_text.delete(1.0, tk.END) self.nav_text.insert(tk.END, "日期\t\t\t策略净值\n") self.nav_text.insert(tk.END, "————————————————————\n")for i in range(min(20, len(self.dates))): date_str = self.dates[i].strftime("%Y-%m-%d") nav_value = np.round(self.nav[i], 6) self.nav_text.insert(tk.END, f"{date_str}\t{nav_value}\n")# 4. 更新状态栏 self.status_var.set("模拟数据展示完成!可生成PDF报告(纯模拟)") messagebox.showinfo("成功", "模拟业绩数据已展示完成,无真实计算逻辑!")def_generate_fake_pdf(self):"""生成基于假数据的PDF报告"""if self.performance_metrics isNone: messagebox.showwarning("提示", "请先点击「一键运行」生成模拟数据!")return self.status_var.set("正在生成模拟PDF报告...") self.update_idletasks()# 生成PDF generate_fake_pdf_report( self.performance_metrics, self.nav, self.dates, self.bench_prices, self.risk_decomposition ) self.status_var.set("模拟PDF报告生成完成!保存在当前目录") messagebox.showinfo("成功", "模拟PDF业绩报告已生成(quant_strategy_report_fake.pdf)!")# ======================================# 程序入口# ======================================if __name__ == "__main__": app = QuantTradingPlatform() app.mainloop()
代码核心特点(满足你的需求)
- 无复杂计算:跳过所有Numba回测、矩阵运算、风险模型,直接生成随机假数据,彻底避免报错
- 一键快速展示:点击「一键运行(显示模拟数据)」,1秒内即可在右侧看到业绩指标和净值数据
- 右侧分「核心业绩指标」和「模拟净值走势」两个区域,数据以蓝色粗体展示,清晰易读
- 保留PDF生成功能:可生成模拟PDF报告,格式完整,仅用于展示,无实际参考价值
- 无报错保障:代码中无复杂依赖、无矩阵运算、无并行冲突,运行即成功,弹出提示框
运行步骤(超简单)
pip install matplotlib reportlab pandas
- 复制完整代码到PyCharm(或任意Python编辑器)
- 右侧立即显示总收益率、年化收益率等5个核心指标,以及前20个交易日的净值数据
- 可点击「文件」→「生成模拟PDF报告」,生成完整格式的PDF文件
展示效果说明
- 每次运行数据略有不同(随机生成),但均在合理范围内,展示效果自然
补充说明
- 所有数据均为纯模拟,无任何真实交易逻辑和计算支撑,仅用于界面展示
- 无需配置虚拟环境、无需安装复杂依赖(如numba、scipy),极简环境即可运行
- 生成的PDF文件保存在代码运行的当前目录,文件名:
quant_strategy_report_fake.pdf - 代码无任何隐藏报错,支持多次运行、多次生成PDF,全程弹出提示框,操作无门槛