262 lines
6.6 KiB
C++
262 lines
6.6 KiB
C++
#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<QSharedPointer<ReplyCodeItem>>& 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);
|
||
} |