提示:在看本博客之前建议先阅读上期所官方的开发文档(SimNow官网中去下载CTP接口文件),然后在SimNow官网注册模拟账号。
提示:股票CTP接口和期货CTP接口类似。若要换经纪商,则只需要将main.cpp文件中的模拟经纪商代码等修改成对应经纪商提供的即可。模拟盘和实盘的转换也只需要替换头文件和链接库文件即可。
上期所官方的开发文档下载地址:
链接: http://www.sfit.com.cn/5_1_DocumentDown.htm .
或百度网盘下载Api接口开发文档:
链接: Api开发文档
提取码:pv2f
ctp接口文件(v6.6.1版本):
链接: https://pan.baidu.com/s/1b3B3OnyqYOyjYHT30-Guhg.
提取码:aoje
量化交易起源于上世纪七十年代,之后迅速发展和普及,尤其是在期货交易市场,程序化逐渐成为主流,有数据显示,国外成熟市场期货程序化交易占总交易量的70%-80%,而国内则刚刚起步,手工交易中交易者的情绪波动等弊端都会导致亏损。随着人工智能和数据分析的发展,越来越多的人开始使用程序化交易。
CTP是上海期货推出的一套程序调用的交易接口。
在登录行情服务器时,不需要账号和密码,也可以通过CTP接口获取行情。
CThostFtdcMdSpi --> 是行情接口文件
行情接口代码如下:
#include
#include
#include
#include "CustomMdSpi.h"
// ---- 全局参数声明 ---- //
//如果函数的声明中带有关键字extern,仅仅是暗示这个函数可能在别的源文件里定义,没有其它作用
extern CThostFtdcMdApi* g_pMdUserApi; // 行情指针
extern char gMdFrontAddr[]; // 模拟行情前置地址
extern TThostFtdcBrokerIDType gBrokerID; // 模拟经纪商代码
extern TThostFtdcInvestorIDType gInvesterID; // 投资者账户名
extern TThostFtdcPasswordType gInvesterPassword; // 投资者密码
extern char* g_pInstrumentID[]; // 行情合约代码列表,中、上、大、郑交易所各选一种
extern int instrumentNum; // 行情合约订阅数量
// ---- ctp_api回调函数 ---- //
// 连接成功应答
void CustomMdSpi::OnFrontConnected()
{
std::cout << "=====建立网络连接成功=====" << std::endl;
// 开始登录
CThostFtdcReqUserLoginField loginReq;
memset(&loginReq, 0, sizeof(loginReq));
strcpy(loginReq.BrokerID, gBrokerID);
strcpy(loginReq.UserID, gInvesterID);
strcpy(loginReq.Password, gInvesterPassword);
static int requestID = 0; // 请求编号
int rt = g_pMdUserApi->ReqUserLogin(&loginReq, ++requestID);
if (!rt)
std::cout << "--->>>行情--发送登录请求成功" << std::endl;
else
std::cerr << "--->>>行情--发送登录请求失败,错误码:"<< rt << std::endl;
}
// 断开连接通知
void CustomMdSpi::OnFrontDisconnected(int nReason)
{
std::cerr << "=====网络连接断开=====" << std::endl;
std::cerr << "错误码: " << nReason << std::endl;
}
// 心跳超时警告
void CustomMdSpi::OnHeartBeatWarning(int nTimeLapse)
{
std::cerr << "=====网络心跳超时=====" << std::endl;
std::cerr << "距上次连接时间: " << nTimeLapse << std::endl;
}
// 登录应答
void CustomMdSpi::OnRspUserLogin(CThostFtdcRspUserLoginField* pRspUserLogin, CThostFtdcRspInfoField* pRspInfo, int nRequestID, bool bIsLast)
{
bool bResult = pRspInfo && (pRspInfo->ErrorID != 0);
if (!bResult)
{
std::cout << "=====账户登录成功=====" << std::endl;
std::cout << "交易日: " << pRspUserLogin->TradingDay << std::endl;
std::cout << "登录时间: " << pRspUserLogin->LoginTime << std::endl;
std::cout << "经纪商: " << pRspUserLogin->BrokerID << std::endl;
std::cout << "帐户名: " << pRspUserLogin->UserID << std::endl;
// 开始订阅行情
int rt = g_pMdUserApi->SubscribeMarketData(g_pInstrumentID, instrumentNum);
if (!rt)
std::cout << ">>>>>>发送订阅行情请求成功" << std::endl;
else
std::cerr << "--->>>发送订阅行情请求失败" << std::endl;
}
else
std::cerr << "返回错误--->>> ErrorID=" << pRspInfo->ErrorID << ", ErrorMsg=" << pRspInfo->ErrorMsg << std::endl;
}
// 登出应答
void CustomMdSpi::OnRspUserLogout(CThostFtdcUserLogoutField* pUserLogout, CThostFtdcRspInfoField* pRspInfo, int nRequestID, bool bIsLast)
{
bool bResult = pRspInfo && (pRspInfo->ErrorID != 0);
if (!bResult)
{
std::cout << "=====账户登出成功=====" << std::endl;
std::cout << "经纪商: " << pUserLogout->BrokerID << std::endl;
std::cout << "帐户名: " << pUserLogout->UserID << std::endl;
}
else
std::cerr << "返回错误--->>> ErrorID=" << pRspInfo->ErrorID << ", ErrorMsg=" << pRspInfo->ErrorMsg << std::endl;
}
// 错误通知
void CustomMdSpi::OnRspError(CThostFtdcRspInfoField* pRspInfo, int nRequestID, bool bIsLast)
{
bool bResult = pRspInfo && (pRspInfo->ErrorID != 0);
if (bResult)
std::cerr << "返回错误--->>> ErrorID=" << pRspInfo->ErrorID << ", ErrorMsg=" << pRspInfo->ErrorMsg << std::endl;
}
// 订阅行情应答
void CustomMdSpi::OnRspSubMarketData(CThostFtdcSpecificInstrumentField* pSpecificInstrument, CThostFtdcRspInfoField* pRspInfo, int nRequestID, bool bIsLast)
{
bool bResult = pRspInfo && (pRspInfo->ErrorID != 0);
if (!bResult)
{
std::cout << "=====订阅行情成功=====" << std::endl;
std::cout << "合约代码: " << pSpecificInstrument->InstrumentID << std::endl;
// 如果需要存入文件或者数据库,在这里创建表头,不同的合约单独存储
char filePath[100] = { '\0' };
sprintf(filePath, ".//SqlData//%s_market_data.csv", pSpecificInstrument->InstrumentID);
std::ofstream outFile;
outFile.open(filePath, std::ios::out); // 新开文件
outFile << "合约代码" << ","
<< "更新时间" << ","
<< "最新价" << ","
<< "成交量" << ","
<< "买价一" << ","
<< "买量一" << ","
<< "卖价一" << ","
<< "卖量一" << ","
<< "持仓量" << ","
<< "换手率"
<< std::endl;
outFile.close();
}
else
std::cerr << "返回错误--->>> ErrorID=" << pRspInfo->ErrorID << ", ErrorMsg=" << pRspInfo->ErrorMsg << std::endl;
}
// 取消订阅行情应答
void CustomMdSpi::OnRspUnSubMarketData(CThostFtdcSpecificInstrumentField* pSpecificInstrument, CThostFtdcRspInfoField* pRspInfo,
int nRequestID,
bool bIsLast)
{
bool bResult = pRspInfo && (pRspInfo->ErrorID != 0);
if (!bResult)
{
std::cout << "=====取消订阅行情成功=====" << std::endl;
std::cout << "合约代码: " << pSpecificInstrument->InstrumentID << std::endl;
}
else
std::cerr << "返回错误--->>> ErrorID=" << pRspInfo->ErrorID << ", ErrorMsg=" << pRspInfo->ErrorMsg << std::endl;
}
// 订阅询价应答
void CustomMdSpi::OnRspSubForQuoteRsp(CThostFtdcSpecificInstrumentField* pSpecificInstrument, CThostFtdcRspInfoField* pRspInfo, int nRequestID, bool bIsLast)
{
bool bResult = pRspInfo && (pRspInfo->ErrorID != 0);
if (!bResult)
{
std::cout << "=====订阅询价成功=====" << std::endl;
std::cout << "合约代码: " << pSpecificInstrument->InstrumentID << std::endl;
}
else
std::cerr << "返回错误--->>> ErrorID=" << pRspInfo->ErrorID << ", ErrorMsg=" << pRspInfo->ErrorMsg << std::endl;
}
// 取消订阅询价应答
void CustomMdSpi::OnRspUnSubForQuoteRsp(CThostFtdcSpecificInstrumentField* pSpecificInstrument, CThostFtdcRspInfoField* pRspInfo, int nRequestID, bool bIsLast)
{
bool bResult = pRspInfo && (pRspInfo->ErrorID != 0);
if (!bResult)
{
std::cout << "=====取消订阅询价成功=====" << std::endl;
std::cout << "合约代码: " << pSpecificInstrument->InstrumentID << std::endl;
}
else
std::cerr << "返回错误--->>> ErrorID=" << pRspInfo->ErrorID << ", ErrorMsg=" << pRspInfo->ErrorMsg << std::endl;
}
// 行情详情通知
void CustomMdSpi::OnRtnDepthMarketData(CThostFtdcDepthMarketDataField* pDepthMarketData)
{
// 打印行情,字段较多,截取部分
std::cout << "=====获得深度行情=====" << std::endl;
std::cout << "交易日: " << pDepthMarketData->TradingDay << std::endl;
std::cout << "交易所代码: " << pDepthMarketData->ExchangeID << std::endl;
std::cout << "合约代码: " << pDepthMarketData->InstrumentID << std::endl;
std::cout << "合约在交易所的代码: " << pDepthMarketData->ExchangeInstID << std::endl;
std::cout << "最新价: " << pDepthMarketData->LastPrice << std::endl;
std::cout << "数量: " << pDepthMarketData->Volume << std::endl;
// 将行情写入到csv文件中
// 如果只获取某一个合约行情,可以逐tick地存入文件或数据库
//char filePath[100] = { '\0' };
//sprintf(filePath, "%s_market_data.csv", pDepthMarketData->InstrumentID);
//std::ofstream outFile;
//outFile.open(filePath, std::ios::app); // 文件追加写入
//outFile << pDepthMarketData->InstrumentID << ","
// << pDepthMarketData->UpdateTime << "." << pDepthMarketData->UpdateMillisec << ","
// << pDepthMarketData->LastPrice << ","
// << pDepthMarketData->Volume << ","
// << pDepthMarketData->BidPrice1 << ","
// << pDepthMarketData->BidVolume1 << ","
// << pDepthMarketData->AskPrice1 << ","
// << pDepthMarketData->AskVolume1 << ","
// << pDepthMarketData->OpenInterest << ","
// << pDepthMarketData->Turnover << std::endl;
//outFile.close();
// 计算实时k线
// 取消订阅行情
//int rt = g_pMdUserApi->UnSubscribeMarketData(g_pInstrumentID, instrumentNum);
//if (!rt)
// std::cout << ">>>>>>发送取消订阅行情请求成功" << std::endl;
//else
// std::cerr << "--->>>发送取消订阅行情请求失败" << std::endl;
}
// 询价详情通知
void CustomMdSpi::OnRtnForQuoteRsp(CThostFtdcForQuoteRspField* pForQuoteRsp)
{
// 部分询价结果
std::cout << "=====获得询价结果=====" << std::endl;
std::cout << "交易日: " << pForQuoteRsp->TradingDay << std::endl;
std::cout << "交易所代码: " << pForQuoteRsp->ExchangeID << std::endl;
std::cout << "合约代码: " << pForQuoteRsp->InstrumentID << std::endl;
std::cout << "询价编号: " << pForQuoteRsp->ForQuoteSysID << std::endl;
}
示例代码如下:
#include
#include
#include
#include
#include
#include "CustomTradeSpi.h"
#include "ThostFtdcUserApiDataType.h"
// ---- 全局参数声明 ---- //
extern TThostFtdcBrokerIDType gBrokerID; // 模拟经纪商代码
extern TThostFtdcInvestorIDType gInvesterID; // 投资者账户名
extern TThostFtdcPasswordType gInvesterPassword; // 投资者密码
extern CThostFtdcTraderApi* g_pTradeUserApi; // 交易指针
extern char gTradeFrontAddr[]; // 模拟交易前置地址
extern TThostFtdcInstrumentIDType g_pTradeInstrumentID; // 所交易的合约代码
extern TThostFtdcPriceType gLimitPrice; // 交易价格
extern TThostFtdcAppIDType AppID; // AppID
extern TThostFtdcAuthCodeType AuthCode; // 授权码
// 会话参数
TThostFtdcFrontIDType trade_front_id; //前置编号
TThostFtdcSessionIDType session_id; //会话编号
TThostFtdcOrderRefType order_ref; //报单引用
void CustomTradeSpi::OnFrontConnected()
{
std::cout << "====网络连接成功===" << std::endl;
// 登录前客户端认证
reqAuthenticate();
}
void CustomTradeSpi::OnRspAuthenticate(CThostFtdcRspAuthenticateField* pRspAuthenticateField, CThostFtdcRspInfoField* pRspInfo, int nRequestID, bool bIsLast)
{
if (!isErrorRspInfo(pRspInfo))
{
// 登录
reqUserLogin();
}
}
void CustomTradeSpi::OnRspUserLogin(CThostFtdcRspUserLoginField* pRspUserLogin, CThostFtdcRspInfoField* pRspInfo, int nRequestID, bool bIsLast)
{
if (!isErrorRspInfo(pRspInfo)) {
std::cout << "=====交易账户登录成功====" << std::endl;
loginFlag = true;
std::cout << "交易日:" << pRspUserLogin->TradingDay << std::endl;
std::cout << "登录时间:" << pRspUserLogin->LoginTime << std::endl;
std::cout << "经纪商:" << pRspUserLogin->BrokerID << std::endl;
std::cout << "账户名:" << pRspUserLogin->UserID << std::endl;
//保存会话参数
trade_front_id = pRspUserLogin->FrontID; // 前置编号
session_id = pRspUserLogin->SessionID; // 会话编号
strcpy(order_ref, pRspUserLogin->MaxOrderRef); // 最大保单引用
// 投资者结算结果确认
reqSettlementInfoConfirm();
}
}
void CustomTradeSpi::OnRspError(CThostFtdcRspInfoField* pRspInfo, int nRequestID, bool bIsLast)
{
isErrorRspInfo(pRspInfo);
}
void CustomTradeSpi::OnFrontDisconnected(int nReason)
{
std::cerr << "=====网络连接断开=====" << std::endl;
std::cerr << "错误码: " << nReason << std::endl;
}
void CustomTradeSpi::OnHeartBeatWarning(int nTimeLapse)
{
std::cerr << "=====网络心跳超时=====" << std::endl;
std::cerr << "距上次连接时间: " << nTimeLapse << std::endl;
}
void CustomTradeSpi::OnRspUserLogout(
CThostFtdcUserLogoutField* pUserLogout,
CThostFtdcRspInfoField* pRspInfo,
int nRequestID,
bool bIsLast)
{
if (!isErrorRspInfo(pRspInfo))
{
loginFlag = false; // 登出就不能再交易了
std::cout << "=====账户登出成功=====" << std::endl;
std::cout << "经纪商: " << pUserLogout->BrokerID << std::endl;
std::cout << "帐户名: " << pUserLogout->UserID << std::endl;
}
}
void CustomTradeSpi::OnRspSettlementInfoConfirm(CThostFtdcSettlementInfoConfirmField* pSettlementInfoConfirm, CThostFtdcRspInfoField* pRspInfo, int nRequestID, bool bIsLast)
{
if (!isErrorRspInfo(pRspInfo))
{
std::cout << "=====投资者结算结果确认成功=====" << std::endl;
std::cout << "确认日期: " << pSettlementInfoConfirm->ConfirmDate << std::endl;
std::cout << "确认时间: " << pSettlementInfoConfirm->ConfirmTime << std::endl;
// 请求查询合约
reqQueryInstrument();
}
}
void CustomTradeSpi::OnRspQryInstrument(CThostFtdcInstrumentField* pInstrument, CThostFtdcRspInfoField* pRspInfo, int nRequestID,bool bIsLast)
{
if (!isErrorRspInfo(pRspInfo))
{
std::cout << "=====查询合约结果成功=====" << std::endl;
std::cout << "交易所代码: " << pInstrument->ExchangeID << std::endl;
std::cout << "合约代码: " << pInstrument->InstrumentID << std::endl;
std::cout << "合约在交易所的代码: " << pInstrument->ExchangeInstID << std::endl;
std::cout << "执行价: " << pInstrument->StrikePrice << std::endl;
std::cout << "到期日: " << pInstrument->EndDelivDate << std::endl;
std::cout << "当前交易状态: " << pInstrument->IsTrading << std::endl;
// 请求查询投资者资金账户(CTP为就绪,后续实盘测测)
reqQueryTradingAccount();
//buy_open(g_pTradeInstrumentID, gLimitPrice, 1);
//sell_open(g_pTradeInstrumentID, gLimitPrice, 1);
//buy_close(g_pTradeInstrumentID, gLimitPrice, 1);
//sell_close(g_pTradeInstrumentID, gLimitPrice, 1);
}
}
void CustomTradeSpi::OnRspQryTradingAccount(CThostFtdcTradingAccountField* pTradingAccount, CThostFtdcRspInfoField* pRspInfo, int nRequestID, bool bIsLast)
{
if (!isErrorRspInfo(pRspInfo))
{
std::cout << "=====查询投资者资金账户成功=====" << std::endl;
std::cout << "投资者账号: " << pTradingAccount->AccountID << std::endl;
std::cout << "可用资金: " << pTradingAccount->Available << std::endl;
std::cout << "可取资金: " << pTradingAccount->WithdrawQuota << std::endl;
std::cout << "当前保证金: " << pTradingAccount->CurrMargin << std::endl;
std::cout << "平仓盈亏: " << pTradingAccount->CloseProfit << std::endl;
// 请求查询投资者持仓
reqQueryInvestorPosition();
}
}
void CustomTradeSpi::OnRspQryInvestorPosition(CThostFtdcInvestorPositionField* pInvestorPosition, CThostFtdcRspInfoField* pRspInfo, int nRequestID,bool bIsLast)
{
if (!isErrorRspInfo(pRspInfo))
{
std::cout << "=====查询投资者持仓成功=====" << std::endl;
if (pInvestorPosition)
{
std::cout << "合约代码: " << pInvestorPosition->InstrumentID << std::endl;
std::cout << "开仓价格: " << pInvestorPosition->OpenAmount << std::endl;
std::cout << "开仓量: " << pInvestorPosition->OpenVolume << std::endl;
std::cout << "开仓方向: " << pInvestorPosition->PosiDirection << std::endl;
std::cout << "占用保证金:" << pInvestorPosition->UseMargin << std::endl;
}
else
std::cout << "----->该合约未持仓" << std::endl;
// 报单录入请求(这里是一部接口,此处是按顺序执行)
/*if (loginFlag)
reqOrderInsert();*/
//if (loginFlag)
// buy_open(); // 自定义一笔交易
// 策略交易
std::cout << "=====开始进入策略交易=====" << std::endl;
//while (loginFlag) {
// StrategyCheckAndTrade(g_pTradeInstrumentID, this); // 调用策略
//}
}
}
void CustomTradeSpi::OnRspOrderInsert(CThostFtdcInputOrderField* pInputOrder, CThostFtdcRspInfoField* pRspInfo, int nRequestID, bool bIsLast)
{
if (!isErrorRspInfo(pRspInfo))
{
std::cout << "=====报单录入成功=====" << std::endl;
std::cout << "合约代码: " << pInputOrder->InstrumentID << std::endl;
std::cout << "价格: " << pInputOrder->LimitPrice << std::endl;
std::cout << "数量: " << pInputOrder->VolumeTotalOriginal << std::endl;
std::cout << "开仓方向: " << pInputOrder->Direction << std::endl;
}
}
void CustomTradeSpi::OnRspOrderAction(CThostFtdcInputOrderActionField* pInputOrderAction, CThostFtdcRspInfoField* pRspInfo, int nRequestID, bool bIsLast)
{
if (!isErrorRspInfo(pRspInfo))
{
std::cout << "=====报单操作成功=====" << std::endl;
std::cout << "合约代码: " << pInputOrderAction->InstrumentID << std::endl;
std::cout << "操作标志: " << pInputOrderAction->ActionFlag;
}
}
void CustomTradeSpi::OnRtnOrder(CThostFtdcOrderField* pOrder)
{
char str[10];
sprintf(str, "%d", pOrder->OrderSubmitStatus);
int orderState = atoi(str) - 48; //报单状态0=已经提交,3=已经接受
std::cout << "=====收到报单应答=====" << std::endl;
if (isMyOrder(pOrder))
{
if (isTradingOrder(pOrder))
{
std::cout << "--->>> 等待成交中!" << std::endl;
//reqOrderAction(pOrder); // 这里可以撤单
//reqUserLogout(); // 登出测试
}
else if (pOrder->OrderStatus == THOST_FTDC_OST_Canceled)
std::cout << "--->>> 撤单成功!" << std::endl;
}
}
void CustomTradeSpi::OnRtnTrade(CThostFtdcTradeField* pTrade)
{
std::cout << "=====报单成功成交=====" << std::endl;
std::cout << "成交时间: " << pTrade->TradeTime << std::endl;
std::cout << "合约代码: " << pTrade->InstrumentID << std::endl;
std::cout << "成交价格: " << pTrade->Price << std::endl;
std::cout << "成交量: " << pTrade->Volume << std::endl;
std::cout << "开平仓方向: " << pTrade->Direction << std::endl;
}
bool CustomTradeSpi::isErrorRspInfo(CThostFtdcRspInfoField* pRspInfo)
{
bool bResult = pRspInfo && (pRspInfo->ErrorID != 0);
if (bResult)
std::cerr << "返回错误--->>> ErrorID=" << pRspInfo->ErrorID << ", ErrorMsg=" << pRspInfo->ErrorMsg << std::endl;
return bResult;
}
// 客户端认证请求
void CustomTradeSpi::reqAuthenticate()
{
CThostFtdcReqAuthenticateField req;
memset(&req, 0, sizeof(req));
strcpy(req.BrokerID, gBrokerID);
strcpy(req.AppID, AppID);
strcpy(req.AuthCode, AuthCode);
strcpy(req.UserID, gInvesterID);
static int requestID = 0;
int iResult = g_pTradeUserApi->ReqAuthenticate(&req, requestID);
std::cerr << "---> 发送客户端认证:" << ((iResult == 0) ? "成功" : "失败") << std::endl;
}
// 登录
void CustomTradeSpi::reqUserLogin()
{
CThostFtdcReqUserLoginField loginReq;
memset(&loginReq, 0, sizeof(loginReq));
strcpy(loginReq.BrokerID, gBrokerID);
strcpy(loginReq.UserID, gInvesterID);
strcpy(loginReq.Password, gInvesterPassword);
static int requestID = 0; // 请求编号
int rt = g_pTradeUserApi->ReqUserLogin(&loginReq, requestID);
if (!rt)
std::cout << ">>>>>>交易--发送登录请求成功" << std::endl;
else
std::cerr << "--->>>交易--发送登录请求失败" << std::endl;
}
// 登出
void CustomTradeSpi::reqUserLogout()
{
CThostFtdcUserLogoutField logoutReq;
memset(&logoutReq, 0, sizeof(logoutReq));
strcpy(logoutReq.BrokerID, gBrokerID);
strcpy(logoutReq.UserID, gInvesterID);
static int requestID = 0; // 请求编号
int rt = g_pTradeUserApi->ReqUserLogout(&logoutReq, requestID);
if (!rt)
std::cout << ">>>>>>交易--发送登出请求成功" << std::endl;
else
std::cerr << "--->>>交易--发送登出请求失败" << std::endl;
}
// 投资者结算结果确认
void CustomTradeSpi::reqSettlementInfoConfirm()
{
CThostFtdcSettlementInfoConfirmField settlementConfirmReq;
memset(&settlementConfirmReq, 0, sizeof(settlementConfirmReq));
strcpy(settlementConfirmReq.BrokerID, gBrokerID);
strcpy(settlementConfirmReq.InvestorID, gInvesterID);
static int requestID = 0; // 请求编号
int rt = g_pTradeUserApi->ReqSettlementInfoConfirm(&settlementConfirmReq, requestID);
if (!rt)
{
std::cout << ">>>>>>发送投资者结算结果确认请求成功" << std::endl;
}
else
std::cerr << "--->>>发送投资者结算结果确认请求失败" << std::endl;
}
// 请求查询合约
void CustomTradeSpi::reqQueryInstrument()
{
CThostFtdcQryInstrumentField instrumentReq;
memset(&instrumentReq, 0, sizeof(instrumentReq));
strcpy(instrumentReq.InstrumentID, g_pTradeInstrumentID);
static int requestID = 0; // 请求编号
int rt = g_pTradeUserApi->ReqQryInstrument(&instrumentReq, requestID);
if (!rt)
std::cout << ">>>>>>发送合约查询请求成功" << std::endl;
else
std::cerr << "--->>>发送合约查询请求失败" << std::endl;
}
// 请求查询资金帐户
void CustomTradeSpi::reqQueryTradingAccount()
{
CThostFtdcQryTradingAccountField tradingAccountReq;
memset(&tradingAccountReq, 0, sizeof(tradingAccountReq));
strcpy(tradingAccountReq.BrokerID, gBrokerID);
strcpy(tradingAccountReq.InvestorID, gInvesterID);
static int requestID = 0; // 请求编号
std::this_thread::sleep_for(std::chrono::milliseconds(700)); // 有时候需要停顿一会才能查询成功
int rt = g_pTradeUserApi->ReqQryTradingAccount(&tradingAccountReq, requestID);
if (!rt)
std::cout << ">>>>>>发送投资者资金账户查询请求成功" << std::endl;
else
std::cerr << "--->>>发送投资者资金账户查询请求失败" << std::endl;
}
void CustomTradeSpi::reqQueryInvestorPosition()
{
CThostFtdcQryInvestorPositionField postionReq;
memset(&postionReq, 0, sizeof(postionReq));
strcpy(postionReq.BrokerID, gBrokerID);
strcpy(postionReq.InvestorID, gInvesterID);
strcpy(postionReq.InstrumentID, g_pTradeInstrumentID);
static int requestID = 0; // 请求编号
std::this_thread::sleep_for(std::chrono::milliseconds(700)); // 有时候需要停顿一会才能查询成功
int rt = g_pTradeUserApi->ReqQryInvestorPosition(&postionReq, requestID);
if (!rt)
std::cout << ">>>>>>发送投资者持仓查询请求成功" << std::endl;
else
std::cerr << "--->>>发送投资者持仓查询请求失败" << std::endl;
}
// 买开仓
void CustomTradeSpi::buy_open(TThostFtdcInstrumentIDType instrumentID, TThostFtdcPriceType NewPrice, TThostFtdcVolumeType volume)
{
CThostFtdcInputOrderField orderInsertReq;
memset(&orderInsertReq, 0, sizeof(orderInsertReq));
///经纪公司代码
strcpy(orderInsertReq.BrokerID, gBrokerID);
///投资者代码
strcpy(orderInsertReq.InvestorID, gInvesterID);
///合约代码
strcpy(orderInsertReq.InstrumentID, instrumentID);
///报单引用
strcpy(orderInsertReq.OrderRef, order_ref);
///报单价格条件: 限价
orderInsertReq.OrderPriceType = THOST_FTDC_OPT_LimitPrice;
///买卖方向:
orderInsertReq.Direction = THOST_FTDC_D_Buy;
///组合开平标志: 开仓、平仓等
orderInsertReq.CombOffsetFlag[0] = THOST_FTDC_OF_Open;
///组合投机套保标志
orderInsertReq.CombHedgeFlag[0] = THOST_FTDC_HF_Speculation;
///价格
orderInsertReq.LimitPrice = NewPrice;
///数量:1
orderInsertReq.VolumeTotalOriginal = volume;
///有效期类型: 当日有效
orderInsertReq.TimeCondition = THOST_FTDC_TC_GFD;
///成交量类型: 任何数量
orderInsertReq.VolumeCondition = THOST_FTDC_VC_AV;
///最小成交量: 1
orderInsertReq.MinVolume = 1;
///触发条件: 立即
orderInsertReq.ContingentCondition = THOST_FTDC_CC_Immediately;
///强平原因: 非强平
orderInsertReq.ForceCloseReason = THOST_FTDC_FCC_NotForceClose;
///自动挂起标志: 否
orderInsertReq.IsAutoSuspend = 0;
///用户强评标志: 否
orderInsertReq.UserForceClose = 0;
static int requestID = 0; // 请求编号
int rt = g_pTradeUserApi->ReqOrderInsert(&orderInsertReq, ++requestID);
if (!rt)
std::cout << ">>>>>>发送买开仓报单录入请求成功" << std::endl;
else
std::cerr << "--->>>发送买开仓报单录入请求失败" << std::endl;
}
// 买平仓
void CustomTradeSpi::buy_close(TThostFtdcInstrumentIDType instrumentID, TThostFtdcPriceType NewPrice, TThostFtdcVolumeType volume, TThostFtdcTimeConditionType CombOffsetFlag)
{
CThostFtdcInputOrderField orderInsertReq;
memset(&orderInsertReq, 0, sizeof(orderInsertReq));
///经纪公司代码
strcpy(orderInsertReq.BrokerID, gBrokerID);
///投资者代码
strcpy(orderInsertReq.InvestorID, gInvesterID);
///合约代码
strcpy(orderInsertReq.InstrumentID, instrumentID);
///报单引用
strcpy(orderInsertReq.OrderRef, order_ref);
///报单价格条件: 限价
orderInsertReq.OrderPriceType = THOST_FTDC_OPT_LimitPrice;
///买卖方向:
orderInsertReq.Direction = THOST_FTDC_D_Buy;
///组合开平标志: 开仓、平仓等
orderInsertReq.CombOffsetFlag[0] = CombOffsetFlag;
///组合投机套保标志
orderInsertReq.CombHedgeFlag[0] = THOST_FTDC_HF_Speculation;
///价格
orderInsertReq.LimitPrice = NewPrice;
///数量:1
orderInsertReq.VolumeTotalOriginal = volume;
///有效期类型: 当日有效
orderInsertReq.TimeCondition = THOST_FTDC_TC_GFD;
///成交量类型: 任何数量
orderInsertReq.VolumeCondition = THOST_FTDC_VC_AV;
///最小成交量: 1
orderInsertReq.MinVolume = 1;
///触发条件: 立即
orderInsertReq.ContingentCondition = THOST_FTDC_CC_Immediately;
///强平原因: 非强平
orderInsertReq.ForceCloseReason = THOST_FTDC_FCC_NotForceClose;
///自动挂起标志: 否
orderInsertReq.IsAutoSuspend = 0;
///用户强评标志: 否
orderInsertReq.UserForceClose = 0;
static int requestID = 0; // 请求编号
int rt = g_pTradeUserApi->ReqOrderInsert(&orderInsertReq, ++requestID);
if (!rt)
std::cout << ">>>>>>发送买平仓报单录入请求成功" << std::endl;
else
std::cerr << "--->>>发送买平仓报单录入请求失败" << std::endl;
}
// 卖开仓
void CustomTradeSpi::sell_open(TThostFtdcInstrumentIDType instrumentID, TThostFtdcPriceType NewPrice, TThostFtdcVolumeType volume)
{
CThostFtdcInputOrderField orderInsertReq;
memset(&orderInsertReq, 0, sizeof(orderInsertReq));
///经纪公司代码
strcpy(orderInsertReq.BrokerID, gBrokerID);
///投资者代码
strcpy(orderInsertReq.InvestorID, gInvesterID);
///合约代码
strcpy(orderInsertReq.InstrumentID, instrumentID);
///报单引用
strcpy(orderInsertReq.OrderRef, order_ref);
///报单价格条件: 限价
orderInsertReq.OrderPriceType = THOST_FTDC_OPT_LimitPrice;
///买卖方向:
orderInsertReq.Direction = THOST_FTDC_D_Sell;
///组合开平标志: 开仓、平仓等
orderInsertReq.CombOffsetFlag[0] = THOST_FTDC_OF_Open;
///组合投机套保标志
orderInsertReq.CombHedgeFlag[0] = THOST_FTDC_HF_Speculation;
///价格
orderInsertReq.LimitPrice = NewPrice;
///数量:1
orderInsertReq.VolumeTotalOriginal = volume;
///有效期类型: 当日有效
orderInsertReq.TimeCondition = THOST_FTDC_TC_GFD;
///成交量类型: 任何数量
orderInsertReq.VolumeCondition = THOST_FTDC_VC_AV;
///最小成交量: 1
orderInsertReq.MinVolume = 1;
///触发条件: 立即
orderInsertReq.ContingentCondition = THOST_FTDC_CC_Immediately;
///强平原因: 非强平
orderInsertReq.ForceCloseReason = THOST_FTDC_FCC_NotForceClose;
///自动挂起标志: 否
orderInsertReq.IsAutoSuspend = 0;
///用户强评标志: 否
orderInsertReq.UserForceClose = 0;
static int requestID = 0; // 请求编号
int rt = g_pTradeUserApi->ReqOrderInsert(&orderInsertReq, ++requestID);
if (!rt)
std::cout << ">>>>>>发送卖开仓报单录入请求成功" << std::endl;
else
std::cerr << "--->>>发送卖开仓报单录入请求失败" << std::endl;
}
// 卖平仓
void CustomTradeSpi::sell_close(TThostFtdcInstrumentIDType instrumentID, TThostFtdcPriceType NewPrice, TThostFtdcVolumeType volume, TThostFtdcTimeConditionType CombOffsetFlag)
{
CThostFtdcInputOrderField orderInsertReq;
memset(&orderInsertReq, 0, sizeof(orderInsertReq));
///经纪公司代码
strcpy(orderInsertReq.BrokerID, gBrokerID);
///投资者代码
strcpy(orderInsertReq.InvestorID, gInvesterID);
///合约代码
strcpy(orderInsertReq.InstrumentID, instrumentID);
///报单引用
strcpy(orderInsertReq.OrderRef, order_ref);
///报单价格条件: 限价
orderInsertReq.OrderPriceType = THOST_FTDC_OPT_LimitPrice;
///买卖方向:
orderInsertReq.Direction = THOST_FTDC_D_Sell;
///组合开平标志: 开仓、平仓等
orderInsertReq.CombOffsetFlag[0] = CombOffsetFlag;
///组合投机套保标志
orderInsertReq.CombHedgeFlag[0] = THOST_FTDC_HF_Speculation;
///价格
orderInsertReq.LimitPrice = NewPrice;
///数量:1
orderInsertReq.VolumeTotalOriginal = volume;
///有效期类型: 当日有效
orderInsertReq.TimeCondition = THOST_FTDC_TC_GFD;
///成交量类型: 任何数量
orderInsertReq.VolumeCondition = THOST_FTDC_VC_AV;
///最小成交量: 1
orderInsertReq.MinVolume = 1;
///触发条件: 立即
orderInsertReq.ContingentCondition = THOST_FTDC_CC_Immediately;
///强平原因: 非强平
orderInsertReq.ForceCloseReason = THOST_FTDC_FCC_NotForceClose;
///自动挂起标志: 否
orderInsertReq.IsAutoSuspend = 0;
///用户强评标志: 否
orderInsertReq.UserForceClose = 0;
static int requestID = 0; // 请求编号
int rt = g_pTradeUserApi->ReqOrderInsert(&orderInsertReq, ++requestID);
if (!rt)
std::cout << ">>>>>>发送卖平仓报单录入请求成功" << std::endl;
else
std::cerr << "--->>>发送卖平仓报单录入请求失败" << std::endl;
}
// 请求报单操作
void CustomTradeSpi::reqOrderAction(CThostFtdcOrderField* pOrder)
{
static bool orderActionSentFlag = false; // 是否发送了报单
if (orderActionSentFlag)
return;
CThostFtdcInputOrderActionField orderActionReq;
memset(&orderActionReq, 0, sizeof(orderActionReq));
///经纪公司代码
strcpy(orderActionReq.BrokerID, pOrder->BrokerID);
///投资者代码
strcpy(orderActionReq.InvestorID, pOrder->InvestorID);
///报单操作引用
// TThostFtdcOrderActionRefType OrderActionRef;
///报单引用
strcpy(orderActionReq.OrderRef, pOrder->OrderRef);
///请求编号
// TThostFtdcRequestIDType RequestID;
///前置编号
orderActionReq.FrontID = trade_front_id;
///会话编号
orderActionReq.SessionID = session_id;
///交易所代码
// TThostFtdcExchangeIDType ExchangeID;
///报单编号
// TThostFtdcOrderSysIDType OrderSysID;
///操作标志
orderActionReq.ActionFlag = THOST_FTDC_AF_Delete;
///价格
// TThostFtdcPriceType LimitPrice;
///数量变化
// TThostFtdcVolumeType VolumeChange;
///用户代码
// TThostFtdcUserIDType UserID;
///合约代码
strcpy(orderActionReq.InstrumentID, pOrder->InstrumentID);
static int requestID = 0; // 请求编号
int rt = g_pTradeUserApi->ReqOrderAction(&orderActionReq, ++requestID);
if (!rt)
std::cout << ">>>>>>发送报单操作请求成功" << std::endl;
else
std::cerr << "--->>>发送报单操作请求失败" << std::endl;
orderActionSentFlag = true;
}
bool CustomTradeSpi::isMyOrder(CThostFtdcOrderField* pOrder)
{
return ((pOrder->FrontID == trade_front_id) &&
(pOrder->SessionID == session_id) &&
(strcmp(pOrder->OrderRef, order_ref) == 0));
}
bool CustomTradeSpi::isTradingOrder(CThostFtdcOrderField* pOrder)
{
return ((pOrder->OrderStatus != THOST_FTDC_OST_PartTradedNotQueueing) &&
(pOrder->OrderStatus != THOST_FTDC_OST_Canceled) &&
(pOrder->OrderStatus != THOST_FTDC_OST_AllTraded));
}
main函数代码如下:
#include
#include
#include
#include
#include "CustomMdSpi.h"
#include "CustomTradeSpi.h"
#include "CreateFiel.h"
using namespace std;
//链接库(导入链接库的第二种方法)
//#pragma comment (lib, "thostmduserapi_se.lib")
//#pragma comment (lib, "thosttraderapi_se.lib")
// ---- 全局变量(公共参数) ---- //
// SimNow(模拟)
TThostFtdcBrokerIDType gBrokerID = "9999"; // 模拟经纪商代码
TThostFtdcInvestorIDType gInvesterID = "******"; // 投资者账户名
TThostFtdcPasswordType gInvesterPassword = "**********"; // 投资者密码
TThostFtdcAppIDType AppID = "simnow_client_test"; // AppID
TThostFtdcAuthCodeType AuthCode = "0000000000000000"; // 授权码
// 行情参数
CThostFtdcMdApi* g_pMdUserApi = nullptr; // 行情指针
char gMdFrontAddr[] = "tcp://180.168.146.187:10131"; // 模拟行情前置地址--全天站点
//char gMdFrontAddr[] = "tcp://180.168.146.187:10211"; // 模拟行情前置地址--电信
//char gMdFrontAddr[] = "tcp://180.168.146.187:10212"; // 模拟行情前置地址--电信1
//char gMdFrontAddr[] = "tcp://180.168.146.187:10213"; // 模拟行情前置地址--移动
char* g_pInstrumentID[] = { "p2209" }; // 行情合约代码列表,中、上、大、郑交易所各选一种 期权:"IO2105-C-5000"
char* a1 = new char[10];
int instrumentNum = 1; // 行情合约订阅数量
// 交易参数
CThostFtdcTraderApi* g_pTradeUserApi = nullptr; // 交易指针
char gTradeFrontAddr[] = "tcp://180.168.146.187:10130"; // 模拟交易前置地址--全天站点
//char gTradeFrontAddr[] = "tcp://180.168.146.187:10201"; // 模拟交易前置地址--电信
//char gTradeFrontAddr[] = "tcp://180.168.146.187:10202"; // 模拟交易前置地址--电信1
//char gTradeFrontAddr[] = "tcp://180.168.146.187:10203"; // 模拟交易前置地址--移动
TThostFtdcInstrumentIDType g_pTradeInstrumentID = "p2209"; // 所交易的合约代码
TThostFtdcPriceType gLimitPrice = 11064; // 交易价格
int main()
{
// 若文件夹不存在,则创建所需文件夹
createFile();
// 初始化行情线程
cout << "初始化行情..." << endl;
char* mdFlowPath = ".//MarketData/"; // 存放行情接口在本地生成的流文件的文件路径(.con)
g_pMdUserApi = CThostFtdcMdApi::CreateFtdcMdApi(mdFlowPath, true); // 创建行情实例
CThostFtdcMdSpi* pMdUserSpi = new CustomMdSpi; // 创建行情回调实例
g_pMdUserApi->RegisterSpi(pMdUserSpi); // 注册事件类
g_pMdUserApi->RegisterFront(gMdFrontAddr); // 设置行情前置地址
g_pMdUserApi->Init(); // 连接运行
// 初始化交易线程
cout << "初始化交易..." << endl;
char* tdFlowPath = ".//TradingData/"; // 存放交易接口在本地生成的流文件的文件路径(.con)
g_pTradeUserApi = CThostFtdcTraderApi::CreateFtdcTraderApi(tdFlowPath); // 创建交易实例
//CThostFtdcTraderSpi *pTradeSpi = new CustomTradeSpi;
CustomTradeSpi* pTradeSpi = new CustomTradeSpi; // 创建交易回调实例
g_pTradeUserApi->RegisterSpi(pTradeSpi); // 注册事件类
g_pTradeUserApi->RegisterFront(gTradeFrontAddr); // 设置交易前置地址
g_pTradeUserApi->SubscribePublicTopic(THOST_TERT_RESTART); // 订阅公共流
g_pTradeUserApi->SubscribePrivateTopic(THOST_TERT_RESTART); // 订阅私有流
g_pTradeUserApi->Init(); // 连接运行
// 等到线程退出
g_pMdUserApi->Join();
delete pMdUserSpi;
g_pMdUserApi->Release();
g_pTradeUserApi->Join();
delete pTradeSpi;
g_pTradeUserApi->Release();
//getchar();
system("pause");
return 0;
}
源代码链接: https://pan.baidu.com/s/1zsD3zp10LbbY1nmB6o3-ZQ .
提取码:JYL8
python版本的量化交易案例链接: http://t.csdn.cn/9FHHe .
若您是新手上路,请下载源代码修改账号和密码即可运行。若您对C++使用不是非常熟练,上期所下面的子公司也封装了python版本的接口:Algoplus(容易上手)