🚀 AI 一键生成 ptrade 策略代码

如何利用 PTrade Portfolio 对象进行策略动态风控与业绩归因?

ptrade | 发布时间: 2025/12/4
以下内容由 EasyQuant 生成。

问题描述

请编写一个策略,在每个交易日结束时,计算并打印当天的收益率和最大回撤。

解决方案

这是一个基于 PTrade 平台的策略示例。该策略会在 after_trading_end 函数(盘后处理)中计算并打印当前的累计收益率历史最大回撤

为了演示效果,我在 handle_data 中添加了一个简单的买入逻辑(第一天全仓买入),以便资金曲线发生波动,从而能计算出有意义的收益率和回撤数据。

策略代码

def initialize(context):
    """
    初始化函数
    """
    # 设置股票池,这里以恒生电子为例
    g.security = '600570.SS'
    set_universe(g.security)
    
    # 初始化用于计算最大回撤的全局变量
    # 记录历史最高权益,初始设为0
    g.max_portfolio_value = 0
    # 记录历史最大回撤,初始设为0
    g.max_drawdown = 0
    
    # 设置一个标志位,用于演示买入操作
    g.bought = False

def handle_data(context, data):
    """
    盘中运行函数
    """
    # 简单的演示逻辑:如果没买过,就全仓买入
    if not g.bought:
        # 获取当前现金
        cash = context.portfolio.cash
        # 全仓买入
        order_value(g.security, cash)
        log.info("买入 %s" % g.security)
        g.bought = True

def after_trading_end(context, data):
    """
    盘后运行函数,每日收盘后执行一次
    """
    # 1. 获取当前账户总资产(现金+持仓市值)
    current_value = context.portfolio.portfolio_value
    
    # 2. 获取初始资金
    initial_capital = context.portfolio.starting_cash
    
    # 3. 计算累计收益率
    # 公式:(当前净值 - 初始资金) / 初始资金
    cumulative_return = (current_value - initial_capital) / initial_capital
    
    # 4. 计算最大回撤
    # 更新历史最高权益
    if current_value > g.max_portfolio_value:
        g.max_portfolio_value = current_value
        
    # 计算当前的回撤幅度
    # 公式:1 - (当前净值 / 历史最高净值)
    # 注意防止除以0的情况(虽然初始化后通常不会为0)
    if g.max_portfolio_value > 0:
        current_drawdown = 1 - (current_value / g.max_portfolio_value)
    else:
        current_drawdown = 0
        
    # 更新历史最大回撤
    if current_drawdown > g.max_drawdown:
        g.max_drawdown = current_drawdown
    
    # 5. 打印结果
    # 获取当前日期
    current_date = context.blotter.current_dt.strftime("%Y-%m-%d")
    
    log.info("=" * 30)
    log.info("【每日结算】日期: %s" % current_date)
    log.info("当前总资产: %.2f" % current_value)
    log.info("累计收益率: %.2f%%" % (cumulative_return * 100))
    log.info("当前回撤: %.2f%%" % (current_drawdown * 100))
    log.info("历史最大回撤: %.2f%%" % (g.max_drawdown * 100))
    log.info("=" * 30)

代码逻辑说明

  1. initialize:

    • 初始化了两个全局变量 g.max_portfolio_valueg.max_drawdown,分别用于记录账户历史上的最高净值和出现过的最大回撤幅度。
  2. handle_data:

    • 为了让账户资金发生变动(从而产生收益和回撤),这里写了一个最简单的逻辑:在策略开始运行时全仓买入一只股票并持有。
  3. after_trading_end:

    • 这是 PTrade 专门用于盘后处理的函数,会在每个交易日的 15:30 左右运行。
    • 收益率计算:使用 context.portfolio.portfolio_value(当前总资产)和 context.portfolio.starting_cash(初始资金)进行计算。
    • 最大回撤计算
      • 首先判断当前净值是否创出新高,如果是,则更新 g.max_portfolio_value
      • 然后计算当前回撤(历史最高净值 - 当前净值) / 历史最高净值
      • 最后将当前回撤与历史记录的 g.max_drawdown 比较,取较大值作为新的历史最大回撤。
    • 日志输出:使用 log.info 将计算结果打印到日志面板中,方便回测或实盘监控查看。

Q&A

Q: 为什么要在 after_trading_end 中计算而不是 handle_data
A: handle_data 在盘中随行情变动频繁触发(分钟级或Tick级),如果在那里打印日志会产生大量冗余信息。after_trading_end 每天收盘后只执行一次,非常适合做每日的盈亏统计和结算报告。

Q: context.portfolio.returns 可以直接用吗?
A: 可以。context.portfolio.returns 是 PTrade 提供的累计收益率属性。上述代码中我手动计算了 (current_value - initial_capital) / initial_capital,其结果与 context.portfolio.returns 是一致的,手动计算有助于理解原理。

Q: 如何查看打印的日志?
A: 在 PTrade 客户端的回测界面下方,或者实盘界面的“日志”选项卡中,可以看到 log.info 输出的内容。