#include "stdafx.h" #include "FTInterface.h" CFTInterface::CFTInterface() { FTAPI::Init(); // 初始化 Futu API 环境 bConnected = false; m_nPagenumber = 0; m_pQotApi = FTAPI::CreateQotApi(); m_pQotApi->RegisterQotSpi(this); m_pQotApi->RegisterConnSpi(this); } CFTInterface::~CFTInterface() { if (m_pQotApi != nullptr) { m_pQotApi->UnregisterQotSpi(); m_pQotApi->UnregisterConnSpi(); FTAPI::ReleaseQotApi(m_pQotApi); m_pQotApi = nullptr; } } /* 初始化连接返回之后,才能进行数据获取相关操作 */ bool CFTInterface::InitConn() { return m_pQotApi->InitConnect("127.0.0.1", 11111, false); } void CFTInterface::DisConn() { } void CFTInterface::getSecurityStaticInfo(string strCode) { Qot_GetStaticInfo::Request req; Qot_GetStaticInfo::C2S *c2s = req.mutable_c2s(); auto secList = c2s->mutable_securitylist(); Qot_Common::Security *sec = secList->Add(); sec->set_code(strCode); //sec->set_code("00700"); sec->set_market(Qot_Common::QotMarket::QotMarket_HK_Security); m_ReplySerialNo = m_pQotApi->GetStaticInfo(req); } void CFTInterface::getIpoListInfo() { // 组包 Qot_GetIpoList::Request req; Qot_GetIpoList::C2S *c2s = req.mutable_c2s(); c2s->set_market(1); m_GetIpoListSerialNo = m_pQotApi->GetIpoList(req); cout << "Request GetIpoList SerialNo: " << m_GetIpoListSerialNo << endl; } void CFTInterface::getPlateSetSerial() { // 组包 Qot_GetPlateSet::Request req; Qot_GetPlateSet::C2S *c2s = req.mutable_c2s(); c2s->set_market(1); c2s->set_platesettype(3); m_GetPlateSetSerialNo = m_pQotApi->GetPlateSet(req); cout << "Request GetPlateSet SerialNo: " << m_GetPlateSetSerialNo << endl; } /////////////////////////////////////////////////////// ////////// Futu 回调函数 ///////////////////////////// void CFTInterface::OnInitConnect(FTAPI_Conn * pConn, Futu::i64_t nErrCode, const char * strDesc) { //qDebug() << "connect"; if(nErrCode == 0 && string(strDesc) == "Succeed!") bConnected = true; } void CFTInterface::OnReply_GetStaticInfo(Futu::u32_t nSerialNo, const Qot_GetStaticInfo::Response &stRsp) { if (nSerialNo == m_ReplySerialNo) { cout << "OnReply_GetStaticInfo SerialNo: " << nSerialNo << endl; // print response // ProtoBufToBodyData and UTF8ToLocal refer to tool.h in Samples string resp_str; ProtoBufToBodyData(stRsp, resp_str); emit SecurityStaticInfo(QString(resp_str.c_str())); } } // 获取板块列表 void CFTInterface::OnReply_GetPlateSet(Futu::u32_t nSerialNo, const Qot_GetPlateSet::Response & stRsp) { //if (nSerialNo == m_GetPlateSetSerialNo) //{ // string resp_str; // ProtoBufToBodyData_Ex(stRsp, resp_str); // emit PlateSetSerial(QString(resp_str.c_str())); //} if (nSerialNo != m_GetPlateSetSerialNo) return; std::string bin_data; ProtoBufToBodyData_Binary(stRsp, bin_data); //FastSerializeProto(stRsp, bin_data); emit PlateSetSerial(QByteArray(bin_data.data(), bin_data.size())); } // 获取历史 K 线 void CFTInterface::getRequestHistoryKL() { // 组包 Qot_RequestHistoryKL::Request req; Qot_RequestHistoryKL::C2S *c2s = req.mutable_c2s(); c2s->set_rehabtype(1); c2s->set_kltype(Qot_Common::KLType::KLType_1Min); Qot_Common::Security *sec = c2s->mutable_security(); sec->set_code("00700"); sec->set_market(Qot_Common::QotMarket::QotMarket_HK_Security); c2s->set_begintime("2021-06-07"); c2s->set_endtime("2021-07-01"); m_RequestHistoryKLSerialNo = m_pQotApi->RequestHistoryKL(req); } void CFTInterface::OnReply_RequestHistoryKL(Futu::u32_t nSerialNo, const Qot_RequestHistoryKL::Response &stRsp) { if (nSerialNo == m_RequestHistoryKLSerialNo) { cout << "OnReply_RequestHistoryKL SerialNo: " << nSerialNo << endl; // 解析内部结构打印出来 // ProtoBufToBodyData和UTF8ToLocal函数的定义参见Sample中的tool.h文件 string resp_str; ProtoBufToBodyData(stRsp, resp_str); qDebug() << QString(resp_str.c_str()); } } /** * @brief 条件选股 * @praram nSerialNo 包序列号 * @param stRsp 回包,具体字段请参考Qot_StockFilter.proto协议 */ void CFTInterface::OnReply_StockFilter(Futu::u32_t nSerialNo, const Qot_StockFilter::Response &stRsp) { if (nSerialNo != m_StockFilterSerialNo) return; string resp_str; FastSerializeProto(stRsp, resp_str); // 反序列化 Qot_StockFilter::Response response; if (!response.ParseFromArray(resp_str.data(), resp_str.size())) { std::cerr << "Failed to parse protobuf data." << std::endl; return; } // 检查返回状态 if (response.rettype() != 0) { // 假设 0 表示成功 qDebug() << QString(response.retmsg().data()); return; } // 检查是否存在 s2c 字段 if (!response.has_s2c()) { std::cout << "No data in response." << std::endl; return; } const Qot_StockFilter::S2C& s2c = response.s2c(); bool blastPage = s2c.lastpage(); int nAllcount = s2c.allcount(); if (!blastPage) { Sleep(3000); // 每 3 秒请求一次 m_nPagenumber += 100; getAllStock_HK(); qDebug() << "Startpage" << m_nPagenumber; } else { qDebug() << "Over!"; } //emit AllStock_HK(QByteArray(resp_str.data(), resp_str.size())); } void CFTInterface::getAllStock_HK() { // 组包 Qot_StockFilter::Request req; Qot_StockFilter::C2S *c2s = req.mutable_c2s(); c2s->set_begin(m_nPagenumber); c2s->set_num(100); c2s->set_market(1); m_StockFilterSerialNo = m_pQotApi->StockFilter(req); } // 后面需要需改一下流程,保存一个历史订阅和新增订阅 void CFTInterface::subStock() { Qot_Sub::Request req; Qot_Sub::C2S *c2s = req.mutable_c2s(); auto secList = c2s->mutable_securitylist(); Qot_Common::Security *sec = secList->Add(); sec->set_market(Qot_Common::QotMarket::QotMarket_HK_Security); c2s->add_subtypelist(Qot_Common::SubType::SubType_OrderBook); c2s->set_isregorunregpush(true); c2s->set_issuborunsub(true); c2s->set_issuborderbookdetail(true); for (const auto &value : m_codeList) { sec->set_code(value->stockCode.toStdString()); m_SubSerialNo = m_pQotApi->Sub(req); } } void CFTInterface::setReplyList(QList>& replyCodes) { m_codeList = replyCodes; } void CFTInterface::OnReply_Sub(Futu::u32_t nSerialNo, const Qot_Sub::Response &stRsp) { if (nSerialNo == m_SubSerialNo) { cout << "OnReply_Sub SerialNo: " << nSerialNo << endl; if (stRsp.rettype() != Common::RetType::RetType_Succeed) { cout << "Sub Failed" << endl; return; } } } void CFTInterface::OnReply_GetBasicQot(Futu::u32_t nSerialNo, const Qot_GetBasicQot::Response &stRsp) { if (nSerialNo == m_GetBasicQotSerialNo) { cout << "OnReply_GetBasicQot SerialNo: " << nSerialNo << endl; // 解析内部结构打印出来 // ProtoBufToBodyData和UTF8ToLocal函数的定义参见Sample中的tool.h文件 string resp_str; ProtoBufToBodyData(stRsp, resp_str); qDebug() << QString(resp_str.c_str()) << endl; } } void CFTInterface::OnPush_UpdateOrderBook(const Qot_UpdateOrderBook::Response &stRsp) { processor.processOrderBook(stRsp); }