第十六章:订单流与程序化交易
说实话,很多做手工交易的朋友一听到「程序化」三个字就头大。觉得那是量化团队才玩的东西,自己搞不定。
但我个人习惯是:能交给机器的,绝不手动干。尤其是订单流这种高频数据,你盯盘盯到眼睛出血,也不如一段代码跑得精准。
这一章,我就带你走一遍完整的流程——从数据获取,到指标编程,再到策略开发和回测。嗯,都是我在实盘里踩过坑之后总结出来的。
核心逻辑:订单流程序化交易 = 数据管道 + 指标引擎 + 策略逻辑 + 回测验证。四者缺一不可。
16.1 订单流数据的获取
做程序化交易,第一步就是搞定数据源。没有数据,什么策略都是空中楼阁。
我早期吃过这个亏——自己写了个爬虫去抓某平台的逐笔数据,结果人家反爬一升级,整个策略直接瘫痪。后来学乖了,老老实实走正规渠道。
目前主流的订单流数据获取方式有三种:
- 交易所API直连:比如币安的WebSocket流,实时推送逐笔成交和深度快照。延迟最低,但需要自己维护连接。
- 第三方数据商:像TickData、Quandl这类,提供清洗好的历史数据。适合回测,但实时性差一些。
- 券商Level2行情:A股市场用这个,包含十档行情和逐笔委托。我建议用CTP接口接入,稳定。
我的经验:如果你做高频,必须用WebSocket直连。如果做日内波段,第三方数据完全够用。别为了省几百块钱去用免费数据——你想想看,数据延迟一秒,策略可能就从盈利变亏损了。
下面是一个简单的WebSocket订阅代码示例,订阅币安的逐笔成交数据:
import websocket
import json
def on_message(ws, message):
data = json.loads(message)
# 提取订单流关键字段
price = float(data['p'])
volume = float(data['q'])
side = 'buy' if data['m'] == False else 'sell'
print(f"价格: {price}, 量: {volume}, 方向: {side}")
def on_error(ws, error):
print(f"连接异常: {error}")
def on_close(ws, close_status_code, close_msg):
print("连接关闭,准备重连...")
def on_open(ws):
# 订阅BTCUSDT的逐笔成交
sub_msg = {
"method": "SUBSCRIBE",
"params": ["btcusdt@trade"],
"id": 1
}
ws.send(json.dumps(sub_msg))
ws = websocket.WebSocketApp(
"wss://stream.binance.com:9443/ws",
on_open=on_open,
on_message=on_message,
on_error=on_error,
on_close=on_close
)
ws.run_forever()
注意:WebSocket连接必须实现重连机制。我曾经因为网络抖动导致数据断流半小时,策略还在按旧数据开仓,结果你懂的...后来我加了心跳检测和自动重连,才算稳下来。
16.2 订单流指标的编程实现
数据拿到手了,接下来就是算指标。订单流里最常用的几个指标,说白了就是:Delta、CVD、失衡比。
我一个个说。
16.2.1 Delta(买卖量差)
Delta = 主动买量 - 主动卖量。正值说明买方更主动,负值反之。
实现起来很简单,但要注意:必须区分主动买和主动卖。在逐笔数据里,一般用「taker buy」标记来判断。
def calculate_delta(trades):
"""
trades: list of dict, 每笔包含 {'price': float, 'volume': float, 'side': str}
"""
buy_vol = sum(t['volume'] for t in trades if t['side'] == 'buy')
sell_vol = sum(t['volume'] for t in trades if t['side'] == 'sell')
delta = buy_vol - sell_vol
return delta
16.2.2 CVD(累积成交量差)
CVD就是Delta的累积版本。它能帮你看到资金是在持续流入还是流出。
我个人习惯用CVD来过滤假突破——价格创新高但CVD没跟上,十有八九是诱多。
class CVDIndicator:
def __init__(self):
self.cumulative_delta = 0
def update(self, delta):
self.cumulative_delta += delta
return self.cumulative_delta
16.2.3 失衡比(Imbalance Ratio)
失衡比 = (买量 - 卖量) / (买量 + 卖量)。范围在-1到1之间。
绝对值大于0.6就算显著失衡,这时候往往意味着短期方向要变了。
def imbalance_ratio(buy_vol, sell_vol):
if buy_vol + sell_vol == 0:
return 0
return (buy_vol - sell_vol) / (buy_vol + sell_vol)
实战技巧:别只看单一指标。我一般把Delta、CVD和失衡比放在一起看。比如Delta为正、CVD持续上升、失衡比大于0.5——三个信号共振,胜率会高很多。
16.3 自动化交易策略的开发
指标算出来了,接下来就是写策略逻辑。订单流策略的核心思路其实就一句话:跟着聪明钱走。
我常用的一个策略框架是这样的:
- 入场条件:Delta连续3根K线为正 + CVD创近期新高 + 价格突破前高
- 出场条件:Delta转负 + CVD拐头向下
- 止损:最近一根大阳线的低点下方1个ATR
- 仓位管理:根据失衡比动态调整,失衡越强仓位越大
下面是一个简化版的策略代码:
class OrderFlowStrategy:
def __init__(self, delta_threshold=100, cvd_breakout=True):
self.delta_threshold = delta_threshold
self.cvd_breakout = cvd_breakout
self.position = 0
self.cvd = CVDIndicator()
def on_bar(self, bar_data):
# bar_data包含该K线的所有逐笔成交
delta = calculate_delta(bar_data['trades'])
cvd_value = self.cvd.update(delta)
# 入场逻辑
if delta > self.delta_threshold and cvd_value > 0:
if self.position == 0:
self.enter_long(bar_data['close'])
self.position = 1
# 出场逻辑
elif delta < -self.delta_threshold:
if self.position == 1:
self.exit_long(bar_data['close'])
self.position = 0
避坑指南:我曾经在策略里用了未来函数——用当前K线的CVD去判断入场,但实际上CVD是累积值,包含了整个K线的数据。这导致回测曲线漂亮得不像话,实盘直接打脸。记住:只能用已完成的K线数据做判断。
16.4 回测系统的搭建
策略写好了,不回测就上实盘?那是赌博。
一个靠谱的回测系统,至少要有这几个模块:
| 模块 | 功能 | 注意事项 |
|---|---|---|
| 数据引擎 | 加载历史订单流数据,按时间切片 | 必须包含逐笔数据,不能用K线模拟 |
| 策略引擎 | 逐笔或逐K线执行策略逻辑 | 注意滑点和手续费模拟 |
| 风控模块 | 检查仓位、资金、最大回撤 | 实盘风控参数要和回测一致 |
| 绩效评估 | 计算夏普、胜率、盈亏比等 | 别只看总收益,要看资金曲线 |
我习惯用Python的backtrader框架做回测,但订单流数据需要自己写数据源适配器。下面是一个简单的回测框架示例:
import pandas as pd
from datetime import datetime
class OrderFlowBacktest:
def __init__(self, strategy, data, initial_capital=100000):
self.strategy = strategy
self.data = data # DataFrame, 包含逐笔数据
self.capital = initial_capital
self.equity_curve = []
def run(self):
# 按时间窗口切片,模拟逐K线运行
for timestamp, bar_data in self.data.groupby(pd.Grouper(freq='1min')):
self.strategy.on_bar(bar_data)
# 记录权益
self.equity_curve.append({
'time': timestamp,
'equity': self.capital + self.strategy.position * bar_data['close'].iloc[-1]
})
return pd.DataFrame(self.equity_curve)
def evaluate(self):
df = pd.DataFrame(self.equity_curve)
total_return = (df['equity'].iloc[-1] - self.capital) / self.capital
max_drawdown = (df['equity'].cummax() - df['equity']).max() / self.capital
print(f"总收益率: {total_return:.2%}")
print(f"最大回撤: {max_drawdown:.2%}")
return total_return, max_drawdown
我的建议:回测时一定要加入滑点模拟。订单流策略通常在高流动性品种上跑,但滑点依然存在。我一般按0.1%的滑点来算,如果回测还能盈利,实盘才有戏。
嗯,到这里,订单流程序化交易的四个核心环节就都讲完了。从数据获取到指标编程,从策略开发到回测验证,每一步都有坑,但也都有解法。你想想看,把这些串起来,就是一个完整的自动化交易系统了。
最后说一句:程序化交易不是让你躺赚的魔法,而是帮你把交易纪律执行到位的工具。工具好不好,还得看用的人。
交易系统化学习资料 微信Strategy888888