前言
突破策略如果只判断 last_price 创了新高就做多,在期货里经常会踩坑:最新价可能是零星成交戳出来的,买卖盘很薄,一跳就触发信号,实盘中却成交困难或滑点很大。我看过不少回测好看的突破,加上盘口过滤后信号少一半,但模拟盘反而更贴近真实。
天勤 TqSdk 的 get_quote 返回对象里带有买一卖一量、买卖价等字段(具体名以 reference/tqsdk.objs.rst 为准)。下面说明怎么在发单前加一层“盘口厚度”过滤,并和涨跌停、交易时段一起考虑。
一、last_price 和盘口各自代表什么
last_price 是最近一次成交价,更新快,适合趋势判断,但不告诉你对手盘有多少量等着。bid_price1、ask_price1 及对应量,能粗略看出短线流动性。
突破做多时,若卖一量很小,可能意味着上方挂单不多,也可能是流动性差、价格乱跳,要结合品种和时段判断,不能单独迷信某一个字段。
二、最小盘口读取示例
from tqsdk import TqApi, TqAuth, TqSim
api = TqApi(TqSim(), auth=TqAuth("账户", "密码"))
symbol = "SHFE.rb2510"
q = api.get_quote(symbol)
while True:
api.wait_update()
if api.is_changing(q, "last_price"):
lp = q.last_price
ask1 = q.ask_price1
bid1 = q.bid_price1
ask_vol = q.ask_volume1 # 字段名以文档为准
bid_vol = q.bid_volume1
# print(lp, bid1, bid_vol, ask1, ask_vol)
首次订阅后要等 wait_update 收到完整 quote,再读盘口,避免全是 nan。
三、流动性过滤的一种实用写法
思路:突破信号成立时,要求卖一(做多)或买一(做空)量大于阈值,避免在“空盘口”上追价。
MIN_ASK_VOL = 10 # 示例,需按品种调整
def liquidity_ok_for_buy(quote):
v = quote.ask_volume1
return v is not None and v >= MIN_ASK_VOL
# 在突破条件为 True 时:
# if breakout and liquidity_ok_for_buy(q):
# task.set_target_volume(1)
阈值要靠历史 tick 或盘口统计定,不能全品种共用同一个数。
四、和涨跌停、价差过滤一起用
接近涨停时,ask_price1 可能不存在或量为 0,突破信号往往是假象。可结合 upper_limit、lower_limit 与 last_price 的距离过滤。
夜盘刚开盘几分钟,盘口可能不稳定,适合加“开盘后 N 分钟不交易”的规则,比单纯调大 MIN_VOL 更清晰。
五、tick 策略与 K 线策略的差异
基于 K 线收盘的突破,可以在 K 线走完时用当时 quote 的盘口过滤;基于 tick 的策略,盘口变化更频,要注意 is_changing 的字段过滤,避免每个 tick 都重复判断加重 CPU 负担。
总结
买卖盘过滤不是可有可无的优化,而是期货突破策略里把“价格碰到”变成“有机会成交”的一步。天勤 quote 提供了盘口字段,策略里在下单前多读两行量,通常比事后抱怨滑点更有用。
建议把“有信号但盘口不过关”的次数也记进日志,回测对比过滤前后成交笔数。过滤太严会错过行情,太松则回测虚高,只能在模拟盘里慢慢调阈值。
FAQ
1)盘口字段全是 nan 怎么办?
多等几帧 wait_update,或检查合约是否交易时段、是否订对 symbol。
2)只有 last_price 没有盘口能交易吗?
能订行情,但过滤逻辑要降级,并接受更大滑点风险。
3)五档盘口要用吗?
流动性要求高的策略可以看多档,注意订阅与 CPU。
4)TargetPosTask 会自动看盘口吗?
不会,过滤要在 set_target_volume 前自己写。
风险提示
本文用于期货量化技术实践讨论,不构成任何投资建议。流动性随市场变化,请充分模拟测试。


