26、订单流与量化平台:在VN.PY、Backtrader中集成订单流数据

说实话,很多做订单流的朋友都问过我一个问题:

“我手工看订单流图表挺顺手的,但怎么把它弄到我的量化策略里?”

嗯,这是个好问题。你想想看,订单流数据本身是高频的、逐笔的,而传统的量化框架比如VN.PY、Backtrader,它们默认处理的是K线数据。这两者之间,存在一个“数据鸿沟”。

今天我就带你亲手填上这个坑。

为什么要在量化平台里集成订单流?

我个人习惯把订单流数据看作是“市场的CT扫描”。普通K线只能看到价格和成交量,但订单流能告诉你:

  • 谁在主动买?谁在主动卖?
  • 在关键价位上,有多少挂单在防守?
  • 大单是吃货还是砸盘?

把这些信息量化成指标,再塞进策略里,效果往往比单纯用均线、MACD好得多。我在项目中遇到过好几次,用订单流数据过滤掉假突破,胜率直接提升了十几个点。

数据格式的“翻译”工作

首先得明确一点:订单流数据不是标准OHLCV。它通常是这样的:

# 原始订单流数据(逐笔成交)
timestamp, price, volume, side, ask_price, bid_price
09:30:01.123, 100.50, 200, BUY,  100.51, 100.49
09:30:01.456, 100.49, 150, SELL, 100.50, 100.48
...

而量化平台要的是这样的:

# 标准K线数据
datetime, open, high, low, close, volume
2024-01-01 09:30:00, 100.50, 100.55, 100.48, 100.52, 350

所以,第一步就是“聚合”。把逐笔数据按时间切片(比如1分钟、5分钟),同时计算出订单流特有的指标:

  • Delta:主动买量 - 主动卖量
  • Cumulative Delta:累计Delta
  • POC:成交量最大价位
  • VAH/VAL:价值区域上下沿

在VN.PY中集成订单流

VN.PY本身是事件驱动的,它的核心是BaseDataBarGenerator。我的做法是:

  1. 自定义一个TickData扩展,加上deltaask_volumebid_volume字段。
  2. 重写BarGenerator,在生成1分钟K线时,同时计算Delta、POC等。
  3. 把订单流指标作为新的K线字段,比如bar.deltabar.cum_delta

代码大概长这样:

class OrderFlowBarGenerator(BarGenerator):
    def update_tick(self, tick: TickData):
        # 原有的K线生成逻辑
        super().update_tick(tick)
        
        # 额外计算Delta
        if tick.last_price >= tick.ask_price_1:
            self.delta += tick.volume  # 主动买
        elif tick.last_price <= tick.bid_price_1:
            self.delta -= tick.volume  # 主动卖
        
        # 当K线完成时,把delta赋值给bar
        if self.bar_completed:
            self.bar.delta = self.delta
            self.delta = 0
            self.on_bar(self.bar)

这样,你的策略里就能直接调用bar.delta了。我曾经用这个框架做过一个策略:当Delta连续3根K线为负且价格没跌,就做多。效果出奇的好。

在Backtrader中集成订单流

Backtrader的思路不太一样。它更偏向于“数据馈送”和“指标计算”。

我的做法是:

  1. 自定义一个DataFeed,继承bt.feeds.PandasData,把订单流指标作为额外的lines。
  2. 在策略中直接使用这些lines

举个例子:

class OrderFlowData(bt.feeds.PandasData):
    # 定义额外的数据列
    lines = ('delta', 'cum_delta', 'poc', 'vah', 'val')
    
    # 映射到CSV或DataFrame的列名
    params = (
        ('delta', 'delta'),
        ('cum_delta', 'cum_delta'),
        ('poc', 'poc'),
        ('vah', 'vah'),
        ('val', 'val'),
    )

# 使用
data = OrderFlowData(dataname=df)  # df里包含delta等列
cerebro.adddata(data)

然后在策略里:

class MyStrategy(bt.Strategy):
    def next(self):
        if self.data.delta[0] > 1000 and self.data.close[0] > self.data.poc[0]:
            self.buy()

嗯,这里要注意:Backtrader的next()是按bar触发的,所以你的订单流数据必须提前聚合好。我建议在数据预处理阶段就把这些指标算好,存到DataFrame里,再喂给Backtrader。

避坑指南

我曾经踩过的坑:

  • 时间对齐问题:订单流数据是微秒级的,而K线是秒级的。聚合时一定要处理好时间戳的舍入,否则数据会错位。
  • 数据量爆炸:全量订单流数据一天可能几百万条。建议只保留聚合后的1分钟或5分钟数据,否则回放速度会慢到让你怀疑人生。
  • Delta的计算口径:不同交易所对“主动买/主动卖”的定义略有不同。记得先做小样本测试,确认你的Delta计算逻辑和交易所一致。

核心逻辑流程图

下面这张图,是我自己总结的“订单流数据集成量化平台”的标准流程。你照着这个走,基本不会出错:

原始订单流数据 逐笔成交/挂单 聚合 数据预处理 计算Delta/POC/VA 封装 量化平台集成 VN.PY / Backtrader 策略 各步骤详细说明: ① 原始数据 - 来源:交易所Level2行情、第三方数据商 - 字段:时间戳、价格、成交量、买卖方向、十档挂单 ② 数据预处理 - 按1分钟/5分钟切片,聚合计算Delta、CumDelta - 计算POC(成交量最大价位)、VAH/VAL(价值区域) ③ 平台集成 - VN.PY:扩展TickData + 重写BarGenerator - Backtrader:自定义DataFeed,增加额外lines

实战建议

我个人给你的建议:

  • 刚开始别贪多。先只集成Delta和Cumulative Delta这两个指标,跑通了再慢慢加POC、VAH这些。
  • 回测时一定要用“逐笔回放”模式,别用“跳跃式回放”。订单流策略对微观结构敏感,跳跃式回放会失真。
  • 数据源方面,我推荐用DolphinDB或者ClickHouse来存原始订单流数据,查询和聚合速度都很快。

好了,关于在VN.PY和Backtrader里集成订单流数据,核心要点就这些。说白了,就是“聚合数据 -> 封装成平台能识别的格式 -> 在策略里调用”。你动手试一次,就会发现其实没那么复杂。


无相订单流研究社 微信Lucian808555