基于CTP的国内期货程序化交易之报单流程讲解

2024-08-28 14:08

本文主要是介绍基于CTP的国内期货程序化交易之报单流程讲解,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

       相比国外期货交易开发,国内期货交易开发就有些繁琐了,坑比较多。第一就是交易时间段多,像国外期货美原油,全天23小时连续交易,而国内期货沪金,全天分四个时间段交易,分别为9:00至10:15、10:30至11:30、13:30至15:00及21:00至次日02:30。交易时间段多,平仓时间段也多,这样无形中就增加了很多业务逻辑。另外,就是交易规则多,上期所的期货品种平仓时又分平今和平仓,这样平仓报单时就要根据成交时间分别判断,是前一个交易日的单子还是当前交易日的单子,否则报单参数不正确,单子将直接被交易系统拒绝。开发过程中主要用到的头文件为:ThostFtdcTraderApi.h、ThostFtdcUserApiDataType.h及ThostFtdcUserApiStruct.h,动态库为:libthosttraderapi.so。下面是一些代码示例:
       1. 创建CTP api实例:
CThostFtdcTraderApi *pTradeApi = CThostFtdcTraderApi::CreateFtdcTraderApi(dirName);
       通过调用CreateFtdcTraderApi()创建api实例——pTradeApi,随后调用该实例发起各种请求,比如连接服务器、用户登录、报单、撤单、查询持仓、查询资金等等。
       2. 创建CTP api回调实例:
CFtdcTradeSpi *pTradeSpi = new CFtdcTradeSpi(pTradeApi, this);
       这个需要自己编写相应实现类,需要继承上期技术提供的CThostFtdcTraderSpi类。重写该类里面的方法,以处理服务器发过来的各类数据。
       3. 将上述两个实例关联起来,并发起连接服务器请求:
pTradeApi->RegisterSpi(pTradeSpi);
pTradeSpi->connect(serverAddr, brokerId, username, password);
       连接服务器以及实例初始化相关代码:
void CFtdcTradeSpi::connect(string serverAddr, string brokerId, string username, string password)
{serverAddr_ = serverAddr;brokerId_ = brokerId;username_ = username;password_ = password;pTradeApi_->SubscribePublicTopic(THOST_TERT_QUICK);pTradeApi_->SubscribePrivateTopic(THOST_TERT_QUICK);pTradeApi_->RegisterFront((char *)serverAddr_.c_str());pTradeApi_->Init();
}
       连接请求发出后,OnFrontConnected()会响应请求,然后在该函数内可以调用登录函数pTradeApi_->ReqUserLogin()完成用户登录操作,相应的OnRspUserLogin()会响应请求。由于国内期货在交易日内首次登录时需要做投资者结算结果确认操作,所以在OnRspUserLogin()函数内,可以进一步调用pTradeApi_->ReqSettlementInfoConfirm()做投资者结算结果确认,确认结果将在OnRspSettlementInfoConfirm()内返回。做完投资者结算结果确认操作,整个服务器连接与用户登录过程就完成了,可以正常下单交易了。
void CFtdcTradeSpi::OnFrontConnected()
{LOG_INFO << username_ << " 回调: 与服务器已建立连接, 开始登录";
}void CFtdcTradeSpi::OnRspUserLogin(CThostFtdcRspUserLoginField *pRspUserLogin, CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast)
{if (pRspUserLogin == NULL || pRspInfo == NULL){LOG_INFO << username_ << " 登录回调异常, 指针为空";return;}if (pRspInfo->ErrorID == Err_Succeed){LOG_INFO << username_ <<  " 登录成功, 开始投资者结算结果确认, 当前交易日: " << pTradeApi_->GetTradingDay();}
}void CFtdcTradeSpi::OnRspSettlementInfoConfirm(CThostFtdcSettlementInfoConfirmField *pSettlementInfoConfirm, CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast)
{if (pSettlementInfoConfirm == NULL || pRspInfo == NULL){LOG_INFO << username_ << " 投资者结算结果确认回调异常, 指针为空";return;}string errorMsg;getErrcodeDesc(pRspInfo->ErrorMsg, errorMsg);LOG_INFO << username_ << " "<< "经纪公司代码: " << pSettlementInfoConfirm->BrokerID << " "<< "投资者代码: " << pSettlementInfoConfirm->InvestorID << " "<< "确认日期: " << pSettlementInfoConfirm->ConfirmDate << " "<< "确认时间: " << pSettlementInfoConfirm->ConfirmTime << " "<< "回调: 错误信息, 错误码: " << pRspInfo->ErrorID << " " << errorMsg;
}
       4. 期货报单:
       (1)ReqOrderInsert():报单请求
CThostFtdcInputOrderField reqField;
memset(&reqField, 0, sizeof(CThostFtdcInputOrderField));
......
......
pTradeApi_->ReqOrderInsert(&reqField, orderInsertReqId_);
       与前文所讲解基本一致,大同小异。 需要正确填写买卖/方向、开仓/平仓、市价/限价、委托数量、委托价格等等,填写完毕就可以调用ReqOrderInsert()报单了。
       (2)OnRspOrderInsert():报单请求应答
void CFtdcTradeSpi::OnRspOrderInsert(CThostFtdcInputOrderField *pInputOrder, CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast)
{
}
       报单成功后,理论上该函数就会被回调。但通过查阅日志来看,可能上期技术为了简化逻辑,弱化了该函数,实际上该函数并没有被回调,当然,这也可能与所使用的sdk版本有关系。
       (3)OnRtnOrder():委托变化通知
void CFtdcTradeSpi::OnRtnOrder(CThostFtdcOrderField *pOrder)
{
}
       当委托状态发生变化时,会被回调。一般常见的委托状态主要有:未知、未成交还在队列中、部分成交还在队列中、完全成交等。一次报单,如果数量比较多,一般不会一次全部成交,而是会分多批次成交,所以该函数会不断被回调。随着不断回调,每次返回的委托量、成交量、剩余量等数据会不断变更。
       (4)OnRtnMatchInfo():成交信息变化推送通知
void CFtdcTradeSpi::OnRtnTrade(CThostFtdcTradeField *pTrade)
{
}
       该函数比较重要,返回的每一条信息都是成交信息,里面包含成交量、成交价、成交费用等等,这些都是投资者关心的数据。总体来说,整个报单过程与前文讲解的国外期货报单流程基本一致。不过有一点简化了,那就是不需要编写报单流控逻辑,因为CTP没有报单频率限制,但是有查询频率限制,这一点刚好和易盛的交易api相反,易盛是查询没频率限制,报单有频率限制。
       5.  查询期货账号持仓:
       查询持仓主要调用pTradeApi_->ReqQryInvestorPosition(),按照文档说明填写合适的参数即可。查询持仓响应函数为:
void CFtdcTradeSpi::OnRspQryInvestorPosition(CThostFtdcInvestorPositionField *pInvestorPosition, CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast)
{
}
       该函数需要由开发者自己重写,比较麻烦的是持仓数据不会一次全部返回,而是一批一批返回,需要自己按照多空方向分别做汇总计算才行。
       编写完代码,如何测试程序呢?貌似上期技术没有提供测试账号,不过可以到SimNow网站(http://www.simnow.com.cn/)注册交易测试账号,不知道SimNow和上期技术啥关系。注册成功后账号内既有100万,这样就可以测试开仓及平仓了。



这篇关于基于CTP的国内期货程序化交易之报单流程讲解的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1114978

相关文章

Security OAuth2 单点登录流程

单点登录(英语:Single sign-on,缩写为 SSO),又译为单一签入,一种对于许多相互关连,但是又是各自独立的软件系统,提供访问控制的属性。当拥有这项属性时,当用户登录时,就可以获取所有系统的访问权限,不用对每个单一系统都逐一登录。这项功能通常是以轻型目录访问协议(LDAP)来实现,在服务器上会将用户信息存储到LDAP数据库中。相同的,单一注销(single sign-off)就是指

Spring Security基于数据库验证流程详解

Spring Security 校验流程图 相关解释说明(认真看哦) AbstractAuthenticationProcessingFilter 抽象类 /*** 调用 #requiresAuthentication(HttpServletRequest, HttpServletResponse) 决定是否需要进行验证操作。* 如果需要验证,则会调用 #attemptAuthentica

计算机毕业设计 大学志愿填报系统 Java+SpringBoot+Vue 前后端分离 文档报告 代码讲解 安装调试

🍊作者:计算机编程-吉哥 🍊简介:专业从事JavaWeb程序开发,微信小程序开发,定制化项目、 源码、代码讲解、文档撰写、ppt制作。做自己喜欢的事,生活就是快乐的。 🍊心愿:点赞 👍 收藏 ⭐评论 📝 🍅 文末获取源码联系 👇🏻 精彩专栏推荐订阅 👇🏻 不然下次找不到哟~Java毕业设计项目~热门选题推荐《1000套》 目录 1.技术选型 2.开发工具 3.功能

kubelet组件的启动流程源码分析

概述 摘要: 本文将总结kubelet的作用以及原理,在有一定基础认识的前提下,通过阅读kubelet源码,对kubelet组件的启动流程进行分析。 正文 kubelet的作用 这里对kubelet的作用做一个简单总结。 节点管理 节点的注册 节点状态更新 容器管理(pod生命周期管理) 监听apiserver的容器事件 容器的创建、删除(CRI) 容器的网络的创建与删除

火语言RPA流程组件介绍--浏览网页

🚩【组件功能】:浏览器打开指定网址或本地html文件 配置预览 配置说明 网址URL 支持T或# 默认FLOW输入项 输入需要打开的网址URL 超时时间 支持T或# 打开网页超时时间 执行后后等待时间(ms) 支持T或# 当前组件执行完成后继续等待的时间 UserAgent 支持T或# User Agent中文名为用户代理,简称 UA,它是一个特殊字符串头,使得服务器

ispunct函数讲解 <ctype.h>头文件函数

目录 1.头文件函数 2.ispunct函数使用  小心!VS2022不可直接接触,否则..!没有这个必要,方源一把抓住VS2022,顷刻 炼化! 1.头文件函数 以上函数都需要包括头文件<ctype.h> ,其中包括 ispunct 函数 #include<ctype.h> 2.ispunct函数使用 简述: ispunct函数一种判断字符是否为标点符号的函

深度学习速通系列:深度学习算法讲解

深度学习算法是一系列基于人工神经网络的算法,它们通过模拟人脑处理信息的方式来学习和解决复杂问题。这些算法在图像识别、语音识别、自然语言处理、游戏等领域取得了显著的成就。以下是一些流行的深度学习算法及其基本原理: 1. 前馈神经网络(Feedforward Neural Networks, FNN) 原理:FNN 是最基本的神经网络结构,它由输入层、隐藏层和输出层组成。信息从输入层流向隐藏层,最

UMI复现代码运行逻辑全流程(一)——eval_real.py(尚在更新)

一、文件夹功能解析 全文件夹如下 其中,核心文件作用为: diffusion_policy:扩散策略核心文件夹,包含了众多模型及基础库 example:标定及配置文件 scripts/scripts_real:测试脚本文件,区别在于前者倾向于单体运行,后者为整体运行 scripts_slam_pipeline:orb_slam3运行全部文件 umi:核心交互文件夹,作用在于构建真

C#设计模式(1)——单例模式(讲解非常清楚)

一、引言 最近在学设计模式的一些内容,主要的参考书籍是《Head First 设计模式》,同时在学习过程中也查看了很多博客园中关于设计模式的一些文章的,在这里记录下我的一些学习笔记,一是为了帮助我更深入地理解设计模式,二同时可以给一些初学设计模式的朋友一些参考。首先我介绍的是设计模式中比较简单的一个模式——单例模式(因为这里只牵涉到一个类) 二、单例模式的介绍 说到单例模式,大家第一

C++/《C/C++程序编译流程》

程序的基本流程如图:   1.预处理        预处理相当于根据预处理指令组装新的C/C++程序。经过预处理,会产生一个没有宏定义,没有条件编译指令,没有特殊符号的输出文件,这个文件的含义同原本的文件无异,只是内容上有所不同。 读取C/C++源程序,对其中的伪指令(以#开头的指令)进行处理将所有的“#define”删除,并且展开所有的宏定义处理所有的条件编译指令,如:“#if”、“