1.CTP是上期技术,提供的国内期货行情和交易的接口,自推出以来,各大券商均架设了CTP技术的接入,引入策略算法便可以初步形成一个自动交易的系统,这也就吸引了很多对自动交易,策略交易感兴趣的各路高人来使用。
2.CTP难点在于,一个库提供了行情和交易两套接口,各自均有一套业务流程,而且两者在业务上还存在部分业务关联,也就是说还要处理两套之间的业务同步问题,没有一些C++基础的人很难开发好用的CTP库。
3.本Demo目标是,在Windows环境下做两个程序:
一个封装CTP行情和交易接口成一个库,尽可能在高内聚低耦合的情况下,保持代码清晰,通俗尽可能让;
一个执行程序很容易的去调用这个库,这里没有使用MFC或QT,直接采用控制台程序,很清晰的展示使用库。
本Demo采用Visualstudio2015专业版update3
Windows764位
综合交易平台API下载,下载列表中的windows下64位库(最新(2015-05-15)),解压如下:
主页右上角,注册账号,例子中方便开箱即用,会使用我自己申请好的,请自行换成自己的帐号。
1.先看下Demo的运行效果。
2.程序目录结构
共两个项目,CTPSample和CTPServer,CTPSample为封装交易所CTP的动态库,CTPServer为使用库的UI程序。
bin64
-----CTPCTP产生的共享文件
-----Log日志文件
config.cfg配置文件
build
CTPServer.sln存放工程文件
Src
------CTPSampleDLL代码
------CTPServerUI代码
------Framwork框架代码,避免复杂,不做公开(这里主要提供日志,数据定义,可自己替换)
说明:confg.cfg主要保存了CTP的地址(其他均为非本Demo演示的主要功能):
[info]
CTPFront.trade1=tcp://180.168.146.187:10030
CTPFront.quote1=tcp://180.168.146.187:10031
CTPFront.trade2=tcp://180.168.146.187:10001
CTPFront.quote2=tcp://180.168.146.187:10011
CTPFront.trade3=tcp://218.202.237.33:10002
CTPFront.quote3=tcp://ctp1-md11.citicsf.com:41213
3.模块介绍
CTPSample模块
CTPBase.h动态库的导出定义
MyCTPQuote.h/MyCTPQuote.CPP交易的封装
MyCTPQuote.h/MyCTPQuote.cpp行情的封装
CTPServer模块
TradeManager.h/TradeManager.cppUI主逻辑
CTPServer.cppmain启动
1.CTPSample模块之MyCTPQuote.h
主要功能点:
MyRecv来封装CThostFtdcMdSpi,CThostFtdcMdApi直接使用。
本模块提供给上层的接口,定义了一个虚基类:
classCPacketReceiver{public:virtualvoidReceive(CBroadcastPacket&pkt)=0;};这里运用到actor模式,接受UI订阅:typedefvector
map
2.CTPSample模块之MyCTPTrade.h
与CTP提供的行情库类似,这里定义了API和封装的回报API,如下:
CThostFtdcTraderApi*m_reqApi;MyRecv*m_RecvSpi;②与UI通信由于交易API用的比较频繁,而回报主要在初始化阶段和数据更新,没有定义回报接口,定义的是全局单例模式,直接共上层使用。
//保存合约map
3.程序注意点
调用TradeManager::InitCTP启动CTP模块,主模块会订阅注册:
MyCTPQuote::Instance()->Subscribe(this);②交易模块与行情模块通信当交易模块登陆成功后(通能说原子操作,来判断多条件满足),来调用行情的完成函数,已便行情模块来进行行情合约订阅
intQry=atomic_exchange(&MyCTPTrade::Instance()->m_bQryIns,false);intQryOK=atomic_exchange(&MyCTPTrade::Instance()->m_bQryInsOK,true);if(!Qry&&QryOK)FinishQryInstrument();③行情回报收到行情回报,会调用下函数:
voidMyCTPQuote::OnRtnDepthMarketData(CThostFtdcDepthMarketDataField*pDepthMarketData)并组织结构,向订阅派发:
收到数据可以按照自己的逻辑处理,本Demo进行了写共享队列。
QUOTATIONquo={0};voidTradeManager::Receive(CBroadcastPacket&pkt){unsignedintnLen=0;constchar*pcBuf=pkt.Encode(nLen);//分发给相应队列处理quo.Decode(pcBuf,nLen);intuiCount=0;stringsXQueName,sTmp;for(vector