🚀 AI 一键生成 ptrade 策略代码

编写通用 PTrade 策略:如何使用 get_business_type 区分股票、期货与两融环境?

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

问题描述

如何让我的策略在股票账户和期货账户下都能运行,并执行不同的下单逻辑?

解决方案

要在PTrade中实现同一套策略代码在不同账户类型(股票或期货)下自动切换交易逻辑,核心在于使用 get_business_type() 接口。

该接口会返回当前策略运行环境的业务类型(如 'stock' 代表股票,'future' 代表期货)。你可以根据返回值的不同,在 handle_data 中编写分支逻辑,分别调用股票的 order 系列函数或期货的 buy_open/sell_close 系列函数。

以下是具体的实现方案和代码示例。

核心思路

  1. 获取业务类型:在 before_trading_startinitialize 中调用 get_business_type() 并存储到全局变量 g 中。
  2. 设置标的池:根据业务类型,设置对应的股票代码或期货合约代码为标的池 (set_universe)。
  3. 分支交易逻辑:在 handle_data 中使用 if-elif 判断业务类型,执行完全隔离的下单逻辑。

策略代码示例

def initialize(context):
    # 定义我们要操作的标的
    g.stock_security = '600570.SS'      # 股票标的:恒生电子
    g.future_security = 'IF2309.CCFX'   # 期货标的:股指期货(示例代码,实盘请换主力合约)
    
    # 初始化业务类型变量
    g.biz_type = None

def before_trading_start(context, data):
    # 获取当前策略运行的业务类型
    # 返回值可能是: 'stock'(股票), 'future'(期货), 'rzrq'(两融) 等
    g.biz_type = get_business_type()
    
    log.info("当前策略运行环境为: %s" % g.biz_type)
    
    # 根据业务类型设置不同的股票池
    if g.biz_type == 'stock':
        set_universe(g.stock_security)
        log.info("已设置股票池: %s" % g.stock_security)
        
    elif g.biz_type == 'future':
        set_universe(g.future_security)
        log.info("已设置期货合约: %s" % g.future_security)
        
    else:
        log.warn("未知的业务类型,未设置标的池")

def handle_data(context, data):
    # ---------------------------------------------------
    # 场景一:股票账户逻辑
    # ---------------------------------------------------
    if g.biz_type == 'stock':
        security = g.stock_security
        # 简单的股票逻辑:如果当前没有持仓,则买入100股
        position = get_position(security)
        
        if position.amount == 0:
            log.info("【股票账户】触发买入逻辑")
            # 股票下单使用 order / order_target / order_value 等接口
            order(security, 100)
            
    # ---------------------------------------------------
    # 场景二:期货账户逻辑
    # ---------------------------------------------------
    elif g.biz_type == 'future':
        security = g.future_security
        # 简单的期货逻辑:如果当前没有多头持仓,则开多1手
        position = get_position(security)
        
        # 期货持仓字段与股票不同,有多头(long_amount)和空头(short_amount)之分
        if position.long_amount == 0:
            log.info("【期货账户】触发开多逻辑")
            # 期货下单使用 buy_open / sell_close / sell_open / buy_close 接口
            # 注意:期货通常需要按“手”交易
            buy_open(security, 1)
            
    # ---------------------------------------------------
    # 其他场景
    # ---------------------------------------------------
    else:
        log.info("当前业务类型暂无交易逻辑")

关键点解析

  1. get_business_type()

    • 这是区分环境的唯一标准。
    • 返回 'stock':对应普通股票账户。
    • 返回 'future':对应期货账户。
    • 返回 'rzrq':对应信用(融资融券)账户。
  2. 下单接口的区别

    • 股票:必须使用 order(code, amount)order_target 等函数。买入 amount 为正,卖出为负。
    • 期货:必须使用 buy_open (买开), sell_close (卖平), sell_open (卖开), buy_close (买平)。参数 amount 必须为正数。
  3. 持仓对象的区别 (get_position)

    • 股票:主要关注 position.amount (总持仓) 和 position.enable_amount (可用持仓)。
    • 期货:必须区分方向,关注 position.long_amount (多头持仓) 和 position.short_amount (空头持仓)。
  4. 兼容性建议

    • 虽然代码可以在一个文件中写完,但建议在回测时分别建立两个回测任务(一个选股票账户,一个选期货账户)来验证逻辑,因为PTrade的回测环境通常不支持单次回测同时模拟股票和期货的混合资金池(除非是多账户模式,但通常策略逻辑是隔离的)。

Q&A

Q: get_business_type() 可以在 initialize 中调用吗?
A: 可以。但在 before_trading_start 中调用通常更稳妥,因为它确保了每天交易开始前都会确认一次环境状态,且此时上下文数据加载更为完全。

Q: 如果我在股票账户里误用了 buy_open 会怎样?
A: 策略会报错或下单失败。PTrade 的交易网关会拦截不符合当前账户权限的指令。因此使用 if g.biz_type == ... 进行逻辑隔离是非常必要的。

Q: 如何在回测中模拟这种情况?
A: 你需要创建两个回测任务。

  1. 第一个回测任务:选择“股票”品种,设置初始资金,运行该策略。此时 g.biz_type'stock',执行股票逻辑。
  2. 第二个回测任务:选择“期货”品种,设置初始资金,运行同一份策略代码。此时 g.biz_type'future',执行期货逻辑。

Q: 这种写法支持融资融券账户吗?
A: 支持。你可以添加 elif g.biz_type == 'rzrq': 分支,并在其中使用 margincash_open (融资买入) 或 marginsec_open (融券卖出) 等两融专用接口。