问题描述
解决方案
在聚宽(JoinQuant)平台上,将回测的详细数据导出进行进一步分析和画图,主要有两种最常用的方法:
- 方法一(推荐):在“研究环境”中使用
get_backtestAPI 获取已完成回测的详细数据。 这是最灵活、最强大的方式,可以直接将回测结果转换为 Pandas DataFrame 进行分析。 - 方法二:在“策略代码”中使用
write_file将数据保存为文件。 这种方式适合在回测过程中实时记录自定义数据,或者在回测结束时导出特定格式的文件(如 CSV)。
以下是详细的操作步骤和代码示例。
方法一:在研究环境(Notebook)中获取回测数据
这是最标准的方法。你不需要修改策略代码,只需在回测完成后,复制回测 ID,然后在研究环境中提取数据。
1. 获取回测 ID
在回测详情页面的 URL 中找到 backtestId 参数。
例如:https://www.joinquant.com/algorithm/backtest/detail?backtestId=1234567890
这里的 1234567890 就是回测 ID。
2. 编写研究环境代码
在聚宽的“我的研究”中新建一个 Notebook,输入以下代码:
# 导入必要的库
from jqdata import *
import pandas as pd
# 1. 获取回测对象 (替换为你自己的回测ID)
backtest_id = '你的回测ID'
gt = get_backtest(backtest_id)
# --- 获取交易记录 (Orders) ---
orders_list = gt.get_orders()
if orders_list:
df_orders = pd.DataFrame(orders_list)
# 转换时间格式方便分析
df_orders['time'] = pd.to_datetime(df_orders['time'])
print("交易记录示例:")
print(df_orders.head())
# 导出为 CSV
# df_orders.to_csv('backtest_orders.csv', encoding='utf-8-sig')
# --- 获取每日持仓详情 (Positions) ---
positions_list = gt.get_positions()
if positions_list:
df_positions = pd.DataFrame(positions_list)
df_positions['time'] = pd.to_datetime(df_positions['time'])
print("\n持仓记录示例:")
print(df_positions.head())
# 导出为 CSV
# df_positions.to_csv('backtest_positions.csv', encoding='utf-8-sig')
# --- 获取每日收益曲线 (Results) ---
results_list = gt.get_results()
if results_list:
df_results = pd.DataFrame(results_list)
df_results['time'] = pd.to_datetime(df_results['time'])
print("\n收益曲线示例:")
print(df_results.head())
# --- 获取自定义记录 (Records) ---
# 如果你在策略中使用了 record() 函数,可以通过此方法获取
records_list = gt.get_records()
if records_list:
df_records = pd.DataFrame(records_list)
print("\n自定义Record数据示例:")
print(df_records.head())
数据说明:
get_orders(): 包含成交时间、标的、买卖方向、成交价、数量、手续费等。get_positions(): 包含每日持仓的标的、数量、成本、市值、当日收益等。get_results(): 包含每日的策略收益、基准收益等。
方法二:在策略代码中直接导出文件
如果你希望在回测结束时自动生成一份 CSV 文件保存到研究目录,可以在策略代码中使用 write_file。
代码实现
在你的策略代码末尾添加 on_strategy_end 函数(或者在 after_trading_end 中处理):
# -*- coding: utf-8 -*-
import pandas as pd
def initialize(context):
# 你的初始化代码
g.security = '000001.XSHE'
run_daily(market_open, time='every_bar')
def market_open(context):
# 你的交易逻辑
order(g.security, 100)
# 策略运行结束时调用
def on_strategy_end(context):
# 获取所有成交记录
trades = get_trades()
# 将数据转换为列表字典格式
data_list = []
for trade_id, trade in trades.items():
data_list.append({
'trade_id': trade.trade_id,
'time': trade.time,
'security': trade.security,
'amount': trade.amount,
'price': trade.price,
'order_id': trade.order_id
})
# 转换为 DataFrame
if len(data_list) > 0:
df = pd.DataFrame(data_list)
# 将数据写入研究目录下的文件
# 注意:write_file 第一个参数是文件名,第二个参数是文件内容(字符串或二进制)
# to_csv 返回的是字符串
write_file('my_backtest_trades.csv', df.to_csv(index=False), append=False)
log.info("交易记录已导出到研究目录:my_backtest_trades.csv")
else:
log.info("无交易记录,未导出文件。")
查看文件:
回测结束后,前往聚宽导航栏的“我的研究”,你会在根目录下看到生成的 my_backtest_trades.csv 文件,可以直接下载或在 Notebook 中读取分析。
总结与建议
| 需求场景 | 推荐方法 | 优势 |
|---|---|---|
| 回测已经跑完了,想分析数据 | 方法一 (get_backtest) | 无需重跑回测,数据最全,直接在 Notebook 分析画图。 |
| 想把数据下载到本地电脑 | 方法一 + 导出 | 在 Notebook 生成 DataFrame 后,使用 df.to_csv 保存,然后从网页下载。 |
| 需要记录策略内部的中间变量 | 方法二 (write_file) | 可以记录 g 变量中的特殊状态,或者 record() 无法满足的复杂数据。 |
Q&A
Q: get_backtest 可以在策略回测代码中使用吗?
A: 不可以。get_backtest 是研究环境(Notebook)专用的 API,用于获取已完成的回测信息。在策略运行过程中(回测/模拟),你应该使用 context.portfolio 获取当前账户信息,或使用 get_trades() / get_orders() 获取当天的交易信息。
Q: 导出的 CSV 文件中文乱码怎么办?
A: 在使用 to_csv 时,建议指定编码格式。例如:df.to_csv('filename.csv', encoding='utf-8-sig')。utf-8-sig 可以让 Excel 正确识别 UTF-8 编码的中文。
Q: 如何画出收益曲线图?
A: 在研究环境获取到 df_results 后,可以直接使用 pandas 的绘图功能:
# 假设 df_results 已经通过 get_results() 获取并转换
import matplotlib.pyplot as plt
df_results.set_index('time', inplace=True)
# 绘制策略收益和基准收益
df_results[['returns', 'benchmark_returns']].plot(figsize=(14, 7))
plt.show()
Q: write_file 保存的文件在哪里?
A: 保存的文件位于你的“我的研究”根目录下。你可以登录聚宽官网,点击顶部导航栏的“我的研究”查看和下载。