做期货日内交易,日子久了就会明白:技术端省下的每一毫秒,都是真金白银。到了2026年这个节点,手续费和点差还在继续压缩,日内策略同质化严重,大家的胜负手其实已经不完全在“方向判断”,而更多落在“谁先看到行情、谁先挂出单子”——这句话听起来有点残酷,却是国内期货市场越来越真实的常态。
这篇文章与其说是教学,不如说是我把过去一两年间折腾日内交易平台和低延迟系统的笔记整理了一遍。我想用一次完整的技术复盘来聊两件事:一是怎么挑一个适合日内交易的平台,二是低延迟系统到底怎么搭。很多朋友容易把这两个问题分开看,要么只挑软件,要么只搭服务器,实际上它们是同一件事的两面。平台选得不对,再贵的硬件也白费;系统搭得不好,平台再快也会被本地处理拖后腿。
内容适合几类人:正在做或准备做日内交易的散户,维护中小规模量化系统的开发者,以及想给团队升级技术架构的负责人。我会把底层逻辑、实操步骤、具体参数和踩过的坑合并在一起讲,尽量做到看完全文就能动手,而不是看了一堆概念却不知道该先动哪里。
1. 平台选择:先搞清楚自己在哪个段位
1.1 平台和自研系统不是单选题
很多人一开始都纠结一个问题:“我是直接买一套交易软件,还是自己写一套交易系统?”其实这个问题的前提就有点偏了。日内交易的完整路径是“行情进来—策略判断—订单出去—回报确认”,这四个环节里,平台和自研系统各占一部分。
商业交易软件的优势是省事,行情、图表、下单、风控都集成好了,打开就能用。但问题在于,它的处理链路是黑盒,你没法在行情到策略之间插入自定义逻辑,也没法精确控制下单路径。自研系统的优势是每个环节都可以自己掌控延迟,代价是所有东西都要自己写,包括行情接入、订单管理、风控、日志,甚至要处理断线恢复。
我的判断标准很简单:看日内频率。
普通人工日内交易,一天几十笔,用商业软件完全够,把精力放在策略和盘感上更重要。半自动或日内高频交易,一天几百上千笔,商业软件就不太行了,因为它的行情刷新和委托回报之间往往有固定延迟,而且很多软件在极端行情下会出现逻辑卡顿。这时候就需要“半自研”,也就是行情和策略自己处理,下单通过柜台的开放接口走。
再往上,高频套利或者盘口交易,一天几万笔,必须全自研,连下单路径都要自己控制,因为这里每一笔都建立在“比别人快一点”上面,不存在“够用就好”。
所以平台选择的第一个维度不是看哪个软件“功能多”,而是看你要在哪个段位作战。平台只是工具,自研也不是目的,适合自己的频率和资金量才最重要。
1.2 2026年的平台评价维度
如果只让我给三个选平台的核心指标,我会这样排:
一是通道质量。通道指你的订单从本地发出去之后,经过多少跳才到交易所撮合。这一项几乎决定了延迟的天花板。市面主流柜台系统之间的差距可能只有几十微秒,但公网和托管机房的差距往往有好几毫秒。选平台之前,先搞清楚它是否支持直连柜台接口、是否支持托管机房部署,这比界面漂不漂亮重要得多。
二是手续费结构和返还模式。日内交易最怕的不是单笔手续费高,而是手续费雪球越滚越大。到2026年,各家期货公司的费率已经非常透明,但不同平台的底层账户模式不同,有的走特殊通道,有的走普通通道,实际成本可能差出一个量级。我会把手续费换算成“单笔成本占策略收益的比例”,低于10%才值得考虑。另外关注保证金占用方式,日内平仓的优惠力度直接决定资金使用效率。
三是数据接口的开放程度。平台能给你提供多细的行情快照?是否支持逐笔委托?是否有完整的盘中数据落盘?这些决定了你能否在本地复现盘口变化。很多商业软件只提供合并后的tick数据,做普通分析够用,但做微结构研究就不行。
我拿一个自己的经历说明:之前帮朋友看某个平台的性能,它的界面和交易执行都不错,但行情源是从主站推送过来的,且中间经历了三层转发。本地看到的行情永远落后于实际盘口。后来换了支持托管机房的方案,同样的策略,滑点减少了将近三成。这就是通道质量带来的实打实差距。
1.3 三条清晰的选型路线
我把目前可落地的方案分成三条路线,大家可以对照着自己选。
路线A:纯软件平台。适合资金量不大、交易频率中等、主要靠人工判断的交易者。选头部期货公司提供的官方软件,重点看是否支持条件单、止损单、快速反手,以及行情推送是否稳定。这套方案不需要自己写代码,但要接受延迟不可控。
路线B:半自研系统。适合有一定编程能力的日内交易者或小团队。行情和策略逻辑自己搞定,下单通过柜台开放API完成。前台可以保留商业软件做盯盘,后台自己跑策略。这条路能把延迟压到毫秒级,而且大幅提升了策略灵活性。
路线C:全自研超低延迟系统。适合高频、套利、做市这类对延迟极其敏感的场景。整个链路自己控制,网络、硬件、操作系统、代码全部围绕延迟优化。这条路门槛最高,但也是我认为2026年真正能拉开差距的方向。
我个人建议是:不要一上来就追求路线C,先把策略跑起来,用路线B摸清自己的延迟痛点,等发现“本地处理占了大头”的时候,再一步步向路线C演进。很多人一上来就买昂贵的服务器和网卡,结果发现瓶颈在网络链路上,钱就白花了。
2. 延迟去哪儿了:链路预算与硬件底子
2.1 先把延迟拆成一本账
低延迟系统搭建的第一步不是买设备,而是搞清楚延迟到底消耗在哪里。日内交易的完整回路大概长这样:交易所把行情推送出来——网络传输到你的服务器——进程收到数据并解析——策略引擎计算信号——订单组装并发送——订单经过柜台系统——进入交易所撮合——返回成交回报。
每个环节的量级差别很大。网络传输从几毫秒到几十毫秒不等,取决于物理距离和链路质量;行情解析通常几十微秒;策略计算一般几十到几百微秒;订单组装和发送在微秒级;柜台系统处理在几百微秒到几毫秒之间。这里有个概念要清楚:1毫秒等于1000微秒,一次网络传输可能吃掉你几十次内部计算的预算。
我习惯把所有延迟项列成一张表,每项都标注“典型值”和“极端值”。典型值决定了平均表现,极端值决定了最差表现。对日内交易来说,极端值反而比平均值更值得关注,因为一次300毫秒的卡顿可能抵消几千次正常交易的优化。延迟的波动性称为抖动,我衡量系统性能时最看重两个指标:平均延迟和P99延迟,也就是99%的情况下延迟不超过某个值。
2.2 硬件选型:不堆最高配,只堆最该配
硬件是整个系统的底子,但很多人堆硬件的方向是错的。日内交易系统不是渲染3D画面,也不是大数据分析,它的核心特征是“单线程低延迟”,所以CPU主频往往比核心数更重要。我测试过很多方案,同样负载下,一个高主频的中端处理器搭配宽松的内存时序,表现要好过低频但多核的高端处理器。因为交易链路本质是一条流水线,多数环节无法分拆到多个核心上并行。
内存方面,频率和时序都有影响,但普通人最容易忽略的是内存分配的稳定性。系统运行时间越长,内存碎片化越严重,局部性变差,缓存命中率下降,延迟就会悄悄上升。交易系统里忌讳在关键路径上频繁new和delete,要么用对象池,要么在初始化阶段就把所有需要的内存分配完毕。
网卡的选择要看中断处理能力。普通家用网卡在高流量下会产生大量中断,抢走CPU资源,影响策略执行的确定性。到2026年,多队列网卡已经成为标配,每个队列可以绑定到固定CPU核心,等于给网络流量安排了专用车道,不会挤占计算资源。
硬盘方面,系统盘和日志盘分开是基本操作。交易进程运行时不直接写普通文件日志,而是写到内存环形缓冲区里再异步落盘,否则一次磁盘阻塞就能让整个交易停顿几毫秒。
2.3 机房与网络:距离决定物理上限
很多人低估了物理距离的影响。光在光纤里的速度大约是每微秒0.3米,但实际网络延迟远不止这个,因为每个路由器都会引入微秒到几十微秒的转发延迟。好的托管机房能把服务器放在离交易所机房最近的地方,只隔一台交换机的距离,这样网络往返可以压缩到几百微秒以内。如果你在普通办公室访问柜台系统,再快也要几毫秒,还要承担公网链路不稳定的风险。
2026年的主流做法是把策略服务器托管到交易所附近,通过专线或同城光纤与柜台系统互联。如果自己做不了机房托管,至少要和平台方确认它的服务器放在哪里、与交易所之间的延迟是多少。别小看这个信息,它决定了后续所有软件优化能兑现多少。我自己测过的案例里,从普通办公室搬进托管机房,同样的策略单笔延迟能下降五到八毫秒,这已经是十几个数量级的差距了。
网络调优方面,调整网卡队列数量、关闭中断合并、增大收发缓冲区,桩桩件件都能挤出一部分延迟。但这些属于部署阶段的事,前提是先把自己的服务器和交易所之间的物理距离缩到最短。
3. 软件层优化:行情处理与下单链路的两个主战场
3.1 行情处理:从“能收到”到“收得又稳又快”
行情接入是策略系统的第一道关口。很多人的行情处理是启动一个线程订阅接口,回调里直接解析数据、更新状态、推送信号,逻辑看似简单,实际上暗藏很多延迟放大器。
最大的问题是系统调用。每次从内核缓冲读取数据、每次线程切换都是有代价的。优化思路是减少不必要的数据复制,尽量在用户态直接处理网络数据。常用的做法是使用内存映射或共享内存,让多个进程共享同一份行情数据,避免频繁拷贝。更进一步可以用绕开内核协议栈的方式直接操作网卡数据,但这属于较高门槛的玩法,适合已经有稳定系统后再考虑。
线程与CPU的绑定也很关键。行情线程、策略线程、下单线程应该分别绑定到不同的CPU核心上,避免系统自动调度导致缓存失效和上下文切换。数据在核心间迁移的代价可能高达上百微秒,对于微秒级优化的目标来说就是灾难性的。
我写行情处理主循环时习惯保持“一路流水线”的思想,从网卡收包到内存队列再到策略引擎,中间不打断、不等待、不落盘。队列采用无锁环形缓冲,单生产者单消费者模式,避免锁竞争。下面是一个简化示例,展示核心循环的骨架:
// 行情处理主循环:单线程、绑定CPU核心、无锁环形队列 void quoteLoop() { // 绑定当前线程到指定CPU核心 bindToCore(3); // 预分配行情对象池,避免关键路径分配内存 QuotePool& qpool = QuotePool::instance(); while (running) { // 从共享内存环形队列获取原始行情包 RawPacket* pkt = shmRing->acquire(); if (pkt == nullptr) { // 无数据时短暂自旋,不使用阻塞等待 continue; } // 快速解析:跳过协议头,直接定位关键字段 QuoteSnapshot& snap = qpool.next(); parseQuote(pkt->payload, snap); // 推送到策略引擎的输入队列 stratInputQueue->push(snap); // 释放原始数据槽位 shmRing->release(pkt); } }这段代码的关键点有三个:线程绑定保证确定性;自旋等待避免休眠切换;对象池避免内存分配。这三个细节对延迟的影响远比很多人想象得大,我在实际应用中把行情解析到策略输入的延迟从几十微秒降到了几个微秒。
另外一个容易被忽略的地方是行情快照的使用。很多策略只关心最新买一卖一,但盘口深度、逐笔成交和委托队列的微结构变化才是日内交易需要抢的信息。能不能在几微秒内完成所有这些状态的更新,决定了策略的决策质量。
3.2 下单链路:减少一个字节也是减少一个微秒
行情处理决定你“看”得多快,下单链路决定你“动”得多快。多数开源或商业软件的下单流程是:策略信号出来—封装对象—序列化成字节—调用接口发送—等待柜台回报。这里面每一步都藏着可以压缩的空间。
序列化是第一个关注点。不要用通用序列化框架,它们是给跨语言通信设计的,对字段做了很多冗余标记。交易系统里用固定格式的二进制协议,字段顺序、字节长度全部提前约定好,发送时一次性组包,尽量复用缓冲区。我见过有人用JSON格式给柜台接口下单,结构清晰但延迟多出上百微秒,这对日内高频来说完全不划算。
内存复用也是重点。每次下单新建一个对象、组装一个字符串,会产生大量临时内存,触发GC或堆分配器锁竞争。交易链路应该在一开始就预分配N份订单对象,循环复用。尤其像Java和C#这类带GC的语言,防止在关键路径上产生垃圾对象是最基本的要求,否则系统运行一段时间后GC停顿就会引发延迟尖峰。
订单状态机要设计得足够精简。从创建订单、发送、部分成交、全部成交、拒绝到撤单,每种状态转换都要有明确的处理函数,不能用一堆if-else在每次回报里临时判断。更严格的方案是把订单状态做成事件驱动,每个事件直接调用对应handler,减少分支预测的开销。
举个例子说明“预组装”的思路:在策略启动阶段,把固定字段(账户、合约、买卖方向)全部组装成二进制模板,只有价格和数量是动态变化。下单时复制模板,替换价格和数量,直接发送。这样既能利用CPU缓存的局部性,也避免了每次重新编码。
// 订单快速发送:复用模板,避免重复组装 bool sendFastOrder(OrderRef& ref, double price, int volume) { // 从对象池取一块预填充的缓冲区 OrderFrame* frame = orderPool.alloc(); frame->copyOnTemplate(price, volume); // 模板复制+动态字段替换 // 一次性写网卡,直接放入发送队列 int ret = gateway->send(frame->bytes(), frame->size()); if (ret != 0) { orderPool.release(frame); return false; } // 注册本地订单映射,便于快速处理回报 orderMap.insert(ref, frame); return true; }这样优化的效果是下单调用本身从毫秒级降到了微秒级,之后瓶颈几乎都集中在网络和柜台处理上。
3.3 时间同步与日志:平时不起眼的隐形杀手
日内交易系统的日志和时间戳经常被忽略,但它们对系统稳定性的影响是决定性的。
时间同步问题来自系统时钟的漂移。普通NTP同步的精度在毫秒级,但对延迟测量来说,多台机器之间哪怕只差几毫秒,统计数据就没有意义了。更麻烦的是,如果系统时间发生跳变,可能导致策略里基于时间的逻辑全部错乱。至少要用PTP或高精度时间服务来同步,让所有计算和数据打点基于统一的时钟源,并把时间校正的频率控制在不会引起跳变的范围内。
日志之所以成为隐形杀手,是因为很多人习惯在每笔成交、每次回报后写日志,普通文件写入在磁盘繁忙时可能阻塞几十毫秒甚至几百毫秒。交易进程里绝不能这么干。应该把日志输出做成一个异步线程,交易主循环只是把日志记录写入内存环形缓冲区,由独立线程批量落盘。这样就算磁盘出现瞬时瓶颈,交易链路也不会被卡住。
我在搭系统时把日志分成了三个级别:异常日志,必须立即落盘;交易日志,异步批量写入;调试日志,默认关闭,只在排查问题时启用。这种分级能节省大量不必要的IO开销。
4. 一种可落地的低延迟系统参考方案
4.1 一套可以用到2026年的参考架构
结合前面的分析,我给出一套个人认为性价比最高的参考架构,适合日内中高频交易团队。
行情层用共享内存总线接收原始行情,行情处理进程负责解析和广播,策略引擎通过订阅拿到所需的行情数据。策略引擎单独部署,可以采用多策略并行,但每个策略实例独占一个核心。订单网关负责与柜台系统通信,统一管理订单发送、回报分发、撤单处理。辅助模块包括风控引擎、监控系统、异步日志和快照持久化,它们都跑在独立核心上,不干扰主链路。
这里的核心思想是“主交易链路越短越好”:行情解析进程、策略进程、订单网关之间通过共享内存或低延迟消息队列直连,不经过网络协议栈中转。整条链路的延迟预算可以控制在1~2毫秒以内,其中行情传输占300~500微秒,策略计算占200~500微秒,订单发送到柜台占500微秒左右。如果再加上托管机房的网络优势,和交易所之间的延迟可以压缩到几百微秒。
4.2 具体配置清单与调优步骤
先给一套低配和一套高配的参考方案,大家根据资金承受能力选。
低配方案适合个人或小团队:一台主频较高的硬件服务器,32GB内存,多队列网卡,系统盘SSD加独立日志盘NVMe。软件层面采用Linux操作系统,行情处理、策略、下单三个进程分别绑定不同核心,共享内存队列通信,日志异步落盘。
高配方案适合有稳定资金规模的团队:双机热备架构,主交易机用高主频处理器和高频内存,网络通过网卡直连或者专用低延迟网络方案,配合千兆甚至万兆内网互联。柜台接口直接部署在同一机房或同一机柜,减少物理跳数。监控节点独立部署,不占交易机资源。
调优步骤我建议按下面六步执行,顺序很重要:
第一步,记录基线。在所有优化之前,先打点统计当前的平均延迟、P99和最大延迟,作为对照。没有基线就动手优化,最后很难判断哪里真正提升了。
第二步,调整线程与核心绑定。把所有关键线程固定在指定CPU核心上,防止线程漂移。
第三步,优化队列和锁。把关键路径上的阻塞队列换成无锁队列,有锁结构尽量改成无锁结构,或者用读写锁替代互斥锁。
第四步,调整内核网络参数。增大网卡环形缓冲区,调整中断合并策略,必要时开启网卡多队列,并设置队列和核心的亲和关系。
第五步,处理写盘问题。所有交易日志和行情落盘都改为异步或周期批量写入,降低IO对主链路的影响。
第六步,重新测量并固化。优化后重新打点,把结果与基线对比,如果平均延迟和P99都明显改善,就把配置文档固化下来,后续每次变更都走同样的流程。
调优的前提是在压力足够大的情况下测试。只用几百条行情测出来的数据没有参考意义,要用历史重复行情或模拟行情发生器,把系统推到接近峰值的流量下,才能暴露真实的延迟尖峰。
4.3 验证方法:别用“感觉变快了”下结论
很多人调优后喜欢凭感觉说“好像快了不少”,这对交易系统来说是不可接受的。我习惯用延迟分布来验证,统计P50、P90、P99、P99.9四档数据,同时记录最大值和平均值。
具体做法是在四个关键位置打时间戳点:行情进入共享内存、策略拿到行情数据、策略输出下单信号、柜台返回订单回报。把这四个点之间的时间差全部记录并统计,就能定位延迟主要消耗在哪里。
另外,用历史行情回放来验证是一个很有效的方案。把一段完整的历史行情数据按原速或者提速回放,驱动当前的策略系统,只要输入一致,两次回放之间的延迟对比就非常有意义。再加上模拟柜台响应,整个闭环就能在本地完成验证。
5. 常见问题排查与踩坑记录
5.1 我反复遇到的四个坑
第一个坑是延迟尖峰。某次优化之后,平均延迟变得很好,但每天总有几次P99特别高,查了很久发现是其他进程周期性触发了内存分配,导致关键线程被CPU调度打断。解决方案是把系统里无关进程全部赶走,交易机只跑交易相关的东西,并用CPU隔离给关键线程保留专属核心。
第二个坑是日志阻塞。我最初图省事,直接在回报处理函数里写日志,某次行情剧烈波动时,磁盘写入速度跟不上,整个交易线程被卡了上百毫秒。改成异步日志后问题彻底消失。教训是交易路径上绝不能出现同步IO。
第三个坑是网卡中断不均匀。多队列网卡配了四个队列,但默认情况下中断全部集中到了第一个CPU核心上,导致那核心忙不过来,其他核心闲着。手动把队列绑定到不同核心之后,延迟下降了将近一倍。
第四个坑是系统时钟跳变。NTP同步时系统时间向前跳了整整一秒,导致策略里所有基于时间戳的判断全部偏离。后来我把时间源换成高精度设备,并设置时钟逐步调整而不是直接跳跃,才把这个隐患消除。
5.2 快速定位问题的排查技巧
当延迟突然变高时,最快的排查方法是分步打点。先在行情接收处记录时间戳,再到策略输入处记录,再到下单发送处记录,比较三个环节的耗时变化。多跑几轮之后,系统会自动把异常样本对应的环节亮出来。
网络层面的问题,优先看丢包和TCP重传率。如果出现TCP重传,基本可以断定链路不稳,优先排查物理线路和交换机端口。应用层面的问题,优先抓取进程CPU使用率和线程调度情况,看是否有核心过载或者频繁上下文切换。
对于延迟尖峰类问题,有个比较实用的小技巧:连续记录一段时间内的每次延迟数据,打印延迟最高的前100个样本,逐个回看它们发生前后的系统状态,很多原因一眼就能发现,比如日志写盘、GC暂停、其他进程抢占等。
5.3 常见问题速查表
| 症状 | 可能原因 | 解决思路 |
|---|---|---|
| 平均延迟逐年升高 | 磁盘碎片化、系统组件升级引入额外检查 | 监控磁盘IO和系统调用次数,精简启动项 |
| P99偶尔暴涨 | 关键线程被调度、GC暂停、内存分配 | 固定核心、避免关键路径分配内存、调整GC参数 |
| 网络延迟忽高忽低 | 公网链路波动、路由器拥塞 | 迁移托管机房,尽量缩短物理距离 |
| 下单后回报迟迟不到 | 柜台接口慢、网络缓冲区拥塞 | 抓包确认往返时间,联系柜台通道管理员优化 |
| 行情和策略不同步 | 多进程时钟不一致 | 统一时间源,使用PTP或专用时间同步 |
| 系统运行几天后变慢 | 内存碎片化、文件句柄泄漏 | 定期监控内存分配数量,使用对象池复用资源 |
| 高流量下单机CPU满载 | 中断集中、逻辑过于膨胀 | 调整网卡队列绑定,拆分独立进程分摊负载 |
这张表是我每次升级系统时都会拿出来对照的检查清单,建议大家把自己的踩坑记录也整理成类似的速查表,排查效率会高很多。
最后再分享一个小技巧:不要一上来就追求极致微秒,先把明显能砍掉的几十毫秒砍掉,收益远比你想象的大。我曾经帮人优化过一套系统,最初延迟在30毫秒,只是把日志从同步改成异步、把网络链路从公网迁到托管机房,就降到了3毫秒以内,连策略代码都没碰一下。方向对了,比单纯堆配置重要得多。另外,始终把监控放在功能前面,没有观测的系统,优化就是闭眼开车。