🚀 AI 一键生成 ptrade 策略代码

ptrade回测结束后如何一次性保存回测结果?

ptrade | 发布时间: 2026/5/21
以下内容由 EasyQuant 生成。

问题描述

ptrade回测结束后执行某个函数,比如保存回测结果

http://ptradeapi.com/#after_trading_end
官方文档只提供一个每天盘后执行的函数,没有函数可以在回测结束后,固定执行某些操作。

比如我回测过程保存的历史交易记录,收益率等,要如何保存? 虽然可以在回测的时候,每个交易日保存一次。
但是这样就需要在回测的时候按照天打开文件,盘后写入一次。 使用一个全局对象操作,显得很啰嗦。

那么有没有办法可以做在回测结束后一次性 保存操作呢?

解决方案

在 ptrade 量化平台中,确实没有提供类似 on_backtest_end 这样在整个回测结束后只执行一次的原生回调函数。所有的盘后逻辑都只能在 after_trading_end(每日盘后)中处理。

虽然每天打开文件写入看起来有些“啰嗦”,但在量化回测中,每天覆盖保存(持久化)其实是官方推荐的最佳实践,因为它可以防止回测意外中断导致的数据全部丢失。不过,如果你坚持想要实现“只在回测最后一天一次性保存”或者寻找更简便的方法,可以通过以下三种替代方案来实现:

方案一:手动指定结束日期进行判断(一次性保存)

既然无法直接获取回测引擎的结束状态,你可以在 initialize 中定义一个与你回测设置界面相同的结束日期。然后在 after_trading_end 中判断当前日期是否等于结束日期,如果是,则执行一次性保存。

import pandas as pd

def initialize(context):
    set_universe('600570.SS')
    # 1. 手动设置与回测界面一致的结束日期
    g.end_date = '2023-12-31'
    # 2. 初始化用于存储结果的全局列表
    g.daily_returns = []

def handle_data(context, data):
    pass

def after_trading_end(context, data):
    current_date = context.blotter.current_dt.strftime('%Y-%m-%d')
    
    # 收集每天的收益率等数据
    g.daily_returns.append({
        'date': current_date,
        'returns': context.portfolio.returns,
        'portfolio_value': context.portfolio.portfolio_value
    })
    
    # 判断当前日期是否是回测的最后一天
    if current_date == g.end_date:
        save_final_results()

def save_final_results():
    # 在这里执行一次性保存操作,例如保存为 CSV
    df = pd.DataFrame(g.daily_returns)
    save_path = get_research_path() + 'my_backtest_results.csv'
    df.to_csv(save_path, index=False)
    log.info(f"回测结束,结果已一次性保存至:{save_path}")

方案二:每天覆盖写入(推荐,代码其实很精简)

如果你觉得每天追加写入文件很啰嗦,可以把所有数据存在全局变量 g 中,每天盘后直接覆盖写入整个对象。使用 pickle 模块,代码只需要两行,并不啰嗦,而且非常安全。

import pickle

def initialize(context):
    set_universe('600570.SS')
    g.daily_returns = []

def after_trading_end(context, data):
    # 收集数据
    g.daily_returns.append(context.portfolio.returns)
    
    # 每天覆盖保存,代码非常简洁
    save_path = get_research_path() + 'backtest_results.pkl'
    with open(save_path, 'wb') as f:
        pickle.dump(g.daily_returns, f, -1)

方案三:使用官方接口直接导出交易记录

如果你想保存的主要是历史交易记录(订单编号、成交价、手续费等),完全不需要自己去写逻辑收集。ptrade 官方提供了一个专门用于回测的接口 get_trades_file(),它可以直接生成对账数据文件。

你只需要在 after_trading_end 中调用它即可(它会自动覆盖更新,最终你得到的就是完整的回测交易记录)。

def initialize(context):
    set_universe('600570.SS')

def handle_data(context, data):
    order('600570.SS', 100)

def after_trading_end(context, data):
    # 获取对账数据,存放到 notebook 下的指定目录
    # 最终回测结束后,你去研究目录下找这个 CSV 文件即可
    user_data_path = get_trades_file('user_data/trades_record.csv')

总结

  • 如果你想保存自定义的复杂指标(如每日收益率、特定因子值),建议使用方案二(每天 pickle 覆盖保存)或方案一(指定结束日期一次性保存)。
  • 如果你只是想保存交易流水/交割单,直接使用方案三get_trades_file() 是最优雅的做法。