第27章:高级订单类型:条件订单与算法交易

做市商系统里,普通限价单和市价单只是基本功。真正让系统拉开差距的,是那些高级订单类型。我个人习惯把这类订单叫做「智能订单」——它们不是简单地报个价格等成交,而是带着策略逻辑去执行。

今天咱们重点聊三种:条件订单(Stop Loss/Take Profit)、TWAP 和 VWAP。这三种订单,我在不同项目里都踩过坑,也积累了一些实战经验,分享给你。

27.1 条件订单:止损与止盈

条件订单,说白了就是「当市场达到某个条件时,自动触发一个动作」。最常见的两种:止损单(Stop Loss)和止盈单(Take Profit)。

嗯,这里要注意:条件订单不是立即成交的订单,它是一个触发器。触发后,系统会生成一个市价单或限价单去执行。

27.1.1 止损单(Stop Loss)

止损单的逻辑很简单:当市场价格跌破某个价位时,立即卖出(做多场景)。目的是限制亏损。

我曾经在开发一个期权做市系统时,遇到过一个大坑:止损单触发后,如果市场流动性不足,市价单会以极差的价格成交。那次我们亏了不少钱。

所以后来我建议:止损单最好配合限价使用,或者设置一个滑点容忍度。

// 止损单核心逻辑(伪代码)
class StopLossOrder {
    double triggerPrice;   // 触发价格
    double limitPrice;     // 限价(可选)
    double quantity;       // 数量
    OrderSide side;        // 买卖方向
    
    bool checkTrigger(double currentPrice) {
        if (side == LONG) {
            return currentPrice <= triggerPrice;
        } else {
            return currentPrice >= triggerPrice;
        }
    }
    
    Order generateMarketOrder() {
        // 生成市价单或限价单
        return new MarketOrder(side, quantity);
    }
}

27.1.2 止盈单(Take Profit)

止盈单和止损单正好相反。当价格涨到目标位时,自动平仓获利。

你想想看,做市商每天处理成千上万笔交易,如果每笔都手动盯盘止盈,那根本不可能。所以止盈单是自动化交易的基础组件。

关键点:止损和止盈的触发价格,建议留一个缓冲区间(buffer)。比如止损价是100,实际触发价可以设在99.98。这样可以避免价格刚好在边界震荡时反复触发。

27.2 时间加权平均价格算法(TWAP)

TWAP 的全称是 Time-Weighted Average Price。它的目标很简单:在指定时间内,把大单拆成小单,均匀地执行。

为什么要用 TWAP?因为大单直接砸进去,会把市场砸出个大坑,成交价格很差。TWAP 就是为了「隐藏意图」,让市场感觉不到你在大量买入或卖出。

27.2.1 TWAP 的核心逻辑

TWAP 把总时间分成 N 个等长的时间片,每个时间片执行等量的订单。

// TWAP 算法核心逻辑
class TWAPExecutor {
    double totalQuantity;    // 总数量
    int totalSeconds;        // 总时间(秒)
    int sliceSeconds;        // 每个时间片长度(秒)
    
    double getSliceQuantity() {
        int slices = totalSeconds / sliceSeconds;
        return totalQuantity / slices;
    }
    
    void executeSlice() {
        double qty = getSliceQuantity();
        // 发送限价单或市价单
        sendOrder(qty);
    }
}

举个例子:你想在 10 分钟内买入 1000 个 ETH。TWAP 会把 10 分钟分成 10 个 1 分钟的时间片,每个时间片只买 100 个 ETH。

实战技巧:我建议 TWAP 的时间片长度不要固定死。可以加入随机偏移,比如 55-65 秒之间随机。这样更不容易被市场察觉你的交易模式。

27.2.2 TWAP 的优缺点

优点 缺点
实现简单,逻辑清晰 不考虑市场成交量变化
适合流动性较好的品种 在成交量稀疏时段效果差
执行成本可预测 无法利用流动性好的时机

27.3 成交量加权平均价格算法(VWAP)

VWAP 比 TWAP 更聪明一些。它不只是均匀地按时间拆分订单,而是根据市场的成交量分布来分配订单量。

说白了:市场成交量大的时候,我多买点;成交量小的时候,我少买点。这样我的订单对市场的影响更小,成交价格也更接近市场均价。

27.3.1 VWAP 的核心逻辑

VWAP 需要历史成交量数据作为参考。通常我们会取过去 5-10 个交易日的成交量分布,预测今天的成交量曲线。

// VWAP 算法核心逻辑
class VWAPExecutor {
    double totalQuantity;
    vector<double> volumeProfile;  // 历史成交量分布
    
    double getSliceQuantity(int timeIndex) {
        double totalVolume = sum(volumeProfile);
        double volumeRatio = volumeProfile[timeIndex] / totalVolume;
        return totalQuantity * volumeRatio;
    }
    
    void executeSlice(int timeIndex) {
        double qty = getSliceQuantity(timeIndex);
        // 根据当前市场深度调整价格
        double price = getAdjustedPrice(qty);
        sendLimitOrder(price, qty);
    }
}

注意:VWAP 依赖历史数据。如果今天市场出现异常事件(比如突发新闻),历史成交量分布可能完全失效。我曾经在某个币种上吃过这个亏——那天成交量分布完全变了,VWAP 执行效果很差。

27.3.2 VWAP vs TWAP 对比

维度 TWAP VWAP
拆分依据 时间均匀 成交量分布
市场影响 中等 较小
实现复杂度 低 中
适用场景 流动性好、波动小 流动性一般、有规律

27.4 三种订单类型的知识体系

下面这张图,是我自己整理的知识结构。你可以看到三种订单类型在整个交易系统中的位置和关系。

高级订单类型知识体系 条件订单 TWAP VWAP 止损单 (Stop Loss) 止盈单 (Take Profit) 时间均匀拆分 固定时间片执行 成交量分布拆分 历史数据驱动 共同目标:降低市场冲击,隐藏交易意图 实现层:订单管理引擎 + 风控模块 + 行情接口 (限价单/市价单生成、滑点控制、重试机制)

27.5 实战中的选择建议

这三种订单类型,在实际做市商系统中怎么选?我个人的经验是这样的:

  • 风控场景:用条件订单。止损止盈是底线,必须优先保障。
  • 大单执行:用 TWAP 或 VWAP。如果品种流动性好,TWAP 就够了;如果流动性一般,VWAP 更优。
  • 混合使用:我见过最成熟的系统,是把条件订单和算法订单结合起来。比如:TWAP 执行过程中,如果价格跌破止损线,立即触发止损单。

一个小技巧:在开发这些订单类型时,建议先实现一个「模拟模式」。在模拟模式下,订单不会真的发到交易所,而是记录执行路径和成交价格。这样你可以回测策略,避免真金白银踩坑。

好了,这一章的内容就到这里。三种订单类型各有适用场景,关键是根据你的交易品种和市场环境来选。下一章我们会聊更高级的订单路由策略,到时候再细说。


无相订单流研究社 微信Lucian808555