diff --git a/README.md b/README.md index f8383f1e7..b063ec103 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ Welcome to StarQuant **StarQuant**(中文名:易数交易系统)是一个轻量的、面向个人( 普通)用户的综合量化交易回测系统,目前主要用于期货期权程序化交易,后期会考虑加入股票交易的功能。 -当前进展:开发已完成75%左右并在实盘测试中,对于流动性好,盘口大的品种非大笔交易下tick级回测与实盘的成交时间和价位一致。 +当前进展:完成1.0版本alpha版本,在实盘测试中,对于流动性好,盘口大的品种非大笔交易下tick级回测与实盘的成交时间和价位一致。 @@ -44,7 +44,7 @@ Welcome to StarQuant ## 开发环境 本系统在开发过程中参考了已有的开源软件vnpy,kungfu,EliteQuant等。 -开发环境:Manjaro(arch,Linux内核4.14),python 3.7.2,gcc 8.2 +开发环境:Manjaro(arch,Linux内核4.14),python 3.7.2,gcc 9.1 第三方库: boost 1.69 nanomsg @@ -103,10 +103,8 @@ python 采用flake8检查,autopep8格式化; ## TODO -本系统尚在开发过程中,当前大约完成了75%左右的功能。 -TODO: -1. 完善gui和大数据处理以及系统运行稳定性(80%) -2. 跨平台支持(100%) +本系统完成了版本1.0的alpha版本,正在实盘测试中。 + diff --git a/cppsrc/StarQuant/CMakeLists.txt b/cppsrc/StarQuant/CMakeLists.txt index 205b04ae9..2384d7fc4 100644 --- a/cppsrc/StarQuant/CMakeLists.txt +++ b/cppsrc/StarQuant/CMakeLists.txt @@ -2,7 +2,6 @@ include_directories(${StarQuantCpp_SOURCE_DIR}/StarQuant) set(StarQuantCppSrc ./Common/datastruct.cpp ./Common/util.cpp - ./Common/heartbeat.cpp ./Common/logger.cpp ./Common/config.cpp ./Common/msgq.cpp diff --git a/cppsrc/StarQuant/Common/config.cpp b/cppsrc/StarQuant/Common/config.cpp index 1a9659ba1..9e53e3f84 100644 --- a/cppsrc/StarQuant/Common/config.cpp +++ b/cppsrc/StarQuant/Common/config.cpp @@ -1,16 +1,34 @@ +/***************************************************************************** + * Copyright [2019] + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *****************************************************************************/ + +#include +#include +#include + +#include +#include #include +#include #include #include #include #include #include -#include -#include -#include -#include -#include -#include + + namespace bpt = boost::property_tree; namespace bpo = boost::program_options; @@ -34,27 +52,26 @@ namespace StarQuant { return *pinstance_; } - void CConfig::readConfig() - { -#ifdef _DEBUG - std::printf("Current path is : %s\n", boost::filesystem::current_path().string().c_str()); -#endif + void CConfig::readConfig() { // reset maps _gatewaymap.clear(); - //read server config +// read server config std::lock_guard g(readlock_); - try{ - string path = boost::filesystem::current_path().string() + "/etc/config_server.yaml"; + try { + string path = fs::current_path().string() + + "/etc/config_server.yaml"; YAML::Node config = YAML::LoadFile(path); string configmode = config["mode"].as(); - if (configmode =="record") + if (configmode =="record") { _mode = RUN_MODE::RECORD_MODE; - else if (configmode == "replay"){ + } else { + if (configmode == "replay") { _mode = RUN_MODE::REPLAY_MODE; - _tickinterval =config["tickinterval"].as(); - _brokerdelay = config["brokerdelay"].as(); + _tickinterval = config["tickinterval"].as(); + _brokerdelay = config["brokerdelay"].as(); filetoreplay = config["filetoreplay"].as(); + } } _config_dir = boost::filesystem::current_path().string() + "/etc/"; _log_dir = config["log_dir"].as(); @@ -63,7 +80,7 @@ namespace StarQuant { boost::filesystem::create_directory(log_path); boost::filesystem::path data_path(dataDir()); boost::filesystem::create_directory(data_path); - logconfigfile_ = boost::filesystem::current_path().string() + "/etc/config_log"; + logconfigfile_ = fs::current_path().string() + "/etc/config_log"; // const string msgq = config["msgq"].as(); // _msgq = MSGQ::NANOMSG; cpuaffinity = config["cpuaffinity"].as(); @@ -76,18 +93,18 @@ namespace StarQuant { SERVERSUB_URL = config["serversub_url"].as(); SERVERPULL_URL = config["serverpull_url"].as(); - // read gateway info + // read gateway info const std::vector gws = config["gateway"].as>(); - for (auto s : gws){ + for (auto s : gws) { struct Gateway gw; gw.id = s; - gw.intid = config[s]["intid"].as(); + gw.intid = config[s]["intid"].as(); gw.api = config[s]["api"].as(); gw.brokerid = config[s]["brokerid"].as(); auto mdips = config[s]["md_address"].as>(); - gw.md_address.assign(mdips.begin(),mdips.end()); + gw.md_address.assign(mdips.begin(), mdips.end()); auto tdips = config[s]["td_address"].as>(); - gw.td_address.assign(tdips.begin(),tdips.end()); + gw.td_address.assign(tdips.begin(), tdips.end()); gw.userid = config[s]["userid"].as(); gw.password = config[s]["password"].as(); gw.auth_code = config[s]["auth_code"].as(); @@ -96,39 +113,35 @@ namespace StarQuant { gw.publicstream = config[s]["publicstream"].as(); gw.privatestream = config[s]["privatestream"].as(); _gatewaymap[s] = gw; - } + } // read risk info riskcheck = config["risk"]["check"].as(); - sizeperorderlimit = config["risk"]["sizeperorder"].as(); + sizeperorderlimit = config["risk"]["sizeperorder"].as(); cashperorderlimit = config["risk"]["cashperorder"].as(); - ordercountlimit = config["risk"]["ordercount"].as(); + ordercountlimit = config["risk"]["ordercount"].as(); cashlimit = config["risk"]["cash"].as(); - ordersizelimit = config["risk"]["ordersize"].as(); - ordercountperseclimit = config["risk"]["ordercountpersec"].as(); + ordersizelimit = config["risk"]["ordersize"].as(); + ordercountperseclimit = config["risk"]["ordercountpersec"].as(); } - catch(exception &e){ - fmt::print("Read Config exception:{}.",e.what()); + catch(exception &e) { + fmt::print("Read Config exception:{}.", e.what()); } - catch(...){ + catch(...) { fmt::print("Read Config error!"); } - } - string CConfig::configDir() - { + string CConfig::configDir() { // return boost::filesystem::current_path().string(); return _config_dir; } - string CConfig::logDir() - { + string CConfig::logDir() { return _log_dir; } - string CConfig::dataDir() - { + string CConfig::dataDir() { return _data_dir; } @@ -143,13 +156,13 @@ namespace StarQuant { string fullsymbol; string num = symbol; string alpha = symbol; - num.erase(std::remove_if(num.begin(),num.end(),&::isalpha),num.end()); - alpha.erase(std::remove_if(alpha.begin(),alpha.end(),&::isdigit),alpha.end()); + num.erase(std::remove_if(num.begin(), num.end(), &::isalpha), num.end()); + alpha.erase(std::remove_if(alpha.begin(), alpha.end(), &::isdigit), alpha.end()); string tmp = instrument2sec[alpha]; fullsymbol = tmp + " " + num; return fullsymbol; } - + diff --git a/cppsrc/StarQuant/Common/config.h b/cppsrc/StarQuant/Common/config.h index b3ccf5490..ef9db8767 100644 --- a/cppsrc/StarQuant/Common/config.h +++ b/cppsrc/StarQuant/Common/config.h @@ -1,6 +1,21 @@ -#ifndef __StarQuant_Common_Config__ -#define __StarQuant_Common_Config__ +/***************************************************************************** + * Copyright [2019] + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *****************************************************************************/ +#ifndef CPPSRC_STARQUANT_COMMON_CONFIG_H_ +#define CPPSRC_STARQUANT_COMMON_CONFIG_H_ +#include #include #include #include @@ -16,9 +31,7 @@ #include #include #include - #include - #define CEREAL_RAPIDJSON_NAMESPACE creal_rapidjson #include #include @@ -27,7 +40,6 @@ #include #include -#include #ifdef _WIN32 #define WIN32_LEAN_AND_MEAN @@ -47,76 +59,70 @@ using std::atomic_int; namespace StarQuant { - class CConfig { - static CConfig* pinstance_; - static mutex instancelock_; - - CConfig(); - public: - RUN_MODE _mode = RUN_MODE::TRADE_MODE; - BROKERS _broker = BROKERS::PAPER; - MSGQ _msgq = MSGQ::NANOMSG; - int _tickinterval =0; - int _brokerdelay = 0; - static CConfig& instance(); - map _gatewaymap; - - mutex readlock_; - void readConfig(); - - string _config_dir; - string _log_dir; - string _data_dir; - string configDir(); - string logDir(); - string dataDir(); - string logconfigfile_; - - - /****************************************Securities List *************************************/ - vector securities; //full symbol - map instrument2sec; //instrument id to full symbol map - map sec2instrument; //symbol to ctp instrument - string SecurityFullNameToCtpSymbol(const std::string& symbol); - string CtpSymbolToSecurityFullName(const std::string& symbol); - /****************************************End of Securities List *************************************/ - - /**************************************** Database info ******************************************/ - string _mongodbaddr = "mongodb://localhost:27017"; - string _mongodbname = ""; - - string filetoreplay; - //vector - /**************************************** End of Database ******************************************/ - - /******************************************* Message Queue ***********************************************/ - string SERVERPUB_URL = "tcp://localhost:55555"; //to all clients - string SERVERSUB_URL = "tcp://localhost:55556"; // pub the requests to engines(which subscribe) - string SERVERPULL_URL = "tcp://localhost:55557"; //listen all the requests from clients - bool cpuaffinity = false; - /******************************************* Message Queue **********/ - - - /************************auto task*****************************/ - bool autoconnect = true; - bool autoqry = false; - - - - - /*****************************************Risk setting**************/ - bool riskcheck = false; - int sizeperorderlimit = 0; - double cashperorderlimit = 0.0; - int ordercountlimit = 0; - double cashlimit =0.0; - int ordersizelimit = 0; - int ordercountperseclimit = 0; - - /*****************************************End Risk setting**************/ - - /**************************************** End of Message Queue ******************************************/ - }; -} - -#endif // __StarQuant_Common_Config__ +class CConfig { + static CConfig* pinstance_; + static mutex instancelock_; + + CConfig(); + + public: + RUN_MODE _mode = RUN_MODE::TRADE_MODE; + BROKERS _broker = BROKERS::PAPER; + MSGQ _msgq = MSGQ::NANOMSG; + int32_t _tickinterval = 0; + int32_t _brokerdelay = 0; + static CConfig& instance(); + map _gatewaymap; + mutex readlock_; + void readConfig(); + + string _config_dir; + string _log_dir; + string _data_dir; + string configDir(); + string logDir(); + string dataDir(); + string logconfigfile_; + + /*************Securities List ****************/ + vector securities; // full symbol + map instrument2sec; // instrument id to full symbol map + map sec2instrument; // symbol to ctp instrument + string SecurityFullNameToCtpSymbol(const std::string& symbol); + string CtpSymbolToSecurityFullName(const std::string& symbol); + /********End of Securities List ************/ + + /******************* Database info ***************/ + string _mongodbaddr = "mongodb://localhost:27017"; + string _mongodbname = ""; + + string filetoreplay; + /************* End of Database **********************/ + + /*************** Message Queue ******************/ + // to all clients + string SERVERPUB_URL = "tcp://localhost:55555"; + // pub the requests to engines(which subscribe) + string SERVERSUB_URL = "tcp://localhost:55556"; + // listen all the requests from clients + string SERVERPULL_URL = "tcp://localhost:55557"; + bool cpuaffinity = false; + /******************** Message Queue **********/ + + /************************auto task*****************/ + bool autoconnect = true; + bool autoqry = false; + + /*********Risk setting**************/ + bool riskcheck = false; + int32_t sizeperorderlimit = 0; + double cashperorderlimit = 0.0; + int32_t ordercountlimit = 0; + double cashlimit = 0.0; + int32_t ordersizelimit = 0; + int32_t ordercountperseclimit = 0; + /***********End Risk setting*********/ +}; +} // namespace StarQuant + +#endif // CPPSRC_STARQUANT_COMMON_CONFIG_H_ diff --git a/cppsrc/StarQuant/Common/datastruct.cpp b/cppsrc/StarQuant/Common/datastruct.cpp index 38725bd42..dca38b423 100644 --- a/cppsrc/StarQuant/Common/datastruct.cpp +++ b/cppsrc/StarQuant/Common/datastruct.cpp @@ -1,78 +1,96 @@ +/***************************************************************************** + * Copyright [2019] + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *****************************************************************************/ -#include #include #include +#include + using namespace std; namespace StarQuant { - -long m_serverOrderId = 0; // unique order id on server side defined in ordermanager.cpp. Every broker has its own id; -std::mutex oid_mtx; // mutex for increasing order id -std::mutex orderStatus_mtx; // mutex for changing order status - -MSG_TYPE MsgType(const string& msg){ +// unique order id on server side defined in ordermanager.cpp, +// Every broker has its own id; +int64_t m_serverOrderId = 0; +// mutex for increasing order id +std::mutex oid_mtx; +// mutex for changing order status +std::mutex orderStatus_mtx; + +MSG_TYPE MsgType(const string& msg) { string header; stringstream ss(msg); - getline(ss,header,SERIALIZATION_SEPARATOR); - getline(ss,header,SERIALIZATION_SEPARATOR); - getline(ss,header,SERIALIZATION_SEPARATOR); + getline(ss, header, SERIALIZATION_SEPARATOR); + getline(ss, header, SERIALIZATION_SEPARATOR); + getline(ss, header, SERIALIZATION_SEPARATOR); MSG_TYPE msgtype_ = MSG_TYPE(atoi(header.c_str())); return msgtype_; } -string MsgFrame::serialize() { - string tmp = destination_ +string MsgFrame::serialize() { + string tmp = destination_ + SERIALIZATION_SEPARATOR + source_ + SERIALIZATION_SEPARATOR + to_string(msgtype_); - if (dataPtr != nullptr){ + if (dataPtr != nullptr) { tmp = tmp + SERIALIZATION_SEPARATOR + dataPtr->serialize(); } return tmp; -}; +} void MsgFrame::deserialize(const string& msgin) { string des; string src; string stype; string datas; stringstream ss(msgin); - getline(ss,des,SERIALIZATION_SEPARATOR); - getline(ss,src,SERIALIZATION_SEPARATOR); - getline(ss,stype,SERIALIZATION_SEPARATOR); - getline(ss,datas); + getline(ss, des, SERIALIZATION_SEPARATOR); + getline(ss, src, SERIALIZATION_SEPARATOR); + getline(ss, stype, SERIALIZATION_SEPARATOR); + getline(ss, datas); MSG_TYPE mtype = MSG_TYPE(stoi(stype)); destination_ = des; source_ = src; msgtype_ = mtype; if (!datas.empty()) dataPtr->deserialize(datas); -}; +} -string accAddress(const string& msg){ +string accAddress(const string& msg) { string acc; stringstream ss(msg); - getline(ss,acc,DESTINATION_SEPARATOR); - getline(ss,acc,DESTINATION_SEPARATOR); - getline(ss,acc,DESTINATION_SEPARATOR); + getline(ss, acc, DESTINATION_SEPARATOR); + getline(ss, acc, DESTINATION_SEPARATOR); + getline(ss, acc, DESTINATION_SEPARATOR); return acc; } -string TickMsg::serialize(){ - string ba; //bid ask price and size - for (int i = 0;i < data_.depth_;i++){ - ba = ba +string TickMsg::serialize() { + string ba; // bid ask price and size + for (int32_t i = 0; i < data_.depth_; i++) { + ba = ba + SERIALIZATION_SEPARATOR + to_string(data_.bidPrice_[i]) + SERIALIZATION_SEPARATOR + to_string(data_.bidSize_[i]) + SERIALIZATION_SEPARATOR + to_string(data_.askPrice_[i]) + SERIALIZATION_SEPARATOR + to_string(data_.askSize_[i]); } string s; - s = destination_ + s = destination_ + SERIALIZATION_SEPARATOR + source_ + SERIALIZATION_SEPARATOR + to_string(msgtype_) - + SERIALIZATION_SEPARATOR + data_.fullSymbol_ + + SERIALIZATION_SEPARATOR + data_.fullSymbol_ + SERIALIZATION_SEPARATOR + data_.time_ + SERIALIZATION_SEPARATOR + to_string(data_.price_) + SERIALIZATION_SEPARATOR + to_string(data_.size_) @@ -87,15 +105,15 @@ string TickMsg::serialize(){ return s; } -string SecurityMsg::serialize(){ +string SecurityMsg::serialize() { string s; - s = destination_ + s = destination_ + SERIALIZATION_SEPARATOR + source_ + SERIALIZATION_SEPARATOR + to_string(msgtype_) - + SERIALIZATION_SEPARATOR + data_.symbol_ - + SERIALIZATION_SEPARATOR + data_.exchange_ - + SERIALIZATION_SEPARATOR + data_.localName_ - + SERIALIZATION_SEPARATOR + data_.securityType_ + + SERIALIZATION_SEPARATOR + data_.symbol_ + + SERIALIZATION_SEPARATOR + data_.exchange_ + + SERIALIZATION_SEPARATOR + data_.localName_ + + SERIALIZATION_SEPARATOR + data_.securityType_ + SERIALIZATION_SEPARATOR + to_string(data_.multiplier_) + SERIALIZATION_SEPARATOR + to_string(data_.ticksize_) + SERIALIZATION_SEPARATOR + data_.postype_ @@ -104,21 +122,20 @@ string SecurityMsg::serialize(){ + SERIALIZATION_SEPARATOR + data_.underlyingSymbol_ + SERIALIZATION_SEPARATOR + data_.optionType_ + SERIALIZATION_SEPARATOR + to_string(data_.strikePrice_) - + SERIALIZATION_SEPARATOR + data_.expiryDate_ ; - + + SERIALIZATION_SEPARATOR + data_.expiryDate_; return s; } -string AccMsg::serialize(){ +string AccMsg::serialize() { string s; - s = destination_ + s = destination_ + SERIALIZATION_SEPARATOR + source_ + SERIALIZATION_SEPARATOR + to_string(msgtype_) - + SERIALIZATION_SEPARATOR + data_.accountID_ + + SERIALIZATION_SEPARATOR + data_.accountID_ + SERIALIZATION_SEPARATOR + to_string(data_.previousDayEquityWithLoanValue_) + SERIALIZATION_SEPARATOR + to_string(data_.netLiquidation_) + SERIALIZATION_SEPARATOR + to_string(data_.availableFunds_) - + SERIALIZATION_SEPARATOR + to_string(data_.commission_) + + SERIALIZATION_SEPARATOR + to_string(data_.commission_) + SERIALIZATION_SEPARATOR + to_string(data_.fullMaintainanceMargin_) + SERIALIZATION_SEPARATOR + to_string(data_.realizedPnL_) + SERIALIZATION_SEPARATOR + to_string(data_.unrealizedPnL_) @@ -128,11 +145,11 @@ string AccMsg::serialize(){ return s; } -string FillMsg::serialize(){ - string str = destination_ +string FillMsg::serialize() { + string str = destination_ + SERIALIZATION_SEPARATOR + source_ + SERIALIZATION_SEPARATOR + to_string(msgtype_) - + SERIALIZATION_SEPARATOR + std::to_string(data_.serverOrderID_) + + SERIALIZATION_SEPARATOR + std::to_string(data_.serverOrderID_) + SERIALIZATION_SEPARATOR + std::to_string(data_.clientOrderID_) + SERIALIZATION_SEPARATOR + std::to_string(data_.clientID_) + SERIALIZATION_SEPARATOR + data_.localNo_ @@ -142,38 +159,36 @@ string FillMsg::serialize(){ + SERIALIZATION_SEPARATOR + data_.fullSymbol_ + SERIALIZATION_SEPARATOR + std::to_string(data_.tradePrice_) + SERIALIZATION_SEPARATOR + std::to_string(data_.tradeSize_) - + SERIALIZATION_SEPARATOR + std::to_string(static_cast(data_.fillFlag_)) + + SERIALIZATION_SEPARATOR + std::to_string(static_cast(data_.fillFlag_)) + SERIALIZATION_SEPARATOR + std::to_string(data_.commission_) + SERIALIZATION_SEPARATOR + data_.account_ + SERIALIZATION_SEPARATOR + data_.api_ - + SERIALIZATION_SEPARATOR + ymdhms(); + + SERIALIZATION_SEPARATOR + ymdhms(); return str; } -bool isActiveOrder(const Order& o){ +bool isActiveOrder(const Order& o) { if (o.orderStatus_ == OrderStatus::OS_Filled) return false; if (o.orderStatus_ == OrderStatus::OS_Error) - return false; + return false; if (o.orderStatus_ == OrderStatus::OS_Canceled) return false; - - return true; + return true; } -bool isActiveOS(const OrderStatus& os){ +bool isActiveOS(const OrderStatus& os) { if (os == OrderStatus::OS_Filled) return false; if (os == OrderStatus::OS_Error) - return false; + return false; if (os == OrderStatus::OS_Canceled) return false; - - return true; + return true; } -void OrderMsg::deserialize(const string& msgin){ - vector v = stringsplit(msgin,SERIALIZATION_SEPARATOR); +void OrderMsg::deserialize(const string& msgin) { + vector v = stringsplit(msgin, SERIALIZATION_SEPARATOR); if (v.size() < 8) throw std::out_of_range("OutofRange in Order deserialize"); destination_ = v[0]; @@ -197,20 +212,20 @@ void OrderMsg::deserialize(const string& msgin){ // data_.tag_ = v[10]; } -std::shared_ptr OrderMsg::toPOrder(){ +std::shared_ptr OrderMsg::toPOrder() { std::shared_ptr o = make_shared(); o->api_ = data_.api_; - o->account_ = data_.account_; + o->account_ = data_.account_; o->clientID_ = data_.clientID_; o->clientOrderID_ = data_.clientOrderID_; o->tag_ = data_.tag_; o->orderType_ = data_.orderType_; - o->fullSymbol_ = data_.fullSymbol_; + o->fullSymbol_ = data_.fullSymbol_; o->price_ = data_.price_; o->quantity_ = data_.quantity_; o->tradedvol_ = data_.tradedvol_; - o->flag_ = data_.flag_; + o->flag_ = data_.flag_; o->serverOrderID_ = data_.serverOrderID_; o->brokerOrderID_ = data_.brokerOrderID_; o->orderNo_ = data_.orderNo_; @@ -222,8 +237,8 @@ std::shared_ptr OrderMsg::toPOrder(){ return o; } -void PaperOrderMsg::deserialize(const string& msgin){ - vector v = stringsplit(msgin,SERIALIZATION_SEPARATOR); +void PaperOrderMsg::deserialize(const string& msgin) { + vector v = stringsplit(msgin, SERIALIZATION_SEPARATOR); if (v.size() < 14) throw std::out_of_range("OutofRange in PaperOrder deserialize."); destination_ = v[0]; @@ -242,10 +257,10 @@ void PaperOrderMsg::deserialize(const string& msgin){ data_.stopPrice_ = stof(v[13]); } -std::shared_ptr PaperOrderMsg::toPOrder(){ +std::shared_ptr PaperOrderMsg::toPOrder() { auto o = make_shared(); o->api_ = data_.api_; - o->account_ = data_.account_; + o->account_ = data_.account_; o->clientID_ = data_.clientID_; o->clientOrderID_ = data_.clientOrderID_; o->tag_ = data_.tag_; @@ -253,7 +268,7 @@ std::shared_ptr PaperOrderMsg::toPOrder(){ o->price_ = data_.price_; o->quantity_ = data_.quantity_; o->tradedvol_ = data_.tradedvol_; - o->flag_ = data_.flag_; + o->flag_ = data_.flag_; o->serverOrderID_ = data_.serverOrderID_; o->brokerOrderID_ = data_.brokerOrderID_; o->orderNo_ = data_.orderNo_; @@ -263,17 +278,17 @@ std::shared_ptr PaperOrderMsg::toPOrder(){ o->orderStatus_ = data_.orderStatus_; o->orderType_ = data_.orderType_; - o->orderSize_ = data_.orderSize_ ; + o->orderSize_ = data_.orderSize_; o->limitPrice_ = data_.limitPrice_; - o->stopPrice_ = data_.stopPrice_ ; + o->stopPrice_ = data_.stopPrice_; o->orderFlag_ = data_.orderFlag_; return o; } -void CtpOrderMsg::deserialize(const string& msgin){ - vector v = stringsplit(msgin,SERIALIZATION_SEPARATOR); +void CtpOrderMsg::deserialize(const string& msgin) { + vector v = stringsplit(msgin, SERIALIZATION_SEPARATOR); if (v.size() < 27) throw std::out_of_range("OutofRange in CtpOrder deserialize."); destination_ = v[0]; @@ -286,15 +301,15 @@ void CtpOrderMsg::deserialize(const string& msgin){ data_.orderType_ = OrderType(stoi(v[7])); data_.orderField_ = {}; - strcpy(data_.orderField_.InstrumentID,v[8].c_str()); + strcpy(data_.orderField_.InstrumentID, v[8].c_str()); data_.orderField_.OrderPriceType = v[9][0]; data_.orderField_.Direction = v[10][0]; - strcpy(data_.orderField_.CombOffsetFlag,v[11].c_str()); - strcpy(data_.orderField_.CombHedgeFlag,v[12].c_str()); + strcpy(data_.orderField_.CombOffsetFlag, v[11].c_str()); + strcpy(data_.orderField_.CombHedgeFlag, v[12].c_str()); data_.orderField_.LimitPrice = stof(v[13]); data_.orderField_.VolumeTotalOriginal = stoi(v[14]); data_.orderField_.TimeCondition = v[15][0]; - strcpy(data_.orderField_.GTDDate,v[16].c_str()); + strcpy(data_.orderField_.GTDDate, v[16].c_str()); data_.orderField_.VolumeCondition = v[17][0]; data_.orderField_.MinVolume = stoi(v[18]); data_.orderField_.ContingentCondition = v[19][0]; @@ -303,25 +318,24 @@ void CtpOrderMsg::deserialize(const string& msgin){ data_.orderField_.IsAutoSuspend = stoi(v[22]); data_.orderField_.UserForceClose = stoi(v[23]); data_.orderField_.IsSwapOrder = stoi(v[24]); - strcpy(data_.orderField_.BusinessUnit,v[25].c_str()); - strcpy(data_.orderField_.CurrencyID,v[26].c_str()); - + strcpy(data_.orderField_.BusinessUnit, v[25].c_str()); + strcpy(data_.orderField_.CurrencyID, v[26].c_str()); } -std::shared_ptr CtpOrderMsg::toPOrder(){ +std::shared_ptr CtpOrderMsg::toPOrder() { std::shared_ptr o = make_shared(); o->api_ = data_.api_; - o->account_ = data_.account_; + o->account_ = data_.account_; o->clientID_ = data_.clientID_; o->clientOrderID_ = data_.clientOrderID_; o->tag_ = data_.tag_; o->orderType_ = data_.orderType_; - + o->fullSymbol_ = data_.fullSymbol_; o->price_ = data_.price_; o->quantity_ = data_.quantity_; o->tradedvol_ = data_.tradedvol_; - o->flag_ = data_.flag_; + o->flag_ = data_.flag_; o->serverOrderID_ = data_.serverOrderID_; o->brokerOrderID_ = data_.brokerOrderID_; o->orderNo_ = data_.orderNo_; @@ -329,14 +343,14 @@ std::shared_ptr CtpOrderMsg::toPOrder(){ o->createTime_ = data_.createTime_; o->updateTime_ = data_.updateTime_; o->orderStatus_ = data_.orderStatus_; - memcpy(&o->orderField_, &data_.orderField_,sizeof(CThostFtdcInputOrderField)); - //return static_pointer_cast(o); + memcpy(&o->orderField_, &data_.orderField_, sizeof(CThostFtdcInputOrderField)); + // return static_pointer_cast(o); return o; } -void CtpParkedOrderMsg::deserialize(const string& msgin){ - vector v = stringsplit(msgin,SERIALIZATION_SEPARATOR); +void CtpParkedOrderMsg::deserialize(const string& msgin) { + vector v = stringsplit(msgin, SERIALIZATION_SEPARATOR); if (v.size() < 27) throw std::out_of_range("OutofRange in CtpParkOrder deserialize."); destination_ = v[0]; @@ -348,15 +362,15 @@ void CtpParkedOrderMsg::deserialize(const string& msgin){ data_.tag_ = v[7]; data_.parkedOrderField_ = {}; - strcpy(data_.parkedOrderField_.InstrumentID,v[8].c_str()); + strcpy(data_.parkedOrderField_.InstrumentID, v[8].c_str()); data_.parkedOrderField_.OrderPriceType = v[9][0]; data_.parkedOrderField_.Direction = v[10][0]; - strcpy(data_.parkedOrderField_.CombOffsetFlag,v[11].c_str()); - strcpy(data_.parkedOrderField_.CombHedgeFlag,v[12].c_str()); + strcpy(data_.parkedOrderField_.CombOffsetFlag, v[11].c_str()); + strcpy(data_.parkedOrderField_.CombHedgeFlag, v[12].c_str()); data_.parkedOrderField_.LimitPrice = stof(v[13]); data_.parkedOrderField_.VolumeTotalOriginal = stoi(v[14]); data_.parkedOrderField_.TimeCondition = v[15][0]; - strcpy(data_.parkedOrderField_.GTDDate,v[16].c_str()); + strcpy(data_.parkedOrderField_.GTDDate, v[16].c_str()); data_.parkedOrderField_.VolumeCondition = v[17][0]; data_.parkedOrderField_.MinVolume = stoi(v[18]); data_.parkedOrderField_.ContingentCondition = v[19][0]; @@ -365,15 +379,14 @@ void CtpParkedOrderMsg::deserialize(const string& msgin){ data_.parkedOrderField_.IsAutoSuspend = stoi(v[22]); data_.parkedOrderField_.UserForceClose = stoi(v[23]); data_.parkedOrderField_.IsSwapOrder = stoi(v[24]); - strcpy(data_.parkedOrderField_.BusinessUnit,v[25].c_str()); - strcpy(data_.parkedOrderField_.CurrencyID,v[26].c_str()); - + strcpy(data_.parkedOrderField_.BusinessUnit, v[25].c_str()); + strcpy(data_.parkedOrderField_.CurrencyID, v[26].c_str()); } -std::shared_ptr CtpParkedOrderMsg::toPOrder(){ +std::shared_ptr CtpParkedOrderMsg::toPOrder() { auto o = make_shared(); o->api_ = data_.api_; - o->account_ = data_.account_; + o->account_ = data_.account_; o->clientID_ = data_.clientID_; o->clientOrderID_ = data_.clientOrderID_; o->tag_ = data_.tag_; @@ -381,7 +394,7 @@ std::shared_ptr CtpParkedOrderMsg::toPOrder(){ o->price_ = data_.price_; o->quantity_ = data_.quantity_; o->tradedvol_ = data_.tradedvol_; - o->flag_ = data_.flag_; + o->flag_ = data_.flag_; o->serverOrderID_ = data_.serverOrderID_; o->brokerOrderID_ = data_.brokerOrderID_; o->orderNo_ = data_.orderNo_; @@ -389,17 +402,17 @@ std::shared_ptr CtpParkedOrderMsg::toPOrder(){ o->createTime_ = data_.createTime_; o->updateTime_ = data_.updateTime_; o->orderStatus_ = data_.orderStatus_; - memcpy(&o->parkedOrderField_, &data_.parkedOrderField_,sizeof(CThostFtdcParkedOrderField)); + memcpy(&o->parkedOrderField_, &data_.parkedOrderField_, sizeof(CThostFtdcParkedOrderField)); //return static_pointer_cast(o); return o; } -void OrderStatusMsg::set(std::shared_ptr po){ - //data_ = *po; +void OrderStatusMsg::set(std::shared_ptr po) { + // data_ = *po; data_.api_ = po->api_; - data_.account_ = po->account_; + data_.account_ = po->account_; data_.clientID_ = po->clientID_; data_.clientOrderID_ = po->clientOrderID_; data_.tag_ = po->tag_; @@ -408,7 +421,7 @@ void OrderStatusMsg::set(std::shared_ptr po){ data_.price_ = po->price_; data_.quantity_ = po->quantity_; data_.tradedvol_ = po->tradedvol_; - data_.flag_ = po->flag_; + data_.flag_ = po->flag_; data_.serverOrderID_ = po->serverOrderID_; data_.brokerOrderID_ = po->brokerOrderID_; data_.orderNo_ = po->orderNo_; @@ -416,57 +429,55 @@ void OrderStatusMsg::set(std::shared_ptr po){ data_.createTime_ = po->createTime_; data_.updateTime_ = po->updateTime_; data_.orderStatus_ = po->orderStatus_; - } -string OrderStatusMsg::serialize(){ - string str = destination_ +string OrderStatusMsg::serialize() { + string str = destination_ + SERIALIZATION_SEPARATOR + source_ + SERIALIZATION_SEPARATOR + to_string(msgtype_) - + SERIALIZATION_SEPARATOR + data_.api_ + + SERIALIZATION_SEPARATOR + data_.api_ + SERIALIZATION_SEPARATOR + data_.account_ - + SERIALIZATION_SEPARATOR + std::to_string(data_.clientID_) - + SERIALIZATION_SEPARATOR + std::to_string(data_.clientOrderID_) + + SERIALIZATION_SEPARATOR + std::to_string(data_.clientID_) + + SERIALIZATION_SEPARATOR + std::to_string(data_.clientOrderID_) + SERIALIZATION_SEPARATOR + data_.tag_ + SERIALIZATION_SEPARATOR + data_.fullSymbol_ + SERIALIZATION_SEPARATOR + std::to_string(data_.price_) + SERIALIZATION_SEPARATOR + std::to_string(data_.quantity_) + SERIALIZATION_SEPARATOR + std::to_string(data_.tradedvol_) - + SERIALIZATION_SEPARATOR + std::to_string(data_.flag_) + + SERIALIZATION_SEPARATOR + std::to_string(data_.flag_) + SERIALIZATION_SEPARATOR + std::to_string(data_.serverOrderID_) + SERIALIZATION_SEPARATOR + std::to_string(data_.brokerOrderID_) + SERIALIZATION_SEPARATOR + data_.orderNo_ + SERIALIZATION_SEPARATOR + data_.localNo_ + SERIALIZATION_SEPARATOR + data_.createTime_ + SERIALIZATION_SEPARATOR + data_.updateTime_ - + SERIALIZATION_SEPARATOR + std::to_string(data_.orderStatus_); + + SERIALIZATION_SEPARATOR + std::to_string(data_.orderStatus_); return str; - } -string PosMsg::serialize(){ - string str = destination_ +string PosMsg::serialize() { + string str = destination_ + SERIALIZATION_SEPARATOR + source_ + SERIALIZATION_SEPARATOR + to_string(msgtype_) + SERIALIZATION_SEPARATOR + data_.key_ + SERIALIZATION_SEPARATOR + data_.account_ + SERIALIZATION_SEPARATOR + data_.api_ + SERIALIZATION_SEPARATOR + data_.fullSymbol_ - + SERIALIZATION_SEPARATOR + data_.type_ + + SERIALIZATION_SEPARATOR + data_.type_ + SERIALIZATION_SEPARATOR + std::to_string(data_.avgPrice_) + SERIALIZATION_SEPARATOR + std::to_string(data_.size_) + SERIALIZATION_SEPARATOR + std::to_string(data_.preSize_) + SERIALIZATION_SEPARATOR + std::to_string(data_.freezedSize_) + SERIALIZATION_SEPARATOR + std::to_string(data_.closedpl_) - + SERIALIZATION_SEPARATOR + std::to_string(data_.openpl_) + + SERIALIZATION_SEPARATOR + std::to_string(data_.openpl_) + SERIALIZATION_SEPARATOR + ymdhmsf(); return str; } -void PosMsg::set(std::shared_ptr pp){ - //data_ = *pp; +void PosMsg::set(std::shared_ptr pp) { + // data_ = *pp; data_.key_ = pp->key_; data_.account_ = pp->account_; data_.api_ = pp->api_; @@ -483,8 +494,8 @@ void PosMsg::set(std::shared_ptr pp){ -void OrderActionMsg::deserialize(const string& msgin){ - vector v = stringsplit(msgin,SERIALIZATION_SEPARATOR); +void OrderActionMsg::deserialize(const string& msgin) { + vector v = stringsplit(msgin, SERIALIZATION_SEPARATOR); if (v.size() < 6) throw std::out_of_range("OutofRange in OrderAction deserialize."); destination_ = v[0]; @@ -494,74 +505,70 @@ void OrderActionMsg::deserialize(const string& msgin){ data_.serverOrderID_ = stol(v[5]); } -void SubscribeMsg::deserialize(const string& msgin){ - vector v = stringsplit(msgin,SERIALIZATION_SEPARATOR); +void SubscribeMsg::deserialize(const string& msgin) { + vector v = stringsplit(msgin, SERIALIZATION_SEPARATOR); if (v.size() < 5) throw std::out_of_range("OutofRange in Subscribe deserialize."); destination_ = v[0]; - source_ = v[1]; - symtype_ = SymbolType(stoi(v[3])); - for (int i = 4; i < v.size(); i++) + source_ = v[1]; + symtype_ = SymbolType(stoi(v[3])); + for (int32_t i = 4; i < v.size(); i++) data_.push_back(v[i]); - } -void UnSubscribeMsg::deserialize(const string& msgin){ - vector v = stringsplit(msgin,SERIALIZATION_SEPARATOR); +void UnSubscribeMsg::deserialize(const string& msgin) { + vector v = stringsplit(msgin, SERIALIZATION_SEPARATOR); if (v.size() < 5) throw std::out_of_range("OutofRange in Unsubscribe deserialize."); destination_ = v[0]; source_ = v[1]; - symtype_ = SymbolType(stoi(v[3])); - for (int i = 4; i < v.size(); i++) + symtype_ = SymbolType(stoi(v[3])); + for (int32_t i = 4; i < v.size(); i++) data_.push_back(v[i]); - } -void QryContractMsg::deserialize(const string& msgin){ - vector v = stringsplit(msgin,SERIALIZATION_SEPARATOR); +void QryContractMsg::deserialize(const string& msgin) { + vector v = stringsplit(msgin, SERIALIZATION_SEPARATOR); if (v.size() < 5) throw std::out_of_range("OutofRange in qrycontract deserialize."); destination_ = v[0]; - source_ = v[1]; - symtype_ = SymbolType(stoi(v[3])); + source_ = v[1]; + symtype_ = SymbolType(stoi(v[3])); data_ = v[4]; - } -void CancelAllMsg::deserialize(const string& msgin){ - vector v = stringsplit(msgin,SERIALIZATION_SEPARATOR); +void CancelAllMsg::deserialize(const string& msgin) { + vector v = stringsplit(msgin, SERIALIZATION_SEPARATOR); if (v.size() < 5) throw std::out_of_range("OutofRange in cancelall deserialize."); destination_ = v[0]; - source_ = v[1]; - symtype_ = SymbolType(stoi(v[3])); + source_ = v[1]; + symtype_ = SymbolType(stoi(v[3])); data_ = v[4]; } -string ErrorMsg::serialize(){ - string str = destination_ +string ErrorMsg::serialize() { + string str = destination_ + SERIALIZATION_SEPARATOR + source_ + SERIALIZATION_SEPARATOR + to_string(msgtype_) - + SERIALIZATION_SEPARATOR + data_ - + SERIALIZATION_SEPARATOR + ymdhms(); + + SERIALIZATION_SEPARATOR + data_ + + SERIALIZATION_SEPARATOR + ymdhms(); return str; } -string InfoMsg::serialize(){ - string str = destination_ +string InfoMsg::serialize() { + string str = destination_ + SERIALIZATION_SEPARATOR + source_ + SERIALIZATION_SEPARATOR + to_string(msgtype_) - + SERIALIZATION_SEPARATOR + data_ - + SERIALIZATION_SEPARATOR + ymdhms(); + + SERIALIZATION_SEPARATOR + data_ + + SERIALIZATION_SEPARATOR + ymdhms(); return str; } - -} +} // namespace StarQuant diff --git a/cppsrc/StarQuant/Common/datastruct.h b/cppsrc/StarQuant/Common/datastruct.h index f0188eaf9..9511a0c1e 100644 --- a/cppsrc/StarQuant/Common/datastruct.h +++ b/cppsrc/StarQuant/Common/datastruct.h @@ -1,6 +1,23 @@ -#ifndef __StarQuant_Common_Datastruct_H_ -#define __StarQuant_Common_Datastruct_H_ +/***************************************************************************** + * Copyright [2019] + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *****************************************************************************/ + +#ifndef CPPSRC_STARQUANT_COMMON_DATASTRUCT_H_ +#define CPPSRC_STARQUANT_COMMON_DATASTRUCT_H_ +#include +#include #include #include #include @@ -8,10 +25,6 @@ #include #include -#include -#include - - using namespace std; @@ -65,6 +78,7 @@ const std::string CurrencyTypeString[] = { "NZD", "SEK" }; + enum OrderType { OT_Market = 0, // market OT_MarketOnClose, @@ -91,35 +105,35 @@ enum OrderType { OT_Swap, OT_FAK, OT_FOK, - OT_LPT //local price conditon touched + OT_LPT // local price conditon touched }; enum OrderStatus { - OS_UNKNOWN = 0, // Unknown - OS_NewBorn = 1, // NewBorn - OS_PendingSubmit = 2, - OS_Submitted = 3, // submitted - OS_Acknowledged = 4, // acknowledged - OS_Queued =5, - OS_PartiallyFilled = 6, // PartiallyFilled - OS_Filled = 7, // Filled + OS_UNKNOWN = 0, // Unknown + OS_NewBorn = 1, // NewBorn + OS_PendingSubmit = 2, + OS_Submitted = 3, // submitted + OS_Acknowledged = 4, // acknowledged + OS_Queued = 5, + OS_PartiallyFilled = 6, // PartiallyFilled + OS_Filled = 7, // Filled OS_PendingCancel = 8 , - OS_PendingModify =9 , - OS_Canceled = 10, // Canceled + OS_PendingModify = 9 , + OS_Canceled = 10, // Canceled OS_LeftDelete = 11, OS_Suspended = 12, OS_ApiPending = 13, OS_ApiCancelled = 14, - OS_Fail =15, //指令失败 - OS_Deleted =16, - OS_Effect = 17, //已生效-询价成功 - OS_Apply = 18, //已申请-行权,弃权等申请成功 + OS_Fail = 15, // 指令失败 + OS_Deleted = 16, + OS_Effect = 17, // 已生效-询价成功 + OS_Apply = 18, // 已申请-行权,弃权等申请成功 OS_Error = 19, - OS_Trig =20, - OS_Exctrig=21 + OS_Trig = 20, + OS_Exctrig = 21 }; -enum OrderFlag { // for CTP,tap offset flag +enum OrderFlag { // for CTP,tap offset flag OF_None = -1, OF_OpenPosition = 0, OF_ClosePosition = 1, @@ -157,22 +171,22 @@ const std::string OrderStatusString[] = { }; enum class MSGQ : uint8_t { - NANOMSG = 0, ZMQ, KAFKA, WEBSOCKET + NANOMSG = 0, ZMQ, KAFKA, WEBSOCKET }; enum class MSGQ_PROTOCOL : uint8_t { - PAIR = 0, REQ, REP, PUB, SUB, PUSH,PULL + PAIR = 0, REQ, REP, PUB, SUB, PUSH, PULL }; -// -----------------------------msg type for interprocess communication----------------- +// ------msg type for interprocess communication----- enum MSG_TYPE : int32_t { - // 10* datatype same as ticktype + // 10* datatype same as ticktype // furtures MSG_TYPE_TICK = 1000, MSG_TYPE_TICK_L1 = 1001, MSG_TYPE_TICK_L5 = 1002, MSG_TYPE_TICK_L10 = 1003, MSG_TYPE_TICK_L20 = 1004, - MSG_TYPE_BAR = 1010, + MSG_TYPE_BAR = 1010, MSG_TYPE_BAR_1MIN = 1011, MSG_TYPE_BAR_5MIN = 1012, MSG_TYPE_BAR_15MIN = 1013, @@ -180,11 +194,11 @@ enum MSG_TYPE : int32_t { MSG_TYPE_BAR_1DAY = 1015, MSG_TYPE_BAR_1WEEK = 1016, MSG_TYPE_BAR_1MON = 1017, - // stock - MSG_TYPE_STOCK_TICK = 1020, + // stock + MSG_TYPE_STOCK_TICK = 1020, MSG_TYPE_STOCK_BAR = 1021, // others - MSG_TYPE_Trade =1060, + MSG_TYPE_Trade = 1060, MSG_TYPE_Bid = 1061, MSG_TYPE_Ask = 1062, MSG_TYPE_Full = 1063, @@ -200,8 +214,8 @@ enum MSG_TYPE : int32_t { MSG_TYPE_ClosePrice = 1073, MSG_TYPE_Volume = 1074, MSG_TYPE_OpenInterest = 1075, - MSG_TYPE_Hist =1076, - // 11* sys control + MSG_TYPE_Hist = 1076, + // 11* sys control MSG_TYPE_ENGINE_STATUS = 1101, MSG_TYPE_ENGINE_START = 1111, MSG_TYPE_ENGINE_STOP = 1112, @@ -215,12 +229,12 @@ enum MSG_TYPE : int32_t { MSG_TYPE_STRATEGY_INIT = 1211, MSG_TYPE_STRATEGY_INIT_ALL = 1212, MSG_TYPE_STRATEGY_START = 1213, - MSG_TYPE_STRATEGY_START_ALL = 1214, + MSG_TYPE_STRATEGY_START_ALL = 1214, MSG_TYPE_STRATEGY_STOP = 1215, - MSG_TYPE_STRATEGY_STOP_ALL = 1216, + MSG_TYPE_STRATEGY_STOP_ALL = 1216, MSG_TYPE_STRATEGY_EDIT = 1220, MSG_TYPE_STRATEGY_REMOVE = 1221, - MSG_TYPE_STRATEGY_REMOVE_DUPLICATE =1222, + MSG_TYPE_STRATEGY_REMOVE_DUPLICATE = 1222, MSG_TYPE_STRATEGY_RTN_REMOVE = 1223, MSG_TYPE_STRATEGY_GET_DATA = 1230, MSG_TYPE_STRATEGY_RTN_DATA = 1231, @@ -229,8 +243,8 @@ enum MSG_TYPE : int32_t { MSG_TYPE_STRATEGY_GET_CLASS_PARAMETERS = 1234, MSG_TYPE_STRATEGY_RTN_CLASS_PARAMETERS = 1235, MSG_TYPE_STRATEGY_GET_PARAMETERS = 1234, - MSG_TYPE_STRATEGY_RTN_PARAMETERS = 1235, - // 13* task + MSG_TYPE_STRATEGY_RTN_PARAMETERS = 1235, + // 13* task MSG_TYPE_TIMER = 1301, MSG_TYPE_TASK_START = 1310, MSG_TYPE_TASK_STOP = 1311, @@ -241,33 +255,33 @@ enum MSG_TYPE : int32_t { MSG_TYPE_SUBSCRIBE_INDEX = 2003, MSG_TYPE_SUBSCRIBE_ORDER_TRADE = 2004, MSG_TYPE_UNSUBSCRIBE = 2011, - // td request - MSG_TYPE_QRY_COMMODITY = 2021, + // td request + MSG_TYPE_QRY_COMMODITY = 2021, MSG_TYPE_QRY_CONTRACT = 2022, MSG_TYPE_QRY_POS = 2023, MSG_TYPE_QRY_ACCOUNT = 2024, MSG_TYPE_QRY_ORDER = 2025, MSG_TYPE_QRY_TRADE = 2026, MSG_TYPE_QRY_POSDETAIL = 2027, - MSG_TYPE_ORDER = 2030, //insert order + MSG_TYPE_ORDER = 2030, // insert order MSG_TYPE_ORDER_PAPER = 2031, MSG_TYPE_ORDER_CTP = 2032, MSG_TYPE_ORDER_CTP_PARKED = 2033, MSG_TYPE_ORDER_TAP = 2034, MSG_TYPE_ORDER_XTP = 2035, - MSG_TYPE_ORDER_ACTION = 2040, //cancel order + MSG_TYPE_ORDER_ACTION = 2040, // cancel order MSG_TYPE_CANCEL_ORDER = 2041, MSG_TYPE_CANCEL_ALL = 2042, MSG_TYPE_ORDER_ACTION_CTP = 2043, MSG_TYPE_ORDER_ACTION_TAP = 2044, - MSG_TYPE_ORDER_ACTION_XTP =2045, - // 25* engine callback - //call back + MSG_TYPE_ORDER_ACTION_XTP = 2045, + // 25* engine callback + // call back MSG_TYPE_RSP_POS = 2500, - MSG_TYPE_RTN_ORDER = 2510, //order status - MSG_TYPE_RTN_ORDER_CTP = 2511, - MSG_TYPE_RTN_ORDER_TAP = 2512, - MSG_TYPE_RTN_ORDER_XTP = 2513, + MSG_TYPE_RTN_ORDER = 2510, // order status + MSG_TYPE_RTN_ORDER_CTP = 2511, + MSG_TYPE_RTN_ORDER_TAP = 2512, + MSG_TYPE_RTN_ORDER_XTP = 2513, MSG_TYPE_RTN_TRADE = 2520, MSG_TYPE_RTN_TRADE_CTP = 2521, MSG_TYPE_RTN_TRADE_TAP = 2522, @@ -276,7 +290,7 @@ enum MSG_TYPE : int32_t { MSG_TYPE_RSP_CONTRACT = 2540, MSG_TYPE_RSP_COMMODITY = 2541, - // 31*: info class msg, mainly about sys + // 31*: info class msg, mainly about sys MSG_TYPE_INFO = 3100, MSG_TYPE_INFO_ENGINE_MDCONNECTED = 3101, MSG_TYPE_INFO_ENGINE_MDDISCONNECTED = 3102, @@ -284,17 +298,17 @@ enum MSG_TYPE : int32_t { MSG_TYPE_INFO_ENGINE_TDDISCONNECTED = 3104, MSG_TYPE_INFO_HEARTBEAT_WARNING = 3105, MSG_TYPE_INFO_ENGINE_STATUS = 3106, - // 34*:error class msg + // 34*:error class msg MSG_TYPE_ERROR = 3400, MSG_TYPE_ERROR_ENGINENOTCONNECTED = 3401, MSG_TYPE_ERROR_SUBSCRIBE = 3402, MSG_TYPE_ERROR_INSERTORDER = 3403, MSG_TYPE_ERROR_CANCELORDER = 3404, - MSG_TYPE_ERROR_ORGANORDER = 3405, //order is not tracted by order manager + MSG_TYPE_ERROR_ORGANORDER = 3405, // order is not tracted by order manager MSG_TYPE_ERROR_QRY_ACC = 3406, MSG_TYPE_ERROR_QRY_POS = 3407, MSG_TYPE_ERROR_QRY_CONTRACT = 3408, - MSG_TYPE_ERROR_CONNECT = 3409, //login fail + MSG_TYPE_ERROR_CONNECT = 3409, // login fail MSG_TYPE_ERROR_DISCONNECT = 3410, MSG_TYPE_ERROR_NOACCOUNT = 3411, // 40*: test class msg @@ -312,7 +326,7 @@ enum class RUN_MODE :uint8_t { }; enum class BROKERS : uint8_t { - IB = 0, CTP, GOOGLE, SINA, PAPER,TAP + IB = 0, CTP, GOOGLE, SINA, PAPER, TAP }; @@ -333,86 +347,83 @@ struct Gateway{ string privatestream; }; -//reserved for furture use +// reserved for furture use class BaseData{ - public: - virtual string serialize(){return string();} - virtual void deserialize(const string& msgin) {}; + public: + virtual string serialize() {return string();} + virtual void deserialize(const string& msgin) {} }; -//reserved for furture use +// reserved for furture use class MsgFrame{ - public: - string destination_; - string source_; - MSG_TYPE msgtype_; - std::shared_ptr dataPtr; - - MsgFrame(){} - MsgFrame(string des, string sour, MSG_TYPE mt_) - { - destination_ = des; - source_ = sour; - msgtype_ = mt_; - }; - virtual ~MsgFrame(){}; + public: + string destination_; + string source_; + MSG_TYPE msgtype_; + std::shared_ptr dataPtr; + + MsgFrame() {} + MsgFrame(string des, string sour, MSG_TYPE mt_) { + destination_ = des; + source_ = sour; + msgtype_ = mt_; + } + virtual ~MsgFrame() {} - string serialize(); - void deserialize(const string& msgin); + string serialize(); + void deserialize(const string& msgin); }; class MsgHeader{ - public: - string destination_; - string source_; - MSG_TYPE msgtype_; - - MsgHeader(){} - MsgHeader(string des, string sour, MSG_TYPE mt_) - { - destination_ = des; - source_ = sour; - msgtype_ = mt_; - }; - virtual ~MsgHeader(){}; - - virtual string serialize() { - string tmp = destination_ - + SERIALIZATION_SEPARATOR + source_ - + SERIALIZATION_SEPARATOR + to_string(msgtype_); - return tmp; - }; - virtual void deserialize(const string& msgin) {}; + public: + string destination_; + string source_; + MSG_TYPE msgtype_; + + MsgHeader() {} + MsgHeader(string des, string sour, MSG_TYPE mt_) { + destination_ = des; + source_ = sour; + msgtype_ = mt_; + } + virtual ~MsgHeader() {} + + virtual string serialize() { + string tmp = destination_ + + SERIALIZATION_SEPARATOR + source_ + + SERIALIZATION_SEPARATOR + to_string(msgtype_); + return tmp; + } + virtual void deserialize(const string& msgin) {} }; class DLL_EXPORT_IMPORT Tick{ - public: - Tick() { } - ~Tick(){ } - - string fullSymbol_; - string time_; - double price_ = 0.0; - int size_ = 0; - int depth_ = 1; - double bidPrice_[20] = {0.0}; - int bidSize_[20] = {0}; - double askPrice_[20] = {0.0}; - int askSize_[20]= {0}; - int openInterest_ = 0; - double open_ = 0.0; - double high_ = 0.0; - double low_ = 0.0; - double preClose_ = 0.0; - double upperLimitPrice_ = 0.0; - double lowerLimitPrice_ = 0.0; + public: + Tick() { } + ~Tick() { } + + string fullSymbol_; + string time_; + double price_ = 0.0; + int32_t size_ = 0; + int32_t depth_ = 1; + double bidPrice_[20] = {0.0}; + int32_t bidSize_[20] = {0}; + double askPrice_[20] = {0.0}; + int32_t askSize_[20]= {0}; + int32_t openInterest_ = 0; + double open_ = 0.0; + double high_ = 0.0; + double low_ = 0.0; + double preClose_ = 0.0; + double upperLimitPrice_ = 0.0; + double lowerLimitPrice_ = 0.0; }; class DLL_EXPORT_IMPORT TickMsg: public MsgHeader{ -public: - TickMsg() :MsgHeader(),data_() - { + public: + TickMsg():MsgHeader(), data_() { msgtype_ = MSG_TYPE::MSG_TYPE_TICK_L1; } ~TickMsg() {} @@ -424,55 +435,51 @@ class DLL_EXPORT_IMPORT TickMsg: public MsgHeader{ }; class DLL_EXPORT_IMPORT Security{ - public: - Security() {} - ~Security(){} - + public: + Security() {} + ~Security() {} string fullSymbol_; string symbol_; char securityType_; string exchange_; string contractNo_; - int multiplier_ = 0; - string localName_; // Unicode; e.g., in Chinese or French + int32_t multiplier_ = 0; + string localName_; // Unicode; e.g., in Chinese or French string currency_; double ticksize_ = 0.0; - double longMarginRatio_ = 0.0; + double longMarginRatio_ = 0.0; double shortMarginRatio_ = 0.0; char postype_ = '2'; - // Options string underlyingSymbol_; - char optionType_ ; + char optionType_; double strikePrice_ = 0.0; - char strikeMode_ ; - char strikeType_ ; + char strikeMode_; + char strikeType_; char applyType_; string expiryDate_; - }; class DLL_EXPORT_IMPORT SecurityMsg: public MsgHeader{ -public: - SecurityMsg() :MsgHeader(),data_() - { + public: + SecurityMsg() :MsgHeader(), data_() { msgtype_ = MSG_TYPE::MSG_TYPE_RSP_CONTRACT; } ~SecurityMsg() {} Security data_; - virtual string serialize() ; + virtual string serialize(); // virtual void deserialize(const string& msgin); }; class AccountInfo { -public: - AccountInfo(){} - ~AccountInfo(){} + public: + AccountInfo() {} + ~AccountInfo() {} string accountID_; - string accountType_; //INDIVIDUAL + string accountType_; // INDIVIDUAL double availableFunds_ = 0.0; double netLiquidation_ = 0.0; double equityWithLoanValue_ = 0.0; @@ -486,13 +493,11 @@ class AccountInfo { double unrealizedPnL_ = 0.0; double frozen_ = 0.0; double balance_ = 0.0; - }; class DLL_EXPORT_IMPORT AccMsg: public MsgHeader{ -public: - AccMsg() :MsgHeader(),data_() - { + public: + AccMsg() :MsgHeader(), data_() { msgtype_ = MSG_TYPE::MSG_TYPE_RSP_ACCOUNT; } ~AccMsg() {} @@ -505,34 +510,33 @@ class DLL_EXPORT_IMPORT AccMsg: public MsgHeader{ class DLL_EXPORT_IMPORT Fill { -public: + public: Fill() { } - ~Fill(){} - - long serverOrderID_ = -1; //local server id - long clientOrderID_ = -1; - long brokerOrderID_ = -1; - long tradeId_ = -1; //local id - int clientID_ = 0; // sid, get from client; 0=mannual - string orderNo_; //exchange id + ~Fill() {} + + int64_t serverOrderID_ = -1; // local server id + int64_t clientOrderID_ = -1; + int64_t brokerOrderID_ = -1; + int64_t tradeId_ = -1; // local id + int32_t clientID_ = 0; // sid, get from client; 0=mannual + string orderNo_; // exchange id string localNo_; - string tradeNo_; //exchange id + string tradeNo_; // exchange id string tradeTime_; string fullSymbol_; string account_; OrderFlag fillFlag_ = OrderFlag::OF_OpenPosition; - string api_; // IB, ctp etc - string currency_; + string api_; // IB, ctp etc + string currency_; double tradePrice_ = 0.0; - int tradeSize_ = 0; // < 0 = short, order size != trade size + int32_t tradeSize_ = 0; // < 0 = short, order size != trade size double commission_ = 0.0; }; class DLL_EXPORT_IMPORT FillMsg: public MsgHeader{ -public: - FillMsg(): MsgHeader(),data_() - { - msgtype_ = MSG_TYPE::MSG_TYPE_RTN_TRADE; + public: + FillMsg(): MsgHeader(), data_() { + msgtype_ = MSG_TYPE::MSG_TYPE_RTN_TRADE; } ~FillMsg() {} @@ -542,49 +546,50 @@ class DLL_EXPORT_IMPORT FillMsg: public MsgHeader{ // virtual void deserialize(const string& msgin); }; -extern long m_serverOrderId; // unique order id on server side defined in ordermanager.cpp. Every broker has its own id; -extern std::mutex oid_mtx; // mutex for increasing order id +extern int64_t m_serverOrderId; // unique order id on server side defined in ordermanager.cpp. +extern std::mutex oid_mtx; // mutex for increasing order id extern std::mutex orderStatus_mtx; // mutex for changing order status class DLL_EXPORT_IMPORT Order { -public: + public: Order() { } - ~Order(){} + ~Order() {} // request msg header string api_; // ctp, tap etc string account_; // account - int clientID_ = 0; // client id, get from client; 0=mannual - long clientOrderID_ = -1; // clientside id + int32_t clientID_ = 0; // client id, get from client; 0=mannual + int64_t clientOrderID_ = -1; // clientside id string tag_; // reseverd for other use -// server and callback content, for return orderstatus msg - string fullSymbol_; //unique symbol for underlying commodity: exchange + type + commodityname + commodityno - double price_ = 0.0; - int quantity_ = 0; //total original - int tradedvol_ = 0; +// server and callback content, for return orderstatus msg + // unique symbol for underlying commodity: exchange + type + commodityname + commodityno + string fullSymbol_; + double price_ = 0.0; + int32_t quantity_ = 0; // total original + int32_t tradedvol_ = 0; OrderFlag flag_ = OrderFlag::OF_OpenPosition; - long serverOrderID_ = -1; // orderref, unique sqserver id - long brokerOrderID_ = -1; // for statistical use - string orderNo_; //unique exchange order id,for ctp = exchangeID_+ orsysid - string localNo_; //unique local id ,frontid +sessionid +orderref + int64_t serverOrderID_ = -1; // orderref, unique sqserver id + int64_t brokerOrderID_ = -1; // for statistical use + string orderNo_; // unique exchange order id,for ctp = exchangeID_+ orsysid + string localNo_; // unique local id ,frontid +sessionid +orderref string createTime_; string updateTime_; OrderStatus orderStatus_ = OrderStatus::OS_UNKNOWN; - OrderType orderType_ = OrderType::OT_Default; + OrderType orderType_ = OrderType::OT_Default; }; bool isActiveOrder(const Order& o); bool isActiveOS(const OrderStatus& os); class DLL_EXPORT_IMPORT PaperOrder: public Order{ -public: - PaperOrder(){} - ~PaperOrder(){} + public: + PaperOrder() {} + ~PaperOrder() {} OrderFlag orderFlag_ = OrderFlag::OF_OpenPosition; - int orderSize_ = 0; - string fillNo_; // < 0 = short, order size != trade size - int filledSize_ = 0; + int32_t orderSize_ = 0; + string fillNo_; // < 0 = short, order size != trade size + int32_t filledSize_ = 0; double lastFilledPrice_ = 0.0; double avgFilledPrice_ = 0.0; double limitPrice_ = 0.0; @@ -600,25 +605,24 @@ class DLL_EXPORT_IMPORT PaperOrder: public Order{ class DLL_EXPORT_IMPORT CtpOrder: public Order{ -public: - CtpOrder(){} - ~CtpOrder(){} + public: + CtpOrder() {} + ~CtpOrder() {} // request msg data - struct CThostFtdcInputOrderField orderField_ ; + struct CThostFtdcInputOrderField orderField_; }; class DLL_EXPORT_IMPORT CtpParkedOrder: public Order{ -public: - CtpParkedOrder(){} - ~CtpParkedOrder(){} + public: + CtpParkedOrder() {} + ~CtpParkedOrder() {} // request msg data - struct CThostFtdcParkedOrderField parkedOrderField_ ; + struct CThostFtdcParkedOrderField parkedOrderField_; }; class DLL_EXPORT_IMPORT OrderMsg: public MsgHeader{ -public: - OrderMsg(): MsgHeader(),data_() - { + public: + OrderMsg(): MsgHeader(), data_() { msgtype_ = MSG_TYPE::MSG_TYPE_ORDER; } ~OrderMsg() {} @@ -630,9 +634,8 @@ class DLL_EXPORT_IMPORT OrderMsg: public MsgHeader{ }; class DLL_EXPORT_IMPORT PaperOrderMsg: public MsgHeader{ -public: - PaperOrderMsg(): MsgHeader(),data_() - { + public: + PaperOrderMsg(): MsgHeader(), data_() { msgtype_ = MSG_TYPE::MSG_TYPE_ORDER_PAPER; } ~PaperOrderMsg() {} @@ -645,9 +648,8 @@ class DLL_EXPORT_IMPORT PaperOrderMsg: public MsgHeader{ class DLL_EXPORT_IMPORT CtpOrderMsg: public MsgHeader{ -public: - CtpOrderMsg(): MsgHeader(),data_() - { + public: + CtpOrderMsg(): MsgHeader(), data_() { msgtype_ = MSG_TYPE::MSG_TYPE_ORDER_CTP; } ~CtpOrderMsg() {} @@ -660,9 +662,8 @@ class DLL_EXPORT_IMPORT CtpOrderMsg: public MsgHeader{ class DLL_EXPORT_IMPORT CtpParkedOrderMsg: public MsgHeader{ -public: - CtpParkedOrderMsg(): MsgHeader(),data_() - { + public: + CtpParkedOrderMsg(): MsgHeader(), data_() { msgtype_ = MSG_TYPE::MSG_TYPE_ORDER_CTP; } ~CtpParkedOrderMsg() {} @@ -675,14 +676,14 @@ class DLL_EXPORT_IMPORT CtpParkedOrderMsg: public MsgHeader{ class DLL_EXPORT_IMPORT OrderStatusMsg: public MsgHeader{ -public: - OrderStatusMsg(string des,string src): MsgHeader(des,src,MSG_TYPE::MSG_TYPE_RTN_ORDER),data_() - { + public: + OrderStatusMsg(string des, string src): + MsgHeader(des, src, MSG_TYPE::MSG_TYPE_RTN_ORDER), data_() { } ~OrderStatusMsg() {} Order data_; - + void set(std::shared_ptr po); virtual string serialize(); }; @@ -690,29 +691,28 @@ class DLL_EXPORT_IMPORT OrderStatusMsg: public MsgHeader{ class DLL_EXPORT_IMPORT Position { -public: - Position(){} - ~Position(){} + public: + Position() {} + ~Position() {} string key_ = ""; string account_ = ""; string api_ = ""; string fullSymbol_ = ""; double avgPrice_ = 0; - int size_ = 0; - int preSize_ = 0; - int freezedSize_ = 0; - double openpl_ = 0; // unrealized pnl - double closedpl_ = 0; // realized pnl + int32_t size_ = 0; + int32_t preSize_ = 0; + int32_t freezedSize_ = 0; + double openpl_ = 0; // unrealized pnl + double closedpl_ = 0; // realized pnl char type_ ='1'; // direction string posNo_ = ""; }; class DLL_EXPORT_IMPORT PosMsg: public MsgHeader{ -public: - PosMsg(string des,string src): MsgHeader(des,src,MSG_TYPE_RSP_POS),data_() - { - } + public: + PosMsg(string des, string src): + MsgHeader(des, src, MSG_TYPE_RSP_POS), data_() {} ~PosMsg() {} Position data_; @@ -724,68 +724,64 @@ class DLL_EXPORT_IMPORT PosMsg: public MsgHeader{ class DLL_EXPORT_IMPORT PositionDetail { -public: - PositionDetail(){} - ~PositionDetail(){} + public: + PositionDetail() {} + ~PositionDetail() {} string key_ = ""; string account_ = ""; string api_ = ""; string fullSymbol_ = ""; double avgPrice_ = 0; - int size_ = 0; - int preSize_ = 0; - int freezedSize_ = 0; - double openpl_ = 0; // unrealized pnl - double closedpl_ = 0; // realized pnl + int32_t size_ = 0; + int32_t preSize_ = 0; + int32_t freezedSize_ = 0; + double openpl_ = 0; // unrealized pnl + double closedpl_ = 0; // realized pnl char type_ ='1'; // direction string posNo_ = ""; string openapi_ = ""; string openOrderNo_ = ""; - int openClientID_ = -1; + int32_t openClientID_ = -1; string closeapi_ = ""; string closeOrderNo_ = ""; - int closeClientID_ = -1; + int32_t closeClientID_ = -1; }; class DLL_EXPORT_IMPORT PosDetailMsg: public MsgHeader{ -public: - PosDetailMsg(string des,string src): MsgHeader(des,src,MSG_TYPE_RSP_POS),data_() - { - } + public: + PosDetailMsg(string des, string src): + MsgHeader(des, src, MSG_TYPE_RSP_POS), data_() {} ~PosDetailMsg() {} PositionDetail data_; - virtual string serialize(){return string();}; + virtual string serialize() {return string();} // virtual void deserialize(const string& msgin); - void set(std::shared_ptr){}; + void set(std::shared_ptr) {} }; class OrderAction { -public: - OrderAction(){} - ~OrderAction(){} + public: + OrderAction() {} + ~OrderAction() {} - int clientID_ = 0; - long serverOrderID_ = -1; - long clientOrderID_ = -1; + int32_t clientID_ = 0; + int64_t serverOrderID_ = -1; + int64_t clientOrderID_ = -1; string orderNo_; }; class DLL_EXPORT_IMPORT OrderActionMsg: public MsgHeader{ -public: - OrderActionMsg() :MsgHeader(),data_() - { + public: + OrderActionMsg():MsgHeader(), data_() { msgtype_ = MSG_TYPE::MSG_TYPE_ORDER_ACTION; } - OrderActionMsg(string des,string src) :MsgHeader(des,src,MSG_TYPE_ORDER_ACTION),data_() - { - - } + OrderActionMsg(string des, string src): + MsgHeader(des, src, MSG_TYPE_ORDER_ACTION), data_() {} ~OrderActionMsg() {} OrderAction data_; @@ -798,11 +794,10 @@ class DLL_EXPORT_IMPORT OrderActionMsg: public MsgHeader{ class DLL_EXPORT_IMPORT SubscribeMsg: public MsgHeader{ -public: - SubscribeMsg(string des,string src) :MsgHeader(des,src,MSG_TYPE_SUBSCRIBE_MARKET_DATA),data_() - { - } - SubscribeMsg():MsgHeader(),data_(){ + public: + SubscribeMsg(string des, string src): + MsgHeader(des, src, MSG_TYPE_SUBSCRIBE_MARKET_DATA), data_() {} + SubscribeMsg():MsgHeader(), data_() { msgtype_ = MSG_TYPE::MSG_TYPE_SUBSCRIBE_MARKET_DATA; } ~SubscribeMsg() {} @@ -814,11 +809,10 @@ class DLL_EXPORT_IMPORT SubscribeMsg: public MsgHeader{ }; class DLL_EXPORT_IMPORT UnSubscribeMsg: public MsgHeader{ -public: - UnSubscribeMsg(string des,string src) :MsgHeader(des,src,MSG_TYPE_UNSUBSCRIBE),data_() - { - } - UnSubscribeMsg():MsgHeader(),data_(){ + public: + UnSubscribeMsg(string des, string src): + MsgHeader(des, src, MSG_TYPE_UNSUBSCRIBE), data_() {} + UnSubscribeMsg():MsgHeader(), data_() { msgtype_ = MSG_TYPE::MSG_TYPE_UNSUBSCRIBE; } ~UnSubscribeMsg() {} @@ -832,11 +826,10 @@ class DLL_EXPORT_IMPORT UnSubscribeMsg: public MsgHeader{ class DLL_EXPORT_IMPORT QryContractMsg: public MsgHeader{ -public: - QryContractMsg(string des,string src) :MsgHeader(des,src,MSG_TYPE_QRY_CONTRACT),data_() - { - } - QryContractMsg():MsgHeader(),data_(){ + public: + QryContractMsg(string des, string src): + MsgHeader(des, src, MSG_TYPE_QRY_CONTRACT), data_() {} + QryContractMsg():MsgHeader(), data_() { msgtype_ = MSG_TYPE::MSG_TYPE_QRY_CONTRACT; } ~QryContractMsg() {} @@ -849,11 +842,10 @@ class DLL_EXPORT_IMPORT QryContractMsg: public MsgHeader{ }; class DLL_EXPORT_IMPORT CancelAllMsg: public MsgHeader{ -public: - CancelAllMsg(string des,string src) :MsgHeader(des,src,MSG_TYPE_CANCEL_ALL),data_() - { - } - CancelAllMsg():MsgHeader(),data_(){ + public: + CancelAllMsg(string des, string src): + MsgHeader(des, src, MSG_TYPE_CANCEL_ALL), data_() {} + CancelAllMsg():MsgHeader(), data_() { msgtype_ = MSG_TYPE::MSG_TYPE_CANCEL_ALL; } ~CancelAllMsg() {} @@ -867,12 +859,9 @@ class DLL_EXPORT_IMPORT CancelAllMsg: public MsgHeader{ class DLL_EXPORT_IMPORT ErrorMsg: public MsgHeader{ -public: - ErrorMsg(string des,string src, MSG_TYPE mt, string em) : - MsgHeader(des,src,mt) - ,data_(em) - { - } + public: + ErrorMsg(string des, string src, MSG_TYPE mt, string em) : + MsgHeader(des, src, mt), data_(em) {} ~ErrorMsg() {} string data_; @@ -882,12 +871,9 @@ class DLL_EXPORT_IMPORT ErrorMsg: public MsgHeader{ }; class DLL_EXPORT_IMPORT InfoMsg: public MsgHeader{ -public: - InfoMsg(string des,string src, MSG_TYPE mt, string em) : - MsgHeader(des,src,mt) - ,data_(em) - { - } + public: + InfoMsg(string des, string src, MSG_TYPE mt, string em): + MsgHeader(des, src, mt), data_(em) {} ~InfoMsg() {} string data_; @@ -896,12 +882,6 @@ class DLL_EXPORT_IMPORT InfoMsg: public MsgHeader{ // virtual void deserialize(const string& msgin); }; +} // namespace StarQuant - - - - - -} - -#endif // __StarQuant_Common_Datastruct_H_ +#endif // CPPSRC_STARQUANT_COMMON_DATASTRUCT_H_ diff --git a/cppsrc/StarQuant/Common/heartbeat.cpp b/cppsrc/StarQuant/Common/heartbeat.cpp deleted file mode 100644 index 5cb224b0c..000000000 --- a/cppsrc/StarQuant/Common/heartbeat.cpp +++ /dev/null @@ -1,13 +0,0 @@ -#include -#include - -namespace StarQuant { - bool CHeartbeat::heartbeat(int interval) { - time_t tmp = time(0); - if (tmp > last_time && (tmp - last_time) % interval == 0) { - last_time = tmp + 1; - return true; - } - return true; - } -} diff --git a/cppsrc/StarQuant/Common/heartbeat.h b/cppsrc/StarQuant/Common/heartbeat.h deleted file mode 100644 index 1c140e38c..000000000 --- a/cppsrc/StarQuant/Common/heartbeat.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef _StarQuant_Common_HeartBeat_H_ -#define _StarQuant_Common_HeartBeat_H_ - -#include - -namespace StarQuant -{ - class CHeartbeat { - protected: - time_t last_time; - public: - // derived class overwrites heartbeat to tell if itself is still alive - bool heartbeat(int); - }; -} -#endif diff --git a/cppsrc/StarQuant/Common/logger.cpp b/cppsrc/StarQuant/Common/logger.cpp index 59c73aa85..7e3e46a2b 100644 --- a/cppsrc/StarQuant/Common/logger.cpp +++ b/cppsrc/StarQuant/Common/logger.cpp @@ -1,3 +1,18 @@ +/***************************************************************************** + * Copyright [2019] + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *****************************************************************************/ + #include #include #include @@ -8,15 +23,6 @@ #include #include #include -#include -#include -#include -#include -#include -#include - - - #ifdef _WIN32 #include #include @@ -24,101 +30,94 @@ #include #include #endif - +#include +#include +#include +#include #include +#include namespace fs = boost::filesystem; using std::lock_guard; using namespace log4cplus; -namespace StarQuant -{ - logger* logger::pinstance_ = nullptr; - mutex logger::instancelock_; +namespace StarQuant { +logger* logger::pinstance_ = nullptr; +mutex logger::instancelock_; - logger::logger() : logfile(nullptr) { - Initialize(); - } +logger::logger() : logfile(nullptr) { + Initialize(); +} - logger::~logger() { - fclose(logfile); - } +logger::~logger() { + fclose(logfile); +} - logger& logger::instance() { +logger& logger::instance() { + if (pinstance_ == nullptr) { + lock_guard g(instancelock_); if (pinstance_ == nullptr) { - lock_guard g(instancelock_); - if (pinstance_ == nullptr) { - pinstance_ = new logger(); - } + pinstance_ = new logger(); } - return *pinstance_; } + return *pinstance_; +} - void logger::Initialize() { - string fname; - - - - if (CConfig::instance()._mode == RUN_MODE::REPLAY_MODE) { - fname = CConfig::instance().logDir() + "/starequant-replay-" + ymd() + ".txt"; - } - else { - fname = CConfig::instance().logDir() + "/starquant-" + ymd() + ".txt"; - } +void logger::Initialize() { + string fname; - logfile = fopen(fname.c_str(), "w"); - setvbuf(logfile, nullptr, _IONBF, 0); + if (CConfig::instance()._mode == RUN_MODE::REPLAY_MODE) { + fname = CConfig::instance().logDir() + "/starequant-replay-" + ymd() + ".txt"; + } else { + fname = CConfig::instance().logDir() + "/starquant-" + ymd() + ".txt"; } - void logger::Printf2File(const char *format, ...) { - lock_guard g(instancelock_); + logfile = fopen(fname.c_str(), "w"); + setvbuf(logfile, nullptr, _IONBF, 0); +} - static char buf[1024 * 2]; - string tmp = nowMS(); - size_t sz = tmp.size(); - strcpy(buf, tmp.c_str()); - buf[sz] = ' '; - - va_list args; - va_start(args, format); - vsnprintf(buf + sz + 1, 1024 * 2 - sz - 1, format, args); - size_t buflen = strlen(buf); - fwrite(buf, sizeof(char), buflen, logfile); - va_end(args); - } +void logger::Printf2File(const char *format, ...) { + lock_guard g(instancelock_); + + static char buf[1024 * 2]; + string tmp = nowMS(); + size_t sz = tmp.size(); + strcpy(buf, tmp.c_str()); + buf[sz] = ' '; + + va_list args; + va_start(args, format); + vsnprintf(buf + sz + 1, 1024 * 2 - sz - 1, format, args); + size_t buflen = strlen(buf); + fwrite(buf, sizeof(char), buflen, logfile); + va_end(args); +} - static bool configured = false; +static bool configured = false; - bool SQLogger::doConfigure(string configureName) - { - if (!configured) - { - log4cplus::PropertyConfigurator::doConfigure(LOG4CPLUS_TEXT(configureName)); - configured = true; - return true; - } - else - { - return false; - } +bool SQLogger::doConfigure(string configureName) { + if (!configured) { + log4cplus::PropertyConfigurator::doConfigure(LOG4CPLUS_TEXT(configureName)); + configured = true; + return true; + } else { + return false; } +} - std::shared_ptr SQLogger::getLogger(string name) - { - return std::shared_ptr(new SQLogger(name)); - } +std::shared_ptr SQLogger::getLogger(string name) { + return std::shared_ptr(new SQLogger(name)); +} - SQLogger::SQLogger(string name) - { - doConfigure(CConfig::instance().logconfigfile_); - logger = log4cplus::Logger::getInstance(name); - } +SQLogger::SQLogger(string name) { + doConfigure(CConfig::instance().logconfigfile_); + logger = log4cplus::Logger::getInstance(name); +} - string SQLogger::getConfigFolder() - { - return CConfig::instance().configDir(); - } +string SQLogger::getConfigFolder() { + return CConfig::instance().configDir(); +} -} +} // namespace StarQuant diff --git a/cppsrc/StarQuant/Common/logger.h b/cppsrc/StarQuant/Common/logger.h index 35f7d7b59..fe7af0d21 100644 --- a/cppsrc/StarQuant/Common/logger.h +++ b/cppsrc/StarQuant/Common/logger.h @@ -1,15 +1,30 @@ -#ifndef _StarQuant_Common_Logger_H_ -#define _StarQuant_Common_Logger_H_ +/***************************************************************************** + * Copyright [2019] + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *****************************************************************************/ + +#ifndef CPPSRC_STARQUANT_COMMON_LOGGER_H_ +#define CPPSRC_STARQUANT_COMMON_LOGGER_H_ +#include #include #include #include -#include - #include #include - -#include +#include +#include +#include #define LOG_FATAL(sqLogger, content) LOG4CPLUS_FATAL(sqLogger->getLogger(), content) #define LOG_ERROR(sqLogger, content) LOG4CPLUS_ERROR(sqLogger->getLogger(), content) @@ -17,12 +32,10 @@ #define LOG_DEBUG(sqLogger, content) LOG4CPLUS_DEBUG(sqLogger->getLogger(), content) - using std::string; using std::mutex; -namespace StarQuant -{ +namespace StarQuant { #define PRINT_TO_FILE logger::instance().Printf2File #define PRINT_TO__CONSOLE(...) do{\ @@ -34,58 +47,52 @@ printf("%s ",ymdhmsf().c_str());printf(__VA_ARGS__);\ }while (0) - class logger { - static logger* pinstance_; - static mutex instancelock_; - - FILE* logfile = nullptr; - logger(); - ~logger(); - - public: - static logger& instance(); - - void Initialize(); +class logger { + static logger* pinstance_; + static mutex instancelock_; - void Printf2File(const char *format, ...); - }; + FILE* logfile = nullptr; + logger(); + ~logger(); - class SQLogger - { - protected: - log4cplus::Logger logger; - protected: - SQLogger() {}; - SQLogger(string name); + public: + static logger& instance(); - public: + void Initialize(); - inline log4cplus::Logger& getLogger(){ - return logger; - } - inline void fatal(const char* content){ - LOG4CPLUS_FATAL(logger, content); - } - inline void error(const char* content){ - LOG4CPLUS_ERROR(logger, content); - } - inline void info(const char* content){ - LOG4CPLUS_INFO(logger, content); - } - inline void debug(const char* content){ - LOG4CPLUS_DEBUG(logger, content); - } + void Printf2File(const char *format, ...); +}; - static string getConfigFolder(); +class SQLogger { + protected: + log4cplus::Logger logger; + SQLogger() {} + explicit SQLogger(string name); - // attention: return true if really configured. - static bool doConfigure(string configureName); + public: + inline log4cplus::Logger& getLogger() { + return logger; + } + inline void fatal(const char* content) { + LOG4CPLUS_FATAL(logger, content); + } + inline void error(const char* content) { + LOG4CPLUS_ERROR(logger, content); + } + inline void info(const char* content) { + LOG4CPLUS_INFO(logger, content); + } + inline void debug(const char* content) { + LOG4CPLUS_DEBUG(logger, content); + } - static std::shared_ptr getLogger(string name); + static string getConfigFolder(); - }; - + // attention: return true if really configured. + static bool doConfigure(string configureName); + static std::shared_ptr getLogger(string name); +}; -} -#endif +} // namespace StarQuant +#endif // CPPSRC_STARQUANT_COMMON_LOGGER_H_ diff --git a/cppsrc/StarQuant/Common/msgq.cpp b/cppsrc/StarQuant/Common/msgq.cpp index 0c3e91a81..83b4c3250 100644 --- a/cppsrc/StarQuant/Common/msgq.cpp +++ b/cppsrc/StarQuant/Common/msgq.cpp @@ -1,13 +1,23 @@ - -#include +/***************************************************************************** + * Copyright [2019] + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *****************************************************************************/ #include #include #include #include #include - -#include #include #ifdef _WIN32 #include @@ -21,319 +31,284 @@ #include // #include #endif +#include +#include namespace StarQuant { +CMsgq::CMsgq(MSGQ_PROTOCOL protocol, string url) { + protocol_ = protocol; + url_ = url; + logger = SQLogger::getLogger("SYS"); +} +IMessenger::IMessenger() { + logger = SQLogger::getLogger("SYS"); +} +CMsgqNanomsg::CMsgqNanomsg(MSGQ_PROTOCOL protocol, string url, bool binding) + : CMsgq(protocol, url) { + endpoint_ = url; + if (protocol_ == MSGQ_PROTOCOL::PAIR) { + sock_ = nn_socket(AF_SP, NN_PAIR); + assert(sock_ >= 0); + int32_t to = 100; + assert(nn_setsockopt(sock_, NN_SOL_SOCKET, NN_RCVTIMEO, &to, sizeof(to)) >= 0); - - CMsgq::CMsgq(MSGQ_PROTOCOL protocol, string url) { - protocol_ = protocol; - url_ = url; - logger = SQLogger::getLogger("SYS"); - } - - IMessenger::IMessenger(){ - logger = SQLogger::getLogger("SYS"); - } - - CMsgqNanomsg::CMsgqNanomsg(MSGQ_PROTOCOL protocol, string url, bool binding) - : CMsgq(protocol, url) { -#ifdef _DEBUG - std::printf("nanomsg protocol: %d port %s binding: %d\n", protocol, port.c_str(), binding); -#endif - endpoint_ = url; - if (protocol_ == MSGQ_PROTOCOL::PAIR) - { - sock_ = nn_socket(AF_SP, NN_PAIR); - assert(sock_ >= 0); - int to = 100; - assert(nn_setsockopt(sock_, NN_SOL_SOCKET, NN_RCVTIMEO, &to, sizeof(to)) >= 0); - - if (binding) { - eid_ = nn_bind(sock_, endpoint_.c_str()); - } - else { - eid_ = nn_connect(sock_, endpoint_.c_str()); - } - } - else if (protocol_ == MSGQ_PROTOCOL::PUB) { - sock_ = nn_socket(AF_SP, NN_PUB); - assert(sock_ >= 0); + if (binding) { eid_ = nn_bind(sock_, endpoint_.c_str()); - } - else if (protocol_ == MSGQ_PROTOCOL::SUB) { - sock_ = nn_socket(AF_SP, NN_SUB); - assert(sock_ >= 0); - int to = 100; - assert(nn_setsockopt(sock_, NN_SOL_SOCKET, NN_RCVTIMEO, &to, sizeof(to)) >= 0); - nn_setsockopt(sock_, NN_SUB, NN_SUB_SUBSCRIBE, "", 0); // subscribe to topic - eid_ = nn_connect(sock_, endpoint_.c_str()); - } - else if (protocol_ == MSGQ_PROTOCOL::PUSH){ - sock_ = nn_socket(AF_SP, NN_PUSH); - assert(sock_ >= 0); + } else { eid_ = nn_connect(sock_, endpoint_.c_str()); } - else if (protocol_ == MSGQ_PROTOCOL::PULL) - { - sock_ = nn_socket(AF_SP, NN_PULL); - assert(sock_ >= 0); - eid_ = nn_bind(sock_, endpoint_.c_str()); - } - - if (eid_ < 0 || sock_ < 0) { - LOG_ERROR(logger,"Nanomsg connect sock "<= 0); + eid_ = nn_bind(sock_, endpoint_.c_str()); + } else if (protocol_ == MSGQ_PROTOCOL::SUB) { + sock_ = nn_socket(AF_SP, NN_SUB); + assert(sock_ >= 0); + int32_t to = 100; + assert(nn_setsockopt(sock_, NN_SOL_SOCKET, NN_RCVTIMEO, &to, sizeof(to)) >= 0); + nn_setsockopt(sock_, NN_SUB, NN_SUB_SUBSCRIBE, "", 0); // subscribe to topic + eid_ = nn_connect(sock_, endpoint_.c_str()); + } else if (protocol_ == MSGQ_PROTOCOL::PUSH) { + sock_ = nn_socket(AF_SP, NN_PUSH); + assert(sock_ >= 0); + eid_ = nn_connect(sock_, endpoint_.c_str()); + } else if (protocol_ == MSGQ_PROTOCOL::PULL) { + sock_ = nn_socket(AF_SP, NN_PULL); + assert(sock_ >= 0); + eid_ = nn_bind(sock_, endpoint_.c_str()); } - std::mutex CMsgqEMessenger::sendlock_; - std::unique_ptr CMsgqEMessenger::msgq_send_; - - CMsgqEMessenger::CMsgqEMessenger(string name, string url_send) - { - name_ = name; - if (msgq_recv_ == nullptr){ - msgq_recv_ = std::make_unique(MSGQ_PROTOCOL::SUB, url_send); - } + if (eid_ < 0 || sock_ < 0) { + LOG_ERROR(logger, "Nanomsg connect sock " << endpoint_ << "error"); } - CMsgqEMessenger::CMsgqEMessenger(string url_send) - { - if (msgq_recv_ == nullptr){ - msgq_recv_ = std::make_unique(MSGQ_PROTOCOL::SUB, url_send); - } +} + +std::mutex CMsgqEMessenger::sendlock_; +std::unique_ptr CMsgqEMessenger::msgq_send_; + +CMsgqEMessenger::CMsgqEMessenger(string name, string url_send) { + name_ = name; + if (msgq_recv_ == nullptr) { + msgq_recv_ = std::make_unique(MSGQ_PROTOCOL::SUB, url_send); } +} - void CMsgqEMessenger::send(shared_ptr Msg,int mode){ - // string msgout = Msg->destination_ - // + SERIALIZATION_SEPARATOR + Msg->source_ - // + SERIALIZATION_SEPARATOR + to_string(Msg->msgtype_) - // + Msg->serialize(); - string msgout = Msg->serialize(); - lock_guard g(CMsgqEMessenger::sendlock_); - CMsgqEMessenger::msgq_send_->sendmsg(msgout,mode); +CMsgqEMessenger::CMsgqEMessenger(string url_send) { + if (msgq_recv_ == nullptr) { + msgq_recv_ = std::make_unique(MSGQ_PROTOCOL::SUB, url_send); } +} - shared_ptr CMsgqEMessenger::recv(int mode){ - string msgin = msgq_recv_->recmsg(mode); - if (msgin.empty()) - return nullptr; - // LOG_DEBUG(logger, name_ <<" recv msg:"< pheader; - switch (mtype) - { - case MSG_TYPE_ORDER: - pheader = make_shared(); - pheader->msgtype_ = MSG_TYPE_ORDER; - pheader->deserialize(msgin); - break; - case MSG_TYPE_ORDER_CTP: - pheader = make_shared(); - pheader->deserialize(msgin); - break; - case MSG_TYPE_ORDER_PAPER: - pheader = make_shared(); - pheader->deserialize(msgin); - break; - case MSG_TYPE_SUBSCRIBE_MARKET_DATA: - pheader = make_shared(des,src); - pheader->deserialize(msgin); - break; - case MSG_TYPE_UNSUBSCRIBE: - pheader = make_shared(des,src); - pheader->deserialize(msgin); - break; - case MSG_TYPE_ORDER_ACTION: - case MSG_TYPE_CANCEL_ORDER: - pheader = make_shared(); - pheader->deserialize(msgin); - break; - case MSG_TYPE_CANCEL_ALL: - pheader = make_shared(); - pheader->deserialize(msgin); - break; - case MSG_TYPE_QRY_CONTRACT: - pheader = make_shared(des,src); - pheader->deserialize(msgin); - break; - default: - pheader = make_shared(des,src,mtype); - break; - } - return pheader; +void CMsgqEMessenger::send(shared_ptr Msg, int32_t mode) { + string msgout = Msg->serialize(); + lock_guard g(CMsgqEMessenger::sendlock_); + CMsgqEMessenger::msgq_send_->sendmsg(msgout, mode); +} +shared_ptr CMsgqEMessenger::recv(int32_t mode) { + string msgin = msgq_recv_->recmsg(mode); + if (msgin.empty()) + return nullptr; + // LOG_DEBUG(logger, name_ <<" recv msg:"< pheader; + switch (mtype) { + case MSG_TYPE_ORDER: + pheader = make_shared(); + pheader->msgtype_ = MSG_TYPE_ORDER; + pheader->deserialize(msgin); + break; + case MSG_TYPE_ORDER_CTP: + pheader = make_shared(); + pheader->deserialize(msgin); + break; + case MSG_TYPE_ORDER_PAPER: + pheader = make_shared(); + pheader->deserialize(msgin); + break; + case MSG_TYPE_SUBSCRIBE_MARKET_DATA: + pheader = make_shared(des, src); + pheader->deserialize(msgin); + break; + case MSG_TYPE_UNSUBSCRIBE: + pheader = make_shared(des, src); + pheader->deserialize(msgin); + break; + case MSG_TYPE_ORDER_ACTION: + case MSG_TYPE_CANCEL_ORDER: + pheader = make_shared(); + pheader->deserialize(msgin); + break; + case MSG_TYPE_CANCEL_ALL: + pheader = make_shared(); + pheader->deserialize(msgin); + break; + case MSG_TYPE_QRY_CONTRACT: + pheader = make_shared(des, src); + pheader->deserialize(msgin); + break; + default: + pheader = make_shared(des, src, mtype); + break; } - catch (std::exception& e) { - LOG_ERROR(logger,e.what()<< " [orignial msg:" < CMsgqRMessenger::msgq_send_; - - void CMsgqRMessenger::Send(shared_ptr Msg,int mode){ - string msgout = Msg->serialize(); - lock_guard g(CMsgqRMessenger::sendlock_); - CMsgqRMessenger::msgq_send_->sendmsg(msgout,mode); - + catch (std::exception& e) { + LOG_ERROR(logger, e.what() << " [orignial msg:" << msgin << "]"); + return nullptr; } + catch(...) { + LOG_ERROR(logger, "MSGQ cannot deserialize msg:" << msgin); + return nullptr; + } +} - CMsgqRMessenger::CMsgqRMessenger(string url_recv){ - msgq_recv_ = std::make_unique(MSGQ_PROTOCOL::PULL, url_recv); - // msgq_send_ = std::make_unique(MSGQ_PROTOCOL::PUB, url_send); - } +std::mutex CMsgqRMessenger::sendlock_; +std::unique_ptr CMsgqRMessenger::msgq_send_; - void CMsgqRMessenger::send(shared_ptr Msg,int mode){ - // string msgout = Msg->destination_ - // + SERIALIZATION_SEPARATOR + Msg->source_ - // + SERIALIZATION_SEPARATOR + to_string(Msg->msgtype_) - // + Msg->serialize(); - string msgout = Msg->serialize(); - lock_guard g(CMsgqRMessenger::sendlock_); - CMsgqRMessenger::msgq_send_->sendmsg(msgout,mode); +void CMsgqRMessenger::Send(shared_ptr Msg, int32_t mode) { + string msgout = Msg->serialize(); + lock_guard g(CMsgqRMessenger::sendlock_); + CMsgqRMessenger::msgq_send_->sendmsg(msgout, mode); +} - } +CMsgqRMessenger::CMsgqRMessenger(string url_recv) { + msgq_recv_ = std::make_unique(MSGQ_PROTOCOL::PULL, url_recv); + // msgq_send_ = std::make_unique(MSGQ_PROTOCOL::PUB, url_send); +} +void CMsgqRMessenger::send(shared_ptr Msg, int32_t mode) { + string msgout = Msg->serialize(); + lock_guard g(CMsgqRMessenger::sendlock_); + CMsgqRMessenger::msgq_send_->sendmsg(msgout, mode); +} - void CMsgqRMessenger::relay(){ - string msgpull = msgq_recv_->recmsg(0); - if (msgpull.empty()) - return; - // cout<<"recv msg at"< g(CMsgqEMessenger::sendlock_); - CMsgqEMessenger::msgq_send_->sendmsg(msgpull); //将消息发回,让策略进程收到 - } - else - { - lock_guard g(CMsgqRMessenger::sendlock_); - CMsgqRMessenger::msgq_send_->sendmsg(msgpull); //转发消息到各个engine - } - } +void CMsgqRMessenger::relay() { + string msgpull = msgq_recv_->recmsg(0); + if (msgpull.empty()) + return; + // cout<<"recv msg at"< g(CMsgqEMessenger::sendlock_); + // 将消息发回,让策略进程收到 + CMsgqEMessenger::msgq_send_->sendmsg(msgpull); + } else { + lock_guard g(CMsgqRMessenger::sendlock_); + // 转发消息到各个engine + CMsgqRMessenger::msgq_send_->sendmsg(msgpull); + } +} - CMsgqNanomsg::~CMsgqNanomsg() - { - nn_shutdown(sock_, eid_); - nn_close(sock_); - } - void CMsgqNanomsg::sendmsg(const string& msg,int dontwait) { - // if (!msg.empty()) - int bytes = nn_send(sock_, msg.c_str(), msg.size() + 1, dontwait); // TODO: size or size+1 +CMsgqNanomsg::~CMsgqNanomsg() { + nn_shutdown(sock_, eid_); + nn_close(sock_); +} - if (bytes != msg.size()+1){ - LOG_ERROR(logger,"Nanomsg "< 0 && buf != nullptr) { - string msg(buf, bytes); - buf != nullptr && nn_freemsg(buf); - return msg; - } - else { - return string(); - } - } +string CMsgqNanomsg::recmsg(int32_t dontwait) { + char* buf = nullptr; + int32_t bytes = nn_recv(sock_, &buf, NN_MSG, dontwait); - CMsgqZmq::CMsgqZmq(MSGQ_PROTOCOL protocol, string port, bool binding) - : CMsgq(protocol, port) { -#ifdef _DEBUG - std::printf("zmq protocol: %d port %s binding: %d\n", protocol, port.c_str(), binding); -#endif - // if (protocol_ == MSGQ_PROTOCOL::PAIR) - // { - // context_ = zmq_ctx_new(); - // socket_ = zmq_socket(context_, ZMQ_PAIR); - - // if (binding) { - // endpoint_ = "tcp://*:" + port; - // rc_ = zmq_bind(socket_, endpoint_.c_str()); - // } - // else { - // endpoint_ = "tcp://localhost:" + port; - // rc_ = zmq_connect(socket_, endpoint_.c_str()); - // } - // } - // else if (protocol_ == MSGQ_PROTOCOL::PUB) { - // context_ = zmq_ctx_new(); - // socket_ = zmq_socket(context_, ZMQ_PUB); - - // endpoint_ = "tcp://*:" + port; - // rc_ = zmq_bind(socket_, endpoint_.c_str()); - // } - // else if (protocol_ == MSGQ_PROTOCOL::SUB) { - // context_ = zmq_ctx_new(); - // socket_ = zmq_socket(context_, ZMQ_SUB); - - // endpoint_ = "tcp://localhost:" + port; - // rc_ = zmq_connect(socket_, endpoint_.c_str()); - // } + if (bytes > 0 && buf != nullptr) { + string msg(buf, bytes); + buf != nullptr && nn_freemsg(buf); + return msg; + } else { + return string(); } +} - CMsgqZmq::~CMsgqZmq() - { - // rc_ = zmq_unbind(socket_, endpoint_.c_str()); - // zmq_close(socket_); - // zmq_ctx_shutdown(context_); - // zmq_term(context_); - // zmq_ctx_destroy(context_); - } +CMsgqZmq::CMsgqZmq(MSGQ_PROTOCOL protocol, string port, bool binding) + : CMsgq(protocol, port) { + // if (protocol_ == MSGQ_PROTOCOL::PAIR) + // { + // context_ = zmq_ctx_new(); + // socket_ = zmq_socket(context_, ZMQ_PAIR); + + // if (binding) { + // endpoint_ = "tcp://*:" + port; + // rc_ = zmq_bind(socket_, endpoint_.c_str()); + // } + // else { + // endpoint_ = "tcp://localhost:" + port; + // rc_ = zmq_connect(socket_, endpoint_.c_str()); + // } + // } + // else if (protocol_ == MSGQ_PROTOCOL::PUB) { + // context_ = zmq_ctx_new(); + // socket_ = zmq_socket(context_, ZMQ_PUB); + + // endpoint_ = "tcp://*:" + port; + // rc_ = zmq_bind(socket_, endpoint_.c_str()); + // } + // else if (protocol_ == MSGQ_PROTOCOL::SUB) { + // context_ = zmq_ctx_new(); + // socket_ = zmq_socket(context_, ZMQ_SUB); + + // endpoint_ = "tcp://localhost:" + port; + // rc_ = zmq_connect(socket_, endpoint_.c_str()); + // } +} - // zmq doesn't have global nn_term(), has to be set non-blocking, ZMQ_DONTWAIT - void CMsgqZmq::sendmsg(const string& msg,int dontwait) { - // int bytes = zmq_send(socket_, msg.c_str(), msg.size() + 1, 0); // TODO: size or size+1 - } +CMsgqZmq::~CMsgqZmq() { + // rc_ = zmq_unbind(socket_, endpoint_.c_str()); + // zmq_close(socket_); + // zmq_ctx_shutdown(context_); + // zmq_term(context_); + // zmq_ctx_destroy(context_); +} - void CMsgqZmq::sendmsg(const char* msg,int dontwait) { - // int bytes = zmq_send(socket_, msg, strlen(msg)+1, 0); - } +// zmq doesn't have global nn_term(), has to be set non-blocking, ZMQ_DONTWAIT +void CMsgqZmq::sendmsg(const string& msg, int32_t dontwait) { + // int32_t bytes = zmq_send(socket_, msg.c_str(), msg.size() + 1, 0); +} - string CMsgqZmq::recmsg(int blockingflags) { - // int bytes = zmq_recv(socket_, buf_, 1024, blockingflags); //ZMQ_NOBLOCK - - // if (bytes > 0) { - // buf_[bytes] = '\0'; - // string msg(buf_); - // return msg; - // } - // else { - // return string(); - // } - } +void CMsgqZmq::sendmsg(const char* msg, int32_t dontwait) { + // int32_t bytes = zmq_send(socket_, msg, strlen(msg)+1, 0); +} - mutex MsgCenter::msglock_; - std::unique_ptr MsgCenter:: msgq_pub_; +string CMsgqZmq::recmsg(int32_t blockingflags) { + // int32_t bytes = zmq_recv(socket_, buf_, 1024, blockingflags);//ZMQ_NOBLOCK + + // if (bytes > 0) { + // buf_[bytes] = '\0'; + // string msg(buf_); + // return msg; + // } + // else { + // return string(); + // } } + +mutex MsgCenter::msglock_; +std::unique_ptr MsgCenter:: msgq_pub_; +} // namespace StarQuant diff --git a/cppsrc/StarQuant/Common/msgq.h b/cppsrc/StarQuant/Common/msgq.h index 4751f55e9..8db286746 100644 --- a/cppsrc/StarQuant/Common/msgq.h +++ b/cppsrc/StarQuant/Common/msgq.h @@ -1,9 +1,22 @@ -#ifndef _StarQuant_Common_Msgq_H_ -#define _StarQuant_Common_Msgq_H_ +/***************************************************************************** + * Copyright [2019] + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *****************************************************************************/ + +#ifndef CPPSRC_STARQUANT_COMMON_MSGQ_H_ +#define CPPSRC_STARQUANT_COMMON_MSGQ_H_ + -#include -#include -#include #include #include #ifdef _WIN32 @@ -13,111 +26,114 @@ #include #include #endif - -//#include +#include +#include +#include +// #include using namespace std; namespace StarQuant { - class IMessenger{ - protected: - std::shared_ptr logger; - public: - string name_; - IMessenger(); - virtual ~IMessenger(){}; - - virtual void send(std::shared_ptr pmsg,int mode = 0) = 0; - virtual std::shared_ptr recv(int mode = 0) =0; - virtual void relay() = 0; - }; - - - class CMsgq { - protected: - MSGQ_PROTOCOL protocol_; - string url_; - std::shared_ptr logger; - public: - CMsgq(MSGQ_PROTOCOL protocol, string url); - virtual ~CMsgq(){}; - virtual void sendmsg(const string& str,int dontwait = 1) = 0; - virtual void sendmsg(const char* str,int dontwait = 1) = 0; - virtual string recmsg(int blockingflags = 1) = 0; - }; - - class CMsgqNanomsg : public CMsgq { - private: - int sock_ = -1; - int eid_ = 0; - string endpoint_; - public: - CMsgqNanomsg(MSGQ_PROTOCOL protocol, string url, bool binding=true); - ~CMsgqNanomsg(); - - virtual void sendmsg(const string& str,int dontwait = 1); - virtual void sendmsg(const char* str,int dontwait = 1); - virtual string recmsg(int blockingflags = 1); - }; - - class CMsgqZmq : public CMsgq { - private: - void* context_; - void* socket_; - string endpoint_; - int rc_; - char buf_[256]; - public: - CMsgqZmq(MSGQ_PROTOCOL protocol, string url, bool binding = true); - ~CMsgqZmq(); - - virtual void sendmsg(const string& str,int dontwait = 1); - virtual void sendmsg(const char* str,int dontwait = 1); - virtual string recmsg(int blockingflags = 1); - }; - class MsgCenter{ - public: - static mutex msglock_; - static std::unique_ptr msgq_pub_; - MsgCenter(); - ~MsgCenter(); - - }; - - // CMsgq Engine messenger, for md and td engine use, send and recv msg using different port - class CMsgqEMessenger : public IMessenger { - private: - std::unique_ptr msgq_recv_; - public: - static mutex sendlock_; - static std::unique_ptr msgq_send_; - - CMsgqEMessenger(string url_recv); - CMsgqEMessenger(string name, string url_recv); - virtual ~CMsgqEMessenger(){}; - virtual void send(shared_ptr pmsg,int mode = 0) ; - virtual shared_ptr recv(int mode = 0) ; - virtual void relay(){}; - }; -// nanomsg relay messenger, for trading engine use - class CMsgqRMessenger : public IMessenger { - private: - std::unique_ptr msgq_recv_; - - public: - CMsgqRMessenger(string url_recv); - virtual ~CMsgqRMessenger(){}; - - static mutex sendlock_; - static std::unique_ptr msgq_send_; - static void Send(std::shared_ptr pmsg,int mode = 0); - - - virtual void send(std::shared_ptr pmsg,int mode = 0); - virtual std::shared_ptr recv(int mode = 0) {return nullptr;}; - virtual void relay() ; - - }; -} - -#endif // _StarQuant_Common_Msgq_H_ +class IMessenger{ + protected: + std::shared_ptr logger; + public: + string name_; + IMessenger(); + virtual ~IMessenger() {} + + virtual void send(std::shared_ptr pmsg, int32_t mode = 0) = 0; + virtual std::shared_ptr recv(int32_t mode = 0) = 0; + virtual void relay() = 0; +}; + + +class CMsgq { + protected: + MSGQ_PROTOCOL protocol_; + string url_; + std::shared_ptr logger; + public: + CMsgq(MSGQ_PROTOCOL protocol, string url); + virtual ~CMsgq() {} + virtual void sendmsg(const string& str, int32_t dontwait = 1) = 0; + virtual void sendmsg(const char* str, int32_t dontwait = 1) = 0; + virtual string recmsg(int32_t blockingflags = 1) = 0; +}; + +class CMsgqNanomsg : public CMsgq { + private: + int32_t sock_ = -1; + int32_t eid_ = 0; + string endpoint_; + public: + CMsgqNanomsg(MSGQ_PROTOCOL protocol, string url, bool binding = true); + ~CMsgqNanomsg(); + + virtual void sendmsg(const string& str, int32_t dontwait = 1); + virtual void sendmsg(const char* str, int32_t dontwait = 1); + virtual string recmsg(int32_t blockingflags = 1); +}; + +class CMsgqZmq : public CMsgq { + private: + void* context_; + void* socket_; + string endpoint_; + int32_t rc_; + char buf_[256]; + public: + CMsgqZmq(MSGQ_PROTOCOL protocol, string url, bool binding = true); + ~CMsgqZmq(); + + virtual void sendmsg(const string& str, int32_t dontwait = 1); + virtual void sendmsg(const char* str, int32_t dontwait = 1); + virtual string recmsg(int32_t blockingflags = 1); +}; +class MsgCenter{ + public: + static mutex msglock_; + static std::unique_ptr msgq_pub_; + MsgCenter(); + ~MsgCenter(); +}; + +// CMsgq Engine messenger +// for md and td engine use, send and recv msg using different port +class CMsgqEMessenger : public IMessenger { + private: + std::unique_ptr msgq_recv_; + public: + static mutex sendlock_; + static std::unique_ptr msgq_send_; + + explicit CMsgqEMessenger(string url_recv); + CMsgqEMessenger(string name, string url_recv); + virtual ~CMsgqEMessenger() {} + + virtual void send(shared_ptr pmsg, int32_t mode = 0); + virtual shared_ptr recv(int32_t mode = 0); + virtual void relay() {} +}; +// nanomsg relay messenger, for trading engine use +class CMsgqRMessenger : public IMessenger { + private: + std::unique_ptr msgq_recv_; + + public: + explicit CMsgqRMessenger(string url_recv); + virtual ~CMsgqRMessenger() {} + + static mutex sendlock_; + static std::unique_ptr msgq_send_; + static void Send(std::shared_ptr pmsg, int32_t mode = 0); + + + virtual void send(std::shared_ptr pmsg, int32_t mode = 0); + virtual std::shared_ptr recv(int32_t mode = 0) {return nullptr;} + virtual void relay(); +}; + +} // namespace StarQuant + +#endif // CPPSRC_STARQUANT_COMMON_MSGQ_H_ diff --git a/cppsrc/StarQuant/Common/util.cpp b/cppsrc/StarQuant/Common/util.cpp index 9ea11eef3..1c760ca08 100644 --- a/cppsrc/StarQuant/Common/util.cpp +++ b/cppsrc/StarQuant/Common/util.cpp @@ -1,77 +1,82 @@ -#include -#include +/***************************************************************************** + * Copyright [2019] + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *****************************************************************************/ + +#include #include #include #include #include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include #include #include #include #include -#include -#include -#include -#include using namespace boost::posix_time; using namespace boost::local_time; using namespace std; namespace StarQuant { +// signal handler +Except_frame g_except_stack = Except_frame(); +void errorDump() { + void* array[30]; + size_t size; + char** strings; + size_t i; -//signal handler - - - -#include -#include -#include -#include - - Except_frame g_except_stack = Except_frame(); - void errorDump() - { - void* array[30]; - size_t size; - char** strings; - size_t i; - - size = backtrace(array, 30); - strings = backtrace_symbols(array, size); - if (NULL == strings) - { - perror("backtrace_symbols"); - } - - printf("Obtained %zd stack frames.\n", size); + size = backtrace(array, 30); + strings = backtrace_symbols(array, size); + if (NULL == strings) { + perror("backtrace_symbols"); + } - for(i = 0 ; i < size; i++) - { - std::cout< gShutdown{ false }; + free(strings); + strings = NULL; +} +void recvSignal(int32_t sig) { + printf("StarQuant received signal %d !\n", sig); + errorDump(); + siglongjmp(g_except_stack.env, 1); +} + +// console related +std::atomic gShutdown{ false }; #if defined(_WIN64) || defined(_WIN32) #define WIN32_LEAN_AND_MEAN #include -#include BOOL CtrlHandler(DWORD fdwCtrlType) { switch (fdwCtrlType) { case CTRL_C_EVENT: @@ -101,100 +106,97 @@ namespace StarQuant { } #elif defined(__linux__) -#include - void ConsoleControlHandler(int sig) { - + void ConsoleControlHandler(int32_t sig) { gShutdown = true; PRINT_SHUTDOWN_MESSAGE; - //throw runtime_error("crl c"); + // throw runtime_error("crl c"); } -// std::atomic* setconsolecontrolhandler(void) { -// signal(SIGINT, ConsoleControlHandler); -// signal(SIGPWR, ConsoleControlHandler); -// return &gShutdown; -// } +// std::atomic* setconsolecontrolhandler(void) { +// signal(SIGINT, ConsoleControlHandler); +// signal(SIGPWR, ConsoleControlHandler); +// return &gShutdown; +// } #endif +// int32_t check_gshutdown(bool force) { +// atomic_bool* g = setconsolecontrolhandler(); +// while (!*g) { +// msleep(1 * 1000); +// } +// // ctrl-c +// if (force) { +// throw runtime_error("Throw an exception to trigger shutdown"); +// } +// return 0; +// } +// string related -// string related - - string extractExchangeID(const string& fullsym) { - string ex; - stringstream ss(fullsym); - getline(ss, ex, ' '); - return ex; - } +string extractExchangeID(const string& fullsym) { + string ex; + stringstream ss(fullsym); + getline(ss, ex, ' '); + return ex; +} - vector stringsplit(const string &s, char delim) { - vector elems; +vector stringsplit(const string &s, char delim) { + vector elems; - stringstream ss(s); - string item; - while (getline(ss, item, delim)) { - elems.push_back(item); - } - string& last = elems.back(); - if (last.back() == '\0') - last.pop_back(); - return elems; + stringstream ss(s); + string item; + while (getline(ss, item, delim)) { + elems.push_back(item); } + string& last = elems.back(); + if (last.back() == '\0') + last.pop_back(); + return elems; +} - bool startwith(const string& x, const string& y) { - return x.find(y) == 0; - } +bool startwith(const string& x, const string& y) { + return x.find(y) == 0; +} - bool endwith(const std::string &str, const std::string &suffix) { - return str.size() >= suffix.size() && - str.compare(str.size() - suffix.size(), suffix.size(), suffix) == 0; - } +bool endwith(const std::string &str, const std::string &suffix) { + return str.size() >= suffix.size() && + str.compare(str.size() - suffix.size(), suffix.size(), suffix) == 0; +} - // int check_gshutdown(bool force) { - // atomic_bool* g = setconsolecontrolhandler(); - // while (!*g) { - // msleep(1 * 1000); - // } - // // ctrl-c - // if (force) { - // throw runtime_error("Throw an exception to trigger shutdown"); - // } - // return 0; - // } - - string UTF8ToGBK(const std::string & strUTF8) { - string stroutGBK = ""; - stroutGBK = boost::locale::conv::between( strUTF8,"GB18030","UTF-8" ); - return stroutGBK; - } - string GBKToUTF8(const std::string & strGBK) { - string strOutUTF8 = ""; - strOutUTF8 = boost::locale::conv::between( strGBK, "UTF-8", "GB18030" ); - return strOutUTF8; - } + +string UTF8ToGBK(const std::string & strUTF8) { + string stroutGBK = ""; + stroutGBK = boost::locale::conv::between(strUTF8, "GB18030", "UTF-8"); + return stroutGBK; +} + +string GBKToUTF8(const std::string & strGBK) { + string strOutUTF8 = ""; + strOutUTF8 = boost::locale::conv::between(strGBK, "UTF-8", "GB18030"); + return strOutUTF8; +} // numerical - double rounded(double x, int n){ - char out[64]; - double xrounded; - sprintf(out, "%.*f", n, x); - xrounded = strtod(out, 0); - return xrounded; - } +double rounded(double x, int32_t n) { + char out[64]; + double xrounded; + sprintf(out, "%.*f", n, x); + xrounded = strtod(out, 0); + return xrounded; +} -// time related - uint64_t getMicroTime() - { - uint64_t t = 0; +// time related +uint64_t getMicroTime() { + uint64_t t = 0; #if defined(_WIN32) || defined(_WIN64) FILETIME tm; @@ -215,8 +217,7 @@ namespace StarQuant { #elif defined(__MACH__) && defined(__APPLE__) /* OSX. ----------------------------------------------------- */ static double timeConvert = 0.0; - if (timeConvert == 0.0) - { + if (timeConvert == 0.0) { mach_timebase_info_data_t timeBase; (void)mach_timebase_info(&timeBase); timeConvert = (double)timeBase.numer / @@ -246,7 +247,7 @@ namespace StarQuant { /* AIX, BSD, HP-UX, Linux, POSIX. ------------------- */ const clockid_t id = CLOCK_REALTIME; #else - const clockid_t id = (clockid_t)-1; /* Unknown. */ + const clockid_t id = (clockid_t)-1; /* Unknown. */ #endif /* CLOCK_* */ if (id != (clockid_t)-1 && clock_gettime(id, &ts) != -1) { t = ts.tv_sec*__NANOO_MULTIPLE__ + ts.tv_nsec; @@ -262,127 +263,129 @@ namespace StarQuant { t = __MICRO_MULTIPLE__*tm.tv_sec + tm.tv_usec; return t; #else - return 0; /* Failed. */ + return 0; /* Failed. */ #endif +} + +int32_t getMilliSeconds() { + struct timeval tm; + int32_t milli = 0; + gettimeofday(&tm, nullptr); + milli = int32_t(tm.tv_usec / 1000); + return milli; +} + +string ymd() { + char buf[128] = { 0 }; + const size_t sz = sizeof("0000-00-00"); + { + time_t timer; + struct tm tm_info; + time(&timer); + localtime_r(&timer, &tm_info); + strftime(buf, sz, DATE_FORMAT, &tm_info); + } + return string(buf); +} +string ymdcompact() { + char buf[128] = { 0 }; + const size_t sz = sizeof("00000000"); + { + time_t timer; + struct tm tm_info; + time(&timer); + localtime_r(&timer, &tm_info); + strftime(buf, sz, DATE_FORMAT_COMPACT, &tm_info); + } + return string(buf); +} + +string ymdhms() { + char buf[128] = { 0 }; + const size_t sz = sizeof("0000-00-00 00-00-00"); + { + time_t timer; + time(&timer); + struct tm tm_info; + localtime_r(&timer, &tm_info); + strftime(buf, sz, DATE_TIME_FORMAT, &tm_info); } + return string(buf); +} - int getMilliSeconds(){ - struct timeval tm; - int milli = 0; - gettimeofday(&tm, nullptr); - milli = int( tm.tv_usec / 1000); - return milli; - } +string ymdhmsf() { + std::chrono::system_clock::time_point now = std::chrono::system_clock::now(); + std::chrono::system_clock::duration tp = now.time_since_epoch(); + tp -= std::chrono::duration_cast(tp); + time_t tt = std::chrono::system_clock::to_time_t(now); - string ymd() { - char buf[128] = { 0 }; - const size_t sz = sizeof("0000-00-00"); - { - time_t timer; - struct tm* tm_info; - time(&timer); - tm_info = localtime(&timer); - strftime(buf, sz, DATE_FORMAT, tm_info); - } - return string(buf); - } - string ymdcompact(){ - char buf[128] = { 0 }; - const size_t sz = sizeof("00000000"); - { - time_t timer; - struct tm* tm_info; - time(&timer); - tm_info = localtime(&timer); - strftime(buf, sz, DATE_FORMAT_COMPACT, tm_info); - } - return string(buf); - } + // tm t = *gmtime(&tt); + struct tm t; + localtime_r(&tt, &t); - string ymdhms() { - char buf[128] = { 0 }; - const size_t sz = sizeof("0000-00-00 00-00-00"); - { - time_t timer; - time(&timer); - struct tm* tm_info = localtime(&timer); - strftime(buf, sz, DATE_TIME_FORMAT, tm_info); - } - return string(buf); - } + char buf[64]; + std::sprintf(buf, "%04u-%02u-%02u %02u:%02u:%02u.%03u", t.tm_year + 1900, + t.tm_mon + 1, t.tm_mday, t.tm_hour, t.tm_min, t.tm_sec, + static_cast(tp / std::chrono::milliseconds(1))); - string ymdhmsf() { - std::chrono::system_clock::time_point now = std::chrono::system_clock::now(); - std::chrono::system_clock::duration tp = now.time_since_epoch(); - tp -= std::chrono::duration_cast(tp); - time_t tt = std::chrono::system_clock::to_time_t(now); - - // tm t = *gmtime(&tt); - tm t = *localtime(&tt); - - char buf[64]; - std::sprintf(buf, "%04u-%02u-%02u %02u:%02u:%02u.%03u", t.tm_year + 1900, - t.tm_mon + 1, t.tm_mday, t.tm_hour, t.tm_min, t.tm_sec, - static_cast(tp / std::chrono::milliseconds(1))); - - return string(buf); - } - string ymdhmsf6() { - std::chrono::system_clock::time_point now = std::chrono::system_clock::now(); - std::chrono::system_clock::duration tp = now.time_since_epoch(); - tp -= std::chrono::duration_cast(tp); - time_t tt = std::chrono::system_clock::to_time_t(now); - - // tm t = *gmtime(&tt); - tm t = *localtime(&tt); - - char buf[64]; - std::sprintf(buf, "%04u-%02u-%02u %02u:%02u:%02u.%06u", t.tm_year + 1900, - t.tm_mon + 1, t.tm_mday, t.tm_hour, t.tm_min, t.tm_sec, - static_cast(tp / std::chrono::microseconds(1))); - - return string(buf); - } + return string(buf); +} +string ymdhmsf6() { + std::chrono::system_clock::time_point now = std::chrono::system_clock::now(); + std::chrono::system_clock::duration tp = now.time_since_epoch(); + tp -= std::chrono::duration_cast(tp); + time_t tt = std::chrono::system_clock::to_time_t(now); + struct tm t; + localtime_r(&tt, &t); + char buf[64]; + std::sprintf(buf, "%04u-%02u-%02u %02u:%02u:%02u.%06u", t.tm_year + 1900, + t.tm_mon + 1, t.tm_mday, t.tm_hour, t.tm_min, t.tm_sec, + static_cast(tp / std::chrono::microseconds(1))); + return string(buf); +} - string hmsf() { - std::chrono::system_clock::time_point now = std::chrono::system_clock::now(); - std::chrono::system_clock::duration tp = now.time_since_epoch(); - tp -= std::chrono::duration_cast(tp); - time_t tt = std::chrono::system_clock::to_time_t(now); - // tm t = *gmtime(&tt); // utc - tm t = *localtime(&tt); - char buf[64]; - std::sprintf(buf, "%02u:%02u:%02u.%03u", t.tm_hour, t.tm_min, t.tm_sec, - static_cast(tp / std::chrono::milliseconds(1))); - return string(buf); - } +string hmsf() { + std::chrono::system_clock::time_point now = std::chrono::system_clock::now(); + std::chrono::system_clock::duration tp = now.time_since_epoch(); + tp -= std::chrono::duration_cast(tp); + time_t tt = std::chrono::system_clock::to_time_t(now); - int hmsf2inttime(string hmsf) { - return std::stoi(hmsf.substr(0, 2)) * 10000 + std::stoi(hmsf.substr(3, 2)) * 100 + std::stoi(hmsf.substr(6, 2)); - } + struct tm t; + localtime_r(&tt, &t); - void msleep(uint64_t _ms) { - if (_ms == 0) { return; } - this_thread::sleep_for(chrono::milliseconds(_ms)); - } + char buf[64]; + std::sprintf(buf, "%02u:%02u:%02u.%03u", t.tm_hour, t.tm_min, t.tm_sec, + static_cast(tp / std::chrono::milliseconds(1))); + + return string(buf); +} + +int32_t hmsf2inttime(string hmsf) { + return std::stoi(hmsf.substr(0, 2)) * 10000 + std::stoi(hmsf.substr(3, 2)) * 100 + std::stoi(hmsf.substr(6, 2)); +} + +void msleep(uint64_t _ms) { + if (_ms == 0) { return; } + this_thread::sleep_for(chrono::milliseconds(_ms)); +} string nowMS() { char buf[128] = {}; #ifdef __linux__ - struct timespec ts = { 0,0 }; + struct timespec ts = { 0, 0 }; struct tm tm = {}; char timbuf[64] = {}; clock_gettime(CLOCK_REALTIME, &ts); time_t tim = ts.tv_sec; localtime_r(&tim, &tm); strftime(timbuf, sizeof(timbuf), "%F %T", &tm); - snprintf(buf, 128, "%s.%03d", timbuf, (int)(ts.tv_nsec / 1000000)); + snprintf(buf, 128, "%s.%03d", timbuf, (int32_t)(ts.tv_nsec / 1000000)); #else SYSTEMTIME SystemTime; GetLocalTime(&SystemTime); @@ -396,128 +399,123 @@ namespace StarQuant { time_t ptime2time(ptime t) { static ptime epoch(boost::gregorian::date(1970, 1, 1)); time_duration::sec_type x = (t - epoch).total_seconds() - 3600 * NYC_TZ_OFFSET; - //hours(4).total_seconds() = 3600 * 4 + // hours(4).total_seconds() = 3600 * 4 // ... check overflow here ... return time_t(x); } string ptime2str(const ptime& pt) { time_zone_ptr tz_cet(new boost::local_time::posix_time_zone(NYC_TZ_STR)); - local_date_time dt_with_zone(pt, tz_cet); //glocale::instance()._ny_tzone); + local_date_time dt_with_zone(pt, tz_cet); // glocale::instance()._ny_tzone); #if 1 tm _t = to_tm(dt_with_zone); char buf[32] = { 0 }; strftime(buf, 32, DATE_TIME_FORMAT, &_t); return buf; #else - //using stringstream only for logging +// using stringstream only for logging stringstream strm; strm.imbue(*glocale::instance()._s_loc); strm << dt_with_zone; - //strm << pt; + // strm << pt; return strm.str(); #endif } - //http://stackoverflow.com/questions/4461586/how-do-i-convert-boostposix-timeptime-to-time-t - time_t str2time_t(const string& s) { - ptime pt(time_from_string(s)); - return ptime2time(pt); - } - - string time_t2str(time_t tt) { - ptime pt = from_time_t(tt); - // return ptime2str(pt); - return to_simple_string(pt); - } - - int tointdate() { - time_t current_time; - time(¤t_time); - return tointdate(current_time); - } - - int tointtime() { - time_t current_time; - time(¤t_time); - return tointtime(current_time); - } - - int tointdate(time_t time) { - struct tm timeinfo; - LOCALTIME_S(&timeinfo, &time); - - return ((timeinfo.tm_year + 1900) * 10000) + ((timeinfo.tm_mon + 1) * 100) + timeinfo.tm_mday; - } - - int tointtime(time_t time) { - //std::time_t rawtime; - //std::tm* timeinfo; - //char queryTime[80]; - //std::time(&rawtime); - //timeinfo = std::localtime(&rawtime); - //std::strftime(queryTime, 80, "%Y%m%d %H:%M:%S", timeinfo); - struct tm timeinfo; - LOCALTIME_S(&timeinfo, &time); - - return (timeinfo.tm_hour * 10000) + (timeinfo.tm_min * 100) + (timeinfo.tm_sec); - } - - // convert to # of seconds - int inttimetointtimespan(int time) { - int s1 = time % 100; - int m1 = ((time - s1) / 100) % 100; - int h1 = (int)((time - (m1 * 100) - s1) / 10000); - - return h1 * 3600 + m1 * 60 + s1; - } - - // # of seconds to int time - int inttimespantointtime(int timespan) { - int hour = timespan / 3600; - int second = timespan % 3600; - int minute = second / 60; - second = second % 60; - return (hour * 10000 + minute * 100 + second); - } - - // adds inttime and int timespan (in seconds). does not rollover 24hr periods. - int inttimeadd(int firsttime, int timespaninseconds) - { - int s1 = firsttime % 100; - int m1 = ((firsttime - s1) / 100) % 100; - int h1 = (int)((firsttime - m1 * 100 - s1) / 10000); - s1 += timespaninseconds; - if (s1 >= 60) - { - m1 += (int)(s1 / 60); - s1 = s1 % 60; - } - if (m1 >= 60) - { - h1 += (int)(m1 / 60); - m1 = m1 % 60; - } - int sum = h1 * 10000 + m1 * 100 + s1; - return sum; - } - - int inttimediff(int firsttime, int latertime) - { - int span1 = inttimetointtimespan(firsttime); - int span2 = inttimetointtimespan(latertime); - return span2 - span1; - } - - - - - int64_t string2unixtimems(const string& s) - { +// http://stackoverflow.com/questions/4461586/how-do-i-convert-boostposix-timeptime-to-time-t +time_t str2time_t(const string& s) { + ptime pt(time_from_string(s)); + return ptime2time(pt); +} + +string time_t2str(time_t tt) { + ptime pt = from_time_t(tt); + // return ptime2str(pt); + return to_simple_string(pt); +} + +int32_t tointdate() { + time_t current_time; + time(¤t_time); + return tointdate(current_time); +} + +int32_t tointtime() { + time_t current_time; + time(¤t_time); + return tointtime(current_time); +} + +int32_t tointdate(time_t time) { + struct tm timeinfo; + LOCALTIME_S(&timeinfo, &time); + + return ((timeinfo.tm_year + 1900) * 10000) + ((timeinfo.tm_mon + 1) * 100) + timeinfo.tm_mday; +} + +int32_t tointtime(time_t time) { + // std::time_t rawtime; + // std::tm* timeinfo; + // char queryTime[80]; + // std::time(&rawtime); + // timeinfo = std::localtime(&rawtime); + // std::strftime(queryTime, 80, "%Y%m%d %H:%M:%S", timeinfo); + struct tm timeinfo; + LOCALTIME_S(&timeinfo, &time); + + return (timeinfo.tm_hour * 10000) + (timeinfo.tm_min * 100) + (timeinfo.tm_sec); +} + +// convert to # of seconds +int32_t inttimetointtimespan(int32_t time) { + int32_t s1 = time % 100; + int32_t m1 = ((time - s1) / 100) % 100; + int32_t h1 = (int32_t)((time - (m1 * 100) - s1) / 10000); + + return h1 * 3600 + m1 * 60 + s1; +} + +// # of seconds to int32_t time +int32_t inttimespantointtime(int32_t timespan) { + int32_t hour = timespan / 3600; + int32_t second = timespan % 3600; + int32_t minute = second / 60; + second = second % 60; + return (hour * 10000 + minute * 100 + second); +} + +// adds inttime and int32_t timespan (in seconds). does not rollover 24hr periods. +int32_t inttimeadd(int32_t firsttime, int32_t timespaninseconds) { + int32_t s1 = firsttime % 100; + int32_t m1 = ((firsttime - s1) / 100) % 100; + int32_t h1 = (int32_t)((firsttime - m1 * 100 - s1) / 10000); + s1 += timespaninseconds; + if (s1 >= 60) { + m1 += (int32_t)(s1 / 60); + s1 = s1 % 60; + } + if (m1 >= 60) { + h1 += (int32_t)(m1 / 60); + m1 = m1 % 60; + } + int32_t sum = h1 * 10000 + m1 * 100 + s1; + return sum; +} + +int32_t inttimediff(int32_t firsttime, int32_t latertime) { + int32_t span1 = inttimetointtimespan(firsttime); + int32_t span2 = inttimetointtimespan(latertime); + return span2 - span1; +} + + + + +int64_t string2unixtimems(const string& s) { struct tm tm_; int64_t unixtimems; - int year, month, day, hour, minute,second,millisec; + int32_t year, month, day, hour, minute, second, millisec; sscanf(s.c_str(),"%d-%d-%d %d:%d:%d.%d", &year, &month, &day, &hour, &minute, &second,&millisec); tm_.tm_year = year-1900; tm_.tm_mon = month-1; @@ -530,9 +528,7 @@ namespace StarQuant { time_t t_ = mktime(&tm_); unixtimems = t_*1000+millisec; return unixtimems; +} - } - - -} \ No newline at end of file +} // namespace StarQuant diff --git a/cppsrc/StarQuant/Common/util.h b/cppsrc/StarQuant/Common/util.h index 19918dd25..107ecd357 100644 --- a/cppsrc/StarQuant/Common/util.h +++ b/cppsrc/StarQuant/Common/util.h @@ -1,6 +1,21 @@ -#ifndef _StarQuant_Common_Util_H -#define _StarQuant_Common_Util_H +/***************************************************************************** + * Copyright [2019] + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *****************************************************************************/ +#ifndef CPPSRC_STARQUANT_COMMON_UTIL_H_ +#define CPPSRC_STARQUANT_COMMON_UTIL_H_ +#include #include #include #include @@ -10,15 +25,10 @@ #include #include #include +#include #include #include #include -//#include -#include - - - - using std::string; using std::vector; @@ -32,15 +42,16 @@ using boost::posix_time::ptime; namespace StarQuant { // macros -#define PRINT_SHUTDOWN_MESSAGE printf("\n Thank you for using Star Quant. Goodbye! \n"); +#define PRINT_SHUTDOWN_MESSAGE \ +printf("\n Thank you for using Star Quant. Goodbye! \n"); #if defined(_WIN32) || defined(_WIN64) #include #elif defined(__unix__) || defined(__unix) || defined(unix) || (defined(__APPLE__) && defined(__MACH__)) -#include /* POSIX flags */ -#include /* clock_gettime(), time() */ -#include /* gethrtime(), gettimeofday() */ +#include /* POSIX flags */ +#include /* clock_gettime(), time() */ +#include /* gethrtime(), gettimeofday() */ #if defined(__MACH__) && defined(__APPLE__) #include @@ -58,9 +69,9 @@ namespace StarQuant { #ifdef __linux__ -#define LOCALTIME_S(x,y) localtime_r(y,x) +#define LOCALTIME_S(x, y) localtime_r(y, x) #else -#define LOCALTIME_S(x,y) localtime_s(x,y) +#define LOCALTIME_S(x, y) localtime_s(x, y) #endif #define DATE_FORMAT "%Y-%m-%d" #define DATE_FORMAT_COMPACT "%Y%m%d" @@ -74,127 +85,110 @@ namespace StarQuant { #define EPSILON (1e-6) -#define DOUBLEMAX (1e16) // 一亿亿, 2018年A股总市值不到50万亿 +#define DOUBLEMAX (1e16) // 一亿亿, 2018年A股总市值不到50万亿 -//console ,control related +// console ,control related // std::atomic* setconsolecontrolhandler(void); - // int check_gshutdown(bool force = true); - - //except signal - #include - #include - - struct Except_frame - { - jmp_buf env; - int flag; - void clear() - { - flag = 0; - bzero(env,sizeof(env)); - } - bool isDef() - { - return flag; - } - Except_frame() - { - clear(); - } - }; - void errorDump(); - void recvSignal(int sig); - - - void ConsoleControlHandler(int sig); - - -//string related - - vector stringsplit(const string &s, char delim); - bool startwith(const string&, const string&); - bool endwith(const std::string &str, const std::string &suffix); - string extractExchangeID(const std::string& fullsym); - string UTF8ToGBK(const std::string & strUTF8); - string GBKToUTF8(const std::string & strGBK); - -// numerical - double rounded(double x, int n = 3); - - - inline bool is_greater(double x, double y) - { - return std::isgreater(x - y, EPSILON); + // int32_t check_gshutdown(bool force = true); + +// except signal +#include +#include + +struct Except_frame { + jmp_buf env; + int32_t flag; + void clear() { + flag = 0; + bzero(env, sizeof(env)); } - - inline bool is_less(double x, double y) - { - return std::isless(x - y, EPSILON * -1); - } - - inline bool is_equal(double x, double y) - { - return std::abs(x - y) <= EPSILON * std::abs(x); + bool isDef() { + return flag; } - - inline bool is_greater_equal(double x, double y) - { - return is_greater(x, y) || is_equal(x, y); - } - - inline bool is_less_equal(double x, double y) - { - return is_less(x, y) || is_equal(x, y); + Except_frame() { + clear(); } +}; +void errorDump(); +void recvSignal(int32_t sig); - inline bool is_zero(double x) - { - return is_equal(x, 0.0); - } +void ConsoleControlHandler(int32_t sig); - inline bool is_too_large(double x) - { - return is_greater(x, DOUBLEMAX); - } +// string related -// time related +vector stringsplit(const string &s, char delim); +bool startwith(const string&, const string&); +bool endwith(const std::string &str, const std::string &suffix); +string extractExchangeID(const std::string& fullsym); +string UTF8ToGBK(const std::string & strUTF8); +string GBKToUTF8(const std::string & strGBK); - uint64_t getMicroTime(); - int getMilliSeconds(); - string ymd(); - string ymdcompact(); - string ymdhms(); - string ymdhmsf(); - string ymdhmsf6(); - string hmsf(); - int hmsf2inttime(string hmsf); +// numerical +double rounded(double x, int32_t n = 3); - void msleep(uint64_t _ms); - string nowMS(); +inline bool is_greater(double x, double y) { + return std::isgreater(x - y, EPSILON); +} - string ptime2str(const ptime& pt); - time_t str2time_t(const string& s); - string time_t2str(time_t tt); - time_t ptime2time(ptime t); +inline bool is_less(double x, double y) { + return std::isless(x - y, EPSILON * -1); +} - int tointdate(); - int tointtime(); - int tointdate(time_t time); - int tointtime(time_t time); - int inttimetointtimespan(int time); // convert to # of seconds - int inttimespantointtime(int timespan); // # of seconds to int time - int inttimeadd(int firsttime, int timespaninseconds); // in seconds - int inttimediff(int firsttime, int latertime); // in seconds - int64_t string2unixtimems(const string& s); +inline bool is_equal(double x, double y) { + return std::abs(x - y) <= EPSILON * std::abs(x); +} +inline bool is_greater_equal(double x, double y) { + return is_greater(x, y) || is_equal(x, y); +} +inline bool is_less_equal(double x, double y) { + return is_less(x, y) || is_equal(x, y); +} +inline bool is_zero(double x) { + return is_equal(x, 0.0); +} +inline bool is_too_large(double x) { + return is_greater(x, DOUBLEMAX); +} -} +// time related -#endif // _StarQuant_Common_Util_H +uint64_t getMicroTime(); +int32_t getMilliSeconds(); +string ymd(); +string ymdcompact(); +string ymdhms(); +string ymdhmsf(); +string ymdhmsf6(); +string hmsf(); +int32_t hmsf2inttime(string hmsf); + +void msleep(uint64_t _ms); +string nowMS(); + +string ptime2str(const ptime& pt); +time_t str2time_t(const string& s); +string time_t2str(time_t tt); +time_t ptime2time(ptime t); + +int32_t tointdate(); +int32_t tointtime(); +int32_t tointdate(time_t time); +int32_t tointtime(time_t time); +int32_t inttimetointtimespan(int32_t time); // convert to # of seconds +int32_t inttimespantointtime(int32_t timespan); // # of seconds to int32_t time +int32_t inttimeadd(int32_t firsttime, int32_t timespaninseconds); // in seconds +int32_t inttimediff(int32_t firsttime, int32_t latertime); // in seconds +int64_t string2unixtimems(const string& s); + + +} // namespace StarQuant + +#endif // CPPSRC_STARQUANT_COMMON_UTIL_H_ diff --git a/cppsrc/StarQuant/Data/datamanager.cpp b/cppsrc/StarQuant/Data/datamanager.cpp index a962371d4..bbd80bf6d 100644 --- a/cppsrc/StarQuant/Data/datamanager.cpp +++ b/cppsrc/StarQuant/Data/datamanager.cpp @@ -1,228 +1,232 @@ -#include -#include -#include -#include -#include +/***************************************************************************** + * Copyright [2019] + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *****************************************************************************/ #include #include #include - +#include +#include +#include +#include +#include namespace StarQuant { - DataManager* DataManager::pinstance_ = nullptr; - mutex DataManager::instancelock_; +DataManager* DataManager::pinstance_ = nullptr; +mutex DataManager::instancelock_; - DataManager::DataManager() : count_(0) - { - loadSecurityFile(); - } +DataManager::DataManager() : count_(0) { + loadSecurityFile(); +} - DataManager::~DataManager() - { - } +DataManager::~DataManager() {} - DataManager& DataManager::instance() { +DataManager& DataManager::instance() { + if (pinstance_ == nullptr) { + lock_guard g(instancelock_); if (pinstance_ == nullptr) { - lock_guard g(instancelock_); - if (pinstance_ == nullptr) { - pinstance_ = new DataManager(); - } + pinstance_ = new DataManager(); } - return *pinstance_; } + return *pinstance_; +} - void DataManager::updateOrderBook(const Fill& fill){ - //assume only price change - if (orderBook_.find(fill.fullSymbol_) != orderBook_.end()){ - orderBook_[fill.fullSymbol_].price_ = fill.tradePrice_; - orderBook_[fill.fullSymbol_].size_ = fill.tradeSize_; - } - else - { - Tick newk; - newk.depth_ = 0; - newk.price_ = fill.tradePrice_; - newk.size_ = fill.tradeSize_; - orderBook_[fill.fullSymbol_] = newk; - } +void DataManager::updateOrderBook(const Fill& fill) { +// assume only price change + if (orderBook_.find(fill.fullSymbol_) != orderBook_.end()) { + orderBook_[fill.fullSymbol_].price_ = fill.tradePrice_; + orderBook_[fill.fullSymbol_].size_ = fill.tradeSize_; + } else { + Tick newk; + newk.depth_ = 0; + newk.price_ = fill.tradePrice_; + newk.size_ = fill.tradeSize_; + orderBook_[fill.fullSymbol_] = newk; } +} - void DataManager::loadSecurityFile(){ - try{ - string contractpath = boost::filesystem::current_path().string() + "/etc/ctpcontract.yaml"; - YAML::Node contractinfo = YAML::LoadFile(contractpath); - for (YAML::const_iterator symsec = contractinfo.begin();symsec != contractinfo.end(); symsec++) - { - auto sym = symsec->first.as(); - auto securities = symsec->second; - Security sec; - sec.symbol_ = securities["symbol"].as(); - sec.exchange_ = securities["exchange"].as(); - sec.securityType_ = securities["product"].as(); - sec.multiplier_ = securities["size"].as(); - sec.localName_ = securities["name"].as(); - sec.ticksize_ = securities["pricetick"].as(); - sec.postype_ = securities["positiontype"].as() ; - sec.longMarginRatio_ = securities["long_margin_ratio"].as(); - sec.shortMarginRatio_ = securities["short_margin_ratio"].as(); - sec.underlyingSymbol_ = securities["option_underlying"].as(); - sec.optionType_ = securities["option_type"].as(); - sec.strikePrice_ = securities["option_strike"].as(); - sec.expiryDate_ = securities["option_expiry"].as(); - sec.fullSymbol_ = securities["full_symbol"].as(); - securityDetails_[sym] = sec; - ctp2Full_[sym] = sec.fullSymbol_; - full2Ctp_[sec.fullSymbol_] = sym; - } - //back up - std::ofstream fout("etc/ctpcontract.yaml.bak"); - fout<< contractinfo; - } - catch(exception &e){ - fmt::print("Read contract exception:{}.",e.what()); - } - catch(...){ - fmt::print("Read contract error!"); +void DataManager::loadSecurityFile() { + try { + string contractpath = boost::filesystem::current_path().string() + "/etc/ctpcontract.yaml"; + YAML::Node contractinfo = YAML::LoadFile(contractpath); + for (YAML::const_iterator symsec = contractinfo.begin(); symsec != contractinfo.end(); symsec++) { + auto sym = symsec->first.as(); + auto securities = symsec->second; + Security sec; + sec.symbol_ = securities["symbol"].as(); + sec.exchange_ = securities["exchange"].as(); + sec.securityType_ = securities["product"].as(); + sec.multiplier_ = securities["size"].as(); + sec.localName_ = securities["name"].as(); + sec.ticksize_ = securities["pricetick"].as(); + sec.postype_ = securities["positiontype"].as(); + sec.longMarginRatio_ = securities["long_margin_ratio"].as(); + sec.shortMarginRatio_ = securities["short_margin_ratio"].as(); + sec.underlyingSymbol_ = securities["option_underlying"].as(); + sec.optionType_ = securities["option_type"].as(); + sec.strikePrice_ = securities["option_strike"].as(); + sec.expiryDate_ = securities["option_expiry"].as(); + sec.fullSymbol_ = securities["full_symbol"].as(); + securityDetails_[sym] = sec; + ctp2Full_[sym] = sec.fullSymbol_; + full2Ctp_[sec.fullSymbol_] = sym; } + // back up + std::ofstream fout("etc/ctpcontract.yaml.bak"); + fout<< contractinfo; + } + catch(exception &e) { + fmt::print("Read contract exception:{}.", e.what()); } + catch(...) { + fmt::print("Read contract error!"); + } +} - void DataManager::saveSecurityToFile() { - try{ - YAML::Node securities; - for (auto iterator = securityDetails_.begin(); iterator != securityDetails_.end(); ++iterator) { - auto sym = iterator->first; - auto sec = iterator->second; - securities[sym]["symbol"] = sec.symbol_; - securities[sym]["exchange"] = sec.exchange_; - securities[sym]["product"] = sec.securityType_; - securities[sym]["size"] = sec.multiplier_; - securities[sym]["name"] = sec.localName_; - securities[sym]["pricetick"] = sec.ticksize_; - securities[sym]["positiontype"] = sec.postype_; - securities[sym]["long_margin_ratio"] = sec.longMarginRatio_; - securities[sym]["short_margin_ratio"] = sec.shortMarginRatio_; - securities[sym]["option_underlying"] = sec.underlyingSymbol_; - securities[sym]["option_type"] = sec.optionType_; - securities[sym]["option_strike"] = sec.strikePrice_; - securities[sym]["option_expiry"] = sec.expiryDate_; - string fullsym; - string type; - string product; - string contracno; - int i; - if (sec.securityType_ == '1' || sec.securityType_ == '2'){ - for(i = 0;ifirst; + auto sec = iterator->second; + securities[sym]["symbol"] = sec.symbol_; + securities[sym]["exchange"] = sec.exchange_; + securities[sym]["product"] = sec.securityType_; + securities[sym]["size"] = sec.multiplier_; + securities[sym]["name"] = sec.localName_; + securities[sym]["pricetick"] = sec.ticksize_; + securities[sym]["positiontype"] = sec.postype_; + securities[sym]["long_margin_ratio"] = sec.longMarginRatio_; + securities[sym]["short_margin_ratio"] = sec.shortMarginRatio_; + securities[sym]["option_underlying"] = sec.underlyingSymbol_; + securities[sym]["option_type"] = sec.optionType_; + securities[sym]["option_strike"] = sec.strikePrice_; + securities[sym]["option_expiry"] = sec.expiryDate_; + string fullsym; + string type; + string product; + string contracno; + int32_t i; + if (sec.securityType_ == '1' || sec.securityType_ == '2') { + for (i = 0; i < sym.size(); i++) { + if (isdigit(sym[i])) + break; } - else if (sec.securityType_ == '3'){ - int pos = sym.find(" "); - string combo = sym.substr(pos+1); - int sep = combo.find("&"); - string sym1 = combo.substr(0,sep); - string sym2 = combo.substr(sep+1); - for(i = 0;i(k); // default assigement shallow copy - // _latestmarkets[k.fullsymbol_].price_ = k.price_; - // _latestmarkets[k.fullsymbol_].size_ = k.size_; - // //cout<<"settickvalue price"<<_latestmarkets[k.fullsymbol_].price_<(k); // default assigement shallow copy + // _latestmarkets[k.fullsymbol_].price_ = k.price_; + // _latestmarkets[k.fullsymbol_].size_ = k.size_; + // //cout<<"settickvalue price"<<_latestmarkets[k.fullsymbol_].price_< +#include #include #include #include #include -#include -#include - #define CEREAL_RAPIDJSON_NAMESPACE creal_rapidjson #include #include @@ -22,39 +36,37 @@ using std::string; namespace StarQuant { - /// DataManager - /// 1. provide latest full tick price info -- DataBoard Service - /// 2. record data - class DataManager { - public: - - - static DataManager* pinstance_; - static mutex instancelock_; - static DataManager& instance(); - - TickWriter recorder_; - uint64_t count_ = 0; - bool contractUpdated_ = false; - bool saveSecurityFile_ = false; - std::map securityDetails_; //ctpsymbol to security - std::map orderBook_; - std::map ctp2Full_; - std::map full2Ctp_; - //std::map _5s; - //std::map _15s; - // std::map _60s; - //std::map _1d; - - DataManager(); - ~DataManager(); - void reset(); - void rebuild(); - void updateOrderBook(const Tick& k){ orderBook_[k.fullSymbol_] = k;}; - void updateOrderBook(const Fill& fill); - void saveSecurityToFile(); - void loadSecurityFile(); - }; -} - -#endif // _StarQuant_Data_DataManager_H_ +/// DataManager +/// 1. provide latest full tick price info -- DataBoard Service +/// 2. record data +class DataManager { + public: + static DataManager* pinstance_; + static mutex instancelock_; + static DataManager& instance(); + + TickWriter recorder_; + uint64_t count_ = 0; + bool contractUpdated_ = false; + bool saveSecurityFile_ = false; + std::map securityDetails_; // ctpsymbol to security + std::map orderBook_; + std::map ctp2Full_; + std::map full2Ctp_; + //std::map _5s; + //std::map _15s; + // std::map _60s; + //std::map _1d; + + DataManager(); + ~DataManager(); + void reset(); + void rebuild(); + void updateOrderBook(const Tick& k) { orderBook_[k.fullSymbol_] = k;} + void updateOrderBook(const Fill& fill); + void saveSecurityToFile(); + void loadSecurityFile(); +}; +} // namespace StarQuant + +#endif // CPPSRC_STARQUANT_DATA_DATAMANAGER_H_ diff --git a/cppsrc/StarQuant/Data/tickreader.h b/cppsrc/StarQuant/Data/tickreader.h index bfd32b060..5d66d396d 100644 --- a/cppsrc/StarQuant/Data/tickreader.h +++ b/cppsrc/StarQuant/Data/tickreader.h @@ -1,9 +1,26 @@ -#ifndef __StarQuant_Data_TickReader_H__ -#define __StarQuant_Data_TickReader_H__ +/***************************************************************************** + * Copyright [2019] + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *****************************************************************************/ +#ifndef CPPSRC_STARQUANT_DATA_TICKREADER_H_ +#define CPPSRC_STARQUANT_DATA_TICKREADER_H_ + +#include #include #include -#include +#include +#include using std::mutex; @@ -13,50 +30,50 @@ using std::mutex; ////////////////////////////////////////////////////////////////////////// namespace StarQuant { - struct TimeAndMsg { - uint64_t t; - string msg; - }; - - // vector readreplayfile(const string& filetoreplay) { - // ifstream f(filetoreplay); - // vector lines; - // string x; - // while (f.is_open() && f.good()) { - // getline(f, x); - // if (!x.empty()) { - // vector tmp = stringsplit(x, '@'); - // if (tmp.size() == 2) { - // TimeAndMsg tam = { (uint64_t)atoll(tmp[0].c_str()), tmp[1] }; - // lines.push_back(tam); - // } - // } - // } - // return lines; - // } - vector readreplayfile(const string& filetoreplay) { - ifstream f(filetoreplay); - vector lines; - string x; - while (f.is_open() && f.good()) { - getline(f, x); - if (!x.empty()) { - vector tmp = stringsplit(x, '@'); - if (tmp.size() == 2) { - string tam = tmp[1] ; - tam.erase(0,1); - lines.push_back(tam); - } +struct TimeAndMsg { + uint64_t t; + string msg; +}; + +// vector readreplayfile(const string& filetoreplay) { +// ifstream f(filetoreplay); +// vector lines; +// string x; +// while (f.is_open() && f.good()) { +// getline(f, x); +// if (!x.empty()) { +// vector tmp = stringsplit(x, '@'); +// if (tmp.size() == 2) { +// TimeAndMsg tam = { (uint64_t)atoll(tmp[0].c_str()), tmp[1] }; +// lines.push_back(tam); +// } +// } +// } +// return lines; +// } +vector readreplayfile(const string& filetoreplay) { + ifstream f(filetoreplay); + vector lines; + string x; + while (f.is_open() && f.good()) { + getline(f, x); + if (!x.empty()) { + vector tmp = stringsplit(x, '@'); + if (tmp.size() == 2) { + string tam = tmp[1]; + tam.erase(0, 1); + lines.push_back(tam); } } - return lines; } + return lines; +} -} +} // namespace StarQuant -#endif +#endif // CPPSRC_STARQUANT_DATA_TICKREADER_H_ diff --git a/cppsrc/StarQuant/Data/tickwriter.h b/cppsrc/StarQuant/Data/tickwriter.h index 666a85f94..8772c01f4 100644 --- a/cppsrc/StarQuant/Data/tickwriter.h +++ b/cppsrc/StarQuant/Data/tickwriter.h @@ -1,8 +1,22 @@ -#ifndef __StarQuant_Data_TickWriter_H__ -#define __StarQuant_Data_TickWriter_H__ +/***************************************************************************** + * Copyright [2019] + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *****************************************************************************/ + +#ifndef CPPSRC_STARQUANT_DATA_TICKWRITER_H_ +#define CPPSRC_STARQUANT_DATA_TICKWRITER_H_ + -#include -#include #include #include #include @@ -11,186 +25,182 @@ #include #include #include - -//#include -//#include +// #include +// #include #include #include #include +#include +#include +#include +#include using std::mutex; ////////////////////////////////////////////////////////////////////////// // tick recorder ////////////////////////////////////////////////////////////////////////// -namespace StarQuant -{ - struct TickWriter { - int bufSize; - FILE* fp = nullptr; - int count = 0; //length of string in the buffer - char* head = nullptr; // = raiibuf.get(); +namespace StarQuant { +struct TickWriter { + int32_t bufSize; + FILE* fp = nullptr; + int32_t count = 0; // length of string in the buffer + char* head = nullptr; // = raiibuf.get(); // mongodb writer - //mongoc_client_t *client; - //mongoc_database_t *database; - //mongoc_collection_t *collection; - //bson_t *command, reply, *insert; - bson_error_t error; - mongoc_client_pool_t *pool; - mongoc_uri_t *uri; - - TickWriter() { - bufSize = 1024; - head = new char[bufSize]; - mongoc_init (); - uri = mongoc_uri_new("mongodb://localhost:27017"); - pool = mongoc_client_pool_new(uri); - //client = mongoc_client_new ("mongodb://localhost:27017"); - //database = mongoc_client_get_database (client, "findata"); - } - ~TickWriter() { - if (fp) { - fwrite(head, sizeof(char), count, fp); - fflush(fp); - fclose(fp); - } - delete[] head; -// mongoc_collection_destroy (collection); -// mongoc_database_destroy (database); -// mongoc_client_destroy (client); - mongoc_client_pool_destroy(pool); - mongoc_uri_destroy(uri); - mongoc_cleanup (); + // mongoc_client_t *client; + // mongoc_database_t *database; + // mongoc_collection_t *collection; + // bson_t *command, reply, *insert; + bson_error_t error; + mongoc_client_pool_t *pool; + mongoc_uri_t *uri; + + TickWriter() { + bufSize = 1024; + head = new char[bufSize]; + mongoc_init(); + uri = mongoc_uri_new("mongodb://localhost:27017"); + pool = mongoc_client_pool_new(uri); + // client = mongoc_client_new ("mongodb://localhost:27017"); + // database = mongoc_client_get_database (client, "findata"); } - - void put(const string& _str) { - if (!_str.empty()) { - char tmp[512] = {}; - //sprintf(tmp, "%lu@%s\n", getMicroTime(), _str.c_str()); - sprintf(tmp, "%s @%s\n", ymdhmsf().c_str(), _str.c_str()); - uint32_t strsize = strlen(tmp); // + 1; - uint32_t required_buffer_len = count + strsize; - - if (required_buffer_len > bufSize) { - size_t r = fwrite(head, sizeof(char), count, fp); - //printf("write files\n"); - if (r == count) { - memcpy(head, tmp, strsize * sizeof(char)); - count = strsize; - fflush(fp); - return; - } - else { - //error - //http://www.cplusplus.com/reference/cstdio/fwrite/ - } + ~TickWriter() { + if (fp) { + fwrite(head, sizeof(char), count, fp); + fflush(fp); + fclose(fp); + } + delete[] head; +// mongoc_collection_destroy (collection); +// mongoc_database_destroy (database); +// mongoc_client_destroy (client); + mongoc_client_pool_destroy(pool); + mongoc_uri_destroy(uri); + mongoc_cleanup(); + } + + void put(const string& _str) { + if (!_str.empty()) { + char tmp[512] = {}; + // sprintf(tmp, "%lu@%s\n", getMicroTime(), _str.c_str()); + sprintf(tmp, "%s @%s\n", ymdhmsf().c_str(), _str.c_str()); + uint32_t strsize = strlen(tmp); // + 1; + uint32_t required_buffer_len = count + strsize; + + if (required_buffer_len > bufSize) { + size_t r = fwrite(head, sizeof(char), count, fp); + // printf("write files\n"); + if (r == count) { + memcpy(head, tmp, strsize * sizeof(char)); + count = strsize; + fflush(fp); + return; + } else { + // error + // http://www.cplusplus.com/reference/cstdio/fwrite/ } - memcpy(head + count, tmp, strsize * sizeof(char)); - count = required_buffer_len; } + memcpy(head + count, tmp, strsize * sizeof(char)); + count = required_buffer_len; } - - void insertdb(const string& _str){ - if (!_str.empty()) { - vector vs = stringsplit(_str, SERIALIZATION_SEPARATOR); - if ((MSG_TYPE)(atoi(vs[0].c_str())) == MSG_TYPE::MSG_TYPE_TICK_L1) - { - - vector fullsym = stringsplit(vs[1], ' '); - string collectionname = fullsym[2]; - mongoc_client_t *client = mongoc_client_pool_pop(pool); - mongoc_collection_t *collection = mongoc_client_get_collection (client, "findata", collectionname.c_str()); - - bson_t *doc = bson_new(); - BSON_APPEND_UTF8(doc, "contractno", fullsym[3].c_str()); - BSON_APPEND_DATE_TIME(doc, "datetime", string2unixtimems(vs[2])+8*3600000); - BSON_APPEND_DOUBLE(doc, "price", atof(vs[3].c_str())); - BSON_APPEND_INT32(doc, "size", atoi(vs[4].c_str())); - BSON_APPEND_DOUBLE(doc, "bidprice1", atof(vs[5].c_str())); - BSON_APPEND_INT32(doc, "bidsize1", atoi(vs[6].c_str())); - BSON_APPEND_DOUBLE(doc, "askprice1", atof(vs[7].c_str())); - BSON_APPEND_INT32(doc, "asksize1", atoi(vs[8].c_str())); - BSON_APPEND_INT32(doc, "openinterest", atoi(vs[9].c_str())); - BSON_APPEND_INT32(doc, "dominant", 0); -// BSON_APPEND_DOUBLE(doc, "upperLimit", atof(vs[14].c_str())); -// BSON_APPEND_DOUBLE(doc, "lowerLimit", atof(vs[15].c_str())); - // 将bson文档插入到集合 - if (!mongoc_collection_insert(collection, MONGOC_INSERT_NONE, doc, NULL, &error)) { - fprintf(stderr, "Count failed: %s\n", error.message); - } - bson_destroy(doc); - mongoc_collection_destroy(collection); - mongoc_client_pool_push(pool, client); - } - else if ((MSG_TYPE)(atoi(vs[0].c_str())) == MSG_TYPE::MSG_TYPE_TICK_L5){ - // Tick_L5 k; - // k.fullsymbol_ = vs[1]; - // k.time_ = vs[2]; - // k.price_ = atof(vs[3].c_str()); - // k.size_ = atoi(vs[4].c_str()); - // k.depth_ = 5; - // k.bidprice_L1_ = atoi(vs[5].c_str()); - // k.bidsize_L1_ = atoi(vs[6].c_str()); - // k.askprice_L1_ = atoi(vs[7].c_str()); - // k.asksize_L1_ = atoi(vs[8].c_str()); - // k.bidprice_L2_ = atoi(vs[9].c_str()); - // k.bidsize_L2_ = atoi(vs[10].c_str()); - // k.askprice_L2_ = atoi(vs[11].c_str()); - // k.asksize_L2_ = atoi(vs[12].c_str()); - // k.bidprice_L3_ = atoi(vs[13].c_str()); - // k.bidsize_L3_ = atoi(vs[14].c_str()); - // k.askprice_L3_ = atoi(vs[15].c_str()); - // k.asksize_L3_ = atoi(vs[16].c_str()); - // k.bidprice_L4_ = atoi(vs[17].c_str()); - // k.bidsize_L4_ = atoi(vs[18].c_str()); - // k.askprice_L4_ = atoi(vs[19].c_str()); - // k.asksize_L4_ = atoi(vs[20].c_str()); - // k.bidprice_L5_ = atoi(vs[21].c_str()); - // k.bidsize_L5_ = atoi(vs[22].c_str()); - // k.askprice_L5_ = atoi(vs[23].c_str()); - // k.asksize_L5_ = atoi(vs[24].c_str()); - // k.open_interest = atoi(vs[25].c_str()); - // k.open_ = atoi(vs[26].c_str()); - // k.high_ = atoi(vs[27].c_str()); - // k.low_ = atoi(vs[28].c_str()); - // k.pre_close_ = atoi(vs[29].c_str()); - // k.upper_limit_price_ = atoi(vs[30].c_str()); - // k.lower_limit_price_ = atoi(vs[31].c_str()); - + } + + void insertdb(const string& _str) { + if (!_str.empty()) { + vector vs = stringsplit(_str, SERIALIZATION_SEPARATOR); + if ((MSG_TYPE)(atoi(vs[0].c_str())) == MSG_TYPE::MSG_TYPE_TICK_L1) { + + vector fullsym = stringsplit(vs[1], ' '); + string collectionname = fullsym[2]; + mongoc_client_t *client = mongoc_client_pool_pop(pool); + mongoc_collection_t *collection = mongoc_client_get_collection (client, "findata", collectionname.c_str()); + + bson_t *doc = bson_new(); + BSON_APPEND_UTF8(doc, "contractno", fullsym[3].c_str()); + BSON_APPEND_DATE_TIME(doc, "datetime", string2unixtimems(vs[2]) + 8*3600000); + BSON_APPEND_DOUBLE(doc, "price", atof(vs[3].c_str())); + BSON_APPEND_INT32(doc, "size", atoi(vs[4].c_str())); + BSON_APPEND_DOUBLE(doc, "bidprice1", atof(vs[5].c_str())); + BSON_APPEND_INT32(doc, "bidsize1", atoi(vs[6].c_str())); + BSON_APPEND_DOUBLE(doc, "askprice1", atof(vs[7].c_str())); + BSON_APPEND_INT32(doc, "asksize1", atoi(vs[8].c_str())); + BSON_APPEND_INT32(doc, "openinterest", atoi(vs[9].c_str())); + BSON_APPEND_INT32(doc, "dominant", 0); + // BSON_APPEND_DOUBLE(doc, "upperLimit", atof(vs[14].c_str())); + // BSON_APPEND_DOUBLE(doc, "lowerLimit", atof(vs[15].c_str())); + // 将bson文档插入到集合 + if (!mongoc_collection_insert(collection, MONGOC_INSERT_NONE, doc, NULL, &error)) { + fprintf(stderr, "Count failed: %s\n", error.message); } - + bson_destroy(doc); + mongoc_collection_destroy(collection); + mongoc_client_pool_push(pool, client); + } else if ((MSG_TYPE)(atoi(vs[0].c_str())) == MSG_TYPE::MSG_TYPE_TICK_L5) { + // Tick_L5 k; + // k.fullsymbol_ = vs[1]; + // k.time_ = vs[2]; + // k.price_ = atof(vs[3].c_str()); + // k.size_ = atoi(vs[4].c_str()); + // k.depth_ = 5; + // k.bidprice_L1_ = atoi(vs[5].c_str()); + // k.bidsize_L1_ = atoi(vs[6].c_str()); + // k.askprice_L1_ = atoi(vs[7].c_str()); + // k.asksize_L1_ = atoi(vs[8].c_str()); + // k.bidprice_L2_ = atoi(vs[9].c_str()); + // k.bidsize_L2_ = atoi(vs[10].c_str()); + // k.askprice_L2_ = atoi(vs[11].c_str()); + // k.asksize_L2_ = atoi(vs[12].c_str()); + // k.bidprice_L3_ = atoi(vs[13].c_str()); + // k.bidsize_L3_ = atoi(vs[14].c_str()); + // k.askprice_L3_ = atoi(vs[15].c_str()); + // k.asksize_L3_ = atoi(vs[16].c_str()); + // k.bidprice_L4_ = atoi(vs[17].c_str()); + // k.bidsize_L4_ = atoi(vs[18].c_str()); + // k.askprice_L4_ = atoi(vs[19].c_str()); + // k.asksize_L4_ = atoi(vs[20].c_str()); + // k.bidprice_L5_ = atoi(vs[21].c_str()); + // k.bidsize_L5_ = atoi(vs[22].c_str()); + // k.askprice_L5_ = atoi(vs[23].c_str()); + // k.asksize_L5_ = atoi(vs[24].c_str()); + // k.open_interest = atoi(vs[25].c_str()); + // k.open_ = atoi(vs[26].c_str()); + // k.high_ = atoi(vs[27].c_str()); + // k.low_ = atoi(vs[28].c_str()); + // k.pre_close_ = atoi(vs[29].c_str()); + // k.upper_limit_price_ = atoi(vs[30].c_str()); + // k.lower_limit_price_ = atoi(vs[31].c_str()); } } - - void insertdb(const Tick& k){ - vector fullsym = stringsplit(k.fullSymbol_, ' '); - string collectionname = fullsym[2]; - mongoc_client_t *client = mongoc_client_pool_pop(pool); - mongoc_collection_t *collection = mongoc_client_get_collection (client, "findata", collectionname.c_str()); - - bson_t *doc = bson_new(); - BSON_APPEND_UTF8(doc, "contractno", fullsym[3].c_str()); - BSON_APPEND_DATE_TIME(doc, "datetime", string2unixtimems(k.time_)+8*3600000); - BSON_APPEND_DOUBLE(doc, "price", k.price_); - BSON_APPEND_INT32(doc, "size", k.size_); - BSON_APPEND_DOUBLE(doc, "bidprice1", k.bidPrice_[0]); - BSON_APPEND_INT32(doc, "bidsize1", k.bidSize_[0]); - BSON_APPEND_DOUBLE(doc, "askprice1", k.askPrice_[0]); - BSON_APPEND_INT32(doc, "asksize1", k.askSize_[0]); - BSON_APPEND_INT32(doc, "openinterest", k.openInterest_); - BSON_APPEND_INT32(doc, "dominant", 0); - //BSON_APPEND_DOUBLE(doc, "upperLimit", k.upper_limit_price_); - //BSON_APPEND_DOUBLE(doc, "lowerLimit", k.lower_limit_price_); - if (!mongoc_collection_insert(collection, MONGOC_INSERT_NONE, doc, NULL, &error)) { - cout<<"insert mongodb failed, errormsg = "< fullsym = stringsplit(k.fullSymbol_, ' '); + string collectionname = fullsym[2]; + mongoc_client_t *client = mongoc_client_pool_pop(pool); + mongoc_collection_t *collection = mongoc_client_get_collection (client, "findata", collectionname.c_str()); + + bson_t *doc = bson_new(); + BSON_APPEND_UTF8(doc, "contractno", fullsym[3].c_str()); + BSON_APPEND_DATE_TIME(doc, "datetime", string2unixtimems(k.time_) + 8*3600000); + BSON_APPEND_DOUBLE(doc, "price", k.price_); + BSON_APPEND_INT32(doc, "size", k.size_); + BSON_APPEND_DOUBLE(doc, "bidprice1", k.bidPrice_[0]); + BSON_APPEND_INT32(doc, "bidsize1", k.bidSize_[0]); + BSON_APPEND_DOUBLE(doc, "askprice1", k.askPrice_[0]); + BSON_APPEND_INT32(doc, "asksize1", k.askSize_[0]); + BSON_APPEND_INT32(doc, "openinterest", k.openInterest_); + BSON_APPEND_INT32(doc, "dominant", 0); + // BSON_APPEND_DOUBLE(doc, "upperLimit", k.upper_limit_price_); + // BSON_APPEND_DOUBLE(doc, "lowerLimit", k.lower_limit_price_); + if (!mongoc_collection_insert(collection, MONGOC_INSERT_NONE, doc, NULL, &error)) { + cout << "insert mongodb failed, errormsg = " << error.message; } + bson_destroy(doc); + mongoc_collection_destroy(collection); + mongoc_client_pool_push(pool, client); + } +}; +} // namespace StarQuant - }; -} - -#endif +#endif // CPPSRC_STARQUANT_DATA_TICKWRITER_H_ diff --git a/cppsrc/StarQuant/Engine/CtpMDEngine.cpp b/cppsrc/StarQuant/Engine/CtpMDEngine.cpp index 66647e1e5..9c1e13fd3 100644 --- a/cppsrc/StarQuant/Engine/CtpMDEngine.cpp +++ b/cppsrc/StarQuant/Engine/CtpMDEngine.cpp @@ -1,592 +1,622 @@ -#include +/***************************************************************************** + * Copyright [2019] + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *****************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include #include #include #include +#include #include #include #include -#include -#include -#include +#include #include #include -#include -#include -#include -#include -#include -#include -#include -#include -#include -using namespace std; -namespace StarQuant -{ - //extern std::atomic gShutdown; - - CtpMDEngine ::CtpMDEngine() - : loginReqId_(0) - , reqId_(0) - , apiinited_(false) - , inconnectaction_(false) - , autoconnect_(false) - , timercount_(0) - { - name_ = "CTP.MD"; - init(); - } - CtpMDEngine::~CtpMDEngine() { - if(estate_ != STOP) - stop(); - releaseapi(); - } - void CtpMDEngine::releaseapi(){ - if (api_ != nullptr){ - // this->api_->Join(); - msleep(1000); - this->api_->RegisterSpi(nullptr); - if (apiinited_) - this->api_->Release();// api must init() or will segfault - this->api_ = nullptr; - } - } +using namespace std; - void CtpMDEngine::reset(){ - disconnect(); - releaseapi(); - CConfig::instance().readConfig(); - init(); - LOG_DEBUG(logger,name_<<" reset"); - } - - void CtpMDEngine::init(){ - // if (IEngine::msgq_send_ == nullptr){ - // lock_guard g(IEngine::sendlock_); - // IEngine::msgq_send_ = std::make_unique(MSGQ_PROTOCOL::PUB, CConfig::instance().SERVERPUB_URL); - // } - reqId_ = 0; - lastsubs_.clear(); - if(logger == nullptr){ - logger = SQLogger::getLogger("MDEngine.CTP"); - } +namespace StarQuant { +// extern std::atomic gShutdown; + +CtpMDEngine ::CtpMDEngine() + : loginReqId_(0) + , reqId_(0) + , apiinited_(false) + , inconnectaction_(false) + , autoconnect_(false) + , timercount_(0) { + name_ = "CTP.MD"; + init(); +} - if (messenger_ == nullptr){ - messenger_ = std::make_unique(name_, CConfig::instance().SERVERSUB_URL); - msleep(100); - } - ctpacc_ = CConfig::instance()._gatewaymap[name_]; - string path = CConfig::instance().logDir() + "/ctp/md"; - boost::filesystem::path dir(path.c_str()); - boost::filesystem::create_directory(dir); - // 创建API对象 - this->api_ = CThostFtdcMdApi::CreateFtdcMdApi(path.c_str()); - this->api_->RegisterSpi(this); - estate_ = DISCONNECTED; - auto pmsgs = make_shared(DESTINATION_ALL, name_, - MSG_TYPE_ENGINE_STATUS, - to_string(estate_)); - messenger_->send(pmsgs); - apiinited_ = false; - autoconnect_ = CConfig::instance().autoconnect; - LOG_DEBUG(logger,name_ <<" inited, api version:"<(DESTINATION_ALL, name_, - MSG_TYPE_ENGINE_STATUS, - to_string(estate_)); - messenger_->send(pmsgs); - LOG_DEBUG(logger,name_ <<" stoped"); +void CtpMDEngine::releaseapi() { + if (api_ != nullptr) { + // this->api_->Join(); + msleep(1000); + this->api_->RegisterSpi(nullptr); + if (apiinited_) + this->api_->Release(); // api must init() or will segfault + this->api_ = nullptr; } +} - void CtpMDEngine::start(){ - while(estate_ != EState::STOP){ - auto pmsgin = messenger_->recv(); - bool processmsg = ((pmsgin != nullptr) && ( startwith(pmsgin->destination_,DESTINATION_ALL) || (pmsgin->destination_ == name_ ))); - // if (pmsgin == nullptr || (pmsgin->destination_ != name_ && ! startwith(pmsgin->destination_,DESTINATION_ALL)) ) - // continue; - if (processmsg){ - switch (pmsgin->msgtype_) - { - case MSG_TYPE_ENGINE_CONNECT: - if (connect()){ - auto pmsgout = make_shared(pmsgin->source_, name_, - MSG_TYPE_INFO_ENGINE_MDCONNECTED,"CTP.MD connected."); - messenger_->send(pmsgout,1); - } - break; - case MSG_TYPE_ENGINE_DISCONNECT: - disconnect(); - break; - case MSG_TYPE_SUBSCRIBE_MARKET_DATA: - if (estate_ == LOGIN_ACK){ - auto pmsgin2 = static_pointer_cast(pmsgin); - subscribe(pmsgin2->data_,pmsgin2->symtype_); - } - else{ - LOG_DEBUG(logger,name_ <<" is not connected,can not subscribe!"); - auto pmsgout = make_shared(pmsgin->source_, name_, - MSG_TYPE_ERROR_ENGINENOTCONNECTED, - "ctp md is not connected,can not subscribe"); - messenger_->send(pmsgout); - } - break; - case MSG_TYPE_UNSUBSCRIBE: - if (estate_ == LOGIN_ACK){ - auto pmsgin2 = static_pointer_cast(pmsgin); - unsubscribe(pmsgin2->data_,pmsgin2->symtype_); - } - else{ - LOG_DEBUG(logger,name_ <<" is not connected,can not unsubscribe!"); - auto pmsgout = make_shared(pmsgin->source_, name_, - MSG_TYPE_ERROR_ENGINENOTCONNECTED, - "ctp md is not connected,can not unsubscribe"); - messenger_->send(pmsgout); - } - break; - case MSG_TYPE_ENGINE_STATUS: - { - auto pmsgout = make_shared(pmsgin->source_, name_, - MSG_TYPE_ENGINE_STATUS, - to_string(estate_)); - messenger_->send(pmsgout); - } - break; - case MSG_TYPE_TEST: - { - auto pmsgout = make_shared(pmsgin->source_, name_, - MSG_TYPE_TEST, - "test"); - messenger_->send(pmsgout); - LOG_DEBUG(logger,name_ <<" return test msg!"); - } - break; - case MSG_TYPE_SWITCH_TRADING_DAY: - switchday(); - break; - case MSG_TYPE_ENGINE_RESET: - reset(); - break; - default: - processbuf(); - break; - } - } - else{ - processbuf(); +void CtpMDEngine::reset() { + disconnect(); + releaseapi(); + CConfig::instance().readConfig(); + init(); + LOG_DEBUG(logger, name_ << " reset"); +} - } +void CtpMDEngine::init() { + // if (IEngine::msgq_send_ == nullptr){ + // lock_guard g(IEngine::sendlock_); + // IEngine::msgq_send_ = std::make_unique(MSGQ_PROTOCOL::PUB, CConfig::instance().SERVERPUB_URL); + // } + reqId_ = 0; + lastsubs_.clear(); + if (logger == nullptr) { + logger = SQLogger::getLogger("MDEngine.CTP"); + } - } + if (messenger_ == nullptr) { + messenger_ = std::make_unique(name_, CConfig::instance().SERVERSUB_URL); + msleep(100); } + ctpacc_ = CConfig::instance()._gatewaymap[name_]; + string path = CConfig::instance().logDir() + "/ctp/md"; + boost::filesystem::path dir(path.c_str()); + boost::filesystem::create_directory(dir); + // 创建API对象 + this->api_ = CThostFtdcMdApi::CreateFtdcMdApi(path.c_str()); + this->api_->RegisterSpi(this); + estate_ = DISCONNECTED; + auto pmsgs = make_shared(DESTINATION_ALL, name_, + MSG_TYPE_ENGINE_STATUS, + to_string(estate_)); + messenger_->send(pmsgs); + apiinited_ = false; + autoconnect_ = CConfig::instance().autoconnect; + LOG_DEBUG(logger, name_ << " inited, api version:" << CThostFtdcMdApi::GetApiVersion()); +} -////////////////////////////////////////////////////// outgoing function /////////////////////////////////////// - bool CtpMDEngine::connect() - { - inconnectaction_ = true; - int error; - int count = 0;// count numbers of tries, two many tries ends - - CThostFtdcReqUserLoginField loginField = CThostFtdcReqUserLoginField(); - while(estate_ != EState::LOGIN_ACK && estate_ != STOP){ - switch(estate_){ - case EState::DISCONNECTED: - if (!apiinited_){ - for (auto it:ctpacc_.md_address){ - // string ctp_data_address = it + ":" + to_string(ctpacc_.md_port); - this->api_->RegisterFront((char*)it.c_str()); - } - this->api_->Init(); - apiinited_ = true; +void CtpMDEngine::stop() { + int32_t tmp = disconnect(); + estate_ = EState::STOP; + auto pmsgs = make_shared(DESTINATION_ALL, name_, + MSG_TYPE_ENGINE_STATUS, + to_string(estate_)); + messenger_->send(pmsgs); + LOG_DEBUG(logger, name_ << " stoped"); +} + +void CtpMDEngine::start() { + while (estate_ != EState::STOP) { + auto pmsgin = messenger_->recv(); + bool processmsg = ((pmsgin != nullptr) \ + && (startwith(pmsgin->destination_, DESTINATION_ALL) || (pmsgin->destination_ == name_))); + // if (pmsgin == nullptr || (pmsgin->destination_ != name_ && ! startwith(pmsgin->destination_,DESTINATION_ALL)) ) + // continue; + if (processmsg) { + switch (pmsgin->msgtype_) { + case MSG_TYPE_ENGINE_CONNECT: + if (connect()) { + auto pmsgout = make_shared(pmsgin->source_, name_, + MSG_TYPE_INFO_ENGINE_MDCONNECTED, "CTP.MD connected."); + messenger_->send(pmsgout, 1); } - estate_ = CONNECTING; - {auto pmsgs = make_shared(DESTINATION_ALL, name_, - MSG_TYPE_ENGINE_STATUS, - to_string(estate_)); - messenger_->send(pmsgs);} - count++; - LOG_INFO(logger,name_ <<" api inited, connecting to front..."); break; - case EState::CONNECTING: - msleep(1000); - count++; + case MSG_TYPE_ENGINE_DISCONNECT: + disconnect(); + break; + case MSG_TYPE_SUBSCRIBE_MARKET_DATA: + if (estate_ == LOGIN_ACK) { + auto pmsgin2 = static_pointer_cast(pmsgin); + subscribe(pmsgin2->data_, pmsgin2->symtype_); + } else { + LOG_DEBUG(logger,name_ << " is not connected,can not subscribe!"); + auto pmsgout = make_shared(pmsgin->source_, name_, + MSG_TYPE_ERROR_ENGINENOTCONNECTED, + "ctp md is not connected,can not subscribe"); + messenger_->send(pmsgout); + } + break; + case MSG_TYPE_UNSUBSCRIBE: + if (estate_ == LOGIN_ACK){ + auto pmsgin2 = static_pointer_cast(pmsgin); + unsubscribe(pmsgin2->data_, pmsgin2->symtype_); + } else { + LOG_DEBUG(logger,name_ <<" is not connected,can not unsubscribe!"); + auto pmsgout = make_shared(pmsgin->source_, name_, + MSG_TYPE_ERROR_ENGINENOTCONNECTED, + "ctp md is not connected,can not unsubscribe"); + messenger_->send(pmsgout); + } + break; + case MSG_TYPE_ENGINE_STATUS: + { + auto pmsgout = make_shared(pmsgin->source_, name_, + MSG_TYPE_ENGINE_STATUS, + to_string(estate_)); + messenger_->send(pmsgout); + } break; - case EState::CONNECT_ACK: - LOG_INFO(logger,name_ <<" logining ...");//行情目前不需要认证 - // strcpy(loginField.BrokerID, ctpacc_.brokerid.c_str()); - // strcpy(loginField.UserID, ctpacc_.userid.c_str()); - // strcpy(loginField.Password, ctpacc_.password.c_str()); - ///用户登录请求 - error = this->api_->ReqUserLogin(&loginField, ++reqId_); - count++; - estate_ = EState::LOGINING; - if (error != 0){ - LOG_ERROR(logger,name_ <<" login error : "<(pmsgin->source_, name_, + MSG_TYPE_TEST, + "test"); + messenger_->send(pmsgout); + LOG_DEBUG(logger,name_ << " return test msg!"); } - {auto pmsgs = make_shared(DESTINATION_ALL, name_, - MSG_TYPE_ENGINE_STATUS, - to_string(estate_)); - messenger_->send(pmsgs);} break; - case EState::LOGINING: - msleep(500); + case MSG_TYPE_SWITCH_TRADING_DAY: + switchday(); + break; + case MSG_TYPE_ENGINE_RESET: + reset(); break; default: - msleep(100); + processbuf(); break; } - if(count >10){ - LOG_ERROR(logger,name_ <<" connect too many tries fails, give up connecting"); - //estate_ = EState::DISCONNECTED; - inconnectaction_ = false; - return false; - } + } else { + processbuf(); } - inconnectaction_ = false; - return true; } +} - bool CtpMDEngine::disconnect() { - if (estate_ == LOGIN_ACK){ - LOG_INFO(logger,name_ <<" logouting .."); - CThostFtdcUserLogoutField logoutField = CThostFtdcUserLogoutField(); - // strcpy(logoutField.BrokerID, ctpacc_.brokerid.c_str()); - // strcpy(logoutField.UserID, ctpacc_.userid.c_str()); - int error = this->api_->ReqUserLogout(&logoutField, ++reqId_); - estate_ = EState::LOGOUTING; - if (error != 0){ - LOG_ERROR(logger,name_ <<" logout error:"<api_->RegisterFront((char*)it.c_str()); + } + this->api_->Init(); + apiinited_ = true; + } + estate_ = CONNECTING; + {auto pmsgs = make_shared(DESTINATION_ALL, name_, + MSG_TYPE_ENGINE_STATUS, + to_string(estate_)); + messenger_->send(pmsgs);} + count++; + LOG_INFO(logger, name_ <<" api inited, connecting to front..."); + break; + case EState::CONNECTING: + msleep(1000); + count++; + break; + case EState::CONNECT_ACK: + LOG_INFO(logger, name_ << " logining ..."); // 行情目前不需要认证 + // strcpy(loginField.BrokerID, ctpacc_.brokerid.c_str()); + // strcpy(loginField.UserID, ctpacc_.userid.c_str()); + // strcpy(loginField.Password, ctpacc_.password.c_str()); + // 用户登录请求 + error = this->api_->ReqUserLogin(&loginField, ++reqId_); + count++; + estate_ = EState::LOGINING; + if (error != 0){ + LOG_ERROR(logger, name_ << " login error : " << error); + estate_ = EState::CONNECT_ACK; + msleep(1000); + } + {auto pmsgs = make_shared(DESTINATION_ALL, name_, + MSG_TYPE_ENGINE_STATUS, + to_string(estate_)); + messenger_->send(pmsgs);} + break; + case EState::LOGINING: + msleep(500); + break; + default: + msleep(100); + break; } - else{ - LOG_DEBUG(logger,name_ <<" is not connected(logined), cannot disconnect!"); + if (count >10) { + LOG_ERROR(logger,name_ << " connect too many tries fails, give up connecting"); + // estate_ = EState::DISCONNECTED; + inconnectaction_ = false; return false; } } + inconnectaction_ = false; + return true; +} - void CtpMDEngine::subscribe(const vector& symbol,SymbolType st) { - const int nCount = symbol.size(); - if (nCount == 0) - return; - vector tmpsymbol(symbol); - int error; - string sout; - if (st == ST_Full ) { - for (int i = 0; i < nCount; i++){ - tmpsymbol[i] = DataManager::instance().full2Ctp_[tmpsymbol[i]]; - } - } - char** insts = new char*[nCount]; - for (int i = 0; i < nCount; i++){ - insts[i] = (char*)tmpsymbol[i].c_str(); - if (find(lastsubs_.begin(),lastsubs_.end(),tmpsymbol[i]) == lastsubs_.end()) - lastsubs_.push_back(tmpsymbol[i]); - sout += tmpsymbol[i] +string("|"); - } - error = this->api_->SubscribeMarketData(insts, nCount); +bool CtpMDEngine::disconnect() { + if (estate_ == LOGIN_ACK) { + LOG_INFO(logger, name_ << " logouting .."); + CThostFtdcUserLogoutField logoutField = CThostFtdcUserLogoutField(); + // strcpy(logoutField.BrokerID, ctpacc_.brokerid.c_str()); + // strcpy(logoutField.UserID, ctpacc_.userid.c_str()); + int32_t error = this->api_->ReqUserLogout(&logoutField, ++reqId_); + estate_ = EState::LOGOUTING; if (error != 0) { - LOG_ERROR(logger,name_ <<" subscribe error "<& symbol,SymbolType st) { - const int nCount = symbol.size(); - if (nCount == 0) - return; - vector tmpsymbol(symbol); - int error; - string sout; - if (st == ST_Full ) { - for (int i = 0; i < nCount; i++){ - tmpsymbol[i] = DataManager::instance().full2Ctp_[tmpsymbol[i]]; - } - } - char** insts = new char*[nCount]; - for (int i = 0; i < nCount; i++){ - insts[i] = (char*)tmpsymbol[i].c_str(); - sout += tmpsymbol[i] +string("|"); - // remove last subcriptions - for(auto it = lastsubs_.begin();it != lastsubs_.end();) { - if (*it == tmpsymbol[i]) { - it = lastsubs_.erase(it); - } else { - ++it; - } - } - } - error = this->api_->UnSubscribeMarketData(insts, nCount); - if (error != 0) { - LOG_ERROR(logger,name_ <<" unsubscribe error "<& symbol,SymbolType st) { + const int32_t nCount = symbol.size(); + if (nCount == 0) + return; + vector tmpsymbol(symbol); + int32_t error; + string sout; + if (st == ST_Full) { + for (int32_t i = 0; i < nCount; i++) { + tmpsymbol[i] = DataManager::instance().full2Ctp_[tmpsymbol[i]]; } - delete[] insts; - LOG_INFO(logger,name_ <<" unsubcribe "<(DESTINATION_ALL, name_, - // MSG_TYPE_ENGINE_STATUS, - // to_string(estate_)); - // messenger_->send(pmsgout); - + char** insts = new char*[nCount]; + for (int32_t i = 0; i < nCount; i++) { + insts[i] = (char*)tmpsymbol[i].c_str(); + if (find(lastsubs_.begin(), lastsubs_.end(), tmpsymbol[i]) == lastsubs_.end()) + lastsubs_.push_back(tmpsymbol[i]); + sout += tmpsymbol[i] +string("|"); } - void CtpMDEngine::processbuf(){ - // save datamanager's security file - if (DataManager::instance().saveSecurityFile_){ - DataManager::instance().saveSecurityToFile(); - DataManager::instance().saveSecurityFile_ = false; - } + error = this->api_->SubscribeMarketData(insts, nCount); + if (error != 0) { + LOG_ERROR(logger, name_ << " subscribe error " << error); } + delete[] insts; + LOG_INFO(logger, name_ << " subcribe " << nCount << "|" << sout << "."); - /////////////////////////////////////////////// end of outgoing functions /////////////////////////////////////// +} - ////////////////////////////////////////////////////// callback function /////////////////////////////////////// - - void CtpMDEngine::OnFrontConnected() { - estate_ = CONNECT_ACK; // not used - auto pmsg = make_shared(DESTINATION_ALL, name_, - MSG_TYPE_ENGINE_STATUS, - to_string(estate_)); - messenger_->send(pmsg); - LOG_INFO(logger,name_ <<" frontend connected. "); - loginReqId_ = 0; - //autologin - if (autoconnect_ && !inconnectaction_ ){ - std::shared_ptr pmsg = make_shared(name_,name_,MSG_TYPE_ENGINE_CONNECT,"CTP.MD Front connected."); - CMsgqRMessenger::Send(pmsg); +void CtpMDEngine::unsubscribe(const vector& symbol,SymbolType st) { + const int32_t nCount = symbol.size(); + if (nCount == 0) + return; + vector tmpsymbol(symbol); + int32_t error; + string sout; + if (st == ST_Full) { + for (int32_t i = 0; i < nCount; i++){ + tmpsymbol[i] = DataManager::instance().full2Ctp_[tmpsymbol[i]]; } - } - - void CtpMDEngine::OnFrontDisconnected(int nReason) { - estate_ = CONNECTING; // automatic connecting - loginReqId_++; - if (loginReqId_ % 4000 == 0){ - auto pmsg = make_shared(DESTINATION_ALL, name_, - MSG_TYPE_ENGINE_STATUS, - to_string(estate_)); - messenger_->send(pmsg); - loginReqId_ = 0; - auto pmsgout = make_shared(DESTINATION_ALL, name_, - MSG_TYPE_INFO_ENGINE_MDDISCONNECTED, - fmt::format("Ctp md disconnected, nReason={}", nReason) - ); - messenger_->send(pmsgout); - LOG_INFO(logger,name_ <<" front is disconnected, nReason="<api_->UnSubscribeMarketData(insts, nCount); + if (error != 0) { + LOG_ERROR(logger, name_ << " unsubscribe error " << error); + } + delete[] insts; + LOG_INFO(logger, name_ << " unsubcribe " << nCount << "|" << sout << "."); +} - - } +void CtpMDEngine::timertask() { + timercount_++; + // // send status every second + // auto pmsgout = make_shared(DESTINATION_ALL, name_, + // MSG_TYPE_ENGINE_STATUS, + // to_string(estate_)); + // messenger_->send(pmsgout); - void CtpMDEngine::OnHeartBeatWarning(int nTimeLapse) { - LOG_INFO(logger,name_ <<" heartbeat overtime error, nTimeLapse="< pmsg = make_shared(name_, name_, MSG_TYPE_ENGINE_CONNECT, "CTP.MD Front connected."); + CMsgqRMessenger::Send(pmsg); } +} - void CtpMDEngine::OnRspUserLogin(CThostFtdcRspUserLoginField *pRspUserLogin, CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast) { - if (pRspInfo != nullptr && pRspInfo->ErrorID != 0){ - string errormsgutf8; - errormsgutf8 = boost::locale::conv::between( pRspInfo->ErrorMsg, "UTF-8", "GB18030" ); - LOG_ERROR(logger,name_ <<" login failed: ErrorID="<ErrorID<<"ErrorMsg="<(DESTINATION_ALL, name_, - MSG_TYPE_ENGINE_STATUS, - to_string(estate_)); - messenger_->send(pmsg); - LOG_INFO(logger,name_ <<" server user logged in," - <<"TradingDay="<TradingDay - <<"LoginTime="<LoginTime - <<"frontID="<FrontID - <<"sessionID="<SessionID - ); - // auto subscribe last securities - if (lastsubs_.size()) - subscribe(lastsubs_); - } - +void CtpMDEngine::OnFrontDisconnected(int32_t nReason) { + estate_ = CONNECTING; // automatic connecting + loginReqId_++; + if (loginReqId_ % 4000 == 0) { + auto pmsg = make_shared(DESTINATION_ALL, name_, + MSG_TYPE_ENGINE_STATUS, + to_string(estate_)); + messenger_->send(pmsg); + loginReqId_ = 0; + auto pmsgout = make_shared(DESTINATION_ALL, name_, + MSG_TYPE_INFO_ENGINE_MDDISCONNECTED, + fmt::format("Ctp md disconnected, nReason={}", nReason) + ); + messenger_->send(pmsgout); + LOG_INFO(logger, name_ << " front is disconnected, nReason=" << nReason); } - void CtpMDEngine::OnRspUserLogout(CThostFtdcUserLogoutField *pUserLogout, CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast) { - if (pRspInfo != nullptr && pRspInfo->ErrorID != 0){ - string errormsgutf8; - errormsgutf8 = boost::locale::conv::between( pRspInfo->ErrorMsg, "UTF-8", "GB18030" ); - LOG_ERROR(logger,name_ <<" logout failed: "<<"ErrorID="<ErrorID<<"ErrorMsg="<(DESTINATION_ALL, name_, - MSG_TYPE_ENGINE_STATUS, - to_string(estate_)); - messenger_->send(pmsg); - LOG_INFO(logger,name_ <<" Logout,BrokerID="<BrokerID<<" UserID="<UserID); - } - } +void CtpMDEngine::OnHeartBeatWarning(int32_t nTimeLapse) { + LOG_INFO(logger, name_ << " heartbeat overtime error, nTimeLapse=" << nTimeLapse); +} - ///订阅行情应答 - void CtpMDEngine::OnRspSubMarketData(CThostFtdcSpecificInstrumentField *pSpecificInstrument, CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast) { - bool bResult = (pRspInfo !=nullptr) && (pRspInfo->ErrorID != 0); - if (!bResult) { - LOG_INFO(logger,name_ <<" OnRspSubMarketData:InstrumentID="<InstrumentID); - } - else { - auto pmsgout = make_shared(DESTINATION_ALL, name_, - MSG_TYPE_ERROR_SUBSCRIBE, - GBKToUTF8(pRspInfo->ErrorMsg)); - LOG_ERROR(logger,name_ <<" OnRspSubMarketData failed: ErrorID="<ErrorID<<"ErrorMsg="<ErrorMsg)); - } +void CtpMDEngine::OnRspError(CThostFtdcRspInfoField *pRspInfo, int32_t nRequestID, bool bIsLast) { + LOG_ERROR(logger, name_ + << " OnRspError: ErrorID=" + << pRspInfo->ErrorID + << "ErrorMsg=" + <ErrorMsg)); +} +void CtpMDEngine::OnRspUserLogin( + CThostFtdcRspUserLoginField *pRspUserLogin, + CThostFtdcRspInfoField *pRspInfo, + int32_t nRequestID, + bool bIsLast) { + + if (pRspInfo != nullptr && pRspInfo->ErrorID != 0) { + string errormsgutf8; + errormsgutf8 = boost::locale::conv::between(pRspInfo->ErrorMsg, "UTF-8", "GB18030"); + LOG_ERROR(logger, name_ << " login failed: ErrorID=" << pRspInfo->ErrorID << "ErrorMsg=" << errormsgutf8); + } else { + estate_ = EState::LOGIN_ACK; + auto pmsg = make_shared(DESTINATION_ALL, name_, + MSG_TYPE_ENGINE_STATUS, + to_string(estate_)); + messenger_->send(pmsg); + LOG_INFO(logger, name_ <<" server user logged in," + << "TradingDay=" << pRspUserLogin->TradingDay + << "LoginTime=" << pRspUserLogin->LoginTime + << "frontID=" << pRspUserLogin->FrontID + << "sessionID=" << pRspUserLogin->SessionID + ); + // auto subscribe last securities + if (lastsubs_.size()) + subscribe(lastsubs_); } - - ///取消订阅行情应答 - void CtpMDEngine::OnRspUnSubMarketData(CThostFtdcSpecificInstrumentField *pSpecificInstrument, CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast) { - bool bResult = (pRspInfo !=nullptr) && (pRspInfo->ErrorID != 0); - if (!bResult) { - LOG_INFO(logger,name_ <<" OnRspUnSubMarketData:InstrumentID="<InstrumentID); - } - else { - LOG_ERROR(logger,name_ <<" OnRspUnSubMarketData failed: ErrorID="<ErrorID<<"ErrorMsg="<ErrorMsg)); - } +} +void CtpMDEngine::OnRspUserLogout( + CThostFtdcUserLogoutField *pUserLogout, + CThostFtdcRspInfoField *pRspInfo, + int32_t nRequestID, + bool bIsLast) { + + if (pRspInfo != nullptr && pRspInfo->ErrorID != 0) { + string errormsgutf8; + errormsgutf8 = boost::locale::conv::between(pRspInfo->ErrorMsg, "UTF-8", "GB18030"); + LOG_ERROR(logger, name_ << " logout failed: " << "ErrorID=" << pRspInfo->ErrorID << "ErrorMsg=" << errormsgutf8); + } else { + estate_ = EState::CONNECT_ACK; + auto pmsg = make_shared(DESTINATION_ALL, name_, + MSG_TYPE_ENGINE_STATUS, + to_string(estate_)); + messenger_->send(pmsg); + LOG_INFO(logger, name_ << " Logout,BrokerID=" << pUserLogout->BrokerID << " UserID=" << pUserLogout->UserID); } +} - ///订阅询价应答 - void CtpMDEngine::OnRspSubForQuoteRsp(CThostFtdcSpecificInstrumentField *pSpecificInstrument, CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast) { - bool bResult = (pRspInfo !=nullptr) && (pRspInfo->ErrorID != 0); - if (!bResult) { - LOG_INFO(logger,name_ <<" OnRspSubForQuoteRsp:InstrumentID="<InstrumentID); - } - else { - LOG_ERROR(logger,name_ <<" OnRspSubForQuotoRsp failed: ErrorID="<ErrorID<<"ErrorMsg="<ErrorMsg)); - } +///订阅行情应答 +void CtpMDEngine::OnRspSubMarketData( + CThostFtdcSpecificInstrumentField *pSpecificInstrument, + CThostFtdcRspInfoField *pRspInfo, + int32_t nRequestID, + bool bIsLast) { + + bool bResult = (pRspInfo !=nullptr) && (pRspInfo->ErrorID != 0); + if (!bResult) { + LOG_INFO(logger, name_ << " OnRspSubMarketData:InstrumentID=" << pSpecificInstrument->InstrumentID); + } else { + auto pmsgout = make_shared(DESTINATION_ALL, name_, + MSG_TYPE_ERROR_SUBSCRIBE, + GBKToUTF8(pRspInfo->ErrorMsg)); + LOG_ERROR(logger,name_ << " OnRspSubMarketData failed: ErrorID=" << pRspInfo->ErrorID << "ErrorMsg=" << GBKToUTF8(pRspInfo->ErrorMsg)); } +} - ///取消订阅询价应答 - void CtpMDEngine::OnRspUnSubForQuoteRsp(CThostFtdcSpecificInstrumentField *pSpecificInstrument, CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast) { - bool bResult = (pRspInfo != nullptr) && (pRspInfo->ErrorID != 0); - if (!bResult) { - LOG_INFO(logger,name_ <<" OnRspUnSubForQuoteRsp:InstrumentID="<InstrumentID); - } - else { - LOG_ERROR(logger,name_ <<" OnRspUnSubForQuoteRsp failed: ErrorID="<ErrorID<<"ErrorMsg="<ErrorMsg)); - } +// 取消订阅行情应答 +void CtpMDEngine::OnRspUnSubMarketData( + CThostFtdcSpecificInstrumentField *pSpecificInstrument, + CThostFtdcRspInfoField *pRspInfo, + int32_t nRequestID, + bool bIsLast) { + + bool bResult = (pRspInfo !=nullptr) && (pRspInfo->ErrorID != 0); + if (!bResult) { + LOG_INFO(logger,name_ << " OnRspUnSubMarketData:InstrumentID=" << pSpecificInstrument->InstrumentID); + } else { + LOG_ERROR(logger,name_ << " OnRspUnSubMarketData failed: ErrorID=" << pRspInfo->ErrorID << "ErrorMsg=" << GBKToUTF8(pRspInfo->ErrorMsg)); } +} - void CtpMDEngine::OnRtnDepthMarketData(CThostFtdcDepthMarketDataField *pDepthMarketData) { - if (pDepthMarketData == nullptr){ - LOG_DEBUG(logger,name_ <<" OnRtnDepthMarketData is nullptr"); - return; - } - - string arrivetime = ymdhmsf6(); - auto pk = make_shared(); - pk->data_.fullSymbol_ = DataManager::instance().ctp2Full_[pDepthMarketData->InstrumentID]; - char buf[64]; - char a[9]; - char b[9]; - strcpy(a,pDepthMarketData->ActionDay); - strcpy(b,pDepthMarketData->UpdateTime); - int msec = pDepthMarketData->UpdateMillisec; - if (startwith(pk->data_.fullSymbol_,"CZCE")){ - // add milliseconds for czce tick data - msec = getMilliSeconds(); - } - // std::sprintf(buf, "%c%c%c%c-%c%c-%c%c %c%c:%c%c:%c%c.%.3d", a[0],a[1],a[2],a[3],a[4],a[5],a[6],a[7],b[0],b[1],b[3],b[4],b[6],b[7],pDepthMarketData->UpdateMillisec ); - std::sprintf(buf, " %c%c:%c%c:%c%c.%.3d", b[0],b[1],b[3],b[4],b[6],b[7],msec ); - pk->destination_ = DESTINATION_ALL; - pk->source_ = name_; - pk->data_.time_ = ymd() + buf; - // pk->data_.fullSymbol_ = CConfig::instance().CtpSymbolToSecurityFullName(pDepthMarketData->InstrumentID); - pk->data_.price_ = pDepthMarketData->LastPrice; - pk->data_.size_ = pDepthMarketData->Volume; - pk->data_.bidPrice_[0] = pDepthMarketData->BidPrice1 == numeric_limits::max()? 0.0: pDepthMarketData->BidPrice1; - pk->data_.bidSize_[0] = pDepthMarketData->BidVolume1; - pk->data_.askPrice_[0] = pDepthMarketData->AskPrice1 == numeric_limits::max()? 0.0: pDepthMarketData->AskPrice1; - pk->data_.askSize_[0] = pDepthMarketData->AskVolume1; - if (startwith(pk->data_.fullSymbol_,"SHFE") ){ - // 5 level data - pk->msgtype_ = MSG_TYPE_TICK_L5; - pk->data_.depth_ = 5; - pk->data_.bidPrice_[1] = pDepthMarketData->BidPrice2 == numeric_limits::max()? 0.0: pDepthMarketData->BidPrice2; - pk->data_.bidSize_[1] = pDepthMarketData->BidVolume2; - pk->data_.askPrice_[1] = pDepthMarketData->AskPrice2 == numeric_limits::max()? 0.0: pDepthMarketData->AskPrice2; - pk->data_.askSize_[1] = pDepthMarketData->AskVolume2; - pk->data_.bidPrice_[2] = pDepthMarketData->BidPrice3 == numeric_limits::max()? 0.0: pDepthMarketData->BidPrice3; - pk->data_.bidSize_[2] = pDepthMarketData->BidVolume3; - pk->data_.askPrice_[2] = pDepthMarketData->AskPrice3 == numeric_limits::max()? 0.0: pDepthMarketData->AskPrice3; - pk->data_.askSize_[2] = pDepthMarketData->AskVolume3; - pk->data_.bidPrice_[3] = pDepthMarketData->BidPrice4 == numeric_limits::max()? 0.0: pDepthMarketData->BidPrice4; - pk->data_.bidSize_[3] = pDepthMarketData->BidVolume4; - pk->data_.askPrice_[3] = pDepthMarketData->AskPrice4 == numeric_limits::max()? 0.0: pDepthMarketData->AskPrice4; - pk->data_.askSize_[3] = pDepthMarketData->AskVolume4; - pk->data_.bidPrice_[4] = pDepthMarketData->BidPrice5 == numeric_limits::max()? 0.0: pDepthMarketData->BidPrice5; - pk->data_.bidSize_[4] = pDepthMarketData->BidVolume5; - pk->data_.askPrice_[4] = pDepthMarketData->AskPrice5 == numeric_limits::max()? 0.0: pDepthMarketData->AskPrice5; - pk->data_.askSize_[4] = pDepthMarketData->AskVolume5; - } - pk->data_.openInterest_ = pDepthMarketData->OpenInterest; - pk->data_.open_ = pDepthMarketData->OpenPrice == numeric_limits::max()? 0.0: pDepthMarketData->OpenPrice; - pk->data_.high_ = pDepthMarketData->HighestPrice == numeric_limits::max()? 0.0: pDepthMarketData->HighestPrice; - pk->data_.low_ = pDepthMarketData->LowestPrice == numeric_limits::max()? 0.0: pDepthMarketData->LowestPrice; - pk->data_.preClose_ = pDepthMarketData->PreClosePrice ; - pk->data_.upperLimitPrice_ = pDepthMarketData->UpperLimitPrice; - pk->data_.lowerLimitPrice_ = pDepthMarketData->LowerLimitPrice; - - messenger_->send(pk,1); - DataManager::instance().updateOrderBook(pk->data_); - LOG_DEBUG(logger,name_ <<" OnRtnDepthMarketData at"<UpdateMillisec - ); - - // DataManager::instance().recorder_.insertdb(k); - +// 订阅询价应答 +void CtpMDEngine::OnRspSubForQuoteRsp( + CThostFtdcSpecificInstrumentField *pSpecificInstrument, + CThostFtdcRspInfoField *pRspInfo, + int32_t nRequestID, + bool bIsLast) { + + bool bResult = (pRspInfo !=nullptr) && (pRspInfo->ErrorID != 0); + if (!bResult) { + LOG_INFO(logger, name_ << " OnRspSubForQuoteRsp:InstrumentID=" << pSpecificInstrument->InstrumentID); + } else { + LOG_ERROR(logger, name_ << " OnRspSubForQuotoRsp failed: ErrorID=" << pRspInfo->ErrorID << "ErrorMsg=" << GBKToUTF8(pRspInfo->ErrorMsg)); + } +} +// 取消订阅询价应答 +void CtpMDEngine::OnRspUnSubForQuoteRsp( + CThostFtdcSpecificInstrumentField *pSpecificInstrument, + CThostFtdcRspInfoField *pRspInfo, + int32_t nRequestID, + bool bIsLast) { + + bool bResult = (pRspInfo != nullptr) && (pRspInfo->ErrorID != 0); + if (!bResult) { + LOG_INFO(logger, name_ << " OnRspUnSubForQuoteRsp:InstrumentID=" << pSpecificInstrument->InstrumentID); + } else { + LOG_ERROR(logger, name_ << " OnRspUnSubForQuoteRsp failed: ErrorID=" << pRspInfo->ErrorID << "ErrorMsg=" << GBKToUTF8(pRspInfo->ErrorMsg)); + } +} +void CtpMDEngine::OnRtnDepthMarketData(CThostFtdcDepthMarketDataField *pDepthMarketData) { + if (pDepthMarketData == nullptr) { + LOG_DEBUG(logger, name_ << " OnRtnDepthMarketData is nullptr"); + return; } - ///询价通知 - void CtpMDEngine::OnRtnForQuoteRsp(CThostFtdcForQuoteRspField *pForQuoteRsp) { - LOG_INFO(logger,name_ <<" OnRtnForQuoteRsp:" - <<"TradingDay="<TradingDay - <<"ExchangeID="<ExchangeID - <<"InstrumentID="<InstrumentID - <<"ForQuoteSysID="<ForQuoteSysID - ); + string arrivetime = ymdhmsf6(); + auto pk = make_shared(); + pk->data_.fullSymbol_ = DataManager::instance().ctp2Full_[pDepthMarketData->InstrumentID]; + char buf[64]; + char a[9]; + char b[9]; + strcpy(a, pDepthMarketData->ActionDay); + strcpy(b, pDepthMarketData->UpdateTime); + int32_t msec = pDepthMarketData->UpdateMillisec; + if (startwith(pk->data_.fullSymbol_, "CZCE")) { + // add milliseconds for czce tick data + msec = getMilliSeconds(); + } + // std::sprintf(buf, "%c%c%c%c-%c%c-%c%c %c%c:%c%c:%c%c.%.3d", a[0],a[1],a[2],a[3],a[4],a[5],a[6],a[7],b[0],b[1],b[3],b[4],b[6],b[7],pDepthMarketData->UpdateMillisec ); + std::sprintf(buf, " %c%c:%c%c:%c%c.%.3d", b[0], b[1], b[3], b[4], b[6], b[7], msec); + pk->destination_ = DESTINATION_ALL; + pk->source_ = name_; + pk->data_.time_ = ymd() + buf; + // pk->data_.fullSymbol_ = CConfig::instance().CtpSymbolToSecurityFullName(pDepthMarketData->InstrumentID); + pk->data_.price_ = pDepthMarketData->LastPrice; + pk->data_.size_ = pDepthMarketData->Volume; + pk->data_.bidPrice_[0] = pDepthMarketData->BidPrice1 == numeric_limits::max()? 0.0: pDepthMarketData->BidPrice1; + pk->data_.bidSize_[0] = pDepthMarketData->BidVolume1; + pk->data_.askPrice_[0] = pDepthMarketData->AskPrice1 == numeric_limits::max()? 0.0: pDepthMarketData->AskPrice1; + pk->data_.askSize_[0] = pDepthMarketData->AskVolume1; + if (startwith(pk->data_.fullSymbol_, "SHFE")) { + // 5 level data + pk->msgtype_ = MSG_TYPE_TICK_L5; + pk->data_.depth_ = 5; + pk->data_.bidPrice_[1] = pDepthMarketData->BidPrice2 == numeric_limits::max()? 0.0: pDepthMarketData->BidPrice2; + pk->data_.bidSize_[1] = pDepthMarketData->BidVolume2; + pk->data_.askPrice_[1] = pDepthMarketData->AskPrice2 == numeric_limits::max()? 0.0: pDepthMarketData->AskPrice2; + pk->data_.askSize_[1] = pDepthMarketData->AskVolume2; + pk->data_.bidPrice_[2] = pDepthMarketData->BidPrice3 == numeric_limits::max()? 0.0: pDepthMarketData->BidPrice3; + pk->data_.bidSize_[2] = pDepthMarketData->BidVolume3; + pk->data_.askPrice_[2] = pDepthMarketData->AskPrice3 == numeric_limits::max()? 0.0: pDepthMarketData->AskPrice3; + pk->data_.askSize_[2] = pDepthMarketData->AskVolume3; + pk->data_.bidPrice_[3] = pDepthMarketData->BidPrice4 == numeric_limits::max()? 0.0: pDepthMarketData->BidPrice4; + pk->data_.bidSize_[3] = pDepthMarketData->BidVolume4; + pk->data_.askPrice_[3] = pDepthMarketData->AskPrice4 == numeric_limits::max()? 0.0: pDepthMarketData->AskPrice4; + pk->data_.askSize_[3] = pDepthMarketData->AskVolume4; + pk->data_.bidPrice_[4] = pDepthMarketData->BidPrice5 == numeric_limits::max()? 0.0: pDepthMarketData->BidPrice5; + pk->data_.bidSize_[4] = pDepthMarketData->BidVolume5; + pk->data_.askPrice_[4] = pDepthMarketData->AskPrice5 == numeric_limits::max()? 0.0: pDepthMarketData->AskPrice5; + pk->data_.askSize_[4] = pDepthMarketData->AskVolume5; } - /////////////////////////////////////////////// end of callback /////////////////////////////////////// + pk->data_.openInterest_ = pDepthMarketData->OpenInterest; + pk->data_.open_ = pDepthMarketData->OpenPrice == numeric_limits::max()? 0.0: pDepthMarketData->OpenPrice; + pk->data_.high_ = pDepthMarketData->HighestPrice == numeric_limits::max()? 0.0: pDepthMarketData->HighestPrice; + pk->data_.low_ = pDepthMarketData->LowestPrice == numeric_limits::max()? 0.0: pDepthMarketData->LowestPrice; + pk->data_.preClose_ = pDepthMarketData->PreClosePrice; + pk->data_.upperLimitPrice_ = pDepthMarketData->UpperLimitPrice; + pk->data_.lowerLimitPrice_ = pDepthMarketData->LowerLimitPrice; + + messenger_->send(pk, 1); + DataManager::instance().updateOrderBook(pk->data_); + LOG_DEBUG(logger,name_ <<" OnRtnDepthMarketData at"<UpdateMillisec + ); + + // DataManager::instance().recorder_.insertdb(k); +} +///询价通知 +void CtpMDEngine::OnRtnForQuoteRsp(CThostFtdcForQuoteRspField *pForQuoteRsp) { + LOG_INFO(logger, name_ <<" OnRtnForQuoteRsp:" + <<"TradingDay="<TradingDay + <<"ExchangeID="<ExchangeID + <<"InstrumentID="<InstrumentID + <<"ForQuoteSysID="<ForQuoteSysID + ); } + ////////// end of callback ///////////////////////// + +} // namespace StarQuant diff --git a/cppsrc/StarQuant/Engine/CtpMDEngine.h b/cppsrc/StarQuant/Engine/CtpMDEngine.h index 8ed43c60c..c6517bee5 100644 --- a/cppsrc/StarQuant/Engine/CtpMDEngine.h +++ b/cppsrc/StarQuant/Engine/CtpMDEngine.h @@ -1,75 +1,91 @@ -#ifndef _StarQuant_Engine_CtpMDEngine_H_ -#define _StarQuant_Engine_CtpMDEngine_H_ +/***************************************************************************** + * Copyright [2019] + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *****************************************************************************/ + +#ifndef CPPSRC_STARQUANT_ENGINE_CTPMDENGINE_H_ +#define CPPSRC_STARQUANT_ENGINE_CTPMDENGINE_H_ -#include #include #include #include +#include +#include +#include using std::mutex; using std::string; -using std::list; using std::vector; namespace StarQuant { - class CtpMDEngine : public IEngine, CThostFtdcMdSpi { - public: - string name_; - Gateway ctpacc_; +class CtpMDEngine : public IEngine, CThostFtdcMdSpi { + public: + string name_; + Gateway ctpacc_; + + CtpMDEngine(); + ~CtpMDEngine(); - CtpMDEngine(); - ~CtpMDEngine(); + virtual void init(); + virtual void start(); + virtual void stop(); - virtual void init(); - virtual void start(); - virtual void stop(); - - virtual bool connect() ; - virtual bool disconnect() ; - void releaseapi(); - void reset(); - void switchday(){}; - void timertask(); - void processbuf(); + virtual bool connect(); + virtual bool disconnect(); + void releaseapi(); + void reset(); + void switchday() {} + void timertask(); + void processbuf(); - void subscribe(const vector& symbols,SymbolType st = ST_Ctp) ; - void unsubscribe(const vector& symbols,SymbolType st = ST_Ctp) ; + void subscribe(const vector& symbols, SymbolType st = ST_Ctp); + void unsubscribe(const vector& symbols, SymbolType st = ST_Ctp); - public: - virtual void OnFrontConnected(); - virtual void OnFrontDisconnected(int nReason); - virtual void OnHeartBeatWarning(int nTimeLapse); - ///登录请求响应 - virtual void OnRspUserLogin(CThostFtdcRspUserLoginField *pRspUserLogin, CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast); - ///登出请求响应 - virtual void OnRspUserLogout(CThostFtdcUserLogoutField *pUserLogout, CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast); - ///错误应答 - virtual void OnRspError(CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast); - ///订阅行情应答 - virtual void OnRspSubMarketData(CThostFtdcSpecificInstrumentField *pSpecificInstrument, CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast); - ///取消订阅行情应答 - virtual void OnRspUnSubMarketData(CThostFtdcSpecificInstrumentField *pSpecificInstrument, CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast); - ///订阅询价应答 - virtual void OnRspSubForQuoteRsp(CThostFtdcSpecificInstrumentField *pSpecificInstrument, CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast); - ///取消订阅询价应答 - virtual void OnRspUnSubForQuoteRsp(CThostFtdcSpecificInstrumentField *pSpecificInstrument, CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast); - ///深度行情通知 - virtual void OnRtnDepthMarketData(CThostFtdcDepthMarketDataField *pDepthMarketData); - ///询价通知 - virtual void OnRtnForQuoteRsp(CThostFtdcForQuoteRspField *pForQuoteRsp); + public: + virtual void OnFrontConnected(); + virtual void OnFrontDisconnected(int32_t nReason); + virtual void OnHeartBeatWarning(int32_t nTimeLapse); + // /登录请求响应 + virtual void OnRspUserLogin(CThostFtdcRspUserLoginField *pRspUserLogin, CThostFtdcRspInfoField *pRspInfo, int32_t nRequestID, bool bIsLast); + // /登出请求响应 + virtual void OnRspUserLogout(CThostFtdcUserLogoutField *pUserLogout, CThostFtdcRspInfoField *pRspInfo, int32_t nRequestID, bool bIsLast); + // /错误应答 + virtual void OnRspError(CThostFtdcRspInfoField *pRspInfo, int32_t nRequestID, bool bIsLast); + // /订阅行情应答 + virtual void OnRspSubMarketData(CThostFtdcSpecificInstrumentField *pSpecificInstrument, CThostFtdcRspInfoField *pRspInfo, int32_t nRequestID, bool bIsLast); + // /取消订阅行情应答 + virtual void OnRspUnSubMarketData(CThostFtdcSpecificInstrumentField *pSpecificInstrument, CThostFtdcRspInfoField *pRspInfo, int32_t nRequestID, bool bIsLast); + // /订阅询价应答 + virtual void OnRspSubForQuoteRsp(CThostFtdcSpecificInstrumentField *pSpecificInstrument, CThostFtdcRspInfoField *pRspInfo, int32_t nRequestID, bool bIsLast); + // /取消订阅询价应答 + virtual void OnRspUnSubForQuoteRsp(CThostFtdcSpecificInstrumentField *pSpecificInstrument, CThostFtdcRspInfoField *pRspInfo, int32_t nRequestID, bool bIsLast); + // /深度行情通知 + virtual void OnRtnDepthMarketData(CThostFtdcDepthMarketDataField *pDepthMarketData); + // /询价通知 + virtual void OnRtnForQuoteRsp(CThostFtdcForQuoteRspField *pForQuoteRsp); - private: - int loginReqId_; - int reqId_; - CThostFtdcMdApi* api_; - bool apiinited_; - bool inconnectaction_; - bool autoconnect_; - vector lastsubs_; - int timercount_; - }; -} + private: + int32_t loginReqId_; + int32_t reqId_; + CThostFtdcMdApi* api_; + bool apiinited_; + bool inconnectaction_; + bool autoconnect_; + vector lastsubs_; + int32_t timercount_; +}; +} // namespace StarQuant -#endif +#endif // CPPSRC_STARQUANT_ENGINE_CTPMDENGINE_H_ diff --git a/cppsrc/StarQuant/Engine/CtpTDEngine.cpp b/cppsrc/StarQuant/Engine/CtpTDEngine.cpp index 363cc4c79..7b11f34a1 100644 --- a/cppsrc/StarQuant/Engine/CtpTDEngine.cpp +++ b/cppsrc/StarQuant/Engine/CtpTDEngine.cpp @@ -1,9 +1,17 @@ -#include -#include -#include -#include - -#include +/***************************************************************************** + * Copyright [2019] + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *****************************************************************************/ #include #include @@ -14,1528 +22,1038 @@ #include #include #include +#include + +#include +#include +#include +#include + using namespace std; -namespace StarQuant -{ - //extern std::atomic gShutdown; - - CtpTDEngine::CtpTDEngine(const string& gw) - : needauthentication_(false) - , needsettlementconfirm_(true) - , issettleconfirmed_(false) - , m_brokerOrderId_(0) - , reqId_(0) - , orderRef_(0) - , frontID_(0) - , sessionID_(0) - , apiinited_(false) - , inconnectaction_(false) - , autoconnect_(false) - , autoqry_(false) - , timercount_(0) - { - lastQryTime_ = getMicroTime(); - name_ = gw; - init(); - - } - CtpTDEngine::~CtpTDEngine() { - if (estate_ != STOP) - stop(); - releaseapi(); +namespace StarQuant { +// extern std::atomic gShutdown; + +CtpTDEngine::CtpTDEngine(const string& gw) + : needauthentication_(false) + , needsettlementconfirm_(true) + , issettleconfirmed_(false) + , m_brokerOrderId_(0) + , reqId_(0) + , orderRef_(0) + , frontID_(0) + , sessionID_(0) + , apiinited_(false) + , inconnectaction_(false) + , autoconnect_(false) + , autoqry_(false) + , timercount_(0) { + lastQryTime_ = getMicroTime(); + name_ = gw; + init(); +} + +CtpTDEngine::~CtpTDEngine() { + if (estate_ != STOP) + stop(); + releaseapi(); +} + +void CtpTDEngine::releaseapi() { + if (api_ != nullptr) { + // this->api_->Join(); + msleep(1000); + this->api_->RegisterSpi(nullptr); + if (apiinited_) + this->api_->Release(); // api must init() or will segfault + this->api_ = nullptr; } - - void CtpTDEngine::releaseapi(){ - if (api_ != nullptr){ - // this->api_->Join(); - msleep(1000); - this->api_->RegisterSpi(nullptr); - if (apiinited_) - this->api_->Release();// api must init() or will segfault - this->api_ = nullptr; - } +} + +void CtpTDEngine::reset() { + disconnect(); + releaseapi(); + CConfig::instance().readConfig(); + init(); + LOG_DEBUG(logger, name_ << " reset"); +} + +void CtpTDEngine::init() { + if (logger == nullptr) { + logger = SQLogger::getLogger("TDEngine.CTP"); } - - void CtpTDEngine::reset(){ - disconnect(); - releaseapi(); - CConfig::instance().readConfig(); - init(); - LOG_DEBUG(logger,name_ <<" reset"); - } - - void CtpTDEngine::init(){ - if(logger == nullptr){ - logger = SQLogger::getLogger("TDEngine.CTP"); - } - if (messenger_ == nullptr){ - messenger_ = std::make_unique(name_, CConfig::instance().SERVERSUB_URL); - msleep(100); - } - string acc = accAddress(name_); - ctpacc_ = CConfig::instance()._gatewaymap[name_]; - string path = CConfig::instance().logDir() + "/ctp/td/" + acc; - boost::filesystem::path dir(path.c_str()); - boost::filesystem::create_directory(dir); - this->api_ = CThostFtdcTraderApi::CreateFtdcTraderApi(path.c_str()); - this->api_->RegisterSpi(this); - if (ctpacc_.auth_code == "NA" || ctpacc_.auth_code.empty() ) { - needauthentication_ = false; - } - else { - needauthentication_ = true; - } - estate_ = DISCONNECTED; - auto pmsgs = make_shared(DESTINATION_ALL, name_, - MSG_TYPE_ENGINE_STATUS, - to_string(estate_)); - messenger_->send(pmsgs); - apiinited_ = false; - autoconnect_ = CConfig::instance().autoconnect; - autoqry_ = CConfig::instance().autoqry; - LOG_DEBUG(logger, name_ <<" inited, api version:"<(name_, CConfig::instance().SERVERSUB_URL); + msleep(100); } - void CtpTDEngine::stop(){ - int tmp = disconnect(); - estate_ = EState::STOP; - auto pmsgs = make_shared(DESTINATION_ALL, name_, - MSG_TYPE_ENGINE_STATUS, - to_string(estate_)); - messenger_->send(pmsgs); - LOG_DEBUG(logger, name_ <<" stoped"); - + string acc = accAddress(name_); + ctpacc_ = CConfig::instance()._gatewaymap[name_]; + string path = CConfig::instance().logDir() + "/ctp/td/" + acc; + boost::filesystem::path dir(path.c_str()); + boost::filesystem::create_directory(dir); + this->api_ = CThostFtdcTraderApi::CreateFtdcTraderApi(path.c_str()); + this->api_->RegisterSpi(this); + if (ctpacc_.auth_code == "NA" || ctpacc_.auth_code.empty()) { + needauthentication_ = false; + } else { + needauthentication_ = true; } - - void CtpTDEngine::start(){ - while(estate_ != EState::STOP){ - auto pmsgin = messenger_->recv(1); - bool processmsg = ((pmsgin != nullptr) && ( startwith(pmsgin->destination_,DESTINATION_ALL) || (pmsgin->destination_ == name_ ))); - // if (pmsgin == nullptr || (pmsgin->destination_ != name_ && ! startwith(pmsgin->destination_,DESTINATION_ALL) ) ) - // continue; - if (processmsg){ - switch (pmsgin->msgtype_) - { - case MSG_TYPE_ENGINE_CONNECT: - if (connect()){ - auto pmsgout = make_shared(pmsgin->source_, name_, - MSG_TYPE_INFO_ENGINE_TDCONNECTED, - fmt::format("{} logined,ready to request.",name_) - ); - messenger_->send(pmsgout,1); - } - break; - case MSG_TYPE_ENGINE_DISCONNECT: - disconnect(); - break; - case MSG_TYPE_ORDER: - case MSG_TYPE_ORDER_CTP: - if (pmsgin->destination_ != name_) - break; - if (estate_ == LOGIN_ACK){ - insertOrder(static_pointer_cast(pmsgin)); - } - else{ - LOG_DEBUG(logger,name_ <<" is not connected,can not insert order!"); - auto pmsgout = make_shared(pmsgin->source_, name_, - MSG_TYPE_ERROR_ENGINENOTCONNECTED, - fmt::format("{} is not connected,can not insert order!", name_) - ); - messenger_->send(pmsgout); - } - break; - case MSG_TYPE_CANCEL_ORDER: - case MSG_TYPE_ORDER_ACTION: - case MSG_TYPE_ORDER_ACTION_CTP: - if (pmsgin->destination_ != name_) - break; - if (estate_ == LOGIN_ACK){ - cancelOrder(static_pointer_cast(pmsgin)); - } - else{ - LOG_DEBUG(logger,name_ <<" is not connected,can not cancel order!"); - auto pmsgout = make_shared(pmsgin->source_, name_, - MSG_TYPE_ERROR_ENGINENOTCONNECTED, - fmt::format("{} is not connected,can not cancel order!", name_) - ); - messenger_->send(pmsgout); - } - break; - case MSG_TYPE_CANCEL_ALL: - if (pmsgin->destination_ != name_) - break; - if (estate_ == LOGIN_ACK){ - cancelAll(static_pointer_cast(pmsgin)); - } - else{ - LOG_DEBUG(logger,name_ <<" is not connected,can not cancel all!"); - auto pmsgout = make_shared(pmsgin->source_, name_, - MSG_TYPE_ERROR_ENGINENOTCONNECTED, - fmt::format("{} is not connected,can not cancel all!", name_ ) - ); - messenger_->send(pmsgout); - } - break; - case MSG_TYPE_QRY_POS: - case MSG_TYPE_QRY_ACCOUNT: - case MSG_TYPE_QRY_CONTRACT: - case MSG_TYPE_QRY_ORDER: - case MSG_TYPE_QRY_TRADE: - case MSG_TYPE_QRY_POSDETAIL: - if (pmsgin->destination_ != name_) - break; - if (estate_ == LOGIN_ACK){ - qryBuffer_.push(pmsgin); - } - else{ - LOG_DEBUG(logger,name_ <<" is not connected,can not qry!"); - auto pmsgout = make_shared(pmsgin->source_, name_, - MSG_TYPE_ERROR_ENGINENOTCONNECTED, - fmt::format("{} is not connected,can not qry !",name_) - ); - messenger_->send(pmsgout); - } - break; - case MSG_TYPE_ENGINE_STATUS: - { - auto pmsgout = make_shared(pmsgin->source_, name_, - MSG_TYPE_ENGINE_STATUS, - to_string(estate_)); - messenger_->send(pmsgout); - } - break; - case MSG_TYPE_TEST: - { - auto pmsgout = make_shared(pmsgin->source_, name_, - MSG_TYPE_TEST, - "test"); - messenger_->send(pmsgout); - LOG_DEBUG(logger,name_ <<" return test msg!"); - } + estate_ = DISCONNECTED; + auto pmsgs = make_shared(DESTINATION_ALL, name_, + MSG_TYPE_ENGINE_STATUS, + to_string(estate_)); + messenger_->send(pmsgs); + apiinited_ = false; + autoconnect_ = CConfig::instance().autoconnect; + autoqry_ = CConfig::instance().autoqry; + LOG_DEBUG(logger, name_ << " inited, api version:" << CThostFtdcTraderApi::GetApiVersion()); +} +void CtpTDEngine::stop() { + int32_t tmp = disconnect(); + estate_ = EState::STOP; + auto pmsgs = make_shared(DESTINATION_ALL, name_, + MSG_TYPE_ENGINE_STATUS, + to_string(estate_)); + messenger_->send(pmsgs); + LOG_DEBUG(logger, name_ << " stoped"); +} + +void CtpTDEngine::start() { + while (estate_ != EState::STOP) { + auto pmsgin = messenger_->recv(1); + bool processmsg = ((pmsgin != nullptr) + && ( startwith(pmsgin->destination_,DESTINATION_ALL) || (pmsgin->destination_ == name_ ))); + // if (pmsgin == nullptr || (pmsgin->destination_ != name_ && ! startwith(pmsgin->destination_,DESTINATION_ALL) ) ) + // continue; + if (processmsg) { + switch (pmsgin->msgtype_) { + case MSG_TYPE_ENGINE_CONNECT: + if (connect()) { + auto pmsgout = make_shared(pmsgin->source_, name_, + MSG_TYPE_INFO_ENGINE_TDCONNECTED, + fmt::format("{} logined,ready to request.", name_) + ); + messenger_->send(pmsgout, 1); + } + break; + case MSG_TYPE_ENGINE_DISCONNECT: + disconnect(); + break; + case MSG_TYPE_ORDER: + case MSG_TYPE_ORDER_CTP: + if (pmsgin->destination_ != name_) break; - case MSG_TYPE_SWITCH_TRADING_DAY: - switchday(); - break; - case MSG_TYPE_ENGINE_RESET: - reset(); + if (estate_ == LOGIN_ACK) { + insertOrder(static_pointer_cast(pmsgin)); + } else { + LOG_DEBUG(logger, name_ << " is not connected,can not insert order!"); + auto pmsgout = make_shared(pmsgin->source_, name_, + MSG_TYPE_ERROR_ENGINENOTCONNECTED, + fmt::format("{} is not connected,can not insert order!", name_) + ); + messenger_->send(pmsgout); + } + break; + case MSG_TYPE_CANCEL_ORDER: + case MSG_TYPE_ORDER_ACTION: + case MSG_TYPE_ORDER_ACTION_CTP: + if (pmsgin->destination_ != name_) break; - case MSG_TYPE_TIMER: - timertask(); - break; - default: - processbuf(); + if (estate_ == LOGIN_ACK) { + cancelOrder(static_pointer_cast(pmsgin)); + } else { + LOG_DEBUG(logger, name_ << " is not connected,can not cancel order!"); + auto pmsgout = make_shared(pmsgin->source_, name_, + MSG_TYPE_ERROR_ENGINENOTCONNECTED, + fmt::format("{} is not connected,can not cancel order!", name_) + ); + messenger_->send(pmsgout); + } + break; + case MSG_TYPE_CANCEL_ALL: + if (pmsgin->destination_ != name_) break; - } - } - else{ - processbuf(); - } - - } - } - - bool CtpTDEngine::connect(){ - inconnectaction_ = true; - THOST_TE_RESUME_TYPE privatetype = THOST_TERT_QUICK;// THOST_TERT_RESTART,THOST_TERT_RESUME, THOST_TERT_QUICK - THOST_TE_RESUME_TYPE publictype = THOST_TERT_QUICK;// THOST_TERT_RESTART,THOST_TERT_RESUME, THOST_TERT_QUICK - if (ctpacc_.publicstream == "restart"){ - publictype = THOST_TERT_RESTART; - } - else if (ctpacc_.publicstream == "resume"){ - publictype = THOST_TERT_RESUME; - } - if (ctpacc_.privatestream == "restart"){ - privatetype = THOST_TERT_RESTART; - } - else if (ctpacc_.privatestream == "resume"){ - privatetype = THOST_TERT_RESUME; - } - int error; - int count = 0;// count numbers of tries, two many tries ends - CThostFtdcReqUserLoginField loginField = CThostFtdcReqUserLoginField(); - while (estate_ != LOGIN_ACK && estate_ != STOP){ - switch (estate_){ - case DISCONNECTED: - if (!apiinited_){ - this->api_->SubscribePrivateTopic(privatetype); - this->api_->SubscribePublicTopic(publictype); - for (auto it:ctpacc_.td_address){ - // string ctp_td_address = it + ":" + to_string(ctpacc_.td_port); - this->api_->RegisterFront((char*)it.c_str()); - } - this->api_->Init(); - apiinited_ = true; + if (estate_ == LOGIN_ACK) { + cancelAll(static_pointer_cast(pmsgin)); + } else { + LOG_DEBUG(logger, name_ << " is not connected,can not cancel all!"); + auto pmsgout = make_shared(pmsgin->source_, name_, + MSG_TYPE_ERROR_ENGINENOTCONNECTED, + fmt::format("{} is not connected,can not cancel all!", name_ ) + ); + messenger_->send(pmsgout); } - estate_ = CONNECTING; - {auto pmsgs = make_shared(DESTINATION_ALL, name_, - MSG_TYPE_ENGINE_STATUS, - to_string(estate_)); - messenger_->send(pmsgs);} - LOG_INFO(logger,name_ <<" api inited, connect Front!"); - count++; break; - case CONNECTING: - msleep(1000); - count++; + case MSG_TYPE_QRY_POS: + case MSG_TYPE_QRY_ACCOUNT: + case MSG_TYPE_QRY_CONTRACT: + case MSG_TYPE_QRY_ORDER: + case MSG_TYPE_QRY_TRADE: + case MSG_TYPE_QRY_POSDETAIL: + if (pmsgin->destination_ != name_) + break; + if (estate_ == LOGIN_ACK) { + qryBuffer_.push(pmsgin); + } else { + LOG_DEBUG(logger, name_ << " is not connected,can not qry!"); + auto pmsgout = make_shared(pmsgin->source_, name_, + MSG_TYPE_ERROR_ENGINENOTCONNECTED, + fmt::format("{} is not connected,can not qry !",name_) + ); + messenger_->send(pmsgout); + } break; - case CONNECT_ACK: - if(needauthentication_){ - CThostFtdcReqAuthenticateField authField; - strcpy(authField.UserID, ctpacc_.userid.c_str()); - strcpy(authField.BrokerID, ctpacc_.brokerid.c_str()); - strcpy(authField.AuthCode, ctpacc_.auth_code.c_str()); - strcpy(authField.UserProductInfo,ctpacc_.productinfo.c_str()); - strcpy(authField.AppID, ctpacc_.appid.c_str()); - LOG_INFO(logger,name_ <<" authenticating :" - <api_->ReqAuthenticate(&authField, reqId_++); - count++; - estate_ = AUTHENTICATING; - if (error != 0){ - LOG_ERROR(logger,name_ <<" authenticate error"); - estate_ = CONNECT_ACK; - msleep(1000); - } + case MSG_TYPE_ENGINE_STATUS: + { + auto pmsgout = make_shared(pmsgin->source_, name_, + MSG_TYPE_ENGINE_STATUS, + to_string(estate_)); + messenger_->send(pmsgout); } - else{ - estate_ = AUTHENTICATE_ACK; + break; + case MSG_TYPE_TEST: + { + auto pmsgout = make_shared(pmsgin->source_, name_, + MSG_TYPE_TEST, + "test"); + messenger_->send(pmsgout); + LOG_DEBUG(logger, name_ << " return test msg!"); } - {auto pmsgs = make_shared(DESTINATION_ALL, name_, - MSG_TYPE_ENGINE_STATUS, - to_string(estate_)); - messenger_->send(pmsgs);} break; - case AUTHENTICATING: - msleep(100); + case MSG_TYPE_SWITCH_TRADING_DAY: + switchday(); break; - case AUTHENTICATE_ACK: - LOG_INFO(logger,name_ <<" logining ..."); - strcpy(loginField.BrokerID, ctpacc_.brokerid.c_str()); - strcpy(loginField.UserID, ctpacc_.userid.c_str()); - strcpy(loginField.Password, ctpacc_.password.c_str()); - strcpy(loginField.UserProductInfo, ctpacc_.productinfo.c_str()); - error = this->api_->ReqUserLogin(&loginField, reqId_++); - // cout<< loginField.BrokerID <(DESTINATION_ALL, name_, - MSG_TYPE_ENGINE_STATUS, - to_string(estate_)); - messenger_->send(pmsgs);} + case MSG_TYPE_ENGINE_RESET: + reset(); break; - case LOGINING: - count++; - msleep(500); + case MSG_TYPE_TIMER: + timertask(); break; default: + processbuf(); break; } - if(count > 20){ - LOG_ERROR(logger,name_ <<" too many tries fails, give up connecting"); - //estate_ = EState::DISCONNECTED; - inconnectaction_ = false; - return false; - } + } else { + processbuf(); } - inconnectaction_ = false; - auto pmsgs = make_shared(DESTINATION_ALL, name_, - MSG_TYPE_ENGINE_STATUS, - to_string(estate_)); - messenger_->send(pmsgs); - // qry instrument only once everyday - if ( ! DataManager::instance().contractUpdated_ ){ - CThostFtdcQryInstrumentField req = {0}; - error = this->api_->ReqQryInstrument(&req,reqId_++); - DataManager::instance().contractUpdated_ = true; - } - return true; } - - bool CtpTDEngine::disconnect(){ - inconnectaction_ = true; - if(estate_ == LOGIN_ACK){ - LOG_INFO(logger,name_ <<" logouting .."); - CThostFtdcUserLogoutField logoutField = CThostFtdcUserLogoutField(); - strcpy(logoutField.BrokerID, ctpacc_.brokerid.c_str()); - strcpy(logoutField.UserID, ctpacc_.userid.c_str()); - int error = this->api_->ReqUserLogout(&logoutField, reqId_++); - estate_ = EState::LOGOUTING; - if (error != 0){ - LOG_ERROR(logger,name_ <<" logout error:"<(DESTINATION_ALL, name_, - // MSG_TYPE_ENGINE_STATUS, - // to_string(estate_)); - // messenger_->send(pmsgout); - - //auto qyr pos and acc - if (estate_ == LOGIN_ACK && autoqry_ ){ - if (timercount_ %2 == 0){ - auto pmsgout = make_shared(name_,name_,MSG_TYPE_QRY_ACCOUNT); - //queryAccount(pmsgout); - qryBuffer_.push(pmsgout); - } - else{ - auto pmsgout = make_shared(name_,name_,MSG_TYPE_QRY_POS); - //queryPosition(pmsgout); - qryBuffer_.push(pmsgout); - } - } - - } - - void CtpTDEngine::processbuf(){ - // check local order - checkLocalOrders(); - - // pop qrybuffer - if (!qryBuffer_.empty()){ - uint64_t timenow = getMicroTime(); - if ( (timenow - lastQryTime_) > 1000000 ) { - lastQryTime_ = timenow; - auto pmsgin = qryBuffer_.front(); - switch (pmsgin->msgtype_) + int32_t error; + int32_t count = 0;// count numbers of tries, two many tries ends + CThostFtdcReqUserLoginField loginField = CThostFtdcReqUserLoginField(); + while (estate_ != LOGIN_ACK && estate_ != STOP) { + switch (estate_) { + case DISCONNECTED: + if (!apiinited_) { + this->api_->SubscribePrivateTopic(privatetype); + this->api_->SubscribePublicTopic(publictype); + for (auto it : ctpacc_.td_address) { + // string ctp_td_address = it + ":" + to_string(ctpacc_.td_port); + this->api_->RegisterFront((char*)it.c_str()); + } + this->api_->Init(); + apiinited_ = true; + } + estate_ = CONNECTING; { - case MSG_TYPE_QRY_POS: - queryPosition(pmsgin); - break; - case MSG_TYPE_QRY_ACCOUNT: - queryAccount(pmsgin); - break; - case MSG_TYPE_QRY_CONTRACT: - queryContract(static_pointer_cast(pmsgin)); - break; - case MSG_TYPE_QRY_ORDER: - queryOrder(pmsgin); - break; - case MSG_TYPE_QRY_POSDETAIL: - queryPositionDetail(pmsgin); - break; - case MSG_TYPE_QRY_TRADE: - queryTrade(pmsgin); - break; - default: - break; + auto pmsgs = make_shared(DESTINATION_ALL, name_, + MSG_TYPE_ENGINE_STATUS, + to_string(estate_)); + messenger_->send(pmsgs); } - qryBuffer_.pop(); - } - } - } - - void CtpTDEngine::checkLocalOrders(){ - // check local order - if (localorders_.empty()) - return; - for (auto it = localorders_.begin();it != localorders_.end();) - { - auto pmsg = (*it); - double stopprice = pmsg->data_.price_; - bool directionbuy = (pmsg->data_.quantity_ >0) ; - string fullsym = pmsg->data_.fullSymbol_; - if (DataManager::instance().orderBook_.count(fullsym) == 0 ){ - ++it; - continue; - } - double lastprice = DataManager::instance().orderBook_[fullsym].price_; - bool longtriggered = ( directionbuy ) && (lastprice >= stopprice ); - bool shorttriggered = ( !directionbuy ) && (lastprice <= stopprice ); - if (longtriggered || shorttriggered){ - //touched - auto o = OrderManager::instance().retrieveOrderFromServerOrderId(pmsg->data_.serverOrderID_); - if (RiskManager::instance().passOrder(o)){ - strcpy(pmsg->data_.orderField_.OrderRef, to_string(orderRef_).c_str()); - pmsg->data_.localNo_ = to_string(frontID_) + "." + to_string(sessionID_) + "." + to_string(orderRef_++) ; - o->localNo_ = pmsg->data_.localNo_; - lock_guard gs(orderStatus_mtx); - o->orderStatus_ = OrderStatus::OS_Submitted; - int error = api_->ReqOrderInsert(&(pmsg->data_.orderField_), reqId_++); - LOG_INFO(logger, name_<<"Local Order Touched: clientorderid ="<data_.clientOrderID_<<" FullSymbol = "<data_.fullSymbol_); - if (error != 0){ - o->orderStatus_ = OrderStatus::OS_Error; - //send error msg - auto pmsgout = make_shared(pmsg->source_, name_, - MSG_TYPE_ERROR_INSERTORDER, - fmt::format("Insert order error, order_server_id:{}",o->serverOrderID_)); - messenger_->send(pmsgout); - LOG_ERROR(logger,name_<<" insertOrder error: "<api_->ReqAuthenticate(&authField, reqId_++); + count++; + estate_ = AUTHENTICATING; + if (error != 0) { + LOG_ERROR(logger, name_ << " authenticate error"); + estate_ = CONNECT_ACK; + msleep(1000); } - //send OrderStatus - auto pmsgout = make_shared(pmsg->source_,name_); - pmsgout->set(o); - messenger_->send(pmsgout); - // delete this localorder, update iterator - it = localorders_.erase(it); + } else { + estate_ = AUTHENTICATE_ACK; } - else{ - ++it; + { + auto pmsgs = make_shared(DESTINATION_ALL, name_, + MSG_TYPE_ENGINE_STATUS, + to_string(estate_)); + messenger_->send(pmsgs); } - - } - else{ - ++it; - } - - } - - } - - void CtpTDEngine::insertOrder(shared_ptr pmsg) { - string exchangeid; - pmsg->data_.fullSymbol_ = DataManager::instance().ctp2Full_[pmsg->data_.orderField_.InstrumentID]; - exchangeid = extractExchangeID(pmsg->data_.fullSymbol_); - strcpy(pmsg->data_.orderField_.InvestorID, ctpacc_.userid.c_str()); - strcpy(pmsg->data_.orderField_.UserID, ctpacc_.userid.c_str()); - strcpy(pmsg->data_.orderField_.BrokerID, ctpacc_.brokerid.c_str()); - strcpy(pmsg->data_.orderField_.ExchangeID, exchangeid.c_str()); - lock_guard g(oid_mtx); - pmsg->data_.serverOrderID_ = m_serverOrderId++; - pmsg->data_.brokerOrderID_ = m_brokerOrderId_++; - pmsg->data_.createTime_ = ymdhmsf(); - - pmsg->data_.price_ = pmsg->data_.orderField_.LimitPrice; - int dir_ = pmsg->data_.orderField_.Direction != THOST_FTDC_D_Sell ? 1:-1 ; - pmsg->data_.quantity_ = dir_ * pmsg->data_.orderField_.VolumeTotalOriginal; - pmsg->data_.flag_ = CtpComboOffsetFlagToOrderFlag(pmsg->data_.orderField_.CombOffsetFlag[0]); - pmsg->data_.tag_ = pmsg->data_.tag_ - + ":h" + pmsg->data_.orderField_.CombHedgeFlag - + ":p" + pmsg->data_.orderField_.OrderPriceType - + ":c" + pmsg->data_.orderField_.ContingentCondition + ":" + to_string(pmsg->data_.orderField_.StopPrice) - + ":t" + pmsg->data_.orderField_.TimeCondition - + ":v" + pmsg->data_.orderField_.VolumeCondition; - pmsg->data_.orderStatus_ = OrderStatus::OS_NewBorn; - std::shared_ptr o = pmsg->toPOrder(); - OrderManager::instance().trackOrder(o); - //local condition order - if (pmsg->data_.orderType_ == OrderType::OT_LPT){ - pmsg->data_.price_ = pmsg->data_.orderField_.StopPrice; - o->price_ = pmsg->data_.price_; - localorders_.push_back(pmsg); - } - //direct order - else - { - //risk check - if (RiskManager::instance().passOrder(o)){ - strcpy(pmsg->data_.orderField_.OrderRef, to_string(orderRef_).c_str()); - pmsg->data_.localNo_ = to_string(frontID_) + "." + to_string(sessionID_) + "." + to_string(orderRef_++) ; - o->localNo_ = pmsg->data_.localNo_; - lock_guard gs(orderStatus_mtx); - o->orderStatus_ = OrderStatus::OS_Submitted; - int error = api_->ReqOrderInsert(&(pmsg->data_.orderField_), reqId_++); - LOG_INFO(logger, name_<<"Insert Order: osid ="<data_.serverOrderID_); + break; + case AUTHENTICATING: + msleep(100); + break; + case AUTHENTICATE_ACK: + LOG_INFO(logger, name_ << " logining ..."); + strcpy(loginField.BrokerID, ctpacc_.brokerid.c_str()); + strcpy(loginField.UserID, ctpacc_.userid.c_str()); + strcpy(loginField.Password, ctpacc_.password.c_str()); + strcpy(loginField.UserProductInfo, ctpacc_.productinfo.c_str()); + error = this->api_->ReqUserLogin(&loginField, reqId_++); + // cout<< loginField.BrokerID <orderStatus_ = OrderStatus::OS_Error; - //send error msg - auto pmsgout = make_shared(pmsg->source_, name_, - MSG_TYPE_ERROR_INSERTORDER, - fmt::format("insertOrder error:{}, oid:{}",error,o->serverOrderID_) - ); - messenger_->send(pmsgout); - LOG_ERROR(logger,name_<<" insertOrder error: "< gs(orderStatus_mtx); - o->orderStatus_ = OrderStatus::OS_Error; - auto pmsgout = make_shared(pmsg->source_, name_, - MSG_TYPE_ERROR_INSERTORDER, - fmt::format("Order Risk, oid:{}",o->serverOrderID_) - ); - messenger_->send(pmsgout); - LOG_ERROR(logger,name_<<" Order Risk, osid:"<serverOrderID_); - } - - } - //send OrderStatus - auto pmsgout = make_shared(pmsg->source_,name_); - pmsgout->set(o); - messenger_->send(pmsgout); - } - - void CtpTDEngine::cancelOrder(shared_ptr pmsg){ - CThostFtdcInputOrderActionField myreq = CThostFtdcInputOrderActionField(); - string oref; - int ofront; - int osess; - long coid = pmsg->data_.clientOrderID_; - string ctpsym; - string exchangeid; - std::shared_ptr o; - if (pmsg->data_.serverOrderID_ < 0){ - o = OrderManager::instance().retrieveOrderFromSourceAndClientOrderId(pmsg->data_.clientID_, pmsg->data_.clientOrderID_); - } - else - { - o = OrderManager::instance().retrieveOrderFromServerOrderId(pmsg->data_.serverOrderID_); - } - if (o != nullptr){ - // delete local orders - if (o->orderType_ == OrderType::OT_LPT){ - long oid = o->serverOrderID_; - for (auto it = localorders_.begin();it != localorders_.end();++it){ - if ((*it)->data_.serverOrderID_ == oid){ - o->orderStatus_ = OrderStatus::OS_Canceled; - o->updateTime_ = ymdhmsf(); - auto pmsgout = make_shared((*it)->source_,name_); - pmsgout->set(o); - messenger_->send(pmsgout); - it = localorders_.erase(it); - break; - } + { + auto pmsgs = make_shared(DESTINATION_ALL, name_, + MSG_TYPE_ENGINE_STATUS, + to_string(estate_)); + messenger_->send(pmsgs); } - return; - } - vector locno = stringsplit(o->localNo_,'.'); - ofront = stoi(locno[0]); - osess = stoi(locno[1]); - oref = locno[2]; - // ctpsym = CConfig::instance().SecurityFullNameToCtpSymbol(o->fullSymbol_); - ctpsym = DataManager::instance().full2Ctp_[o->fullSymbol_]; - } - else - { - auto pmsgout = make_shared(pmsg->source_, name_, - MSG_TYPE_ERROR_ORGANORDER, - fmt::format("cancelOrder OM cannot find order, osid:{},ocid:{}", o->serverOrderID_,o->clientOrderID_) - ); - messenger_->send(pmsgout); - LOG_ERROR(logger,"cancelorder OM cannot find order(osid):"<serverOrderID_); - return; - } - // send cancel request - strcpy(myreq.InstrumentID, ctpsym.c_str()); - exchangeid = extractExchangeID(o->fullSymbol_); - strcpy(myreq.ExchangeID, exchangeid.c_str()); - strcpy(myreq.OrderRef, oref.c_str()); - myreq.FrontID = ofront; - myreq.SessionID = osess; - myreq.ActionFlag = THOST_FTDC_AF_Delete; - strcpy(myreq.InvestorID, ctpacc_.userid.c_str()); - strcpy(myreq.BrokerID, ctpacc_.brokerid.c_str()); - myreq.OrderActionRef = m_brokerOrderId_++; - int i = this->api_->ReqOrderAction(&myreq, reqId_++); - if (i != 0){ - auto pmsgout = make_shared(pmsg->source_, name_, - MSG_TYPE_ERROR_CANCELORDER, - fmt::format("cancle order error:{}, osid:{}",i,o->serverOrderID_) ); - messenger_->send(pmsgout); - LOG_ERROR(logger,name_<<" cancle order error "< g2(orderStatus_mtx); - o->orderStatus_ = OrderStatus::OS_PendingCancel; - o->updateTime_ = ymdhmsf(); - auto pmsgout = make_shared(pmsg->source_,name_); - pmsgout->set(o); - messenger_->send(pmsgout); - - } - - void CtpTDEngine::cancelAll(shared_ptr pmsg ){ - vector> olist; - string fullsym = pmsg->data_; - if (pmsg->symtype_ == SymbolType::ST_Ctp){ - fullsym = DataManager::instance().ctp2Full_[fullsym]; - } - if (fullsym.empty()){ - olist = OrderManager::instance().retrieveNonFilledOrderPtr(); - } - else - { - olist = OrderManager::instance().retrieveNonFilledOrderPtr(fullsym); - } - if (!olist.empty()){ - for (auto o : olist) - { - auto pmsg = make_shared(name_,name_); - pmsg->data_.serverOrderID_ = o->serverOrderID_; - cancelOrder(pmsg); - } - } - } - - void CtpTDEngine::closeAll(const string& fullsym){ - if (fullsym.empty()){ - // retrieve all pos - } - else{ - string longkey = ctpacc_.userid + "." + fullsym + "." + THOST_FTDC_PD_Long ; - string shortkey = ctpacc_.userid + "." + fullsym + "." + THOST_FTDC_PD_Short ; - auto poslong = PortfolioManager::instance().retrievePosition(longkey); - auto posshort = PortfolioManager::instance().retrievePosition(shortkey); - - } - } - - - // 查询账户 - void CtpTDEngine::queryAccount(shared_ptr pmsg) { - CThostFtdcQryTradingAccountField myreq = CThostFtdcQryTradingAccountField(); - strcpy(myreq.InvestorID, ctpacc_.userid.c_str()); - strcpy(myreq.BrokerID, ctpacc_.brokerid.c_str()); - int error = api_->ReqQryTradingAccount(&myreq, reqId_++); - LOG_INFO(logger,name_ <<" qry account information"); - if (error != 0){ - auto pmsgout = make_shared(pmsg->source_, name_, - MSG_TYPE_ERROR_QRY_ACC, - "Ctp td qry acc error"); - messenger_->send(pmsgout); - LOG_ERROR(logger,name_ <<" qry acc error "< pmsg) { - CThostFtdcQryInvestorPositionField myreq = CThostFtdcQryInvestorPositionField(); - strcpy(myreq.InvestorID, ctpacc_.userid.c_str()); - strcpy(myreq.BrokerID, ctpacc_.brokerid.c_str()); - int error = this->api_->ReqQryInvestorPosition(&myreq, reqId_++); - LOG_INFO(logger,name_ <<" qry positions"); - if (error != 0){ - auto pmsgout = make_shared(pmsg->source_, name_, - MSG_TYPE_ERROR_QRY_POS, - "Ctp td qry pos error"); - messenger_->send(pmsgout); - LOG_ERROR(logger,name_ <<" qry pos error "< 20) { + LOG_ERROR(logger, name_ << " too many tries fails, give up connecting"); + // estate_ = EState::DISCONNECTED; + inconnectaction_ = false; + return false; } } - - - void CtpTDEngine::queryContract(shared_ptr pmsg){ + inconnectaction_ = false; + auto pmsgs = make_shared(DESTINATION_ALL, name_, + MSG_TYPE_ENGINE_STATUS, + to_string(estate_)); + messenger_->send(pmsgs); + // qry instrument only once everyday + if (!DataManager::instance().contractUpdated_) { CThostFtdcQryInstrumentField req = {0}; - string ctpsym = pmsg->data_; - // if (ctpsym.back() == '\0') - // ctpsym.pop_back(); - if (pmsg->symtype_ == ST_Full) - ctpsym = DataManager::instance().full2Ctp_[ctpsym]; - // ctpsym = CConfig::instance().SecurityFullNameToCtpSymbol(pmsg->data_); - strcpy(req.InstrumentID, ctpsym.c_str()); - int error = this->api_->ReqQryInstrument(&req,reqId_++); - if (error != 0){ - auto pmsgout = make_shared(pmsg->source_, name_, - MSG_TYPE_ERROR_QRY_CONTRACT, - "Ctp td qry contract error"); - messenger_->send(pmsgout); - LOG_ERROR(logger,name_ <<" qry pos contract "< pmsg) { - CThostFtdcQryOrderField myreq = {0}; - strcpy(myreq.InvestorID, ctpacc_.userid.c_str()); - strcpy(myreq.BrokerID, ctpacc_.brokerid.c_str()); - int error = this->api_->ReqQryOrder(&myreq, reqId_++); - LOG_INFO(logger,name_ <<" qry order"); - if (error != 0){ - auto pmsgout = make_shared(pmsg->source_, name_, - MSG_TYPE_ERROR_QRY_POS, - "Ctp td qry order error"); - messenger_->send(pmsgout); - LOG_ERROR(logger,name_ <<" qry order error "< pmsg) { - CThostFtdcQryTradeField myreq = {0}; - strcpy(myreq.InvestorID, ctpacc_.userid.c_str()); - strcpy(myreq.BrokerID, ctpacc_.brokerid.c_str()); - int error = this->api_->ReqQryTrade(&myreq, reqId_++); - LOG_INFO(logger,name_ <<" Qry Trade"); - if (error != 0){ - auto pmsgout = make_shared(pmsg->source_, name_, - MSG_TYPE_ERROR_QRY_POS, - "Ctp td qry trade error"); - messenger_->send(pmsgout); - LOG_ERROR(logger,name_ <<" qry trade error "< pmsg) { - CThostFtdcQryInvestorPositionDetailField myreq = {0}; - strcpy(myreq.InvestorID, ctpacc_.userid.c_str()); - strcpy(myreq.BrokerID, ctpacc_.brokerid.c_str()); - int error = this->api_->ReqQryInvestorPositionDetail(&myreq, reqId_++); - LOG_INFO(logger,name_ <<" Qry PosDetail"); - if (error != 0){ - auto pmsgout = make_shared(pmsg->source_, name_, - MSG_TYPE_ERROR_QRY_POS, - "Ctp td qry posdetail error"); - messenger_->send(pmsgout); - LOG_ERROR(logger,name_ <<" qry posdetail error "<(DESTINATION_ALL, name_, - MSG_TYPE_ENGINE_STATUS, - to_string(estate_)); - messenger_->send(pmsgs); - //autologin - if (autoconnect_ && !inconnectaction_ ){ - std::shared_ptr pmsg = make_shared(name_,name_,MSG_TYPE_ENGINE_CONNECT,name_ + "front connected."); - CMsgqRMessenger::Send(pmsg); - } - + error = this->api_->ReqQryInstrument(&req, reqId_++); + DataManager::instance().contractUpdated_ = true; } - - void CtpTDEngine::OnFrontDisconnected(int nReason) { - estate_ = CONNECTING; - reqId_ ++; - // every 1 min login once - if (reqId_ % 4000 == 0){ - auto pmsgs = make_shared(DESTINATION_ALL, name_, - MSG_TYPE_ENGINE_STATUS, - to_string(estate_)); - messenger_->send(pmsgs); - reqId_ = 1; - auto pmsgout = make_shared(DESTINATION_ALL, name_, - MSG_TYPE_INFO_ENGINE_TDDISCONNECTED, - fmt::format("Ctp td disconnected, nReason={}.",nReason) - ); - messenger_->send(pmsgout); - LOG_INFO(logger, name_ <<" disconnected, nReason="<api_->ReqUserLogout(&logoutField, reqId_++); + estate_ = EState::LOGOUTING; + if (error != 0) { + LOG_ERROR(logger, name_ << " logout error:" << error);//TODO: send error msg to client + return false; } + return true; + } else { + LOG_DEBUG(logger, name_ << " is not connected(logined), cannot disconnect!"); + return false; } - ///心跳超时警告。当长时间未收到报文时,该方法被调用。 - void CtpTDEngine::OnHeartBeatWarning(int nTimeLapse) { - auto pmsgout = make_shared(DESTINATION_ALL, name_, - MSG_TYPE_INFO_HEARTBEAT_WARNING, - fmt::format("Ctp td heartbeat overtime error, nTimeLapse={}",nTimeLapse) - ); - messenger_->send(pmsgout); - LOG_INFO(logger,name_ <<" heartbeat overtime error, nTimeLapse="<ErrorID != 0){ - string errormsgutf8; - errormsgutf8 = boost::locale::conv::between( pRspInfo->ErrorMsg, "UTF-8", "GB18030" ); - auto pmsgout = make_shared(DESTINATION_ALL, name_, - MSG_TYPE_ERROR_CONNECT, - fmt::format("Ctp Td authentication failed, ErrorID:{},Errmsg:{}",pRspInfo->ErrorID,errormsgutf8) - ); - messenger_->send(pmsgout); - LOG_ERROR(logger,name_ <<" authentication failed."<ErrorID<(DESTINATION_ALL, name_, - MSG_TYPE_ENGINE_STATUS, - to_string(estate_)); - messenger_->send(pmsgs); - LOG_INFO(logger,name_ <<" authenticated."); +} + +void CtpTDEngine::switchday() { + issettleconfirmed_ = false; + LOG_DEBUG(logger, name_ << " switch day reset settleconfirmed!"); +} + +void CtpTDEngine::timertask() { + timercount_++; + // // send status every second + // auto pmsgout = make_shared(DESTINATION_ALL, name_, + // MSG_TYPE_ENGINE_STATUS, + // to_string(estate_)); + // messenger_->send(pmsgout); + + //auto qyr pos and acc + if (estate_ == LOGIN_ACK && autoqry_) { + if (timercount_ %2 == 0) { + auto pmsgout = make_shared(name_, name_, MSG_TYPE_QRY_ACCOUNT); + // queryAccount(pmsgout); + qryBuffer_.push(pmsgout); + } else { + auto pmsgout = make_shared(name_, name_, MSG_TYPE_QRY_POS); + // queryPosition(pmsgout); + qryBuffer_.push(pmsgout); } } - /// 登录请求响应 - void CtpTDEngine::OnRspUserLogin(CThostFtdcRspUserLoginField *pRspUserLogin, CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast) { - if (pRspInfo != nullptr && pRspInfo->ErrorID != 0) - { - string errormsgutf8; - errormsgutf8 = boost::locale::conv::between( pRspInfo->ErrorMsg, "UTF-8", "GB18030" ); - auto pmsgout = make_shared(DESTINATION_ALL, name_, - MSG_TYPE_ERROR_CONNECT, - fmt::format("Ctp td login failed: ErrorID={},ErrorMsg={}",pRspInfo->ErrorID,errormsgutf8 ) - ); - messenger_->send(pmsgout); - LOG_ERROR(logger,name_ <<" login failed: ErrorID="<ErrorID<<"ErrorMsg="<FrontID; - sessionID_ = pRspUserLogin->SessionID; - orderRef_ = stoi(pRspUserLogin->MaxOrderRef) + 1; - DataManager::instance().contractUpdated_ = ( ymdcompact() == string(pRspUserLogin->TradingDay) ); - LOG_INFO(logger,name_ <<" user logged in," - <<"TradingDay="<TradingDay - <<" LoginTime="<LoginTime - <<" frontID="<FrontID - <<" sessionID="<SessionID - <<" MaxOrderRef="<MaxOrderRef - ); - if(needsettlementconfirm_ && !issettleconfirmed_){ - // 投资者结算结果确认 - CThostFtdcSettlementInfoConfirmField myreq = CThostFtdcSettlementInfoConfirmField(); - strcpy(myreq.BrokerID, ctpacc_.brokerid.c_str()); - strcpy(myreq.InvestorID, ctpacc_.userid.c_str()); - int error = api_->ReqSettlementInfoConfirm(&myreq, reqId_++); - if (error != 0){ - auto pmsgout = make_shared(DESTINATION_ALL, name_, - MSG_TYPE_ERROR_CONNECT, - fmt::format("Ctp TD settlement confirming error:{}",error) - ); - LOG_ERROR(logger,name_ <<" settlement confirming error"); - return; - } - LOG_INFO(logger,name_ <<" settlement confirming..."); - } - else{ - estate_ = LOGIN_ACK; +} + +void CtpTDEngine::processbuf() { + // check local order + checkLocalOrders(); + + // pop qrybuffer + if (!qryBuffer_.empty()) { + uint64_t timenow = getMicroTime(); + if ( (timenow - lastQryTime_) > 1000000 ) { + lastQryTime_ = timenow; + auto pmsgin = qryBuffer_.front(); + switch (pmsgin->msgtype_) { + case MSG_TYPE_QRY_POS: + queryPosition(pmsgin); + break; + case MSG_TYPE_QRY_ACCOUNT: + queryAccount(pmsgin); + break; + case MSG_TYPE_QRY_CONTRACT: + queryContract(static_pointer_cast(pmsgin)); + break; + case MSG_TYPE_QRY_ORDER: + queryOrder(pmsgin); + break; + case MSG_TYPE_QRY_POSDETAIL: + queryPositionDetail(pmsgin); + break; + case MSG_TYPE_QRY_TRADE: + queryTrade(pmsgin); + break; + default: + break; } - - } - } - ///投资者结算结果确认响应 - void CtpTDEngine::OnRspSettlementInfoConfirm(CThostFtdcSettlementInfoConfirmField *pSettlementInfoConfirm, CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast) { - if (pRspInfo != nullptr && pRspInfo->ErrorID != 0){ - string errormsgutf8; - errormsgutf8 = boost::locale::conv::between( pRspInfo->ErrorMsg, "UTF-8", "GB18030" ); - auto pmsgout = make_shared(DESTINATION_ALL, name_, - MSG_TYPE_ERROR_CONNECT, - fmt::format("Ctp TD settlement confirming error, ErrorID={},ErrorMsg={}",pRspInfo->ErrorID,errormsgutf8) - ); - LOG_ERROR(logger,name_ <<" Settlement confirm error: "<<"ErrorID="<ErrorID<<"ErrorMsg="<(DESTINATION_ALL, name_, - MSG_TYPE_ERROR_CONNECT, - fmt::format("Ctp td logout failed, ErrorID={},ErrorMsg={}",pRspInfo->ErrorID,errormsgutf8) - ); - LOG_ERROR(logger,name_ <<" logout failed: "<<"ErrorID="<ErrorID<<"ErrorMsg="<(DESTINATION_ALL, name_, - MSG_TYPE_INFO_ENGINE_TDDISCONNECTED, - "Ctp td logouted"); - messenger_->send(pmsgout); - estate_ = CONNECTING; - auto pmsgs = make_shared(DESTINATION_ALL, name_, - MSG_TYPE_ENGINE_STATUS, - to_string(estate_)); - messenger_->send(pmsgs); - LOG_INFO(logger,name_ <<" Logout,BrokerID="<BrokerID<<" UserID="<UserID); + qryBuffer_.pop(); } } - - ///报单录入请求响应(参数不通过) - void CtpTDEngine::OnRspOrderInsert(CThostFtdcInputOrderField *pInputOrder, CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast) { - bool bResult = (pRspInfo != nullptr) && (pRspInfo->ErrorID != 0); - if (bResult) - { - string errormsgutf8; - errormsgutf8 = boost::locale::conv::between( pRspInfo->ErrorMsg, "UTF-8", "GB18030" ); - string oref = to_string(frontID_) + "." + to_string(sessionID_) + "." + pInputOrder->OrderRef; - std::shared_ptr o = OrderManager::instance().retrieveOrderFromAccAndLocalNo(ctpacc_.userid,oref); - if (o != nullptr) { - lock_guard g(orderStatus_mtx); - o->orderStatus_ = OS_Error; - o->updateTime_ = ymdhmsf(); - auto pmsgout = make_shared(to_string(o->clientID_), name_, - MSG_TYPE_ERROR_INSERTORDER, - fmt::format("OnRspOrderInsert, osid:{}",o->serverOrderID_ )); - messenger_->send(pmsgout); - auto pmsgout2 = make_shared(to_string(o->clientID_),name_); - pmsgout2->set(o); - messenger_->send(pmsgout2); - - } - else {//not record this order yet - auto pmsgout = make_shared(DESTINATION_ALL, name_, - MSG_TYPE_ERROR_ORGANORDER, - fmt::format("onRspOrderInsert, OrderManager cannot find OrderRef:{}",oref) - ); +} + +void CtpTDEngine::checkLocalOrders() { + // check local order + if (localorders_.empty()) + return; + for (auto it = localorders_.begin(); it != localorders_.end();) { + auto pmsg = (*it); + double stopprice = pmsg->data_.price_; + bool directionbuy = (pmsg->data_.quantity_ >0); + string fullsym = pmsg->data_.fullSymbol_; + if (DataManager::instance().orderBook_.count(fullsym) == 0) { + ++it; + continue; + } + double lastprice = DataManager::instance().orderBook_[fullsym].price_; + bool longtriggered = (directionbuy) && (lastprice >= stopprice); + bool shorttriggered = (!directionbuy) && (lastprice <= stopprice); + if (longtriggered || shorttriggered) { + // touched + auto o = OrderManager::instance().retrieveOrderFromServerOrderId(pmsg->data_.serverOrderID_); + if (RiskManager::instance().passOrder(o)) { + strcpy(pmsg->data_.orderField_.OrderRef, to_string(orderRef_).c_str()); + pmsg->data_.localNo_ = + to_string(frontID_) + "." + to_string(sessionID_) + "." + to_string(orderRef_++); + o->localNo_ = pmsg->data_.localNo_; + lock_guard gs(orderStatus_mtx); + o->orderStatus_ = OrderStatus::OS_Submitted; + int32_t error = api_->ReqOrderInsert(&(pmsg->data_.orderField_), reqId_++); + LOG_INFO(logger, name_ + << "Local Order Touched: clientorderid =" + << pmsg->data_.clientOrderID_ + << " FullSymbol = " + <data_.fullSymbol_); + if (error != 0) { + o->orderStatus_ = OrderStatus::OS_Error; + // send error msg + auto pmsgout = make_shared(pmsg->source_, name_, + MSG_TYPE_ERROR_INSERTORDER, + fmt::format("Insert order error, order_server_id:{}", o->serverOrderID_)); + messenger_->send(pmsgout); + LOG_ERROR(logger, name_ << " insertOrder error: " << error); + } + // send OrderStatus + auto pmsgout = make_shared(pmsg->source_, name_); + pmsgout->set(o); messenger_->send(pmsgout); - LOG_ERROR(logger,name_ <<" onRspOrder Insert, OrderManager cannot find order,OrderRef="<OrderRef); + // delete this localorder, update iterator + it = localorders_.erase(it); + } else { + ++it; } - LOG_ERROR(logger,name_ <<" OnRspOrderInsert: ErrorID="<ErrorID<<"ErrorMsg="<ErrorID != 0); - if (bResult) - { - string errormsgutf8; - errormsgutf8 = boost::locale::conv::between( pRspInfo->ErrorMsg, "UTF-8", "GB18030" ); - - long oid = std::stol(pInputOrderAction->OrderRef); - string localno = to_string(pInputOrderAction->FrontID) + "." + to_string(pInputOrderAction->SessionID) - + "." + pInputOrderAction->OrderRef; - //std::shared_ptr o = OrderManager::instance().retrieveOrderFromServerOrderId(oid); - auto o = OrderManager::instance().retrieveOrderFromAccAndLocalNo(ctpacc_.userid,localno); - if (o != nullptr) { - auto pmsgout = make_shared(to_string(o->clientID_), name_, - MSG_TYPE_ERROR_CANCELORDER, - fmt::format("OnRspOrderAction,osid:{}",o->serverOrderID_) ); - messenger_->send(pmsgout); - - } - else - { - auto pmsgout = make_shared(DESTINATION_ALL, name_, - MSG_TYPE_ERROR_ORGANORDER, - fmt::format("OnRspOrderAction OrderManager cannot find order,localNo:{}.",localno) - ); +} + +void CtpTDEngine::insertOrder(shared_ptr pmsg) { + string exchangeid; + pmsg->data_.fullSymbol_ = DataManager::instance().ctp2Full_[pmsg->data_.orderField_.InstrumentID]; + exchangeid = extractExchangeID(pmsg->data_.fullSymbol_); + strcpy(pmsg->data_.orderField_.InvestorID, ctpacc_.userid.c_str()); + strcpy(pmsg->data_.orderField_.UserID, ctpacc_.userid.c_str()); + strcpy(pmsg->data_.orderField_.BrokerID, ctpacc_.brokerid.c_str()); + strcpy(pmsg->data_.orderField_.ExchangeID, exchangeid.c_str()); + lock_guard g(oid_mtx); + pmsg->data_.serverOrderID_ = m_serverOrderId++; + pmsg->data_.brokerOrderID_ = m_brokerOrderId_++; + pmsg->data_.createTime_ = ymdhmsf(); + + pmsg->data_.price_ = pmsg->data_.orderField_.LimitPrice; + int32_t dir_ = pmsg->data_.orderField_.Direction != THOST_FTDC_D_Sell ? 1:-1; + pmsg->data_.quantity_ = dir_ * pmsg->data_.orderField_.VolumeTotalOriginal; + pmsg->data_.flag_ = CtpComboOffsetFlagToOrderFlag(pmsg->data_.orderField_.CombOffsetFlag[0]); + pmsg->data_.tag_ = pmsg->data_.tag_ + + ":h" + pmsg->data_.orderField_.CombHedgeFlag + + ":p" + pmsg->data_.orderField_.OrderPriceType + + ":c" + pmsg->data_.orderField_.ContingentCondition + ":" + to_string(pmsg->data_.orderField_.StopPrice) + + ":t" + pmsg->data_.orderField_.TimeCondition + + ":v" + pmsg->data_.orderField_.VolumeCondition; + pmsg->data_.orderStatus_ = OrderStatus::OS_NewBorn; + std::shared_ptr o = pmsg->toPOrder(); + OrderManager::instance().trackOrder(o); + // local condition order + if (pmsg->data_.orderType_ == OrderType::OT_LPT) { + pmsg->data_.price_ = pmsg->data_.orderField_.StopPrice; + o->price_ = pmsg->data_.price_; + localorders_.push_back(pmsg); + } else { // direct order + // risk check + if (RiskManager::instance().passOrder(o)) { + strcpy(pmsg->data_.orderField_.OrderRef, to_string(orderRef_).c_str()); + pmsg->data_.localNo_ = + to_string(frontID_) + "." + to_string(sessionID_) + "." + to_string(orderRef_++); + o->localNo_ = pmsg->data_.localNo_; + lock_guard gs(orderStatus_mtx); + o->orderStatus_ = OrderStatus::OS_Submitted; + int32_t error = api_->ReqOrderInsert(&(pmsg->data_.orderField_), reqId_++); + LOG_INFO(logger, name_<<"Insert Order: osid ="<data_.serverOrderID_); + if (error != 0) { + o->orderStatus_ = OrderStatus::OS_Error; + // send error msg + auto pmsgout = make_shared(pmsg->source_, name_, + MSG_TYPE_ERROR_INSERTORDER, + fmt::format("insertOrder error:{}, oid:{}", error, o->serverOrderID_)); messenger_->send(pmsgout); - LOG_ERROR(logger,name_ <<" OnRspOrderAction OrderManager cannot find order,localNo="< gs(orderStatus_mtx); + o->orderStatus_ = OrderStatus::OS_Error; + auto pmsgout = make_shared(pmsg->source_, name_, + MSG_TYPE_ERROR_INSERTORDER, + fmt::format("Order Risk, oid:{}",o->serverOrderID_)); + messenger_->send(pmsgout); + LOG_ERROR(logger, name_ << " Order Risk, osid:" << o->serverOrderID_); } } - - void CtpTDEngine::OnRspQryOrder(CThostFtdcOrderField *pOrder, CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast){ - bool bResult = (pRspInfo != nullptr) && (pRspInfo->ErrorID != 0); - if (bIsLast){ - lastQryTime_ = getMicroTime(); - } - if (!bResult){ - if(pOrder == nullptr){ - LOG_INFO(logger,name_ <<" onQryOrder return nullptr"); - return; - } - string localno = to_string(pOrder->FrontID) + "." + to_string(pOrder->SessionID) + "." + pOrder->OrderRef ; - shared_ptr o = OrderManager::instance().retrieveOrderFromAccAndLocalNo(ctpacc_.userid,localno); - if ( o == nullptr) { // create an order - o = make_shared(); - o->api_ = "CTP.TD"; - o->account_ = ctpacc_.userid; - // o->fullSymbol_ = CConfig::instance().CtpSymbolToSecurityFullName(pOrder->InstrumentID); - o->fullSymbol_ = DataManager::instance().ctp2Full_[pOrder->InstrumentID]; - o->price_ = pOrder->LimitPrice; - int dir_ = pOrder->Direction != THOST_FTDC_D_Sell ? 1:-1 ; - o->quantity_ = dir_ * pOrder->VolumeTotalOriginal ; - o->tradedvol_ = dir_ * pOrder->VolumeTraded ; - o->flag_ = CtpComboOffsetFlagToOrderFlag(pOrder->CombOffsetFlag[0]); - o->tag_ = string("14") - + ":h" + pOrder->CombHedgeFlag - + ":p" + pOrder->OrderPriceType - + ":c" + pOrder->ContingentCondition + ":" + to_string(pOrder->StopPrice) - + ":t" + pOrder->TimeCondition - + ":v" + pOrder->VolumeCondition; - lock_guard g(oid_mtx); - o->serverOrderID_ = m_serverOrderId++; - o->brokerOrderID_ = m_brokerOrderId_++; - o->orderNo_ = pOrder->OrderSysID; - o->localNo_ = localno; - o->createTime_ = string(pOrder->InsertDate) + " " + string(pOrder->InsertTime); - o->updateTime_ = ymdhmsf(); - o->orderStatus_ =CtpOrderStatusToOrderStatus(pOrder->OrderStatus); - OrderManager::instance().trackOrder(o); - auto pmsgout = make_shared(DESTINATION_ALL,name_); - pmsgout->set(o); - messenger_->send(pmsgout); - auto pmsgout2 = make_shared(DESTINATION_ALL, name_, - MSG_TYPE_ERROR_ORGANORDER, - fmt::format("OM don't record this order:{}.",localno) - ); - messenger_->send(pmsgout2); - LOG_INFO(logger,name_ <<" OnQryOrder details:" - <<" InstrumentID="<InstrumentID - <<" OrderRef="<OrderRef - <<" ExchangeID="<ExchangeID - <<" InsertTime="<InsertTime - <<" CancelTime="<CancelTime - <<" FrontID="<FrontID - <<" SessionID="<SessionID - <<" Direction="<Direction - <<" CombOffsetFlag="<CombOffsetFlag - <<" OrderStatus="<OrderStatus - <<" OrderSubmitStatus="<OrderSubmitStatus - <<" StatusMsg="<StatusMsg) - <<" LimitPrice="<LimitPrice - <<" VolumeTotalOriginal="<VolumeTotalOriginal - <<" VolumeTraded="<VolumeTraded - <<" OrderSysID="<OrderSysID - <<" SequenceNo="<SequenceNo - ); - } - else { - o->orderStatus_ = CtpOrderStatusToOrderStatus(pOrder->OrderStatus); - o->orderNo_ = pOrder->OrderSysID; - o->updateTime_ = ymdhmsf(); - auto pmsgout = make_shared(to_string(o->clientID_),name_); - pmsgout->set(o); - messenger_->send(pmsgout); + // send OrderStatus + auto pmsgout = make_shared(pmsg->source_, name_); + pmsgout->set(o); + messenger_->send(pmsgout); +} + +void CtpTDEngine::cancelOrder(shared_ptr pmsg) { + CThostFtdcInputOrderActionField myreq = CThostFtdcInputOrderActionField(); + string oref; + int32_t ofront; + int32_t osess; + int64_t coid = pmsg->data_.clientOrderID_; + string ctpsym; + string exchangeid; + std::shared_ptr o; + if (pmsg->data_.serverOrderID_ < 0) { + o = OrderManager::instance().retrieveOrderFromSourceAndClientOrderId(pmsg->data_.clientID_, pmsg->data_.clientOrderID_); + } else { + o = OrderManager::instance().retrieveOrderFromServerOrderId(pmsg->data_.serverOrderID_); + } + if (o != nullptr) { + // delete local orders + if (o->orderType_ == OrderType::OT_LPT) { + int64_t oid = o->serverOrderID_; + for (auto it = localorders_.begin(); it != localorders_.end(); ++it) { + if ((*it)->data_.serverOrderID_ == oid) { + o->orderStatus_ = OrderStatus::OS_Canceled; + o->updateTime_ = ymdhmsf(); + auto pmsgout = make_shared((*it)->source_, name_); + pmsgout->set(o); + messenger_->send(pmsgout); + it = localorders_.erase(it); + break; + } } + return; } - else{ - string errormsgutf8; - errormsgutf8 = boost::locale::conv::between( pRspInfo->ErrorMsg, "UTF-8", "GB18030" ); - auto pmsgout = make_shared(DESTINATION_ALL, name_, - MSG_TYPE_ERROR_QRY_POS, - fmt::format("Ctp.td qry order error: ErrorID={},ErrorMsg={}",pRspInfo->ErrorID,errormsgutf8) - ); - messenger_->send(pmsgout); - LOG_ERROR(logger,name_ <<" Qry order error, errorID="<ErrorID<<" ErrorMsg:"< locno = stringsplit(o->localNo_, '.'); + ofront = stoi(locno[0]); + osess = stoi(locno[1]); + oref = locno[2]; + // ctpsym = CConfig::instance().SecurityFullNameToCtpSymbol(o->fullSymbol_); + ctpsym = DataManager::instance().full2Ctp_[o->fullSymbol_]; + } else { + auto pmsgout = make_shared(pmsg->source_, name_, + MSG_TYPE_ERROR_ORGANORDER, + fmt::format("cancelOrder OM cannot find order, osid:{},ocid:{}", o->serverOrderID_,o->clientOrderID_)); + messenger_->send(pmsgout); + LOG_ERROR(logger,"cancelorder OM cannot find order(osid):" << o->serverOrderID_); + return; + } + // send cancel request + strcpy(myreq.InstrumentID, ctpsym.c_str()); + exchangeid = extractExchangeID(o->fullSymbol_); + strcpy(myreq.ExchangeID, exchangeid.c_str()); + strcpy(myreq.OrderRef, oref.c_str()); + myreq.FrontID = ofront; + myreq.SessionID = osess; + myreq.ActionFlag = THOST_FTDC_AF_Delete; + strcpy(myreq.InvestorID, ctpacc_.userid.c_str()); + strcpy(myreq.BrokerID, ctpacc_.brokerid.c_str()); + myreq.OrderActionRef = m_brokerOrderId_++; + int32_t i = this->api_->ReqOrderAction(&myreq, reqId_++); + if (i != 0) { + auto pmsgout = make_shared(pmsg->source_, name_, + MSG_TYPE_ERROR_CANCELORDER, + fmt::format("cancle order error:{}, osid:{}", i, o->serverOrderID_)); + messenger_->send(pmsgout); + LOG_ERROR(logger, name_ << " cancle order error " << i); + return; + } + lock_guard g2(orderStatus_mtx); + o->orderStatus_ = OrderStatus::OS_PendingCancel; + o->updateTime_ = ymdhmsf(); + auto pmsgout = make_shared(pmsg->source_, name_); + pmsgout->set(o); + messenger_->send(pmsgout); +} + +void CtpTDEngine::cancelAll(shared_ptr pmsg) { + vector> olist; + string fullsym = pmsg->data_; + if (pmsg->symtype_ == SymbolType::ST_Ctp) { + fullsym = DataManager::instance().ctp2Full_[fullsym]; + } + if (fullsym.empty()) { + olist = OrderManager::instance().retrieveNonFilledOrderPtr(); + } else { + olist = OrderManager::instance().retrieveNonFilledOrderPtr(fullsym); + } + if (!olist.empty()) { + for (auto o : olist) { + auto pmsg = make_shared(name_, name_); + pmsg->data_.serverOrderID_ = o->serverOrderID_; + cancelOrder(pmsg); } + } +} + +void CtpTDEngine::closeAll(const string& fullsym) { + if (fullsym.empty()) { + // retrieve all pos + } else { + string longkey = ctpacc_.userid + "." + fullsym + "." + THOST_FTDC_PD_Long; + string shortkey = ctpacc_.userid + "." + fullsym + "." + THOST_FTDC_PD_Short; + auto poslong = PortfolioManager::instance().retrievePosition(longkey); + auto posshort = PortfolioManager::instance().retrievePosition(shortkey); + } +} + + +// 查询账户 +void CtpTDEngine::queryAccount(shared_ptr pmsg) { + CThostFtdcQryTradingAccountField myreq = CThostFtdcQryTradingAccountField(); + strcpy(myreq.InvestorID, ctpacc_.userid.c_str()); + strcpy(myreq.BrokerID, ctpacc_.brokerid.c_str()); + int32_t error = api_->ReqQryTradingAccount(&myreq, reqId_++); + LOG_INFO(logger, name_ <<" qry account information"); + if (error != 0) { + auto pmsgout = make_shared(pmsg->source_, name_, + MSG_TYPE_ERROR_QRY_ACC, + "Ctp td qry acc error"); + messenger_->send(pmsgout); + LOG_ERROR(logger, name_ << " qry acc error " << error); + } +} +/// 查询pos +void CtpTDEngine::queryPosition(shared_ptr pmsg) { + CThostFtdcQryInvestorPositionField myreq = CThostFtdcQryInvestorPositionField(); + strcpy(myreq.InvestorID, ctpacc_.userid.c_str()); + strcpy(myreq.BrokerID, ctpacc_.brokerid.c_str()); + int32_t error = this->api_->ReqQryInvestorPosition(&myreq, reqId_++); + LOG_INFO(logger, name_ << " qry positions"); + if (error != 0) { + auto pmsgout = make_shared(pmsg->source_, name_, + MSG_TYPE_ERROR_QRY_POS, + "Ctp td qry pos error"); + messenger_->send(pmsgout); + LOG_ERROR(logger, name_ << " qry pos error " << error); + } +} + + +void CtpTDEngine::queryContract(shared_ptr pmsg) { + CThostFtdcQryInstrumentField req = {0}; + string ctpsym = pmsg->data_; + // if (ctpsym.back() == '\0') + // ctpsym.pop_back(); + if (pmsg->symtype_ == ST_Full) + ctpsym = DataManager::instance().full2Ctp_[ctpsym]; + // ctpsym = CConfig::instance().SecurityFullNameToCtpSymbol(pmsg->data_); + strcpy(req.InstrumentID, ctpsym.c_str()); + int32_t error = this->api_->ReqQryInstrument(&req, reqId_++); + if (error != 0) { + auto pmsgout = make_shared(pmsg->source_, name_, + MSG_TYPE_ERROR_QRY_CONTRACT, + "Ctp td qry contract error"); + messenger_->send(pmsgout); + LOG_ERROR(logger, name_ << " qry pos contract " << error); + } +} + +/// 查询order +void CtpTDEngine::queryOrder(shared_ptr pmsg) { + CThostFtdcQryOrderField myreq = {0}; + strcpy(myreq.InvestorID, ctpacc_.userid.c_str()); + strcpy(myreq.BrokerID, ctpacc_.brokerid.c_str()); + int32_t error = this->api_->ReqQryOrder(&myreq, reqId_++); + LOG_INFO(logger, name_ << " qry order"); + if (error != 0) { + auto pmsgout = make_shared(pmsg->source_, name_, + MSG_TYPE_ERROR_QRY_POS, + "Ctp td qry order error"); + messenger_->send(pmsgout); + LOG_ERROR(logger, name_ << " qry order error " << error); + } +} + +/// 查询trade +void CtpTDEngine::queryTrade(shared_ptr pmsg) { + CThostFtdcQryTradeField myreq = {0}; + strcpy(myreq.InvestorID, ctpacc_.userid.c_str()); + strcpy(myreq.BrokerID, ctpacc_.brokerid.c_str()); + int32_t error = this->api_->ReqQryTrade(&myreq, reqId_++); + LOG_INFO(logger, name_ << " Qry Trade"); + if (error != 0) { + auto pmsgout = make_shared(pmsg->source_, name_, + MSG_TYPE_ERROR_QRY_POS, + "Ctp td qry trade error"); + messenger_->send(pmsgout); + LOG_ERROR(logger, name_ << " qry trade error " << error); + } +} + +void CtpTDEngine::queryPositionDetail(shared_ptr pmsg) { + CThostFtdcQryInvestorPositionDetailField myreq = {0}; + strcpy(myreq.InvestorID, ctpacc_.userid.c_str()); + strcpy(myreq.BrokerID, ctpacc_.brokerid.c_str()); + int32_t error = this->api_->ReqQryInvestorPositionDetail(&myreq, reqId_++); + LOG_INFO(logger, name_ <<" Qry PosDetail"); + if (error != 0) { + auto pmsgout = make_shared(pmsg->source_, name_, + MSG_TYPE_ERROR_QRY_POS, + "Ctp td qry posdetail error"); + messenger_->send(pmsgout); + LOG_ERROR(logger, name_ << " qry posdetail error " << error); + } +} + + + +//////// begin callback/incoming function //////////// +// 当客户端与交易后台建立起通信连接时(还未登录前),该方法被调用。 +void CtpTDEngine::OnFrontConnected() { + LOG_INFO(logger, name_ <<" front connected."); + estate_ = CONNECT_ACK; + reqId_ = 0; + auto pmsgs = make_shared(DESTINATION_ALL, name_, + MSG_TYPE_ENGINE_STATUS, + to_string(estate_)); + messenger_->send(pmsgs); + // autologin + if (autoconnect_ && !inconnectaction_) { + std::shared_ptr pmsg = make_shared(name_, name_, MSG_TYPE_ENGINE_CONNECT, name_ + "front connected."); + CMsgqRMessenger::Send(pmsg); + } +} +void CtpTDEngine::OnFrontDisconnected(int32_t nReason) { + estate_ = CONNECTING; + reqId_++; + // every 1 min login once + if (reqId_ % 4000 == 0) { + auto pmsgs = make_shared(DESTINATION_ALL, name_, + MSG_TYPE_ENGINE_STATUS, + to_string(estate_)); + messenger_->send(pmsgs); + reqId_ = 1; + auto pmsgout = make_shared(DESTINATION_ALL, name_, + MSG_TYPE_INFO_ENGINE_TDDISCONNECTED, + fmt::format("Ctp td disconnected, nReason={}.", nReason)); + messenger_->send(pmsgout); + LOG_INFO(logger, name_ << " disconnected, nReason=" << nReason); } - ///请求查询成交响应 - void CtpTDEngine::OnRspQryTrade(CThostFtdcTradeField *pTrade, CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast){ - bool bResult = (pRspInfo != nullptr) && (pRspInfo->ErrorID != 0); - if (bIsLast){ - lastQryTime_ = getMicroTime(); - } - if (!bResult){ - if(pTrade == nullptr){ - LOG_INFO(logger,name_ <<" onQrytrade return nullptr"); - return; - } - auto pmsg = make_shared(); - pmsg->destination_ = DESTINATION_ALL; - pmsg->source_ = name_; - // pmsg->data_.fullSymbol_ = CConfig::instance().CtpSymbolToSecurityFullName(pTrade->InstrumentID); - pmsg->data_.fullSymbol_ = DataManager::instance().ctp2Full_[pTrade->InstrumentID]; - pmsg->data_.tradeTime_ = pTrade->TradeTime; - //pmsg->data_.serverOrderID_ = std::stol(pTrade->OrderRef); - pmsg->data_.orderNo_ = pTrade->OrderSysID; - //pmsg->data_.tradeId = std::stoi(pTrade->TraderID); - pmsg->data_.tradeNo_ = pTrade->TradeID; - pmsg->data_.tradePrice_ = pTrade->Price; - pmsg->data_.tradeSize_ = (pTrade->Direction == THOST_FTDC_D_Buy ? 1 : -1)*pTrade->Volume; - pmsg->data_.fillFlag_ = CtpComboOffsetFlagToOrderFlag(pTrade->OffsetFlag); - string localno = to_string(frontID_) + "." + to_string(sessionID_) + "." + pTrade->OrderRef; - auto o = OrderManager::instance().retrieveOrderFromAccAndLocalNo(ctpacc_.userid,localno); - auto o2 = OrderManager::instance().retrieveOrderFromOrderNo(pTrade->OrderSysID); - //bool islocalorder = ( (o != nullptr) && !(o2 != nullptr && o2->localNo_ != localno) ); - if (o2 != nullptr) { - pmsg->data_.serverOrderID_ = o2->serverOrderID_; - pmsg->data_.clientOrderID_ = o2->clientOrderID_; - pmsg->data_.brokerOrderID_ = o2->brokerOrderID_; - pmsg->data_.localNo_ = o2->localNo_; - pmsg->data_.account_ = o2->account_; - pmsg->data_.clientID_ = o2->clientID_; - pmsg->data_.api_ = o2->api_; - //o->fillNo_ = pTrade->TradeID; - OrderManager::instance().gotFill(pmsg->data_); - messenger_->send(pmsg); - auto pmsgos = make_shared(to_string(o2->clientID_),name_); - pmsgos->set(o2); - messenger_->send(pmsgos); - } - else if (o != nullptr) { - pmsg->data_.serverOrderID_ = o->serverOrderID_; - pmsg->data_.clientOrderID_ = o->clientOrderID_; - pmsg->data_.brokerOrderID_ = o->brokerOrderID_; - pmsg->data_.localNo_ = localno; - pmsg->data_.account_ = o->account_; - pmsg->data_.clientID_ = o->clientID_; - pmsg->data_.api_ = o->api_; - //o->fillNo_ = pTrade->TradeID; - OrderManager::instance().gotFill(pmsg->data_); - messenger_->send(pmsg); - auto pmsgos = make_shared(to_string(o->clientID_),name_); - pmsgos->set(o); - messenger_->send(pmsgos); - } - else { - pmsg->data_.api_ = "CTP.TD"; - pmsg->data_.account_ = ctpacc_.userid; - messenger_->send(pmsg); +} +// 心跳超时警告。当长时间未收到报文时,该方法被调用。 +void CtpTDEngine::OnHeartBeatWarning(int32_t nTimeLapse) { + auto pmsgout = make_shared(DESTINATION_ALL, name_, + MSG_TYPE_INFO_HEARTBEAT_WARNING, + fmt::format("Ctp td heartbeat overtime error, nTimeLapse={}", nTimeLapse)); + messenger_->send(pmsgout); + LOG_INFO(logger, name_ << " heartbeat overtime error, nTimeLapse=" << nTimeLapse); +} +// 客户端认证响应 +void CtpTDEngine::OnRspAuthenticate( + CThostFtdcRspAuthenticateField *pRspAuthenticateField, + CThostFtdcRspInfoField *pRspInfo, + int32_t nRequestID, + bool bIsLast) { + + if (pRspInfo != nullptr && pRspInfo->ErrorID != 0) { + string errormsgutf8; + errormsgutf8 = boost::locale::conv::between( pRspInfo->ErrorMsg, "UTF-8", "GB18030"); + auto pmsgout = make_shared(DESTINATION_ALL, name_, + MSG_TYPE_ERROR_CONNECT, + fmt::format("Ctp Td authentication failed, ErrorID:{},Errmsg:{}", pRspInfo->ErrorID, errormsgutf8)); + messenger_->send(pmsgout); + LOG_ERROR(logger, name_ << " authentication failed." << pRspInfo->ErrorID << errormsgutf8); + } else { + estate_ = AUTHENTICATE_ACK; + auto pmsgs = make_shared(DESTINATION_ALL, name_, + MSG_TYPE_ENGINE_STATUS, + to_string(estate_)); + messenger_->send(pmsgs); + LOG_INFO(logger, name_ <<" authenticated."); + } +} +// 登录请求响应 +void CtpTDEngine::OnRspUserLogin( + CThostFtdcRspUserLoginField *pRspUserLogin, + CThostFtdcRspInfoField *pRspInfo, + int32_t nRequestID, + bool bIsLast) { + + if (pRspInfo != nullptr && pRspInfo->ErrorID != 0) { + string errormsgutf8; + errormsgutf8 = boost::locale::conv::between(pRspInfo->ErrorMsg, "UTF-8", "GB18030"); + auto pmsgout = make_shared(DESTINATION_ALL, name_, + MSG_TYPE_ERROR_CONNECT, + fmt::format("Ctp td login failed: ErrorID={},ErrorMsg={}", pRspInfo->ErrorID, errormsgutf8 )); + messenger_->send(pmsgout); + LOG_ERROR(logger, name_ << " login failed: ErrorID=" << pRspInfo->ErrorID << "ErrorMsg=" << errormsgutf8); + } else { + frontID_ = pRspUserLogin->FrontID; + sessionID_ = pRspUserLogin->SessionID; + orderRef_ = stoi(pRspUserLogin->MaxOrderRef) + 1; + DataManager::instance().contractUpdated_ = (ymdcompact() == string(pRspUserLogin->TradingDay)); + LOG_INFO(logger, name_ <<" user logged in," + << "TradingDay=" << pRspUserLogin->TradingDay + << " LoginTime=" << pRspUserLogin->LoginTime + << " frontID=" << pRspUserLogin->FrontID + << " sessionID=" << pRspUserLogin->SessionID + << " MaxOrderRef=" << pRspUserLogin->MaxOrderRef + ); + if (needsettlementconfirm_ && !issettleconfirmed_) { + // 投资者结算结果确认 + CThostFtdcSettlementInfoConfirmField myreq = CThostFtdcSettlementInfoConfirmField(); + strcpy(myreq.BrokerID, ctpacc_.brokerid.c_str()); + strcpy(myreq.InvestorID, ctpacc_.userid.c_str()); + int32_t error = api_->ReqSettlementInfoConfirm(&myreq, reqId_++); + if (error != 0) { auto pmsgout = make_shared(DESTINATION_ALL, name_, - MSG_TYPE_ERROR_ORGANORDER, - fmt::format("OM dont record this order:{}.",pTrade->OrderSysID) + MSG_TYPE_ERROR_CONNECT, + fmt::format("Ctp TD settlement confirming error:{}", error) ); - messenger_->send(pmsgout); - LOG_INFO(logger,name_ <<" OnQryTrade details:" - <<" TradeID="<TradeID - <<" OrderRef="<OrderRef - <<" InstrumentID="<InstrumentID - <<" ExchangeID="<ExchangeID - <<" TradeTime="<TradeTime - <<" OffsetFlag="<OffsetFlag - <<" Direction="<Direction - <<" Price="<Price - <<" Volume="<Volume - ); + LOG_ERROR(logger, name_ <<" settlement confirming error"); + return; } - } - else - { - string errormsgutf8; - errormsgutf8 = boost::locale::conv::between( pRspInfo->ErrorMsg, "UTF-8", "GB18030" ); - auto pmsgout = make_shared(DESTINATION_ALL, name_, - MSG_TYPE_ERROR_QRY_POS, - fmt::format("Ctp Td Qry order error, errorID={}, errorMsg={}", pRspInfo->ErrorID,errormsgutf8) - ); - messenger_->send(pmsgout); - LOG_ERROR(logger,name_ <<" Qry order error, errorID="<ErrorID<<" ErrorMsg:"<ErrorID != 0); - if (bIsLast){ - lastQryTime_ = getMicroTime(); - } - if (!bResult){ - if(pInvestorPositionDetail == nullptr){ - LOG_DEBUG(logger,name_ <<" onRspQryposdetail return nullptr."); - return; - } - LOG_INFO(logger,name_ <<" OnRspQryInvestorPositionDetail:" - <<" InstrumentID="<InstrumentID - <<" Position="<Direction - <<" OpenDate="<OpenDate - <<" Volume="<Volume - <<" OpenPirce="<OpenPrice - <<" Margin="<Margin - <<" MarginRateByMoney="<MarginRateByMoney - <<" CloseVolume="<CloseVolume - <<" CloseProfitByTrade="<CloseProfitByTrade - <<" PositionProfitByTrade="<PositionProfitByTrade - <<" islast="<ErrorID != 0) { + string errormsgutf8; + errormsgutf8 = boost::locale::conv::between( pRspInfo->ErrorMsg, "UTF-8", "GB18030" ); + auto pmsgout = make_shared(DESTINATION_ALL, name_, + MSG_TYPE_ERROR_CONNECT, + fmt::format("Ctp TD settlement confirming error, ErrorID={},ErrorMsg={}", pRspInfo->ErrorID, errormsgutf8)); + LOG_ERROR(logger, name_ <<" Settlement confirm error: " << "ErrorID=" << pRspInfo->ErrorID << "ErrorMsg=" << errormsgutf8); + } else { + estate_ = LOGIN_ACK; + issettleconfirmed_ = true; + LOG_INFO(logger, name_ << " Settlement confirmed.ConfirmDate=" << pSettlementInfoConfirm->ConfirmDate << "ConfirmTime=" << pSettlementInfoConfirm->ConfirmTime); + } +} +// /登出请求响应 +void CtpTDEngine::OnRspUserLogout( + CThostFtdcUserLogoutField *pUserLogout, + CThostFtdcRspInfoField *pRspInfo, + int32_t nRequestID, + bool bIsLast) { + + if (pRspInfo != nullptr && pRspInfo->ErrorID != 0) { + string errormsgutf8; + errormsgutf8 = boost::locale::conv::between( pRspInfo->ErrorMsg, "UTF-8", "GB18030" ); + auto pmsgout = make_shared(DESTINATION_ALL, name_, + MSG_TYPE_ERROR_CONNECT, + fmt::format("Ctp td logout failed, ErrorID={},ErrorMsg={}", pRspInfo->ErrorID, errormsgutf8) ); - } - else{ - string errormsgutf8; - errormsgutf8 = boost::locale::conv::between( pRspInfo->ErrorMsg, "UTF-8", "GB18030" ); + LOG_ERROR(logger, name_ <<" logout failed: "<<"ErrorID="<ErrorID<<"ErrorMsg="<(DESTINATION_ALL, name_, + MSG_TYPE_INFO_ENGINE_TDDISCONNECTED, + "Ctp td logouted"); + messenger_->send(pmsgout); + estate_ = CONNECTING; + auto pmsgs = make_shared(DESTINATION_ALL, name_, + MSG_TYPE_ENGINE_STATUS, + to_string(estate_)); + messenger_->send(pmsgs); + LOG_INFO(logger, name_ <<" Logout,BrokerID="<BrokerID<<" UserID="<UserID); + } +} + +// /报单录入请求响应(参数不通过) +void CtpTDEngine::OnRspOrderInsert( + CThostFtdcInputOrderField *pInputOrder, + CThostFtdcRspInfoField *pRspInfo, + int32_t nRequestID, + bool bIsLast) { + + bool bResult = (pRspInfo != nullptr) && (pRspInfo->ErrorID != 0); + if (bResult) { + string errormsgutf8; + errormsgutf8 = boost::locale::conv::between( pRspInfo->ErrorMsg, "UTF-8", "GB18030" ); + string oref = to_string(frontID_) + "." + to_string(sessionID_) + "." + pInputOrder->OrderRef; + std::shared_ptr o = OrderManager::instance().retrieveOrderFromAccAndLocalNo(ctpacc_.userid,oref); + if (o != nullptr) { + lock_guard g(orderStatus_mtx); + o->orderStatus_ = OS_Error; + o->updateTime_ = ymdhmsf(); + auto pmsgout = make_shared(to_string(o->clientID_), name_, + MSG_TYPE_ERROR_INSERTORDER, + fmt::format("OnRspOrderInsert, osid:{}",o->serverOrderID_)); + messenger_->send(pmsgout); + auto pmsgout2 = make_shared(to_string(o->clientID_),name_); + pmsgout2->set(o); + messenger_->send(pmsgout2); + } else { // not record this order yet auto pmsgout = make_shared(DESTINATION_ALL, name_, - MSG_TYPE_ERROR_QRY_POS, - fmt::format("Ctp Td Qry posdetail error, errorID={}, errorMsg={}", pRspInfo->ErrorID,errormsgutf8) + MSG_TYPE_ERROR_ORGANORDER, + fmt::format("onRspOrderInsert, OrderManager cannot find OrderRef:{}", oref) ); messenger_->send(pmsgout); - LOG_ERROR(logger,name_ <<" Qry posdetail error, errorID="<ErrorID<<" ErrorMsg:"<ErrorID != 0); + if (bResult) { + string errormsgutf8; + errormsgutf8 = boost::locale::conv::between( pRspInfo->ErrorMsg, "UTF-8", "GB18030" ); + int64_t oid = std::stol(pInputOrderAction->OrderRef); + string localno = + to_string(pInputOrderAction->FrontID) + "." + to_string(pInputOrderAction->SessionID) + + "." + pInputOrderAction->OrderRef; + //std::shared_ptr o = OrderManager::instance().retrieveOrderFromServerOrderId(oid); + auto o = OrderManager::instance().retrieveOrderFromAccAndLocalNo(ctpacc_.userid,localno); + if (o != nullptr) { + auto pmsgout = make_shared(to_string(o->clientID_), name_, + MSG_TYPE_ERROR_CANCELORDER, + fmt::format("OnRspOrderAction,osid:{}",o->serverOrderID_) ); + messenger_->send(pmsgout); - - - ///请求查询投资者持仓响应 - void CtpTDEngine::OnRspQryInvestorPosition(CThostFtdcInvestorPositionField *pInvestorPosition, CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast) { - bool bResult = (pRspInfo != nullptr) && (pRspInfo->ErrorID != 0); - if (bIsLast){ - lastQryTime_ = getMicroTime(); - } - if (!bResult){ - if(pInvestorPosition == nullptr){ - LOG_DEBUG(logger,name_ <<" onRspQrypos return nullptr."); - return; - } - // string fullsym = CConfig::instance().CtpSymbolToSecurityFullName(pInvestorPosition->InstrumentID); - string fullsym = DataManager::instance().ctp2Full_[pInvestorPosition->InstrumentID]; - string exchid = stringsplit(fullsym,' ')[0]; - string key = ctpacc_.userid + "." + fullsym + "." + pInvestorPosition->PosiDirection; - - // auto pos = PortfolioManager::instance().retrievePosition(key); - std::shared_ptr pos; - if (posbuffer_.find(key) == posbuffer_.end() ){ - pos = std::make_shared(); - pos->key_ = key; - pos->account_ = ctpacc_.userid; - pos->fullSymbol_ = fullsym; - pos->api_ = "CTP.TD"; - posbuffer_[key] = pos; - }else - { - pos = posbuffer_[key]; - } - pos->type_ = pInvestorPosition->PosiDirection; - // int dirsign = pInvestorPosition->PosiDirection == THOST_FTDC_PD_Short ? -1 : 1; - if (exchid == "SHFE"){ - if ((pInvestorPosition->YdPosition != 0 ) && (pInvestorPosition->TodayPosition == 0)) - pos->preSize_ = pInvestorPosition->Position; - }else{ - pos->preSize_ = (pInvestorPosition->Position - pInvestorPosition->TodayPosition); - } - int multiples = DataManager::instance().securityDetails_[pInvestorPosition->InstrumentID].multiplier_; - - double cost = pos->avgPrice_ * pos->size_ * multiples; - pos->size_ += pInvestorPosition->Position; - pos->openpl_ += pInvestorPosition->PositionProfit; - if (pos->size_ != 0 && multiples ){ - cost += pInvestorPosition->PositionCost; - pos->avgPrice_ = cost /(pos->size_ * multiples); - } - if (pos->type_ == THOST_FTDC_PD_Long){ - pos->freezedSize_ += pInvestorPosition->ShortFrozen; - } - else{ - pos->freezedSize_ += pInvestorPosition->LongFrozen; - } - pos->closedpl_ += pInvestorPosition->CloseProfit; - if (bIsLast){ - for (auto iter = posbuffer_.begin();iter != posbuffer_.end(); ++ iter){ - auto pmsg = make_shared(DESTINATION_ALL,name_); - pmsg->set(iter->second); - messenger_->send(pmsg); - PortfolioManager::instance().Add(iter->second); - } - posbuffer_.clear(); - } - LOG_INFO(logger,name_ <<" OnRspQryInvestorPosition:" - <<" InstrumentID="<InstrumentID - <<" InvestorID="<InvestorID - <<" Position="<Position - <<" OpenAmount="<OpenAmount - <<" OpenVolume="<OpenVolume - <<" OpenCost=" <OpenCost - <<" PosiDirection="<PosiDirection - <<" PositionProfit="<PositionProfit - <<" PositionCost="<PositionCost - <<" UseMargin="<UseMargin - <<" LongFrozen="<LongFrozen - <<" ShortFrozen="<ShortFrozen - <<" TradingDay="<TradingDay - <<" YdPosition="<YdPosition - <<" islast="<ErrorMsg, "UTF-8", "GB18030" ); + } else { auto pmsgout = make_shared(DESTINATION_ALL, name_, - MSG_TYPE_ERROR_QRY_POS, - fmt::format("Ctp Td Qry pos error, errorID={}, errorMsg={}", pRspInfo->ErrorID,errormsgutf8) + MSG_TYPE_ERROR_ORGANORDER, + fmt::format("OnRspOrderAction OrderManager cannot find order,localNo:{}.",localno) ); messenger_->send(pmsgout); - LOG_ERROR(logger,name_ <<" Qry pos error, errorID="<ErrorID<<" ErrorMsg:"<ErrorID != 0); - if (bIsLast){ - lastQryTime_ = getMicroTime(); - } - if (!bResult){ - if(pTradingAccount == nullptr){ - LOG_INFO(logger,name_ <<" qry acc return nullptr"); - return; - } - double netLiquidation = pTradingAccount->PreBalance - pTradingAccount->PreCredit - pTradingAccount->PreMortgage - + pTradingAccount->Mortgage - pTradingAccount->Withdraw + pTradingAccount->Deposit - + pTradingAccount->CloseProfit + pTradingAccount->PositionProfit + pTradingAccount->CashIn - pTradingAccount->Commission; - auto pmsg = make_shared(); - pmsg->destination_ = DESTINATION_ALL; - pmsg->source_ = name_; - pmsg->data_.accountID_ = pTradingAccount->AccountID; - pmsg->data_.previousDayEquityWithLoanValue_ = pTradingAccount->PreBalance; - pmsg->data_.netLiquidation_ = netLiquidation; - pmsg->data_.availableFunds_ = pTradingAccount->Available; - pmsg->data_.commission_ = pTradingAccount->Commission; - pmsg->data_.fullMaintainanceMargin_ = pTradingAccount->CurrMargin; - pmsg->data_.realizedPnL_ = pTradingAccount->CloseProfit; - pmsg->data_.unrealizedPnL_ = pTradingAccount->PositionProfit; - pmsg->data_.frozen_ = pTradingAccount->FrozenMargin + pTradingAccount->FrozenCash + pTradingAccount->FrozenCommission; - pmsg->data_.balance_ = pTradingAccount->Balance; - messenger_->send(pmsg); - PortfolioManager::instance().accinfomap_[ctpacc_.userid] = pmsg->data_; - LOG_INFO(logger,name_ <<" OnRspQryTradingAccount:" - <<" AccountID="<AccountID - <<" Available="<Available - <<" PreBalance="<PreBalance - <<" Deposit="<Deposit - <<" Withdraw="<Withdraw - <<" WithdrawQuota="<WithdrawQuota - <<" Commission="<Commission - <<" CurrMargin="<CurrMargin - <<" FrozenMargin="<FrozenMargin - <<" CloseProfit="<CloseProfit - <<" PositionProfit="<PositionProfit - <<" Balance="<Balance - ); - } - else { - string errormsgutf8; - errormsgutf8 = boost::locale::conv::between( pRspInfo->ErrorMsg, "UTF-8", "GB18030" ); - auto pmsgout = make_shared(DESTINATION_ALL, name_, - MSG_TYPE_ERROR_QRY_ACC, - fmt::format("Ctp Td Qry acc error, errorID={}, errorMsg={}", pRspInfo->ErrorID,errormsgutf8) - ); - messenger_->send(pmsgout); - LOG_ERROR(logger,name_ <<" Qry Acc error:"<StrikePrice; pInstrument->EndDelivDate; pInstrument->IsTrading; - bool bResult = (pRspInfo != nullptr) && (pRspInfo->ErrorID != 0); - if (bIsLast){ - lastQryTime_ = getMicroTime(); - } - if(bResult){ - string errormsgutf8; - errormsgutf8 = boost::locale::conv::between( pRspInfo->ErrorMsg, "UTF-8", "GB18030" ); - auto pmsgout = make_shared(DESTINATION_ALL, name_, - MSG_TYPE_ERROR_QRY_CONTRACT, - fmt::format("Ctp Td Qry instrument error, errorID={}, errorMsg={}", pRspInfo->ErrorID,errormsgutf8) - ); - messenger_->send(pmsgout); - LOG_ERROR(logger,name_ <<" Qry Instrument error:"<(); - pmsg->destination_ = DESTINATION_ALL; - pmsg->source_ = name_; - pmsg->data_.symbol_ = pInstrument->InstrumentID; - pmsg->data_.exchange_ = pInstrument->ExchangeID; - pmsg->data_.securityType_ = pInstrument->ProductClass ; - pmsg->data_.multiplier_ = pInstrument->VolumeMultiple; - pmsg->data_.localName_ = GBKToUTF8(pInstrument->InstrumentName); - pmsg->data_.ticksize_ = pInstrument->PriceTick; - pmsg->data_.postype_ = pInstrument->PositionType; - pmsg->data_.longMarginRatio_ = pInstrument->LongMarginRatio == numeric_limits::max()? 0.0: pInstrument->LongMarginRatio; - pmsg->data_.shortMarginRatio_ = pInstrument->ShortMarginRatio == numeric_limits::max()? 0.0: pInstrument->ShortMarginRatio; - - if (pInstrument->ProductClass == THOST_FTDC_PC_Options ){ - pmsg->data_.underlyingSymbol_ = pInstrument->UnderlyingInstrID ; - pmsg->data_.optionType_ = pInstrument->OptionsType; - pmsg->data_.strikePrice_ = pInstrument->StrikePrice; - pmsg->data_.expiryDate_ = pInstrument-> ExpireDate; - } - - messenger_->send(pmsg); - // string symbol = boost::to_upper_copy(string(pInstrument->InstrumentName)); - - string symbol = pInstrument->InstrumentID; - DataManager::instance().securityDetails_[symbol] = pmsg->data_; - // auto it = DataManager::instance().securityDetails_.find(symbol); - // if (it == DataManager::instance().securityDetails_.end()) { - // DataManager::instance().securityDetails_[symbol] = pmsg->data_; - // } - if (bIsLast){ - //DataManager::instance().saveSecurityToFile(); - DataManager::instance().saveSecurityFile_ = true; - LOG_DEBUG(logger,name_ <<" OnRspQryInstrument:" - <<" InstrumentID="<InstrumentID - <<" InstrumentName="<InstrumentName) - <<" ExchangeID="<ExchangeID - <<" ExchangeInstID="<ExchangeInstID - <<" PriceTick="<PriceTick - <<" VolumeMultiple="<VolumeMultiple - <<" UnderlyingInstrID="<UnderlyingInstrID - <<" ProductClass="<ProductClass - <<" ExpireDate="<ExpireDate - <<" LongMarginRatio="<LongMarginRatio - ); - } +void CtpTDEngine::OnRspQryOrder( + CThostFtdcOrderField *pOrder, + CThostFtdcRspInfoField *pRspInfo, + int32_t nRequestID, + bool bIsLast) { - } - } - ///错误应答 - void CtpTDEngine::OnRspError(CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast) { - bool bResult = (pRspInfo != nullptr) && (pRspInfo->ErrorID != 0); - if (bResult){ - string errormsgutf8; - errormsgutf8 = boost::locale::conv::between( pRspInfo->ErrorMsg, "UTF-8", "GB18030" ); - auto pmsgout = make_shared(DESTINATION_ALL, name_, - MSG_TYPE_ERROR, - fmt::format("Ctp.td OnRspError: ErrorID={},ErrorMsg={}",pRspInfo->ErrorID,errormsgutf8) - ); - LOG_ERROR(logger,name_ <<" server OnRspError: ErrorID="<ErrorID <<"ErrorMsg="<ErrorID != 0); + if (bIsLast) { + lastQryTime_ = getMicroTime(); } - ///报单通知 - void CtpTDEngine::OnRtnOrder(CThostFtdcOrderField *pOrder) { - if(pOrder == nullptr){ - LOG_INFO(logger,name_ <<" onRtnOrder return nullptr"); + if (!bResult) { + if (pOrder == nullptr) { + LOG_INFO(logger, name_ << " onQryOrder return nullptr"); return; } - string localno = to_string(pOrder->FrontID) + "." + to_string(pOrder->SessionID) + "." + pOrder->OrderRef ; - //long nOrderref = std::stol(pOrder->OrderRef); - //bool isotherorder = (pOrder->FrontID != frontID_) || (pOrder->SessionID != sessionID_) ; + string localno = + to_string(pOrder->FrontID) + "." + to_string(pOrder->SessionID) + "." + pOrder->OrderRef; shared_ptr o = OrderManager::instance().retrieveOrderFromAccAndLocalNo(ctpacc_.userid,localno); - if ( o == nullptr) { // create an order + if (o == nullptr) { // create an order o = make_shared(); o->api_ = "CTP.TD"; - o->account_ = ctpacc_.userid; + o->account_ = ctpacc_.userid; // o->fullSymbol_ = CConfig::instance().CtpSymbolToSecurityFullName(pOrder->InstrumentID); o->fullSymbol_ = DataManager::instance().ctp2Full_[pOrder->InstrumentID]; o->price_ = pOrder->LimitPrice; - int dir_ = pOrder->Direction != THOST_FTDC_D_Sell ? 1:-1 ; - o->quantity_ = dir_ * pOrder->VolumeTotalOriginal ; - o->tradedvol_ = dir_ * pOrder->VolumeTraded ;//pOrder->VolumeTotalOriginal - pOrder->VolumeTotal + int32_t dir_ = pOrder->Direction != THOST_FTDC_D_Sell ? 1:-1; + o->quantity_ = dir_ * pOrder->VolumeTotalOriginal; + o->tradedvol_ = dir_ * pOrder->VolumeTraded; o->flag_ = CtpComboOffsetFlagToOrderFlag(pOrder->CombOffsetFlag[0]); - o->tag_ = string("14") + o->tag_ = string("14") + ":h" + pOrder->CombHedgeFlag + ":p" + pOrder->OrderPriceType + ":c" + pOrder->ContingentCondition + ":" + to_string(pOrder->StopPrice) @@ -1550,26 +1068,14 @@ namespace StarQuant o->updateTime_ = ymdhmsf(); o->orderStatus_ =CtpOrderStatusToOrderStatus(pOrder->OrderStatus); OrderManager::instance().trackOrder(o); - auto pmsgout = make_shared(DESTINATION_ALL,name_); + auto pmsgout = make_shared(DESTINATION_ALL, name_); pmsgout->set(o); - messenger_->send(pmsgout); + messenger_->send(pmsgout); auto pmsgout2 = make_shared(DESTINATION_ALL, name_, MSG_TYPE_ERROR_ORGANORDER, - fmt::format("OnRtnOrder OrderManager cannot find LocalNo:{}",localno) - ); + fmt::format("OM don't record this order:{}.", localno)); messenger_->send(pmsgout2); - LOG_ERROR(logger,name_ <<" OnRtnOrder OrderManager cannot find LocalNo:"<orderStatus_ = CtpOrderStatusToOrderStatus(pOrder->OrderStatus); - o->orderNo_ = pOrder->OrderSysID; - o->updateTime_ = ymdhmsf(); - o->tradedvol_ = pOrder->VolumeTraded; - auto pmsgout = make_shared(to_string(o->clientID_),name_); - pmsgout->set(o); - messenger_->send(pmsgout); - } - LOG_INFO(logger,name_ <<" OnRtnOrder details:" + LOG_INFO(logger, name_ <<" OnQryOrder details:" <<" InstrumentID="<InstrumentID <<" OrderRef="<OrderRef <<" ExchangeID="<ExchangeID @@ -1585,15 +1091,41 @@ namespace StarQuant <<" LimitPrice="<LimitPrice <<" VolumeTotalOriginal="<VolumeTotalOriginal <<" VolumeTraded="<VolumeTraded - <<" VolumeTotal"<VolumeTotal <<" OrderSysID="<OrderSysID <<" SequenceNo="<SequenceNo - ); + ); + } else { + o->orderStatus_ = CtpOrderStatusToOrderStatus(pOrder->OrderStatus); + o->orderNo_ = pOrder->OrderSysID; + o->updateTime_ = ymdhmsf(); + auto pmsgout = make_shared(to_string(o->clientID_), name_); + pmsgout->set(o); + messenger_->send(pmsgout); + } + } else { + string errormsgutf8; + errormsgutf8 = boost::locale::conv::between( pRspInfo->ErrorMsg, "UTF-8", "GB18030"); + auto pmsgout = make_shared(DESTINATION_ALL, name_, + MSG_TYPE_ERROR_QRY_POS, + fmt::format("Ctp.td qry order error: ErrorID={},ErrorMsg={}",pRspInfo->ErrorID,errormsgutf8)); + messenger_->send(pmsgout); + LOG_ERROR(logger, name_ <<" Qry order error, errorID="<ErrorID<<" ErrorMsg:"<ErrorID != 0); + if (bIsLast) { + lastQryTime_ = getMicroTime(); + } + if (!bResult) { + if (pTrade == nullptr) { + LOG_INFO(logger, name_ <<" onQrytrade return nullptr"); return; } auto pmsg = make_shared(); @@ -1609,8 +1141,6 @@ namespace StarQuant pmsg->data_.tradePrice_ = pTrade->Price; pmsg->data_.tradeSize_ = (pTrade->Direction == THOST_FTDC_D_Buy ? 1 : -1)*pTrade->Volume; pmsg->data_.fillFlag_ = CtpComboOffsetFlagToOrderFlag(pTrade->OffsetFlag); - //auto o = OrderManager::instance().retrieveOrderFromServerOrderId(std::stol(pTrade->OrderRef)); - string localno = to_string(frontID_) + "." + to_string(sessionID_) + "." + pTrade->OrderRef; auto o = OrderManager::instance().retrieveOrderFromAccAndLocalNo(ctpacc_.userid,localno); auto o2 = OrderManager::instance().retrieveOrderFromOrderNo(pTrade->OrderSysID); @@ -1623,14 +1153,13 @@ namespace StarQuant pmsg->data_.account_ = o2->account_; pmsg->data_.clientID_ = o2->clientID_; pmsg->data_.api_ = o2->api_; - //o->fillNo_ = pTrade->TradeID; + // o->fillNo_ = pTrade->TradeID; OrderManager::instance().gotFill(pmsg->data_); messenger_->send(pmsg); - auto pmsgos = make_shared(to_string(o2->clientID_),name_); + auto pmsgos = make_shared(to_string(o2->clientID_), name_); pmsgos->set(o2); - messenger_->send(pmsgos); - } - else if (o != nullptr) { + messenger_->send(pmsgos); + } else if (o != nullptr) { pmsg->data_.serverOrderID_ = o->serverOrderID_; pmsg->data_.clientOrderID_ = o->clientOrderID_; pmsg->data_.brokerOrderID_ = o->brokerOrderID_; @@ -1640,23 +1169,19 @@ namespace StarQuant pmsg->data_.api_ = o->api_; //o->fillNo_ = pTrade->TradeID; OrderManager::instance().gotFill(pmsg->data_); - messenger_->send(pmsg); + messenger_->send(pmsg); auto pmsgos = make_shared(to_string(o->clientID_),name_); pmsgos->set(o); - messenger_->send(pmsgos); - } - else { + messenger_->send(pmsgos); + } else { pmsg->data_.api_ = "CTP.TD"; pmsg->data_.account_ = ctpacc_.userid; messenger_->send(pmsg); auto pmsgout = make_shared(DESTINATION_ALL, name_, MSG_TYPE_ERROR_ORGANORDER, - fmt::format("OnRtnTrade ordermanager cannot find orderNo:{}",pTrade->OrderSysID) - ); - messenger_->send(pmsgout); - LOG_ERROR(logger,name_ <<" OnRtnTrade ordermanager cannot find orderNo:"<OrderSysID); - } - LOG_INFO(logger,name_ <<" OnRtnTrade details:" + fmt::format("OM dont record this order:{}.",pTrade->OrderSysID)); + messenger_->send(pmsgout); + LOG_INFO(logger, name_ <<" OnQryTrade details:" <<" TradeID="<TradeID <<" OrderRef="<OrderRef <<" InstrumentID="<InstrumentID @@ -1666,162 +1191,632 @@ namespace StarQuant <<" Direction="<Direction <<" Price="<Price <<" Volume="<Volume - ); - } - ///交易所报单录入错误回报 - void CtpTDEngine::OnErrRtnOrderInsert(CThostFtdcInputOrderField *pInputOrder, CThostFtdcRspInfoField *pRspInfo) { - bool bResult = (pRspInfo != nullptr) && (pRspInfo->ErrorID != 0); - if(bResult){ - if (pInputOrder == nullptr){ - LOG_INFO(logger,name_ <<" OnErrRtnOrderInsert return nullptr"); - return; - } - string errormsgutf8; - errormsgutf8 = boost::locale::conv::between( pRspInfo->ErrorMsg, "UTF-8", "GB18030" ); - string localno = to_string(frontID_) + "." + to_string(sessionID_) + "." + pInputOrder->OrderRef; - std::shared_ptr o = OrderManager::instance().retrieveOrderFromAccAndLocalNo(ctpacc_.userid,localno); - if (o != nullptr) { - lock_guard g(orderStatus_mtx); - o->orderStatus_ = OS_Error; // rejected - o->updateTime_ = ymdhmsf(); - auto pmsgout = make_shared(to_string(o->clientID_), name_, - MSG_TYPE_ERROR_INSERTORDER, - fmt::format("OnErrRtnOrderInsert,osid:{}",o->serverOrderID_)); - messenger_->send(pmsgout); - - auto pmsgout2 = make_shared(to_string(o->clientID_),name_); - pmsgout2->set(o); - messenger_->send(pmsgout2); - } - else { - auto pmsgout = make_shared(DESTINATION_ALL, name_, - MSG_TYPE_ERROR_ORGANORDER, - fmt::format("OnErrRtnOrderInsert ordermanager cannot find orderref:{}",localno) - ); - messenger_->send(pmsgout); - LOG_ERROR(logger,name_ <<" OnErrRtnOrderInsert ordermanager cannot find orderref:"<OrderRef); - } - LOG_ERROR(logger,name_ <<" OnErrRtnOrderinsert:" - <<" ErrorMsg:"<ErrorMsg, "UTF-8", "GB18030" ); + auto pmsgout = make_shared(DESTINATION_ALL, name_, + MSG_TYPE_ERROR_QRY_POS, + fmt::format("Ctp Td Qry order error, errorID={}, errorMsg={}", pRspInfo->ErrorID,errormsgutf8) + ); + messenger_->send(pmsgout); + LOG_ERROR(logger, name_ <<" Qry order error, errorID="<ErrorID<<" ErrorMsg:"<ErrorID != 0); - if(bResult){ - string errormsgutf8; - errormsgutf8 = boost::locale::conv::between( pRspInfo->ErrorMsg, "UTF-8", "GB18030" ); - string localno = to_string(pOrderAction->FrontID) + "." + to_string(pOrderAction->SessionID) + "." + pOrderAction->OrderRef; - std::shared_ptr o = OrderManager::instance().retrieveOrderFromAccAndLocalNo(ctpacc_.userid,localno); - if (o != nullptr) { - auto pmsgout = make_shared(to_string(o->clientID_), name_, - MSG_TYPE_ERROR_CANCELORDER, - fmt::format("OnErrRtnOrderAction, osid:{}",o->serverOrderID_) ); - messenger_->send(pmsgout); - } - else - { - auto pmsgout = make_shared(DESTINATION_ALL, name_, - MSG_TYPE_ERROR_ORGANORDER, - fmt::format("OnErrRtnOrderAction OrderManager cannot find order,OrderRef:{}", localno) - ); - messenger_->send(pmsgout); - LOG_ERROR(logger,name_ <<" OnErrRtnOrderAction OrderManager cannot find order,OrderRef="<ErrorID != 0); + if (bIsLast) { + lastQryTime_ = getMicroTime(); + } + if (!bResult) { + if (pInvestorPositionDetail == nullptr) { + LOG_DEBUG(logger, name_ <<" onRspQryposdetail return nullptr."); + return; } + LOG_INFO(logger, name_ <<" OnRspQryInvestorPositionDetail:" + <<" InstrumentID="<InstrumentID + <<" Position="<Direction + <<" OpenDate="<OpenDate + <<" Volume="<Volume + <<" OpenPirce="<OpenPrice + <<" Margin="<Margin + <<" MarginRateByMoney="<MarginRateByMoney + <<" CloseVolume="<CloseVolume + <<" CloseProfitByTrade="<CloseProfitByTrade + <<" PositionProfitByTrade="<PositionProfitByTrade + <<" islast="<ErrorMsg, "UTF-8", "GB18030" ); + auto pmsgout = make_shared(DESTINATION_ALL, name_, + MSG_TYPE_ERROR_QRY_POS, + fmt::format("Ctp Td Qry posdetail error, errorID={}, errorMsg={}", pRspInfo->ErrorID,errormsgutf8) + ); + messenger_->send(pmsgout); + LOG_ERROR(logger, name_ <<" Qry posdetail error, errorID="<ErrorID<<" ErrorMsg:"<ErrorID != 0); + if (bIsLast) { + lastQryTime_ = getMicroTime(); + } + if (!bResult) { + if (pInvestorPosition == nullptr) { + LOG_DEBUG(logger, name_ <<" onRspQrypos return nullptr."); + return; } - else { - return OrderStatus::OS_UNKNOWN; + // string fullsym = CConfig::instance().CtpSymbolToSecurityFullName(pInvestorPosition->InstrumentID); + string fullsym = DataManager::instance().ctp2Full_[pInvestorPosition->InstrumentID]; + string exchid = stringsplit(fullsym,' ')[0]; + string key = ctpacc_.userid + "." + fullsym + "." + pInvestorPosition->PosiDirection; + + // auto pos = PortfolioManager::instance().retrievePosition(key); + std::shared_ptr pos; + if (posbuffer_.find(key) == posbuffer_.end()) { + pos = std::make_shared(); + pos->key_ = key; + pos->account_ = ctpacc_.userid; + pos->fullSymbol_ = fullsym; + pos->api_ = "CTP.TD"; + posbuffer_[key] = pos; + } else { + pos = posbuffer_[key]; + } + pos->type_ = pInvestorPosition->PosiDirection; + // int32_t dirsign = pInvestorPosition->PosiDirection == THOST_FTDC_PD_Short ? -1 : 1; + if (exchid == "SHFE") { + if ((pInvestorPosition->YdPosition != 0 ) && (pInvestorPosition->TodayPosition == 0)) + pos->preSize_ = pInvestorPosition->Position; + } else { + pos->preSize_ = (pInvestorPosition->Position - pInvestorPosition->TodayPosition); + } + int32_t multiples = DataManager::instance().securityDetails_[pInvestorPosition->InstrumentID].multiplier_; + + double cost = pos->avgPrice_ * pos->size_ * multiples; + pos->size_ += pInvestorPosition->Position; + pos->openpl_ += pInvestorPosition->PositionProfit; + if (pos->size_ != 0 && multiples) { + cost += pInvestorPosition->PositionCost; + pos->avgPrice_ = cost /(pos->size_ * multiples); + } + if (pos->type_ == THOST_FTDC_PD_Long) { + pos->freezedSize_ += pInvestorPosition->ShortFrozen; + } else { + pos->freezedSize_ += pInvestorPosition->LongFrozen; + } + pos->closedpl_ += pInvestorPosition->CloseProfit; + if (bIsLast) { + for (auto iter = posbuffer_.begin(); iter != posbuffer_.end(); ++iter) { + auto pmsg = make_shared(DESTINATION_ALL, name_); + pmsg->set(iter->second); + messenger_->send(pmsg); + PortfolioManager::instance().Add(iter->second); + } + posbuffer_.clear(); + } + LOG_INFO(logger, name_ <<" OnRspQryInvestorPosition:" + <<" InstrumentID="<InstrumentID + <<" InvestorID="<InvestorID + <<" Position="<Position + <<" OpenAmount="<OpenAmount + <<" OpenVolume="<OpenVolume + <<" OpenCost=" <OpenCost + <<" PosiDirection="<PosiDirection + <<" PositionProfit="<PositionProfit + <<" PositionCost="<PositionCost + <<" UseMargin="<UseMargin + <<" LongFrozen="<LongFrozen + <<" ShortFrozen="<ShortFrozen + <<" TradingDay="<TradingDay + <<" YdPosition="<YdPosition + <<" islast="<ErrorMsg, "UTF-8", "GB18030" ); + auto pmsgout = make_shared(DESTINATION_ALL, name_, + MSG_TYPE_ERROR_QRY_POS, + fmt::format("Ctp Td Qry pos error, errorID={}, errorMsg={}", pRspInfo->ErrorID, errormsgutf8) + ); + messenger_->send(pmsgout); + LOG_ERROR(logger, name_ <<" Qry pos error, errorID="<ErrorID<<" ErrorMsg:"<ErrorID != 0); + if (bIsLast) { + lastQryTime_ = getMicroTime(); + } + if (!bResult) { + if (pTradingAccount == nullptr) { + LOG_INFO(logger, name_ <<" qry acc return nullptr"); + return; } + double netLiquidation = pTradingAccount->PreBalance - pTradingAccount->PreCredit - pTradingAccount->PreMortgage + + pTradingAccount->Mortgage - pTradingAccount->Withdraw + pTradingAccount->Deposit + + pTradingAccount->CloseProfit + pTradingAccount->PositionProfit + pTradingAccount->CashIn - pTradingAccount->Commission; + auto pmsg = make_shared(); + pmsg->destination_ = DESTINATION_ALL; + pmsg->source_ = name_; + pmsg->data_.accountID_ = pTradingAccount->AccountID; + pmsg->data_.previousDayEquityWithLoanValue_ = pTradingAccount->PreBalance; + pmsg->data_.netLiquidation_ = netLiquidation; + pmsg->data_.availableFunds_ = pTradingAccount->Available; + pmsg->data_.commission_ = pTradingAccount->Commission; + pmsg->data_.fullMaintainanceMargin_ = pTradingAccount->CurrMargin; + pmsg->data_.realizedPnL_ = pTradingAccount->CloseProfit; + pmsg->data_.unrealizedPnL_ = pTradingAccount->PositionProfit; + pmsg->data_.frozen_ = pTradingAccount->FrozenMargin + pTradingAccount->FrozenCash + pTradingAccount->FrozenCommission; + pmsg->data_.balance_ = pTradingAccount->Balance; + messenger_->send(pmsg); + PortfolioManager::instance().accinfomap_[ctpacc_.userid] = pmsg->data_; + LOG_INFO(logger, name_ <<" OnRspQryTradingAccount:" + <<" AccountID="<AccountID + <<" Available="<Available + <<" PreBalance="<PreBalance + <<" Deposit="<Deposit + <<" Withdraw="<Withdraw + <<" WithdrawQuota="<WithdrawQuota + <<" Commission="<Commission + <<" CurrMargin="<CurrMargin + <<" FrozenMargin="<FrozenMargin + <<" CloseProfit="<CloseProfit + <<" PositionProfit="<PositionProfit + <<" Balance="<Balance + ); + } else { + string errormsgutf8; + errormsgutf8 = boost::locale::conv::between( pRspInfo->ErrorMsg, "UTF-8", "GB18030" ); + auto pmsgout = make_shared(DESTINATION_ALL, name_, + MSG_TYPE_ERROR_QRY_ACC, + fmt::format("Ctp Td Qry acc error, errorID={}, errorMsg={}", pRspInfo->ErrorID,errormsgutf8) + ); + messenger_->send(pmsgout); + LOG_ERROR(logger, name_ << " Qry Acc error:" << errormsgutf8); } - OrderFlag CtpTDEngine::CtpComboOffsetFlagToOrderFlag(const char flag) { - OrderFlag f; - - switch (flag) { - case THOST_FTDC_OF_Open: - f = OrderFlag::OF_OpenPosition; - break; - case THOST_FTDC_OF_Close: - f = OrderFlag::OF_ClosePosition; - break; - case THOST_FTDC_OF_ForceClose: - f = OrderFlag::OF_ForceClose; - break; - case THOST_FTDC_OF_CloseToday: - f = OrderFlag::OF_CloseToday; - break; - case THOST_FTDC_OF_CloseYesterday: - f = OrderFlag::OF_CloseYesterday; - break; - default: - f = OrderFlag::OF_OpenPosition; - break; +} +///请求查询合约响应 +void CtpTDEngine::OnRspQryInstrument( + CThostFtdcInstrumentField *pInstrument, + CThostFtdcRspInfoField *pRspInfo, + int32_t nRequestID, + bool bIsLast) { + + // pInstrument->StrikePrice; pInstrument->EndDelivDate; pInstrument->IsTrading; + bool bResult = (pRspInfo != nullptr) && (pRspInfo->ErrorID != 0); + if (bIsLast) { + lastQryTime_ = getMicroTime(); + } + if (bResult) { + string errormsgutf8; + errormsgutf8 = boost::locale::conv::between( pRspInfo->ErrorMsg, "UTF-8", "GB18030" ); + auto pmsgout = make_shared(DESTINATION_ALL, name_, + MSG_TYPE_ERROR_QRY_CONTRACT, + fmt::format("Ctp Td Qry instrument error, errorID={}, errorMsg={}", pRspInfo->ErrorID,errormsgutf8) + ); + messenger_->send(pmsgout); + LOG_ERROR(logger, name_ <<" Qry Instrument error:"<(); + pmsg->destination_ = DESTINATION_ALL; + pmsg->source_ = name_; + pmsg->data_.symbol_ = pInstrument->InstrumentID; + pmsg->data_.exchange_ = pInstrument->ExchangeID; + pmsg->data_.securityType_ = pInstrument->ProductClass ; + pmsg->data_.multiplier_ = pInstrument->VolumeMultiple; + pmsg->data_.localName_ = GBKToUTF8(pInstrument->InstrumentName); + pmsg->data_.ticksize_ = pInstrument->PriceTick; + pmsg->data_.postype_ = pInstrument->PositionType; + pmsg->data_.longMarginRatio_ = pInstrument->LongMarginRatio == numeric_limits::max()? 0.0: pInstrument->LongMarginRatio; + pmsg->data_.shortMarginRatio_ = pInstrument->ShortMarginRatio == numeric_limits::max()? 0.0: pInstrument->ShortMarginRatio; + + if (pInstrument->ProductClass == THOST_FTDC_PC_Options) { + pmsg->data_.underlyingSymbol_ = pInstrument->UnderlyingInstrID; + pmsg->data_.optionType_ = pInstrument->OptionsType; + pmsg->data_.strikePrice_ = pInstrument->StrikePrice; + pmsg->data_.expiryDate_ = pInstrument-> ExpireDate; + } + + messenger_->send(pmsg); + // string symbol = boost::to_upper_copy(string(pInstrument->InstrumentName)); + + string symbol = pInstrument->InstrumentID; + DataManager::instance().securityDetails_[symbol] = pmsg->data_; + // auto it = DataManager::instance().securityDetails_.find(symbol); + // if (it == DataManager::instance().securityDetails_.end()) { + // DataManager::instance().securityDetails_[symbol] = pmsg->data_; + // } + if (bIsLast) { + //DataManager::instance().saveSecurityToFile(); + DataManager::instance().saveSecurityFile_ = true; + LOG_DEBUG(logger, name_ <<" OnRspQryInstrument:" + <<" InstrumentID="<InstrumentID + <<" InstrumentName="<InstrumentName) + <<" ExchangeID="<ExchangeID + <<" ExchangeInstID="<ExchangeInstID + <<" PriceTick="<PriceTick + <<" VolumeMultiple="<VolumeMultiple + <<" UnderlyingInstrID="<UnderlyingInstrID + <<" ProductClass="<ProductClass + <<" ExpireDate="<ExpireDate + <<" LongMarginRatio="<LongMarginRatio + ); } - return f; } +} +// 错误应答 +void CtpTDEngine::OnRspError(CThostFtdcRspInfoField *pRspInfo, int32_t nRequestID, bool bIsLast) { + bool bResult = (pRspInfo != nullptr) && (pRspInfo->ErrorID != 0); + if (bResult) { + string errormsgutf8; + errormsgutf8 = boost::locale::conv::between( pRspInfo->ErrorMsg, "UTF-8", "GB18030" ); + auto pmsgout = make_shared(DESTINATION_ALL, name_, + MSG_TYPE_ERROR, + fmt::format("Ctp.td OnRspError: ErrorID={},ErrorMsg={}",pRspInfo->ErrorID,errormsgutf8) + ); + LOG_ERROR(logger, name_ <<" server OnRspError: ErrorID="<ErrorID <<"ErrorMsg="<FrontID) + "." + to_string(pOrder->SessionID) + "." + pOrder->OrderRef ; + //int64_t nOrderref = std::stol(pOrder->OrderRef); + //bool isotherorder = (pOrder->FrontID != frontID_) || (pOrder->SessionID != sessionID_) ; + shared_ptr o = OrderManager::instance().retrieveOrderFromAccAndLocalNo(ctpacc_.userid,localno); + if (o == nullptr) { // create an order + o = make_shared(); + o->api_ = "CTP.TD"; + o->account_ = ctpacc_.userid; + // o->fullSymbol_ = CConfig::instance().CtpSymbolToSecurityFullName(pOrder->InstrumentID); + o->fullSymbol_ = DataManager::instance().ctp2Full_[pOrder->InstrumentID]; + o->price_ = pOrder->LimitPrice; + int32_t dir_ = pOrder->Direction != THOST_FTDC_D_Sell ? 1:-1; + o->quantity_ = dir_ * pOrder->VolumeTotalOriginal; + o->tradedvol_ = dir_ * pOrder->VolumeTraded ; // pOrder->VolumeTotalOriginal - pOrder->VolumeTotal + o->flag_ = CtpComboOffsetFlagToOrderFlag(pOrder->CombOffsetFlag[0]); + o->tag_ = string("14") + + ":h" + pOrder->CombHedgeFlag + + ":p" + pOrder->OrderPriceType + + ":c" + pOrder->ContingentCondition + ":" + to_string(pOrder->StopPrice) + + ":t" + pOrder->TimeCondition + + ":v" + pOrder->VolumeCondition; + lock_guard g(oid_mtx); + o->serverOrderID_ = m_serverOrderId++; + o->brokerOrderID_ = m_brokerOrderId_++; + o->orderNo_ = pOrder->OrderSysID; + o->localNo_ = localno; + o->createTime_ = string(pOrder->InsertDate) + " " + string(pOrder->InsertTime); + o->updateTime_ = ymdhmsf(); + o->orderStatus_ = CtpOrderStatusToOrderStatus(pOrder->OrderStatus); + OrderManager::instance().trackOrder(o); + auto pmsgout = make_shared(DESTINATION_ALL, name_); + pmsgout->set(o); + messenger_->send(pmsgout); + auto pmsgout2 = make_shared(DESTINATION_ALL, name_, + MSG_TYPE_ERROR_ORGANORDER, + fmt::format("OnRtnOrder OrderManager cannot find LocalNo:{}", localno)); + messenger_->send(pmsgout2); + LOG_ERROR(logger, name_ <<" OnRtnOrder OrderManager cannot find LocalNo:" << localno); + } else { + o->orderStatus_ = CtpOrderStatusToOrderStatus(pOrder->OrderStatus); + o->orderNo_ = pOrder->OrderSysID; + o->updateTime_ = ymdhmsf(); + o->tradedvol_ = pOrder->VolumeTraded; + auto pmsgout = make_shared(to_string(o->clientID_), name_); + pmsgout->set(o); + messenger_->send(pmsgout); + } + LOG_INFO(logger, name_ <<" OnRtnOrder details:" + <<" InstrumentID="<InstrumentID + <<" OrderRef="<OrderRef + <<" ExchangeID="<ExchangeID + <<" InsertTime="<InsertTime + <<" CancelTime="<CancelTime + <<" FrontID="<FrontID + <<" SessionID="<SessionID + <<" Direction="<Direction + <<" CombOffsetFlag="<CombOffsetFlag + <<" OrderStatus="<OrderStatus + <<" OrderSubmitStatus="<OrderSubmitStatus + <<" StatusMsg="<StatusMsg) + <<" LimitPrice="<LimitPrice + <<" VolumeTotalOriginal="<VolumeTotalOriginal + <<" VolumeTraded="<VolumeTraded + <<" VolumeTotal"<VolumeTotal + <<" OrderSysID="<OrderSysID + <<" SequenceNo="<SequenceNo + ); +} +/// 成交通知 +void CtpTDEngine::OnRtnTrade(CThostFtdcTradeField *pTrade) { + if (pTrade == nullptr) { + LOG_INFO(logger, name_ <<" onRtnTrade return nullptr"); + return; + } + auto pmsg = make_shared(); + pmsg->destination_ = DESTINATION_ALL; + pmsg->source_ = name_; + // pmsg->data_.fullSymbol_ = CConfig::instance().CtpSymbolToSecurityFullName(pTrade->InstrumentID); + pmsg->data_.fullSymbol_ = DataManager::instance().ctp2Full_[pTrade->InstrumentID]; + pmsg->data_.tradeTime_ = pTrade->TradeTime; + //pmsg->data_.serverOrderID_ = std::stol(pTrade->OrderRef); + pmsg->data_.orderNo_ = pTrade->OrderSysID; + //pmsg->data_.tradeId = std::stoi(pTrade->TraderID); + pmsg->data_.tradeNo_ = pTrade->TradeID; + pmsg->data_.tradePrice_ = pTrade->Price; + pmsg->data_.tradeSize_ = (pTrade->Direction == THOST_FTDC_D_Buy ? 1 : -1)*pTrade->Volume; + pmsg->data_.fillFlag_ = CtpComboOffsetFlagToOrderFlag(pTrade->OffsetFlag); + //auto o = OrderManager::instance().retrieveOrderFromServerOrderId(std::stol(pTrade->OrderRef)); + + string localno = to_string(frontID_) + "." + to_string(sessionID_) + "." + pTrade->OrderRef; + auto o = OrderManager::instance().retrieveOrderFromAccAndLocalNo(ctpacc_.userid,localno); + auto o2 = OrderManager::instance().retrieveOrderFromOrderNo(pTrade->OrderSysID); + //bool islocalorder = ( (o != nullptr) && !(o2 != nullptr && o2->localNo_ != localno) ); + if (o2 != nullptr) { + pmsg->data_.serverOrderID_ = o2->serverOrderID_; + pmsg->data_.clientOrderID_ = o2->clientOrderID_; + pmsg->data_.brokerOrderID_ = o2->brokerOrderID_; + pmsg->data_.localNo_ = o2->localNo_; + pmsg->data_.account_ = o2->account_; + pmsg->data_.clientID_ = o2->clientID_; + pmsg->data_.api_ = o2->api_; + //o->fillNo_ = pTrade->TradeID; + OrderManager::instance().gotFill(pmsg->data_); + messenger_->send(pmsg); + auto pmsgos = make_shared(to_string(o2->clientID_),name_); + pmsgos->set(o2); + messenger_->send(pmsgos); + } else if (o != nullptr) { + pmsg->data_.serverOrderID_ = o->serverOrderID_; + pmsg->data_.clientOrderID_ = o->clientOrderID_; + pmsg->data_.brokerOrderID_ = o->brokerOrderID_; + pmsg->data_.localNo_ = localno; + pmsg->data_.account_ = o->account_; + pmsg->data_.clientID_ = o->clientID_; + pmsg->data_.api_ = o->api_; + //o->fillNo_ = pTrade->TradeID; + OrderManager::instance().gotFill(pmsg->data_); + messenger_->send(pmsg); + auto pmsgos = make_shared(to_string(o->clientID_),name_); + pmsgos->set(o); + messenger_->send(pmsgos); + } else { + pmsg->data_.api_ = "CTP.TD"; + pmsg->data_.account_ = ctpacc_.userid; + messenger_->send(pmsg); + auto pmsgout = make_shared(DESTINATION_ALL, name_, + MSG_TYPE_ERROR_ORGANORDER, + fmt::format("OnRtnTrade ordermanager cannot find orderNo:{}",pTrade->OrderSysID) + ); + messenger_->send(pmsgout); + LOG_ERROR(logger, name_ <<" OnRtnTrade ordermanager cannot find orderNo:"<OrderSysID); + } + LOG_INFO(logger, name_ <<" OnRtnTrade details:" + <<" TradeID="<TradeID + <<" OrderRef="<OrderRef + <<" InstrumentID="<InstrumentID + <<" ExchangeID="<ExchangeID + <<" TradeTime="<TradeTime + <<" OffsetFlag="<OffsetFlag + <<" Direction="<Direction + <<" Price="<Price + <<" Volume="<Volume + ); +} +///交易所报单录入错误回报 +void CtpTDEngine::OnErrRtnOrderInsert( + CThostFtdcInputOrderField *pInputOrder, + CThostFtdcRspInfoField *pRspInfo) { + + bool bResult = (pRspInfo != nullptr) && (pRspInfo->ErrorID != 0); + if (bResult) { + if (pInputOrder == nullptr) { + LOG_INFO(logger, name_ <<" OnErrRtnOrderInsert return nullptr"); + return; + } + string errormsgutf8; + errormsgutf8 = boost::locale::conv::between( pRspInfo->ErrorMsg, "UTF-8", "GB18030" ); + string localno = to_string(frontID_) + "." + to_string(sessionID_) + "." + pInputOrder->OrderRef; + std::shared_ptr o = OrderManager::instance().retrieveOrderFromAccAndLocalNo(ctpacc_.userid,localno); + if (o != nullptr) { + lock_guard g(orderStatus_mtx); + o->orderStatus_ = OS_Error; // rejected + o->updateTime_ = ymdhmsf(); + auto pmsgout = make_shared(to_string(o->clientID_), name_, + MSG_TYPE_ERROR_INSERTORDER, + fmt::format("OnErrRtnOrderInsert,osid:{}",o->serverOrderID_)); + messenger_->send(pmsgout); - char CtpTDEngine::OrderFlagToCtpComboOffsetFlag(const OrderFlag flag) { - char c; - - switch (flag) { - case OrderFlag::OF_OpenPosition: - c = THOST_FTDC_OF_Open; // 开仓 - break; - case OrderFlag::OF_ClosePosition: - c = THOST_FTDC_OF_Close; // 平仓 - break; - case OrderFlag::OF_ForceClose: - c = THOST_FTDC_OF_ForceClose; // 平仓 - break; - case OrderFlag::OF_CloseToday: - c = THOST_FTDC_OF_CloseToday; // 平今 - break; - case OrderFlag::OF_CloseYesterday: - c = THOST_FTDC_OF_CloseYesterday; // 平昨 - break; - default: - c = THOST_FTDC_OF_Open; // 开仓 - break; + auto pmsgout2 = make_shared(to_string(o->clientID_),name_); + pmsgout2->set(o); + messenger_->send(pmsgout2); + } else { + auto pmsgout = make_shared(DESTINATION_ALL, name_, + MSG_TYPE_ERROR_ORGANORDER, + fmt::format("OnErrRtnOrderInsert ordermanager cannot find orderref:{}",localno) + ); + messenger_->send(pmsgout); + LOG_ERROR(logger, name_ <<" OnErrRtnOrderInsert ordermanager cannot find orderref:"<OrderRef); + } + LOG_ERROR(logger, name_ <<" OnErrRtnOrderinsert:" + <<" ErrorMsg:"<ErrorID != 0); + if (bResult){ + string errormsgutf8; + errormsgutf8 = boost::locale::conv::between( pRspInfo->ErrorMsg, "UTF-8", "GB18030" ); + string localno = to_string(pOrderAction->FrontID) + "." + to_string(pOrderAction->SessionID) + "." + pOrderAction->OrderRef; + std::shared_ptr o = OrderManager::instance().retrieveOrderFromAccAndLocalNo(ctpacc_.userid,localno); + if (o != nullptr) { + auto pmsgout = make_shared(to_string(o->clientID_), name_, + MSG_TYPE_ERROR_CANCELORDER, + fmt::format("OnErrRtnOrderAction, osid:{}",o->serverOrderID_) ); + messenger_->send(pmsgout); + } else { + auto pmsgout = make_shared(DESTINATION_ALL, name_, + MSG_TYPE_ERROR_ORGANORDER, + fmt::format("OnErrRtnOrderAction OrderManager cannot find order,OrderRef:{}", localno) + ); + messenger_->send(pmsgout); + LOG_ERROR(logger, name_ <<" OnErrRtnOrderAction OrderManager cannot find order,OrderRef="< -#include -#include - +/***************************************************************************** + * Copyright [2019] + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *****************************************************************************/ + +#ifndef CPPSRC_STARQUANT_ENGINE_CTPTDENGINE_H_ +#define CPPSRC_STARQUANT_ENGINE_CTPTDENGINE_H_ #include #include #include #include +#include +#include +#include +#include +#include +#include +#include using std::mutex; @@ -16,386 +33,386 @@ using std::string; using std::list; using std::vector; -namespace StarQuant -{ - - class CtpTDEngine : public IEngine, CThostFtdcTraderSpi { - public: - string name_; - bool needauthentication_; - bool needsettlementconfirm_; - bool issettleconfirmed_; - int m_brokerOrderId_; - Gateway ctpacc_; - - CtpTDEngine(const string& gw ); - ~CtpTDEngine(); - - virtual void init(); - virtual void start(); - virtual void stop(); - virtual bool connect() ; - virtual bool disconnect() ; - void switchday(); - void releaseapi(); - void reset(); - void timertask(); - void processbuf();// reserverd for future use,such as local condition order, algo-trading etc. - - void insertOrder(shared_ptr pmsg); - void cancelOrder(shared_ptr pmsg); - void cancelAll(shared_ptr pmsg); - void closeAll(const string& fullsym = ""); - void checkLocalOrders(); - - void queryAccount(shared_ptr pmsg); - void queryPosition(shared_ptr pmsg); - void queryContract(shared_ptr pmsg); - void queryOrder(shared_ptr pmsg); - void queryTrade(shared_ptr pmsg); - void queryPositionDetail(shared_ptr pmsg); - - - public: - virtual void OnFrontConnected(); - virtual void OnFrontDisconnected(int nReason); - virtual void OnHeartBeatWarning(int nTimeLapse); - virtual void OnRspAuthenticate(CThostFtdcRspAuthenticateField *pRspAuthenticateField, CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast); - virtual void OnRspUserLogin(CThostFtdcRspUserLoginField *pRspUserLogin, CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast); - ///登出请求响应 - virtual void OnRspUserLogout(CThostFtdcUserLogoutField *pUserLogout, CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast); - ///用户口令更新请求响应 - virtual void OnRspUserPasswordUpdate(CThostFtdcUserPasswordUpdateField *pUserPasswordUpdate, CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast) {}; - ///资金账户口令更新请求响应 - virtual void OnRspTradingAccountPasswordUpdate(CThostFtdcTradingAccountPasswordUpdateField *pTradingAccountPasswordUpdate, CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast) {}; - ///报单录入请求响应 - virtual void OnRspOrderInsert(CThostFtdcInputOrderField *pInputOrder, CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast); - ///预埋单录入请求响应 - virtual void OnRspParkedOrderInsert(CThostFtdcParkedOrderField *pParkedOrder, CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast) {}; - ///预埋撤单录入请求响应 - virtual void OnRspParkedOrderAction(CThostFtdcParkedOrderActionField *pParkedOrderAction, CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast) {}; - ///报单操作请求响应 - virtual void OnRspOrderAction(CThostFtdcInputOrderActionField *pInputOrderAction, CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast); - ///查询最大报单数量响应 - virtual void OnRspQueryMaxOrderVolume(CThostFtdcQueryMaxOrderVolumeField *pQueryMaxOrderVolume, CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast) {}; - ///投资者结算结果确认响应 - virtual void OnRspSettlementInfoConfirm(CThostFtdcSettlementInfoConfirmField *pSettlementInfoConfirm, CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast); - ///删除预埋单响应 - virtual void OnRspRemoveParkedOrder(CThostFtdcRemoveParkedOrderField *pRemoveParkedOrder, CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast) {}; - ///删除预埋撤单响应 - virtual void OnRspRemoveParkedOrderAction(CThostFtdcRemoveParkedOrderActionField *pRemoveParkedOrderAction, CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast) {}; - - ///执行宣告录入请求响应 - virtual void OnRspExecOrderInsert(CThostFtdcInputExecOrderField *pInputExecOrder, CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast) {}; - - ///执行宣告操作请求响应 - virtual void OnRspExecOrderAction(CThostFtdcInputExecOrderActionField *pInputExecOrderAction, CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast) {}; - - ///询价录入请求响应 - virtual void OnRspForQuoteInsert(CThostFtdcInputForQuoteField *pInputForQuote, CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast) {}; +namespace StarQuant { +class CtpTDEngine : public IEngine, CThostFtdcTraderSpi { + public: + string name_; + bool needauthentication_; + bool needsettlementconfirm_; + bool issettleconfirmed_; + int32_t m_brokerOrderId_; + Gateway ctpacc_; + + explicit CtpTDEngine(const string& gw); + ~CtpTDEngine(); + + virtual void init(); + virtual void start(); + virtual void stop(); + virtual bool connect(); + virtual bool disconnect(); + void switchday(); + void releaseapi(); + void reset(); + void timertask(); + void processbuf(); + + void insertOrder(shared_ptr pmsg); + void cancelOrder(shared_ptr pmsg); + void cancelAll(shared_ptr pmsg); + void closeAll(const string& fullsym = ""); + void checkLocalOrders(); + + void queryAccount(shared_ptr pmsg); + void queryPosition(shared_ptr pmsg); + void queryContract(shared_ptr pmsg); + void queryOrder(shared_ptr pmsg); + void queryTrade(shared_ptr pmsg); + void queryPositionDetail(shared_ptr pmsg); + + + public: + virtual void OnFrontConnected(); + virtual void OnFrontDisconnected(int32_t nReason); + virtual void OnHeartBeatWarning(int32_t nTimeLapse); + virtual void OnRspAuthenticate(CThostFtdcRspAuthenticateField *pRspAuthenticateField, CThostFtdcRspInfoField *pRspInfo, int32_t nRequestID, bool bIsLast); + virtual void OnRspUserLogin(CThostFtdcRspUserLoginField *pRspUserLogin, CThostFtdcRspInfoField *pRspInfo, int32_t nRequestID, bool bIsLast); + ///登出请求响应 + virtual void OnRspUserLogout(CThostFtdcUserLogoutField *pUserLogout, CThostFtdcRspInfoField *pRspInfo, int32_t nRequestID, bool bIsLast); + ///用户口令更新请求响应 + virtual void OnRspUserPasswordUpdate(CThostFtdcUserPasswordUpdateField *pUserPasswordUpdate, CThostFtdcRspInfoField *pRspInfo, int32_t nRequestID, bool bIsLast) {}; + ///资金账户口令更新请求响应 + virtual void OnRspTradingAccountPasswordUpdate(CThostFtdcTradingAccountPasswordUpdateField *pTradingAccountPasswordUpdate, CThostFtdcRspInfoField *pRspInfo, int32_t nRequestID, bool bIsLast) {}; + ///报单录入请求响应 + virtual void OnRspOrderInsert(CThostFtdcInputOrderField *pInputOrder, CThostFtdcRspInfoField *pRspInfo, int32_t nRequestID, bool bIsLast); + ///预埋单录入请求响应 + virtual void OnRspParkedOrderInsert(CThostFtdcParkedOrderField *pParkedOrder, CThostFtdcRspInfoField *pRspInfo, int32_t nRequestID, bool bIsLast) {}; + ///预埋撤单录入请求响应 + virtual void OnRspParkedOrderAction(CThostFtdcParkedOrderActionField *pParkedOrderAction, CThostFtdcRspInfoField *pRspInfo, int32_t nRequestID, bool bIsLast) {}; + ///报单操作请求响应 + virtual void OnRspOrderAction(CThostFtdcInputOrderActionField *pInputOrderAction, CThostFtdcRspInfoField *pRspInfo, int32_t nRequestID, bool bIsLast); + ///查询最大报单数量响应 + virtual void OnRspQueryMaxOrderVolume(CThostFtdcQueryMaxOrderVolumeField *pQueryMaxOrderVolume, CThostFtdcRspInfoField *pRspInfo, int32_t nRequestID, bool bIsLast) {}; + ///投资者结算结果确认响应 + virtual void OnRspSettlementInfoConfirm(CThostFtdcSettlementInfoConfirmField *pSettlementInfoConfirm, CThostFtdcRspInfoField *pRspInfo, int32_t nRequestID, bool bIsLast); + ///删除预埋单响应 + virtual void OnRspRemoveParkedOrder(CThostFtdcRemoveParkedOrderField *pRemoveParkedOrder, CThostFtdcRspInfoField *pRspInfo, int32_t nRequestID, bool bIsLast) {}; + ///删除预埋撤单响应 + virtual void OnRspRemoveParkedOrderAction(CThostFtdcRemoveParkedOrderActionField *pRemoveParkedOrderAction, CThostFtdcRspInfoField *pRspInfo, int32_t nRequestID, bool bIsLast) {}; + + ///执行宣告录入请求响应 + virtual void OnRspExecOrderInsert(CThostFtdcInputExecOrderField *pInputExecOrder, CThostFtdcRspInfoField *pRspInfo, int32_t nRequestID, bool bIsLast) {}; + + ///执行宣告操作请求响应 + virtual void OnRspExecOrderAction(CThostFtdcInputExecOrderActionField *pInputExecOrderAction, CThostFtdcRspInfoField *pRspInfo, int32_t nRequestID, bool bIsLast) {}; + + ///询价录入请求响应 + virtual void OnRspForQuoteInsert(CThostFtdcInputForQuoteField *pInputForQuote, CThostFtdcRspInfoField *pRspInfo, int32_t nRequestID, bool bIsLast) {}; - ///报价录入请求响应 - virtual void OnRspQuoteInsert(CThostFtdcInputQuoteField *pInputQuote, CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast) {}; + ///报价录入请求响应 + virtual void OnRspQuoteInsert(CThostFtdcInputQuoteField *pInputQuote, CThostFtdcRspInfoField *pRspInfo, int32_t nRequestID, bool bIsLast) {}; - ///报价操作请求响应 - virtual void OnRspQuoteAction(CThostFtdcInputQuoteActionField *pInputQuoteAction, CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast) {}; + ///报价操作请求响应 + virtual void OnRspQuoteAction(CThostFtdcInputQuoteActionField *pInputQuoteAction, CThostFtdcRspInfoField *pRspInfo, int32_t nRequestID, bool bIsLast) {}; - ///批量报单操作请求响应 - virtual void OnRspBatchOrderAction(CThostFtdcInputBatchOrderActionField *pInputBatchOrderAction, CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast) {}; + ///批量报单操作请求响应 + virtual void OnRspBatchOrderAction(CThostFtdcInputBatchOrderActionField *pInputBatchOrderAction, CThostFtdcRspInfoField *pRspInfo, int32_t nRequestID, bool bIsLast) {}; - ///申请组合录入请求响应 - virtual void OnRspCombActionInsert(CThostFtdcInputCombActionField *pInputCombAction, CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast) {}; + ///申请组合录入请求响应 + virtual void OnRspCombActionInsert(CThostFtdcInputCombActionField *pInputCombAction, CThostFtdcRspInfoField *pRspInfo, int32_t nRequestID, bool bIsLast) {}; - ///请求查询报单响应 - virtual void OnRspQryOrder(CThostFtdcOrderField *pOrder, CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast) ; + ///请求查询报单响应 + virtual void OnRspQryOrder(CThostFtdcOrderField *pOrder, CThostFtdcRspInfoField *pRspInfo, int32_t nRequestID, bool bIsLast) ; - ///请求查询成交响应 - virtual void OnRspQryTrade(CThostFtdcTradeField *pTrade, CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast) ; + ///请求查询成交响应 + virtual void OnRspQryTrade(CThostFtdcTradeField *pTrade, CThostFtdcRspInfoField *pRspInfo, int32_t nRequestID, bool bIsLast) ; - ///请求查询投资者持仓响应 - virtual void OnRspQryInvestorPosition(CThostFtdcInvestorPositionField *pInvestorPosition, CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast); + ///请求查询投资者持仓响应 + virtual void OnRspQryInvestorPosition(CThostFtdcInvestorPositionField *pInvestorPosition, CThostFtdcRspInfoField *pRspInfo, int32_t nRequestID, bool bIsLast); - ///请求查询资金账户响应 - virtual void OnRspQryTradingAccount(CThostFtdcTradingAccountField *pTradingAccount, CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast); + ///请求查询资金账户响应 + virtual void OnRspQryTradingAccount(CThostFtdcTradingAccountField *pTradingAccount, CThostFtdcRspInfoField *pRspInfo, int32_t nRequestID, bool bIsLast); - ///请求查询投资者响应 - virtual void OnRspQryInvestor(CThostFtdcInvestorField *pInvestor, CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast) {}; + ///请求查询投资者响应 + virtual void OnRspQryInvestor(CThostFtdcInvestorField *pInvestor, CThostFtdcRspInfoField *pRspInfo, int32_t nRequestID, bool bIsLast) {}; - ///请求查询交易编码响应 - virtual void OnRspQryTradingCode(CThostFtdcTradingCodeField *pTradingCode, CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast) {}; + ///请求查询交易编码响应 + virtual void OnRspQryTradingCode(CThostFtdcTradingCodeField *pTradingCode, CThostFtdcRspInfoField *pRspInfo, int32_t nRequestID, bool bIsLast) {}; - ///请求查询合约保证金率响应 - virtual void OnRspQryInstrumentMarginRate(CThostFtdcInstrumentMarginRateField *pInstrumentMarginRate, CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast) {}; + ///请求查询合约保证金率响应 + virtual void OnRspQryInstrumentMarginRate(CThostFtdcInstrumentMarginRateField *pInstrumentMarginRate, CThostFtdcRspInfoField *pRspInfo, int32_t nRequestID, bool bIsLast) {}; - ///请求查询合约手续费率响应 - virtual void OnRspQryInstrumentCommissionRate(CThostFtdcInstrumentCommissionRateField *pInstrumentCommissionRate, CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast) {}; + ///请求查询合约手续费率响应 + virtual void OnRspQryInstrumentCommissionRate(CThostFtdcInstrumentCommissionRateField *pInstrumentCommissionRate, CThostFtdcRspInfoField *pRspInfo, int32_t nRequestID, bool bIsLast) {}; - ///请求查询交易所响应 - virtual void OnRspQryExchange(CThostFtdcExchangeField *pExchange, CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast) {}; + ///请求查询交易所响应 + virtual void OnRspQryExchange(CThostFtdcExchangeField *pExchange, CThostFtdcRspInfoField *pRspInfo, int32_t nRequestID, bool bIsLast) {}; - ///请求查询产品响应 - virtual void OnRspQryProduct(CThostFtdcProductField *pProduct, CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast) {}; + ///请求查询产品响应 + virtual void OnRspQryProduct(CThostFtdcProductField *pProduct, CThostFtdcRspInfoField *pRspInfo, int32_t nRequestID, bool bIsLast) {}; - ///请求查询合约响应 - virtual void OnRspQryInstrument(CThostFtdcInstrumentField *pInstrument, CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast); + ///请求查询合约响应 + virtual void OnRspQryInstrument(CThostFtdcInstrumentField *pInstrument, CThostFtdcRspInfoField *pRspInfo, int32_t nRequestID, bool bIsLast); - ///请求查询行情响应 - virtual void OnRspQryDepthMarketData(CThostFtdcDepthMarketDataField *pDepthMarketData, CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast) {}; + ///请求查询行情响应 + virtual void OnRspQryDepthMarketData(CThostFtdcDepthMarketDataField *pDepthMarketData, CThostFtdcRspInfoField *pRspInfo, int32_t nRequestID, bool bIsLast) {}; - ///请求查询投资者结算结果响应 - virtual void OnRspQrySettlementInfo(CThostFtdcSettlementInfoField *pSettlementInfo, CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast) {}; + ///请求查询投资者结算结果响应 + virtual void OnRspQrySettlementInfo(CThostFtdcSettlementInfoField *pSettlementInfo, CThostFtdcRspInfoField *pRspInfo, int32_t nRequestID, bool bIsLast) {}; - ///请求查询转帐银行响应 - virtual void OnRspQryTransferBank(CThostFtdcTransferBankField *pTransferBank, CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast) {}; + ///请求查询转帐银行响应 + virtual void OnRspQryTransferBank(CThostFtdcTransferBankField *pTransferBank, CThostFtdcRspInfoField *pRspInfo, int32_t nRequestID, bool bIsLast) {}; - ///请求查询投资者持仓明细响应 - virtual void OnRspQryInvestorPositionDetail(CThostFtdcInvestorPositionDetailField *pInvestorPositionDetail, CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast); + ///请求查询投资者持仓明细响应 + virtual void OnRspQryInvestorPositionDetail(CThostFtdcInvestorPositionDetailField *pInvestorPositionDetail, CThostFtdcRspInfoField *pRspInfo, int32_t nRequestID, bool bIsLast); - ///请求查询客户通知响应 - virtual void OnRspQryNotice(CThostFtdcNoticeField *pNotice, CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast) {}; + ///请求查询客户通知响应 + virtual void OnRspQryNotice(CThostFtdcNoticeField *pNotice, CThostFtdcRspInfoField *pRspInfo, int32_t nRequestID, bool bIsLast) {}; - ///请求查询结算信息确认响应 - virtual void OnRspQrySettlementInfoConfirm(CThostFtdcSettlementInfoConfirmField *pSettlementInfoConfirm, CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast) {}; + ///请求查询结算信息确认响应 + virtual void OnRspQrySettlementInfoConfirm(CThostFtdcSettlementInfoConfirmField *pSettlementInfoConfirm, CThostFtdcRspInfoField *pRspInfo, int32_t nRequestID, bool bIsLast) {}; - ///请求查询投资者持仓明细响应 - virtual void OnRspQryInvestorPositionCombineDetail(CThostFtdcInvestorPositionCombineDetailField *pInvestorPositionCombineDetail, CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast) {}; + ///请求查询投资者持仓明细响应 + virtual void OnRspQryInvestorPositionCombineDetail(CThostFtdcInvestorPositionCombineDetailField *pInvestorPositionCombineDetail, CThostFtdcRspInfoField *pRspInfo, int32_t nRequestID, bool bIsLast) {}; - ///查询保证金监管系统经纪公司资金账户密钥响应 - virtual void OnRspQryCFMMCTradingAccountKey(CThostFtdcCFMMCTradingAccountKeyField *pCFMMCTradingAccountKey, CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast) {}; + ///查询保证金监管系统经纪公司资金账户密钥响应 + virtual void OnRspQryCFMMCTradingAccountKey(CThostFtdcCFMMCTradingAccountKeyField *pCFMMCTradingAccountKey, CThostFtdcRspInfoField *pRspInfo, int32_t nRequestID, bool bIsLast) {}; - ///请求查询仓单折抵信息响应 - virtual void OnRspQryEWarrantOffset(CThostFtdcEWarrantOffsetField *pEWarrantOffset, CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast) {}; + ///请求查询仓单折抵信息响应 + virtual void OnRspQryEWarrantOffset(CThostFtdcEWarrantOffsetField *pEWarrantOffset, CThostFtdcRspInfoField *pRspInfo, int32_t nRequestID, bool bIsLast) {}; - ///请求查询投资者品种/跨品种保证金响应 - virtual void OnRspQryInvestorProductGroupMargin(CThostFtdcInvestorProductGroupMarginField *pInvestorProductGroupMargin, CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast) {}; + ///请求查询投资者品种/跨品种保证金响应 + virtual void OnRspQryInvestorProductGroupMargin(CThostFtdcInvestorProductGroupMarginField *pInvestorProductGroupMargin, CThostFtdcRspInfoField *pRspInfo, int32_t nRequestID, bool bIsLast) {}; - ///请求查询交易所保证金率响应 - virtual void OnRspQryExchangeMarginRate(CThostFtdcExchangeMarginRateField *pExchangeMarginRate, CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast) {}; + ///请求查询交易所保证金率响应 + virtual void OnRspQryExchangeMarginRate(CThostFtdcExchangeMarginRateField *pExchangeMarginRate, CThostFtdcRspInfoField *pRspInfo, int32_t nRequestID, bool bIsLast) {}; - ///请求查询交易所调整保证金率响应 - virtual void OnRspQryExchangeMarginRateAdjust(CThostFtdcExchangeMarginRateAdjustField *pExchangeMarginRateAdjust, CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast) {}; + ///请求查询交易所调整保证金率响应 + virtual void OnRspQryExchangeMarginRateAdjust(CThostFtdcExchangeMarginRateAdjustField *pExchangeMarginRateAdjust, CThostFtdcRspInfoField *pRspInfo, int32_t nRequestID, bool bIsLast) {}; - ///请求查询汇率响应 - virtual void OnRspQryExchangeRate(CThostFtdcExchangeRateField *pExchangeRate, CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast) {}; + ///请求查询汇率响应 + virtual void OnRspQryExchangeRate(CThostFtdcExchangeRateField *pExchangeRate, CThostFtdcRspInfoField *pRspInfo, int32_t nRequestID, bool bIsLast) {}; - ///请求查询二级代理操作员银期权限响应 - virtual void OnRspQrySecAgentACIDMap(CThostFtdcSecAgentACIDMapField *pSecAgentACIDMap, CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast) {}; + ///请求查询二级代理操作员银期权限响应 + virtual void OnRspQrySecAgentACIDMap(CThostFtdcSecAgentACIDMapField *pSecAgentACIDMap, CThostFtdcRspInfoField *pRspInfo, int32_t nRequestID, bool bIsLast) {}; - ///请求查询产品报价汇率 - virtual void OnRspQryProductExchRate(CThostFtdcProductExchRateField *pProductExchRate, CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast) {}; + ///请求查询产品报价汇率 + virtual void OnRspQryProductExchRate(CThostFtdcProductExchRateField *pProductExchRate, CThostFtdcRspInfoField *pRspInfo, int32_t nRequestID, bool bIsLast) {}; - ///请求查询产品组 - virtual void OnRspQryProductGroup(CThostFtdcProductGroupField *pProductGroup, CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast) {}; + ///请求查询产品组 + virtual void OnRspQryProductGroup(CThostFtdcProductGroupField *pProductGroup, CThostFtdcRspInfoField *pRspInfo, int32_t nRequestID, bool bIsLast) {}; - ///请求查询做市商合约手续费率响应 - virtual void OnRspQryMMInstrumentCommissionRate(CThostFtdcMMInstrumentCommissionRateField *pMMInstrumentCommissionRate, CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast) {}; + ///请求查询做市商合约手续费率响应 + virtual void OnRspQryMMInstrumentCommissionRate(CThostFtdcMMInstrumentCommissionRateField *pMMInstrumentCommissionRate, CThostFtdcRspInfoField *pRspInfo, int32_t nRequestID, bool bIsLast) {}; - ///请求查询做市商期权合约手续费响应 - virtual void OnRspQryMMOptionInstrCommRate(CThostFtdcMMOptionInstrCommRateField *pMMOptionInstrCommRate, CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast) {}; + ///请求查询做市商期权合约手续费响应 + virtual void OnRspQryMMOptionInstrCommRate(CThostFtdcMMOptionInstrCommRateField *pMMOptionInstrCommRate, CThostFtdcRspInfoField *pRspInfo, int32_t nRequestID, bool bIsLast) {}; - ///请求查询报单手续费响应 - virtual void OnRspQryInstrumentOrderCommRate(CThostFtdcInstrumentOrderCommRateField *pInstrumentOrderCommRate, CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast) {}; + ///请求查询报单手续费响应 + virtual void OnRspQryInstrumentOrderCommRate(CThostFtdcInstrumentOrderCommRateField *pInstrumentOrderCommRate, CThostFtdcRspInfoField *pRspInfo, int32_t nRequestID, bool bIsLast) {}; - ///请求查询期权交易成本响应 - virtual void OnRspQryOptionInstrTradeCost(CThostFtdcOptionInstrTradeCostField *pOptionInstrTradeCost, CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast) {}; + ///请求查询期权交易成本响应 + virtual void OnRspQryOptionInstrTradeCost(CThostFtdcOptionInstrTradeCostField *pOptionInstrTradeCost, CThostFtdcRspInfoField *pRspInfo, int32_t nRequestID, bool bIsLast) {}; - ///请求查询期权合约手续费响应 - virtual void OnRspQryOptionInstrCommRate(CThostFtdcOptionInstrCommRateField *pOptionInstrCommRate, CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast) {}; + ///请求查询期权合约手续费响应 + virtual void OnRspQryOptionInstrCommRate(CThostFtdcOptionInstrCommRateField *pOptionInstrCommRate, CThostFtdcRspInfoField *pRspInfo, int32_t nRequestID, bool bIsLast) {}; - ///请求查询执行宣告响应 - virtual void OnRspQryExecOrder(CThostFtdcExecOrderField *pExecOrder, CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast) {}; + ///请求查询执行宣告响应 + virtual void OnRspQryExecOrder(CThostFtdcExecOrderField *pExecOrder, CThostFtdcRspInfoField *pRspInfo, int32_t nRequestID, bool bIsLast) {}; - ///请求查询询价响应 - virtual void OnRspQryForQuote(CThostFtdcForQuoteField *pForQuote, CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast) {}; + ///请求查询询价响应 + virtual void OnRspQryForQuote(CThostFtdcForQuoteField *pForQuote, CThostFtdcRspInfoField *pRspInfo, int32_t nRequestID, bool bIsLast) {}; - ///请求查询报价响应 - virtual void OnRspQryQuote(CThostFtdcQuoteField *pQuote, CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast) {}; + ///请求查询报价响应 + virtual void OnRspQryQuote(CThostFtdcQuoteField *pQuote, CThostFtdcRspInfoField *pRspInfo, int32_t nRequestID, bool bIsLast) {}; - ///请求查询组合合约安全系数响应 - virtual void OnRspQryCombInstrumentGuard(CThostFtdcCombInstrumentGuardField *pCombInstrumentGuard, CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast) {}; + ///请求查询组合合约安全系数响应 + virtual void OnRspQryCombInstrumentGuard(CThostFtdcCombInstrumentGuardField *pCombInstrumentGuard, CThostFtdcRspInfoField *pRspInfo, int32_t nRequestID, bool bIsLast) {}; - ///请求查询申请组合响应 - virtual void OnRspQryCombAction(CThostFtdcCombActionField *pCombAction, CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast) {}; + ///请求查询申请组合响应 + virtual void OnRspQryCombAction(CThostFtdcCombActionField *pCombAction, CThostFtdcRspInfoField *pRspInfo, int32_t nRequestID, bool bIsLast) {}; - ///请求查询转帐流水响应 - virtual void OnRspQryTransferSerial(CThostFtdcTransferSerialField *pTransferSerial, CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast) {}; + ///请求查询转帐流水响应 + virtual void OnRspQryTransferSerial(CThostFtdcTransferSerialField *pTransferSerial, CThostFtdcRspInfoField *pRspInfo, int32_t nRequestID, bool bIsLast) {}; - ///请求查询银期签约关系响应 - virtual void OnRspQryAccountregister(CThostFtdcAccountregisterField *pAccountregister, CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast) {}; + ///请求查询银期签约关系响应 + virtual void OnRspQryAccountregister(CThostFtdcAccountregisterField *pAccountregister, CThostFtdcRspInfoField *pRspInfo, int32_t nRequestID, bool bIsLast) {}; - ///错误应答 - virtual void OnRspError(CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast); + ///错误应答 + virtual void OnRspError(CThostFtdcRspInfoField *pRspInfo, int32_t nRequestID, bool bIsLast); - ///报单通知 - virtual void OnRtnOrder(CThostFtdcOrderField *pOrder); + ///报单通知 + virtual void OnRtnOrder(CThostFtdcOrderField *pOrder); - ///成交通知 - virtual void OnRtnTrade(CThostFtdcTradeField *pTrade); + ///成交通知 + virtual void OnRtnTrade(CThostFtdcTradeField *pTrade); - ///报单录入错误回报 - virtual void OnErrRtnOrderInsert(CThostFtdcInputOrderField *pInputOrder, CThostFtdcRspInfoField *pRspInfo); + ///报单录入错误回报 + virtual void OnErrRtnOrderInsert(CThostFtdcInputOrderField *pInputOrder, CThostFtdcRspInfoField *pRspInfo); - ///报单操作错误回报 - virtual void OnErrRtnOrderAction(CThostFtdcOrderActionField *pOrderAction, CThostFtdcRspInfoField *pRspInfo); + ///报单操作错误回报 + virtual void OnErrRtnOrderAction(CThostFtdcOrderActionField *pOrderAction, CThostFtdcRspInfoField *pRspInfo); - ///合约交易状态通知 - virtual void OnRtnInstrumentStatus(CThostFtdcInstrumentStatusField *pInstrumentStatus) {}; + ///合约交易状态通知 + virtual void OnRtnInstrumentStatus(CThostFtdcInstrumentStatusField *pInstrumentStatus) {}; - ///交易所公告通知 - virtual void OnRtnBulletin(CThostFtdcBulletinField *pBulletin) {}; + ///交易所公告通知 + virtual void OnRtnBulletin(CThostFtdcBulletinField *pBulletin) {}; - ///交易通知 - virtual void OnRtnTradingNotice(CThostFtdcTradingNoticeInfoField *pTradingNoticeInfo) {}; + ///交易通知 + virtual void OnRtnTradingNotice(CThostFtdcTradingNoticeInfoField *pTradingNoticeInfo) {}; - ///提示条件单校验错误 - virtual void OnRtnErrorConditionalOrder(CThostFtdcErrorConditionalOrderField *pErrorConditionalOrder) {}; + ///提示条件单校验错误 + virtual void OnRtnErrorConditionalOrder(CThostFtdcErrorConditionalOrderField *pErrorConditionalOrder) {}; - ///执行宣告通知 - virtual void OnRtnExecOrder(CThostFtdcExecOrderField *pExecOrder) {}; + ///执行宣告通知 + virtual void OnRtnExecOrder(CThostFtdcExecOrderField *pExecOrder) {}; - ///执行宣告录入错误回报 - virtual void OnErrRtnExecOrderInsert(CThostFtdcInputExecOrderField *pInputExecOrder, CThostFtdcRspInfoField *pRspInfo) {}; + ///执行宣告录入错误回报 + virtual void OnErrRtnExecOrderInsert(CThostFtdcInputExecOrderField *pInputExecOrder, CThostFtdcRspInfoField *pRspInfo) {}; - ///执行宣告操作错误回报 - virtual void OnErrRtnExecOrderAction(CThostFtdcExecOrderActionField *pExecOrderAction, CThostFtdcRspInfoField *pRspInfo) {}; + ///执行宣告操作错误回报 + virtual void OnErrRtnExecOrderAction(CThostFtdcExecOrderActionField *pExecOrderAction, CThostFtdcRspInfoField *pRspInfo) {}; - ///询价录入错误回报 - virtual void OnErrRtnForQuoteInsert(CThostFtdcInputForQuoteField *pInputForQuote, CThostFtdcRspInfoField *pRspInfo) {}; + ///询价录入错误回报 + virtual void OnErrRtnForQuoteInsert(CThostFtdcInputForQuoteField *pInputForQuote, CThostFtdcRspInfoField *pRspInfo) {}; - ///报价通知 - virtual void OnRtnQuote(CThostFtdcQuoteField *pQuote) {}; + ///报价通知 + virtual void OnRtnQuote(CThostFtdcQuoteField *pQuote) {}; - ///报价录入错误回报 - virtual void OnErrRtnQuoteInsert(CThostFtdcInputQuoteField *pInputQuote, CThostFtdcRspInfoField *pRspInfo) {}; + ///报价录入错误回报 + virtual void OnErrRtnQuoteInsert(CThostFtdcInputQuoteField *pInputQuote, CThostFtdcRspInfoField *pRspInfo) {}; - ///报价操作错误回报 - virtual void OnErrRtnQuoteAction(CThostFtdcQuoteActionField *pQuoteAction, CThostFtdcRspInfoField *pRspInfo) {}; + ///报价操作错误回报 + virtual void OnErrRtnQuoteAction(CThostFtdcQuoteActionField *pQuoteAction, CThostFtdcRspInfoField *pRspInfo) {}; - ///询价通知 - virtual void OnRtnForQuoteRsp(CThostFtdcForQuoteRspField *pForQuoteRsp) {}; + ///询价通知 + virtual void OnRtnForQuoteRsp(CThostFtdcForQuoteRspField *pForQuoteRsp) {}; - ///保证金监控中心用户令牌 - virtual void OnRtnCFMMCTradingAccountToken(CThostFtdcCFMMCTradingAccountTokenField *pCFMMCTradingAccountToken) {}; + ///保证金监控中心用户令牌 + virtual void OnRtnCFMMCTradingAccountToken(CThostFtdcCFMMCTradingAccountTokenField *pCFMMCTradingAccountToken) {}; - ///批量报单操作错误回报 - virtual void OnErrRtnBatchOrderAction(CThostFtdcBatchOrderActionField *pBatchOrderAction, CThostFtdcRspInfoField *pRspInfo) {}; + ///批量报单操作错误回报 + virtual void OnErrRtnBatchOrderAction(CThostFtdcBatchOrderActionField *pBatchOrderAction, CThostFtdcRspInfoField *pRspInfo) {}; - ///申请组合通知 - virtual void OnRtnCombAction(CThostFtdcCombActionField *pCombAction) {}; + ///申请组合通知 + virtual void OnRtnCombAction(CThostFtdcCombActionField *pCombAction) {}; - ///申请组合录入错误回报 - virtual void OnErrRtnCombActionInsert(CThostFtdcInputCombActionField *pInputCombAction, CThostFtdcRspInfoField *pRspInfo) {}; + ///申请组合录入错误回报 + virtual void OnErrRtnCombActionInsert(CThostFtdcInputCombActionField *pInputCombAction, CThostFtdcRspInfoField *pRspInfo) {}; - ///请求查询签约银行响应 - virtual void OnRspQryContractBank(CThostFtdcContractBankField *pContractBank, CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast) {}; + ///请求查询签约银行响应 + virtual void OnRspQryContractBank(CThostFtdcContractBankField *pContractBank, CThostFtdcRspInfoField *pRspInfo, int32_t nRequestID, bool bIsLast) {}; - ///请求查询预埋单响应 - virtual void OnRspQryParkedOrder(CThostFtdcParkedOrderField *pParkedOrder, CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast) {}; + ///请求查询预埋单响应 + virtual void OnRspQryParkedOrder(CThostFtdcParkedOrderField *pParkedOrder, CThostFtdcRspInfoField *pRspInfo, int32_t nRequestID, bool bIsLast) {}; - ///请求查询预埋撤单响应 - virtual void OnRspQryParkedOrderAction(CThostFtdcParkedOrderActionField *pParkedOrderAction, CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast) {}; + ///请求查询预埋撤单响应 + virtual void OnRspQryParkedOrderAction(CThostFtdcParkedOrderActionField *pParkedOrderAction, CThostFtdcRspInfoField *pRspInfo, int32_t nRequestID, bool bIsLast) {}; - ///请求查询交易通知响应 - virtual void OnRspQryTradingNotice(CThostFtdcTradingNoticeField *pTradingNotice, CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast) {}; + ///请求查询交易通知响应 + virtual void OnRspQryTradingNotice(CThostFtdcTradingNoticeField *pTradingNotice, CThostFtdcRspInfoField *pRspInfo, int32_t nRequestID, bool bIsLast) {}; - ///请求查询经纪公司交易参数响应 - virtual void OnRspQryBrokerTradingParams(CThostFtdcBrokerTradingParamsField *pBrokerTradingParams, CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast) {}; + ///请求查询经纪公司交易参数响应 + virtual void OnRspQryBrokerTradingParams(CThostFtdcBrokerTradingParamsField *pBrokerTradingParams, CThostFtdcRspInfoField *pRspInfo, int32_t nRequestID, bool bIsLast) {}; - ///请求查询经纪公司交易算法响应 - virtual void OnRspQryBrokerTradingAlgos(CThostFtdcBrokerTradingAlgosField *pBrokerTradingAlgos, CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast) {}; + ///请求查询经纪公司交易算法响应 + virtual void OnRspQryBrokerTradingAlgos(CThostFtdcBrokerTradingAlgosField *pBrokerTradingAlgos, CThostFtdcRspInfoField *pRspInfo, int32_t nRequestID, bool bIsLast) {}; - ///请求查询监控中心用户令牌 - virtual void OnRspQueryCFMMCTradingAccountToken(CThostFtdcQueryCFMMCTradingAccountTokenField *pQueryCFMMCTradingAccountToken, CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast) {}; + ///请求查询监控中心用户令牌 + virtual void OnRspQueryCFMMCTradingAccountToken(CThostFtdcQueryCFMMCTradingAccountTokenField *pQueryCFMMCTradingAccountToken, CThostFtdcRspInfoField *pRspInfo, int32_t nRequestID, bool bIsLast) {}; - ///银行发起银行资金转期货通知 - virtual void OnRtnFromBankToFutureByBank(CThostFtdcRspTransferField *pRspTransfer) {}; + ///银行发起银行资金转期货通知 + virtual void OnRtnFromBankToFutureByBank(CThostFtdcRspTransferField *pRspTransfer) {}; - ///银行发起期货资金转银行通知 - virtual void OnRtnFromFutureToBankByBank(CThostFtdcRspTransferField *pRspTransfer) {}; + ///银行发起期货资金转银行通知 + virtual void OnRtnFromFutureToBankByBank(CThostFtdcRspTransferField *pRspTransfer) {}; - ///银行发起冲正银行转期货通知 - virtual void OnRtnRepealFromBankToFutureByBank(CThostFtdcRspRepealField *pRspRepeal) {}; + ///银行发起冲正银行转期货通知 + virtual void OnRtnRepealFromBankToFutureByBank(CThostFtdcRspRepealField *pRspRepeal) {}; - ///银行发起冲正期货转银行通知 - virtual void OnRtnRepealFromFutureToBankByBank(CThostFtdcRspRepealField *pRspRepeal) {}; + ///银行发起冲正期货转银行通知 + virtual void OnRtnRepealFromFutureToBankByBank(CThostFtdcRspRepealField *pRspRepeal) {}; - ///期货发起银行资金转期货通知 - virtual void OnRtnFromBankToFutureByFuture(CThostFtdcRspTransferField *pRspTransfer) {}; + ///期货发起银行资金转期货通知 + virtual void OnRtnFromBankToFutureByFuture(CThostFtdcRspTransferField *pRspTransfer) {}; - ///期货发起期货资金转银行通知 - virtual void OnRtnFromFutureToBankByFuture(CThostFtdcRspTransferField *pRspTransfer) {}; + ///期货发起期货资金转银行通知 + virtual void OnRtnFromFutureToBankByFuture(CThostFtdcRspTransferField *pRspTransfer) {}; - ///系统运行时期货端手工发起冲正银行转期货请求,银行处理完毕后报盘发回的通知 - virtual void OnRtnRepealFromBankToFutureByFutureManual(CThostFtdcRspRepealField *pRspRepeal) {}; + ///系统运行时期货端手工发起冲正银行转期货请求,银行处理完毕后报盘发回的通知 + virtual void OnRtnRepealFromBankToFutureByFutureManual(CThostFtdcRspRepealField *pRspRepeal) {}; - ///系统运行时期货端手工发起冲正期货转银行请求,银行处理完毕后报盘发回的通知 - virtual void OnRtnRepealFromFutureToBankByFutureManual(CThostFtdcRspRepealField *pRspRepeal) {}; + ///系统运行时期货端手工发起冲正期货转银行请求,银行处理完毕后报盘发回的通知 + virtual void OnRtnRepealFromFutureToBankByFutureManual(CThostFtdcRspRepealField *pRspRepeal) {}; - ///期货发起查询银行余额通知 - virtual void OnRtnQueryBankBalanceByFuture(CThostFtdcNotifyQueryAccountField *pNotifyQueryAccount) {}; + ///期货发起查询银行余额通知 + virtual void OnRtnQueryBankBalanceByFuture(CThostFtdcNotifyQueryAccountField *pNotifyQueryAccount) {}; - ///期货发起银行资金转期货错误回报 - virtual void OnErrRtnBankToFutureByFuture(CThostFtdcReqTransferField *pReqTransfer, CThostFtdcRspInfoField *pRspInfo) {}; + ///期货发起银行资金转期货错误回报 + virtual void OnErrRtnBankToFutureByFuture(CThostFtdcReqTransferField *pReqTransfer, CThostFtdcRspInfoField *pRspInfo) {}; - ///期货发起期货资金转银行错误回报 - virtual void OnErrRtnFutureToBankByFuture(CThostFtdcReqTransferField *pReqTransfer, CThostFtdcRspInfoField *pRspInfo) {}; + ///期货发起期货资金转银行错误回报 + virtual void OnErrRtnFutureToBankByFuture(CThostFtdcReqTransferField *pReqTransfer, CThostFtdcRspInfoField *pRspInfo) {}; - ///系统运行时期货端手工发起冲正银行转期货错误回报 - virtual void OnErrRtnRepealBankToFutureByFutureManual(CThostFtdcReqRepealField *pReqRepeal, CThostFtdcRspInfoField *pRspInfo) {}; + ///系统运行时期货端手工发起冲正银行转期货错误回报 + virtual void OnErrRtnRepealBankToFutureByFutureManual(CThostFtdcReqRepealField *pReqRepeal, CThostFtdcRspInfoField *pRspInfo) {}; - ///系统运行时期货端手工发起冲正期货转银行错误回报 - virtual void OnErrRtnRepealFutureToBankByFutureManual(CThostFtdcReqRepealField *pReqRepeal, CThostFtdcRspInfoField *pRspInfo) {}; + ///系统运行时期货端手工发起冲正期货转银行错误回报 + virtual void OnErrRtnRepealFutureToBankByFutureManual(CThostFtdcReqRepealField *pReqRepeal, CThostFtdcRspInfoField *pRspInfo) {}; - ///期货发起查询银行余额错误回报 - virtual void OnErrRtnQueryBankBalanceByFuture(CThostFtdcReqQueryAccountField *pReqQueryAccount, CThostFtdcRspInfoField *pRspInfo) {}; + ///期货发起查询银行余额错误回报 + virtual void OnErrRtnQueryBankBalanceByFuture(CThostFtdcReqQueryAccountField *pReqQueryAccount, CThostFtdcRspInfoField *pRspInfo) {}; - ///期货发起冲正银行转期货请求,银行处理完毕后报盘发回的通知 - virtual void OnRtnRepealFromBankToFutureByFuture(CThostFtdcRspRepealField *pRspRepeal) {}; + ///期货发起冲正银行转期货请求,银行处理完毕后报盘发回的通知 + virtual void OnRtnRepealFromBankToFutureByFuture(CThostFtdcRspRepealField *pRspRepeal) {}; - ///期货发起冲正期货转银行请求,银行处理完毕后报盘发回的通知 - virtual void OnRtnRepealFromFutureToBankByFuture(CThostFtdcRspRepealField *pRspRepeal) {}; + ///期货发起冲正期货转银行请求,银行处理完毕后报盘发回的通知 + virtual void OnRtnRepealFromFutureToBankByFuture(CThostFtdcRspRepealField *pRspRepeal) {}; - ///期货发起银行资金转期货应答 - virtual void OnRspFromBankToFutureByFuture(CThostFtdcReqTransferField *pReqTransfer, CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast) {}; + ///期货发起银行资金转期货应答 + virtual void OnRspFromBankToFutureByFuture(CThostFtdcReqTransferField *pReqTransfer, CThostFtdcRspInfoField *pRspInfo, int32_t nRequestID, bool bIsLast) {}; - ///期货发起期货资金转银行应答 - virtual void OnRspFromFutureToBankByFuture(CThostFtdcReqTransferField *pReqTransfer, CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast) {}; + ///期货发起期货资金转银行应答 + virtual void OnRspFromFutureToBankByFuture(CThostFtdcReqTransferField *pReqTransfer, CThostFtdcRspInfoField *pRspInfo, int32_t nRequestID, bool bIsLast) {}; - ///期货发起查询银行余额应答 - virtual void OnRspQueryBankAccountMoneyByFuture(CThostFtdcReqQueryAccountField *pReqQueryAccount, CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast) {}; + ///期货发起查询银行余额应答 + virtual void OnRspQueryBankAccountMoneyByFuture(CThostFtdcReqQueryAccountField *pReqQueryAccount, CThostFtdcRspInfoField *pRspInfo, int32_t nRequestID, bool bIsLast) {}; - ///银行发起银期开户通知 - virtual void OnRtnOpenAccountByBank(CThostFtdcOpenAccountField *pOpenAccount) {}; + ///银行发起银期开户通知 + virtual void OnRtnOpenAccountByBank(CThostFtdcOpenAccountField *pOpenAccount) {}; - ///银行发起银期销户通知 - virtual void OnRtnCancelAccountByBank(CThostFtdcCancelAccountField *pCancelAccount) {}; + ///银行发起银期销户通知 + virtual void OnRtnCancelAccountByBank(CThostFtdcCancelAccountField *pCancelAccount) {}; - ///银行发起变更银行账号通知 - virtual void OnRtnChangeAccountByBank(CThostFtdcChangeAccountField *pChangeAccount) {}; + ///银行发起变更银行账号通知 + virtual void OnRtnChangeAccountByBank(CThostFtdcChangeAccountField *pChangeAccount) {}; - private: + private: + int32_t reqId_; // 操作请求编号 + int32_t frontID_; // 前置机编号 + int32_t sessionID_; // 会话编号,以上三组编号唯一确定订单 + int32_t orderRef_; // 订单编号 + CThostFtdcTraderApi* api_; + bool apiinited_; + bool inconnectaction_; + bool autoconnect_; + bool autoqry_; +// used for calculate position + map > posbuffer_; +// used for qry queue to keep qry interval < 1s + std::queue < std::shared_ptr > qryBuffer_; +// local condition order + std::vector > localorders_; + uint64_t lastQryTime_; + int32_t timercount_; - int reqId_; // 操作请求编号 - int frontID_; // 前置机编号 - int sessionID_; // 会话编号,以上三组编号唯一确定订单 - int orderRef_; // 订单编号 - CThostFtdcTraderApi* api_; - bool apiinited_; - bool inconnectaction_; - bool autoconnect_; - bool autoqry_; + OrderStatus CtpOrderStatusToOrderStatus(const char status); + OrderFlag CtpComboOffsetFlagToOrderFlag(const char flag); + char OrderFlagToCtpComboOffsetFlag(const OrderFlag flag); +}; - map > posbuffer_; //used for calculate position - std::queue < std::shared_ptr > qryBuffer_; // used for qry queue to keep qry interval < 1s - std::vector > localorders_; //local condition order - uint64_t lastQryTime_; - int timercount_; - - OrderStatus CtpOrderStatusToOrderStatus(const char status); - OrderFlag CtpComboOffsetFlagToOrderFlag(const char flag); - char OrderFlagToCtpComboOffsetFlag(const OrderFlag flag); - }; -} +} // namespace StarQuant -#endif +#endif // CPPSRC_STARQUANT_ENGINE_CTPTDENGINE_H_ diff --git a/cppsrc/StarQuant/Engine/IEngine.cpp b/cppsrc/StarQuant/Engine/IEngine.cpp index 99f5c0fb7..000f5b9e0 100644 --- a/cppsrc/StarQuant/Engine/IEngine.cpp +++ b/cppsrc/StarQuant/Engine/IEngine.cpp @@ -1,30 +1,37 @@ +/***************************************************************************** + * Copyright [2019] + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *****************************************************************************/ #include #include -namespace StarQuant -{ +namespace StarQuant { // mutex IEngine::sendlock_; // std::unique_ptr IEngine::msgq_send_; IEngine::IEngine() - :estate_(EState::DISCONNECTED) - { + :estate_(EState::DISCONNECTED) { init(); } -IEngine::~IEngine(){ -} -void IEngine::init(){ - -} -void IEngine::start(){ - -} -void IEngine::stop(){ +IEngine::~IEngine() {} +void IEngine::init() {} +void IEngine::start() {} +void IEngine::stop() { estate_ = EState::STOP; } -} \ No newline at end of file +} // namespace StarQuant diff --git a/cppsrc/StarQuant/Engine/IEngine.h b/cppsrc/StarQuant/Engine/IEngine.h index 29730265a..d031a5151 100644 --- a/cppsrc/StarQuant/Engine/IEngine.h +++ b/cppsrc/StarQuant/Engine/IEngine.h @@ -1,19 +1,34 @@ -#ifndef _StarQuant_Engine_IEngine_H_ -#define _StarQuant_Engine_IEngine_H_ +/***************************************************************************** + * Copyright [2019] + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *****************************************************************************/ +#ifndef CPPSRC_STARQUANT_ENGINE_IENGINE_H_ +#define CPPSRC_STARQUANT_ENGINE_IENGINE_H_ + #include #include - +#include namespace StarQuant { // Engine state -enum EState :int { +enum EState :int32_t { DISCONNECTED = 0, // initial state is disconnected CONNECTING, CONNECT_ACK, // ctp: front end is connected; tap: logined AUTHENTICATING, - AUTHENTICATE_ACK, //ctp trade authencated + AUTHENTICATE_ACK, // ctp trade authencated LOGINING, LOGIN_ACK, // logined for ctp, for tap api is ready to do things LOGOUTING, @@ -21,11 +36,10 @@ enum EState :int { }; // Interface class: base engine for td and md engine -class IEngine { -public: +class IEngine { + public: // static mutex sendlock_; // msg send lock_ // static std::unique_ptr msgq_send_; //for md and td messenge to client, all engine share same msgq, usually publish mode - // std::unique_ptr msgq_recv_; //each engine has its own msgq, usually subscribe mode std::atomic estate_; std::unique_ptr messenger_; @@ -38,10 +52,10 @@ class IEngine { virtual void stop(); virtual bool connect() = 0; virtual bool disconnect() = 0; -protected: + protected: std::shared_ptr logger; }; -} +} // namespace StarQuant -#endif // _StarQuant_Engine_IEngine_H_ \ No newline at end of file +#endif // CPPSRC_STARQUANT_ENGINE_IENGINE_H_ diff --git a/cppsrc/StarQuant/Engine/PaperTDEngine.cpp b/cppsrc/StarQuant/Engine/PaperTDEngine.cpp index 5b87ada9b..6b2a23333 100644 --- a/cppsrc/StarQuant/Engine/PaperTDEngine.cpp +++ b/cppsrc/StarQuant/Engine/PaperTDEngine.cpp @@ -1,6 +1,17 @@ -#include -#include -#include +/***************************************************************************** + * Copyright [2019] + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *****************************************************************************/ #include #include @@ -10,337 +21,312 @@ #include #include -using namespace std; -namespace StarQuant -{ - //extern std::atomic gShutdown; +#include +#include +#include +#include +#include - PaperTDEngine::PaperTDEngine() - { - m_brokerOrderId_ = 0; - fillID_ = 0; - init(); - } - PaperTDEngine::~PaperTDEngine() { - if (estate_ != STOP) - stop(); +using namespace std; +namespace StarQuant { +//extern std::atomic gShutdown; - } +PaperTDEngine::PaperTDEngine() { + m_brokerOrderId_ = 0; + fillID_ = 0; + init(); +} - void PaperTDEngine::init(){ - name_ = "PAPER.TD"; - if(logger == nullptr){ - logger = SQLogger::getLogger("TDEngine.Paper"); - } - if (messenger_ == nullptr){ - messenger_ = std::make_unique(name_, CConfig::instance().SERVERSUB_URL); - msleep(100); - } - estate_ = DISCONNECTED; - auto pmsgs = make_shared(DESTINATION_ALL, name_, - MSG_TYPE_ENGINE_STATUS, - to_string(estate_)); - messenger_->send(pmsgs); - LOG_DEBUG(logger,"Paper TD inited"); - } - void PaperTDEngine::stop(){ - estate_ = EState::STOP; - auto pmsgs = make_shared(DESTINATION_ALL, name_, - MSG_TYPE_ENGINE_STATUS, - to_string(estate_)); - messenger_->send(pmsgs); - LOG_DEBUG(logger,"Paper TD stoped"); +PaperTDEngine::~PaperTDEngine() { + if (estate_ != STOP) + stop(); +} +void PaperTDEngine::init() { + name_ = "PAPER.TD"; + if (logger == nullptr) { + logger = SQLogger::getLogger("TDEngine.Paper"); + } + if (messenger_ == nullptr) { + messenger_ = std::make_unique(name_, CConfig::instance().SERVERSUB_URL); + msleep(100); } + estate_ = DISCONNECTED; + auto pmsgs = make_shared(DESTINATION_ALL, name_, + MSG_TYPE_ENGINE_STATUS, + to_string(estate_)); + messenger_->send(pmsgs); + LOG_DEBUG(logger, "Paper TD inited"); +} +void PaperTDEngine::stop() { + estate_ = EState::STOP; + auto pmsgs = make_shared(DESTINATION_ALL, name_, + MSG_TYPE_ENGINE_STATUS, + to_string(estate_)); + messenger_->send(pmsgs); + LOG_DEBUG(logger, "Paper TD stoped"); +} - void PaperTDEngine::start(){ - while(estate_ != EState::STOP){ - auto pmsgin = messenger_->recv(); - bool processmsg = ((pmsgin != nullptr) && ( startwith(pmsgin->destination_,DESTINATION_ALL) || (startwith(pmsgin->destination_,name_) ))); - // if (pmsgin == nullptr || !startwith(pmsgin->destination_, name_) ) - // continue; - if (processmsg){ - switch (pmsgin->msgtype_) - { - case MSG_TYPE_ENGINE_CONNECT: - if (connect()){ - auto pmsgout = make_shared(pmsgin->source_, name_, - MSG_TYPE_INFO_ENGINE_TDCONNECTED,"PAPER TD Connected."); - messenger_->send(pmsgout,1); - - } - break; - case MSG_TYPE_ENGINE_DISCONNECT: - disconnect(); - break; - case MSG_TYPE_ORDER_PAPER: - case MSG_TYPE_ORDER: - if (estate_ == LOGIN_ACK){ - auto pmsgin2 = static_pointer_cast(pmsgin); - insertOrder(pmsgin2); - } - else{ - LOG_DEBUG(logger,"PAPER_TD is not connected,can not insert order!"); - auto pmsgout = make_shared(pmsgin->source_, name_, - MSG_TYPE_ERROR_ENGINENOTCONNECTED, - "Paper Td is not connected,can not insert order!"); - messenger_->send(pmsgout); - } - break; - case MSG_TYPE_CANCEL_ORDER: - if (estate_ == LOGIN_ACK){ - auto pmsgin2 = static_pointer_cast(pmsgin); - cancelOrder(pmsgin2); - } - else{ - LOG_DEBUG(logger,"PAPER_TD is not connected,can not cancel order!"); - auto pmsgout = make_shared(pmsgin->source_, name_, - MSG_TYPE_ERROR_ENGINENOTCONNECTED, - "Paper Td is not connected,can not cancel order!"); - messenger_->send(pmsgout); - } - break; - case MSG_TYPE_QRY_POS: - if (estate_ == LOGIN_ACK){ - queryPosition(pmsgin); - } - else{ - LOG_DEBUG(logger,"PAPER_TD is not connected,can not qry pos!"); - auto pmsgout = make_shared(pmsgin->source_, name_, - MSG_TYPE_ERROR_ENGINENOTCONNECTED, - "PAPER TD is not connected,can not qry pos!"); - messenger_->send(pmsgout); - } - break; - case MSG_TYPE_QRY_ACCOUNT: - if (estate_ == LOGIN_ACK){ - queryAccount(pmsgin); - } - else{ - LOG_DEBUG(logger,"PAPER_TD is not connected,can not qry acc!"); - auto pmsgout = make_shared(pmsgin->source_, name_, - MSG_TYPE_ERROR_ENGINENOTCONNECTED, - "paper Td is not connected,can not qry acc!"); - messenger_->send(pmsgout); - } - break; - case MSG_TYPE_ENGINE_STATUS: - { - auto pmsgout = make_shared(pmsgin->source_, name_, - MSG_TYPE_ENGINE_STATUS, - to_string(estate_)); - messenger_->send(pmsgout); - } - break; - case MSG_TYPE_TEST: - { - auto pmsgout = make_shared(pmsgin->source_, name_, - MSG_TYPE_TEST, - "test"); - messenger_->send(pmsgout); - LOG_DEBUG(logger,"PAPER_TD return test msg!"); - } - break; - case MSG_TYPE_TIMER: - timertask(); - break; - default: - processbuf(); - break; - } - } - else{ - processbuf(); +void PaperTDEngine::start() { + while (estate_ != EState::STOP) { + auto pmsgin = messenger_->recv(); + bool processmsg = ((pmsgin != nullptr) + && ( startwith(pmsgin->destination_,DESTINATION_ALL) || (startwith(pmsgin->destination_,name_)))); + // if (pmsgin == nullptr || !startwith(pmsgin->destination_, name_) ) + // continue; + if (processmsg) { + switch (pmsgin->msgtype_) { + case MSG_TYPE_ENGINE_CONNECT: + if (connect()) { + auto pmsgout = make_shared(pmsgin->source_, name_, + MSG_TYPE_INFO_ENGINE_TDCONNECTED, "PAPER TD Connected."); + messenger_->send(pmsgout, 1); + } + break; + case MSG_TYPE_ENGINE_DISCONNECT: + disconnect(); + break; + case MSG_TYPE_ORDER_PAPER: + case MSG_TYPE_ORDER: + if (estate_ == LOGIN_ACK) { + auto pmsgin2 = static_pointer_cast(pmsgin); + insertOrder(pmsgin2); + } else { + LOG_DEBUG(logger,"PAPER_TD is not connected,can not insert order!"); + auto pmsgout = make_shared(pmsgin->source_, name_, + MSG_TYPE_ERROR_ENGINENOTCONNECTED, + "Paper Td is not connected,can not insert order!"); + messenger_->send(pmsgout); + } + break; + case MSG_TYPE_CANCEL_ORDER: + if (estate_ == LOGIN_ACK) { + auto pmsgin2 = static_pointer_cast(pmsgin); + cancelOrder(pmsgin2); + } else { + LOG_DEBUG(logger,"PAPER_TD is not connected,can not cancel order!"); + auto pmsgout = make_shared(pmsgin->source_, name_, + MSG_TYPE_ERROR_ENGINENOTCONNECTED, + "Paper Td is not connected,can not cancel order!"); + messenger_->send(pmsgout); + } + break; + case MSG_TYPE_QRY_POS: + if (estate_ == LOGIN_ACK) { + queryPosition(pmsgin); + } else { + LOG_DEBUG(logger, "PAPER_TD is not connected,can not qry pos!"); + auto pmsgout = make_shared(pmsgin->source_, name_, + MSG_TYPE_ERROR_ENGINENOTCONNECTED, + "PAPER TD is not connected,can not qry pos!"); + messenger_->send(pmsgout); + } + break; + case MSG_TYPE_QRY_ACCOUNT: + if (estate_ == LOGIN_ACK){ + queryAccount(pmsgin); + } else { + LOG_DEBUG(logger, "PAPER_TD is not connected,can not qry acc!"); + auto pmsgout = make_shared(pmsgin->source_, name_, + MSG_TYPE_ERROR_ENGINENOTCONNECTED, + "paper Td is not connected,can not qry acc!"); + messenger_->send(pmsgout); + } + break; + case MSG_TYPE_ENGINE_STATUS: + { + auto pmsgout = make_shared(pmsgin->source_, name_, + MSG_TYPE_ENGINE_STATUS, + to_string(estate_)); + messenger_->send(pmsgout); + } + break; + case MSG_TYPE_TEST: + { + auto pmsgout = make_shared(pmsgin->source_, name_, + MSG_TYPE_TEST, + "test"); + messenger_->send(pmsgout); + LOG_DEBUG(logger,"PAPER_TD return test msg!"); + } + break; + case MSG_TYPE_TIMER: + timertask(); + break; + default: + processbuf(); + break; } - + } else { + processbuf(); } } +} - void PaperTDEngine::processbuf(){ +void PaperTDEngine::processbuf() { +} - } - void PaperTDEngine::timertask(){ - - } - bool PaperTDEngine::connect(){ - msleep(1000); - estate_ = LOGIN_ACK; - auto pmsg = make_shared(DESTINATION_ALL, name_, - MSG_TYPE_ENGINE_STATUS, - to_string(estate_)); - messenger_->send(pmsg); - return true; - } +void PaperTDEngine::timertask() { +} - bool PaperTDEngine::disconnect(){ - msleep(1000); - estate_ = DISCONNECTED; - auto pmsg = make_shared(DESTINATION_ALL, name_, +bool PaperTDEngine::connect() { + msleep(1000); + estate_ = LOGIN_ACK; + auto pmsg = make_shared(DESTINATION_ALL, name_, MSG_TYPE_ENGINE_STATUS, to_string(estate_)); - messenger_->send(pmsg); - return true; - } + messenger_->send(pmsg); + return true; +} +bool PaperTDEngine::disconnect() { + msleep(1000); + estate_ = DISCONNECTED; + auto pmsg = make_shared(DESTINATION_ALL, name_, + MSG_TYPE_ENGINE_STATUS, + to_string(estate_)); + messenger_->send(pmsg); + return true; +} - void PaperTDEngine::insertOrder(shared_ptr pmsg){ - lock_guard g(oid_mtx); - pmsg->data_.serverOrderID_ = m_serverOrderId++; - pmsg->data_.brokerOrderID_ = m_brokerOrderId_++; - pmsg->data_.orderNo_ = string("PAPER.TD-") + to_string(pmsg->data_.brokerOrderID_); - pmsg->data_.localNo_ = pmsg->data_.orderNo_; - pmsg->data_.createTime_ = ymdhmsf(); - pmsg->data_.orderStatus_ = OrderStatus::OS_Submitted; - pmsg->data_.price_ = pmsg->data_.limitPrice_; - pmsg->data_.quantity_ = pmsg->data_.orderSize_; - pmsg->data_.flag_ = pmsg->data_.orderFlag_; - auto o = static_pointer_cast(pmsg->toPOrder()); - OrderManager::instance().trackOrder(o); - // begin simulate trade, now only support L1 - if (DataManager::instance().orderBook_.find(o->fullSymbol_) != DataManager::instance().orderBook_.end()){ - double lastprice = DataManager::instance().orderBook_[o->fullSymbol_].price_; - double lastaskprice1 = DataManager::instance().orderBook_[o->fullSymbol_].askPrice_[0]; - double lastbidprice1 = DataManager::instance().orderBook_[o->fullSymbol_].bidPrice_[0]; - long lastasksize1 = DataManager::instance().orderBook_[o->fullSymbol_].askSize_[0]; - long lastbidsize1 = DataManager::instance().orderBook_[o->fullSymbol_].bidSize_[0]; - auto pmsgfill = make_shared(); - pmsgfill->destination_ = pmsg->source_; - pmsgfill->source_ = name_; - pmsgfill->data_.fullSymbol_ = o->fullSymbol_; - pmsgfill->data_.tradeTime_ = ymdhmsf(); - pmsgfill->data_.orderNo_ = o->orderNo_; - pmsgfill->data_.serverOrderID_ = o->serverOrderID_; - pmsgfill->data_.clientOrderID_ = o->clientOrderID_; - pmsgfill->data_.brokerOrderID_ = o->brokerOrderID_; - pmsgfill->data_.tradeId_ = fillID_++; - pmsgfill->data_.tradeNo_ = to_string(pmsgfill->data_.tradeId_); - pmsgfill->data_.account_ = o->account_; - pmsgfill->data_.api_ = o->api_; +void PaperTDEngine::insertOrder(shared_ptr pmsg) { + lock_guard g(oid_mtx); + pmsg->data_.serverOrderID_ = m_serverOrderId++; + pmsg->data_.brokerOrderID_ = m_brokerOrderId_++; + pmsg->data_.orderNo_ = string("PAPER.TD-") + to_string(pmsg->data_.brokerOrderID_); + pmsg->data_.localNo_ = pmsg->data_.orderNo_; + pmsg->data_.createTime_ = ymdhmsf(); + pmsg->data_.orderStatus_ = OrderStatus::OS_Submitted; + pmsg->data_.price_ = pmsg->data_.limitPrice_; + pmsg->data_.quantity_ = pmsg->data_.orderSize_; + pmsg->data_.flag_ = pmsg->data_.orderFlag_; - if (o->orderType_ == OrderType::OT_Market){ - pmsgfill->data_.fillFlag_ = o->orderFlag_; - if (o->orderSize_ > 0){ - pmsgfill->data_.tradePrice_ = lastaskprice1; - pmsgfill->data_.tradeSize_ = o->orderSize_ < lastasksize1 ? o->orderSize_ : lastasksize1; - } - else - { - pmsgfill->data_.tradePrice_ = lastbidprice1; - pmsgfill->data_.tradeSize_ = (-1)*o->orderSize_ < lastasksize1 ? o->orderSize_ : lastasksize1*(-1); - } + auto o = static_pointer_cast(pmsg->toPOrder()); + OrderManager::instance().trackOrder(o); + // begin simulate trade, now only support L1 + if (DataManager::instance().orderBook_.find(o->fullSymbol_) != DataManager::instance().orderBook_.end()) { + double lastprice = DataManager::instance().orderBook_[o->fullSymbol_].price_; + double lastaskprice1 = DataManager::instance().orderBook_[o->fullSymbol_].askPrice_[0]; + double lastbidprice1 = DataManager::instance().orderBook_[o->fullSymbol_].bidPrice_[0]; + int64_t lastasksize1 = DataManager::instance().orderBook_[o->fullSymbol_].askSize_[0]; + int64_t lastbidsize1 = DataManager::instance().orderBook_[o->fullSymbol_].bidSize_[0]; + auto pmsgfill = make_shared(); + pmsgfill->destination_ = pmsg->source_; + pmsgfill->source_ = name_; + pmsgfill->data_.fullSymbol_ = o->fullSymbol_; + pmsgfill->data_.tradeTime_ = ymdhmsf(); + pmsgfill->data_.orderNo_ = o->orderNo_; + pmsgfill->data_.serverOrderID_ = o->serverOrderID_; + pmsgfill->data_.clientOrderID_ = o->clientOrderID_; + pmsgfill->data_.brokerOrderID_ = o->brokerOrderID_; + pmsgfill->data_.tradeId_ = fillID_++; + pmsgfill->data_.tradeNo_ = to_string(pmsgfill->data_.tradeId_); + pmsgfill->data_.account_ = o->account_; + pmsgfill->data_.api_ = o->api_; + + if (o->orderType_ == OrderType::OT_Market) { + pmsgfill->data_.fillFlag_ = o->orderFlag_; + if (o->orderSize_ > 0) { + pmsgfill->data_.tradePrice_ = lastaskprice1; + pmsgfill->data_.tradeSize_ = o->orderSize_ < lastasksize1 ? o->orderSize_ : lastasksize1; + } else { + pmsgfill->data_.tradePrice_ = lastbidprice1; + pmsgfill->data_.tradeSize_ = (-1)*o->orderSize_ < lastasksize1 ? o->orderSize_ : lastasksize1*(-1); } - else if(o->orderType_ == OrderType::OT_Limit){ - if (o->orderSize_ > 0){ - if (o->limitPrice_ >= lastaskprice1){ - if (lastprice < lastaskprice1){ - pmsgfill->data_.tradePrice_ = lastaskprice1; - } - else if (lastprice > o->limitPrice_) - { - pmsgfill->data_.tradePrice_ = o->limitPrice_; - } - else - { - pmsgfill->data_.tradePrice_ = lastprice; - } - pmsgfill->data_.tradeSize_ = o->orderSize_ < lastasksize1 ? o->orderSize_ : lastasksize1; - pmsgfill->data_.fillFlag_ = o->orderFlag_; - } - else - { - lock_guard gs(orderStatus_mtx); - o->orderStatus_ = OrderStatus::OS_Error; - auto pos = make_shared(pmsg->source_,name_); - pos->set(o); - // auto pmsgout = make_shared(pmsg->source_, name_, - // MSG_TYPE_ERROR_INSERTORDER, - // to_string(o->clientOrderID_)); - messenger_->send(pos); - LOG_INFO(logger,"Paper TD cannot deal due to price is below ask price"); - return; + } else if (o->orderType_ == OrderType::OT_Limit) { + if (o->orderSize_ > 0) { + if (o->limitPrice_ >= lastaskprice1) { + if (lastprice < lastaskprice1) { + pmsgfill->data_.tradePrice_ = lastaskprice1; + } else if (lastprice > o->limitPrice_) { + pmsgfill->data_.tradePrice_ = o->limitPrice_; + } else { + pmsgfill->data_.tradePrice_ = lastprice; } + pmsgfill->data_.tradeSize_ = o->orderSize_ < lastasksize1 ? o->orderSize_ : lastasksize1; + pmsgfill->data_.fillFlag_ = o->orderFlag_; + } else { + lock_guard gs(orderStatus_mtx); + o->orderStatus_ = OrderStatus::OS_Error; + auto pos = make_shared(pmsg->source_, name_); + pos->set(o); + // auto pmsgout = make_shared(pmsg->source_, name_, + // MSG_TYPE_ERROR_INSERTORDER, + // to_string(o->clientOrderID_)); + messenger_->send(pos); + LOG_INFO(logger, "Paper TD cannot deal due to price is below ask price"); + return; } - else - { - if (o->limitPrice_ <= lastbidprice1){ - if (lastprice > lastbidprice1){ - pmsgfill->data_.tradePrice_ = lastbidprice1; - } - else if (lastprice < o->limitPrice_) - { - pmsgfill->data_.tradePrice_ = o->limitPrice_; - } - else - { - pmsgfill->data_.tradePrice_ = lastprice; - } - pmsgfill->data_.tradeSize_ = (-1)*o->orderSize_ < lastbidsize1 ? o->orderSize_ : (-1)*lastbidsize1; - pmsgfill->data_.fillFlag_ = o->orderFlag_; - } - else - { - lock_guard gs(orderStatus_mtx); - o->orderStatus_ = OrderStatus::OS_Error; - auto pos = make_shared(pmsg->source_,name_); - pos->set(o); - // auto pmsgout = make_shared(pmsg->source_, name_, - // MSG_TYPE_ERROR_INSERTORDER, - // to_string(o->clientOrderID_)); - messenger_->send(pos); - LOG_INFO(logger,"Paper TD cannot deal due to price is above bid price"); - return; + } else { + if (o->limitPrice_ <= lastbidprice1) { + if (lastprice > lastbidprice1) { + pmsgfill->data_.tradePrice_ = lastbidprice1; + } else if (lastprice < o->limitPrice_) { + pmsgfill->data_.tradePrice_ = o->limitPrice_; + } else { + pmsgfill->data_.tradePrice_ = lastprice; } - } - } - else if (o->orderType_ == OrderType::OT_StopLimit){ - lock_guard gs(orderStatus_mtx); - o->orderStatus_ = OrderStatus::OS_Error; - auto pos = make_shared(pmsg->source_,name_); - pos->set(o); - // auto pmsgout = make_shared(pmsg->source_, name_, - // MSG_TYPE_ERROR_INSERTORDER, - // to_string(o->clientOrderID_)); - messenger_->send(pos); - LOG_ERROR(logger,"Paper TD donot support stop order yet"); - return; + pmsgfill->data_.tradeSize_ = (-1)*o->orderSize_ < lastbidsize1 ? o->orderSize_ : (-1)*lastbidsize1; + pmsgfill->data_.fillFlag_ = o->orderFlag_; + } else { + lock_guard gs(orderStatus_mtx); + o->orderStatus_ = OrderStatus::OS_Error; + auto pos = make_shared(pmsg->source_, name_); + pos->set(o); + // auto pmsgout = make_shared(pmsg->source_, name_, + // MSG_TYPE_ERROR_INSERTORDER, + // to_string(o->clientOrderID_)); + messenger_->send(pos); + LOG_INFO(logger, "Paper TD cannot deal due to price is above bid price"); + return; + } } - OrderManager::instance().gotFill(pmsgfill->data_); - lock_guard gs(orderStatus_mtx); - o->orderStatus_ = OrderStatus::OS_Filled; - o->tradedvol_ = pmsgfill->data_.tradeSize_; - auto pos = make_shared(pmsg->source_,name_); - pos->set(o); - messenger_->send(pos); - messenger_->send(pmsgfill); - LOG_INFO(logger,name_<<" Fill Order: clientorderid ="<clientOrderID_<<"fullsymbol = "<fullSymbol_); - } - else - { + } else if (o->orderType_ == OrderType::OT_StopLimit) { lock_guard gs(orderStatus_mtx); o->orderStatus_ = OrderStatus::OS_Error; auto pos = make_shared(pmsg->source_,name_); - pos->set(o); + pos->set(o); // auto pmsgout = make_shared(pmsg->source_, name_, // MSG_TYPE_ERROR_INSERTORDER, // to_string(o->clientOrderID_)); messenger_->send(pos); - LOG_ERROR(logger,"Paper TD order insert error: due to DM dont have markets info"); + LOG_ERROR(logger,"Paper TD donot support stop order yet"); return; } - - } - - void PaperTDEngine::cancelOrder(shared_ptr pmsg){ - LOG_INFO(logger,name_<<" don't support cancelorder yet!"); - } - - // 查询账户 - void PaperTDEngine::queryAccount(shared_ptr pmsg) { - } - /// 查询pos - void PaperTDEngine::queryPosition(shared_ptr pmsg) { + OrderManager::instance().gotFill(pmsgfill->data_); + lock_guard gs(orderStatus_mtx); + o->orderStatus_ = OrderStatus::OS_Filled; + o->tradedvol_ = pmsgfill->data_.tradeSize_; + auto pos = make_shared(pmsg->source_,name_); + pos->set(o); + messenger_->send(pos); + messenger_->send(pmsgfill); + LOG_INFO(logger,name_<<" Fill Order: clientorderid ="<clientOrderID_<<"fullsymbol = "<fullSymbol_); + } else { + lock_guard gs(orderStatus_mtx); + o->orderStatus_ = OrderStatus::OS_Error; + auto pos = make_shared(pmsg->source_,name_); + pos->set(o); + // auto pmsgout = make_shared(pmsg->source_, name_, + // MSG_TYPE_ERROR_INSERTORDER, + // to_string(o->clientOrderID_)); + messenger_->send(pos); + LOG_ERROR(logger,"Paper TD order insert error: due to DM dont have markets info"); + return; } +} + +void PaperTDEngine::cancelOrder(shared_ptr pmsg) { + LOG_INFO(logger, name_<< " don't support cancelorder yet!"); +} + +// 查询账户 +void PaperTDEngine::queryAccount(shared_ptr pmsg) { +} +/// 查询pos +void PaperTDEngine::queryPosition(shared_ptr pmsg) { +} -} \ No newline at end of file +} // namespace StarQuant diff --git a/cppsrc/StarQuant/Engine/PaperTDEngine.h b/cppsrc/StarQuant/Engine/PaperTDEngine.h index 166a12611..79ff16079 100644 --- a/cppsrc/StarQuant/Engine/PaperTDEngine.h +++ b/cppsrc/StarQuant/Engine/PaperTDEngine.h @@ -1,12 +1,27 @@ -#ifndef _StarQuant_Engine_PaperTDEngine_H_ -#define _StarQuant_Engine_PaperTDEngine_H_ +/***************************************************************************** + * Copyright [2019] + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *****************************************************************************/ + +#ifndef CPPSRC_STARQUANT_ENGINE_PAPERTDENGINE_H_ +#define CPPSRC_STARQUANT_ENGINE_PAPERTDENGINE_H_ -#include #include #include #include - +#include +#include using std::mutex; using std::string; @@ -16,30 +31,30 @@ using std::vector; namespace StarQuant { - class PaperTDEngine : public IEngine { - public: - string name_; - long m_brokerOrderId_; - long fillID_; - - PaperTDEngine(); - ~PaperTDEngine(); - - virtual void init(); - virtual void start(); - virtual void stop(); - virtual bool connect() ; - virtual bool disconnect() ; - - void processbuf(); - void timertask(); - - void insertOrder(shared_ptr pmsg); - void cancelOrder(shared_ptr pmsg); - void queryAccount(shared_ptr pmsg); - void queryPosition(shared_ptr pmsg); - - }; -} - -#endif +class PaperTDEngine : public IEngine { + public: + string name_; + int64_t m_brokerOrderId_; + int64_t fillID_; + + PaperTDEngine(); + ~PaperTDEngine(); + + virtual void init(); + virtual void start(); + virtual void stop(); + virtual bool connect(); + virtual bool disconnect(); + + void processbuf(); + void timertask(); + + void insertOrder(shared_ptr pmsg); + void cancelOrder(shared_ptr pmsg); + void queryAccount(shared_ptr pmsg); + void queryPosition(shared_ptr pmsg); +}; + +} // namespace StarQuant + +#endif // CPPSRC_STARQUANT_ENGINE_PAPERTDENGINE_H_ diff --git a/cppsrc/StarQuant/Engine/TapMDEngine.cpp b/cppsrc/StarQuant/Engine/TapMDEngine.cpp index 53cd9b528..cc58cf3e9 100644 --- a/cppsrc/StarQuant/Engine/TapMDEngine.cpp +++ b/cppsrc/StarQuant/Engine/TapMDEngine.cpp @@ -58,8 +58,8 @@ namespace StarQuant } void TapMDEngine::stop(){ - int tmp = disconnect(); - int count = 0; + int32_t tmp = disconnect(); + int32_t count = 0; while( estate_ != DISCONNECTED){ msleep(100); count++; @@ -82,7 +82,7 @@ namespace StarQuant APIStrncpy(stLoginAuth.Password, tapacc_.password.c_str()); stLoginAuth.ISModifyPassword = APIYNFLAG_NO; stLoginAuth.ISDDA = APIYNFLAG_NO; - int count = 0; + int32_t count = 0; while(estate_ != EState::LOGIN_ACK){ switch(estate_){ case EState::DISCONNECTED: diff --git a/cppsrc/StarQuant/Engine/TapTDEngine.cpp b/cppsrc/StarQuant/Engine/TapTDEngine.cpp index 090fe0db3..21ec5b4e1 100644 --- a/cppsrc/StarQuant/Engine/TapTDEngine.cpp +++ b/cppsrc/StarQuant/Engine/TapTDEngine.cpp @@ -55,8 +55,8 @@ void TapTDEngine::init(){ } void TapTDEngine::stop(){ - int tmp = disconnect(); - int count = 0; + int32_t tmp = disconnect(); + int32_t count = 0; while( estate_ != DISCONNECTED){ msleep(100); count++; @@ -78,7 +78,7 @@ bool TapTDEngine::connect() { strcpy(stLoginAuth.Password, tapacc_.password.c_str()); stLoginAuth.ISModifyPassword = APIYNFLAG_NO; stLoginAuth.ISDDA = APIYNFLAG_NO; - int count = 0; + int32_t count = 0; while(estate_ != EState::LOGIN_ACK){ switch(estate_){ case EState::DISCONNECTED: @@ -122,7 +122,7 @@ bool TapTDEngine::connect() { bool TapTDEngine::disconnect() { PRINT_TO_FILE("INFO:[%s,%d][%s]Tap td disconnecting!\n", __FILE__, __LINE__, __FUNCTION__); estate_ = LOGOUTING; - int i = api_->Disconnect(); + int32_t i = api_->Disconnect(); if (i != TAPIERROR_SUCCEED){ cout<<"tap td disconnect error:"<& v) { - int source = stoi(v[1]); + int32_t source = stoi(v[1]); long coid = stol(v[3]); PRINT_TO_FILE_AND_CONSOLE("INFO:[%s,%d][%s]Cancel Order clientOrderId=%ld\n", __FILE__, __LINE__, __FUNCTION__, coid); TAPIINT32 iErr = TAPIERROR_SUCCEED; diff --git a/cppsrc/StarQuant/Engine/TapTDEngine.h b/cppsrc/StarQuant/Engine/TapTDEngine.h index 7919718f8..29614402f 100644 --- a/cppsrc/StarQuant/Engine/TapTDEngine.h +++ b/cppsrc/StarQuant/Engine/TapTDEngine.h @@ -76,7 +76,7 @@ namespace StarQuant private: long m_brokerOrderId_; - unsigned int sessionID_; // 会话编号 + unsigned int32_t sessionID_; // 会话编号 ITapTradeAPI* api_; OrderStatus TapOrderStatusToOrderStatus(const TAPIOrderStateType); diff --git a/cppsrc/StarQuant/Services/dataservice.cpp b/cppsrc/StarQuant/Services/dataservice.cpp index 3c3d6271d..c22a57579 100644 --- a/cppsrc/StarQuant/Services/dataservice.cpp +++ b/cppsrc/StarQuant/Services/dataservice.cpp @@ -149,7 +149,7 @@ namespace StarQuant //PRINT_TO_FILE("INFO:[%s,%d][%s]recording service stopped: %s\n", __FILE__, __LINE__, __FUNCTION__); } - void TickReplayService(const std::string& filetoreplay,int tickinterval) + void TickReplayService(const std::string& filetoreplay,int32_t tickinterval) { std::unique_ptr msgq_pub_; msgq_pub_ = std::make_unique(MSGQ_PROTOCOL::PUB, CConfig::instance().SERVERPUB_URL); @@ -157,7 +157,7 @@ namespace StarQuant uint64_t logt = 0; //vector lines = readreplayfile(filetoreplay); vector lines = readreplayfile(filetoreplay); - int i = 0, sz = lines.size(); + int32_t i = 0, sz = lines.size(); while (!gShutdown && i++ < sz) { // logt = lines[i].t; // curt = getMicroTime(); diff --git a/cppsrc/StarQuant/Services/dataservice.h b/cppsrc/StarQuant/Services/dataservice.h index c11619ee1..9d0a23637 100644 --- a/cppsrc/StarQuant/Services/dataservice.h +++ b/cppsrc/StarQuant/Services/dataservice.h @@ -7,11 +7,11 @@ namespace StarQuant { - //void MarketDataService(std::shared_ptr, int); + //void MarketDataService(std::shared_ptr, int32_t); void DataBoardService(); void BarAggregatorServcie(); void TickRecordingService(); - void TickReplayService(const std::string& filetoreplay,int tickinterval=0); + void TickReplayService(const std::string& filetoreplay,int32_t tickinterval=0); } #endif diff --git a/cppsrc/StarQuant/Services/sqserver.cpp b/cppsrc/StarQuant/Services/sqserver.cpp index d9f17d84b..38f05e122 100644 --- a/cppsrc/StarQuant/Services/sqserver.cpp +++ b/cppsrc/StarQuant/Services/sqserver.cpp @@ -1,20 +1,31 @@ -#include -#include -#include -#include -#include +/***************************************************************************** + * Copyright [2019] + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *****************************************************************************/ + + -#include #include #include -#include -#include +#include + + using namespace StarQuant; -int main(int argc, char** argv) { - std::cout << "StarQuant Server. Version 0.5\n"; +int32_t main(int32_t argc, char** argv) { + std::cout << "StarQuant Server. Version alpha~ \n"; tradingengine engine; std::cout << "Type Ctrl-C to exit\n\n"; diff --git a/cppsrc/StarQuant/Services/starquant_.cpp b/cppsrc/StarQuant/Services/starquant_.cpp index 73d9d4b91..381563919 100644 --- a/cppsrc/StarQuant/Services/starquant_.cpp +++ b/cppsrc/StarQuant/Services/starquant_.cpp @@ -1,5 +1,20 @@ -#include +/***************************************************************************** + * Copyright [2019] + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *****************************************************************************/ #include +#include + using namespace boost::python; using namespace StarQuant; diff --git a/cppsrc/StarQuant/Services/tradingengine.cpp b/cppsrc/StarQuant/Services/tradingengine.cpp index 1b4b65787..4f0baf0b4 100644 --- a/cppsrc/StarQuant/Services/tradingengine.cpp +++ b/cppsrc/StarQuant/Services/tradingengine.cpp @@ -1,11 +1,17 @@ -#include -#include -#include -#include -#include -#include -#include -#include +/***************************************************************************** + * Copyright [2019] + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *****************************************************************************/ #include #include @@ -25,244 +31,237 @@ //#include #include +#include +#include +#include +#include +#include +#include +#include +#include -namespace StarQuant -{ +namespace StarQuant { - extern std::atomic gShutdown; - extern Except_frame g_except_stack; +extern std::atomic gShutdown; +extern Except_frame g_except_stack; - extern atomic MICRO_SERVICE_NUMBER; +extern atomic MICRO_SERVICE_NUMBER; - void startengine(shared_ptr pe){ - pe->start(); - } +void startengine(shared_ptr pe) { + pe->start(); +} - tradingengine::tradingengine() { - CConfig::instance(); - DataManager::instance(); - OrderManager::instance(); - PortfolioManager::instance(); - RiskManager::instance(); - _broker = CConfig::instance()._broker; - mode = CConfig::instance()._mode; - if(logger == nullptr){ - logger = SQLogger::getLogger("SYS"); - } - // if (IEngine::msgq_send_ == nullptr){ - // IEngine::msgq_send_ = std::make_unique(MSGQ_PROTOCOL::PUB, CConfig::instance().SERVERPUB_URL); - // } - if (CMsgqEMessenger::msgq_send_ == nullptr){ - CMsgqEMessenger::msgq_send_ = std::make_unique(MSGQ_PROTOCOL::PUB, CConfig::instance().SERVERPUB_URL); - msleep(100); - } - if (CMsgqRMessenger::msgq_send_ == nullptr){ - CMsgqRMessenger::msgq_send_ = std::make_unique(MSGQ_PROTOCOL::PUB, CConfig::instance().SERVERSUB_URL); - msleep(100); - } - msg_relay_ = std::make_unique(CConfig::instance().SERVERPULL_URL); +tradingengine::tradingengine() { + CConfig::instance(); + DataManager::instance(); + OrderManager::instance(); + PortfolioManager::instance(); + RiskManager::instance(); + _broker = CConfig::instance()._broker; + mode = CConfig::instance()._mode; + if (logger == nullptr) { + logger = SQLogger::getLogger("SYS"); + } + // if (IEngine::msgq_send_ == nullptr){ + // IEngine::msgq_send_ = std::make_unique(MSGQ_PROTOCOL::PUB, CConfig::instance().SERVERPUB_URL); + // } + if (CMsgqEMessenger::msgq_send_ == nullptr) { + CMsgqEMessenger::msgq_send_ = std::make_unique(MSGQ_PROTOCOL::PUB, CConfig::instance().SERVERPUB_URL); + msleep(100); + } + if (CMsgqRMessenger::msgq_send_ == nullptr) { + CMsgqRMessenger::msgq_send_ = std::make_unique(MSGQ_PROTOCOL::PUB, CConfig::instance().SERVERSUB_URL); msleep(100); } + msg_relay_ = std::make_unique(CConfig::instance().SERVERPULL_URL); + msleep(100); +} - tradingengine::~tradingengine() { - for (auto& e: pengines_){ - while ( (e != nullptr) && (e->estate_ != STOP) ){ - e->stop(); - msleep(100); - } - } - while (MICRO_SERVICE_NUMBER > 0) { +tradingengine::~tradingengine() { + for (auto& e : pengines_) { + while ( (e != nullptr) && (e->estate_ != STOP) ) { + e->stop(); msleep(100); } - if (CConfig::instance()._msgq == MSGQ::NANOMSG) - nn_term(); - for (thread* t : threads_){ - if (t->joinable()){ - t->join(); - delete t; - } - else{ - // pthread_cancel(t->native_handle()); - // delete t; - } + } + while (MICRO_SERVICE_NUMBER > 0) { + msleep(100); + } + if (CConfig::instance()._msgq == MSGQ::NANOMSG) + nn_term(); + for (thread* t : threads_) { + if (t->joinable()) { + t->join(); + delete t; + } else { + // pthread_cancel(t->native_handle()); + // delete t; } - LOG_DEBUG(logger,"Exit trading engine"); } + LOG_DEBUG(logger, "Exit trading engine"); +} - int tradingengine::cronjobs(bool force) { - //set console handler - signal(SIGINT, ConsoleControlHandler); - signal(SIGPWR, ConsoleControlHandler); - - time_t timer; - struct tm tm_info; - - //cronjobs: - //check gshutdown - while (!gShutdown) { - msleep(1 * 1000); - // switch day, at 20:30 everyday, reset td engine, needconfirmation - time(&timer); - tm_info = *localtime(&timer); - // at weekend do nothing 0=sunday 6=saturday - if ((tm_info.tm_wday == 0) || (tm_info.tm_wday == 6)){ - continue; - } - if (tm_info.tm_hour == 20 && tm_info.tm_min == 30 && tm_info.tm_sec == 0){ - std::shared_ptr pmsg = make_shared(DESTINATION_ALL,"0",MSG_TYPE_SWITCH_TRADING_DAY); - msg_relay_->send(pmsg); - RiskManager::instance().switchday(); - } - // auto connect at 8:45, 1:15, 20:45 - if (tm_info.tm_hour == 8 && tm_info.tm_min == 45 && tm_info.tm_sec == 0){ - std::shared_ptr pmsg = make_shared(DESTINATION_ALL,"0",MSG_TYPE_ENGINE_CONNECT); - msg_relay_->send(pmsg); - } - if (tm_info.tm_hour == 13 && tm_info.tm_min == 15 && tm_info.tm_sec == 0){ - std::shared_ptr pmsg = make_shared(DESTINATION_ALL,"0",MSG_TYPE_ENGINE_CONNECT); - msg_relay_->send(pmsg); - } - if (tm_info.tm_hour == 20 && tm_info.tm_min == 45 && tm_info.tm_sec == 0){ - - std::shared_ptr pmsg = make_shared(DESTINATION_ALL,"0",MSG_TYPE_ENGINE_CONNECT); - msg_relay_->send(pmsg); - } - // auto reset at 16:00 ,2:35 - if (tm_info.tm_hour == 16 && tm_info.tm_min == 0 && tm_info.tm_sec == 0){ - std::shared_ptr pmsg = make_shared(DESTINATION_ALL,"0",MSG_TYPE_ENGINE_RESET); - msg_relay_->send(pmsg); - } - if (tm_info.tm_hour == 2 && tm_info.tm_min == 35 && tm_info.tm_sec == 0){ - std::shared_ptr pmsg = make_shared(DESTINATION_ALL,"0",MSG_TYPE_ENGINE_RESET); - msg_relay_->send(pmsg); - } - // send timer msg to all engine - std::shared_ptr pmsg = make_shared(DESTINATION_ALL,"0",MSG_TYPE_TIMER); +int32_t tradingengine::cronjobs(bool force) { +// set console handler + signal(SIGINT, ConsoleControlHandler); + signal(SIGPWR, ConsoleControlHandler); + + time_t timer; + struct tm tm_info; + +// cronjobs: +// check gshutdown + while (!gShutdown) { + msleep(1 * 1000); +// switch day, at 20:30 everyday, reset td engine, needconfirmation + time(&timer); + localtime_r(&timer, &tm_info); + // at weekend do nothing 0=sunday 6=saturday + if ((tm_info.tm_wday == 0) || (tm_info.tm_wday == 6)) { + continue; + } + if (tm_info.tm_hour == 20 && tm_info.tm_min == 30 && tm_info.tm_sec == 0) { + std::shared_ptr pmsg = make_shared(DESTINATION_ALL,"0", MSG_TYPE_SWITCH_TRADING_DAY); msg_relay_->send(pmsg); - //flow count reset - RiskManager::instance().resetflow(); - - + RiskManager::instance().switchday(); } - // ctrl-c - if (force) { - throw runtime_error("ctrl-c triggered shutdown"); +// auto connect at 8:45, 1:15, 20:45 + if (tm_info.tm_hour == 8 && tm_info.tm_min == 45 && tm_info.tm_sec == 0) { + std::shared_ptr pmsg = make_shared(DESTINATION_ALL,"0", MSG_TYPE_ENGINE_CONNECT); + msg_relay_->send(pmsg); + } + if (tm_info.tm_hour == 13 && tm_info.tm_min == 15 && tm_info.tm_sec == 0) { + std::shared_ptr pmsg = make_shared(DESTINATION_ALL,"0", MSG_TYPE_ENGINE_CONNECT); + msg_relay_->send(pmsg); + } + if (tm_info.tm_hour == 20 && tm_info.tm_min == 45 && tm_info.tm_sec == 0) { + std::shared_ptr pmsg = make_shared(DESTINATION_ALL,"0", MSG_TYPE_ENGINE_CONNECT); + msg_relay_->send(pmsg); + } +// auto reset at 16:00 ,2:35 + if (tm_info.tm_hour == 16 && tm_info.tm_min == 0 && tm_info.tm_sec == 0) { + std::shared_ptr pmsg = make_shared(DESTINATION_ALL,"0", MSG_TYPE_ENGINE_RESET); + msg_relay_->send(pmsg); + } + if (tm_info.tm_hour == 2 && tm_info.tm_min == 35 && tm_info.tm_sec == 0) { + std::shared_ptr pmsg = make_shared(DESTINATION_ALL,"0", MSG_TYPE_ENGINE_RESET); + msg_relay_->send(pmsg); } - return 0; +// send timer msg to all engine + std::shared_ptr pmsg = make_shared(DESTINATION_ALL,"0", MSG_TYPE_TIMER); + msg_relay_->send(pmsg); +// flow count reset + RiskManager::instance().resetflow(); } + // ctrl-c + if (force) { + throw runtime_error("ctrl-c triggered shutdown"); + } + return 0; +} - int tradingengine::run() { - if (gShutdown) - return 1; - // sigsegv sig backtrace - g_except_stack.flag = sigsetjmp(g_except_stack.env,1); - if (!g_except_stack.isDef()){ - signal(SIGSEGV,recvSignal); - try { - auto fu1 = async(launch::async, std::bind(&tradingengine::cronjobs,this,std::placeholders::_1), true); - if (mode == RUN_MODE::RECORD_MODE) { - LOG_INFO(logger,"RECORD_MODE"); - //threads_.push_back(new thread(TickRecordingService)); +int32_t tradingengine::run() { + if (gShutdown) + return 1; + // sigsegv sig backtrace + g_except_stack.flag = sigsetjmp(g_except_stack.env, 1); + if (!g_except_stack.isDef()) { + signal(SIGSEGV, recvSignal); + try { + auto fu1 = async(launch::async, std::bind(&tradingengine::cronjobs,this,std::placeholders::_1), true); + if (mode == RUN_MODE::RECORD_MODE) { + LOG_INFO(logger, "RECORD_MODE"); + // threads_.push_back(new thread(TickRecordingService)); + } else if (mode == RUN_MODE::REPLAY_MODE) { + LOG_INFO(logger, "REPLAY_MODE"); + // threads_.push_back(new thread(TickReplayService, CConfig::instance().filetoreplay,CConfig::instance()._tickinterval)); + // threads_.push_back(new thread(DataBoardService)); + // //threads_.push_back(new thread(StrategyManagerService)); + } else if (mode == RUN_MODE::TRADE_MODE) { + LOG_INFO(logger, "TRADE_MODE"); + // threads_.push_back(new thread(TickRecordingService)); + for (auto iter = CConfig::instance()._gatewaymap.begin(); iter != CConfig::instance()._gatewaymap.end(); iter++){ + if (iter->second.api == "CTP.TD") { + std::shared_ptr ctptdengine = make_shared(iter->first); + threads_.push_back(new std::thread(startengine, ctptdengine)); + pengines_.push_back(ctptdengine); + } else if (iter->second.api == "CTP.MD") { + std::shared_ptr ctpmdengine = make_shared(); + pengines_.push_back(ctpmdengine); + threads_.push_back(new std::thread(startengine, ctpmdengine)); + } else if (iter->second.api == "PAPER.TD") { + std::shared_ptr papertdengine = make_shared(); + threads_.push_back(new std::thread(startengine, papertdengine)); + pengines_.push_back(papertdengine); + } else if (iter->second.api == "TAP.TD") { + // TODO: finish later + } else if (iter->second.api == "TAP.MD") { + // TODO: finish later + } else { + LOG_INFO(logger, "API not supported ,ignore it!"); } - else if (mode == RUN_MODE::REPLAY_MODE) { - LOG_INFO(logger,"REPLAY_MODE"); - // threads_.push_back(new thread(TickReplayService, CConfig::instance().filetoreplay,CConfig::instance()._tickinterval)); - // threads_.push_back(new thread(DataBoardService)); - // //threads_.push_back(new thread(StrategyManagerService)); - } - else if (mode == RUN_MODE::TRADE_MODE) { - LOG_INFO(logger,"TRADE_MODE"); - //threads_.push_back(new thread(TickRecordingService)); - for (auto iter = CConfig::instance()._gatewaymap.begin(); iter != CConfig::instance()._gatewaymap.end(); iter++){ - if (iter->second.api == "CTP.TD"){ - std::shared_ptr ctptdengine = make_shared(iter->first); - threads_.push_back(new std::thread(startengine,ctptdengine)); - pengines_.push_back(ctptdengine); - } - else if (iter->second.api == "CTP.MD"){ - std::shared_ptr ctpmdengine = make_shared(); - pengines_.push_back(ctpmdengine); - threads_.push_back(new std::thread(startengine,ctpmdengine)); - } - else if (iter->second.api == "PAPER.TD"){ - std::shared_ptr papertdengine = make_shared(); - threads_.push_back(new std::thread(startengine,papertdengine)); - pengines_.push_back(papertdengine); - } - else if (iter->second.api == "TAP.TD"){ - // TODO: finish later - } - else if (iter->second.api == "TAP.MD"){ - // TODO: finish later - } - else{ - LOG_INFO(logger,"API not supported ,ignore it!"); - } - } - } - else { - LOG_ERROR(logger,"Mode doesn't exist,exit."); - return 1; } - // set thread affinity - //engine thread - if (CConfig::instance().cpuaffinity){ - int num_cpus = std::thread::hardware_concurrency(); - for (int i = 0; i< threads_.size();i ++){ - cpu_set_t cpuset; - CPU_ZERO(&cpuset); - CPU_SET(i%num_cpus,&cpuset); - int rc = pthread_setaffinity_np(threads_[i]->native_handle(),sizeof(cpu_set_t),&cpuset); - if (rc != 0) { - std::cerr << "Error calling pthread_setaffinity_np: " << rc << "\n"; - } - } - //main thread + } else { + LOG_ERROR(logger, "Mode doesn't exist,exit."); + return 1; + } + // set thread affinity + // engine thread + if (CConfig::instance().cpuaffinity) { + int32_t num_cpus = std::thread::hardware_concurrency(); + for (int32_t i = 0; i< threads_.size(); i ++) { cpu_set_t cpuset; CPU_ZERO(&cpuset); - CPU_SET(threads_.size()%num_cpus,&cpuset); - int rc = pthread_setaffinity_np(pthread_self(),sizeof(cpu_set_t),&cpuset); - if (rc != 0) { - std::cerr << "Error calling pthread_setaffinity_np: " << rc << "\n"; - } + CPU_SET(i%num_cpus, &cpuset); + int32_t rc = pthread_setaffinity_np(threads_[i]->native_handle(),sizeof(cpu_set_t),&cpuset); + if (rc != 0) { + std::cerr << "Error calling pthread_setaffinity_np: " << rc << "\n"; + } } - while(!gShutdown){ - msg_relay_->relay(); + //main thread + cpu_set_t cpuset; + CPU_ZERO(&cpuset); + CPU_SET(threads_.size()%num_cpus, &cpuset); + int32_t rc = pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset); + if (rc != 0) { + std::cerr << "Error calling pthread_setaffinity_np: " << rc << "\n"; } - - fu1.get(); } - catch (exception& e) { - LOG_INFO(logger,e.what()); - } - catch (...) { - LOG_ERROR(logger,"StarQuant terminated in error!"); + while (!gShutdown) { + msg_relay_->relay(); } + + fu1.get(); } - else - { - //g_except_stack.clear(); - signal(SIGSEGV,SIG_IGN); - LOG_ERROR(logger,"StarQuant terminated by SEGSEGV!"); - exit(0); + catch (exception& e) { + LOG_INFO(logger, e.what()); } - - for (const auto& e: pengines_){ - e->stop(); + catch (...) { + LOG_ERROR(logger, "StarQuant terminated in error!"); } - return 0; + } else { + // g_except_stack.clear(); + signal(SIGSEGV, SIG_IGN); + LOG_ERROR(logger, "StarQuant terminated by SEGSEGV!"); + exit(0); } - bool tradingengine::live() const { - return gShutdown == true; + for (const auto& e : pengines_) { + e->stop(); } + return 0; +} + +bool tradingengine::live() const { + return gShutdown == true; +} @@ -271,4 +270,4 @@ namespace StarQuant -} +} // namespace StarQuant diff --git a/cppsrc/StarQuant/Services/tradingengine.h b/cppsrc/StarQuant/Services/tradingengine.h index 7e7b90c47..1f08d6c87 100644 --- a/cppsrc/StarQuant/Services/tradingengine.h +++ b/cppsrc/StarQuant/Services/tradingengine.h @@ -1,52 +1,62 @@ -#ifndef _StarQuant_Engine_TradingEngine_H_ -#define _StarQuant_Engine_TradingEngine_H_ +/***************************************************************************** + * Copyright [2019] + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *****************************************************************************/ + +#ifndef CPPSRC_STARQUANT_SERVICES_TRADINGENGINE_H_ +#define CPPSRC_STARQUANT_SERVICES_TRADINGENGINE_H_ +#include +#include #include #include #include -#include -#include -using namespace std; - -namespace StarQuant -{ - void startengine(shared_ptr pe); - - - - class DLL_EXPORT_IMPORT tradingengine { - RUN_MODE mode = RUN_MODE::TRADE_MODE; //RUN_MODE::REPLAY_MODE; - BROKERS _broker = BROKERS::PAPER; - vector threads_; - vector> pengines_; - std::unique_ptr msg_relay_; - std::shared_ptr logger; - - public: +#include +using namespace std; +namespace StarQuant { +void startengine(shared_ptr pe); - //std::atomic* setconsolecontrolhandler(void); - //setconsolecontrolhandler(void) - int cronjobs(bool force = true); +class DLL_EXPORT_IMPORT tradingengine { + RUN_MODE mode = RUN_MODE::TRADE_MODE; // RUN_MODE::REPLAY_MODE; + BROKERS _broker = BROKERS::PAPER; + vector threads_; + vector> pengines_; + std::unique_ptr msg_relay_; + std::shared_ptr logger; - int run(); - bool live() const; + public: + // std::atomic* setconsolecontrolhandler(void); + // setconsolecontrolhandler(void) + int32_t cronjobs(bool force = true); + int32_t run(); + bool live() const; + tradingengine(); + ~tradingengine(); + // https://mail.python.org/pipermail/cplusplus-sig/2004-July/007472.html + // http://stackoverflow.com/questions/10142417/boostpython-compilation-fails-because-copy-constructor-is-private + // For Boost::Python + tradingengine(tradingengine&&) = delete; + tradingengine(const tradingengine&) = delete; + tradingengine& operator=(tradingengine&&) = delete; + tradingengine& operator=(const tradingengine&) = delete; +}; - tradingengine(); - ~tradingengine(); +} // namespace StarQuant - // https://mail.python.org/pipermail/cplusplus-sig/2004-July/007472.html - // http://stackoverflow.com/questions/10142417/boostpython-compilation-fails-because-copy-constructor-is-private - // For Boost::Python - tradingengine(tradingengine&&) = delete; - tradingengine(const tradingengine&) = delete; - tradingengine& operator=(tradingengine&&) = delete; - tradingengine& operator=(const tradingengine&) = delete; - }; -} +#endif // CPPSRC_STARQUANT_SERVICES_TRADINGENGINE_H_ -#endif // _StarQuant_Engine_TradingEngine_H_ diff --git a/cppsrc/StarQuant/Trade/calc.cpp b/cppsrc/StarQuant/Trade/calc.cpp index 5e9711eed..c877ad19b 100644 --- a/cppsrc/StarQuant/Trade/calc.cpp +++ b/cppsrc/StarQuant/Trade/calc.cpp @@ -1,38 +1,49 @@ -#include +/***************************************************************************** + * Copyright [2019] + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *****************************************************************************/ + #include #include +#include + using namespace std; namespace StarQuant { namespace Calc { - double OpenPT(double LastTrade, double AvgPrice, bool Side) - { + double OpenPT(double LastTrade, double AvgPrice, bool Side) { return Side ? LastTrade - AvgPrice : AvgPrice - LastTrade; } - double OpenPT(double LastTrade, double AvgPrice, int PosSize) - { + double OpenPT(double LastTrade, double AvgPrice, int32_t PosSize) { return (PosSize == 0) ? 0 : OpenPT(LastTrade, AvgPrice, PosSize > 0); } - double OpenPL(double LastTrade, double AvgPrice, int PosSizeMultiplier) - { + double OpenPL(double LastTrade, double AvgPrice, int32_t PosSizeMultiplier) { return PosSizeMultiplier * (LastTrade - AvgPrice); } - double ClosePT(Position& existing, Fill& adjust) - { + double ClosePT(Position& existing, Fill& adjust) { if (existing.size_ == 0) return 0; // nothing to close if ((existing.size_ > 0) == (adjust.tradeSize_ > 0)) return 0; // if we're adding, nothing to close return (existing.size_ > 0) ? adjust.tradePrice_ - existing.avgPrice_ : existing.avgPrice_ - adjust.tradePrice_; // if long, sell high = profit; if short, sell low = profit } - double ClosePL(Position& existing, Fill& adjust, int multiplier) - { - int closedsize = std::abs(adjust.tradeSize_) > std::abs(existing.size_) ? std::abs(existing.size_) : std::abs(adjust.tradeSize_); // choose the smaller one + double ClosePL(Position& existing, Fill& adjust, int32_t multiplier) { + int32_t closedsize = std::abs(adjust.tradeSize_) > std::abs(existing.size_) ? std::abs(existing.size_) : std::abs(adjust.tradeSize_); // choose the smaller one return ClosePT(existing, adjust) * closedsize * multiplier; } - } -} \ No newline at end of file + } // namespace Calc +} // namespace StarQuant diff --git a/cppsrc/StarQuant/Trade/calc.h b/cppsrc/StarQuant/Trade/calc.h index 2410712d8..b04632132 100644 --- a/cppsrc/StarQuant/Trade/calc.h +++ b/cppsrc/StarQuant/Trade/calc.h @@ -1,5 +1,7 @@ -#ifndef _StarQuant_Trade_Calc_H -#define _StarQuant_Trade_Calc_H + + +#ifndef CPPSRC_STARQUANT_TRADE_CALC_H +#define CPPSRC_STARQUANT_TRADE_CALC_H #include @@ -7,15 +9,15 @@ namespace StarQuant { namespace Calc { // Gets the open PL on a per-share basis, ignoring the size of the position. double OpenPT(double LastTrade, double AvgPrice, bool Side); - double OpenPT(double LastTrade, double AvgPrice, int PosSize); + double OpenPT(double LastTrade, double AvgPrice, int32_t PosSize); // Gets the open PL considering all the shares held in a position. - double OpenPL(double LastTrade, double AvgPrice, int PosSizeMultiplier); + double OpenPL(double LastTrade, double AvgPrice, int32_t PosSizeMultiplier); // Gets the closed PL on a per-share basis, ignoring how many shares are held. - double ClosePT(Position& existing, Fill& adjust); + double ClosePT(const Position& existing, const Fill& adjust); // Gets the closed PL on a position basis, the PL that is registered to the account for the entire shares transacted. - double ClosePL(Position& existing, Fill& adjust, int multiplier = 1); - } -} + double ClosePL(const Position& existing, const Fill& adjust, int32_t multiplier = 1); + } // namespace Calc +} // namespace StarQuant -#endif +#endif // CPPSRC_STARQUANT_TRADE_CALC_H diff --git a/cppsrc/StarQuant/Trade/marginmanager.cpp b/cppsrc/StarQuant/Trade/marginmanager.cpp index ec911767a..30cb58dc4 100644 --- a/cppsrc/StarQuant/Trade/marginmanager.cpp +++ b/cppsrc/StarQuant/Trade/marginmanager.cpp @@ -1,3 +1,17 @@ +/***************************************************************************** + * Copyright [2019] + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *****************************************************************************/ #include namespace StarQuant { diff --git a/cppsrc/StarQuant/Trade/marginmanager.h b/cppsrc/StarQuant/Trade/marginmanager.h index d05cb74ae..a5085babc 100644 --- a/cppsrc/StarQuant/Trade/marginmanager.h +++ b/cppsrc/StarQuant/Trade/marginmanager.h @@ -1,5 +1,20 @@ -#ifndef _StarQuant_Trade_MarginManager_H_ -#define _StarQuant_Trade_MarginManager_H_ +/***************************************************************************** + * Copyright [2019] + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *****************************************************************************/ + +#ifndef CPPSRC_STARQUANT_TRADE_MARGINMANAGER_H_ +#define CPPSRC_STARQUANT_TRADE_MARGINMANAGER_H_ #include #include @@ -8,10 +23,10 @@ using std::string; -namespace StarQuant -{ - class MarginManager { - }; -} +namespace StarQuant { +class MarginManager { +}; + +} // namespace StarQuant -#endif // _StarQuant_Common_MarginManager_H_ \ No newline at end of file +#endif // CPPSRC_STARQUANT_TRADE_MARGINMANAGER_H_ diff --git a/cppsrc/StarQuant/Trade/ordermanager.cpp b/cppsrc/StarQuant/Trade/ordermanager.cpp index 481a1af79..dce222c2c 100644 --- a/cppsrc/StarQuant/Trade/ordermanager.cpp +++ b/cppsrc/StarQuant/Trade/ordermanager.cpp @@ -1,258 +1,249 @@ -#include +/***************************************************************************** + * Copyright [2019] + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *****************************************************************************/ + +#include #include #include #include namespace StarQuant { + // extern int64_t m_serverOrderId ; // unique order id on server side defined in ordermanager.cpp. Every broker has its own id; + // extern std::mutex oid_mtx; // mutex for increasing order id + // extern std::mutex orderStatus_mtx; // mutex for changing order status + +OrderManager* OrderManager::pinstance_ = nullptr; +mutex OrderManager::instancelock_; + +OrderManager::OrderManager() : _count(0) { + // set up stocks from config + reset(); + logger = SQLogger::getLogger("SYS"); +} + +OrderManager::~OrderManager() { + // release all the orders +} + +OrderManager& OrderManager::instance() { + if (pinstance_ == nullptr) { + lock_guard g(instancelock_); + if (pinstance_ == nullptr) { + pinstance_ = new OrderManager(); + } + } + return *pinstance_; +} - //extern long m_serverOrderId ; // unique order id on server side defined in ordermanager.cpp. Every broker has its own id; - //extern std::mutex oid_mtx; // mutex for increasing order id - //extern std::mutex orderStatus_mtx; // mutex for changing order status - - OrderManager* OrderManager::pinstance_ = nullptr; - mutex OrderManager::instancelock_; +void OrderManager::reset() { + orders_.clear(); + fills_.clear(); + cancels_.clear(); - OrderManager::OrderManager() : _count(0) - { - // set up stocks from config - reset(); - logger = SQLogger::getLogger("SYS"); - } + _count = 0; +} - OrderManager::~OrderManager() - { - // release all the orders - } +void OrderManager::trackOrder(std::shared_ptr o) { + // if (o->orderSize_ == 0) { + // LOG_ERROR(logger, "Incorrect OrderSize."); + // return; + // } - OrderManager& OrderManager::instance() { - if (pinstance_ == nullptr) { - lock_guard g(instancelock_); - if (pinstance_ == nullptr) { - pinstance_ = new OrderManager(); - } - } - return *pinstance_; - } + auto iter = orders_.find(o->serverOrderID_); + if (iter != orders_.end()) // order exists + return; - void OrderManager::reset() { - orders_.clear(); - fills_.clear(); - cancels_.clear(); + orders_[o->serverOrderID_] = o; // add to map + cancels_[o->serverOrderID_] = false; + fills_[o->serverOrderID_] = 0; + LOG_INFO(logger, "Order is put under track. ServerOrderId=" << o->serverOrderID_); +} - _count = 0; +void OrderManager::gotOrder(int64_t oid) { + if (!isTracked(oid)) { + LOG_ERROR(logger, "Order is not tracked. ServerOrderId= " << oid); + return; } - void OrderManager::trackOrder(std::shared_ptr o) - { - // if (o->orderSize_ == 0) { - // LOG_ERROR(logger,"Incorrect OrderSize."); - // return; - // } - - auto iter = orders_.find(o->serverOrderID_); - if (iter != orders_.end()) // order exists - return; - - orders_[o->serverOrderID_] = o; // add to map - cancels_[o->serverOrderID_] = false; - fills_[o->serverOrderID_] = 0; - LOG_INFO(logger,"Order is put under track. ServerOrderId="<serverOrderID_); + lock_guard g(orderStatus_mtx); + if ((orders_[oid]->orderStatus_ == OrderStatus::OS_NewBorn) + || (orders_[oid]->orderStatus_ == OrderStatus::OS_Submitted)) { + orders_[oid]->orderStatus_ = OrderStatus::OS_Acknowledged; } +} - void OrderManager::gotOrder(long oid) - { - if (!isTracked(oid)) - { - LOG_ERROR(logger,"Order is not tracked. ServerOrderId= "< +#include #include #include #include #include -#include -#include using namespace std; namespace StarQuant { - //extern long m_serverOrderId; // unique order id on server side defined in ordermanager.cpp. Every broker has its own id; - //extern std::mutex oid_mtx; // mutex for increasing order id; defined in ordermanager.cpp - //extern std::mutex orderStatus_mtx; // mutex for changing order status; defined in ordermanager.cpp - - // TODO: maintain order book - class OrderManager { - public: - OrderManager(); - ~OrderManager(); // release all the orders - static OrderManager* pinstance_; - static mutex instancelock_; - static OrderManager& instance(); - - //std::atomic_int _count = { 0 }; - std::shared_ptr logger; - int _count = 0; - std::map> orders_; - std::map fills_; // signed filled size - std::map cancels_; // if cancelled - mutex wlock; - void reset(); - - void trackOrder(std::shared_ptr o); // put order under track - void gotOrder(long oid); // order acknowledged - void gotFill(Fill& fill); - void gotCancel(long oid); - std::shared_ptr retrieveOrderFromServerOrderId(long oid); - std::shared_ptr retrieveOrderFromSourceAndClientOrderId(int source, long oid); - std::shared_ptr retrieveOrderFromOrderNo(const string& ono); - std::shared_ptr retrieveOrderFromAccAndBrokerOrderId(const string& acc,int oid); - std::shared_ptr retrieveOrderFromAccAndLocalNo(const string& acc,const string& ono); - //std::shared_ptr retrieveOrderFromMatchNo(string fno); - vector> retrieveOrder(const string& fullsymbol); - vector> retrieveNonFilledOrderPtr(); - vector> retrieveNonFilledOrderPtr(const string& fullsymbol); - vector retrieveNonFilledOrderId(); - vector retrieveNonFilledOrderId(const string& fullsymbol); - - bool isEmpty(); - bool isTracked(long oid); - bool isCompleted(long oid); // either filled or canceled - bool hasPendingOrders(); // is all orders either filled or canceled? - }; -} - -#endif // _StarQuant_Common_OrderManager_H_ \ No newline at end of file + //extern int64_t m_serverOrderId; // unique order id on server side defined in ordermanager.cpp. Every broker has its own id; + //extern std::mutex oid_mtx; // mutex for increasing order id; defined in ordermanager.cpp + //extern std::mutex orderStatus_mtx; // mutex for changing order status; defined in ordermanager.cpp + + +class OrderManager { + public: + OrderManager(); + ~OrderManager(); // release all the orders + static OrderManager* pinstance_; + static mutex instancelock_; + static OrderManager& instance(); + + // std::atomic_int _count = { 0 }; + std::shared_ptr logger; + int32_t _count = 0; + std::map> orders_; + std::map fills_; // signed filled size + std::map cancels_; // if cancelled + mutex wlock; + void reset(); + + void trackOrder(std::shared_ptr o); // put order under track + void gotOrder(int64_t oid); // order acknowledged + void gotFill(const Fill& fill); + void gotCancel(int64_t oid); + std::shared_ptr retrieveOrderFromServerOrderId(int64_t oid); + std::shared_ptr retrieveOrderFromSourceAndClientOrderId(int32_t source, int64_t oid); + std::shared_ptr retrieveOrderFromOrderNo(const string& ono); + std::shared_ptr retrieveOrderFromAccAndBrokerOrderId(const string& acc, int32_t oid); + std::shared_ptr retrieveOrderFromAccAndLocalNo(const string& acc, const string& ono); + // std::shared_ptr retrieveOrderFromMatchNo(string fno); + vector> retrieveOrder(const string& fullsymbol); + vector> retrieveNonFilledOrderPtr(); + vector> retrieveNonFilledOrderPtr(const string& fullsymbol); + vector retrieveNonFilledOrderId(); + vector retrieveNonFilledOrderId(const string& fullsymbol); + + bool isEmpty(); + bool isTracked(int64_t oid); + bool isCompleted(int64_t oid); // either filled or canceled + bool hasPendingOrders(); // is all orders either filled or canceled? +}; + +} // namespace StarQuant + +#endif // CPPSRC_STARQUANT_TRADE_ORDERMANAGER_H_ diff --git a/cppsrc/StarQuant/Trade/portfoliomanager.cpp b/cppsrc/StarQuant/Trade/portfoliomanager.cpp index 7b0ca80f2..a5d63f377 100644 --- a/cppsrc/StarQuant/Trade/portfoliomanager.cpp +++ b/cppsrc/StarQuant/Trade/portfoliomanager.cpp @@ -1,71 +1,87 @@ +/***************************************************************************** + * Copyright [2019] + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *****************************************************************************/ + #include #include + namespace StarQuant { - PortfolioManager* PortfolioManager::pinstance_ = nullptr; - mutex PortfolioManager::instancelock_; +PortfolioManager* PortfolioManager::pinstance_ = nullptr; +mutex PortfolioManager::instancelock_; - PortfolioManager::~PortfolioManager() - { - // release all the positions - /*for (auto&& p : positions_) { - if (p.second != nullptr) delete p.second; - }*/ - } +PortfolioManager::~PortfolioManager() +{ + // release all the positions + /*for (auto&& p : positions_) { + if (p.second != nullptr) delete p.second; + }*/ +} - PortfolioManager& PortfolioManager::instance() { +PortfolioManager& PortfolioManager::instance() { + if (pinstance_ == nullptr) { + lock_guard g(instancelock_); if (pinstance_ == nullptr) { - lock_guard g(instancelock_); - if (pinstance_ == nullptr) { - pinstance_ = new PortfolioManager(); - } + pinstance_ = new PortfolioManager(); } - return *pinstance_; } + return *pinstance_; +} - PortfolioManager::PortfolioManager() :_count(0) { - rebuild(); - } +PortfolioManager::PortfolioManager() :_count(0) { + rebuild(); +} - void PortfolioManager::reset() { - /*for (auto&& p : positions_) { - if (p.second != nullptr) delete p.second; - }*/ +void PortfolioManager::reset() { + /*for (auto&& p : positions_) { + if (p.second != nullptr) delete p.second; + }*/ - positions_.clear(); - _count = 0; - } + positions_.clear(); + _count = 0; +} - void PortfolioManager::rebuild() { - reset(); - } +void PortfolioManager::rebuild() { + reset(); +} - void PortfolioManager::Add(std::shared_ptr pos) { - if (pos) - positions_[pos->key_] = pos; - } +void PortfolioManager::Add(std::shared_ptr pos) { + if (pos) + positions_[pos->key_] = pos; +} - double PortfolioManager::Adjust(const Fill& fill) { - // auto it = positions_.find(fill.fullSymbol_); - // if (it == positions_.end()) { - // Position pos; - // pos.fullSymbol_ = fill.fullSymbol_; - // pos.size_ = 0; - // pos.avgPrice_ = 0; - // positions_.insert(std::pair(fill.fullSymbol_, pos)); +double PortfolioManager::Adjust(const Fill& fill) { + // auto it = positions_.find(fill.fullSymbol_); + // if (it == positions_.end()) { + // Position pos; + // pos.fullSymbol_ = fill.fullSymbol_; + // pos.size_ = 0; + // pos.avgPrice_ = 0; + // positions_.insert(std::pair(fill.fullSymbol_, pos)); - // } + // } - // return positions_[fill.fullSymbol_].Adjust(fill);TODO: add adjust - return 1.0; - } - - std::shared_ptr PortfolioManager::retrievePosition(const string& key){ - auto it = positions_.find(key); - if (it != positions_.end()) { - return it->second; - } - return nullptr; + // return positions_[fill.fullSymbol_].Adjust(fill);TODO: add adjust + return 1.0; +} + +std::shared_ptr PortfolioManager::retrievePosition(const string& key) { + auto it = positions_.find(key); + if (it != positions_.end()) { + return it->second; } + return nullptr; +} -} \ No newline at end of file +} // namespace StarQuant diff --git a/cppsrc/StarQuant/Trade/portfoliomanager.h b/cppsrc/StarQuant/Trade/portfoliomanager.h index 3e05f4389..c26fd6d81 100644 --- a/cppsrc/StarQuant/Trade/portfoliomanager.h +++ b/cppsrc/StarQuant/Trade/portfoliomanager.h @@ -1,40 +1,57 @@ -#ifndef _StarQuant_Common_PortfolioManager_H_ -#define _StarQuant_Common_PortfolioManager_H_ +/***************************************************************************** + * Copyright [2019] + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *****************************************************************************/ -#include +#ifndef CPPSRC_STARQUANT_TRADE_PORTFOLIOMANAGER_H_ +#define CPPSRC_STARQUANT_TRADE_PORTFOLIOMANAGER_H_ + + +#include #include +#include #include #include #include #include #include -#include - +#include using namespace std; namespace StarQuant { - class PortfolioManager { - public: - PortfolioManager(); - ~PortfolioManager(); - static PortfolioManager* pinstance_; - static mutex instancelock_; - static PortfolioManager& instance(); - //atomic _count = { 0 }; - uint64_t _count = 0; - AccountInfo account_; - map accinfomap_; //accname->acc - map > positions_; // poskey ->pos - double cash_; - - void reset(); - void rebuild(); - - void Add(std::shared_ptr ppos); - double Adjust(const Fill& fill); - std::shared_ptr retrievePosition(const string& key); - }; -} - -#endif // _StarQuant_Common_PortfolioManager_H_ \ No newline at end of file +class PortfolioManager { + public: + PortfolioManager(); + ~PortfolioManager(); + static PortfolioManager* pinstance_; + static mutex instancelock_; + static PortfolioManager& instance(); + // atomic _count = { 0 }; + uint64_t _count = 0; + AccountInfo account_; + map accinfomap_; // accname->acc + map > positions_; // poskey ->pos + double cash_; + + void reset(); + void rebuild(); + + void Add(std::shared_ptr ppos); + double Adjust(const Fill& fill); + std::shared_ptr retrievePosition(const string& key); +}; + +} // namespace StarQuant + +#endif // CPPSRC_STARQUANT_TRADE_PORTFOLIOMANAGER_H_ diff --git a/cppsrc/StarQuant/Trade/riskmanager.cpp b/cppsrc/StarQuant/Trade/riskmanager.cpp index b23e8d31b..83d55a48d 100644 --- a/cppsrc/StarQuant/Trade/riskmanager.cpp +++ b/cppsrc/StarQuant/Trade/riskmanager.cpp @@ -1,77 +1,85 @@ +/***************************************************************************** + * Copyright [2019] + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *****************************************************************************/ + -#include #include #include - +#include +#include namespace StarQuant { - RiskManager* RiskManager::pinstance_ = nullptr; - mutex RiskManager::instancelock_; - - RiskManager::RiskManager() : alive_(false) - { - // set up from config - reset(); - } +RiskManager* RiskManager::pinstance_ = nullptr; +mutex RiskManager::instancelock_; - RiskManager::~RiskManager() - { +RiskManager::RiskManager() : alive_(false) { + // set up from config + reset(); +} - } +RiskManager::~RiskManager() { +} - RiskManager& RiskManager::instance() { +RiskManager& RiskManager::instance() { + if (pinstance_ == nullptr) { + lock_guard g(instancelock_); if (pinstance_ == nullptr) { - lock_guard g(instancelock_); - if (pinstance_ == nullptr) { - pinstance_ = new RiskManager(); - } + pinstance_ = new RiskManager(); } - return *pinstance_; } + return *pinstance_; +} - bool RiskManager::passOrder(std::shared_ptr o){ - if (!alive_) - return true; - totalOrderCount_ += 1; - totalOrderSize_ += abs(o->quantity_); - orderCountPerSec_ += 1; - bool ocok = (totalOrderCount_ <= limitOrderCount_); - bool osok = (totalOrderSize_ <= limitOrderSize_); - bool ospok = (abs(o->quantity_) <= limitSizePerOrder_); - bool ocpsok = (orderCountPerSec_ <= limitOrderCountPerSec_); - if (ocok && osok && ospok && ocpsok) - return true; - fmt:printf("totalcount:{},totalsize{},sizeperorder:{},countpersecond{}", - ocok,osok,ospok,ocpsok - ); - return false; - } - - - void RiskManager::reset() { - alive_ = CConfig::instance().riskcheck; - limitSizePerOrder_ = CConfig::instance().sizeperorderlimit; - limitCashPerOrder_ = CConfig::instance().cashperorderlimit; - limitOrderCount_ = CConfig::instance().ordercountlimit; - limitCash_ = CConfig::instance().cashlimit; - limitOrderSize_ = CConfig::instance().ordersizelimit; - limitOrderCountPerSec_ = CConfig::instance().ordercountperseclimit; - - } - - void RiskManager::resetflow() { - orderCountPerSec_ = 0; +bool RiskManager::passOrder(std::shared_ptr o) { + if (!alive_) + return true; + totalOrderCount_ += 1; + totalOrderSize_ += abs(o->quantity_); + orderCountPerSec_ += 1; + bool ocok = (totalOrderCount_ <= limitOrderCount_); + bool osok = (totalOrderSize_ <= limitOrderSize_); + bool ospok = (abs(o->quantity_) <= limitSizePerOrder_); + bool ocpsok = (orderCountPerSec_ <= limitOrderCountPerSec_); + if (ocok && osok && ospok && ocpsok) + return true; + fmt:printf("totalcount:{},totalsize{},sizeperorder:{},countpersecond{}", + ocok, osok, ospok, ocpsok); + return false; +} - } - void RiskManager::switchday() { - totalOrderCount_ = 0; - totalCash_ = 0.0; - totalOrderSize_ = 0; +void RiskManager::reset() { + alive_ = CConfig::instance().riskcheck; + limitSizePerOrder_ = CConfig::instance().sizeperorderlimit; + limitCashPerOrder_ = CConfig::instance().cashperorderlimit; + limitOrderCount_ = CConfig::instance().ordercountlimit; + limitCash_ = CConfig::instance().cashlimit; + limitOrderSize_ = CConfig::instance().ordersizelimit; + limitOrderCountPerSec_ = CConfig::instance().ordercountperseclimit; +} - } +void RiskManager::resetflow() { + orderCountPerSec_ = 0; +} +void RiskManager::switchday() { + totalOrderCount_ = 0; + totalCash_ = 0.0; + totalOrderSize_ = 0; } +} // namespace StarQuant + diff --git a/cppsrc/StarQuant/Trade/riskmanager.h b/cppsrc/StarQuant/Trade/riskmanager.h index 39c261789..96c172ea9 100644 --- a/cppsrc/StarQuant/Trade/riskmanager.h +++ b/cppsrc/StarQuant/Trade/riskmanager.h @@ -1,55 +1,71 @@ -#ifndef _StarQuant_Trade_RiskManager_H_ -#define _StarQuant_Trade_RiskManager_H_ +/***************************************************************************** + * Copyright [2019] + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *****************************************************************************/ +#ifndef CPPSRC_STARQUANT_TRADE_RISKMANAGER_H_ +#define CPPSRC_STARQUANT_TRADE_RISKMANAGER_H_ + +#include #include #include #include #include #include #include -#include +#include + using namespace std; -namespace StarQuant -{ - class RiskManager { - public: - RiskManager(); - ~RiskManager(); - static RiskManager* pinstance_; - static mutex instancelock_; - static RiskManager& instance(); +namespace StarQuant { +class RiskManager { + public: + RiskManager(); + ~RiskManager(); + static RiskManager* pinstance_; + static mutex instancelock_; + static RiskManager& instance(); - bool alive_; + bool alive_; - // per order limit - int limitSizePerOrder_ = 100; - double limitCashPerOrder_ = 100000; + // per order limit + int32_t limitSizePerOrder_ = 100; + double limitCashPerOrder_ = 100000; - // total limit everyday - int limitOrderCount_ = 100; - int limitCash_ = 100000; - int limitOrderSize_ = 100; + // total limit everyday + int32_t limitOrderCount_ = 100; + int32_t limitCash_ = 100000; + int32_t limitOrderSize_ = 100; - int totalOrderCount_ = 0; - double totalCash_ = 0; - int totalOrderSize_ = 0; + int32_t totalOrderCount_ = 0; + double totalCash_ = 0; + int32_t totalOrderSize_ = 0; - //flow limit - int limitOrderCountPerSec_ = 10; + // flow limit + int32_t limitOrderCountPerSec_ = 10; - int orderCountPerSec_ = 0; + int32_t orderCountPerSec_ = 0; - //check order - bool passOrder(std::shared_ptr); + // check order + bool passOrder(std::shared_ptr); - // reset per day, sec ... - void reset(); - void switchday(); + // reset per day, sec ... + void reset(); + void switchday(); - void resetflow(); + void resetflow(); +}; - }; -} +} // namespace StarQuant -#endif // _StarQuant_Common_RiskManager_H_ \ No newline at end of file +#endif // CPPSRC_STARQUANT_TRADE_RISKMANAGER_H_ diff --git a/quantvs.code-workspace b/quantvs.code-workspace index 3a9b87788..ebb4694fe 100644 --- a/quantvs.code-workspace +++ b/quantvs.code-workspace @@ -69,7 +69,14 @@ "valarray": "cpp", "variant": "cpp", "algorithm": "cpp", - "cinttypes": "cpp" + "cinttypes": "cpp", + "bit": "cpp", + "map": "cpp", + "set": "cpp", + "memory_resource": "cpp", + "regex": "cpp", + "shared_mutex": "cpp", + "string": "cpp" } } } \ No newline at end of file