跳到主要内容

开发示例7.0

信息采集API使用demo

#include <stdio.h>
#include "exportSecApi.h"
int main()
{
char *systemInfo = new char[1024];
char *errmsg = new char [256];
memset(systemInfo, 0x00, sizeof(systemInfo));
memset(errmsg, 0x00, sizeof(errmsg));
int nRet = QDGetLocalSystemInfo(systemInfo, errmsg, true);

if (nRet > 0 && NULL != systemInfo)
{
printf("sysinfo:%s, nRet:%d\n", systemInfo, nRet);
if (NULL != errmsg)
{
printf("errmsg:%s\n", errmsg);
}
}
else
{
printf("QDGetLocalSystemInfo return:%d\n", nRet);
}

if (NULL != systemInfo)
{
delete systemInfo;
systemInfo = NULL;
}

if (NULL != errmsg)
{
delete errmsg;
errmsg = NULL;
}
return 0;
}

普通Tcp API使用demo

注意

  • 在API7.0版本中,报单时填写InstrumentIDNum。
  • 填写9位以上的InvestorIDNum需要通过InvestorIDToNum函数转换,截取后8位,或者通过ReqQryUserInvestor查询返回客户端
#include "QdpFtdcTraderApi.h"
#include <iostream>
#include <cstdlib>
#include <string.h>
#include <stdio.h>
#include <thread>
#include <chrono>
#include <map>
#include <string>

using namespace std;

// 报单录入操作是否完成的标志
// 经纪公司代码
TQdpFtdcBrokerIDType g_chBrokerID;
// 交易用户代码
TQdpFtdcUserIDType g_chUserID;
// 用户密码
TQdpFtdcPasswordType g_chPassword;
// 投资者代码
TQdpFtdcInvestorIDType g_chInvestorID;
// 用户本地最大报单号
int g_nOrdLocalID = 0;
/* 认证相关信息 */
// 是否需要认证 0-不需要 1-需要
int g_nAuthenticate = 0;
TQdpFtdcAppIDType g_chAppID;
TQdpFtdcPasswordType g_chAuthCode;

/// 交易API
CQdpFtdcTraderApi *g_pTraderApi = NULL;
typedef map<string, int> CInstumentIDNumMap; // InstrumentID -> InstrumentIDNum
CInstumentIDNumMap g_mapInstrumentIDNum;

void ReqLogin(int RequestID);

void ReqAuth(int RequestID);

void ReqUserPasswordUpdate(int RequestID);

void ReqSubPrdTradeFlow(int RequestID);

void ReqUnSubPrdTradeFlow(int RequestID);

void ReqForQuoteInsert(int RequestID);

void ReqQryForQuote(int RequestID);

void ReqQryMarketData(int RequestID);

void ReqQryExchange(int &RequestID);

void ReqQryTrade(int &RequestID);

void ReqQryOrder(int &RequestID);

void ReqQuoteAction(int RequestID);

void ReqQuoteInsert(int RequestID);

void ReqSubmitUserSystemInfo(int RequestID);

int ReqSetClientMaxSigVol(int RequestID);

int ReqOrderAction(int RequestID);

int ReqOrderInsert(int RequestID);

int ReqQryUserInvestor(int RequestID);

int ReqQryInvestorAccount(int RequestID);

int ReqQryInvestorOptionFee(int RequestID);

int ReqQryInvestorMargin(int RequestID);

int ReqQryInstrument(int RequestID);

int ReqQrySGEDeferRate(int RequestID);

int ReqQryInvestorFee(int RequestID);

int ReqQryInvestorPosition(int RequestID);

int InvestorIDToNum(const char *investorID);

class CTraderSpi : public CQdpFtdcTraderSpi
{
public:
CTraderSpi(CQdpFtdcTraderApi *pUserApi) : m_pTraderApi(pUserApi),
m_bIsLogin(false),
m_bConnected(false)
{
g_mapInstrumentIDNum.clear();
}
~CTraderSpi() {};

// 实现CTraderSpi的各个接口
virtual void OnFrontConnected()
{
std::cout << "OnFrontConnected\n";
m_bConnected = true;
};

virtual void OnFrontDisconnected(int nReason)
{
std::cout << "OnFrontDisconnected: " << nReason << std::endl;
m_bConnected = false;
m_bIsLogin = false;
}

virtual void OnRspUserLogin(CQdpFtdcRspUserLoginField *pRspUserLogin, CQdpFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast)
{
if (pRspInfo == NULL)
{
std::cout << "OnRspUserLogin=NULL!\n";
return;
}

if (pRspInfo->ErrorID != 0)
{
std::cout << "UserID: " << g_chUserID << "Login failed, ErrorMsg: " << pRspInfo->ErrorMsg;
return;
}
std::cout << "UserID: " << g_chUserID << "Login Success.\n";

/// 准备就绪 QDP_TERT_PRIVATE 私有流; QDP_TERT_PUBLIC 公有流;
CQdpFtdcFlowStatusField ftdField1;
memset(&ftdField1, 0, sizeof(CQdpFtdcFlowStatusField));
ftdField1.SequenceSeries = QDP_TERT_PRIVATE;
ftdField1.bReady = true;
m_pTraderApi->ReqReady(&ftdField1, 0);
memset(&ftdField1, 0, sizeof(CQdpFtdcFlowStatusField));
ftdField1.SequenceSeries = QDP_TERT_PUBLIC;
ftdField1.bReady = true;
m_pTraderApi->ReqReady(&ftdField1, 0);

m_bIsLogin = true;
}

virtual void OnRspUserLogout(CQdpFtdcRspUserLogoutField *pRspUserLogout, CQdpFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast)
{
if (pRspInfo == NULL)
{
std::cout << "OnRspUserLogout=NULL!\n";
return;
}
if (pRspInfo->ErrorID != 0)
{
std::cout << "OnRspUserLogout failed, ErrorMsg:" << pRspInfo->ErrorMsg << "\n";
return;
}

m_bIsLogin = false;
}

virtual void OnRspUserPasswordUpdate(CQdpFtdcUserPasswordUpdateField *pUserPasswordUpdate, CQdpFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast)
{
if (pRspInfo == NULL)
{
std::cout << "OnRspUserPasswordUpdate=NULL!\n";
return;
}
if (pRspInfo->ErrorID != 0)
{
std::cout << "OnRspUserPasswordUpdate failed, ErrorMsg:" << pRspInfo->ErrorMsg << "\n";
return;
}
}

virtual void OnRspAuthenticate(CQdpFtdcRtnAuthenticateField *pRtnAuthenticate, CQdpFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast)
{
if (pRspInfo == NULL)
{
std::cout << "OnRspAuthenticate=NULL!\n";
return;
}
if (pRspInfo->ErrorID != 0)
{
std::cout << "OnRspAuthenticate failed, ErrorMsg:" << pRspInfo->ErrorMsg << "\n";
return;
}

std::cout << "OnRspAuthenticate success, UserID:" << pRtnAuthenticate->UserID << "\n";

// 认证成功后登录
ReqLogin(nRequestID);
}

// traderSPI
virtual void OnRtnTrade(CQdpFtdcTradeField *pTrade)
{
std::cout << "OnRtnTrade: OrderSysID=" << pTrade->OrderSysID
<< ", InstrumentID=" << pTrade->InstrumentID
<< ", TradeID=" << pTrade->TradeID
<< ", TradeVolume=" << pTrade->TradeVolume
<< "\n";
}

virtual void OnRtnOrder(CQdpFtdcOrderField *pOrder)
{
// store OrderSysID
std::cout << "OnRtnOrder: OrderSysID=" << pOrder->OrderSysID
<< ", InstrumentID=" << pOrder->InstrumentID
<< ", Volume=" << pOrder->Volume
<< ", OrderStatus=" << pOrder->OrderStatus
<< "\n";
}

virtual void OnRtnInstrumentStatus(CQdpFtdcInstrumentStatusField *pInstrumentStatus) {}

// virtual void OnErrRtnOrderInsert(CQdpFtdcInputOrderField* pInputOrder, CQdpFtdcRspInfoField* pRspInfo){};

virtual void OnRspOrderAction(CQdpFtdcOrderActionField *pOrderAction, CQdpFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast)
{
if (pRspInfo == NULL)
{
std::cout << "OnRspOrderAction=NULL!\n";
return;
}
if (pRspInfo != NULL && pRspInfo->ErrorID != 0)
{
std::cout << "OnRspOrderAction failed, ErrorMsg:" << pRspInfo->ErrorMsg << "\n";
return;
}
std::cout << "OnRspOrderAction success, OrderSysID=" << pOrderAction->OrderSysID;
}

// QuerySPI
virtual void OnRspQryUserInvestor(CQdpFtdcRspUserInvestorField *pRspUserInvestor, CQdpFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast)
{
std::cout << "UserID:" << pRspUserInvestor->UserID
<< "InvestorID:" << pRspUserInvestor->InvestorID
<< "InvestorIDNum:" << pRspUserInvestor->InvestorIDNum <<"\n";
}

// virtual void OnRspQryInvestor(CQdpFtdcRspQryInvestorField *pRspQryInvestor, CQdpFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast){};

virtual void OnRspQryInvestorPosition(CQdpFtdcRspInvestorPositionField *pRspInvestorPosition, CQdpFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast)
{
std::cout << "OnRspQryInvestorPosition\n";
if (pRspInfo != NULL && pRspInfo->ErrorID != 0)
{
std::cout << "failed; ErrorID: " << pRspInfo->ErrorID
<< ", ErrorMsg: " << pRspInfo->ErrorMsg << ", RequestID: " << nRequestID << "\n";
return;
}

if (pRspInvestorPosition != NULL)
{
// 总持仓成本 总持仓量 合约乘数
std::cout << "Success; InvestorID=[" << pRspInvestorPosition->InvestorID
<< "], InstrumentID=[" << pRspInvestorPosition->InstrumentID
<< "], UsedMargin=[" << pRspInvestorPosition->UsedMargin
<< "], FrozenMargin=[" << pRspInvestorPosition->FrozenMargin
<< "], FrozenPremium=[" << pRspInvestorPosition->FrozenPremium
<< "], PositionProfit=[" << pRspInvestorPosition->PositionProfit
<< "], PositionCost=[" << pRspInvestorPosition->PositionCost
<< "], TodayPosition=[" << pRspInvestorPosition->TodayPosition
<< "];\n";
}
}

virtual void OnRspQryInstrument(CQdpFtdcRspInstrumentField *pRspInstrument, CQdpFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast)
{
std::cout << "OnRspQryInstrument\n";

if (pRspInfo != NULL && pRspInfo->ErrorID != 0)
{
std::cout << "failed; ErrorID: " << pRspInfo->ErrorID
<< ", ErrorMsg: " << pRspInfo->ErrorMsg << ", RequestID: " << nRequestID << "\n";
return;
}

if (pRspInstrument != NULL)
{
g_mapInstrumentIDNum.insert(CInstumentIDNumMap::value_type(pRspInstrument->InstrumentID, pRspInstrument->InstrumentIDNum));
std::cout << "Success; ExchangeID=[" << pRspInstrument->ExchangeID
<< "], InstrumentID=[" << pRspInstrument->InstrumentID
<< "], InstrumentIDNum=" << pRspInstrument->InstrumentIDNum // 在API7.0版本中,报单时填写InstrumentIDNum
<< "], VolumeMultiple=[" << pRspInstrument->VolumeMultiple
<< "], PriceTick=[" << pRspInstrument->PriceTick
<< "], PreSettlementPrice=[" << pRspInstrument->PreSettlementPrice
<< "], InstrumentStatus=[" << pRspInstrument->InstrumentStatus
<< "];\n";
}
}

virtual void OnRspQryInvestorAccount(CQdpFtdcRspInvestorAccountField *pRspInvestorAccount, CQdpFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast)
{
std::cout << "OnRspQryInvestorAccount\n";

if (pRspInfo != NULL && pRspInfo->ErrorID != 0)
{
std::cout << "failed; ErrorID: " << pRspInfo->ErrorID
<< ", ErrorMsg: " << pRspInfo->ErrorMsg << ", RequestID: " << nRequestID << "\n";
return;
}

if (pRspInvestorAccount != NULL)
{
std::cout << "Success; AccountID=[" << pRspInvestorAccount->AccountID
<< "InvestorID=[" << pRspInvestorAccount->InvestorID
<< "], PreBalance=[" << pRspInvestorAccount->PreBalance
<< "], PreAvailable=[" << pRspInvestorAccount->PreAvailable
<< "], CloseProfit=[" << pRspInvestorAccount->CloseProfit
<< "], PositionProfit=[" << pRspInvestorAccount->PositionProfit
<< "], Fee=[" << pRspInvestorAccount->Fee
<< "], FrozenFee=[" << pRspInvestorAccount->FrozenFee
<< "], FrozenPremium=[" << pRspInvestorAccount->FrozenPremium
<< "], Margin=[" << pRspInvestorAccount->Margin
<< "], FrozenMargin=[" << pRspInvestorAccount->FrozenMargin
<< "], Available=[" << pRspInvestorAccount->Available
<< "], DynamicRights=[" << pRspInvestorAccount->DynamicRights
<< "], Balance=[" << pRspInvestorAccount->Balance
<< "], Deposit=[" << pRspInvestorAccount->Deposit
<< "], Withdraw=[" << pRspInvestorAccount->Withdraw
<< "];\n";
}
}

virtual void OnRspQryInvestorMargin(CQdpFtdcInvestorMarginField *pInvestorMargin, CQdpFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast)
{
std::cout << "OnRspQryInvestorMargin\n";
if (pRspInfo != NULL && pRspInfo->ErrorID != 0)
{
std::cout << "failed; ErrorID: " << pRspInfo->ErrorID
<< ", ErrorMsg: " << pRspInfo->ErrorMsg << ", RequestID: " << nRequestID << "\n";
return;
}
if (pInvestorMargin != NULL)
{
std::cout << "Success; InstrumentID=[" << pInvestorMargin->InstrumentID
<< "], InvestorID=[" << pInvestorMargin->InvestorID
<< "], HedgeFlag=[" << pInvestorMargin->HedgeFlag
<< "], LongMarginRate=[" << pInvestorMargin->LongMarginRate
<< "], LongMarginAmt=[" << pInvestorMargin->LongMarginAmt
<< "], ShortMarginRate=[" << pInvestorMargin->ShortMarginRate
<< "], ShortMarginAmt=[" << pInvestorMargin->ShortMarginAmt
<< "];" << "\n";
}
}

virtual void OnRspQryInvestorFee(CQdpFtdcInvestorFeeField *pInvestorFee, CQdpFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast)
{
std::cout << "OnRspQryInvestorFee\n";

if (pRspInfo != NULL && pRspInfo->ErrorID != 0)
{
std::cout << "failed; ErrorID: " << pRspInfo->ErrorID
<< ", ErrorMsg: " << pRspInfo->ErrorMsg << ", RequestID: " << nRequestID << "\n";
return;
}

if (pInvestorFee != NULL)
{
std::cout << "Success; InstrumentID=[" << pInvestorFee->InstrumentID
<< "], InvestorID=[" << pInvestorFee->InvestorID
<< "], HedgeFlag=[" << pInvestorFee->HedgeFlag
<< "], OpenFeeRate=[" << pInvestorFee->OpenFeeRate
<< "], OpenFeeAmt=[" << pInvestorFee->OpenFeeAmt
<< "], OffsetFeeRate=[" << pInvestorFee->OffsetFeeRate
<< "], OffsetFeeAmt=[" << pInvestorFee->OffsetFeeAmt
<< "], OTFeeRate=[" << pInvestorFee->OTFeeRate
<< "], OTFeeAmt=[" << pInvestorFee->OTFeeAmt
<< "];" << "\n";
}
}

virtual void OnRspQryInvestorOptionFee(CQdpFtdcRspInvestorOptionFeeField *pRspInvestorOptionFee, CQdpFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast)
{
std::cout << "OnRspQryInvestorOptionFee\n";

if (pRspInfo != NULL && pRspInfo->ErrorID != 0)
{
std::cout << "failed; ErrorID: " << pRspInfo->ErrorID
<< ", ErrorMsg: " << pRspInfo->ErrorMsg << ", RequestID: " << nRequestID << "\n";
return;
}

if (pRspInvestorOptionFee != NULL)
{
std::cout << "Success; InstrumentID=[" << pRspInvestorOptionFee->InstrumentID
<< "], InvestorID=[" << pRspInvestorOptionFee->InvestorID
<< "], OpenFeeRate=[" << pRspInvestorOptionFee->OpenFeeRate
<< "], OpenFeeAmt=[" << pRspInvestorOptionFee->OpenFeeAmt
<< "], OffsetFeeRate=[" << pRspInvestorOptionFee->OffsetFeeRate
<< "], OffsetFeeAmt=[" << pRspInvestorOptionFee->OffsetFeeAmt
<< "], OTFeeRate=[" << pRspInvestorOptionFee->OTFeeRate
<< "], OTFeeAmt=[" << pRspInvestorOptionFee->OTFeeAmt
<< "], StrikeFeeRate=[" << pRspInvestorOptionFee->StrikeFeeRate
<< "], StrikeFeeAmt=[" << pRspInvestorOptionFee->StrikeFeeAmt
<< "];" << "\n";
}
}

virtual void OnRspQryMarketData(CQdpFtdcMarketDataField *pMarketData, CQdpFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast)
{
std::cout << "OnRspQryMarketData\n";
if (pRspInfo != NULL && pRspInfo->ErrorID != 0)
{
std::cout << "failed; ErrorID: " << pRspInfo->ErrorID
<< ", ErrorMsg: " << pRspInfo->ErrorMsg << ", RequestID: " << nRequestID << "\n";
return;
}

if (pMarketData != NULL)
{
std::cout << "Success; InstrumentID=[" << pMarketData->InstrumentID
<< "], ExchangeID=[" << pMarketData->ExchangeID
<< "], LastPrice=[" << pMarketData->LastPrice
<< "], PreSettlementPrice=[" << pMarketData->PreSettlementPrice
<< "], OpenPrice=[" << pMarketData->OpenPrice
<< "], HighestPrice=[" << pMarketData->HighestPrice
<< "], LowestPrice=[" << pMarketData->LowestPrice
<< "], Volume=[" << pMarketData->Volume
<< "], Turnover=[" << pMarketData->Turnover
<< "], OpenInterest=[" << pMarketData->OpenInterest
<< "], PreClosePrice=[" << pMarketData->PreClosePrice
<< "], SettlementPrice=[" << pMarketData->SettlementPrice
<< "], UpperLimitPrice=[" << pMarketData->UpperLimitPrice
<< "], LowerLimitPrice=[" << pMarketData->LowerLimitPrice
<< "];" << "\n";
}
}

virtual void OnRspQryExchange(CQdpFtdcRspExchangeField *pRspExchange, CQdpFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast)
{
std::cout << "OnRspQryExchange\n";
if (pRspInfo != NULL && pRspInfo->ErrorID != 0)
{
std::cout << "failed; ErrorID: " << pRspInfo->ErrorID
<< ", ErrorMsg: " << pRspInfo->ErrorMsg << ", RequestID: " << nRequestID << "\n";
return;
}

if (pRspExchange != NULL)
{
std::cout << "Success; ExchangeID=[" << pRspExchange->ExchangeID
<< "], ExchangeName=[" << pRspExchange->ExchangeName
<< "];" << "\n";
}
}

virtual void OnRspQryTrade(CQdpFtdcTradeField *pTrade, CQdpFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast)
{
std::cout << "OnRspQryTrade\n";
if (pRspInfo != NULL && pRspInfo->ErrorID != 0)
{
std::cout << "failed; ErrorID: " << pRspInfo->ErrorID
<< ", ErrorMsg: " << pRspInfo->ErrorMsg << ", RequestID: " << nRequestID << "\n";
return;
}

if (pTrade != NULL)
{
std::cout << "Success; InstrumentID=[" << pTrade->InstrumentID
<< "], InvestorID=[" << pTrade->InvestorID
<< "], OrderSysID=[" << pTrade->OrderSysID
<< "], ExchangeID=[" << pTrade->ExchangeID
<< "], TradeID=[" << pTrade->TradeID
<< "], TradeVolume=[" << pTrade->TradeVolume
<< "], TradePrice=[" << pTrade->TradePrice
<< "], TradeTime=[" << pTrade->TradeTime
<< "];" << "\n";
}
}

virtual void OnRspQryOrder(CQdpFtdcOrderField *pOrder, CQdpFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast)
{
std::cout << "OnRspQryOrder\n";
if (pRspInfo != NULL && pRspInfo->ErrorID != 0)
{
std::cout << "failed; ErrorID: " << pRspInfo->ErrorID
<< ", ErrorMsg: " << pRspInfo->ErrorMsg
<< ", RequestID: " << nRequestID << std::endl;
return;
}

if (pOrder != NULL)
{
std::cout << "Success; InstrumentID=[" << pOrder->InstrumentID
<< "], InvestorID=[" << pOrder->InvestorID
<< "], OrderSysID=[" << pOrder->OrderSysID
<< "], ExchangeID=[" << pOrder->ExchangeID
<< "], OrderStatus=[" << pOrder->OrderStatus
<< "], Volume=[" << pOrder->Volume
<< "], LimitPrice=[" << pOrder->LimitPrice
<< "], VolumeTraded=[" << pOrder->VolumeTraded
<< "], VolumeRemain=[" << pOrder->VolumeRemain
<< "];" << "\n";
}
}

virtual void OnRspQuoteAction(CQdpFtdcQuoteActionField *pQuoteAction, CQdpFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast)
{
std::cout << "OnRspQuoteAction\n";
if (pRspInfo != NULL && pRspInfo->ErrorID != 0)
{
std::cout << "failed; ErrorID: " << pRspInfo->ErrorID
<< ", ErrorMsg: " << pRspInfo->ErrorMsg
<< ", RequestID: " << nRequestID << std::endl;
return;
}
if (pQuoteAction != NULL)
{

std::cout << "Success; UserOrderLocalID=[" << pQuoteAction->UserOrderLocalID
<< "], UserOrderActionLocalID=[" << pQuoteAction->UserOrderActionLocalID
<< "], OrderSysID=[" << pQuoteAction->OrderSysID
<< "];\n";
}
}

virtual void OnRtnQuote(CQdpFtdcQuoteField *pQuote)
{
// 报价回报
std::cout << "OnRtnQuote, OrderSysID=" << pQuote->OrderSysID
<< ", InvestorID=" << pQuote->InvestorID
<< ", UserOrderLocalID=" << pQuote->UserOrderLocalID
<< ", OrderStatus=" << pQuote->OrderStatus
<< ", BidOrderSysID=" << pQuote->BidOrderSysID
<< ", AskOrderSysID=" << pQuote->AskOrderSysID
<< "\n";
}

virtual void OnRspOrderInsert(CQdpFtdcRspInputOrderField *pRspInputOrder, CQdpFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast)
{
std::cout << "OnRspOrderInsert\n";
if (pRspInfo != NULL && pRspInfo->ErrorID != 0)
{
std::cout << "failed; ErrorID: " << pRspInfo->ErrorID
<< ", ErrorMsg: " << pRspInfo->ErrorMsg
<< ", RequestID: " << nRequestID << std::endl;
return;
}

if (pRspInputOrder != NULL)
{
std::cout << "Success; InvestorIDNum=[" << pRspInputOrder->InvestorIDNum
<< "],InstrumentID=[" << pRspInputOrder->InstrumentID
<< "],OrderSysID=[" << pRspInputOrder->OrderSysID
<< "],Volume=[" << pRspInputOrder->Volume
<< "],LimitPrice=[" << pRspInputOrder->LimitPrice
<< "],UserOrderLocalID=[" << pRspInputOrder->UserOrderLocalID
<< "];\n";
}
}

virtual void OnRspQryForQuote(CQdpFtdcForQuoteField *pForQuote, CQdpFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast)
{
std::cout << "OnRspQryForQuote\n";
if (pRspInfo != NULL && pRspInfo->ErrorID != 0)
{
std::cout << "failed; ErrorID: " << pRspInfo->ErrorID
<< ", ErrorMsg: " << pRspInfo->ErrorMsg
<< ", RequestID: " << nRequestID << std::endl;
return;
}

if (pForQuote != NULL)
{
std::cout << "Success; InstrumentID=[" << pForQuote->InstrumentID
<< "], ExchangeID=[" << pForQuote->ExchangeID
<< "], InvestorID=[" << pForQuote->InvestorID
<< "], ForQuoteStatus=[" << pForQuote->ForQuoteStatus
<< "], UserOrderLocalID=[" << pForQuote->UserOrderLocalID
<< "];\n";
}
}

virtual void OnRspForQuoteInsert(CQdpFtdcInputForQuoteField *pInputForQuote, CQdpFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast)
{
std::cout << "OnRspForQuoteInsert\n";
if (pRspInfo != NULL && pRspInfo->ErrorID != 0)
{
std::cout << "failed; ErrorID: " << pRspInfo->ErrorID
<< ", ErrorMsg: " << pRspInfo->ErrorMsg
<< ", RequestID: " << nRequestID << std::endl;
return;
}

if (pInputForQuote != NULL)
{
std::cout << "Success; InstrumentID=[" << pInputForQuote->InstrumentID
<< "], ExchangeID=[" << pInputForQuote->ExchangeID
<< "], InvestorID=[" << pInputForQuote->InvestorID
<< "], UserOrderLocalID=[" << pInputForQuote->UserOrderLocalID
<< "];\n";
}
}

virtual void OnRspQuoteInsert(CQdpFtdcRspInputQuoteField *pRspInputQuote, CQdpFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast)
{
std::cout << "OnRspQuoteInsert\n";
if (pRspInfo != NULL && pRspInfo->ErrorID != 0)
{
std::cout << "failed; ErrorID: " << pRspInfo->ErrorID
<< ", ErrorMsg: " << pRspInfo->ErrorMsg
<< ", RequestID: " << nRequestID << std::endl;
return;
}

if (pRspInputQuote != NULL)
{
std::cout << "Success; InstrumentIDNum=[" << pRspInputQuote->InstrumentIDNum
<< "],InvestorIDNum=[" << pRspInputQuote->InvestorIDNum
<< "],AskPrice=[" << pRspInputQuote->AskPrice
<< "],AskVolume=[" << pRspInputQuote->AskVolume
<< "],BidPrice=[" << pRspInputQuote->BidPrice
<< "],BidVolume=[" << pRspInputQuote->BidVolume
<< "],BidOrderRef=[" << pRspInputQuote->BidOrderRef
<< "],AskOrderRef=[" << pRspInputQuote->AskOrderRef
<< "],ExchangeID=[" << pRspInputQuote->ExchangeID
<< "],OrderSysID=[" << pRspInputQuote->OrderSysID
<< "\n";
}
}

private:
CQdpFtdcTraderApi *m_pTraderApi;

public:
bool m_bIsLogin;
bool m_bConnected;
};

int GetInstrumentIDNum(const char *pInstrumentID)
{
CInstumentIDNumMap::iterator it = g_mapInstrumentIDNum.find(string(pInstrumentID));
if (it != g_mapInstrumentIDNum.end())
{
return it->second;
}
else
{
return 0;
}
}

void ReqLogin(int RequestID)
{
CQdpFtdcReqUserLoginField reqUserLogin;

strcpy(reqUserLogin.UserProductInfo, "demo_test");
strcpy(reqUserLogin.BrokerID, g_chBrokerID);
strcpy(reqUserLogin.UserID, g_chUserID);
strcpy(reqUserLogin.Password, g_chPassword);
// 发出登陆请求
g_pTraderApi->ReqUserLogin(&reqUserLogin, RequestID);
}

void ReqAuth(int RequestID)
{
CQdpFtdcAuthenticateField reqfield;
strcpy(reqfield.BrokerID, g_chBrokerID);
strcpy(reqfield.UserID, g_chUserID);
strcpy(reqfield.UserProductInfo, "demo_test");
strcpy(reqfield.AppID, g_chAppID);
strcpy(reqfield.AuthCode, g_chAuthCode);
// 发出认证请求
g_pTraderApi->ReqAuthenticate(&reqfield, RequestID);
}

void ReqUserPasswordUpdate(int RequestID)
{
std::cout << "ReqUserPasswordUpdate Info:" << std::endl;
CQdpFtdcUserPasswordUpdateField t_field;
memset(&t_field, 0, sizeof(t_field));
strcpy(t_field.BrokerID, g_chBrokerID);
strcpy(t_field.UserID, g_chUserID);
std::cout << "OldPassword: ";
std::cin >> t_field.OldPassword;
std::cout << "NewPassword: ";
std::cin >> t_field.NewPassword;
g_pTraderApi->ReqUserPasswordUpdate(&t_field, RequestID);
}

void ReqSubPrdTradeFlow(int RequestID)
{
std::cout << "ReqSubPrdTradeFlow Info:" << std::endl;
CQdpFtdcSpecificInstrumentField t_field;
memset(&t_field, 0, sizeof(t_field));
std::cout << "ProductID: ";
std::cin >> t_field.InstrumentID;
g_pTraderApi->ReqSubPrdTradeFlow(&t_field, RequestID);
}

void ReqUnSubPrdTradeFlow(int RequestID)
{
std::cout << "ReqSubPrdTradeFlow Info:" << std::endl;
CQdpFtdcSpecificInstrumentField t_field;
memset(&t_field, 0, sizeof(t_field));
std::cout << "ProductID: ";
std::cin >> t_field.InstrumentID;
g_pTraderApi->ReqUnSubPrdTradeFlow(&t_field, RequestID);
}

void ReqForQuoteInsert(int RequestID)
{
std::cout << "ReqForQuoteInsert Info:" << std::endl;
CQdpFtdcInputForQuoteField a_field;
memset(&a_field, 0, sizeof(a_field));
strcpy(a_field.BrokerID, g_chBrokerID);
strcpy(a_field.InvestorID, g_chInvestorID);
strcpy(a_field.UserID, g_chUserID);
std::cout << "ExchangeID:";
std::cin >> a_field.ExchangeID;
std::cout << "InstrumentID: ";
std::cin >> a_field.InstrumentID;
a_field.UserOrderLocalID = ++g_nOrdLocalID;
g_pTraderApi->ReqForQuoteInsert(&a_field, RequestID);
}

void ReqQryForQuote(int RequestID)
{
std::cout << "ReqQryForQuote Info:" << std::endl;
CQdpFtdcQryForQuoteField a_field;
memset(&a_field, 0, sizeof(a_field));
strcpy(a_field.BrokerID, g_chBrokerID);
strcpy(a_field.InvestorID, g_chInvestorID);
std::cout << "ExchangeID:";
std::cin >> a_field.ExchangeID;
std::cout << "InstrumentID: ";
std::cin >> a_field.InstrumentID;
g_pTraderApi->ReqQryForQuote(&a_field, RequestID);
}

void ReqQryMarketData(int RequestID)
{
CQdpFtdcQryMarketDataField d_field;
memset(&d_field, 0, sizeof(CQdpFtdcQryMarketDataField));
g_pTraderApi->ReqQryMarketData(&d_field, RequestID);
}

void ReqQryExchange(int &RequestID)
{
CQdpFtdcQryExchangeField t_field;
memset(&t_field, 0, sizeof(CQdpFtdcQryExchangeField));
g_pTraderApi->ReqQryExchange(&t_field, RequestID);
}

void ReqQryTrade(int &RequestID)
{
CQdpFtdcQryTradeField t_field;
memset(&t_field, 0, sizeof(CQdpFtdcQryTradeField));
strcpy(t_field.BrokerID, g_chBrokerID);
strcpy(t_field.UserID, g_chUserID);
strcpy(t_field.InvestorID, g_chInvestorID);
g_pTraderApi->ReqQryTrade(&t_field, RequestID);
}

void ReqQryOrder(int &RequestID)
{
CQdpFtdcQryOrderField o_field;
memset(&o_field, 0, sizeof(CQdpFtdcQryOrderField));
strcpy(o_field.BrokerID, g_chBrokerID);
strcpy(o_field.UserID, g_chUserID);
strcpy(o_field.InvestorID, g_chInvestorID);
g_pTraderApi->ReqQryOrder(&o_field, RequestID);
}

void ReqQuoteAction(int RequestID)
{
std::cout << "ReqQuoteAction Info:" << std::endl;
CQdpFtdcQuoteActionField quote;
memset(&quote, 0, sizeof(quote));
std::cout << "ExchangeID:";
std::cin >> quote.ExchangeID;
quote.UserOrderActionLocalID = ++g_nOrdLocalID;
std::cout << "OrderSysID:";
std::cin >> quote.OrderSysID;
std::cout << "UserOrderLocalID:";
std::cin >> quote.UserOrderLocalID;
quote.ActionFlag = QDP_FTDC_AF_Delete;
g_pTraderApi->ReqQuoteAction(&quote, RequestID);
}

void ReqQuoteInsert(int RequestID)
{
std::cout << "ReqQuoteInsert Info:" << std::endl;
CQdpFtdcInputQuoteField quote;
memset(&quote, 0, sizeof(quote));
// 合约号 -- 需要调用合约查询 获取合约代码对应的合约号
std::cout << "InstrumentID: ";
string strInsturmentID = "";
std::cin >> strInsturmentID;
quote.InstrumentIDNum = GetInstrumentIDNum(strInsturmentID.c_str());
std::cout << "InstrumentIDNum: " << quote.InstrumentIDNum;
// 本地报单号
quote.UserOrderLocalID = ++g_nOrdLocalID;
// 投资者IDNum
quote.InvestorIDNum = atoi(g_chInvestorID);

// 卖出参数
std::cout << "AskOffsetFlag: ";
std::cin >> quote.AskOffsetFlag;
std::cout << "AskHedgeFlag: ";
std::cin >> quote.AskHedgeFlag;
std::cout << "AskPrice: ";
std::cin >> quote.AskPrice;
std::cout << "AskVolume: ";
std::cin >> quote.AskVolume;
quote.AskOrderRef = ++g_nOrdLocalID;

// 买入参数
std::cout << "BidOffsetFlag: ";
std::cin >> quote.BidOffsetFlag;
std::cout << "BidHedgeFlag: ";
std::cin >> quote.BidHedgeFlag;
std::cout << "BidPrice: ";
std::cin >> quote.BidPrice;
std::cout << "BidVolume: ";
std::cin >> quote.BidVolume;
quote.BidOrderRef = ++g_nOrdLocalID;

g_pTraderApi->ReqQuoteInsert(&quote, RequestID);
}

void ReqSubmitUserSystemInfo(int RequestID)
{
CQdpFtdcUserSystemInfoField a_field;
memset(&a_field, 0, sizeof(a_field));
// 基于数据收集的库(qdpdatacollectapi)获取到相关信息后填写
g_pTraderApi->ReqSubmitUserSystemInfo(&a_field, RequestID);
}

int ReqSetClientMaxSigVol(int RequestID)
{
CQdpFtdcClientMaxSigVolField a_field;
memset(&a_field, 0, sizeof(a_field));
strcpy(a_field.BrokerID, g_chBrokerID);
strcpy(a_field.ExchangeID, "CFFEX");
strcpy(a_field.InvestorID, g_chInvestorID);
a_field.HedgeFlag = '1';
// strcpy(a_field.InstrumentID,"");
// a_field.MaxSigVol = 10;
return g_pTraderApi->ReqSetClientMaxSigVol(&a_field, RequestID);
}

int ReqOrderAction(int RequestID)
{
std::cout << "ReqOrderAction Info:" << std::endl;
CQdpFtdcOrderActionField ord;
memset(&ord, 0, sizeof(ord));
// 交易所
std::cout << "ExchangeID: ";
std::cin >> ord.ExchangeID;
// 被撤订单的本地报单编号
std::cout << "UserOrderLocalID: ";
std::cin >> ord.UserOrderLocalID;
// 本次撤单操作的本地编号
ord.UserOrderActionLocalID = ++g_nOrdLocalID;
// 报单编号
std::cout << "OrderSysID: ";
std::cin >> ord.OrderSysID;
// 报单操作标志
ord.ActionFlag = QDP_FTDC_AF_Delete;

return g_pTraderApi->ReqOrderAction(&ord, RequestID);
}

// InvestorID和InvestorIDNum的转换关系
int InvestorIDToNum(const char *investorID)
{
char buffer[20] = { 0 };
size_t i = 0;

const size_t valid_length = strlen(investorID);
if (valid_length > 19 || valid_length == 0)
{
printf("invalid investorID: %s\n", investorID);
return 0;
}

// 预处理:替换非数字字符为'0',并复制到缓冲区
for (i = 0; i < valid_length; ++i)
{
if (investorID[i] < '0' || investorID[i] > '9')
{
buffer[i] = '0';
}
else
{
buffer[i] = investorID[i];
}
}
buffer[i] = '\0'; // 确保字符串终止

// 确定起始位置(长度>9时取后8位)
const char *start = buffer;
if (valid_length > 9)
{
start += valid_length - 8;
}

// 高性能转换:直接计算整数值
int result = 0;
for (const char *p = start; *p != '\0'; ++p)
{
result = result * 10 + (*p - '0');
}

return result;
}

int ReqOrderInsert(int RequestID)
{
std::cout << "ReqOrderInsert Info:" << std::endl;
CQdpFtdcInputOrderField ord;
memset(&ord, 0, sizeof(ord));
// 投资者编号 (对于API7.0版本,InstrumentIDNum通过合约查询的回调获取)
ord.InvestorIDNum = atoi(g_chInvestorID);

//如果9位及以上的InvestorID可以通过InvestorIDToNum()函数转换。对于超过的截取后8位,并且通过UserInvestor查询返回客户端
ord.InvestorIDNum = InvestorIDToNum(g_chInvestorID);

// 合约号 -- 需要调用合约查询 获取合约代码对应的合约号
std::cout << "InstrumentID: ";
string strInsturmentID = "";
std::cin >> strInsturmentID;
ord.InstrumentIDNum = GetInstrumentIDNum(strInsturmentID.c_str());
std::cout << "InstrumentIDNum: " << ord.InstrumentIDNum << std::endl;
// 本地报单号
ord.UserOrderLocalID = ++g_nOrdLocalID;
// 报单类型
std::cout << "OrderPriceType: ";
std::cin >> ord.OrderPriceType;
// ord.OrderPriceType = QDP_FTDC_OPT_LimitPrice;
// 买卖方向
std::cout << "Direction: ";
std::cin >> ord.Direction;
// ord.Direction = QDP_FTDC_D_Buy;
// 开平标志
std::cout << "OffsetFlag: ";
std::cin >> ord.OffsetFlag;
// strcpy(&(ord.OffsetFlag), "0");
// 投机套保标志
std::cout << "HedgeFlag: ";
std::cin >> ord.HedgeFlag;
// strcpy(&(ord.HedgeFlag), "1");
// 价格
std::cout << "LimitPrice: ";
std::cin >> ord.LimitPrice;
// ord.LimitPrice = 3074;
// 数量
std::cout << "Volume: ";
std::cin >> ord.Volume;
// ord.Volume = 1;
// 有效期类型
std::cout << "TimeCondition: ";
std::cin >> ord.TimeCondition;
// ord.TimeCondition = QDP_FTDC_TC_GFD;
// 成交量类型
std::cout << "VolumeCondition: ";
std::cin >> ord.VolumeCondition;
// ord.VolumeCondition = QDP_FTDC_VC_AV;

return g_pTraderApi->ReqOrderInsert(&ord, RequestID);
}

int ReqQryUserInvestor(int RequestID)
{
CQdpFtdcQryUserInvestorField a_field;
memset(&a_field, 0, sizeof(CQdpFtdcQryUserInvestorField));
strcpy(a_field.BrokerID, g_chBrokerID);
strcpy(a_field.UserID, g_chUserID);
return g_pTraderApi->ReqQryUserInvestor(&a_field, RequestID);
}

int ReqQryInvestorAccount(int RequestID)
{
CQdpFtdcQryInvestorAccountField a_field;
memset(&a_field, 0, sizeof(CQdpFtdcQryInvestorAccountField));
strcpy(a_field.BrokerID, g_chBrokerID);
strcpy(a_field.UserID, g_chUserID);
strcpy(a_field.InvestorID, g_chInvestorID);
return g_pTraderApi->ReqQryInvestorAccount(&a_field, RequestID);
}

int ReqQryInvestorOptionFee(int RequestID)
{
CQdpFtdcQryInvestorOptionFeeField of_field;
memset(&of_field, 0, sizeof(CQdpFtdcQryInvestorOptionFeeField));
strcpy(of_field.BrokerID, g_chBrokerID);
strcpy(of_field.UserID, g_chUserID);
strcpy(of_field.InvestorID, g_chInvestorID);
return g_pTraderApi->ReqQryInvestorOptionFee(&of_field, RequestID);
}

int ReqQryInvestorMargin(int RequestID)
{
CQdpFtdcQryInvestorMarginField m_field;
memset(&m_field, 0, sizeof(CQdpFtdcQryInvestorMarginField));
strcpy(m_field.BrokerID, g_chBrokerID);
strcpy(m_field.UserID, g_chUserID);
strcpy(m_field.InvestorID, g_chInvestorID);
return g_pTraderApi->ReqQryInvestorMargin(&m_field, RequestID);
}

int ReqQryInstrument(int RequestID)
{
CQdpFtdcQryInstrumentField i_field;
memset(&i_field, 0, sizeof(CQdpFtdcQryInstrumentField));
return g_pTraderApi->ReqQryInstrument(&i_field, RequestID);
}

int ReqQrySGEDeferRate(int RequestID)
{
CQdpFtdcQrySGEDeferRateField s_field;
memset(&s_field, 0, sizeof(CQdpFtdcQrySGEDeferRateField));
return g_pTraderApi->ReqQrySGEDeferRate(&s_field, RequestID);
}

int ReqQryInvestorFee(int RequestID)
{
CQdpFtdcQryInvestorFeeField f_field;
memset(&f_field, 0, sizeof(CQdpFtdcQryInvestorFeeField));
strcpy(f_field.BrokerID, g_chBrokerID);
strcpy(f_field.UserID, g_chUserID);
return g_pTraderApi->ReqQryInvestorFee(&f_field, RequestID);
}

int ReqQryInvestorPosition(int RequestID)
{
std::cout << "ReqQryInvestorPosition Info:" << std::endl;
CQdpFtdcQryInvestorPositionField p_field;
memset(&p_field, 0, sizeof(CQdpFtdcQryInvestorPositionField));
strcpy(p_field.BrokerID, g_chBrokerID);
strcpy(p_field.UserID, g_chUserID);
strcpy(p_field.InvestorID, g_chInvestorID);
std::cout << "ExchangeID: ";
std::cin >> p_field.ExchangeID;
std::cout << "InstrumentID: ";
std::cin >> p_field.InstrumentID;
return g_pTraderApi->ReqQryInvestorPosition(&p_field, RequestID);
}

void ShowHelp()
{
std::cout << "输入数字执行对应的操作:\n"
" 1: 合约查询请求(必须执行, 否则后面填写InstrmentID找不到对应的Num)\n"
" 2: 报单录入请求\n"
" 3: 报单操作请求\n"
" 4: 客户信息量阈值设置请求\n"
" 5: 可用投资者账户查询请求\n"
" 6: 投资者资金账户查询请求\n"
" 7: 投资者持仓查询请求\n"
" 8: 投资者手续费率查询请求\n"
" 9: 投资者保证金率查询请求\n"
"10: 金交所递延费率查询请求\n"
"11: 投资者期权手续费率查询请求\n"
"12: 报价录入请求\n"
"13: 报价操作请求\n"
"16: 报单查询请求\n"
"17: 成交单查询请求\n"
"18: 交易所查询请求\n"
"19: 实时行情查询请求\n"
"20: 询价查询请求\n"
"21: 询价录入请求\n"
"24: 用户密码修改请求\n"
"------------------------------\n";
}

void OrderFunc(CTraderSpi *pTraderSpi)
{
if (NULL == pTraderSpi)
{
return;
}
while (!pTraderSpi->m_bConnected)
{
std::this_thread::sleep_for(std::chrono::microseconds(1000));
continue;
}
int RequestID = 0;

std::cout << "please input user info...\n";
std::cout << "BrokerID:";
std::cin >> g_chBrokerID;
std::cout << "UserID:";
std::cin >> g_chUserID;
std::cout << "Password:";
std::cin >> g_chPassword;
std::cout << "InvestorID:";
std::cin >> g_chInvestorID;
// 输入是否认证 0-否 1-是
std::cout << "Is Need Authenticate (0-no, 1-yes):";
std::cin >> g_nAuthenticate;
if (g_nAuthenticate == 1)
{
std::cout << "AppID:";
std::cin >> g_chAppID;
std::cout << "AuthCode:";
std::cin >> g_chAuthCode;
ReqAuth(++RequestID);
}
else
{
ReqLogin(++RequestID);
}

while (!pTraderSpi->m_bIsLogin)
{
std::this_thread::sleep_for(std::chrono::microseconds(1000));
continue;
}

// 注释了报价相关的请求 需要时打开
// 操作类型
int operationType = 0;
while (1)
{
ShowHelp();
// 接受用户输入 执行对应的查询和报单操作
std::cin >> operationType;
switch (operationType)
{
case 1:
// 合约查询请求
ReqQryInstrument(RequestID);
break;
case 2:
// 报单录入请求
ReqOrderInsert(RequestID);
break;
case 3:
// 报单操作请求
ReqOrderAction(RequestID);
break;
case 4:
// 客户信息量阈值设置请求
// ReqSetClientMaxSigVol(RequestID);
break;
case 5:
// 可用投资者账户查询请求
ReqQryUserInvestor(RequestID);
break;
case 6:
// 投资者资金账户查询请求
ReqQryInvestorAccount(RequestID);
break;
case 7:
// 投资者持仓查询请求
ReqQryInvestorPosition(RequestID);
break;
case 8:
// 投资者手续费率查询请求
ReqQryInvestorFee(RequestID);
break;
case 9:
// 投资者保证金率查询请求
ReqQryInvestorMargin(RequestID);
break;
case 10:
// 金交所递延费率查询请求
// ReqQrySGEDeferRate(RequestID);
break;
case 11:
// 投资者期权手续费率查询请求
ReqQryInvestorOptionFee(RequestID);
break;
case 12:
// 报价录入请求
ReqQuoteInsert(RequestID);
break;
case 13:
// 报价操作请求
ReqQuoteAction(RequestID);
break;
case 15:
// 用户采集信息发送请求
// ReqSubmitUserSystemInfo(RequestID);
break;
case 16:
// 报单查询请求
ReqQryOrder(RequestID);
break;
case 17:
// 成交单查询请求
ReqQryTrade(RequestID);
break;
case 18:
// 交易所查询请求
ReqQryExchange(RequestID);
break;
case 19:
// 实时行情查询请求
ReqQryMarketData(RequestID);
break;
case 20:
// 询价查询请求
ReqQryForQuote(RequestID);
break;
case 21:
// 询价录入请求
ReqForQuoteInsert(RequestID);
break;
case 22:
// 订阅品种交易流水
// ReqSubPrdTradeFlow(RequestID);
break;
case 23:
// 退订订阅品种交易流水
// ReqUnSubPrdTradeFlow(RequestID);
break;
case 24:
// 用户密码修改请求
ReqUserPasswordUpdate(RequestID);
break;
default:
break;
}
RequestID++;
}
}

int main()
{
// 产生一个CQdpFtdcTraderApi实例
CQdpFtdcTraderApi *pUserApi = CQdpFtdcTraderApi::CreateFtdcTraderApi();

// 保存api
g_pTraderApi = pUserApi;

// 获取API版本号
int max_version, min_version;
std::cout << "API版本号:" << CQdpFtdcTraderApi::GetVersion(max_version, min_version);

// 产生一个事件处理的实例
CTraderSpi *pTraderSpi = new CTraderSpi(pUserApi);

// 注册事件处理的实例
pUserApi->RegisterSpi(pTraderSpi);
// 订阅私有流
// QDP_TERT_RESTART:从本交易日开始重传
// QDP_TERT_RESUME:从上次收到的续传
// QDP_TERT_QUICK:只传送登录后私有流的内容
pUserApi->SubscribePrivateTopic(QDP_TERT_QUICK);
// 订阅公共流
// QDP_TERT_RESTART:从本交易日开始重传
// QDP_TERT_RESUME:从上次收到的续传
// QDP_TERT_QUICK:只传送登录后私有流的内容
pUserApi->SubscribePublicTopic(QDP_TERT_QUICK);

// 设置量投科技服务的地址,可以注册多个地址备用
pUserApi->RegisterFront("tcp://192.168.92.212:30005");

// 设置心跳超时
// pUserApi->SetHeartbeatTimeout(240);

// 使客户端开始与后台服务建立连接
pUserApi->Init();

OrderFunc(pTraderSpi);

// 等待API实例
pUserApi->Join();
// 释放API实例
pUserApi->Release();
return 0;
}

Udp或者EfviUdp使用demo

注意:

  • 如果策略机安装了solarflare网卡,则可以选择efviudp通道,穿透延迟最低,报单接口调用耗时最少,在200ns左右。
#include "QdpShmTraderApi.h"
#include <iostream>
#include <cstdlib>
#include <string.h>
#include <stdio.h>
#include <unistd.h>
#include <thread>
#include <chrono>

using namespace std;

#ifdef WIN32
#define WINDOWS
#endif

#ifdef WINDOWS
#include <windows.h>
typedef HANDLE THREAD_HANDLE;
#define SLEEP(ms) Sleep(ms)
#else
#include <pthread.h>
#include <sys/time.h>
#include <unistd.h>
typedef pthread_t THREAD_HANDLE;
#define SLEEP(ms) usleep((ms) * 1000)
typedef unsigned int DWORD;
#endif

// 报单录入操作是否完成的标志
// 经纪公司代码
TQdpFtdcBrokerIDType g_chBrokerID;
// 交易用户代码
TQdpFtdcUserIDType g_chUserID;
// 用户密码
TQdpFtdcPasswordType g_chPassword;
// 投资者代码
TQdpFtdcInvestorIDType g_chInvestorID;
// 用户本地最大报单号
int g_nOrdLocalID = 0;
/* 认证相关信息 */
// 是否需要认证 0-不需要 1-需要
int g_nAuthenticate = 0;
TQdpFtdcAppIDType g_chAppID;
TQdpFtdcPasswordType g_chAuthCode;
/// 交易API
CQdpShmTraderApi *g_pShmTraderApi = NULL;

class CThread
{
public:
CThread()
{
m_hThread = (THREAD_HANDLE)0;
m_IDThread = 0;
}

virtual ~CThread() {}

virtual bool Create()
{
if (m_hThread != (THREAD_HANDLE)0)
{
return true;
}
bool ret = true;
#ifdef WIN32
m_hThread = ::CreateThread(NULL, 0, _ThreadEntry, this, 0, &m_IDThread);
if (m_hThread == NULL)
{
ret = false;
}
#else
ret = (::pthread_create(&m_hThread, NULL, &_ThreadEntry, this) == 0);
#endif
return ret;
}

void ExitThread()
{
#ifdef WIN32
::ExitThread(0);
#endif
}

private:
#ifdef WIN32
static DWORD WINAPI _ThreadEntry(LPVOID pParam)
#else
static void *_ThreadEntry(void *pParam)
#endif
{
CThread *pThread = (CThread *)pParam;
if (pThread->InitInstance())
{
pThread->Run();
}

pThread->ExitInstance();

return NULL;
}

virtual bool InitInstance()
{
return true;
}

virtual void ExitInstance() {}

virtual void Run() = 0;

private:
THREAD_HANDLE m_hThread;
DWORD m_IDThread;
};

class CMyWorkThread : public CThread
{
public:
CMyWorkThread(CQdpShmTraderApi *pSuperApi) : m_pSuperApi(pSuperApi) {};
~CMyWorkThread() {};
virtual void Run()
{
while (1)
{
m_pSuperApi->ReadFromSession();
// SLEEP(100);
}
}

public:
CQdpShmTraderApi *m_pSuperApi;
};

void ReqLogin(int RequestID);

void ReqAuth(int RequestID);

void ReqQuoteAction(int RequestID);

void ReqQuoteInsert(int RequestID);

int ReqOrderAction(int RequestID);

int ReqOrderInsert(int RequestID);

int InvestorIDToNum(const char *investorID);

class CShmTraderSpi : public CQdpShmTraderSpi
{
public:
explicit CShmTraderSpi(CQdpShmTraderApi *pUserApi) :
m_pTraderApi(pUserApi),
m_bConnected(false),
m_bIsLogin(false) {}

~CShmTraderSpi() {}

// 实现CTraderSpi的各个接口
void OnFrontConnected()
{
std::cout << "OnFrontConnected\n";
// udp登出一次,防止会话未删除
CQdpFtdcReqUserLogoutField pRspUserLogout;
memset(&pRspUserLogout, 0, sizeof(pRspUserLogout));
m_pTraderApi->ReqUserLogout(&pRspUserLogout, 0);
// 必须睡眠,不能立刻登录
sleep(1);

m_bConnected = true;
}

void OnFrontDisconnected()
{
std::cout << "OnFrontDisconnected\n";
m_bConnected = false;
m_bIsLogin = false;
}

void OnRspUserLogin(CQdpFtdcRspUserLoginField *pRspUserLogin, CQdpFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast)
{
if (pRspInfo == NULL)
{
std::cout << "OnRspUserLogin=NULL!\n";
return;
}

if (pRspInfo->ErrorID != 0)
{
std::cout << "UserID: " << g_chUserID << "Login failed, ErrorMsg: " << pRspInfo->ErrorMsg;
return;
}
std::cout << "UserID: " << g_chUserID << "Login Success.\n";

m_bIsLogin = true;
}

void OnRspAuthenticate(CQdpFtdcRtnAuthenticateField *pRtnAuthenticate, CQdpFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast)
{
if (pRspInfo == NULL)
{
std::cout << "OnRspAuthenticate=NULL!\n";
return;
}
if (pRspInfo->ErrorID != 0)
{
std::cout << "OnRspAuthenticate failed, ErrorMsg:" << pRspInfo->ErrorMsg << "\n";
return;
}

std::cout << "OnRspAuthenticate success, UserID:" << pRtnAuthenticate->UserID << "\n";

// 认证成功后登录
ReqLogin(nRequestID);
}

void OnRspOrderAction(CQdpFtdcOrderActionField *pOrderAction, CQdpFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast)
{
if (pRspInfo == NULL)
{
std::cout << "OnRspOrderAction=NULL!\n";
return;
}
if (pRspInfo != NULL && pRspInfo->ErrorID != 0)
{
std::cout << "OnRspOrderAction failed, ErrorMsg:" << pRspInfo->ErrorMsg << "\n";
return;
}
std::cout << "OnRspOrderAction success, OrderSysID=" << pOrderAction->OrderSysID;
};

void OnRspOrderInsert(CQdpFtdcRspInputOrderField *pRspInputOrder, CQdpFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast)
{
std::cout << "OnRspOrderInsert\n";
if (pRspInfo != NULL && pRspInfo->ErrorID != 0)
{
std::cout << "failed; ErrorID: " << pRspInfo->ErrorID
<< ", ErrorMsg: " << pRspInfo->ErrorMsg
<< ", RequestID: " << nRequestID << std::endl;
return;
}

if (pRspInputOrder != NULL)
{
std::cout << "Success; InvestorIDNum=[" << pRspInputOrder->InvestorIDNum
<< "],InstrumentID=[" << pRspInputOrder->InstrumentID
<< "],OrderSysID=[" << pRspInputOrder->OrderSysID
<< "],Volume=[" << pRspInputOrder->Volume
<< "],LimitPrice=[" << pRspInputOrder->LimitPrice
<< "],UserOrderLocalID=[" << pRspInputOrder->UserOrderLocalID
<< "];\n";
}
}

// traderSPI
void OnRtnTrade(CQdpFtdcTradeField *pTrade)
{
std::cout << "OnRtnTrade: OrderSysID=" << pTrade->OrderSysID
<< ", InstrumentID=" << pTrade->InstrumentID
<< ", TradeID=" << pTrade->TradeID
<< ", TradeVolume=" << pTrade->TradeVolume
<< "\n";
}

void OnRtnOrder(CQdpFtdcOrderField *pOrder)
{
// store OrderSysID
std::cout << "OnRtnOrder: OrderSysID=" << pOrder->OrderSysID
<< ", InstrumentID=" << pOrder->InstrumentID
<< ", Volume=" << pOrder->Volume
<< ", OrderStatus=" << pOrder->OrderStatus
<< "\n";
}

void OnRspQuoteAction(CQdpFtdcQuoteActionField *pQuoteAction, CQdpFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast)
{
std::cout << "OnRspQuoteAction\n";
if (pRspInfo != NULL && pRspInfo->ErrorID != 0)
{
std::cout << "failed; ErrorID: " << pRspInfo->ErrorID
<< ", ErrorMsg: " << pRspInfo->ErrorMsg
<< ", RequestID: " << nRequestID << std::endl;
return;
}
if (pQuoteAction != NULL)
{

std::cout << "Success; UserOrderLocalID=[" << pQuoteAction->UserOrderLocalID
<< "], UserOrderActionLocalID=[" << pQuoteAction->UserOrderActionLocalID
<< "], OrderSysID=[" << pQuoteAction->OrderSysID
<< "];\n";
}
}

void OnRspQuoteInsert(CQdpFtdcRspInputQuoteField *pRspInputQuote, CQdpFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast)
{
std::cout << "OnRspQuoteInsert\n";
if (pRspInfo != NULL && pRspInfo->ErrorID != 0)
{
std::cout << "failed; ErrorID: " << pRspInfo->ErrorID
<< ", ErrorMsg: " << pRspInfo->ErrorMsg
<< ", RequestID: " << nRequestID << std::endl;
return;
}

if (pRspInputQuote != NULL)
{
std::cout << "Success; InstrumentIDNum=[" << pRspInputQuote->InstrumentIDNum
<< "],InvestorIDNum=[" << pRspInputQuote->InvestorIDNum
<< "],AskPrice=[" << pRspInputQuote->AskPrice
<< "],AskVolume=[" << pRspInputQuote->AskVolume
<< "],BidPrice=[" << pRspInputQuote->BidPrice
<< "],BidVolume=[" << pRspInputQuote->BidVolume
<< "],BidOrderRef=[" << pRspInputQuote->BidOrderRef
<< "],AskOrderRef=[" << pRspInputQuote->AskOrderRef
<< "],ExchangeID=[" << pRspInputQuote->ExchangeID
<< "],OrderSysID=[" << pRspInputQuote->OrderSysID
<< "\n";
}
}

void OnRtnQuote(CQdpFtdcQuoteField *pQuote)
{
// 报价回报
std::cout << "OnRtnQuote, OrderSysID=" << pQuote->OrderSysID
<< ", InvestorID=" << pQuote->InvestorID
<< ", UserOrderLocalID=" << pQuote->UserOrderLocalID
<< ", OrderStatus=" << pQuote->OrderStatus
<< ", BidOrderSysID=" << pQuote->BidOrderSysID
<< ", AskOrderSysID=" << pQuote->AskOrderSysID
<< "\n";
}

private:
CQdpShmTraderApi *m_pTraderApi; // spi对应的shm api

public:
bool m_bIsLogin;
bool m_bConnected;
};

void ReqLogin(int RequestID)
{
CQdpFtdcReqUserLoginField reqUserLogin;

strcpy(reqUserLogin.UserProductInfo, "demo_test");
strcpy(reqUserLogin.BrokerID, g_chBrokerID);
strcpy(reqUserLogin.UserID, g_chUserID);
strcpy(reqUserLogin.Password, g_chPassword);
// 发出登陆请求
g_pShmTraderApi->ReqUserLogin(&reqUserLogin, RequestID);
}

void ReqAuth(int RequestID)
{
CQdpFtdcAuthenticateField reqfield;
strcpy(reqfield.BrokerID, g_chBrokerID);
strcpy(reqfield.UserID, g_chUserID);
strcpy(reqfield.UserProductInfo, "demo_test");
strcpy(reqfield.AppID, g_chAppID);
strcpy(reqfield.AuthCode, g_chAuthCode);
// 发出认证请求
g_pShmTraderApi->ReqAuthenticate(&reqfield, RequestID);
}

void ReqQuoteAction(int RequestID)
{
std::cout << "ReqQuoteAction Info:" << std::endl;
CQdpFtdcQuoteActionField quote;
memset(&quote, 0, sizeof(quote));
std::cout << "ExchangeID:";
std::cin >> quote.ExchangeID;
quote.UserOrderActionLocalID = ++g_nOrdLocalID;
std::cout << "OrderSysID:";
std::cin >> quote.OrderSysID;
std::cout << "UserOrderLocalID:";
std::cin >> quote.UserOrderLocalID;
quote.ActionFlag = QDP_FTDC_AF_Delete;
g_pShmTraderApi->ReqQuoteAction(&quote, RequestID);
}

void ReqQuoteInsert(int RequestID)
{
std::cout << "ReqQuoteInsert Info:" << std::endl;
CQdpFtdcInputQuoteField quote;
memset(&quote, 0, sizeof(quote));
// 合约号 -- 需要调用合约查询(来自tcp通道) 获取合约代码对应的合约号
std::cout << "InstrumentIDNum: ";
std::cin >> quote.InstrumentIDNum;
// 本地报单号
quote.UserOrderLocalID = ++g_nOrdLocalID;
// 投资者IDNum
quote.InvestorIDNum = atoi(g_chInvestorID);

// 卖出参数
std::cout << "AskOffsetFlag: ";
std::cin >> quote.AskOffsetFlag;
std::cout << "AskHedgeFlag: ";
std::cin >> quote.AskHedgeFlag;
std::cout << "AskPrice: ";
std::cin >> quote.AskPrice;
std::cout << "AskVolume: ";
std::cin >> quote.AskVolume;
quote.AskOrderRef = ++g_nOrdLocalID;

// 买入参数
std::cout << "BidOffsetFlag: ";
std::cin >> quote.BidOffsetFlag;
std::cout << "BidHedgeFlag: ";
std::cin >> quote.BidHedgeFlag;
std::cout << "BidPrice: ";
std::cin >> quote.BidPrice;
std::cout << "BidVolume: ";
std::cin >> quote.BidVolume;
quote.BidOrderRef = ++g_nOrdLocalID;

g_pShmTraderApi->ReqQuoteInsert(&quote, RequestID);
}

int ReqOrderAction(int RequestID)
{
std::cout << "ReqOrderAction Info:" << std::endl;
CQdpFtdcOrderActionField ord;
memset(&ord, 0, sizeof(ord));
// 交易所
std::cout << "ExchangeID: ";
std::cin >> ord.ExchangeID;
// 被撤订单的本地报单编号
std::cout << "UserOrderLocalID: ";
std::cin >> ord.UserOrderLocalID;
// 本次撤单操作的本地编号
ord.UserOrderActionLocalID = ++g_nOrdLocalID;
// 报单编号
std::cout << "OrderSysID: ";
std::cin >> ord.OrderSysID;
// 报单操作标志
ord.ActionFlag = QDP_FTDC_AF_Delete;

return g_pShmTraderApi->ReqOrderAction(&ord, RequestID);
}

// InvestorID和InvestorIDNum的转换关系
int InvestorIDToNum(const char *investorID)
{
char buffer[20] = { 0 };
size_t i = 0;

const size_t valid_length = strlen(investorID);
if (valid_length > 19 || valid_length == 0)
{
printf("invalid investorID: %s\n", investorID);
return 0;
}

// 预处理:替换非数字字符为'0',并复制到缓冲区
for (i = 0; i < valid_length; ++i)
{
if (investorID[i] < '0' || investorID[i] > '9')
{
buffer[i] = '0';
}
else
{
buffer[i] = investorID[i];
}
}
buffer[i] = '\0'; // 确保字符串终止

// 确定起始位置(长度>9时取后8位)
const char *start = buffer;
if (valid_length > 9)
{
start += valid_length - 8;
}

// 高性能转换:直接计算整数值
int result = 0;
for (const char *p = start; *p != '\0'; ++p)
{
result = result * 10 + (*p - '0');
}

return result;
}

int ReqOrderInsert(int RequestID)
{
std::cout << "ReqOrderInsert Info:" << std::endl;
CQdpFtdcInputOrderField ord;
memset(&ord, 0, sizeof(ord));
// 投资者编号 (对于API7.0版本,InstrumentIDNum通过合约查询的回调获取)

ord.InvestorIDNum = atoi(g_chInvestorID);
//如果9位及以上的InvestorID可以通过InvestorIDToNum()函数转换,对于超过的截取后8位
ord.InvestorIDNum = InvestorIDToNum(g_chInvestorID);

// 合约号 -- 需要调用合约查询 获取合约代码对应的合约号
std::cout << "InstrumentIDNum: ";
std::cin >> ord.InstrumentIDNum;

// 本地报单号
ord.UserOrderLocalID = ++g_nOrdLocalID;
// 报单类型
std::cout << "OrderPriceType: ";
std::cin >> ord.OrderPriceType;
// ord.OrderPriceType = QDP_FTDC_OPT_LimitPrice;
// 买卖方向
std::cout << "Direction: ";
std::cin >> ord.Direction;
// ord.Direction = QDP_FTDC_D_Buy;
// 开平标志
std::cout << "OffsetFlag: ";
std::cin >> ord.OffsetFlag;
// strcpy(&(ord.OffsetFlag), "0");
// 投机套保标志
std::cout << "HedgeFlag: ";
std::cin >> ord.HedgeFlag;
// strcpy(&(ord.HedgeFlag), "1");
// 价格
std::cout << "LimitPrice: ";
std::cin >> ord.LimitPrice;
// ord.LimitPrice = 3074;
// 数量
std::cout << "Volume: ";
std::cin >> ord.Volume;
// ord.Volume = 1;
// 有效期类型
std::cout << "TimeCondition: ";
std::cin >> ord.TimeCondition;
// ord.TimeCondition = QDP_FTDC_TC_GFD;
// 成交量类型
std::cout << "VolumeCondition: ";
std::cin >> ord.VolumeCondition;
// ord.VolumeCondition = QDP_FTDC_VC_AV;

return g_pShmTraderApi->ReqOrderInsert(&ord, RequestID);
}

void ShowHelp()
{
std::cout << "输入数字执行对应的操作:\n"
" 1: 报单录入请求\n"
" 2: 报单操作请求\n"
" 3: 报价录入请求\n"
" 4: 报价操作请求\n"
"------------------------------\n";
}

void OrderFunc(CShmTraderSpi *pShmTraderSpi)
{
if (NULL == pShmTraderSpi)
{
return;
}
while (!pShmTraderSpi->m_bConnected)
{
std::this_thread::sleep_for(std::chrono::microseconds(1000));
continue;
}
int RequestID = 0;

std::cout << "please input user info...\n";
std::cout << "BrokerID:";
std::cin >> g_chBrokerID;
std::cout << "UserID:";
std::cin >> g_chUserID;
std::cout << "Password:";
std::cin >> g_chPassword;
std::cout << "InvestorID:";
std::cin >> g_chInvestorID;
// 输入是否认证 0-否 1-是
std::cout << "Is Need Authenticate (0-no, 1-yes):";
std::cin >> g_nAuthenticate;
if (g_nAuthenticate == 1)
{
std::cout << "AppID:";
std::cin >> g_chAppID;
std::cout << "AuthCode:";
std::cin >> g_chAuthCode;
ReqAuth(++RequestID);
}
else
{
ReqLogin(++RequestID);
}

while (!pShmTraderSpi->m_bIsLogin)
{
std::this_thread::sleep_for(std::chrono::microseconds(1000));
continue;
}

// 操作类型
int operationType = 0;
while (1)
{
ShowHelp();
// 接受用户输入 执行对应的查询和报单操作
std::cin >> operationType;
switch (operationType)
{
case 1:
// 报单录入请求
ReqOrderInsert(RequestID);
break;
case 2:
// 报单操作请求
ReqOrderAction(RequestID);
break;
case 3:
// 报价录入请求
ReqQuoteInsert(RequestID);
break;
case 4:
// 报价操作请求
ReqQuoteAction(RequestID);
break;
default:
break;
}
RequestID++;
}
}


// TODO:添加报单,登录和认证功能
int main()
{
// 产生一个CQdpShmTraderApi实例
CQdpShmTraderApi *pSupUserApi = CQdpShmTraderApi::CreateShmTraderApi();

// 保存api
g_pShmTraderApi = pSupUserApi;

// 产生一个事件处理的实例
CShmTraderSpi *pShmTraderSpi = new CShmTraderSpi(pSupUserApi);

// 注册事件处理的实例
pSupUserApi->RegisterSpi(pShmTraderSpi);

// 设置量投科技服务的地址,可以注册多个地址备用

pSupUserApi->RegisterFront("udp://192.168.92.212:6099"); // UDP模式

// EfviUDP模式 使用efviudp通道前一定要注册solarflare网卡
// pSupUserApi->RegisterEfviUdpNic("p1p1");
// pSupUserApi->RegisterFront("efviudp://192.168.92.12:6099");
pSupUserApi->Connect();

CMyWorkThread myCMyWorkThread(pSupUserApi);
myCMyWorkThread.Create();

OrderFunc(pShmTraderSpi);

while (1)
{
sleep(1);
}
return 0;
}