CTP API对接与测试

CTP柜台在期货领域具有举足轻重的地位,其提供的API以代码风格的规范著称。近期实现了一下对其接口的测试,使用起来还是比较简单清晰的,发现的一个问题就是接口与字段太多了,对使用者的理解增加了不少难度,好在对大多数使用者来说,不需要搞清楚所有的接口和字段。

因为CTP接口的规范性,我这里将其接口抽象成了了几种元素,进一步通过python脚本自动生成了一些代码,以达到对所有回调函数的所有字段进行日志记录的功能。同时对一些关键的接口进行了测试。因为篇幅限制,这里仅列出部分接口的代码实现,如果感兴趣可以移步 GitHub 获取完整代码。

 

CTP 的SPI类其回调函数主要分为五类,On、OnRsp、OnRspQry、OnErrRtn、OnRtn:

以On开头的回调函数参数通常是一些简单的类型或者无参数;

以OnRsp和OnRspQry开头的回调函数参数,包含 一个Field 结构,加一个固定的 CThostFtdcRspInfoField 结构,还有两个简单的参数 int nRequestID 和 bool bIsLast;

以OnErrRtn开头的回调函数参数,包含 一个Field 结构,加一个固定的 CThostFtdcRspInfoField 结构;

以OnRtn开头的回调函数参数,仅包含 一个Field 结构。

一些元素的抽象如下所示,

<?xml version="1.0" encoding="utf-8"?>
<root>
	<fields>
		<field name="RspInfo">
			<item name="ErrorID" type="int"/>
			<item name="ErrorMsg" type="string"/>
		</field>
		<field name="RspAuthenticate">
			<item name="BrokerID" type="string"/>
			<item name="UserID" type="string"/>
			<item name="UserProductInfo" type="string"/>
			<item name="AppID" type="string"/>
			<item name="AppType" type="char"/>
		</field>
		<field name="RspUserLogin">
			<item name="TradingDay" type="string"/>
			<item name="LoginTime" type="string"/>
			<item name="BrokerID" type="string"/>
			<item name="UserID" type="string"/>
			<item name="SystemName" type="string"/>
			<item name="FrontID" type="int"/>
			<item name="SessionID" type="int"/>
			<item name="MaxOrderRef" type="string"/>
			<item name="SHFETime" type="string"/>
			<item name="DCETime" type="string"/>
			<item name="CZCETime" type="string"/>
			<item name="FFEXTime" type="string"/>
			<item name="INETime" type="string"/>
		</field>
		<field name="UserLogout">
			<item name="BrokerID" type="string"/>
			<item name="UserID" type="string"/>
		</field>
		<field name="UserPasswordUpdate">
			<item name="BrokerID" type="string"/>
			<item name="UserID" type="string"/>
			<item name="OldPassword" type="string"/>
			<item name="NewPassword" type="string"/>
		</field>
		<field name="TradingAccountPasswordUpdate">
			<item name="BrokerID" type="string"/>
			<item name="AccountID" type="string"/>
			<item name="OldPassword" type="string"/>
			<item name="NewPassword" type="string"/>
			<item name="CurrencyID" type="string"/>
		</field>
		<field name="RspUserAuthMethod">
			<item name="UsableAuthMethod" type="int"/>
		</field>
		<field name="RspGenUserCaptcha">
			<item name="BrokerID" type="string"/>
			<item name="UserID" type="string"/>
			<item name="CaptchaInfoLen" type="int"/>
			<item name="CaptchaInfo" type="string"/>
		</field>
        ...
	</fields>
    <spi>
		<func name="OnFrontConnected" retrun="void" type="On" sequence="0"/>
		<func name="OnFrontDisconnected" retrun="void" type="On" sequence="1">
			<param type="int" name="nReason"/>
		</func>
		<func name="OnHeartBeatWarning" retrun="void" type="On" sequence="2">
			<param type="int" name="nTimeLapse"/>
		</func>
		<func name="OnRspAuthenticate" retrun="void" type="OnRsp" sequence="3">
			<param type="CThostFtdcRspAuthenticateField" name="RspAuthenticate"/>
		</func>
		<func name="OnRspUserLogin" retrun="void" type="OnRsp" sequence="4">
			<param type="CThostFtdcRspUserLoginField" name="RspUserLogin"/>
		</func>
		<func name="OnRspUserLogout" retrun="void" type="OnRsp" sequence="5">
			<param type="CThostFtdcUserLogoutField" name="UserLogout"/>
		</func>
		<func name="OnRspUserPasswordUpdate" retrun="void" type="OnRsp" sequence="6" >
			<param type="CThostFtdcUserPasswordUpdateField" name="UserPasswordUpdate"/>
		</func>
		<func name="OnRspTradingAccountPasswordUpdate" retrun="void" type="OnRsp" sequence="7">
			<param type="CThostFtdcTradingAccountPasswordUpdateField" name="TradingAccountPasswordUpdate"/>
		</func>
		<func name="OnRspUserAuthMethod" retrun="void" type="OnRsp" sequence="8">
			<param type="CThostFtdcRspUserAuthMethodField" name="RspUserAuthMethod"/>
		</func>
		<func name="OnRspGenUserCaptcha" retrun="void" type="OnRsp" sequence="9">
			<param type="CThostFtdcRspGenUserCaptchaField" name="RspGenUserCaptcha"/>
		</func>
		<func name="OnRspGenUserText" retrun="void" type="OnRsp" sequence="10">
			<param type="CThostFtdcRspGenUserTextField" name="RspGenUserText"/>
		</func>
		<func name="OnRspOrderInsert" retrun="void" type="OnRsp" sequence="11">
			<param type="CThostFtdcInputOrderField" name="InputOrder"/>
		</func>
		<func name="OnRspParkedOrderInsert" retrun="void" type="OnRsp" sequence="12">
			<param type="CThostFtdcParkedOrderField" name="ParkedOrder"/>
		</func>
		<func name="OnRspParkedOrderAction" retrun="void" type="OnRsp" sequence="13">
			<param type="CThostFtdcParkedOrderActionField" name="ParkedOrderAction"/>
		</func>
		<func name="OnRspOrderAction" retrun="void" type="OnRsp" sequence="14">
			<param type="CThostFtdcInputOrderActionField" name="InputOrderAction"/>
		</func>
		<func name="OnRspQueryMaxOrderVolume" retrun="void" type="OnRsp" sequence="15">
			<param type="CThostFtdcQueryMaxOrderVolumeField" name="QueryMaxOrderVolume"/>
		</func>
		<func name="OnRspSettlementInfoConfirm" retrun="void" type="OnRsp" sequence="16">
			<param type="CThostFtdcSettlementInfoConfirmField" name="SettlementInfoConfirm"/>
		</func>
		<func name="OnRspRemoveParkedOrder" retrun="void" type="OnRsp" sequence="17">
			<param type="CThostFtdcRemoveParkedOrderField" name="RemoveParkedOrder"/>
		</func>
		<func name="OnRspRemoveParkedOrderAction" retrun="void" type="OnRsp" sequence="18">
			<param type="CThostFtdcRemoveParkedOrderActionField" name="RemoveParkedOrderAction"/>
		</func>
		<func name="OnRspExecOrderInsert" retrun="void" type="OnRsp" sequence="19">
			<param type="CThostFtdcInputExecOrderField" name="InputExecOrder"/>
		</func>
		<func name="OnRspExecOrderAction" retrun="void" type="OnRsp" sequence="20">
            <param type="CThostFtdcInputExecOrderField" name="InputExecOrderAction"/>
		</func>
        ...
    </spi>
</root>

对所有Field生成写日志的函数代码:

StructWriteLogFunc.cpp.tpl

#include "StructWriteLogFunc.h"
#include "Logger.h"

!!types={}!!
!!types['char']='c'!!
!!types['short']='d'!!
!!types['int']='d'!!
!!types['double']='f'!!
!!types['string']='s'!!


!!entry fields!!
!!travel!!
void Write!!@name!!(CThostFtdc!!@name!!Field* !!@name!!)
{
!!fieldName=@name!!
	if(!!@name!!)
	{
		WRITE_LOG(LogLevel::Info, "CThostFtdc!!@name!!Field: !!travel!!!!currType=types[@type]!!!!if $pumpid != '1':!!!!inc indent!!, !!dec indent!!!!@name!![%!!$currType!!]!!leave!!",
			!!travel!!!!if $pumpid != '1':!!!!inc indent!!, !!dec indent!!!!$fieldName!!->!!@name!!!!leave!!);
	}
}

!!leave!!
!!leave!!

生成后部分代码如下:

StructWriteLogFunc.cpp

#include "StructWriteLogFunc.h"
#include "Logger.h"



void WriteRspInfo(CThostFtdcRspInfoField* RspInfo)
{
	if(RspInfo)
	{
		WRITE_LOG(LogLevel::Info, "CThostFtdcRspInfoField: ErrorID[%d], ErrorMsg[%s]",
			RspInfo->ErrorID, RspInfo->ErrorMsg);
	}
}

void WriteRspAuthenticate(CThostFtdcRspAuthenticateField* RspAuthenticate)
{
	if(RspAuthenticate)
	{
		WRITE_LOG(LogLevel::Info, "CThostFtdcRspAuthenticateField: BrokerID[%s], UserID[%s], UserProductInfo[%s], AppID[%s], AppType[%c]",
			RspAuthenticate->BrokerID, RspAuthenticate->UserID, RspAuthenticate->UserProductInfo, RspAuthenticate->AppID, RspAuthenticate->AppType);
	}
}

void WriteRspUserLogin(CThostFtdcRspUserLoginField* RspUserLogin)
{
	if(RspUserLogin)
	{
		WRITE_LOG(LogLevel::
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值