带你详细了解PTrade策略框架(第三篇)before_trading_start函数详解

QUANT 2025-12-30 09:55:14 28 举报

在上一篇文章中,我们详细探讨了PTrade的重要初始化函数initialize(),它负责完成策略的一次性全局配置

本文将继续沿着策略构建的框架,深入讲解第二个核心函数——before_trading_start()

1. before_trading_start(context, data) 函数的核心定位
before_trading_start() 函数会在每个交易日的开盘交易前被调用

它的主要任务是执行每日的初始化和准备工作,确保策略以一个干净、预设好的状态迎接新的交易


• 参数 context:与initialize函数一样,context对象包含了策略的上下文信息,如账户资金、持仓等
• 参数 data:此处的data对象可以用来获取前一个交易日的历史数据,但不能获取当日的实时行情,因为市场尚未开盘

2. before_trading_start() 的核心用法
与initialize()的一次性设置不同,before_trading_start()中的代码是每日重复执行的

因此,它主要承担以下几类任务:
1.每日状态变量的重置
这是before_trading_start()最常见的用途之一策略中经常会有一些需要按天重置的状态标记

例如,为了避免策略在一天内重复交易,我们可能会设置一个g.traded_today的标记;

这个标记在当天交易后被设为True,而在第二天开始前,就必须通过before_trading_start()将其重置为False

2.每日动态证券池的筛选
很多策略的每日股票池并非一成不变,而是需要根据过去,或集合竞价的数据进行动态调整。

before_trading_start()是执行这个策略的重要函数。例如,我们可以在盘前获取前一日的收盘价、成交量等数据,筛选出符合特定条件的股票,或在集合竞价时间获取并筛选我们理想的标的,作为当日的操作目标


3.盘前信息的查询与预处理
在开盘前,我们可以也利用这个函数提前查询账户信息,如可用资金、当前持仓等,为盘中的交易决策做好数据准备。也可以在这里预先计算一些基于昨日数据的指标,以供盘中直接使用

完整的 before_trading_start() 代码示例:

def before_trading_start(context, data):
    g.traded_today = False

    dt = getattr(context, "current_dt", None)
    date_str = dt.strftime("%Y-%m-%d") if dt else "unknown_date"
    log.info(f"进入交易日 {date_str},重置每日状态。")

    sec_list = getattr(g, "security_list", None)
    if not sec_list:
        sec_list = ["600519.SS", "000001.SZ"]
        g.security_list = sec_list
        log.info(f"提示:未检测到 g.security_list,已使用默认股票池:{sec_list}")

    g.today_options = []

    try:
        hist = get_history(
            1,
            frequency="1d",
            field="close",
            security_list=sec_list,
            fq=None,
            include=False
        )
    except TypeError:
        hist = get_history(1, "1d", "close", sec_list, fq=None, include=False)

    if hist is None:
        log.info("get_history 返回 None,今日不做盘前筛选。")
        g.today_options = list(sec_list)
    else:
        ok = False
        try:
            close_series = hist.iloc[-1]
            for s in sec_list:
                if s in close_series.index and float(close_series[s]) > 20:
                    g.today_options.append(s)
            ok = True
        except Exception:
            pass

        if not ok:
            try:
                close_df = hist["close"]
                close_series = close_df.iloc[-1]
                for s in sec_list:
                    if s in close_series.index and float(close_series[s]) > 20:
                        g.today_options.append(s)
                ok = True
            except Exception as e:
                log.info(f"get_history 返回结构解析失败:{e}")

        if not ok:
            g.today_options = list(sec_list)

    log.info(f"今日备选股票池: {g.today_options}")

    cash = context.portfolio.cash
    log.info(f"盘前可用资金: {cash:.2f}")


日志如下:


注意事项

  • 与initialize()的根本区别(说的简单一点):必须清晰地区分initialize()和before_trading_start()的职责一次性的、永久性的设置放在initialize()中;需要每日更新和重置的操作放在before_trading_start()中
  • 数据局限性:在此函数中,无法获取当日的分钟线、tick等实时行情数据(重点),因为交易尚未开始所有的数据分析都应基于历史数据(通常是前一日或更早的数据)
  •  避免耗时操作:盘前准备阶段的时间有限,应避免过于复杂的计算或大规模的数据操作,以免影响策略在开盘前准时就绪。


before_trading_start()函数为策略提供了一个宝贵的盘前准备窗口,通过每日重置状态、筛选标的、预处理信息,我们可以让核心的盘中交易逻辑(handle_data)变得更加纯粹和高效


PTrade免费申请

PTrade免费领取学习案例

PTrade落地辅助

需要的朋友欢迎联系 ~~~



尊重知识,尊重市场 1

著作权归文章作者所有。

最新回复 ( 0 )
发新帖
0
DEPRECATED: addslashes(): Passing null to parameter #1 ($string) of type string is deprecated (/data/user/htdocs/xiunophp/xiunophp.min.php:48)