用于EagleEye3.0 规则集漏报和误报测试的示例项目,项目收集于github和gitee
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

278 lines
10 KiB

10 months ago
/*****************************************************************************
* 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 <Services/tradingengine.h>
#include <Common/datastruct.h>
#include <Common/config.h>
#include <Common/util.h>
#include <Common/logger.h>
#include <Data/datamanager.h>
#include <Engine/IEngine.h>
#include <Engine/CtpMDEngine.h>
#include <Engine/CtpTDEngine.h>
// #include <Engine/TapMDEngine.h>
// #include <Engine/TapTDEngine.h>
#include <Engine/PaperTDEngine.h>
#include <Trade/ordermanager.h>
#include <Trade/portfoliomanager.h>
#include <Trade/riskmanager.h>
//#include <Services/Strategy/strategyservice.h>
#include <Services/dataservice.h>
#include <pthread.h>
#include <signal.h>
#include <future>
#include <atomic>
#include <fstream>
#include <iostream>
#include <string>
#include <functional>
namespace StarQuant {
extern std::atomic<bool> gShutdown;
extern Except_frame g_except_stack;
extern atomic<uint64_t> MICRO_SERVICE_NUMBER;
void startengine(shared_ptr<IEngine> 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<CMsgqNanomsg>(MSGQ_PROTOCOL::PUB, CConfig::instance().SERVERPUB_URL);
// }
if (CMsgqEMessenger::msgq_send_ == nullptr) {
CMsgqEMessenger::msgq_send_ = std::make_unique<CMsgqNanomsg>(MSGQ_PROTOCOL::PUB, CConfig::instance().SERVERPUB_URL);
msleep(100);
}
if (CMsgqRMessenger::msgq_send_ == nullptr) {
CMsgqRMessenger::msgq_send_ = std::make_unique<CMsgqNanomsg>(MSGQ_PROTOCOL::PUB, CConfig::instance().SERVERSUB_URL);
msleep(100);
}
msg_relay_ = std::make_unique<CMsgqRMessenger>(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) {
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");
}
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);
time(&timer);
localtime_r(&timer, &tm_info);
// at weekend do nothing 0=sunday 6=saturday
if (tm_info.tm_wday == 0) {
continue;
}
// send timer msg to all engine
std::shared_ptr<MsgHeader> pmsg = make_shared<MsgHeader>(DESTINATION_ALL,"0", MSG_TYPE_TIMER);
msg_relay_->send(pmsg);
// flow count reset
RiskManager::instance().resetflow();
// auto reset at 2:35
if (tm_info.tm_hour == 2 && tm_info.tm_min == 35 && tm_info.tm_sec == 0) {
std::shared_ptr<MsgHeader> pmsg = make_shared<MsgHeader>(DESTINATION_ALL,"0", MSG_TYPE_ENGINE_RESET);
msg_relay_->send(pmsg);
}
if (tm_info.tm_wday != 6) {
// auto reset at 16:00
if (tm_info.tm_hour == 16 && tm_info.tm_min == 0 && tm_info.tm_sec == 0) {
std::shared_ptr<MsgHeader> pmsg = make_shared<MsgHeader>(DESTINATION_ALL,"0", MSG_TYPE_ENGINE_RESET);
msg_relay_->send(pmsg);
}
// switch day, at 20:30 everyday, reset td engine, needconfirmation
if (tm_info.tm_hour == 20 && tm_info.tm_min == 30 && tm_info.tm_sec == 0) {
std::shared_ptr<MsgHeader> pmsg = make_shared<MsgHeader>(DESTINATION_ALL,"0", MSG_TYPE_SWITCH_TRADING_DAY);
msg_relay_->send(pmsg);
RiskManager::instance().switchday();
}
// auto connect at 8:45, 13:15, 20:45
if (tm_info.tm_hour == 8 && tm_info.tm_min == 45 && tm_info.tm_sec == 0) {
std::shared_ptr<MsgHeader> pmsg = make_shared<MsgHeader>(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<MsgHeader> pmsg = make_shared<MsgHeader>(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<MsgHeader> pmsg = make_shared<MsgHeader>(DESTINATION_ALL,"0", MSG_TYPE_ENGINE_CONNECT);
msg_relay_->send(pmsg);
}
}
}
// ctrl-c
if (force) {
throw runtime_error("ctrl-c triggered shutdown");
}
return 0;
}
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<IEngine> ctptdengine = make_shared<CtpTDEngine>(iter->first);
threads_.push_back(new std::thread(startengine, ctptdengine));
pengines_.push_back(ctptdengine);
} else if (iter->second.api == "CTP.MD") {
std::shared_ptr<IEngine> ctpmdengine = make_shared<CtpMDEngine>();
pengines_.push_back(ctpmdengine);
threads_.push_back(new std::thread(startengine, ctpmdengine));
} else if (iter->second.api == "PAPER.TD") {
std::shared_ptr<IEngine> papertdengine = make_shared<PaperTDEngine>();
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) {
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(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";
}
}
//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";
}
}
while (!gShutdown) {
msg_relay_->relay();
}
fu1.get();
}
catch (exception& e) {
LOG_INFO(logger, e.what());
}
catch (...) {
LOG_ERROR(logger, "StarQuant terminated in error!");
}
} else {
// g_except_stack.clear();
signal(SIGSEGV, SIG_IGN);
LOG_ERROR(logger, "StarQuant terminated by SEGSEGV!");
exit(0);
}
// for (const auto& e : pengines_) {
// e->stop();
// }
return 0;
}
bool tradingengine::live() const {
return gShutdown == true;
}
} // namespace StarQuant