摘要: 交易所撮合遵循价格优先、时间优先,但市价单、涨跌停板、集合竞价和期货夜盘会打破单纯的时间顺序。量化策略若用市价单或忽略隐藏队列,滑点会远超预期。

股票挂单真的按时间排队吗

每个刚接触股票和期货的人,都会听到一句话:价格优先,时间优先。听起来就像排队买奶茶,谁先到谁先拿。可真到了盘口,你发现有时候明明挂得早,却没成交;有时候晚一秒挂进去,反而先被吃掉。这背后不是交易所骗你,而是撮合规则比你想的复杂得多。

撮合规则先看价格再看时间

交易所的电脑每天干的事,就是把买单和卖单配对。配对的第一原则是价格。买单价高的人优先,卖单价低的人优先。同一价格上,才轮到时间。谁先挂单,谁排在前面。这就是时间优先。

股票挂单确实按照时间顺序,但有一个前提:价格相同。你挂10块钱买,别人挂10块零1分买,哪怕你提前一小时挂,也是别人先成交。所以时间优先是个相对概念,在价格面前它得往后排。

股票挂单真的按照时间顺序成交吗 期货量化新手常踩的撮合逻辑坑

市价单插队才是最常见的意外

很多人以为挂单就是限价单。其实交易所还接受市价单。市价单的意思是:不管价格,立刻成交。这种单子进入撮合系统后,会直接吃掉当前最优的卖单。你前面排了100个限价买单,突然来了一个市价买单,它不排队,直接成交。

股票里市价单相对少,期货里非常普遍。期货主力合约盘口厚,市价单冲进去,瞬间吃掉好几档。做量化交易的人如果习惯用市价单开平仓,回测时按盘口中间价算成交,实盘滑点会大到怀疑人生。

集合竞价阶段没有连续时间优先

开盘前和收盘前,交易所采用集合竞价。这段时间不是谁先挂谁先成交,而是把所有单子攒在一起,找出一个能让成交量最大的价格。所有能成交的单子,不管挂单时间早晚,都按这个统一价格成交。

股票开盘集合竞价9:15到9:25,期货夜盘开盘前也有集合竞价。量化策略如果在这段时间发单,时间优先基本失效。你9:15:01挂的单和9:24:59挂的单,只要价格合适,成交价一样。

涨跌停板上的时间优先会变形

股票和期货都有涨跌停板。当价格封死在涨停板,买单堆积如山,卖单极少。这时候时间优先确实起作用,谁先挂涨停价买单,谁先成交。可一旦有卖单出来,交易所不是简单按时间排队,而是看谁的买单手数能匹配。

大单优先还是时间优先,不同交易所规则有差异。国内股票和期货都是时间优先,但大单可以拆成小单。量化程序拆单后,每笔小单都有自己的时间戳。拆得越细,时间戳越靠后,反而可能排在别人后面。

期货撮合还有隐藏队列和自成交防范

期货交易所为了防自成交,会检查同一账户的买卖单。如果你的量化程序同时挂买单和卖单,交易所可能先冻结其中一笔,不让它立即成交。这导致你的单子虽然时间靠前,但被系统暂时移出队列。

还有隐藏队列。有些交易所允许冰山单,只显示一小部分,成交后再补充。你以为盘口只有100手,实际后面藏着1000手。你的单子时间优先,但前面有一堆看不见的单子,成交速度远慢于预期。

量化交易如何应对撮合时间差

做股票和期货量化,不能只依赖时间优先。回测时要用逐笔成交数据,不能只用K线。策略发单要用限价单,避免市价单的滑点。拆单算法要考虑队列位置,而不是简单按时间切片。

下面是一个简单的Python片段,演示如何用限价单排队,而不是市价单追价。


# 模拟限价挂单排队逻辑

from collections import deque

class OrderQueue:

    def __init__(self):

        self.buy_queue = deque()

        self.sell_queue = deque()

    def add_limit_order(self, side, price, time_stamp):

        order = (price, time_stamp)

        if side == 'buy':

            self.buy_queue.append(order)

            self.buy_queue = deque(sorted(self.buy_queue, key=lambda x: (-x[0], x[1])))

        else:

            self.sell_queue.append(order)

            self.sell_queue = deque(sorted(self.sell_queue, key=lambda x: (x[0], x[1])))

    def match(self):

        trades = []

        while self.buy_queue and self.sell_queue:

            best_buy = self.buy_queue[0]

            best_sell = self.sell_queue[0]

            if best_buy[0] >= best_sell[0]:

                trade_price = best_sell[0] if best_buy[1] < best_sell[1] else best_buy[0]

                trades.append((trade_price, best_buy, best_sell))

                self.buy_queue.popleft()

                self.sell_queue.popleft()

            else:

                break

        return trades

# 使用示例

q = OrderQueue()

q.add_limit_order('buy', 10.00, 1001)

q.add_limit_order('buy', 10.01, 1002)

q.add_limit_order('sell', 10.01, 1003)

print(q.match())

这段代码里,买单价格高的排前面,同价格时间早的排前面。卖单价格低的排前面,同价格时间早的排前面。撮合时价格交叉就成交。实盘比这复杂,但核心逻辑一样。

挂单时间优先不是万能钥匙

股票挂单在连续竞价、同价格、同方向的前提下,确实按时间顺序。期货撮合也遵循这个原则。可市价单、集合竞价、涨跌停板、隐藏队列、自成交防范,都会让时间优先打折扣。量化交易者要清楚这些细节,否则回测赚钱,实盘亏钱。

价格优先是铁律,时间优先是补充。理解撮合逻辑,比多写几行代码更重要。