期貨行情介面開發之一
阿新 • • 發佈:2019-01-11
#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);