3、订单前置检查:资金检查、持仓检查、频率限制、价格偏离度检查、自成交预防

订单前置检查,说白了就是交易系统的大门保安。

每一笔订单进来,都得先过我这五道关。过不去?直接拒掉,连交易所的门都摸不到。

我做了这么多年高频风控,见过太多因为前置检查没做好而爆仓的案例。嗯,今天就把这五道关的细节掰开揉碎了讲给你听。

3.1 资金检查:别让订单变成"空头支票"

资金检查是第一道防线。你的账户里有多少钱,决定了你能开多大的仓位。

我个人习惯把资金检查分成两步:

  • 冻结资金检查:当前订单需要的保证金 + 手续费,账户可用资金够不够?
  • 动态权益检查:算上持仓浮动盈亏后,账户权益是否仍然充足?

我在项目中遇到过一个问题:某客户账户里明明有100万,但连续下了10笔大单,每笔都需要20万保证金。按说够啊?

但问题出在——系统只检查了单笔订单的资金,没考虑多笔订单同时挂单时的资金占用。结果10笔订单同时挂出去,保证金占用200万,直接穿仓了。

所以我的做法是:

// 伪代码示例:资金检查逻辑
bool checkFunds(Order order) {
    // 1. 计算当前订单所需保证金
    double requiredMargin = order.quantity * order.price * marginRate;
    
    // 2. 计算已占用保证金(含其他挂单)
    double usedMargin = getUsedMargin(accountId);
    
    // 3. 计算可用资金
    double available = account.balance - usedMargin;
    
    // 4. 检查是否足够
    if (available < requiredMargin) {
        return false; // 资金不足,拒绝
    }
    return true;
}
注意:资金检查一定要考虑"在途订单"。也就是那些已经提交但还没成交的订单,它们也在占用你的资金。

3.2 持仓检查:别把自己"撑死"

持仓检查,说白了就是看看你手里已经有多少货了。

期货交易有持仓限额,你最多只能持有一定数量的合约。超过了?交易所会强制平仓,那滋味可不好受。

我一般把持仓检查分为三个维度:

  • 单合约持仓上限:某个合约最多能持有多少手
  • 多空双向持仓:同一合约的多单和空单是否允许同时存在
  • 总持仓市值:所有合约的总市值不能超过某个阈值

举个例子:

合约 当前持仓 持仓上限 是否允许开仓
螺纹钢2410 多单 800手 1000手 ✅ 可以开200手
铁矿石2409 空单 500手 500手 ❌ 已达上限

我曾经遇到过一个客户,他同时持有了螺纹钢的多单和空单。你想想看,这其实就是在锁仓,白白浪费保证金。所以我的系统里会加一条规则:同一合约的多空持仓,超过一定比例就报警。

3.3 频率限制:别把交易所"刷爆"

频率限制,这是高频交易的核心风控点。

交易所对报单频率有严格限制。比如上期所,每秒最多报单多少笔?每家交易所不一样,但一旦超了,轻则警告,重则限制交易。

我的做法是:

  • 按账户维度限频:每个账户每秒最多N笔订单
  • 按合约维度限频:每个合约每秒最多M笔订单
  • 按IP维度限频:每个交易IP每秒最多K笔订单
核心指标:我个人习惯把频率限制的阈值设为交易所限制的80%。留点余量,别卡着上限跑,万一网络抖动一下,你就超了。

代码实现其实不复杂:

// 频率检查:滑动窗口算法
bool checkRateLimit(string accountId) {
    long now = getCurrentTimestamp();
    // 获取过去1秒内的订单数
    int count = getOrderCountInWindow(accountId, now - 1000, now);
    if (count >= MAX_ORDER_PER_SECOND) {
        return false; // 超频,拒绝
    }
    return true;
}

3.4 价格偏离度检查:别被"钓鱼单"坑了

价格偏离度检查,这个很多人会忽略。但我觉得它特别重要。

你想想看,如果当前螺纹钢的价格是3500元/吨,突然有人挂了个3000元的买单。这正常吗?

要么是手滑了,要么是恶意钓鱼。不管哪种情况,你的系统都不应该去成交这种单子。

我的检查逻辑是这样的:

  • 与最新成交价比较:偏离超过X%就拒绝
  • 与盘口价比较:偏离买一/卖一超过Y个tick就拒绝
  • 与理论价格比较:比如股指期货,可以跟现货指数比较,偏离超过Z%就拒绝
经验值:对于商品期货,我一般设偏离度上限为3%。对于股指期货,可以设到1%。太紧了容易误杀,太松了又防不住。

我曾经见过一个极端案例:某交易员在收盘前手滑,把"卖出100手"输成了"卖出10000手",价格还输错了。如果没有价格偏离度检查,这一单下去,账户直接归零。

3.5 自成交预防:别自己跟自己"打架"

自成交,就是你自己下的买单和卖单互相成交了。

这在高频交易里特别容易发生。你想想看,你的策略同时下了买单和卖单,如果价格区间重叠了,那不就自己跟自己成交了吗?

交易所是禁止自成交的,一旦发现,轻则罚款,重则取消交易资格。

我的预防策略:

  • 按账户隔离:同一账户的买单和卖单,价格区间不能重叠
  • 按策略隔离:不同策略之间,如果属于同一账户,也要检查
  • 按交易员隔离:同一交易员管理的多个账户,也要防自成交

具体实现上,我一般用"价格区间锁定":

// 自成交预防:检查买单和卖单的价格区间
bool preventSelfTrade(Order buyOrder, Order sellOrder) {
    // 如果买单价格 >= 卖单价格,就会自成交
    if (buyOrder.price >= sellOrder.price) {
        // 调整价格,或者拒绝其中一个订单
        return false;
    }
    return true;
}
注意:自成交预防不能只检查当前订单,还要检查所有挂单。比如你已经有了一笔卖单在挂着,现在新下一笔买单,也要检查会不会跟那笔卖单成交。

3.6 五道关的联动逻辑

这五道关不是独立的,它们需要联动起来。

我画了一张流程图,你看看就明白了:

订单前置检查五道关流程图 订单进入 ① 资金检查 ② 持仓检查 ③ 频率限制 ④ 价格偏离度检查 ⑤ 自成交预防 通过 → 发往交易所 拒绝订单

你看,订单进来后,依次经过这五道关。任何一道关没通过,直接拒绝,并记录日志。

为什么要按这个顺序?

资金检查和持仓检查是最基础的,先过。频率限制是为了保护系统,放中间。价格偏离度和自成交预防是精细控制,放最后。

这个顺序是我在实践中摸索出来的。一开始我把频率限制放最前面,结果发现很多订单因为频率被拒,但资金和持仓其实没问题,白白浪费了计算资源。

总结一下:订单前置检查不是简单的"检查-通过"逻辑,而是一个系统工程。每一道关都要考虑性能、准确性和容错性。我见过太多系统因为前置检查没做好,导致实盘时出大问题。

嗯,这五道关讲完了。你回去可以看看自己的系统,这五道关都齐了吗?有没有漏掉什么?

一个小建议:前置检查的日志一定要详细记录。哪天出了问题,查日志就能定位到是哪道关拦下来的。我每次排查问题,第一件事就是翻前置检查的日志。

公众号:蓝海资料掘金营,微信deep3321