ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

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

CATS API接口详解:程序化交易系统从初始化到委托下单的全流程实践 简介中信证券自动化交易平台CATSAPI参考文档面向量化交易开发者与程序化交易客户端设计人员。这份资源系统梳理了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_conn1时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个tick8-卖一价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_conn1只是启动后台连接但连接建立是异步的初始化完成时服务器连接可能还没建立。 解决把下单动作挂到OnTrdReConnected回调之后。连接成功的回调是最好的“可交易”信号比定时器等靠谱得多。坑三use_ssl1时连接超时。现象配置了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的调试窗口只显示进程内信息而日志文件是落盘的程序崩溃后依然可以查。我有一个习惯每次写交易逻辑之前先把这套自检跑通再动策略代码。从那以后我每次新环境部署都会强制走一遍这个流程确认交易和行情链路都通了才开始接策略。希望帮到你。本文还有配套的精品资源点击获取
返回列表