量化交易之One Piece篇 - 生成主力合约文件(.cc文件)

#include<onepiece/configmakercore/ConfigMakerCore.h>
#include <boost/filesystem.hpp>
#include <rapidjson/document.h>
#include <fstream>
#include <sstream>
#include <boost/regex.hpp>
#include <rapidjson/writer.h>
#include <rapidjson/stringbuffer.h>

using namespace rapidjson;

ConfigMakerCore::ConfigMakerCore(string marketDepthDataConfigPath): m_marketDepthDataConfigPath(make_shared<string>(marketDepthDataConfigPath)), m_marketDepthDataCSVPath(nullptr) {
    string fileName = string("./log/") + string("configmakercore") + string(".log");
    this->m_coreLogger = make_shared<spdlog::logger>("ConfigMakerCoreLogger", make_shared<spdlog::sinks::basic_file_sink_mt>(fileName.c_str()));
    this->m_coreLogger->set_level(spdlog::level::info);
    this->m_coreLogger->flush_on(spdlog::level::info);
    
    this->m_sourceTradingTimeConfigPath = make_shared<string>("./config/source_trading_time.json");
}


bool ConfigMakerCore::Check() {
    if (!boost::filesystem::exists(this->m_sourceTradingTimeConfigPath->data())) {
        this->m_coreLogger->error("[ConfigMakerCore Check]: source trading time config path: {0} is not exist.", this->m_sourceTradingTimeConfigPath->data());
        cout << "[ConfigMakerCore Check]: source trading time config path: " << this->m_sourceTradingTimeConfigPath->data() << " is not exist." << endl;
        return false;
    }

    if (!this->InitSourceTradingTimeMap()) return false;

    if (!boost::filesystem::exists(this->m_marketDepthDataConfigPath->data())) {
        this->m_coreLogger->error("[ConfigMakerCore Check]: market depth data config path: {0} is not exist.", this->m_marketDepthDataConfigPath->data());
        cout << "[ConfigMakerCore Check]: market depth data config path: " << this->m_marketDepthDataConfigPath->data() << " is not exist." << endl;
        return false;
    }

    ifstream marketDepthDataIfs((*this->m_marketDepthDataConfigPath).c_str());
    string marketDepthDataContent((istreambuf_iterator<char>(marketDepthDataIfs)), (istreambuf_iterator<char>()));
    marketDepthDataIfs.close();

    Document marketDepthDataDocument;
    marketDepthDataDocument.Parse(marketDepthDataContent.c_str());
    this->m_csvName = (marketDepthDataDocument.HasMember("csv_name") && marketDepthDataDocument["csv_name"].IsString()) ? make_unique<string>(marketDepthDataDocument["csv_name"].GetString()) : nullptr;
    if (!this->m_csvName) {
        this->m_coreLogger->error("market depth data config file: {0} has no csv_name key.", this->m_marketDepthDataConfigPath->data());
        cout << "[ConfigMakerCore Check]: market depth data config file: " << this->m_marketDepthDataConfigPath->data() << " has no csv_name key." << endl;
        return false;
    }
    
    this->m_marketDepthDataCSVPath = make_shared<string>(("../datacore/ret_data/" + (*this->m_csvName)));
    if (!boost::filesystem::exists(this->m_marketDepthDataCSVPath->data())) {
        this->m_coreLogger->error("[ConfigMakerCore Check]: market depth data csv file: {0} is not exist.", this->m_marketDepthDataCSVPath->data());
        cout << "[ConfigMakerCore Check]: market depth data csv file: " << this->m_marketDepthDataCSVPath->data() << " is not exist." << endl;
        return false;
    }

    return true;
}


bool ConfigMakerCore::InitSourceTradingTimeMap() {
    ifstream sourceTradingTimeIfs((*this->m_sourceTradingTimeConfigPath).c_str());
    string sourceTradingTimeContent((istreambuf_iterator<char>(sourceTradingTimeIfs)), (istreambuf_iterator<char>()));
    sourceTradingTimeIfs.close();

    Document sourceTradingTimeDocument;
    sourceTradingTimeDocument.Parse(sourceTradingTimeContent.c_str());
    
    for (rapidjson::Value::ConstMemberIterator itr = sourceTradingTimeDocument.MemberBegin(); itr != sourceTradingTimeDocument.MemberEnd(); ++itr) {
        // day.
        if (!sourceTradingTimeDocument[itr->name.GetString()].HasMember("day")) {
            this->m_coreLogger->error("[ConfigMakerCore InitSourceTradingTimeMap]: source trading time json file: {0} has no day key.", itr->name.GetString());
            cout << "[ConfigMakerCore InitSourceTradingTimeMap]: source trading time json file: " << itr->name.GetString() << " has no day key." << endl;
            return false;
        }
        const Value& daySessionsValue = sourceTradingTimeDocument[itr->name.GetString()]["day"];
        if (!daySessionsValue.IsArray()) {
            this->m_coreLogger->error("[ConfigMakerCore InitSourceTradingTimeMap]: {0} daySessionsValue is not array.", itr->name.GetString());
            cout << "[ConfigMakerCore InitSourceTradingTimeMap]: " << itr->name.GetString() << " daySessionsValue is not array." << endl;
            return false;
        }

        vector<vector<string>> daySessions;
        for (SizeType i = 0; i < daySessionsValue.Size(); i++) {
            vector<string> daySession;
            if (daySessionsValue[i].IsArray()) {
                for (SizeType j = 0; j < daySessionsValue[i].Size(); j++) {
                    if (daySessionsValue[i][j].IsString()) {
                        daySession.push_back(daySessionsValue[i][j].GetString());
                    } else {
                        this->m_coreLogger->error("[ConfigMakerCore InitSourceTradingTimeMap]: {0} daySessionsValue [{1},{2}] is not string.", itr->name.GetString(), i, j);
                        cout << "[ConfigMakerCore InitSourceTradingTimeMap]: " << itr->name.GetString() << " daySessionsValue [" << i << "]" << "[" << j << "]" << " is not string." << endl;
                        return false;
                    }
                }
            } else {
                this->m_coreLogger->error("[ConfigMakerCore InitSourceTradingTimeMap]: {0} daySessionsValue [{1}] is not array.", itr->name.GetString(), i);
                cout << "[ConfigMakerCore InitSourceTradingTimeMap]: " << itr->name.GetString() << " daySessionsValue [" << i << "]" << " is not array." << endl;
                return false;
            }
            daySessions.push_back(daySession);
        }


        // night.
        if (!sourceTradingTimeDocument[itr->name.GetString()].HasMember("night")) {
            this->m_coreLogger->error("[ConfigMakerCore InitSourceTradingTimeMap]: source trading time json file: {0} has no night key.", itr->name.GetString());
            cout << "[ConfigMakerCore InitSourceTradingTimeMap]: source trading time json file: " << itr->name.GetString() << " has no night key." << endl;
            return false;
        }
        const Value& nightSessionsValue = sourceTradingTimeDocument[itr->name.GetString()]["night"];
        if (!nightSessionsValue.IsArray()) {
            // log
            this->m_coreLogger->error("[ConfigMakerCore InitSourceTradingTimeMap]: {0} nightSessionsValue is not array.", itr->name.GetString());
            cout << "[ConfigMakerCore InitSourceTradingTimeMap]: " << itr->name.GetString() << " nightSessionsValue is not array." << endl;
            return false;
        }

        vector<vector<string>> nightSessions;
        for (SizeType i = 0; i < nightSessionsValue.Size(); i++) {
            vector<string> nightSession;
            if (nightSessionsValue[i].IsArray()) {
                for (SizeType j = 0; j < nightSessionsValue[i].Size(); j++) {
                    if (nightSessionsValue[i][j].IsString()) {
                        nightSession.push_back(nightSessionsValue[i][j].GetString());
                    } else {
                        this->m_coreLogger->error("[ConfigMakerCore InitSourceTradingTimeMap]: {0} nightSessionsValue [{1},{2}] is not string.", itr->name.GetString(), i, j);
                        cout << "[ConfigMakerCore InitSourceTradingTimeMap]: " << itr->name.GetString() << " nightSessionsValue [" << i << "]" << "[" << j << "]" << " is not string." << endl;
                        return false;
                    }
                }
            } else {
                this->m_coreLogger->error("[ConfigMakerCore InitSourceTradingTimeMap]: {0} nightSessionsValue [{1}] is not array.", itr->name.GetString(), i);
                cout << "[ConfigMakerCore InitSourceTradingTimeMap]: " << itr->name.GetString() << " nightSessionsValue [" << i << "]" << " is not array." << endl;
                return false;
            }
            nightSessions.push_back(nightSession);
        }

        this->m_sourceTradingTimeMap[itr->name.GetString()] = {{"day", daySessions}, {"night", nightSessions}};
    }

    return true;
}


string ConfigMakerCore::GetExchangeInstru(const string& exchangeInstrument) {
    boost::regex pattern("(.+?)(?=\\d|$)");
    boost::smatch matches;
    if (!boost::regex_search(exchangeInstrument, matches, pattern)) {
        this->m_coreLogger->error("[ConfigMakerCore GetExchangeInstru]: regex_search not match found: {0}.", exchangeInstrument);
        cout << "[ConfigMakerCore GetExchangeInstru]: regex_search not match found: " << exchangeInstrument << endl;
        exit(1); // kill self process.
    }

    return matches.str(1);
}


bool ConfigMakerCore::IsInDaySession(const std::string& time, const std::vector<std::string>& timeRange) {
    return time >= timeRange[0] && time < timeRange[1];
}


bool ConfigMakerCore::IsInNightSession(const std::string& time, const std::vector<std::string>& timeRange) {
    return (timeRange[0] < timeRange[1]) ? this->IsInDaySession(time, timeRange) : (time >= timeRange[0] || time < timeRange[1]);
}


bool ConfigMakerCore::IsTradingTime(const string& exchangeInstru, const std::string& time) {
    if (!(this->m_sourceTradingTimeMap.count(exchangeInstru) > 0)) {
        this->m_coreLogger->error("[ConfigMakerCore IsTradingTime]: sourceTradingTimeMap has no {0} key.", exchangeInstru);
        cout << "[ConfigMakerCore IsTradingTime]: sourceTradingTimeMap has no " << exchangeInstru << " key." << endl;
        exit(1); // kill self process.
    }

    vector<vector<string>> daySessions = this->m_sourceTradingTimeMap[exchangeInstru]["day"];
    for (const auto& daySession : daySessions) {
        if ((2 == daySession.size()) && this->IsInDaySession(time, daySession)) {
            return true;
        }
    }
    
    vector<vector<string>> nightSessions = this->m_sourceTradingTimeMap[exchangeInstru]["night"];
    for (const auto& nightSession : nightSessions) {
        if (2 == nightSession.size() && this->IsInNightSession(time, nightSession)) {
            return true;
        }
    }
    
    return false;
}

string ConfigMakerCore::GetMainContractsDailyPath() {
    size_t last_underscore_pos = (*this->m_csvName).find_last_of("_");
    string mainContractsDailyDir = "./main_contracts_daily/";

    if (!boost::filesystem::exists(mainContractsDailyDir)) {
        mkdir(mainContractsDailyDir.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
    }

    string mainContractsDailyPath = "";
    if (last_underscore_pos != string::npos) {
        mainContractsDailyPath = mainContractsDailyDir + "main_contracts_" + (*this->m_csvName).substr(last_underscore_pos + 1, 8) + ".json";
    } else {
        this->m_coreLogger->error("[ConfigMakerCore Parser]: no find date {0}.", this->m_csvName->data());
        cout << "[ConfigMakerCore Parser]: no find date " << this->m_csvName->data() << "." << endl;
        exit(1); // kill self process.
    }

    return mainContractsDailyPath;
}


void ConfigMakerCore::Parser() {
    if (!this->Check())
        return;

    this->m_coreLogger->info("[ConfigMakerCore Parser]: start parse csv file {0}.", this->m_csvName->data());
    cout << "[ConfigMakerCore Parser]: start parse csv file " << this->m_csvName->data() << "." << endl;

    ifstream csvFile(this->m_marketDepthDataCSVPath->data());
    vector<vector<string>> csvTitles;
    if (!csvFile.is_open()) {
        this->m_coreLogger->error("[ConfigMakerCore Parser]: open depth data csv {0} file fail.", this->m_marketDepthDataCSVPath->data());
        cout << "[ConfigMakerCore Parser]: open depth data csv " << this->m_marketDepthDataCSVPath->data() << " file fail." << endl;
        return;
    }

    string line;
    while (getline(csvFile, line)) {
        vector<string> row;
        string cell;
        istringstream line_stream(line);
        while (getline(line_stream, cell, ',')) {
            row.push_back(cell);
        }

        if (0 == csvTitles.data()) { // filter first line.
            csvTitles.push_back(row);
            continue;
        }

        string exchangeInstru = this->GetExchangeInstru(row[4]);
        if (!this->IsTradingTime(exchangeInstru, row[1]))
            continue;
        
        if (this->m_mainContractsMap.count(exchangeInstru) > 0) {
            if (stol(this->m_mainContractsMap[exchangeInstru]["volume"]) < stol(row[9])) {
                this->m_mainContractsMap[exchangeInstru] = {{"exchange_instrument", row[4]}, {"volume", row[9]}};
            }
        } else {
            this->m_mainContractsMap[exchangeInstru] = {{"exchange_instrument", row[4]}, {"volume", row[9]}};
        }
    }

    csvFile.close();
    csvTitles.clear();
}


void ConfigMakerCore::DumpMainContractsJson() {
    string mainContraactsDailyPath = this->GetMainContractsDailyPath();

    Document document;
    document.SetObject();

    for (const auto& entry : this->m_mainContractsMap) {
        Value key(entry.first.c_str(), document.GetAllocator());
        Value value(kObjectType);
        for (const auto& subentry : entry.second) {
            Value subkey(subentry.first.c_str(), document.GetAllocator());
            Value subvalue(subentry.second.c_str(), document.GetAllocator());
            value.AddMember(subkey, subvalue, document.GetAllocator());
        }
        document.AddMember(key, value, document.GetAllocator());
    }

    StringBuffer buffer;
    Writer<StringBuffer> writer(buffer);
    document.Accept(writer);
    string json_str = buffer.GetString();

    ofstream ofs(this->GetMainContractsDailyPath());
    ofs << json_str << endl;

    this->m_coreLogger->info("[ConfigMakerCore DumpMainContractsJson]: dump main contracts json is ok.");
    cout << "[ConfigMakerCore DumpMainContractsJson]: dump main contracts json is ok." << endl;
}

ConfigMakerCore::~ConfigMakerCore() {
    if (this->m_marketDepthDataConfigPath)
        this->m_marketDepthDataConfigPath.reset();
    
    if (this->m_marketDepthDataCSVPath)
        this->m_marketDepthDataCSVPath.reset();
    
    if (this->m_coreLogger)
        this->m_coreLogger.reset();
    
    if (this->m_csvName)
        this->m_csvName.reset();
    
    if (this->m_sourceTradingTimeConfigPath)
        this->m_sourceTradingTimeConfigPath.reset();

    this->m_mainContractsMap.clear();
    this->m_sourceTradingTimeMap.clear();
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值