量化交易之One Piece篇 - MarketCTP.cc

cpp 复制代码
#include <boost/filesystem.hpp>
#include <sys/stat.h>

#include <onepiece/marketctp/MarketCTP.h>
#include <onepiece/models/TickData.h>
#include <onepiece/models/StatusInfoFieldData.h>
#include <thread>

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<spdlog::logger>("MarketCTPLogger", std::make_shared<spdlog::sinks::basic_file_sink_mt>(fileName.c_str()));

    this->m_marketLogger->set_level(spdlog::level::info);
    this->m_marketLogger->flush_on(spdlog::level::info);
}

MarketCTP::~MarketCTP() {
    this->Disconnect();

    if (this->m_accountPtr)
        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.");
        return false;
    }
    
    this->m_api = CThostFtdcMdApi::CreateFtdcMdApi(marketRuntimeFold.c_str(), false, false);
    this->m_api->RegisterSpi(this);

    // string md_url = "tcp://218.17.194.3:41205"; // 招商期货.
    // string md_url = "tcp://180.168.146.187:10131"; // simnow 全天站点
    this->m_api->RegisterFront((char *)this->m_accountPtr->MarketFrontAddress()->data());
    this->m_api->Init();

    return true;
}

bool MarketCTP::Disconnect() {
    if (!this->m_api) {
        this->m_marketLogger->error("[MarketCTP::Disconnect]: this->m_api is nullptr.");
        return false;
    }

    this->m_api->RegisterSpi(NULL);
    this->m_api->Release();
    this->m_api = nullptr;

    return true;
}

void MarketCTP::Subscribe(const shared_ptr<vector<string>> instruments) {
    if (!instruments) {
        this->m_marketLogger->error("[MarketCTP::Subscribe]: instruments is nullptr.");
        return;
    }

    this->m_marketLogger->info("[MarketCTP::Subscribe]: instruments.size: {0}.", instruments->size());
    if (!this->m_api) {
        this->m_marketLogger->error("[MarketCTP::Subscribe]: this->m_api is nullptr.");
        return;
    }

    // 订阅合约
    // vector<char*> instrumentsFormat = {"rb2310"}; // for test.
    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<vector<string>> instruments) {
    // 退订合约
}


bool MarketCTP::RegisterListener(ICoreListener* coreListener) {
    if (!coreListener) {
        this->m_marketLogger->error("[MarketCTP::RegisterListener]: coreListener is nullptr.");
        return false;
    } 
    
    this->m_coreListener = coreListener;

    return true;
}


void MarketCTP::OnFrontConnected() {
    this->m_marketLogger->info("MarketCTP::OnFrontConnected.");
    if (!this->m_api) {
        this->m_marketLogger->error("[MarketCTP::OnFrontConnected]: this->m_api is nullptr.");
        return;
    }

    // login
    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<StatusInfoFieldData>(0, ""));
}

void MarketCTP::OnRtnDepthMarketData(CThostFtdcDepthMarketDataField *pDepthMarketData) {
    if (pDepthMarketData && this->m_coreListener) {
        TickSPtr tickSPtr = make_shared<TickData>(pDepthMarketData);

        ContractSPtr contractSPtr = this->m_coreListener->GetSysContractSPtr(tickSPtr->InstrumentID()->data());
        if (!contractSPtr) {
            this->m_marketLogger->error("[MarketCTP::OnRtnDepthMarketData]: contract({0}) not in sys.", tickSPtr->InstrumentID()->c_str());
            return;
        }

        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);
}
相关推荐
xiaoye-duck12 分钟前
《算法题讲解指南:动态规划算法--子数组系列》--25.单词拆分,26.环绕字符串中唯一的子字符串
c++·算法·动态规划
Alphapeople20 分钟前
isaac sim和isaac lab的安装
linux·运维·服务器
炘爚27 分钟前
Linux 时间函数、格式化及 printf 相关总结
linux
承渊政道31 分钟前
【优选算法】(实战:栈、队列、优先级队列高频考题通关全解)
数据结构·c++·笔记·学习·算法·leetcode·宽度优先
平常心cyk31 分钟前
Linux快速复习——常用命令
linux
w61001046634 分钟前
CKAD-2026-金丝雀部署
linux·运维·服务器·k8s
.小小陈.38 分钟前
深度拆解 Linux Ext 系列文件系统:从硬件底层到软硬链接全流程
linux·运维·服务器
liulilittle43 分钟前
OPENPPP2 1.0.0.26145 正式版发布:内核态 SYSNAT 性能飞跃 + Windows 平台避坑指南
开发语言·网络·c++·windows·通信·vrrp
AIminminHu1 小时前
OpenGL渲染与几何内核那点事-项目实践理论补充(三-1-(2):当你的CAD代码变得“又大又乱”:从手动编译到CMake,从随性编码到单元测试))
c++·单元测试·cmake·cad·cad开发
xiaoye-duck1 小时前
《算法题讲解指南:动态规划算法--子数组系列》--23.等差数列划分,24.最长湍流子数组
c++·算法·动态规划