第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 三种订单类型的知识体系
下面这张图,是我自己整理的知识结构。你可以看到三种订单类型在整个交易系统中的位置和关系。
27.5 实战中的选择建议
这三种订单类型,在实际做市商系统中怎么选?我个人的经验是这样的:
- 风控场景:用条件订单。止损止盈是底线,必须优先保障。
- 大单执行:用 TWAP 或 VWAP。如果品种流动性好,TWAP 就够了;如果流动性一般,VWAP 更优。
- 混合使用:我见过最成熟的系统,是把条件订单和算法订单结合起来。比如:TWAP 执行过程中,如果价格跌破止损线,立即触发止损单。
一个小技巧:在开发这些订单类型时,建议先实现一个「模拟模式」。在模拟模式下,订单不会真的发到交易所,而是记录执行路径和成交价格。这样你可以回测策略,避免真金白银踩坑。
好了,这一章的内容就到这里。三种订单类型各有适用场景,关键是根据你的交易品种和市场环境来选。下一章我们会聊更高级的订单路由策略,到时候再细说。
交易系统化学习资料 微信Strategy888888