🚀 AI 一键生成 ptrade 策略代码

PTrade 量化实战:BBI 多空指数指标计算与策略编写

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

问题描述

如何编写一个 BBI 多空指数策略?

解决方案

BBI 多空指数策略设计与实现

BBI(Bull And Bear Index)多空指数是一种将不同周期的移动平均线加权平均之后的综合指标。它结合了短期(3日、6日)和长期(12日、24日)移动平均线的优势,用于判断市场的多空趋势。

策略逻辑

  1. 指标计算
    BBI = (MA(3) + MA(6) + MA(12) + MA(24)) / 4
    其中 MA(N) 代表最近 N 日的收盘价算术平均值。

  2. 交易信号

    • 买入信号:当股价(收盘价)上穿 BBI 指标线时,视为多头市场,执行买入。
    • 卖出信号:当股价(收盘价)下穿 BBI 指标线时,视为空头市场,执行卖出。
  3. 资金管理

    • 买入时使用当前所有可用现金。
    • 卖出时清空该标的所有持仓。

PTrade 策略代码实现

以下是基于 PTrade 框架的完整策略代码。代码兼容 Python 3.5 语法,可以直接在 PTrade 回测或交易环境中运行。

import numpy as np
import pandas as pd

def initialize(context):
    """
    初始化函数,设置股票池、基准和全局变量
    """
    # 设定要交易的股票,这里以 600570.SS (恒生电子) 为例
    # 实际使用时可修改为其他股票或通过 get_index_stocks 获取股票池
    g.security = '600570.SS'
    set_universe(g.security)
    
    # 设置基准为沪深300
    set_benchmark('000300.SS')
    
    # 设置佣金费率(可选,回测常用设置)
    set_commission(commission_ratio=0.0003, min_commission=5.0)
    
    # 设定 BBI 计算所需的周期参数
    g.ma_periods = [3, 6, 12, 24]
    
    # 打印策略启动日志
    log.info("BBI 策略初始化完成")

def handle_data(context, data):
    """
    核心策略逻辑,每个运行周期(日线或分钟)执行一次
    """
    security = g.security
    
    # 1. 获取历史数据
    # BBI 最大周期为 24,我们需要获取足够的数据来计算 MA24
    # 为了保险起见,获取过去 30 天的数据,避免停牌导致数据不足
    # include=False 表示不包含当前周期(即只取历史收盘价),避免未来函数
    history_count = 30
    h_data = get_history(history_count, frequency='1d', field='close', security_list=security, include=False)
    
    # 检查数据长度是否足够,如果不足 24 天无法计算 BBI,直接返回
    if len(h_data) < 24:
        log.warning("历史数据不足,跳过本次计算")
        return
    
    # 提取收盘价序列 (Series)
    close_prices = h_data['close']
    
    # 2. 计算 BBI 指标
    # 分别计算 3日, 6日, 12日, 24日 均线
    # 使用 iloc[-N:] 获取最后 N 个数据,然后求 mean()
    ma3 = close_prices.iloc[-g.ma_periods[0]:].mean()
    ma6 = close_prices.iloc[-g.ma_periods[1]:].mean()
    ma12 = close_prices.iloc[-g.ma_periods[2]:].mean()
    ma24 = close_prices.iloc[-g.ma_periods[3]:].mean()
    
    # 计算 BBI 值
    bbi = (ma3 + ma6 + ma12 + ma24) / 4.0
    
    # 3. 获取当前市场数据
    # 获取当前最新价格
    current_price = data[security]['close']
    
    # 获取当前持仓数量
    position = get_position(security).amount
    # 获取当前可用现金
    cash = context.portfolio.cash
    
    # 4. 生成交易信号并执行
    # 信号逻辑:
    # 如果 当前价格 > BBI 且 空仓 -> 买入 (多头趋势)
    # 如果 当前价格 < BBI 且 持仓 -> 卖出 (空头趋势)
    
    if current_price > bbi and position == 0:
        # 全仓买入
        order_value(security, cash)
        log.info("买入信号触发: 价格(%.2f) > BBI(%.2f), 全仓买入 %s" % (current_price, bbi, security))
        
    elif current_price < bbi and position > 0:
        # 清仓卖出
        order_target(security, 0)
        log.info("卖出信号触发: 价格(%.2f) < BBI(%.2f), 清仓卖出 %s" % (current_price, bbi, security))

代码解析

  1. 数据获取 (get_history):

    • 我们设置 count=30 并使用 include=False。这意味着我们使用昨天及之前的收盘价来计算 BBI 指标。这样做符合技术分析中“基于历史数据判断当前走势”的逻辑,且在回测中更严谨。
    • frequency='1d' 表示使用日线数据。
  2. 指标计算:

    • 利用 Pandas 的切片功能 iloc[-N:] 快速获取最近 N 天的数据,并使用 .mean() 计算平均值。
    • BBI 是这四个均值的算术平均。
  3. 交易逻辑:

    • 策略比较的是 current_price(当前最新价)与 bbi(基于历史收盘价计算的支撑/阻力位)。
    • 买入:当价格站上 BBI 线,且当前没有持仓时,使用 order_value 买入。
    • 卖出:当价格跌破 BBI 线,且当前持有股票时,使用 order_target(security, 0) 卖出所有持仓。
  4. 兼容性:

    • 使用了 % 格式化字符串(如 "%s" % var),而不是 f-string,确保在 Python 3.5 环境下也能正常运行。

常见问题 (Q&A)

Q1: 如何修改 BBI 的计算周期?
A1: 在 initialize 函数中,修改 g.ma_periods = [3, 6, 12, 24] 列表中的数字即可。例如,如果你想计算更长周期的 BBI,可以改为 [6, 12, 24, 48],同时记得增加 handle_dataget_history 获取的天数(history_count)。

Q2: 这个策略可以用于分钟级别回测吗?
A2: 可以。只需将 get_history 中的 frequency='1d' 改为 frequency='1m' 或其他分钟周期,并将策略回测频率设置为分钟级。但在分钟级别下,BBI 的参数(3, 6, 12, 24)代表的是分钟数的均线,可能需要根据实际情况调整参数大小。

Q3: 为什么使用 include=False
A3: 在计算均线类指标时,通常使用已收盘的 K 线数据。如果在盘中实时将当前未收盘的价格计入 MA 计算,会导致指标在盘中不断跳动(Repainting),造成信号不稳定。使用 include=False 锁定昨天的 BBI 值作为今日的参考线是比较稳健的做法。

Q4: 如何对多只股票运行此策略?
A4: 你可以在 initialize 中使用 set_universe 设置多只股票列表,然后在 handle_data 中使用 for 循环遍历 g.security 列表,对每一只股票分别执行计算和交易逻辑。