第26章:基差交易系统搭建
系统架构设计、数据模块、策略模块、风控模块、执行模块——这五个词,说白了就是一套交易系统的五脏六腑。我做了这么多年量化,见过太多人一上来就写策略代码,结果数据源断了、风控没拦住、执行滑点大,最后亏得莫名其妙。今天咱们就把这套系统拆开揉碎了讲清楚。
一、系统架构设计:别让代码变成一团乱麻
我个人习惯,先把系统分成三层:数据层、策略层、执行层。每一层只干自己的事,别越界。你想想看,如果数据清洗和策略逻辑混在一起,改一个地方就得动全局,那维护成本就太高了。
核心原则:高内聚、低耦合。每个模块独立部署,通过消息队列或API通信。
举个例子,我早期做的一个基差套利系统,数据模块用Python写,策略模块用C++,执行模块直接对接CTP。它们之间通过Redis传递信号。这样哪怕数据模块挂了,策略模块还能用缓存数据撑一会儿。
架构图如下:
二、数据模块:地基不牢,地动山摇
数据模块是整个系统的命根子。我见过最惨的一次,是数据源突然断流,策略还在傻乎乎地发信号,结果全仓做反了方向。嗯,这里要注意:数据模块必须做三件事——接入、清洗、存储。
2.1 行情数据接入
基差交易需要两类数据:期货价格和现货价格。期货数据从交易所API拿,现货数据得找资讯商。我个人习惯用CTP接口拿期货行情,用Wind或Bloomberg拿现货数据。
# 伪代码示例:数据接入
class DataFeed:
def __init__(self):
self.future_api = CTPApi()
self.spot_api = WindApi()
def get_basis(self, symbol):
future_price = self.future_api.get_last_price(symbol)
spot_price = self.spot_api.get_index_price(symbol)
return future_price - spot_price
小技巧:数据频率要匹配。做日内基差就用1分钟线,做跨期就用日线。别拿tick数据算日频基差,那纯粹是给自己找麻烦。
2.2 数据清洗与存储
数据进来之后,第一件事不是算基差,而是清洗。我曾经遇到过某天现货数据突然跳空,算出来的基差直接爆表,策略差点开仓。后来我加了三道防线:
- 异常值检测:价格超过3倍标准差就标记
- 时间戳对齐:期货和现货的时间戳必须精确到毫秒
- 缺失值处理:用前向填充,别用插值
三、策略模块:核心逻辑,但别太复杂
策略模块说白了就是两件事:什么时候开仓,什么时候平仓。基差交易的核心逻辑其实很简单——基差偏离均值太多就进场,回归了就离场。但执行起来,细节多得吓人。
3.1 信号生成
我常用的方法是滚动窗口的Z-score。当基差的Z-score超过2.5时,认为偏离过度,准备开仓。低于-2.5时反向开仓。但这里有个坑:窗口长度怎么选?
| 窗口长度 | 适用场景 | 缺点 |
|---|---|---|
| 20个交易日 | 短期均值回归 | 噪音多,假信号多 |
| 60个交易日 | 中期趋势交易 | 反应慢,容易错过行情 |
| 120个交易日 | 长期套利 | 对结构变化不敏感 |
我个人习惯用60日窗口,再叠加一个20日窗口做辅助判断。两个窗口同时发出信号,我才进场。这样能过滤掉不少噪音。
3.2 仓位管理
仓位管理比信号生成更重要。我见过太多人信号对了,但仓位太重,一波回调就爆仓。我的原则是:每笔交易的风险不超过总资金的2%。
# 仓位计算示例
def calculate_position(basis, z_score, capital):
risk_per_trade = capital * 0.02
# 基差每偏离1个点,亏损多少
point_value = 10 # 假设每点10元
stop_loss = 5 # 止损5个点
position = risk_per_trade / (stop_loss * point_value)
return int(position)
注意:别用凯利公式算仓位。凯利公式在连续亏损时会让你下重注,这在基差交易里是致命的。我吃过这个亏,后来改用固定比例法。
四、风控模块:保命用的,别当摆设
风控模块是系统的最后一道防线。我把它分成三层:事前、事中、事后。
4.1 事前风控
开仓前检查三件事:
- 资金是否充足:保证金占用不超过70%
- 持仓是否超限:单品种持仓不超过总资金的30%
- 关联品种检查:如果已经持有螺纹钢多单,就别再开热卷多单
4.2 事中风控
持仓过程中,实时监控两个指标:
- 最大回撤:当日回撤超过5%就强制平仓
- 基差偏离:基差超过3倍标准差,立即检查数据源
4.3 事后风控
每天收盘后,跑一遍归因分析。看看今天的盈亏是来自基差变动,还是来自方向性风险。如果方向性风险占比太高,说明策略可能跑偏了。
避坑指南:我曾经把风控阈值设得太宽松,结果一次黑天鹅事件直接亏了15%。后来我把所有阈值都收紧了一半,虽然信号少了,但活得久了。
五、执行模块:最后一公里,别掉链子
执行模块负责把策略信号变成真实的成交。这里最大的敌人是滑点。基差交易本身利润就薄,滑点一多,直接亏钱。
5.1 订单路由
我一般用限价单,不追单。如果限价单5秒内没成交,就撤单重发。价格稍微调高或调低0.5个tick。这样既能控制滑点,又不会错过行情。
5.2 滑点控制
滑点控制的核心是流动性判断。如果当前盘口的买卖价差超过正常值的2倍,我就暂停交易,等流动性恢复再说。
# 滑点控制示例
def check_spread(symbol):
bid, ask = get_market_depth(symbol)
spread = ask - bid
normal_spread = get_normal_spread(symbol)
if spread > normal_spread * 2:
return False # 流动性不足,暂停交易
return True
5.3 成交反馈
每笔成交后,系统要立即更新持仓和资金。我习惯用事件驱动的方式,成交回报一来,就触发风控检查和策略状态更新。别用轮询,太慢了。
个人经验:执行模块最好单独部署在一台低延迟的服务器上。别跟策略模块混在一起,否则策略计算卡顿的时候,执行也跟着遭殃。
好了,以上就是基差交易系统的五个核心模块。每个模块单独看都不复杂,但组合起来,就是一个能稳定盈利的系统。记住:系统搭建不是一蹴而就的事,边跑边改,慢慢优化,才是正道。