news 2026/10/6 11:33:42

CATS API接口详解:程序化交易系统从初始化到委托下单的全流程实践

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
CATS API接口详解:程序化交易系统从初始化到委托下单的全流程实践

简介:中信证券自动化交易平台(CATS)API参考文档,面向量化交易开发者与程序化交易客户端设计人员。这份资源系统梳理了CATS API的全双工异步通信机制、初始化与业务调用流程,重点涵盖账户登录、交易订阅、行情订阅等核心函数分类与接口说明,也包含了错误处理与本地内存数据库操作等模块。压缩包内目前仅有1个pdf文件,总体积509KB,为官方API的技术参考文档,适合需要在中信证券体系内构建自动化交易策略、开发交易接入模块或了解API调用关系的开发者对照查阅。文档详细列出了CATSAPI_Init、CATSAPI_Execute_CatsLogin、CATSAPI_Subscribe_MarketData等关键函数的用途,并说明了从通信会话管理到内存数据库操作的完整工具链,可帮助读者快速理解接口调用关系、降低二次开发中的排查成本。目前已有3300人浏览学习,是从事量化交易或券商系统对接工作的一份实用参考资料。

1. 这是什么:CATS自动化交易平台的接口工具包,值不值得接入

拿到中信证券这套CATS自动化交易平台API参考时,我第一反应是它和券商常见的交易接口很不一样。CATS API没有把网络协议和通信细节暴露给调用方,而是用一套应用级函数把底层全双工异步通信、压缩和加密全部收口,调用方只需要关心业务功能。行情推送和委托回报走的是回调,不会互相阻塞;两阶段的Prepare/Execute设计让参数设置和执行分离,写起来很像在填一张业务表单。适合两类人:一类是给券商做程序化交易客户端的量化开发,另一类是自研交易系统、卡在行情订阅和下单链路上的团队。这份文档解决的是从初始化、登录、订阅到委托撤单的完整链路怎么调,以及每个环节的参数怎么选。

2. 初始化与会话管理:Init到InitSession的参数细节,连不上先查这里

2.1 Init/Fini与调试窗口,开发期建议打开

CATS API的第一步永远是初始化。函数原型很简洁:

int ret = CATSAPI_Init(1); // 参数为1时启用调试窗口,0为关闭 if (ret != 0) { // 初始化失败,用CATSAPI_GetLastError()拉取错误码 } // ...业务逻辑... CATSAPI_Fini(); // 程序退出前清理

这里的debug_console参数是不少新手会忽略的。开发阶段传1,可以把logdebug、logwarn、logerror这些日志直接打到调试窗口,方便观察回调触发顺序;上线部署时传0,所有输出走本地日志文件。初始化失败的概率不高,一旦发生,优先检查环境变量里是否缺少catsapi.ini的路径配置,其次是检查SDK版本和中间件版本是否匹配。

初始化之后紧接着是会话创建。CATSAPI_InitSession的入参比较多,我们放在下一节单独拆开讲。

2.2 InitSession的七个参数,哪个都不能漏

这个函数是整个API生命周期的基础,参数不全会导致后面登录、订阅各种意外。函数原型和参数含义如下:

CATSHANDLE hHandle = NULL; int ret = CATSAPI_InitSession( &hHandle, // 输出参数,会话句柄 1, // use_ssl:是否启用SSL通道 1, // start_conn:是否自动后台连接CATS服务器 OnTrdReConnected, // 交易服务器重连成功后的回调钩子 NULL, // 该回调的用户自定义参数 OnTrdDisConnected, // 交易服务器连接中断后的回调钩子 NULL, // 该回调的用户自定义参数 OnHqReConnected, // 行情服务器重连成功后的回调钩子 NULL, // 该回调的用户自定义参数 OnHqDisConnected, // 行情服务器连接中断后的回调钩子 NULL // 该回调的用户自定义参数 );

TS_Notify_t是回调函数指针类型,具体签名在SDK头文件里有定义。这里的关键是start_conn和四个回调钩子的配合:start_conn=1时API会自动在后台尝试连接服务器,连接状态通过回调通知。开发时最常见的坑是回调里做耗时操作,比如写数据库或者同步HTTP请求,这会直接拖住内部通信线程,导致行情延迟和委托回报变慢。

我一般习惯在重连成功的回调里设置一个全局标志位,业务逻辑等标志位置位后再发起请求,而不是初始化结束后立刻下单。

2.3 连接服务器前,先确认版本和配置

连接服务器分为Prepare和Execute两步,这是CATS API一贯的风格。先看版本信息,再确认配置,最后连接:

// 获取版本信息,确认SDK和中间件匹配 const char* ver = CATSAPI_GetVersion(); // 准备连接参数 CATSAPI_Prepare_CatsConnect(); // 执行连接 int ret = CATSAPI_Execute_CatsConnect(); if (ret != 0) { int err = CATSAPI_GetLastError(); // 重点检查catsapi.ini里的服务器地址和端口 }

Prepare阶段通常在内部把参数清零或填充默认值,Execute阶段才真正发起连接。这里有一个容易被忽略的点:catsapi.ini的配置信息是由用户指定的,API提供了一系列get_*_def函数去读取。如果配置文件缺失或者配置了错误的IP端口,连接必然是失败的。连接失败时不要只盯错误码,先把配置文件里的交易服务器、行情服务器地址分开核对,交易和行情经常是不同的IP和端口。

3. 数据字典与参数选型:买卖方向、订单类型、行情聚集类型最容易混

3.1 买卖方向代码,证券、信用、期货是三套字典

这份参考文档里最容易踩坑的地方就是这里。同样是“买入”,证券账户传1,期货账户要传FA开多仓,信用账户还要区分融资买入A和融券卖出B。我按文档整理成表:

代码证券/信用含义期货含义
1买入/担保品买入-
2卖出/担保品卖出-
A融资买入开多仓
B融券卖出开空仓
FA-开多仓(开仓买入)
FB-开空仓(开仓卖出)
FC-平空仓(平仓买入)
FD-平多仓(平仓卖出)
FO-先平仓买入、再开仓买入
FP-先平仓卖出、再开仓卖出

注意期货的“平今”和“平昨”是分开的,FG到FJ这一组,代表了平今空、平今多、平昨空、平昨多。如果你的策略在股指期货上做过夜和日内混合交易,这个区分直接决定手续费和持仓方向是否合法。我见过有人把所有平仓统一传FD,结果被柜台拒绝。

3.2 订单类型:市价单的细分比想象中多

订单类型这块,证券和信用的分类能看懂,期货的写法相对绕。限价单在证券和期货里都是0,但市价单的编码差异很大:

代码证券/信用含义期货含义
0限价单限价单
Q对手方最优价格-
R最优五档即时成交剩余转限价-
S本方最优价格-
T即时成交剩余撤销-
U最优五档即时成交剩余撤销-
V全额成交或撤单-
3-最优价
4-最新价
5-最新价浮盈上浮1个tick
8-卖一价
9-卖一价浮盈上浮1个tick

做A股股票策略时,用Q、R、U、V这类市价单较多,但要注意部分柜台和交易所对市价单的适用范围有限制。做期货时,最优价、最新价和卖一价这些细分的tick偏移,本质上是用来抢执行速度的。我一般建议股票程序化优先用限价单,避免市价单滑点不可控。

订单状态代码就五个数字:0新建、1部分成交、2完全成交、3部分撤单、4全部撤单、5订单拒绝。回调里处理状态时,建议按“新建→部分成交→完全成交”的状态机推进,而不是简单覆盖字段。部分撤单和全部撤单在实盘里出现时,要立刻把剩余可撤数量清零,防止后续重复撤单。

3.3 聚集行情类型:分钟线选错了周期,数据全废

行情订阅里的聚集类型,文档给了完整清单:1代表一分钟线,5代表五分钟线,以此类推到60分钟线;日线聚集则是61到65,对应日线、周线、月线、季线、年线。这里容易搞混的是61。有人会把日线当成60分钟线来取,导致K线收盘价对不上。

商品种类也要注意:01股票、01基金、03债券、04指数、05股指期货、06商品期货、99其他。注意文档里的基金和股票代码都是01开头,实际使用时要用交易所代码去区分,比如SZ、SH前缀。订阅行情时,商品种类和交易所代码必须同时匹配,否则返回的数据字段对不上。

4. 业务请求与回调:Prepare/Execute配对与查询调用的正确写法

4.1 两阶段调用的设计逻辑,为什么不是直接传参

CATS API的所有业务接口几乎都是Prepare和Execute成对出现。Prepare阶段设置参数,Execute阶段执行请求。这种设计的好处是参数可以反复复用,比如一个算法实例要连续下多笔委托,只需要在Prepare之后循环修改价格和数量。

参数设置统一走CATSAPI_SetParam和CATSAPI_SetGroupParam,按名赋值。这意味着字段名的拼写必须和头文件定义完全一致,大小写也敏感。我踩过的坑是把acct_id写成acctID,结果Execute直接返回参数错误,GetLastError也只给了一个泛化的错误码,排查了半天。

4.2 单笔委托的完整调用,含字段说明

下面这段代码展示一次完整的单笔委托,字段名以CATS API头文件为准:

// 第一步:准备单笔委托 CATSAPI_Prepare_OrderSingle(); // 第二步:按名称设置业务输入参数 CATSAPI_SetParam("acct_id", "3000001"); // 资金账号 CATSAPI_SetParam("stock_code", "000001"); // 证券代码 CATSAPI_SetParam("price", 10.50); // 委托价格 CATSAPI_SetParam("qty", 100); // 委托数量 CATSAPI_SetParam("bs_flag", 1); // 买卖方向:1买入,2卖出 CATSAPI_SetParam("order_type", 0); // 订单类型:0限价单 // 第三步:执行委托 int ret = CATSAPI_Execute_OrderSingle(); if (ret != 0) { int err = CATSAPI_GetLastError(); // 错误处理:优先检查bs_flag和order_type是否匹配 } // 第四步:委托回报在订阅的OrderUpdate回调里获取

两阶段调用的好处在于,Execute之前可以反复调整参数而不用重新准备。参数名里bs_flag对应前面数据字典里的买卖方向代码,证券传1或2,期货传FA、FB、FO这种代码。价格和数量建议用浮点和整数类型对应好,CATSAPI_SetParam是按字符串解析的,传10.50和传10.5结果一致,但有些接口对价格精度有要求,最好在字符串里保留两位小数。

4.3 查询类调用与子账户管理

查询类的调用逻辑和交易类保持一致,只是执行后不是等回调,而是通过GetIntField、GetLongField、GetCStrField、GetFloatField这些函数读取输出参数。以查询交易时间和查询子账户为例:

// 查询交易时间 CATSAPI_Prepare_QueryTradeTime(); if (CATSAPI_Execute_QueryTradeTime() == 0) { // 从输出参数里读取开市时间、闭市时间 const char* openTime = CATSAPI_GetCStrField("open_time"); const char* closeTime = CATSAPI_GetCStrField("close_time"); } // 查询子账户列表 CATSAPI_Prepare_QuerySubAcc(); if (CATSAPI_Execute_QuerySubAcc() == 0) { int count = CATSAPI_GetIntField("sub_acc_count"); // 遍历子账户,用GetCStrField按字段名取账户ID }

加子账户和删子账户的流程完全一样:先Prepare,再SetParam设置子账户名称或ID,最后Execute。子账户是CATS平台做资金分拆的重要机制,多策略并行时,每个策略独立子账户下单,资金持仓互不干扰。查询子账户的返回字段里,建议重点关注账户状态字段,有的子账户会被运维禁用,不查状态直接在它上下单,等到的只是订单拒绝。

5. 订阅推送与常见问题排查:订阅流程和四条实测踩坑记录

5.1 标准订阅流程,先订阅再等回调

交易订阅和行情订阅都遵循“准备→订阅→回调→退订”的流程。以资金持仓变动订阅为例:

// 准备订阅请求 CATSAPI_PrepSub_AssetUpdate(); // 执行订阅 int ret = CATSAPI_Subscribe_AssetUpdate(); if (ret == 0) { // 订阅成功,后续资金和持仓变动会通过回调推上来 } // 不需要时退订 CATSAPI_PreUnSub_AssetUpdate(); CATSAPI_UnSubscribe_AssetUpdate();

行情订阅的写法类似,但要注意行情数据的生命周期:

// 订阅行情 CATSAPI_PreSub_MarketData(); CATSAPI_Subscribe_MarketData(); // 批量订阅 CATSAPI_PreSub_BatchMarketData(); // 通过SetGroupParam设置一组股票代码 CATSAPI_Subscribe_BatchMarketData(); // 退订行情,节省带宽 CATSAPI_PreUnSub_MarketData(); CATSAPI_UnSubscribe_MarketData();

分钟线和日线数据是独立通道。当日分钟线订阅用Subscribe_MinuteBar,退订用UnSubscribe_MinuteBar,历史分钟线则走QueryHisMinFilePath查询文件路径,再通过FTP下载。这里容易混淆的是:订阅分钟线拿的是实时推送的当日bar,历史分钟线拿的是离线文件,两者不是一个数据源。做盘后回测时,用查询类的历史数据接口更合适。

5.2 四条实测踩坑记录,按现象到解决排列

坑一:订阅了AssetUpdate,但回调一次都没触发。现象:代码执行Subscribe_AssetUpdate返回0,但资金变动后回调函数没有反应。 原因:订阅动作发生在账户登录成功之前,服务器认为会话未就绪,直接丢弃了订阅请求。 解决:先执行CATSAPI_Prepare_CatsLogin和CATSAPI_Execute_CatsLogin,等登录回调确认成功后,再发起订阅。我现在的代码里会用一个login_ready标志位,订阅函数只在标志位置位后执行。

坑二:初始化后立刻下单,返回失败。现象:CATSAPI_Init和CATSAPI_InitSession都成功,紧接着CATSAPI_Execute_OrderSingle返回非0,错误码指向会话异常。 原因:start_conn=1只是启动后台连接,但连接建立是异步的,初始化完成时服务器连接可能还没建立。 解决:把下单动作挂到OnTrdReConnected回调之后。连接成功的回调是最好的“可交易”信号,比定时器等靠谱得多。

坑三:use_ssl=1时连接超时。现象:配置了SSL通道后,Execute_CatsConnect一直超时。 原因:SSL的端口和明文端口不是同一个,配置文件里填的端口没切换。 解决:先用明文连接完成功能验证,确认业务逻辑后再切换SSL端口。SSL的配置项通常独立于普通连接端口,检查catsapi.ini里是否有单独的加密端口配置段,不要只在IP后面改一个数字。

坑四:期货方向代码解析错误。现象:期货账户报单后,回调里的方向字段显示出来的值和预期不符,甚至被拒绝。 原因:直接用证券方向的1/2去判断期货的买卖方向,而期货方向用的是FA/FB/FC这一组代码。 解决:根据商品种类字段判断账户类型,期货账户单独走期货方向解释逻辑。特别是FA和FB,它们分别对应开多仓和开空仓,搞反了就是反向开仓,后果极其严重。

6. 进阶验证:用日志分级做一次启动自检,确认链路全通

CATS API自带的日志函数有四个:logdebug、loginfo、logwarn、logerror。很多人的用法是只在catch里打logerror,但我觉得更好的方式是拿这四个函数组成一个启动自检流程,每次连新环境都强制走一遍,能省下大量来回扯皮的时间。

loginfo("CATS API 启动自检开始"); // 第一步:初始化与版本确认 if (CATSAPI_Init(0) == 0) { logdebug("Init OK, version=%s", CATSAPI_GetVersion()); } else { logerror("Init failed, err=%d", CATSAPI_GetLastError()); return -1; } // 第二步:连接服务器 CATSAPI_Prepare_CatsConnect(); if (CATSAPI_Execute_CatsConnect() == 0) { loginfo("Connect success"); } else { logerror("Connect failed, err=%d", CATSAPI_GetLastError()); return -2; } // 第三步:账户登录 CATSAPI_Prepare_CatsLogin(); if (CATSAPI_Execute_CatsLogin() == 0) { loginfo("Login success"); } else { logerror("Login failed, err=%d", CATSAPI_GetLastError()); return -3; } // 第四步:查询交易时间,验证请求链路 CATSAPI_Prepare_QueryTradeTime(); if (CATSAPI_Execute_QueryTradeTime() == 0) { loginfo("QueryTradeTime success, open_time=%s", CATSAPI_GetCStrField("open_time")); } else { logwarn("QueryTradeTime failed, err=%d", CATSAPI_GetLastError()); }

这套自检脚本我会保留在工程里,每次部署到新环境时先跑一遍。日志分级的意义在于,debug记录每个接口的入参和返回码,info记录关键里程碑,warn记录不影响主流程但需要关注的点,error记录必须中断的故障。线上定位问题时,直接看logerror文件定位故障点,再看logdebug确认参数是否传对,命中率比盲目打断点高不少。

日志文件输出还有个容易被忽略的优势:CATSAPI的调试窗口只显示进程内信息,而日志文件是落盘的,程序崩溃后依然可以查。我有一个习惯,每次写交易逻辑之前,先把这套自检跑通再动策略代码。从那以后,我每次新环境部署都会强制走一遍这个流程,确认交易和行情链路都通了才开始接策略。希望帮到你。

本文还有配套的精品资源,点击获取

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/6 11:33:24

HEIF/HEIC 文件结构解析:ISO/IEC 23008-12:2017 标准与 box 实战

简介:ISO/IEC 23008-12:2017 是国际标准化组织与国际电工委员会联合发布的图像文件格式标准,聚焦高效编码与异构环境下的媒体交付,是理解 HEIF、HEIC 格式的权威依据。资源面向从事图像编解码、移动端多媒体开发、流媒体与智能终端适配的工程…

作者头像 李华
网站建设 2026/10/6 11:33:24

ArduPilot避障实战:MR72与TFmini Plus参数配置与调试指南

1. 从零讲清楚:ArduPilot 避障到底在解决什么问题 很多人第一次接触 ArduPilot 的避障功能,脑子里想的都是“装个雷达,车就能自己绕开障碍物了”。但实际动手之后才发现,事情远没有这么简单——雷达装上了,参数也改了&…

作者头像 李华
网站建设 2026/10/6 11:33:01

VS Code + MCP + Seedream 搭建中文海报生成工作台指南

之前做海报,我的路径基本是:打开网页版 AI 绘画工具,把想好的文案粘进去,生成,下载,拖进修图软件改文字,再导出。听起来不算远,但一天做 5 张就烦了——来回切换窗口、反复试提示词、…

作者头像 李华
网站建设 2026/10/6 11:32:56

浏览器端侧视觉AI工程实战:WebGL+WASM协同推理

1. 这不是“跑个 demo”,而是把神经网络真刀真枪塞进浏览器标签页里 “把神经网络塞进一个浏览器标签页”——这句话听起来像极了技术圈里那种带点戏谑又藏着狠活的标题党。但如果你真去翻过 TensorFlow.js 的 GitHub star 数、看看 ONNX Runtime Web 的 release no…

作者头像 李华
网站建设 2026/10/6 11:32:46

DeepSeek Harness 桌面端安装配置与插件 Skill 实战指南

DeepSeek Harness 的官方桌面端终于来了。要说这玩意儿,圈子里不少搞 AI 辅助编码的人已经盼了大半年——以前要么在终端里敲命令,要么开个 Web 页面将就用,本地文件和模型之间的交互总是隔着一层。现在桌面端一出来,等于把之前 C…

作者头像 李华
网站建设 2026/10/6 11:32:45

Attero网络损伤仪实操:从接口到双方向损伤配置全解析

简介:这份中文使用手册面向网络设备测试与运维人员,聚焦Attero损伤仪在复杂网络环境下的性能评估需求。手册从硬件接口讲起,说明10GE光口、1G/100Mb电口、LED显示屏与PC控制终端连接方式,并提示XFP/SFP光模块选配、.NET Framework…

作者头像 李华