void DbService::insertBar(const BfBarData& bfItem) { BfDebug(__FUNCTION__); g_sm->checkCurrentOn(ServiceMgr::DB); if (bfItem.symbol().length() == 0 || bfItem.exchange().length() == 0 || bfItem.actiondate().length() == 0 || bfItem.bartime().length() == 0 || bfItem.period() == PERIOD_UNKNOWN) { BfDebug("invalid bar,ignore"); return; } leveldb::WriteOptions options; leveldb::WriteBatch batch; std::string key, val; if (1) { // key: bar-symbol-exchange-period-actiondate-bartime key = QString().sprintf("bar-%s-%s-%s-%s-%s", bfItem.symbol().c_str(), bfItem.exchange().c_str(), qPrintable(ProtoUtils::formatPeriod(bfItem.period())), bfItem.actiondate().c_str(), bfItem.bartime().c_str()).toStdString(); bool ok = bfItem.SerializeToString(&val); if (!ok) { qFatal("SerializeToString fail"); } batch.Put(key, val); } db_->Write(options, &batch); }
virtual ::grpc::Status GetContract(::grpc::ServerContext* context, const BfGetContractReq* request, ::grpc::ServerWriter<BfContractData>* writer) override { BfDebug("%s on thread:%d", __FUNCTION__, ::GetCurrentThreadId()); QString clientId = getClientId(context); BfDebug("clientId=%s", qPrintable(clientId)); if (request->symbol() == "*" && request->exchange() == "*") { QStringList ids = g_sm->gatewayMgr()->getIds(); //g_sm->gatewayMgr()->getIdsAll(); for (int index = 0; index < ids.length(); index++) { QString symbol = ids.at(index); void* contract = g_sm->gatewayMgr()->getContract(symbol); BfContractData bfItem; CtpUtils::translateContract(contract, &bfItem); writer->Write(bfItem); } } else { QString symbol = request->symbol().c_str(); void* contract = g_sm->gatewayMgr()->getContract(symbol); BfContractData bfItem; CtpUtils::translateContract(contract, &bfItem); writer->Write(bfItem); } return grpc::Status::OK; }
void DbService::dbOpen() { BfDebug(__FUNCTION__); g_sm->checkCurrentOn(ServiceMgr::DB); if (db_) { BfDebug("opened already"); return; } QString path = Profile::dbPath(); mkDir(path); leveldb::Options options; options.create_if_missing = true; options.error_if_exists = false; options.compression = leveldb::kNoCompression; options.paranoid_checks = false; leveldb::DB* db; leveldb::Status status = leveldb::DB::Open(options, path.toStdString(), &db); if (!status.ok()) { qFatal("leveldb::DB::Open fail"); } db_ = db; }
void MdSm::subscrible(QStringList ids, unsigned int delayTick, QString robotId) { BfDebug(__FUNCTION__); std::function<int(int, QString)> fn = [=](int reqId, QString robotId) -> int { (void)reqId; QList<std::string> std_ids; char** cids = new char*[ids.length()]; for (int i = 0; i < ids.length(); i++) { std_ids.append(ids.at(i).toStdString()); cids[i] = (char*)std_ids.at(i).c_str(); } int result = mdapi_->SubscribeMarketData(cids, ids.length()); delete[] cids; BfDebug("CmdMdSubscrible,result=%d", result); return result; }; CtpCmd* cmd = new CtpCmd; cmd->fn = fn; cmd->delayTick = delayTick; cmd->robotId = robotId; g_sm->ctpMgr()->runCmd(cmd); }
virtual ::grpc::Status QueryOrders(::grpc::ServerContext* context, const BfVoid* request, BfVoid* response) override { BfDebug("%s on thread:%d", __FUNCTION__, ::GetCurrentThreadId()); QString clientId = getClientId(context); BfDebug("clientId=%s", qPrintable(clientId)); QMetaObject::invokeMethod(g_sm->gatewayMgr(), "queryOrders", Qt::QueuedConnection); return grpc::Status::OK; }
virtual ::grpc::Status DisconnectPush(::grpc::ServerContext* context, const BfVoid* request, BfVoid* response) override { BfDebug("%s on thread:%d", __FUNCTION__, ::GetCurrentThreadId()); QString clientId = getClientId(context); BfDebug("(%s)->Disconnect", qPrintable(clientId)); // NOTE(hege):关闭stream QMetaObject::invokeMethod(g_sm->pushService(), "disconnectClient", Qt::QueuedConnection, Q_ARG(QString, clientId)); return grpc::Status::OK; }
void DbService::dbClose() { BfDebug(__FUNCTION__); g_sm->checkCurrentOn(ServiceMgr::DB); if (db_ == nullptr) { BfDebug("not open yet"); return; } delete db_; db_ = nullptr; }
virtual ::grpc::Status SendOrder(::grpc::ServerContext* context, const BfSendOrderReq* request, BfSendOrderResp* response) override { BfDebug("%s on thread:%d", __FUNCTION__, ::GetCurrentThreadId()); QString clientId = getClientId(context); BfDebug("clientId=%s", qPrintable(clientId)); QString bfOrderId = g_sm->gatewayMgr()->genOrderId(); response->set_bforderid(bfOrderId.toStdString()); QMetaObject::invokeMethod(g_sm->gatewayMgr(), "sendOrderWithId", Qt::QueuedConnection, Q_ARG(QString, bfOrderId), Q_ARG(BfSendOrderReq, *request)); return grpc::Status::OK; }
void DbService::insertContract(const BfContractData& bfItem) { BfDebug(__FUNCTION__); g_sm->checkCurrentOn(ServiceMgr::DB); if (bfItem.symbol().length() == 0 || bfItem.exchange().length() == 0 || bfItem.name().length() == 0) { BfDebug("invalid contract,ignore"); return; } leveldb::WriteOptions options; leveldb::WriteBatch batch; std::string key, val; if (1) { // key: contract-symbol-exchange key = QString().sprintf("contract-%s-%s", bfItem.symbol().c_str(), bfItem.exchange().c_str()).toStdString(); bool ok = bfItem.SerializeToString(&val); if (!ok) { qFatal("SerializeToString fail"); } batch.Put(key, val); // key: tick-symbol-exchange+ // key: tick-symbol-exchange= BfTickData bfNullTick; key = QString().sprintf("tick-%s-%s+", bfItem.symbol().c_str(), bfItem.exchange().c_str()).toStdString(); val = bfNullTick.SerializeAsString(); batch.Put(key, val); key = QString().sprintf("tick-%s-%s=", bfItem.symbol().c_str(), bfItem.exchange().c_str()).toStdString(); val = bfNullTick.SerializeAsString(); batch.Put(key, val); // key: bar-symbol-exchange-period+ // key: bar-symbol-exchange-period= BfBarData bfNullBar; for (int i = BfBarPeriod_MIN; i <= BfBarPeriod_MAX; i++) { key = QString().sprintf("bar-%s-%s-%s+", bfItem.symbol().c_str(), bfItem.exchange().c_str(), qPrintable(ProtoUtils::formatPeriod((BfBarPeriod)i))).toStdString(); val = bfNullBar.SerializeAsString(); batch.Put(key, val); key = QString().sprintf("bar-%s-%s-%s=", bfItem.symbol().c_str(), bfItem.exchange().c_str(), qPrintable(ProtoUtils::formatPeriod((BfBarPeriod)i))).toStdString(); val = bfNullBar.SerializeAsString(); batch.Put(key, val); } } db_->Write(options, &batch); }
void GatewayMgr::start(QString password) { g_sm->checkCurrentOn(ServiceMgr::LOGIC); // check if (mdsm_ != nullptr || tdsm_ != nullptr) { BfDebug("mdsm_!= nullptr || tdsm_ != nullptr"); return; } // init mdsm password_ = password; if (!initMdSm()) { return; } if (!initTdSm()) { delete mdsm_; mdsm_ = nullptr; return; } startMdSm(); startTdSm(); return; }
void CtpMgr::onRunCmdInterval() { g_sm->checkCurrentOn(ServiceMgr::LOGIC); if (cmds_.length() == 0) { return; } CtpCmd* cmd = cmds_.head(); // 检查时间是否到了= quint32 curTick = ::GetTickCount(); if (curTick < cmd->expires) { return; } // 流控了就一秒后重试= if (cmd->fn(++reqId_, cmd->robotId) == -3) { cmd->expires = curTick + 1000; BfDebug("sendcmd toofast,reqId=%d", reqId_); return; } // 消费掉这个cmd= cmds_.dequeue(); delete cmd; }
void DbService::insertTick(const BfTickData& bfItem) { //BfDebug(__FUNCTION__); g_sm->checkCurrentOn(ServiceMgr::DB); if (bfItem.symbol().length() == 0 || bfItem.exchange().length() == 0 || bfItem.actiondate().length() == 0 || bfItem.ticktime().length() == 0) { BfDebug("invalid tick,ignore"); return; } leveldb::WriteOptions options; leveldb::WriteBatch batch; std::string key, val; if (1) { // key: tick-symbol-exchange-actiondate-ticktime key = QString().sprintf("tick-%s-%s-%s-%s", bfItem.symbol().c_str(), bfItem.exchange().c_str(), bfItem.actiondate().c_str(), bfItem.ticktime().c_str()).toStdString(); bool ok = bfItem.SerializeToString(&val); if (!ok) { qFatal("SerializeToString fail"); } batch.Put(key, val); } db_->Write(options, &batch); }
leveldb::DB* DbService::getDb() { BfDebug(__FUNCTION__); if (!db_) { qFatal("db not open yet"); return nullptr; } return db_; }
void GatewayMgr::onTdSmStateChanged(int state) { g_sm->checkCurrentOn(ServiceMgr::LOGIC); if (!tdsm_) { BfDebug("tdsm freed,ingore onTdSmStateChanged:%d", state); return; } if (state == TDSM_CONNECTED) { tdsm_logined_ = false; if (autoLoginTd_) { tdsm_->login(1000); } else { tdsm_->stop(); } } if (state == TDSM_DISCONNECTED) { resetCmds(); tdsm_logined_ = false; if (!autoLoginTd_) { tdsm_->stop(); } else { BfInfo("waiting for tdapi auto-reconnect......"); } } if (state == TDSM_LOGINED) { tdsm_logined_ = true; tryStartSubscrible(); } if (state == TDSM_LOGINFAIL) { if (autoLoginTd_) { BfInfo("tdsm login fail,try again 1 minute later"); tdsm_->login(60 * 1000); } else { tdsm_->stop(); } } if (state == TDSM_LOGOUTED) { tdsm_logined_ = false; tdsm_->stop(); } if (state == TDSM_LOGOUTFAIL) { tdsm_logined_ = false; tdsm_->stop(); } if (state == TDSM_STOPPED) { resetCmds(); tdsm_logined_ = false; delete tdsm_; tdsm_ = nullptr; tdsm_logined_ = false; } }
void DbService::shutdown() { BfDebug(__FUNCTION__); g_sm->checkCurrentOn(ServiceMgr::DB); // dbClose dbClose(); // free env delete leveldb::BytewiseComparator(); delete leveldb::Env::Default(); }
void CtpMgr::onGotInstruments(QStringList ids, QStringList idsAll) { BfDebug(__FUNCTION__); g_sm->checkCurrentOn(ServiceMgr::LOGIC); // mdapi开始订阅= mdsm_->subscrible(ids, 0, ""); // tdapi开始确认账单= tdsm_->reqSettlementInfoConfirm(0, ""); }
void GatewayMgr::resetCmds() { g_sm->checkCurrentOn(ServiceMgr::LOGIC); if (cmds_.length()) { BfDebug(__FUNCTION__); for (auto cmd : cmds_) { delete cmd; } cmds_.clear(); } }
virtual ::grpc::Status ConnectPush(::grpc::ServerContext* context, const BfConnectPushReq* request, ::grpc::ServerWriter< ::google::protobuf::Any>* writer) override { BfDebug("%s on thread:%d", __FUNCTION__, ::GetCurrentThreadId()); QString clientId = request->clientid().c_str(); BfDebug("(%s)->Connect", qPrintable(clientId)); auto queue = new SafeQueue<google::protobuf::Any>; QMetaObject::invokeMethod(g_sm->pushService(), "connectClient", Qt::QueuedConnection, Q_ARG(QString, gatewayId_), Q_ARG(BfConnectPushReq, *request), Q_ARG(void*, (void*)queue)); while (auto data = queue->dequeue()) { // NOTE(hege):客户端异常导致stream关闭 bool ok = writer->Write(*data); delete data; if (!ok) { BfDebug("(%s)-->stream closed!", qPrintable(clientId)); QMetaObject::invokeMethod(g_sm->pushService(), "disconnectClient", Qt::QueuedConnection, Q_ARG(QString, clientId)); break; } } BfDebug("(%s)->Connect exit!", qPrintable(clientId)); return grpc::Status::OK; }
void MdSm::login(unsigned int delayTick, QString robotId) { BfDebug(__FUNCTION__); std::function<int(int, QString)> fn = [=](int reqId, QString robotId) -> int { CThostFtdcReqUserLoginField req; memset(&req, 0, sizeof(req)); strncpy(req.BrokerID, brokerId_.toStdString().c_str(), sizeof(req.BrokerID) - 1); strncpy(req.UserID, userId_.toStdString().c_str(), sizeof(req.UserID) - 1); strncpy(req.Password, password_.toStdString().c_str(), sizeof(req.Password) - 1); int result = mdapi_->ReqUserLogin(&req, reqId); BfDebug("CmdMdLogin,reqId=%d,result=%d", reqId, result); if (result == 0) { emit g_sm->ctpMgr()->requestSent(reqId, robotId); } return result; }; CtpCmd* cmd = new CtpCmd; cmd->fn = fn; cmd->delayTick = delayTick; cmd->robotId = robotId; g_sm->ctpMgr()->runCmd(cmd); }
void DbService::init() { BfDebug(__FUNCTION__); g_sm->checkCurrentOn(ServiceMgr::DB); // init env leveldb::Env::Default(); leveldb::BytewiseComparator(); // dbOpen dbOpen(); // dbInit dbInit(); }
void DbService::init() { BfDebug(__FUNCTION__); g_sm->checkCurrentOn(ServiceMgr::DB); // init env leveldb::Env::Default(); leveldb::BytewiseComparator(); // dbOpen dbOpen(); // ctpmgr QObject::connect(g_sm->ctpMgr(), &CtpMgr::gotTick, this, &DbService::onGotTick); QObject::connect(g_sm->ctpMgr(), &CtpMgr::gotContracts, this, &DbService::onGotContracts); QObject::connect(g_sm->ctpMgr(), &CtpMgr::tradeWillBegin, this, &DbService::onTradeWillBegin); }
void MdSm::start() { BfDebug(__FUNCTION__); if (mdapi_ != nullptr) { qFatal("mdapi_!=nullptr"); return; } QDir dir; dir.mkpath(flowPathMd_); mdapi_ = CThostFtdcMdApi::CreateFtdcMdApi(flowPathMd_.toStdString().c_str()); mdspi_ = new MdSmSpi(this); mdapi_->RegisterSpi(mdspi_); mdapi_->RegisterFront((char*)qPrintable(frontMd_)); mdapi_->Init(); }
void MdSm::stop() { BfDebug(__FUNCTION__); if (mdapi_ == nullptr) { qFatal("mdapi_==nullptr"); return; } this->mdapi_->RegisterSpi(nullptr); this->mdapi_->Release(); this->mdapi_ = nullptr; delete this->mdspi_; this->mdspi_ = nullptr; emit this->statusChanged(MDSM_STOPPED); }
void CtpMgr::runCmd(CtpCmd* cmd) { g_sm->checkCurrentOn(ServiceMgr::LOGIC); if (cmd->delayTick == 0) { int result = cmd->fn(++reqId_, cmd->robotId); if (result == -3) { BfDebug("sendcmd toofast,reqId=%d", reqId_); cmd->expires = ::GetTickCount() + 1000; cmds_.append(cmd); } else { delete cmd; } } else { cmd->expires = ::GetTickCount() + cmd->delayTick; cmds_.append(cmd); } }
void GatewayMgr::onGotContracts(QStringList symbolsMy, QStringList symbolsAll) { BfDebug(__FUNCTION__); g_sm->checkCurrentOn(ServiceMgr::LOGIC); // 保存ids,便于枚举= symbols_my_ = symbolsMy; symbols_my_.sort(); symbols_all_ = symbolsAll; symbols_all_.sort(); // mdapi开始订阅= mdsm_->subscrible(symbolsMy, 0); // tdapi开始确认账单= tdsm_->reqSettlementInfoConfirm(0); }
void DbService::getTick(const BfGetTickReq* request, ::grpc::ServerWriter<BfTickData>* writer) { g_sm->checkCurrentOn(ServiceMgr::EXTERNAL); if (request->symbol().length() == 0 || request->exchange().length() == 0 || request->todate().length() == 0 || request->totime().length() == 0) { BfDebug("invalid parm,ignore"); return; } leveldb::ReadOptions options; options.fill_cache = false; leveldb::Iterator* it = db_->NewIterator(options); if (!it) { qFatal("NewIterator == nullptr"); } // key: tick-symbol-exchange-actiondate-ticktime std::string key = QString().sprintf("tick-%s-%s-%s-%s", request->symbol().c_str(), request->exchange().c_str(), request->todate().c_str(), request->totime().c_str()).toStdString(); it->Seek(leveldb::Slice(key)); int count = 0; for (; it->Valid() && count < request->count(); it->Prev()) { //遇到了前后两个结束item const char* buf = it->value().data(); int len = it->value().size(); BfTickData bfItem; if (!bfItem.ParseFromArray(buf, len)) { qFatal("ParseFromArray error"); break; } if (bfItem.symbol().length() == 0) { std::string lastestKey = QString().sprintf("tick-%s-%s=", request->symbol().c_str(), request->exchange().c_str()).toStdString(); std::string itKey = it->key().ToString(); if (itKey == lastestKey) { continue; } else { break; } } count++; writer->Write(bfItem); } delete it; }
void CtpMgr::onMdSmStateChanged(int state) { g_sm->checkCurrentOn(ServiceMgr::LOGIC); if (!mdsm_) { BfDebug("mdsm freed,ingore onMdSmStateChanged:%d", state); return; } if (state == MDSM_CONNECTED) { mdsm_logined_ = false; if (autoLoginMd_) { mdsm_->login(1000, ""); } else { mdsm_->stop(); } } if (state == MDSM_DISCONNECTED) { mdsm_logined_ = false; if (!autoLoginMd_) { mdsm_->stop(); }else{ BfInfo("waiting for mdapi auto-reconnect......"); } } if (state == MDSM_LOGINED) { mdsm_logined_ = true; tryStartSubscrible(); } if (state == MDSM_LOGINFAIL) { if (autoLoginMd_) { BfInfo("mdsm login fail,try again 1 minute later"); mdsm_->login(60 * 1000, ""); } else { mdsm_->stop(); } } if (state == MDSM_STOPPED) { mdsm_logined_ = false; delete mdsm_; mdsm_ = nullptr; mdsm_logined_ = false; } }
void GatewayMgr::stop() { g_sm->checkCurrentOn(ServiceMgr::LOGIC); // check if (mdsm_ == nullptr && tdsm_ == nullptr) { BfDebug("mdsm_ == nullptr && tdsm_ == nullptr"); return; } if (mdsm_) { autoLoginMd_ = false; mdsm_->stop(); } if (tdsm_) { autoLoginTd_ = false; if (tdsm_logined_) { //先logout,然后自动退出= tdsm_->logout(0); } else { tdsm_->stop(); } } }
void MainWindow::onTradeWillBegin() { BfDebug(__FUNCTION__); }
void DbService::getContract(const BfGetContractReq* request, ::grpc::ServerWriter<BfContractData>* writer) { g_sm->checkCurrentOn(ServiceMgr::EXTERNAL); if (request->symbol().length() == 0 || request->exchange().length() == 0) { BfDebug("invalid parm,ignore"); return; } if (request->symbol() == "*" && request->exchange() == "*") { leveldb::DB* db = db_; leveldb::ReadOptions options; options.fill_cache = false; leveldb::Iterator* it = db->NewIterator(options); if (!it) { qFatal("NewIterator == nullptr"); } //第一个是contract+ //最后一个是contract= QString key = QStringLiteral("contract+"); it->Seek(leveldb::Slice(key.toStdString())); if (it->Valid()) { it->Next(); } for (; it->Valid(); it->Next()) { //遇到了前后两个结束item const char* buf = it->value().data(); int len = it->value().size(); BfContractData bfContract; //std::string stdKey = it->key().ToString(); //std::string stdVal = it->value().ToString(); //if(!bfContract.ParseFromString(stdVal)){ if (!bfContract.ParseFromArray(buf, len)) { qFatal("ParseFromArray fail"); break; } if (bfContract.symbol().length() == 0) { break; } writer->Write(bfContract); } delete it; } else { leveldb::ReadOptions options; std::string val; // key: contract-symbol-exchange std::string key = QString().sprintf("contract-%s-%s", request->symbol().c_str(), request->exchange().c_str()).toStdString(); leveldb::Status status = db_->Get(options, key, &val); if (status.ok()) { BfContractData bfItem; if (!bfItem.ParseFromString(val)) { qFatal("ParseFromString error"); return; } if (bfItem.symbol().length() == 0) { return; } writer->Write(bfItem); } } }