#include "FutuApiManager.h" FutuApiManager::FutuApiManager() { m_pQotApi = FTAPI::CreateQotApi(); m_pQotApi->RegisterQotSpi(this); m_pQotApi->RegisterConnSpi(this); m_bQotInitSuc = false; m_pTrdApi = FTAPI::CreateTrdApi(); m_pTrdApi->RegisterTrdSpi(this); m_pTrdApi->RegisterConnSpi(this); m_bTrdInitSuc = false; m_pSem = new Semaphore(0); } FutuApiManager::~FutuApiManager() { UnInitQot(); UnInitTrd(); delete m_pSem; } bool FutuApiManager::InitQot(const char* szIP, uint16_t nPort) { if (!m_bQotInitSuc && m_pQotApi != nullptr) { m_pQotApi->InitConnect(szIP, nPort, false); m_pSem->wait(); } cout << "InitQot, suc = " << m_bQotInitSuc << endl; return m_bQotInitSuc; } void FutuApiManager::UnInitQot() { if (m_pQotApi != nullptr) { m_pQotApi->UnregisterQotSpi(); m_pQotApi->UnregisterConnSpi(); FTAPI::ReleaseQotApi(m_pQotApi); m_pQotApi = nullptr; m_bQotInitSuc = false; } } bool FutuApiManager::InitTrd(const char* szIP, uint16_t nPort, const char* szPwdMD5, Trd_Common::SecurityFirm enFirm) { if (!m_bTrdInitSuc && m_pTrdApi != nullptr) { m_mapRealAccID.clear(); m_mapSimAccID.clear(); m_setAllAccID.clear(); m_pTrdApi->InitConnect(szIP, nPort, false); m_pSem->wait(); if (m_bTrdInitSuc) { //ÏȽâËø½»Ò×(Ä£Äâ½»Òײ»ÐèÒª½âËø) Unlock(szPwdMD5, enFirm); //À­È¡½»Ò×ÕË»§£¬²¢ÇÒ¶©ÔĽ»Ò×ÕË»§µÄÍÆËÍ GetAccListAndSubTradePush(); } } cout << "InitTrd, suc = " << m_bTrdInitSuc << endl; return m_bTrdInitSuc; } void FutuApiManager::UnInitTrd() { if (m_pTrdApi != nullptr) { m_pTrdApi->UnregisterTrdSpi(); m_pTrdApi->UnregisterConnSpi(); FTAPI::ReleaseTrdApi(m_pTrdApi); m_pTrdApi = nullptr; m_bTrdInitSuc = false; } m_mapRealAccID.clear(); m_mapSimAccID.clear(); m_setAllAccID.clear(); } void FutuApiManager::Unlock(const char* szPwdMD5, Trd_Common::SecurityFirm enFirm) { if (m_pTrdApi != nullptr && szPwdMD5 != nullptr && strlen(szPwdMD5) != 0) { Trd_UnlockTrade::Request pbUnlockTrade; Trd_UnlockTrade::C2S* pUnlockTradeC2S = pbUnlockTrade.mutable_c2s(); pUnlockTradeC2S->set_unlock(true); pUnlockTradeC2S->set_pwdmd5(szPwdMD5); pUnlockTradeC2S->set_securityfirm(enFirm); WaitReply(m_pTrdApi->UnlockTrade(pbUnlockTrade)); } } void FutuApiManager::GetAccListAndSubTradePush() { if (m_pTrdApi != nullptr) { Trd_GetAccList::Request pbGetAccList; Trd_GetAccList::C2S* pGetAccListC2S = pbGetAccList.mutable_c2s(); pGetAccListC2S->set_userid(0); WaitReply(m_pTrdApi->GetAccList(pbGetAccList)); if (!m_setAllAccID.empty()) { Trd_SubAccPush::Request pbSubAccPush; Trd_SubAccPush::C2S* pSubAccC2S = pbSubAccPush.mutable_c2s(); for (auto iter = m_setAllAccID.begin(); iter != m_setAllAccID.end(); ++iter) { pSubAccC2S->add_accidlist(*iter); } WaitReply(m_pTrdApi->SubAccPush(pbSubAccPush)); } } } void FutuApiManager::OnInitConnect(FTAPI_Conn* pConn, Futu::i64_t nErrCode, const char* strDesc) { if (pConn != nullptr) { if (pConn == m_pQotApi) { m_bQotInitSuc = (nErrCode == 0); } else if (pConn == m_pTrdApi) { m_bTrdInitSuc = (nErrCode == 0); } PostReply(); } } void FutuApiManager::OnReply_GetAccList(Futu::u32_t nSerialNo, const Trd_GetAccList::Response& stRsp) { if (stRsp.rettype() == Common::RetType_Succeed) { const Trd_GetAccList::S2C& pbS2C = stRsp.s2c(); i32_t nAccCount = pbS2C.acclist_size(); for (int32_t i = 0; i < nAccCount; ++i) { const Trd_Common::TrdAcc& pbTrdAcc = pbS2C.acclist(i); //ÒµÎñÕ˺Šuint64_t nAccID = pbTrdAcc.accid(); //½»Ò×»·¾³ Trd_Common::TrdEnv enTrdEnv = (Trd_Common::TrdEnv)pbTrdAcc.trdenv(); //ÒµÎñÕË»§Ö§³ÖµÄ½»Ò×Êг¡È¨ÏÞ£¬¼´´ËÕË»§Äܽ»Ò×ÄÇЩÊг¡, ¿ÉÓµÓжà¸ö½»Ò×Êг¡È¨ÏÞ£¬Ä¿Ç°½öµ¥¸ö Trd_Common::TrdMarket enTrdMarket = (Trd_Common::TrdMarket)pbTrdAcc.trdmarketauthlist(0); //ÊÕ¼¯½»Ò×·¶Àý±ØÒªÐÅÏ¢ m_setAllAccID.insert(nAccID); vector& vAccID = (enTrdEnv == Trd_Common::TrdEnv_Real) ? m_mapRealAccID[enTrdMarket] : m_mapSimAccID[enTrdMarket]; vAccID.push_back(nAccID); } } else { PrintUTF8(stRsp.retmsg()); } PostReply(); } void FutuApiManager::OnReply_UnlockTrade(Futu::u32_t nSerialNo, const Trd_UnlockTrade::Response& stRsp) { if (stRsp.rettype() != Common::RetType_Succeed) { PrintUTF8(stRsp.retmsg()); } PostReply(); } void FutuApiManager::OnReply_SubAccPush(Futu::u32_t nSerialNo, const Trd_SubAccPush::Response& stRsp) { if (stRsp.rettype() != Common::RetType_Succeed) { PrintUTF8(stRsp.retmsg()); } PostReply(); } void FutuApiManager::WaitReply(int32_t nSerilNo) { //½Ó¿Ú·µ»ØµÄnSerilNoÓë»Øµ÷º¯ÊýOnReply_XXXµÚÒ»¸ö²ÎÊý¶ÔÓ¦ //ÓÃÓÚ¶ÔÓ¦ÇëÇóºÍ»Ø°ü£¬±¾·¶ÀýÒÔͬ²½½Ó¿ÚµÄÐÎʽµ÷Óã¬Ã¿´ÎÖ»·¢ËÍÒ»¸öÇëÇóËùÒÔÐèÒª¼Ç¼¡¢¶Ô±È¸Ã×Ö¶Î if (nSerilNo != 0) { m_pSem->wait(); } } void FutuApiManager::PostReply() { m_pSem->post(); } uint64_t FutuApiManager::GetFirstAccID(Trd_Common::TrdMarket enTrdMarket, Trd_Common::TrdEnv enTrdEnv) { uint64_t nAccID = 0; vector& vAccID = (enTrdEnv == Trd_Common::TrdEnv_Real) ? m_mapRealAccID[enTrdMarket] : m_mapSimAccID[enTrdMarket]; if (!vAccID.empty()) { nAccID = vAccID[0]; } return nAccID; }