Skip to content

Latest commit

 

History

1 Commit

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

高频量化交易系统

项目介绍

高频量化交易系统 是一个基于 C++20 实现的量化交易系统模拟项目,主要面向低延迟交易场景,完整模拟了量化交易系统中客户端与交易所之间的核心交互流程。系统整体由**交易所端(Exchange)交易客户端端(Trading)**两大部分组成,涵盖了行情接收、策略决策、订单管理、风控校验、订单发送、撮合成交、订单响应以及市场行情回传等关键环节。

系统运行过程中,客户端首先接收市场行情,并根据策略决定是否下单或撤单;在正式发单前,请求会先经过 OrderManagerRiskManager 完成订单管理与风控检查;通过校验后,订单通过 TCP 发送至交易所端,由交易所完成订单接收、订单簿维护和撮合处理。撮合结果一方面以订单响应的形式返回客户端,另一方面以市场行情更新的形式继续发布,客户端再根据新的订单状态和市场状态进入下一轮决策,从而形成完整的交易闭环。

在技术实现上,项目采用现代 C++20 标准,结合多线程、无锁队列、TCP 通信、多播通信、内存优化等高性能设计手段,提升了系统的消息处理效率与整体吞吐能力。该项目体现了量化交易系统从行情驱动到撮合反馈的完整业务链路。

主要特点

  • 高性能: 使用无锁队列、内存池等技术确保低延迟
  • 多线程: 各主要组件在独立线程中运行,充分利用多核处理器
  • 网络通信: 支持TCP和多播通信,实现高效的数据传输
  • 模块化设计: 系统各组件高度模块化,便于扩展和维护
  • 风险管理: 内置风险控制机制,保障交易安全
  • 多种交易策略: 支持做市商(Market Maker)和流动性接受者(Liquidity Taker)等不同策略
  • 现代C++: 采用C++20标准,利用现代C++特性提高代码质量和性能

系统架构

系统分为以下几个主要模块:

1. 公共模块 (common)

提供了整个系统所需的基础设施和工具类:

  • 无锁队列 (lf_queue): 用于组件间的高性能通信
  • 内存池 (mem_pool): 高效的内存管理
  • 日志系统 (logging): 系统日志记录
  • 网络通信: 支持TCP和多播通信
  • 线程工具: 线程管理和同步
  • 时间工具: 高精度时间管理

2. 交易所模块 (exchange)

模拟了一个完整的交易所系统,包括:

  • 匹配引擎: 处理订单匹配和执行
  • 市场数据: 生成和发布市场数据
  • 订单服务器: 处理客户端订单请求

3. 交易客户端模块 (trading)

实现了交易策略和订单管理:

  • 交易引擎: 交易系统的核心,协调各组件工作
  • 市场数据消费者: 接收和处理市场数据
  • 订单网关: 发送订单到交易所
  • 策略组件: 包括市场做市商、流动性提供者、订单管理、风险管理、持仓管理和特征引擎

4. 性能测试模块 (benchmarks)

包含用于测试系统各组件性能的基准测试工具。

安装教程

环境要求

  • Linux操作系统(推荐Ubuntu 20.04或更高版本)
  • GCC 10.0或更高版本(支持C++20)
  • CMake 3.16或更高版本

补充:我们提供的源码是在 windows下以压缩包的形式,如何将 windows 中的文件和 Linux 中的文件共享。

如何在Linux中搭建Samba文件共享服务器

对于**.tar.gz的压缩包如何解压**

tar -xzvf fileName.tar.gz

如何打包并压缩

tar -czvf fileName.tar.gz fileName 

c 创建

v 显示过程(可不要)

f 指定文件名

编译步骤

  1. 进入项目目录

    cd cppquant
  2. 创建并进入构建目录

    mkdir build
    cd build
  3. 配置和编译项目

    cmake ..
    make -j4
  4. 运行测试(可选)

    ctest

使用说明

第一步启动交易所

./exchange_main

交易所程序启动

交易所程序启动后,把“撮合引擎、订单服务器、行情发布、快照模块、各自的日志线程”全都创建好了,并打印了线程的 CPU 绑定信息(线程名称,已经线程ID);

当前 to -1 表示不固定绑核,由系统调度。

第二步启动交易客户端

方式1:可运行提供的脚本

scripts/                      项目启动与测试脚本
  ├── build.sh                完整构建脚本(含 clean)
  ├── no_clean_build.sh       项目构建脚本,作用是:分别编译 Release 和 Debug 两个版本
  ├── run_exchange_and_clients.sh   一键启动交易所与客户端
  ├── run_clients.sh          启动交易客户端(可以批量启用多个,详解看脚本具体实现)
  └── run_benchmarks.sh       执行性能测试脚本
cd scripts
# 运行脚本
bash run_exchange_and_clients.sh

方式2:

可运行提供的脚本run_clients.sh

./trading_main CLIENT_ID ALGO_TYPE [CLIP_1 THRESH_1 MAX_ORDER_SIZE_1 MAX_POS_1 MAX_LOSS_1] [CLIP_2 THRESH_2 MAX_ORDER_SIZE_2 MAX_POS_2 MAX_LOSS_2] ...

# 示例
/*
启动 1 号交易客户端,并让它用 MAKER 做市策略运行;后面每 5 个数字是一组参数,给一个交易标的配置策略参数和风控参数。
./trading_main  1 MAKER \
                  100 0.6 150 300 -100 \
                  60 0.6 150 300 -100  \
                  150 0.5 250 600 -100 \
                  200 0.4 500 3000 -100 \
                  1000 0.9 5000 4000 -100 \
                  300 0.8 1500 3000 -100 \
                  50 0.7 150 300 -100 \
                  100 0.3 250 300 -100 
*/
#启动客户端5RANDOM 的作用就是主动往市场里打一些随机订单。                  
./trading_main 5 RANDOM

参数说明:

  • CLIENT_ID: 客户端标识符
  • ALGO_TYPE: 算法类型(MAKER/TAKER/RANDOM)
  • 后续参数以组为单位,每组包含5个参数,对应一个交易工具的配置:
    • CLIP_N: 价格剪裁参数,用于限制订单价格偏离市场价格的范围
    • THRESH_N: 阈值参数,用于决定交易策略的触发条件
    • MAX_ORDER_SIZE_N: 最大订单大小,用于风险控制
    • MAX_POS_N: 最大仓位大小,用于风险控制
    • MAX_LOSS_N: 最大允许损失,用于风险控制

启动客户端-RANDOM

5 号客户端已经成功启动,并且其核心业务线程和日志线程均已创建完成。后续操作是自动的,不需要我们继续进行输入。

  • 1.MarketDataConsumer 自动接收交易所发布的行情;
  • 2.TradeEngine 自动根据行情更新本地状态;
  • 3.MAKER 策略自动判断是否下单/撤单;
  • 4.OrderManagerRiskManager 自动做订单管理与风控检查;
  • 5.OrderGateway 自动把订单发给交易所;
  • 6.交易所自动撮合并返回响应;
  • 7.客户端再根据新行情和新订单状态继续下一轮决策;

交易所、客户端运行之后,各个核心模块各自输出运行日志。

日志文件

简单说明

├── exchange_main.log      # 交易所端日志,记录交易所主程序本身的启动信息,主线程的基本运行信息
├── exchange_market_data_publisher.log   # 记录交易所发布市场行情的过程,记录哪些盘口变化、成交信息被广播出去
├── exchange_matching_engine.log   # 订单有没有进入撮合引擎,撮合引擎有没有真正处理订单
├── exchange_order_server.log      # 客户端和交易所之间的订单通信是否正常
└── exchange_snapshot_synthesizer.log # 记录市场快照生成过程,主要是给客户端做行情恢复用的
└── trading_main_5.log # 记录 client_id = 5 这个客户端的启动信息
└── trading_engine_5.log  # 记录客户端交易引擎的核心处理流程,记录接收到的市场更新等
└── trading_market_data_consumer_5.log # 客户端有没有正常收行情,行情链路是不是稳定
└── trading_order_gateway_5.log # 订单通信日志

# 为什么有些日志后面带 _5
因为源码里客户端日志文件名是按 client_id 拼出来的

如何通过日志判断客户端到底有没有交易成功

1.先看客户端有没有把单发出去trading_order_gateway_5.log

最早的:

  • Sending cid:5 seq:1 ... type:NEW client:5 ticker:1 ...
/home/xiaosu/project/cppquant/trading/order_gw/order_gateway.cpp:63 run() 17:22:58.502417495 Sending cid:5 seq:1 MEClientRequest [type:NEW client:5 ticker:1 oid:5000 side:SELL qty:28 price:167]
17:22:58.502437689 RDTSC Trading_TCPSocket_send 1698
17:22:58.502441093 TTT T12_OrderGateway_TCP_write 1774516978502441057
/home/xiaosu/project/cppquant/common/tcp_socket.cpp:71 sendAndRecv() 17:22:58.502488872 send socket:6 len:38
/home/xiaosu/project/cppquant/common/tcp_socket.cpp:63 sendAndRecv() 17:22:58.515416045 read socket:6 len:50 utime:1774516978515415929 ktime:1774516978512628000 diff:2787929
17:22:58.515433096 TTT T7t_OrderGateway_TCP_read 1774516978515433054
/home/xiaosu/project/cppquant/trading/order_gw/order_gateway.cpp:105 recvCallback() 17:22:58.515441216 Received socket:6 len:50 1774516978512628000
/home/xiaosu/project/cppquant/trading/order_gw/order_gateway.cpp:111 recvCallback() 17:22:58.515453676 Received OMClientResponse [seq:1 MEClientResponse [type:ACCEPTED client:5 ticker:1 coid:5000 moid:1 side:SELL exec_qty:0 leaves_qty:28 price:167]]
17:22:58.515461959 TTT T8t_OrderGateway_LFQueue_write 1774516978515461927
17:22:58.515464235 RDTSC Trading_OrderGateway_recvCallback 84894
17:22:58.522429026 TTT T11_OrderGateway_LFQueue_read 1774516978522428946

2.看交易所有没有收到并处理exchange_order_server.log

  • Received OMClientRequest [seq:1 ... type:NEW client:5 ...]
  • 随后写入 FIFO 并返回响应
  • 还能看到撮合引擎真正处理了这些请求,Processing MEClientRequest [type:NEW client:5 ...]
/home/xiaosu/project/cppquant/exchange/order_server/order_server.h:89 run() 17:22:32.703349585
/home/xiaosu/project/cppquant/common/tcp_server.cpp:77 poll() 17:22:44.526736070 EPOLLIN listener_socket:11
/home/xiaosu/project/cppquant/common/tcp_server.cpp:105 poll() 17:22:44.526778787 have_new_connection
/home/xiaosu/project/cppquant/common/tcp_server.cpp:116 poll() 17:22:44.526825044 accepted socket:12
/home/xiaosu/project/cppquant/common/tcp_server.cpp:105 poll() 17:22:44.864972428 have_new_connection
/home/xiaosu/project/cppquant/common/tcp_socket.cpp:63 sendAndRecv() 17:22:58.506419127 read socket:12 len:38 utime:1774516978506418952 ktime:1774516978502471000 diff:3947952
17:22:58.506439355 TTT T1_OrderServer_TCP_read 1774516978506439316
/home/xiaosu/project/cppquant/exchange/order_server/order_server.h:149 recvCallback() 17:22:58.506442266 Received socket:12 len:38 rx:1774516978502471000
/home/xiaosu/project/cppquant/exchange/order_server/order_server.h:160 recvCallback() 17:22:58.506460697 Received OMClientRequest [seq:1 MEClientRequest [type:NEW client:5 ticker:1 oid:5000 side:SELL qty:28 price:167]]
17:22:58.506548775 RDTSC Exchange_FIFOSequencer_addClientRequest 1224
/home/xiaosu/project/cppquant/exchange/order_server/fifo_sequencer.h:93 sequenceAndPublish() 17:22:58.506553152 Processing 1 requests.
/home/xiaosu/project/cppquant/exchange/order_server/fifo_sequencer.h:103 sequenceAndPublish() 17:22:58.506559887 Writing RX:1774516978502471000 Req:MEClientRequest [type:NEW client:5 ticker:1 oid:5000 side:SELL qty:28 price:167] to FIFO.
17:22:58.508444770 TTT T2_OrderServer_LFQueue_write 1774516978508444725
17:22:58.508455699 RDTSC Exchange_FIFOSequencer_sequenceAndPublish 7013452
17:22:58.512563569 TTT T5t_OrderServer_LFQueue_read 1774516978512563521

3.客户端网关日志trading_order_gateway_5.log,交易所日志exchange_matching_engine.log看到 FILLED

  • Received OMClientResponse [ ... type:FILLED client:5 ... ]
/home/xiaosu/project/cppquant/trading/order_gw/order_gateway.cpp:63 run() 17:22:58.991968976 Sending cid:5 seq:25 MEClientRequest [type:NEW client:5 ticker:3 oid:5012 side:SELL qty:92 price:173]
17:22:58.991976725 RDTSC Trading_TCPSocket_send 1328
17:22:58.991979843 TTT T12_OrderGateway_TCP_write 1774516978991979811
/home/xiaosu/project/cppquant/common/tcp_socket.cpp:71 sendAndRecv() 17:22:58.992006400 send socket:6 len:38
/home/xiaosu/project/cppquant/common/tcp_socket.cpp:63 sendAndRecv() 17:22:58.999213469 read socket:6 len:150 utime:1774516978999213415 ktime:1774516978996578000 diff:2635415
17:22:58.999225555 TTT T7t_OrderGateway_TCP_read 1774516978999225516
/home/xiaosu/project/cppquant/trading/order_gw/order_gateway.cpp:105 recvCallback() 17:22:58.999228252 Received socket:6 len:150 1774516978996578000
/home/xiaosu/project/cppquant/trading/order_gw/order_gateway.cpp:111 recvCallback() 17:22:58.999240541 Received OMClientResponse [seq:25 MEClientResponse [type:ACCEPTED client:5 ticker:3 coid:5012 moid:2 side:SELL exec_qty:0 leaves_qty:92 price:173]]
17:22:58.999248915 TTT T8t_OrderGateway_LFQueue_write 1774516978999248880
/home/xiaosu/project/cppquant/trading/order_gw/order_gateway.cpp:111 recvCallback() 17:22:58.999252849 Received OMClientResponse [seq:26 MEClientResponse [type:FILLED client:5 ticker:3 coid:5012 moid:2 side:SELL exec_qty:44 leaves_qty:48 price:182]]
17:22:58.999259671 TTT T8t_OrderGateway_LFQueue_write 1774516978999259641
/home/xiaosu/project/cppquant/trading/order_gw/order_gateway.cpp:111 recvCallback() 17:22:58.999263724 Received OMClientResponse [seq:27 MEClientResponse [type:FILLED client:5 ticker:3 coid:5010 moid:1 side:BUY exec_qty:44 leaves_qty:0 price:182]]
17:22:58.999270570 TTT T8t_OrderGateway_LFQueue_write 1774516978999270532
17:22:58.999272824 RDTSC Trading_OrderGateway_recvCallback 164338
17:22:59.014959603 TTT T11_OrderGateway_LFQueue_read 1774516979014959517

4.客户端持仓有没有更新仓位trading_engine_5.log

  • onOrderUpdate() ... type:FILLED ...
  • position_keeper.h:155 addFill() ... Position{...}
/home/xiaosu/project/cppquant/trading/strategy/trade_engine.cpp:262 onOrderUpdate() 17:22:59.006686493 MEClientResponse [type:FILLED client:5 ticker:3 coid:5012 moid:2 side:SELL exec_qty:44 leaves_qty:48 price:182]
/home/xiaosu/project/cppquant/trading/strategy/position_keeper.h:156 addFill() 17:22:59.006740983 Position{pos:-44 u-pnl:0 r-pnl:0 t-pnl:0 vol:44 vwaps:[0X182] BBO{INVALID@INVALIDXINVALID@INVALID}} MEClientResponse [type:FILLED client:5 ticker:3 coid:5012 moid:2 side:SELL exec_qty:44 leaves_qty:48 price:182]

运行性能测试

./logger_benchmark  # 测试日志系统性能
./hash_benchmark    # 测试哈希表性能
./release_benchmark # 测试内存池性能

系统通信流程

系统使用无锁队列进行组件间的高效通信:

  1. 订单流程:

    • 交易客户端通过OrderGateway发送订单请求
    • 交易所的OrderServer接收请求并转发给MatchingEngine
    • MatchingEngine处理订单并生成响应
    • 响应通过OrderServer返回给客户端的OrderGateway
  2. 市场数据流程:

    • MatchingEngine生成市场数据更新
    • MarketDataPublisher发布市场数据
    • 客户端的MarketDataConsumer接收市场数据
    • TradeEngine根据市场数据更新内部状态并可能生成新的订单

文档

详细的系统架构和设计文档位于 docs/ 目录下:

About

量化交易系统

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages