MarketCTP::MarketCTP(AccountSPtr accountPtr): m_api(nullptr), m_nRequestID(0), m_accountPtr(accountPtr), m_coreListener(nullptr) {
string fileName = string("./log/") + string("marketctp") + string(".log");
this->m_marketLogger = std::make_shared("MarketCTPLogger", std::make_shared(fileName.c_str()));
this->m_marketLogger->set_level(spdlog::level::info);
this->m_marketLogger->flush_on(spdlog::level::info);
MarketCTP::~MarketCTP() {
this->m_accountPtr.reset();
this->m_coreListener = nullptr;
if (this->m_marketLogger)
this->m_marketLogger.reset();
bool MarketCTP::Connect() {
this->m_marketLogger->info("MarketCTP::Connect.");
string marketRuntimeFold = this->m_accountPtr->MarketRuntimeFold()->empty() ? "./runtime_md_ctp/" : this->m_accountPtr->MarketRuntimeFold()->data();
if (!boost::filesystem::exists(marketRuntimeFold) && mkdir(marketRuntimeFold.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH)) {
this->m_marketLogger->error("[MarketCTP::Connect]: runtime_md is not exist, and make runtime_md dir failed.");
this->m_api = CThostFtdcMdApi::CreateFtdcMdApi(marketRuntimeFold.c_str(), false, false);
this->m_api->RegisterSpi(this);
this->m_api->RegisterFront((char *)this->m_accountPtr->MarketFrontAddress()->data());
bool MarketCTP::Disconnect() {
this->m_marketLogger->error("[MarketCTP::Disconnect]: this->m_api is nullptr.");
this->m_api->RegisterSpi(NULL);
void MarketCTP::Subscribe(const shared_ptr> instruments) {
this->m_marketLogger->error("[MarketCTP::Subscribe]: instruments is nullptr.");
this->m_marketLogger->info("[MarketCTP::Subscribe]: instruments.size: {0}.", instruments->size());
this->m_marketLogger->error("[MarketCTP::Subscribe]: this->m_api is nullptr.");
vector<char*> instrumentsFormat;
for (size_t i = 0; i < instruments->size(); i++) {
instrumentsFormat.push_back(const_cast<char*>(instruments->at(i).c_str()));
this->m_api->SubscribeMarketData(instrumentsFormat.data(), instrumentsFormat.size());
instrumentsFormat.clear(), instrumentsFormat.shrink_to_fit();
void MarketCTP::Unsubscribe(const shared_ptr> instruments) {
bool MarketCTP::RegisterListener(ICoreListener* coreListener) {
this->m_marketLogger->error("[MarketCTP::RegisterListener]: coreListener is nullptr.");
this->m_coreListener = coreListener;
void MarketCTP::OnFrontConnected() {
this->m_marketLogger->info("MarketCTP::OnFrontConnected.");
this->m_marketLogger->error("[MarketCTP::OnFrontConnected]: this->m_api is nullptr.");
CThostFtdcReqUserLoginField req = {};
this->m_api->ReqUserLogin(&req, MakeRequestID());
void MarketCTP::OnRspUserLogin(CThostFtdcRspUserLoginField *pRspUserLogin, CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast) {
this->m_marketLogger->info("MarketCTP::OnRspUserLogin.");
if (bIsLast && this->m_coreListener)
this->m_coreListener->OnMarketReady(make_shared(0, ""));
void MarketCTP::OnRtnDepthMarketData(CThostFtdcDepthMarketDataField *pDepthMarketData) {
if (pDepthMarketData && this->m_coreListener) {
TickSPtr tickSPtr = make_shared(pDepthMarketData);
ContractSPtr contractSPtr = this->m_coreListener->GetSysContractSPtr(tickSPtr->InstrumentID()->data());
this->m_marketLogger->error("[MarketCTP::OnRtnDepthMarketData]: contract({0}) not in sys.", tickSPtr->InstrumentID()->c_str());
tickSPtr->setExchangeInstrument(contractSPtr->ExchangeInstrument());
tickSPtr->setPriceTick(contractSPtr->PriceTick());
tickSPtr->setVolumeMultiple(contractSPtr->VolumeMultiple());
if (this->m_coreListener)
this->m_coreListener->HandleTick(tickSPtr);
void MarketCTP::OnFrontDisconnected(int nReason) {
this->m_marketLogger->error("MarketCTP::OnFrontDisconnected(int nReason): {0}.", this->GetDisconnectedReason(nReason));
void MarketCTP::OnRspError(CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast) {
this->m_marketLogger->error("MarketCTP::OnRspError.");
void MarketCTP::OnHeartBeatWarning(int nTimeLapse) {
this->m_marketLogger->info("MarketCTP::OnHeartBeatWarning nTimeLapse: {0}.", nTimeLapse);