1. 程式人生 > >期貨行情介面開發之一

期貨行情介面開發之一

#include"acsy/util/publictools.h"
#include <stdio.h> 
#include <iostream>
#include <windows.h> 
#include "ThostTraderApi/win32/ThostFtdcMdApi.h"
#include "ThostTraderApi/win32/ThostFtdcTraderApi.h"
#include <fstream>
#include <vector>
#include <string>
#include <boost/filesystem.hpp>
#include<string>
#include<mutex>
#include "acsy/util/acsyapplication.h"








#define MAX_ACCEPTABLE_PRICE (1.0E+15)
#define DEAL_TOO_MAX( x ) if( ((x)>MAX_ACCEPTABLE_PRICE) || ((x)<(0-MAX_ACCEPTABLE_PRICE)) ) x = 0
HANDLE g_hEvent = CreateEvent(NULL, true, false, NULL);


namespace acsy
{
namespace trader
{
struct A
{
std::mutex mutex;
bool value;
void setValue(bool v){
this->mutex.lock();
this->value = v;
this->mutex.unlock();
}
bool getValue(){
return this->value;
}
void fun();
bool fun1();
};
class tools :public util::Application < tools > {
public:
TThostFtdcBrokerIDType m_chBrokerID;
TThostFtdcUserIDType m_chUserID;
TThostFtdcUserIDType m_chUserPassword;
TThostFtdcInstrumentIDType m_instrumentID;
TThostFtdcExchangeIDType m_exchangeID;
TThostFtdcExchangeInstIDType m_exchangeInstID;
TThostFtdcInstrumentIDType m_productID;
std::vector<std::string> m_vec;
A m_login;
A m_insok;
int cnt = 0;
int cnt1 = 0;
CThostFtdcMdApi *m_pUserApi1;
CThostFtdcTraderApi *m_pUserApi;
public:
tools();
int main();
std::string getappname(){ return "shujubaocun"; }
};
template < class T > class Deal{
public:
void setValue(const T &v);
T getValue() const;
public:
std::mutex m_mutex;
T m_value;
};
class datasvrlog :public util::Logger
{
public:
virtual int log(const char *str);
};
class CSimpleHandler : public CThostFtdcTraderSpi
{
public:
// 建構函式,需要 個有效的指向CThostFtdcMduserApi例項的指標 
CSimpleHandler(CThostFtdcTraderApi *pUserApi, tools *tl);
~CSimpleHandler() {}
virtual void OnFrontConnected();
virtual void OnFrontDisconnected(int nReason);
virtual void OnRspUserLogin(CThostFtdcRspUserLoginField *pRspUserLogin, CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast);
virtual void OnRspOrderInsert(CThostFtdcInputOrderField *pInputOrder, CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast);
virtual void OnRspError(CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast);
virtual void OnRspQryInstrument(CThostFtdcInstrumentField *pInstrument, CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast);
public:
tools *tl;
};
class CSimpleHandler1 : public CThostFtdcMdSpi
{
public:
CSimpleHandler1(CThostFtdcMdApi *pUserApi1,tools *tl);
~CSimpleHandler1() {};
virtual void OnRspError(CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast);
virtual void OnRtnDepthMarketData(CThostFtdcDepthMarketDataField *pDepthMarketData) override;
virtual void OnRspSubMarketData(CThostFtdcSpecificInstrumentField *pSpecificInstrument, CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast);
virtual void OnRspUserLogin(CThostFtdcRspUserLoginField *pRspUserLogin, CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast);
virtual void OnFrontDisconnected(int nReason);
virtual void OnFrontConnected();
public:
tools *tl;
};
//tools實現
int tools::main()
{
datasvrlog ds;
ref().logger().registerLogger(&ds);
// 產生一個CThostFtdcTraderApi例項 
CThostFtdcTraderApi *pUserApi = CThostFtdcTraderApi::CreateFtdcTraderApi();
CThostFtdcMdApi *pUserApi1 = CThostFtdcMdApi::CreateFtdcMdApi();
// 產生一個事件處理的例項 
CSimpleHandler sh(pUserApi, this);
CSimpleHandler1 sh1(pUserApi1, this);
// 註冊 事件處理的例項 
pUserApi->RegisterSpi(&sh);
pUserApi1->RegisterSpi(&sh1);
// 訂閱私有流 
//        TERT_RESTART:從本交易日開始重傳 
//        TERT_RESUME:從上次收到的續傳 
//        TERT_QUICK:只傳送登入後私有流的內容 
pUserApi->SubscribePrivateTopic(THOST_TERT_RESUME);


// 訂閱公共流 
//        TERT_RESTART:從本交易日開始重傳 
//        TERT_RESUME:從上次收到的續傳 
//        TERT_QUICK:只傳送登入後公共流的內容 
pUserApi->SubscribePublicTopic(THOST_TERT_RESUME);
// 設定交易託管系統服務的地址,可以註冊多個地址備用 
pUserApi->RegisterFront("tcp://180.168.146.187:10000");
pUserApi1->RegisterFront("tcp://180.168.146.187:10010");
// 使客戶端開始與後臺服務建立連線 
pUserApi->Init();
pUserApi1->Init();




// 客戶端等待報單操作完成 
WaitForSingleObject(g_hEvent, INFINITE);


// 釋放API例項 
pUserApi->Release();
pUserApi1->Release();
system("pause");
return 0;
}
tools::tools()
{
m_insok.value = false;
m_login.value = false;
strcpy(m_chBrokerID, "9999");
strcpy(m_chUserID, "******");
strcpy(m_chUserPassword, "******");
strcpy(m_instrumentID, "");
strcpy(m_exchangeID, "");
strcpy(m_productID, "");
}
//datasvrlog實現
int datasvrlog::log(const char *str)
{
std::string filename = "h:\\log.txt";
std::ifstream ifs(filename);
if (ifs)   //存在
{
std::ofstream fout(filename, std::ios::app);
fout << str;
fout.close();
}
else     //不存在
{
std::ofstream fout(filename);
fout << str;
}
return 0;
}
//CSimpleHandler實現
CSimpleHandler::CSimpleHandler(CThostFtdcTraderApi *pUserApi,tools *tl)
{
this->tl = tl;
tl->m_pUserApi = pUserApi;
}
void CSimpleHandler::OnFrontConnected()
{
CThostFtdcReqUserLoginField reqUserLogin;
strcpy(reqUserLogin.BrokerID, tl->m_chBrokerID);
strcpy(reqUserLogin.UserID, tl->m_chUserID);
strcpy(reqUserLogin.Password, tl->m_chUserPassword);
tl->m_pUserApi->ReqUserLogin(&reqUserLogin, 0);
}
void CSimpleHandler::OnFrontDisconnected(int nReason)
{
// 當發生這個情況後,API會自動重新連線,客戶端可不做處理 
tools::instance().logger().log("OnFrontDisconnected.");
}
void CSimpleHandler::OnRspUserLogin(CThostFtdcRspUserLoginField *pRspUserLogin,CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast)
{


tools::instance().logger().log("OnRspUserLogin:");
tools::instance().logger().log("ErrorCode=[%d], ErrorMsg=[%s]", pRspInfo->ErrorID,
pRspInfo->ErrorMsg);
tools::instance().logger().log("RequestID= [%d], Chain=[%d]", nRequestID, bIsLast);
if (pRspInfo->ErrorID != 0) {
// 端登失敗,客戶端需進行錯誤處理 
tools::instance().logger().log("Trader failed to login, errorcode=%d errormsg=%s requestid=%d chain = %d", pRspInfo->ErrorID, pRspInfo->ErrorMsg, nRequestID, bIsLast);
/*exit(-1);*/
Sleep(5000);
tl->cnt++;
CThostFtdcReqUserLoginField reqUserLogin;
strcpy(reqUserLogin.BrokerID, tl->m_chBrokerID);
strcpy(reqUserLogin.UserID, tl->m_chUserID);
strcpy(reqUserLogin.Password, tl->m_chUserPassword);
tl->m_pUserApi->ReqUserLogin(&reqUserLogin, 0);
tools::instance().logger().log("Trader登入失敗後,第[%d]次登入!",tl->cnt);
}
//查詢合約請求
else if (pRspInfo->ErrorID == 0)
{
CThostFtdcQryInstrumentField req;
strcpy(req.InstrumentID, tl->m_instrumentID);
strcpy(req.ExchangeInstID, tl->m_exchangeInstID);
strcpy(req.ExchangeID, tl->m_exchangeID);
strcpy(req.ProductID, tl->m_productID);
tl->m_pUserApi->ReqQryInstrument(&req, 0);
}
}
void CSimpleHandler::OnRspOrderInsert(CThostFtdcInputOrderField *pInputOrder,CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast)
{
// 輸出報單錄入結果 
tools::instance().logger().log("ErrorCode=[%d], ErrorMsg=[%s]", pRspInfo->ErrorID,
pRspInfo->ErrorMsg);


// 通知報單錄入完成 
SetEvent(g_hEvent);
};
void CSimpleHandler::OnRspError(CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast)
{
tools::instance().logger().log("OnRspError:");
tools::instance().logger().log("ErrorCode=[%d], ErrorMsg=[%s]", pRspInfo->ErrorID,
pRspInfo->ErrorMsg);
tools::instance().logger().log("RequestID= [%d], Chain=[%d]", nRequestID, bIsLast);
// 客戶端需進行錯誤處理 
//{客戶端的錯誤處理}
}
void CSimpleHandler::OnRspQryInstrument(CThostFtdcInstrumentField *pInstrument, CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast)
{
tools::instance().logger().log("合約請求響應!,InstrumentID:[%s]", pInstrument->InstrumentID);
std::cout << "InstrumentID=" << pInstrument->InstrumentID << std::endl;


tl->m_vec.push_back(pInstrument->InstrumentID);
if (bIsLast)
{
tl->m_insok.fun();   //m_insok加鎖
if (tl->m_login.fun1()==true)   //m_login加鎖
{
int len = tl->m_vec.size();
char** Instrument = new char*[len];
for (int i = 0; i < len; i++)
{
Instrument[i] = const_cast<char*>(tl->m_vec[i].c_str());
}
tl->m_pUserApi1->SubscribeMarketData(Instrument, len);
}
}
std::string ss = "\n";
std::string isd = pInstrument->InstrumentID + ss;
}
//CSimpleHandler1實現
CSimpleHandler1::CSimpleHandler1(CThostFtdcMdApi *pUserApi1,tools *tl)
{
this->tl = tl;
tl->m_pUserApi1 = pUserApi1;
}
void CSimpleHandler1::OnRspError(CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast) {
tools::instance().logger().log("OnRspError:");
tools::instance().logger().log("ErrorCode=[%d], ErrorMsg=[%s]", pRspInfo->ErrorID,
pRspInfo->ErrorMsg);
tools::instance().logger().log("RequestID=[%d], Chain=[%d]", nRequestID, bIsLast);
// 客戶端需進行錯誤處理
//{客戶端的錯誤處理}
}
void CSimpleHandler1::OnRtnDepthMarketData(CThostFtdcDepthMarketDataField *pDepthMarketData)
{
// 輸出報單錄入結果
char stime[64];
acsy::util::BinDateTime bts_now = acsy::util::BinDateTime::now();
acsy::util::BinDateTime bts_now_local = bts_now + 8 * acsy::util::BinDateTime::MILLIS_PER_HOUR;
bts_now_local.toLongString(stime);
/*"InstrumentID=[%s],UpdateTime=[%s],UpdateMillisec=[%d],LastPrice=[%lf],BidPrice1=[%lf],AskPrice1=[%],LowestPrice=[%],HighestPrice=[%],Volume=[%],BidVolume1=[%],AskVolume1=[%],OpenInterest=[%],Turnover=[%]\n"*/
DEAL_TOO_MAX(pDepthMarketData->PreOpenInterest);
DEAL_TOO_MAX(pDepthMarketData->PreClosePrice);
DEAL_TOO_MAX(pDepthMarketData->PreSettlementPrice);
DEAL_TOO_MAX(pDepthMarketData->ClosePrice);
DEAL_TOO_MAX(pDepthMarketData->SettlementPrice);
DEAL_TOO_MAX(pDepthMarketData->OpenInterest);
DEAL_TOO_MAX(pDepthMarketData->LastPrice);
DEAL_TOO_MAX(pDepthMarketData->UpperLimitPrice);
DEAL_TOO_MAX(pDepthMarketData->LowerLimitPrice);
DEAL_TOO_MAX(pDepthMarketData->HighestPrice);
DEAL_TOO_MAX(pDepthMarketData->LowestPrice);
DEAL_TOO_MAX(pDepthMarketData->OpenPrice);
DEAL_TOO_MAX(pDepthMarketData->LowestPrice);
DEAL_TOO_MAX(pDepthMarketData->Turnover);
if (pDepthMarketData->AskPrice1 > 10 * pDepthMarketData->LastPrice)
{
pDepthMarketData->AskPrice1 = pDepthMarketData->LastPrice;
}
if (pDepthMarketData->BidPrice1 > 10 * pDepthMarketData->LastPrice)
{
pDepthMarketData->BidPrice1 = pDepthMarketData->LastPrice;
}


printf("%s,%s.%03d,%.4f,%.4f,%.4f,%.4f,%.4f,%d,%d,%d,%s,%.2lf,%.2lf\n",
pDepthMarketData->InstrumentID, pDepthMarketData->UpdateTime, pDepthMarketData->UpdateMillisec, pDepthMarketData->LastPrice,
pDepthMarketData->BidPrice1, pDepthMarketData->AskPrice1, pDepthMarketData->LowestPrice, pDepthMarketData->HighestPrice,
pDepthMarketData->Volume, pDepthMarketData->BidVolume1, pDepthMarketData->AskVolume1, stime,
pDepthMarketData->OpenInterest, pDepthMarketData->Turnover);
std::string subs = acsy::util::strprintf("%s,%s.%03d,%.4f,%.4f,%.4f,%.4f,%.4f,%d,%d,%d,%s,%.2lf,%.2lf\n",
pDepthMarketData->InstrumentID, pDepthMarketData->UpdateTime, pDepthMarketData->UpdateMillisec, pDepthMarketData->LastPrice,
pDepthMarketData->BidPrice1, pDepthMarketData->AskPrice1, pDepthMarketData->LowestPrice, pDepthMarketData->HighestPrice,
pDepthMarketData->Volume, pDepthMarketData->BidVolume1, pDepthMarketData->AskVolume1, stime,
pDepthMarketData->OpenInterest, pDepthMarketData->Turnover);




namespace fs = boost::filesystem;
/* char stime[30] = "2015-10-23 14:07:03.579";*/
std::string date;
date = stime;




std::string s1 = date.substr(0, 4);
std::string s2 = date.substr(5, 2);
std::string s3 = date.substr(8, 2);
std::string floder = "h:\\" + s1 + s2 + s3;
fs::path full_path(fs::initial_path());
full_path = fs::system_complete(fs::path(floder, fs::native));


if (!fs::exists(floder))
{
fs::create_directories(floder);
}


std::string filename = pDepthMarketData->InstrumentID;
std::string filename1 = floder + "\\" + filename + ".csv";
std::ifstream ifs(filename1);


if (ifs)   //存在
{
std::ofstream fout(filename1, std::ios::app);
fout << subs;
fout.close();
}
else     //不存在
{
std::ofstream fout(filename1);
fout << subs;
}
}
void CSimpleHandler1::OnRspSubMarketData(CThostFtdcSpecificInstrumentField *pSpecificInstrument, CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast)
{
tools::instance().logger().log("行情請求響應!,InstrumentID:[%s]", pSpecificInstrument->InstrumentID);
}
void CSimpleHandler1::OnRspUserLogin(CThostFtdcRspUserLoginField *pRspUserLogin, CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast)
{
if (bIsLast)
{
tl->m_login.fun();  //m_login加鎖




if (tl->m_insok.fun1()==true)   //m_insok加鎖
{
int len = tl->m_vec.size();
char** Instrument = new char*[len];
for (int i = 0; i < len; i++)
{
Instrument[i] = const_cast<char*>(tl->m_vec[i].c_str());
}
tl->m_pUserApi1->SubscribeMarketData(Instrument, len);
}
}
tools::instance().logger().log("OnRspUserLogin:");
tools::instance().logger().log("ErrorCode=[%d], ErrorMsg=[%s]", pRspInfo->ErrorID,
pRspInfo->ErrorMsg);
tools::instance().logger().log("RequestID=[%d], Chain=[%d]", nRequestID, bIsLast);


if (pRspInfo->ErrorID != 0) {
// 端登失敗,客戶端需進行錯誤處理
tools::instance().logger().log("MD failed to login, errorcode=%d errormsg=%s requestid=%d chain = %d", pRspInfo->ErrorID, pRspInfo->ErrorMsg, nRequestID, bIsLast);
/*exit(-1);*/
Sleep(5000);
tl->cnt1++;
CThostFtdcReqUserLoginField reqUserLogin;
strcpy(reqUserLogin.BrokerID, tl->m_chBrokerID);
strcpy(reqUserLogin.UserID, tl->m_chUserID);
strcpy(reqUserLogin.Password, tl->m_chUserPassword);
tl->m_pUserApi1->ReqUserLogin(&reqUserLogin, 0);
tools::instance().logger().log("MD登入失敗後,第[%d]次登入!", tl->cnt1);
}
}
void CSimpleHandler1::OnFrontDisconnected(int nReason)
{
// 當發生這個情況後,API會自動重新連線,客戶端可不做處理
tools::instance().logger().log("OnFrontDisconnected.");
}
void CSimpleHandler1::OnFrontConnected()
{
CThostFtdcReqUserLoginField reqUserLogin;
strcpy(reqUserLogin.BrokerID, tl->m_chBrokerID);
strcpy(reqUserLogin.UserID, tl->m_chUserID);
strcpy(reqUserLogin.Password, tl->m_chUserPassword);
tl->m_pUserApi1->ReqUserLogin(&reqUserLogin, 0);


}
void A::fun()
{
this->mutex.lock();
this->value = true;
this->mutex.unlock();
}
bool A::fun1()
{
bool b;
this->mutex.lock();
b = this->value;
this->mutex.unlock();
return b;
}
}
}
ACSY_DEF_MAINCLASS(acsy::trader::tools);