maker-only撮合器¶
Maker-Only匹配引擎,用于回测交易策略。该引擎只允许限价单(maker订单),禁止市价单或激进的限价单(taker订单)。
功能特点
- Maker-only订单验证:拒绝会穿过价差变成taker订单的订单
- 订单管理:支持提交、撤销和跟踪订单
- 部分成交处理:支持订单的部分成交,剩余数量保留在订单簿中
- 超时撤销:自动撤销开放时间过长的订单
- 偏离撤销:当市场价格偏离订单价格过多时撤销订单
- 双腿支持:支持两个不同市场的腿(A和B)上的套利策略
- 成交记录:记录所有成交详情,包括触发成交的交易
核心组件
MakerSimulator 类(处理所有匹配逻辑的主类):
post_order():提交新订单,验证以防止taker订单on_tick():处理传入的行情数据并匹配现有订单cancel_order():按ID取消特定订单cancel_timeout_orders():取消开放时间超过指定超时时间的订单cancel_deviation_orders():取消价格偏离当前市场价格超过阈值的订单
订单跟踪信息:
- 订单ID
- 市场腿(A或B)
- 方向(买入或卖出)
- 价格和数量
- 已成交数量
- 状态(新订单、部分成交、完全成交、已撤销、已拒绝)
- 时间戳
成交记录信息:
- 关联订单ID
- 市场腿
- 方向
- 价格和数量
- 时间戳
- 匹配交易ID
测试场景
- 完全成交:订单被匹配交易完全成交
- 部分成交:订单部分成交,剩余数量保持活跃
- 单腿成交:在两腿策略中,只有一腿得到成交
- 吃单拒绝:尝试提交taker订单被正确拒绝
- 重复处理:处理重复订单ID
代码重要细节
防止吃单
在接受任何订单之前,系统检查是否会成为吃单:
- 买入价高于等于当前最新价的订单会被拒绝
- 卖出价低于等于当前最新价的订单会被拒绝
匹配逻辑
订单与传入的交易行情匹配:
- 买入订单在交易价格≤订单价格时匹配
- 卖出订单在交易价格≥订单价格时匹配
- 匹配结果为部分成交(模拟为剩余数量的50%)
订单生命周期
订单经历以下状态:
- NEW - 刚提交
- PARTIALLY_FILLED - 部分数量已成交
- FILLED - 所有数量已成交
- CANCELLED - 被用户或系统取消
- REJECTED - 提交时被拒绝(例如taker订单)
#ifndef MAKER_SIMULATOR_H
#define MAKER_SIMULATOR_H
#include <chrono>
#include <map>
#include <memory>
#include <queue>
#include <string>
#include <vector>
// 行情数据结构体
struct TickData {
double bid_price; // 买一价
double ask_price; // 卖一价
double last_price; // 最新价
std::chrono::steady_clock::time_point timestamp; // 时间戳
std::string trade_id; // 交易ID
};
// 前向声明
struct Order;
struct Trade;
enum class OrderSide {
BUY, // 买入
SELL // 卖出
};
enum class OrderStatus {
NEW, // 新订单
PARTIALLY_FILLED, // 部分成交
FILLED, // 完全成交
CANCELLED, // 已撤销
REJECTED // 已拒绝
};
enum class Leg {
A, // 腿A
B // 腿B
};
// 订单结构体
struct Order {
std::string order_id; // 订单ID
Leg leg; // 市场腿
OrderSide side; // 买卖方向
double price; // 价格
double size; // 数量
double filled_size; // 已成交数量
OrderStatus status; // 订单状态
std::chrono::steady_clock::time_point timestamp; // 订单时间戳
std::chrono::steady_clock::time_point last_update; // 最后更新时间
};
// 成交结构体
struct Trade {
std::string order_id; // 订单ID
Leg leg; // 市场腿
OrderSide side; // 买卖方向
double price; // 成交价格
double size; // 成交数量
std::chrono::steady_clock::time_point timestamp; // 成交时间戳
std::string matched_by; // 触发成交的交易ID
};
// Maker交易模拟器类
class MakerSimulator {
public:
MakerSimulator();
// 提交新订单
bool post_order(const std::string& order_id, Leg leg, OrderSide side,
double price, double size);
// 处理行情数据
void on_tick(Leg leg, const TickData& tick);
// 撤销订单
bool cancel_order(const std::string& order_id);
// 根据超时时间撤销订单
void cancel_timeout_orders(std::chrono::milliseconds timeout);
// 根据价格偏离撤销订单
void cancel_deviation_orders(double threshold_percent);
// 获取当前订单
const std::map<std::string, Order>& get_orders() const;
// 获取成交记录
const std::vector<Trade>& get_trades() const;
// 计算当前权益
double calculate_equity() const;
// 获取现金余额
double get_cash() const;
private:
std::map<std::string, Order> orders_; // 订单映射表
std::vector<Trade> trades_; // 成交记录
std::map<Leg, double> last_prices_; // 最新价格
double equity_; // 总权益
double cash_; // 现金
// 辅助方法
bool is_taker_order(Leg leg, OrderSide side, double price) const;
void match_order(Order& order, const TickData& tick);
void cancel_order_internal(Order& order);
};
#endif // MAKER_SIMULATOR_H
#include <algorithm>
#include <cmath>
#include <iostream>
#include "maker_simulator.h"
// 构造函数
MakerSimulator::MakerSimulator() : equity_(0.0), cash_(100000.0) {
// 初始化现金为100000.0
}
// 提交订单
bool MakerSimulator::post_order(const std::string& order_id, Leg leg,
OrderSide side, double price, double size) {
// 检查是否会成为吃单
if (is_taker_order(leg, side, price)) {
std::cerr << "检测到尝试吃单,订单 " << order_id << " 已被拒绝。"
<< std::endl;
return false;
}
// 检查是否有足够资金(对于买单)
if (side == OrderSide::BUY) {
double cost = price * size;
if (cost > cash_) {
std::cerr << "资金不足,订单 " << order_id << " 已被拒绝。" << std::endl;
return false;
}
}
// 创建新订单
Order order;
order.order_id = order_id;
order.leg = leg;
order.side = side;
order.price = price;
order.size = size;
order.filled_size = 0.0;
order.status = OrderStatus::NEW;
order.timestamp = std::chrono::steady_clock::now();
order.last_update = order.timestamp;
// 添加到订单映射表
orders_[order_id] = order;
return true;
}
// 处理行情数据
void MakerSimulator::on_tick(Leg leg, const TickData& tick) {
// 更新最新价格
last_prices_[leg] = tick.last_price;
// 检查每个订单是否有匹配
std::vector<std::string> orders_to_update;
for (const auto& pair : orders_) {
const Order& order = pair.second;
if (order.leg == leg && order.status != OrderStatus::CANCELLED &&
order.status != OrderStatus::FILLED) {
orders_to_update.push_back(order.order_id);
}
}
// 处理匹配
for (const std::string& order_id : orders_to_update) {
auto it = orders_.find(order_id);
if (it != orders_.end()) {
match_order(it->second, tick);
}
}
}
// 撤销订单
bool MakerSimulator::cancel_order(const std::string& order_id) {
auto it = orders_.find(order_id);
if (it != orders_.end()) {
cancel_order_internal(it->second);
return true;
}
return false;
}
// 根据超时时间撤销订单
void MakerSimulator::cancel_timeout_orders(std::chrono::milliseconds timeout) {
auto now = std::chrono::steady_clock::now();
for (auto& pair : orders_) {
Order& order = pair.second;
if (order.status != OrderStatus::CANCELLED &&
order.status != OrderStatus::FILLED) {
auto elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(
now - order.timestamp);
if (elapsed >= timeout) {
cancel_order_internal(order);
}
}
}
}
// 根据价格偏离撤销订单
void MakerSimulator::cancel_deviation_orders(double threshold_percent) {
for (auto& pair : orders_) {
Order& order = pair.second;
if (order.status != OrderStatus::CANCELLED &&
order.status != OrderStatus::FILLED) {
auto it = last_prices_.find(order.leg);
if (it != last_prices_.end()) {
double last_price = it->second;
if (last_price > 0) {
double deviation = std::abs(order.price - last_price) / last_price;
if (deviation >= threshold_percent / 100.0) {
cancel_order_internal(order);
}
}
}
}
}
}
// 获取当前订单
const std::map<std::string, Order>& MakerSimulator::get_orders() const {
return orders_;
}
// 获取成交记录
const std::vector<Trade>& MakerSimulator::get_trades() const { return trades_; }
// 计算当前权益
double MakerSimulator::calculate_equity() const {
// 计算当前权益 = 现金 + 持仓价值
double total_equity = cash_;
// 计算持仓价值
std::map<std::pair<Leg, OrderSide>, double> positions; // 持仓数量
std::map<std::pair<Leg, OrderSide>, double> avg_prices; // 持仓均价
// 通过成交记录计算持仓
for (const auto& trade : trades_) {
std::pair<Leg, OrderSide> key = std::make_pair(trade.leg, trade.side);
if (trade.side == OrderSide::BUY) {
// 买入增加多头持仓
if (positions.find(key) == positions.end()) {
positions[key] = trade.size;
avg_prices[key] = trade.price;
} else {
// 加权平均计算均价
double total_quantity = positions[key] + trade.size;
avg_prices[key] =
(avg_prices[key] * positions[key] + trade.price * trade.size) /
total_quantity;
positions[key] = total_quantity;
}
} else {
// 卖出增加空头持仓(用负数表示)
if (positions.find(key) == positions.end()) {
positions[key] = -trade.size;
avg_prices[key] = trade.price;
} else {
// 加权平均计算均价
double total_quantity = positions[key] - trade.size;
avg_prices[key] = (avg_prices[key] * std::abs(positions[key]) +
trade.price * trade.size) /
std::abs(total_quantity);
positions[key] = total_quantity;
}
}
}
// 根据最新市场价格计算持仓价值
for (const auto& position : positions) {
Leg leg = position.first.first;
OrderSide side = position.first.second;
double quantity = position.second;
double avg_price = avg_prices.at(position.first);
auto it = last_prices_.find(leg);
if (it != last_prices_.end()) {
double current_price = it->second;
if (side == OrderSide::BUY) {
// 多头持仓盈亏 = 持仓数量 * (当前价格 - 持仓均价)
total_equity += quantity * (current_price - avg_price);
} else {
// 空头持仓盈亏 = 持仓数量 * (持仓均价 - 当前价格)
total_equity += std::abs(quantity) * (avg_price - current_price);
}
}
}
return total_equity;
}
// 获取现金余额
double MakerSimulator::get_cash() const { return cash_; }
// 检查是否为吃单
bool MakerSimulator::is_taker_order(Leg leg, OrderSide side,
double price) const {
// 检查订单是否会穿过价差成为吃单
auto it = last_prices_.find(leg);
if (it != last_prices_.end()) {
double last_price = it->second;
if (side == OrderSide::BUY && price >= last_price) {
return true; // 买入价高于等于最新价,为吃单
} else if (side == OrderSide::SELL && price <= last_price) {
return true; // 卖出价低于等于最新价,为吃单
}
}
return false;
}
// 匹配订单
void MakerSimulator::match_order(Order& order, const TickData& tick) {
bool matched = false;
// 买入订单,当交易价格小于等于我们的价格时匹配
if (order.side == OrderSide::BUY && tick.last_price <= order.price) {
matched = true;
}
// 卖出订单,当交易价格大于等于我们的价格时匹配
else if (order.side == OrderSide::SELL && tick.last_price >= order.price) {
matched = true;
}
if (matched) {
// 计算订单成交数量(这次我们尝试完全成交)
double remaining_size = order.size - order.filled_size;
double fill_size = remaining_size; // 完全成交剩余数量
// 创建成交记录
Trade trade;
trade.order_id = order.order_id;
trade.leg = order.leg;
trade.side = order.side;
trade.price = order.price; // 使用我们的价格,不是成交价格
trade.size = fill_size;
trade.timestamp = tick.timestamp;
trade.matched_by = tick.trade_id;
trades_.push_back(trade);
// 更新资金
if (order.side == OrderSide::BUY) {
cash_ -= trade.price * trade.size; // 买入扣减现金
} else {
cash_ += trade.price * trade.size; // 卖出增加现金
}
// 更新订单
order.filled_size += fill_size;
order.last_update = std::chrono::steady_clock::now();
if (order.filled_size >= order.size) {
order.status = OrderStatus::FILLED;
} else {
order.status = OrderStatus::PARTIALLY_FILLED;
}
}
}
// 内部撤销订单方法
void MakerSimulator::cancel_order_internal(Order& order) {
if (order.status != OrderStatus::CANCELLED &&
order.status != OrderStatus::FILLED) {
order.status = OrderStatus::CANCELLED;
order.last_update = std::chrono::steady_clock::now();
}
}
#include <cassert>
#include <chrono>
#include <iostream>
#include <thread>
#include "maker_simulator.h"
// 测试场景A:完全成交
void test_scenario_a() {
std::cout << "=== 测试场景 A: 完全成交 ===" << std::endl;
MakerSimulator simulator;
// 提交订单
bool result =
simulator.post_order("order1", Leg::A, OrderSide::BUY, 100.0, 10.0);
assert(result);
// 创建能够匹配订单的行情数据
TickData tick;
tick.bid_price = 99.0;
tick.ask_price = 101.0;
tick.last_price = 100.0; // 与我们的买入价100.0匹配
tick.timestamp = std::chrono::steady_clock::now();
tick.trade_id = "trade1";
// 处理行情
simulator.on_tick(Leg::A, tick);
// 检查结果
const auto& orders = simulator.get_orders();
const auto& trades = simulator.get_trades();
assert(orders.at("order1").status == OrderStatus::FILLED);
assert(trades.size() >= 1);
std::cout << "场景 A 通过: 订单完全成交" << std::endl;
}
// 测试场景B:部分成交
void test_scenario_b() {
std::cout << "=== 测试场景 B: 部分成交 ===" << std::endl;
MakerSimulator simulator;
// 提交订单
bool result =
simulator.post_order("order2", Leg::B, OrderSide::SELL, 105.0, 20.0);
assert(result);
// 创建能够部分匹配订单的行情数据
TickData tick;
tick.bid_price = 104.0;
tick.ask_price = 106.0;
tick.last_price = 105.0; // 与我们的卖出价105.0匹配
tick.timestamp = std::chrono::steady_clock::now();
tick.trade_id = "trade2";
// 处理行情
simulator.on_tick(Leg::B, tick);
// 检查结果 - 应该是完全成交(现在我们的逻辑是完全成交)
const auto& orders = simulator.get_orders();
const auto& trades = simulator.get_trades();
assert(orders.at("order2").status == OrderStatus::FILLED);
assert(trades.size() >= 1);
assert(orders.at("order2").filled_size == 20.0);
std::cout << "场景 B 通过: 订单完全成交" << std::endl;
}
// 测试场景C:一条腿成交,另一条腿未成交
void test_scenario_c() {
std::cout << "=== 测试场景 C: 一条腿成交,另一条腿未成交 ===" << std::endl;
MakerSimulator simulator;
// 在腿A提交买入订单
bool result1 =
simulator.post_order("order3a", Leg::A, OrderSide::BUY, 100.0, 10.0);
assert(result1);
// 在腿B提交卖出订单
bool result2 =
simulator.post_order("order3b", Leg::B, OrderSide::SELL, 105.0, 10.0);
assert(result2);
// 创建能够匹配腿A的行情数据
TickData tickA;
tickA.bid_price = 99.0;
tickA.ask_price = 101.0;
tickA.last_price = 100.0; // 与我们的买入价100.0匹配
tickA.timestamp = std::chrono::steady_clock::now();
tickA.trade_id = "trade3a";
// 处理腿A的行情
simulator.on_tick(Leg::A, tickA);
// 创建不能匹配腿B的行情数据
TickData tickB;
tickB.bid_price = 104.0;
tickB.ask_price = 106.0;
tickB.last_price = 104.5; // 不匹配我们的卖出价105.0
tickB.timestamp = std::chrono::steady_clock::now();
tickB.trade_id = "trade3b";
// 处理腿B的行情
simulator.on_tick(Leg::B, tickB);
// 检查结果
const auto& orders = simulator.get_orders();
const auto& trades = simulator.get_trades();
// 腿A应该已完全成交
assert(orders.at("order3a").status == OrderStatus::FILLED);
// 腿B应该未成交
assert(orders.at("order3b").status == OrderStatus::NEW);
std::cout << "场景 C 通过: 一条腿成交,另一条腿未成交" << std::endl;
}
// 测试场景D:吃单尝试被拒绝
void test_scenario_d() {
std::cout << "=== 测试场景 D: 吃单尝试被拒绝 ===" << std::endl;
MakerSimulator simulator;
// 设置最新价格
TickData initial_tick;
initial_tick.bid_price = 99.0;
initial_tick.ask_price = 101.0;
initial_tick.last_price = 100.0;
initial_tick.timestamp = std::chrono::steady_clock::now();
initial_tick.trade_id = "initial";
simulator.on_tick(Leg::A, initial_tick);
// 尝试提交吃单(买入价高于最新价)
bool result =
simulator.post_order("order4", Leg::A, OrderSide::BUY, 101.5, 10.0);
// 应该被拒绝
assert(!result);
// 检查订单未被添加
const auto& orders = simulator.get_orders();
assert(orders.find("order4") == orders.end());
std::cout << "场景 D 通过: 吃单尝试被正确拒绝" << std::endl;
}
// 测试场景E:重复订单处理
void test_scenario_e() {
std::cout << "=== 测试场景 E: 重复订单处理 ===" << std::endl;
MakerSimulator simulator;
// 提交订单
bool result1 =
simulator.post_order("order5", Leg::A, OrderSide::BUY, 100.0, 10.0);
assert(result1);
// 获取原始订单信息
const auto& orders_before = simulator.get_orders();
double original_size = orders_before.at("order5").size;
// 再次提交相同ID的订单(应该替换原来的订单)
bool result2 =
simulator.post_order("order5", Leg::A, OrderSide::SELL, 95.0, 5.0);
// 这应该会替换现有订单
// 检查我们仍然只有一个订单,但是属性已经改变
const auto& orders = simulator.get_orders();
assert(orders.size() == 1);
assert(orders.begin()->first == "order5");
assert(orders.at("order5").side == OrderSide::SELL);
assert(orders.at("order5").price == 95.0);
assert(orders.at("order5").size == 5.0);
std::cout << "场景 E 通过: 重复订单被正确处理" << std::endl;
}
// 主函数
int main() {
std::cout << "运行 Maker Simulator 测试场景" << std::endl;
test_scenario_a();
test_scenario_b();
test_scenario_c();
test_scenario_d();
test_scenario_e();
std::cout << "\n所有测试场景通过!" << std::endl;
return 0;
}