CTP接口笔记(2)- 行情接口

本文详细介绍了期货API接口的使用方法,包括行情API的CThostFtdcMdApi和CThostFtdcMdSpi组件,以及如何重载回调函数来接收行情数据。通过创建CThostFtdcMdApi实例,连接到服务器,实现登录和订阅行情的功能。在代码示例中,展示了如何订阅并处理深度市场数据。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

开始之前,强烈建议阅读下官方出的API接口说明,是个.chm文件,在上期技术官网可以找到,就在api接口下载页那里。
P.S. simnow自22年7月8日起关闭一个月,上期技术官网也关闭了。。。


一. 接口的使用方法

1.API&SPI
行情接口分为两大块:CThostFtdcMdApi和CthostFtdcMdspi,前者提供了行情api的初始化,登录,订阅等功能;后者提供了行情相关的回调接口,用户需要继承该类并重载这些接口,以获取响应数据。(交易接口也分为了API和SPI)
图片描述

打开头文件的样子:
在这里插入图片描述

2.如何使用
无论是行情接口还是接口,大部分功能(在API中)都有对应的回调函数(在SPI中),例如API中的SubscribeMarketData,这个函数功能是订阅行情,如果要使用这个功能的话需要在程序调用之后重载它的回调函数OnRspSubMarketData,然后再重载OnRtnDepthMarketData,就可以收到深度行情了,重载OnRtnDepthMarketData时可以选择获得什么数据。
所有的回调函数对应的功能都可以在API接口说明中找到。

二.接口代码

1.把行情接口的头文件和源文件准备好
在项目中建好main.cpp,MdApi.cpp还有MdApi.h。
在这里插入图片描述

先在MdApi.h中把要重载的行情接口写好,参数在接口说明中可以找到。(交易接口有很多功能,自己开发的时候要根据情况选择。)

//MdSpi.h
#pragma once
#include"../sdk/ThostFtdcMdApi.h"
#include <stdio.h>
#include <Windows.h>
//链接库
#pragma comment (lib, "thostmduserapi_se.lib")
#pragma comment (lib, "thosttraderapi_se.lib")
#pragma warning(disable : 4996)
using namespace std;
//MdApi继承了CThostFtdcMdSpi类,并且重载了OnRtnDepthMarketData等接口
class MdApi :public CThostFtdcMdSpi
{
public:
	// 当客户端与交易后台建立起通信连接时(还未登录前),该方法被调用。在Init()之后,被重载的话就会调用他
	void OnFrontConnected();
	//在发送登录请求之后,还需要重载回调函数 OnRspUserLogin 接收登陆信息。
	//注意如果登录的本机ip在当前交易日没有登录过交易系统,那么直接行情登录的话会报错,返回“不合法的登录”
	void OnRspUserLogin(CThostFtdcRspUserLoginField* pRspUserLogin, CThostFtdcRspInfoField* pRspInfo, int nRequestID, bool bIsLast);
	//订阅行情应答,调用SubscribeMarketData后,通过此接口返回。
	void OnRspSubMarketData(CThostFtdcSpecificInstrumentField* pSpecificInstrument, CThostFtdcRspInfoField* pRspInfo, int nRequestID, bool bIsLast);
	//订阅深度行情,包括最新价,昨持仓量等等
	void OnRtnDepthMarketData(CThostFtdcDepthMarketDataField* pDepthMarketData);
}; 

在main.cpp中创建CThostFtdcMdApi实例,并连接到simnow的服务器地址,simnow是上期技术的仿真平台。
建议连接之前ping一下simnow的地址,有时候会关闭。最近一次是从2022年7月8日起,关闭一个月。

//main.cpp
#include <stdio.h>
#include <iostream>
#include <../sdk/ThostFtdcMdApi.h>	
#include "MdApi.h"
using namespace std;
//链接库
#pragma comment(lib,"thostmduserapi_se.lib")
#pragma comment(lib,"thosttraderapi_se.lib")
CThostFtdcMdApi* m_MdApi;

//行情接口
void MDconnect()
{
	m_MdApi = CThostFtdcMdApi::CreateFtdcMdApi();//通过CreateFtdcMdApi创建了一个API实例,将他赋值给m_MdApi
	CThostFtdcMdSpi* MdSpi = new MdApi; //建立了一个Spi实例--->MdSpi  这里的MdApi在MdApi.h里创建的类
	m_MdApi->RegisterSpi(MdSpi);//通过RegisterSpi将API(m_MdApi)和SPI(MdSpi)绑定
	m_MdApi->RegisterFront("tcp://180.168.146.187:10211");//注册了前置地址以便与服务器连接。
	m_MdApi->Init();//调用 Init() 函数开始正式初始化 api,也就是说前面的工作只是准备工作,到了这里 api 才真正开始工作。此时 api 会向之前注册的地址发起与 CTP 前置的连接
	m_MdApi->Join();
}
int main(){
	MDconnect();
	system("pause");
}

最后在MdApi.cpp中进行重载

//MdApi.cpp
#include <iostream>
#include "MdApi.h"
using namespace std;
extern CThostFtdcMdApi* m_MdApi;//声明全局变量 m_MdApi,也就是在main,cpp中创建的 Api 实例

//登录代码直接写在了 OnFrontConnected 中,那么这也就意味着,一旦建立网络连接成功,调用 OnFrontConnected 之后便会进行登录操作
void MdApi::OnFrontConnected()
{
	//如果这里没有输出,那么去检查RegisterFront的地址对不对,ping一下
	cout << "网络链接链接成功" << endl;
	//开始登录,如果是simnow账号,如果是第一次登录,需要修改密码(ReqUserPasswordUpdate)
	CThostFtdcReqUserLoginField req; //创建了一个 CThostFtdcReqUserLoginField 类型的对象
	memset(&req, 0, sizeof(req));//初始化登录数据
	strcpy(req.BrokerID, ""); //simnow是9999
	strcpy(req.UserID, ""); //去simnow注册个账号
	strcpy(req.Password, ""); 
	static int iRequestID = 0;
	//调用登录,然后就要重载OnRspUserLogin来进行登录
	int iResult = m_MdApi->ReqUserLogin(&req, iRequestID++);
	if (!iResult)
		cout << "发送登录请求成功" << endl;
	else
		cerr << "发送登录请求失败" << endl;
}

void MdApi::OnRspUserLogin(CThostFtdcRspUserLoginField* pRspUserLogin, CThostFtdcRspInfoField* pRspInfo, int nRequestID, bool bIsLast)
{
	bool bResult = pRspInfo && (pRspInfo->ErrorID != 0);
	if (!bResult) {
		cout << "账户登录成功" << endl;
		cout << "交易日: " << pRspUserLogin->TradingDay << endl;
		//开始订阅行情,注意别写错合约了,当然你也可以写外面
		char* iInstrumentID[] = { "i2201" ,"cu2201" };
		int iCount = sizeof(iInstrumentID) / sizeof(iInstrumentID[0]);
		m_MdApi->SubscribeMarketData(iInstrumentID, iCount);//SubscribeMarketData(char **ppInstrument,int nCount)
	}
	else
		cerr << "返回错误--->>> ErrorID=" << pRspInfo->ErrorID << ", ErrorMsg=" << pRspInfo->ErrorMsg << endl;
}

void MdApi::OnRspSubMarketData(CThostFtdcSpecificInstrumentField* pSpecificInstrument, CThostFtdcRspInfoField* pRspInfo, int nRequestID, bool bIsLast)
{
	bool bResult = pRspInfo && (pRspInfo->ErrorID != 0);
	if (!bResult) {
		cout << "订阅行情成功" << endl;
		cout << "合约代码: " << pSpecificInstrument->InstrumentID << endl;

	}
	else
		cerr << "返回错误--->>> ErrorID=" << pRspInfo->ErrorID << ", ErrorMsg=" << pRspInfo->ErrorMsg << endl;
}

void MdApi::OnRtnDepthMarketData(CThostFtdcDepthMarketDataField* pDepthMarketData)
{	
	//有很多数据,可以自己选择要接受那些
	cout << "=====获得深度行情成功=====" << endl;
	cout << "合约代码:" << pDepthMarketData->InstrumentID << endl;
	cout << "最新价:" << pDepthMarketData->LastPrice << endl;
	cout << "成交量:" << pDepthMarketData->Volume << endl;
}

写完这里就可以运行main.cpp了,但是应该没有输出,因为simnow自2022年7月8号起关闭一个月。只能过段时间再测试了

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值