🚀 AI 一键生成 ptrade 策略代码

在 PTrade 策略中,如何高效使用 Pandas 对行情数据进行处理与分析?

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

问题描述

如何使用 Pandas 对 get_history 返回的行情数据进行分析?

解决方案

在 PTrade 量化交易平台中,get_history 函数是获取历史行情数据的核心接口。根据 PTrade 的 API 文档,该函数返回的数据通常已经是 pandas.DataFrame(单只股票或 Python 3.11 多只股票)或 pandas.Panel(Python 3.5 多只股票多字段)格式,这使得直接利用 Pandas 库进行数据分析变得非常便捷。

以下是如何使用 Pandas 对 get_history 返回的数据进行清洗、计算技术指标以及生成交易信号的详细指南。

1. 获取数据与基础查看

首先,我们需要调用 get_history 获取数据。通常我们获取的是一个 DataFrame,其中行索引(Index)是时间(datetime),列(Columns)是行情字段(如 open, close, high, low, volume)。

# 获取单只股票过去 100 天的日线数据
# 返回的是 DataFrame,索引为 datetime 对象
df = get_history(100, frequency='1d', field=['open', 'high', 'low', 'close', 'volume'], security_list='600570.SS')

# 打印前 5 行查看数据结构
log.info("前5行数据:\n%s" % df.head())

# 查看数据的基础统计信息(均值、标准差、最大最小值等)
log.info("数据统计描述:\n%s" % df.describe())

2. 使用 Pandas 计算技术指标

Pandas 的强大之处在于其向量化运算和滚动窗口函数(Rolling Window),这对于计算移动平均线(MA)、波动率等指标非常高效。

计算移动平均线 (MA)

使用 rolling().mean() 方法:

# 计算 5 日均线
df['MA5'] = df['close'].rolling(window=5).mean()

# 计算 10 日均线
df['MA10'] = df['close'].rolling(window=10).mean()

计算涨跌幅 (Returns)

使用 pct_change() 方法:

# 计算每日涨跌幅
df['pct_change'] = df['close'].pct_change()

计算历史波动率 (Volatility)

使用 rolling().std() 方法:

# 计算 20 日的历史波动率
df['volatility'] = df['close'].rolling(window=20).std()

3. 数据清洗与筛选

在计算指标后,通常前几行数据会因为窗口期不足而产生 NaN(空值)。

# 删除包含空值的行
df.dropna(inplace=True)

# 筛选出收盘价大于 5 日均线的日期数据
bullish_days = df[df['close'] > df['MA5']]

4. 完整策略代码示例

下面是一个完整的 PTrade 策略示例。该策略在 handle_data 中获取历史数据,使用 Pandas 计算双均线(MA5 和 MA10),并根据金叉(MA5 上穿 MA10)和死叉(MA5 下穿 MA10)进行买卖操作。

def initialize(context):
    # 设置股票池:恒生电子
    g.security = '600570.SS'
    set_universe(g.security)
    # 设置滑点和佣金(可选,为了回测更真实)
    set_commission(commission_ratio=0.0003, min_commission=5.0)
    set_slippage(slippage=0.002)

def handle_data(context, data):
    security = g.security
    
    # 1. 获取过去 20 天的收盘价数据
    # 注意:为了计算 MA10,我们需要至少 10 根 K 线,取 20 根是为了确保数据充足
    # include=False 表示不包含当前周期(即只取历史数据,避免未来函数)
    df = get_history(20, frequency='1d', field=['close'], security_list=security, include=False)
    
    # 检查数据是否获取成功且长度足够
    if df is None or len(df) < 10:
        log.info("数据不足,跳过本次计算")
        return

    # 2. 使用 Pandas 计算均线
    # 计算 5 日均线
    ma5_series = df['close'].rolling(window=5).mean()
    # 计算 10 日均线
    ma10_series = df['close'].rolling(window=10).mean()
    
    # 获取最新的均线值(序列的最后一个值)
    current_ma5 = ma5_series.iloc[-1]
    current_ma10 = ma10_series.iloc[-1]
    
    # 获取前一天的均线值(用于判断交叉)
    prev_ma5 = ma5_series.iloc[-2]
    prev_ma10 = ma10_series.iloc[-2]
    
    # 获取当前持仓
    position = get_position(security)
    
    # 3. 交易逻辑判断
    # 金叉:昨天 MA5 < MA10,且今天 MA5 > MA10
    if prev_ma5 < prev_ma10 and current_ma5 > current_ma10:
        # 记录日志
        log.info("金叉出现:MA5=%.2f, MA10=%.2f" % (current_ma5, current_ma10))
        # 满仓买入
        cash = context.portfolio.cash
        if cash > 0:
            order_value(security, cash)
            log.info("买入 %s" % security)
            
    # 死叉:昨天 MA5 > MA10,且今天 MA5 < MA10
    elif prev_ma5 > prev_ma10 and current_ma5 < current_ma10:
        # 记录日志
        log.info("死叉出现:MA5=%.2f, MA10=%.2f" % (current_ma5, current_ma10))
        # 如果有持仓,清仓卖出
        if position.amount > 0:
            order_target(security, 0)
            log.info("卖出 %s" % security)

5. 处理多只股票的数据

security_list 包含多只股票时,get_history 的返回格式在不同 Python 版本下可能不同。

  • Python 3.11 环境:返回 MultiIndex DataFrame(多级索引),列索引包含股票代码。
  • Python 3.5 环境:如果查询多个字段,可能返回 pandas.Panel(已弃用的数据结构)。

推荐的处理方式(兼容性写法):

如果需要处理多只股票,建议使用 query 方法或者循环处理,或者明确指定 is_dict=True(如果 API 支持)来获取字典格式,然后自行转换为 DataFrame。

在 Python 3.11 中处理多只股票 DataFrame 的示例:

# 假设 df 是包含多只股票数据的 DataFrame
# 使用 query 提取特定股票的数据
df_stock_a = df.query('code == "600570.SS"')
# 接下来可以像处理单只股票一样处理 df_stock_a

总结

使用 Pandas 分析 PTrade 数据的主要步骤:

  1. 获取get_history 拿到 DataFrame。
  2. 计算:利用 rolling(), mean(), std(), pct_change() 等向量化函数计算指标。
  3. 切片:利用 .iloc[-1] 获取最新值用于交易判断。
  4. 清洗:利用 dropna() 处理计算产生的空值。

Q&A: PTrade 数据分析常见问题

Q1: 为什么计算出的 MA(均线)前几行是 NaN?
A: 这是因为滚动窗口计算需要足够的数据。例如计算 5 日均线,前 4 天的数据不足以计算平均值,因此 Pandas 会填充为 NaN。在使用数据前,建议使用 df.dropna() 去除这些无效行,或者在获取数据时多获取一些历史长度(如需要 10 日均线,至少获取 20 天数据)。

Q2: get_history 中的 include 参数应该设为 True 还是 False?
A: 在编写策略逻辑(尤其是 handle_data 中)时,通常建议设为 False。因为 handle_data 运行时,当天的 K 线可能尚未走完(如果是盘中运行),包含当前数据可能导致“未来函数”问题(即利用了收盘后才能确定的价格在盘中交易)。如果是在盘后分析或 after_trading_end 中,可以设为 True

Q3: 如何将 Pandas 计算出的信号转换为交易指令?
A: Pandas 计算出的通常是整个序列(Series)。你需要提取序列的最后一行(iloc[-1])作为“当前时刻”的指标值,将其与阈值进行比较(if 语句),然后调用 PTrade 的 order 系列函数(如 order, order_target, order_value)进行下单。