#include "QdpFtdcTraderApi.h"
#include <iostream>
#include <cstdlib>
#include <string.h>
#include <stdio.h>
#include <thread>
#include <chrono>
#include <map>
#include <string>

using namespace std;

// 报单录入操作是否完成的标志
// 经纪公司代码
TQdpFtdcBrokerIDType g_chBrokerID;
// 交易用户代码
TQdpFtdcUserIDType g_chUserID;
// 用户密码
TQdpFtdcPasswordType g_chPassword;
// 用户本地最大报单号
int g_nOrdLocalID = 0;

/// 交易API
CQdpFtdcTraderApi *g_pTraderApi = NULL;

void ReqLogin(int RequestID);

void ReqAuth(int RequestID);

void ReqUserPasswordUpdate(int RequestID);

void ReqSubPrdTradeFlow(int RequestID);

void ReqUnSubPrdTradeFlow(int RequestID);

void ReqQryMarketData(int RequestID);

void ReqQryExchange(int &RequestID);

void ReqQryTrade(int &RequestID);

void ReqQryOrder(int &RequestID);

void ReqSubmitUserSystemInfo(int RequestID);

int ReqSetClientMaxSigVol(int RequestID);

int ReqOrderAction(int RequestID);

int ReqOrderInsert(int RequestID);

int ReqQryUserInvestor(int RequestID);

int ReqQryInvestorAccount(int RequestID);

int ReqQryInvestorOptionFee(int RequestID);

int ReqQryInvestorMargin(int RequestID);

int ReqQryInstrument(int RequestID);

int ReqQryInvestorFee(int RequestID);

int ReqQryInvestorPosition(int RequestID);

class CTraderSpi : public CQdpFtdcTraderSpi
{
public:
    CTraderSpi(CQdpFtdcTraderApi *pUserApi) : m_pTraderApi(pUserApi),
                                              m_bIsLogin(false),
                                              m_bConnected(false)
    {
    }
    ~CTraderSpi() {};

    // 实现CTraderSpi的各个接口
    virtual void OnFrontConnected()
    {
        std::cout << "OnFrontConnected\n";
        m_bConnected = true;

        ReqAuth(0);
    };

    virtual void OnFrontDisconnected(int nReason)
    {
        std::cout << "OnFrontDisconnected: " << nReason << std::endl;
        m_bConnected = false;
        m_bIsLogin = false;
    }

    virtual void OnRspUserLogin(CQdpFtdcRspUserLoginField *pRspUserLogin, CQdpFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast)
    {
        if (pRspInfo == NULL)
        {
            std::cout << "OnRspUserLogin=NULL!\n";
            return;
        }

        if (pRspInfo->ErrorID != 0)
        {
            std::cout << "UserID: " << g_chUserID << "Login failed, ErrorMsg: " << pRspInfo->ErrorMsg;
            return;
        }
        std::cout << "UserID: " << g_chUserID << "Login Success.\n";

        /// 准备就绪 QDP_TERT_PRIVATE 私有流; QDP_TERT_PUBLIC 公有流;
        CQdpFtdcFlowStatusField ftdField1;
        memset(&ftdField1, 0, sizeof(CQdpFtdcFlowStatusField));
        ftdField1.SequenceSeries = QDP_TERT_PRIVATE;
        ftdField1.bReady = true;
        m_pTraderApi->ReqReady(&ftdField1, 0);
        memset(&ftdField1, 0, sizeof(CQdpFtdcFlowStatusField));
        ftdField1.SequenceSeries = QDP_TERT_PUBLIC;
        ftdField1.bReady = true;
        m_pTraderApi->ReqReady(&ftdField1, 0);

        m_bIsLogin = true;
    }

    virtual void OnRspUserLogout(CQdpFtdcRspUserLogoutField *pRspUserLogout, CQdpFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast)
    {
        if (pRspInfo == NULL)
        {
            std::cout << "OnRspUserLogout=NULL!\n";
            return;
        }
        if (pRspInfo->ErrorID != 0)
        {
            std::cout << "OnRspUserLogout failed, ErrorMsg:" << pRspInfo->ErrorMsg << "\n";
            return;
        }

        m_bIsLogin = false;
    }

    virtual void OnRspUserPasswordUpdate(CQdpFtdcUserPasswordUpdateField *pUserPasswordUpdate, CQdpFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast)
    {
        if (pRspInfo == NULL)
        {
            std::cout << "OnRspUserPasswordUpdate=NULL!\n";
            return;
        }
        if (pRspInfo->ErrorID != 0)
        {
            std::cout << "OnRspUserPasswordUpdate failed, ErrorMsg:" << pRspInfo->ErrorMsg << "\n";
            return;
        }
    }

    virtual void OnRspAuthenticate(CQdpFtdcRtnAuthenticateField *pRtnAuthenticate, CQdpFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast)
    {
        if (pRspInfo == NULL)
        {
            std::cout << "OnRspAuthenticate=NULL!\n";
            return;
        }
        if (pRspInfo->ErrorID != 0)
        {
            std::cout << "OnRspAuthenticate failed, ErrorMsg:" << pRspInfo->ErrorMsg << "\n";
            return;
        }

        std::cout << "OnRspAuthenticate success, UserID:" << pRtnAuthenticate->UserID << "\n";

        // 认证成功后登录
        ReqLogin(nRequestID);
    }

    // traderSPI
    virtual void OnRtnTrade(CQdpFtdcTradeField *pTrade)
    {
        std::cout << "OnRtnTrade: OrderSysID=" << pTrade->OrderSysID
                  << ", InstrumentID=" << pTrade->InstrumentID
                  << ", TradeID=" << pTrade->TradeID
                  << ", TradeVolume=" << pTrade->TradeVolume
                  << "\n";
    }

    virtual void OnRtnOrder(CQdpFtdcOrderField *pOrder)
    {
        // store OrderSysID
        std::cout << "OnRtnOrder: OrderSysID=" << pOrder->OrderSysID
                  << ", InstrumentID=" << pOrder->InstrumentID
                  << ", Volume=" << pOrder->Volume
                  << ", OrderStatus=" << pOrder->OrderStatus
                  << "\n";
    }

    virtual void OnRtnInstrumentStatus(CQdpFtdcInstrumentStatusField *pInstrumentStatus)
    {
        if (NULL != pInstrumentStatus)
        {
            std::cout << "OnRtnInstrumentStatus: InstrumentID=" << pInstrumentStatus->InstrumentID
                      << ", InstrumentStatus=" << pInstrumentStatus->InstrumentStatus
                      << "\n";
        }
    }

    // virtual void OnErrRtnOrderInsert(CQdpFtdcInputOrderField* pInputOrder, CQdpFtdcRspInfoField* pRspInfo){};

    virtual void OnRspOrderAction(CQdpFtdcOrderActionField *pOrderAction, CQdpFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast)
    {
        if (pRspInfo == NULL)
        {
            std::cout << "OnRspOrderAction=NULL!\n";
            return;
        }
        if (pRspInfo != NULL && pRspInfo->ErrorID != 0)
        {
            std::cout << "OnRspOrderAction failed, ErrorMsg:" << pRspInfo->ErrorMsg << "\n";
            return;
        }
        std::cout << "OnRspOrderAction success, OrderSysID=" << pOrderAction->OrderSysID;
    }

    // QuerySPI
    virtual void OnRspQryUserInvestor(CQdpFtdcRspUserInvestorField *pRspUserInvestor, CQdpFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast)
    {
        std::cout << "UserID:" << pRspUserInvestor->UserID
                  << ", InvestorIDNum:" << pRspUserInvestor->InvestorIDNum
                  << ", InvestorID:" << pRspUserInvestor->InvestorID << "\n";
    }

    virtual void OnRspQryInvestorPosition(CQdpFtdcRspInvestorPositionField *pRspInvestorPosition, CQdpFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast)
    {
        std::cout << "OnRspQryInvestorPosition\n";
        if (pRspInfo != NULL && pRspInfo->ErrorID != 0)
        {
            std::cout << "failed; ErrorID: " << pRspInfo->ErrorID
                      << ", ErrorMsg: " << pRspInfo->ErrorMsg << ", RequestID: " << nRequestID << "\n";
            return;
        }

        if (pRspInvestorPosition != NULL)
        {
            // 总持仓成本 总持仓量 合约乘数
            std::cout << "Success; InvestorID=[" << pRspInvestorPosition->InvestorID
                      << "], InstrumentID=[" << pRspInvestorPosition->InstrumentID
                      << "], UsedMargin=[" << pRspInvestorPosition->UsedMargin
                      << "], FrozenMargin=[" << pRspInvestorPosition->FrozenMargin
                      << "], FrozenPremium=[" << pRspInvestorPosition->FrozenPremium
                      << "], PositionProfit=[" << pRspInvestorPosition->PositionProfit
                      << "], PositionCost=[" << pRspInvestorPosition->PositionCost
                      << "], TodayPosition=[" << pRspInvestorPosition->TodayPosition
                      << "];\n";
        }
    }

    virtual void OnRspQryInstrument(CQdpFtdcRspInstrumentField *pRspInstrument, CQdpFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast)
    {
        std::cout << "OnRspQryInstrument\n";

        if (pRspInfo != NULL && pRspInfo->ErrorID != 0)
        {
            std::cout << "failed; ErrorID: " << pRspInfo->ErrorID
                      << ", ErrorMsg: " << pRspInfo->ErrorMsg << ", RequestID: " << nRequestID << "\n";
            return;
        }

        if (pRspInstrument != NULL)
        {
            std::cout << "Success; ExchangeID=[" << pRspInstrument->ExchangeID
                      << "], InstrumentID=[" << pRspInstrument->InstrumentID
                      << "], InstrumentIDNum=" << pRspInstrument->InstrumentIDNum // 在API7.0版本中，报单时填写InstrumentIDNum
                      << "], VolumeMultiple=[" << pRspInstrument->VolumeMultiple
                      << "], PriceTick=[" << pRspInstrument->PriceTick
                      << "], PreSettlementPrice=[" << pRspInstrument->PreSettlementPrice
                      << "], InstrumentStatus=[" << pRspInstrument->InstrumentStatus
                      << "];\n";
        }
    }

    virtual void OnRspQryInvestorAccount(CQdpFtdcRspInvestorAccountField *pRspInvestorAccount, CQdpFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast)
    {
        std::cout << "OnRspQryInvestorAccount\n";

        if (pRspInfo != NULL && pRspInfo->ErrorID != 0)
        {
            std::cout << "failed; ErrorID: " << pRspInfo->ErrorID
                      << ", ErrorMsg: " << pRspInfo->ErrorMsg << ", RequestID: " << nRequestID << "\n";
            return;
        }

        if (pRspInvestorAccount != NULL)
        {
            std::cout << "Success; AccountID=[" << pRspInvestorAccount->AccountID
                      << "InvestorID=[" << pRspInvestorAccount->InvestorID
                      << "], PreBalance=[" << pRspInvestorAccount->PreBalance
                      << "], PreAvailable=[" << pRspInvestorAccount->PreAvailable
                      << "], CloseProfit=[" << pRspInvestorAccount->CloseProfit
                      << "], PositionProfit=[" << pRspInvestorAccount->PositionProfit
                      << "], Fee=[" << pRspInvestorAccount->Fee
                      << "], FrozenFee=[" << pRspInvestorAccount->FrozenFee
                      << "], FrozenPremium=[" << pRspInvestorAccount->FrozenPremium
                      << "], Margin=[" << pRspInvestorAccount->Margin
                      << "], FrozenMargin=[" << pRspInvestorAccount->FrozenMargin
                      << "], Available=[" << pRspInvestorAccount->Available
                      << "], DynamicRights=[" << pRspInvestorAccount->DynamicRights
                      << "], Balance=[" << pRspInvestorAccount->Balance
                      << "], Deposit=[" << pRspInvestorAccount->Deposit
                      << "], Withdraw=[" << pRspInvestorAccount->Withdraw
                      << "];\n";
        }
    }

    virtual void OnRspQryInvestorMargin(CQdpFtdcInvestorMarginField *pInvestorMargin, CQdpFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast)
    {
        std::cout << "OnRspQryInvestorMargin\n";
        if (pRspInfo != NULL && pRspInfo->ErrorID != 0)
        {
            std::cout << "failed; ErrorID: " << pRspInfo->ErrorID
                      << ", ErrorMsg: " << pRspInfo->ErrorMsg << ", RequestID: " << nRequestID << "\n";
            return;
        }
        if (pInvestorMargin != NULL)
        {
            std::cout << "Success; InstrumentID=[" << pInvestorMargin->InstrumentID
                      << "], InvestorID=[" << pInvestorMargin->InvestorID
                      << "], HedgeFlag=[" << pInvestorMargin->HedgeFlag
                      << "], LongMarginRate=[" << pInvestorMargin->LongMarginRate
                      << "], LongMarginAmt=[" << pInvestorMargin->LongMarginAmt
                      << "], ShortMarginRate=[" << pInvestorMargin->ShortMarginRate
                      << "], ShortMarginAmt=[" << pInvestorMargin->ShortMarginAmt
                      << "];" << "\n";
        }
    }

    virtual void OnRspQryInvestorFee(CQdpFtdcInvestorFeeField *pInvestorFee, CQdpFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast)
    {
        std::cout << "OnRspQryInvestorFee\n";

        if (pRspInfo != NULL && pRspInfo->ErrorID != 0)
        {
            std::cout << "failed; ErrorID: " << pRspInfo->ErrorID
                      << ", ErrorMsg: " << pRspInfo->ErrorMsg << ", RequestID: " << nRequestID << "\n";
            return;
        }

        if (pInvestorFee != NULL)
        {
            std::cout << "Success; InstrumentID=[" << pInvestorFee->InstrumentID
                      << "], InvestorID=[" << pInvestorFee->InvestorID
                      << "], HedgeFlag=[" << pInvestorFee->HedgeFlag
                      << "], OpenFeeRate=[" << pInvestorFee->OpenFeeRate
                      << "], OpenFeeAmt=[" << pInvestorFee->OpenFeeAmt
                      << "], OffsetFeeRate=[" << pInvestorFee->OffsetFeeRate
                      << "], OffsetFeeAmt=[" << pInvestorFee->OffsetFeeAmt
                      << "], OTFeeRate=[" << pInvestorFee->OTFeeRate
                      << "], OTFeeAmt=[" << pInvestorFee->OTFeeAmt
                      << "];" << "\n";
        }
    }

    virtual void OnRspQryInvestorOptionFee(CQdpFtdcRspInvestorOptionFeeField *pRspInvestorOptionFee, CQdpFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast)
    {
        std::cout << "OnRspQryInvestorOptionFee\n";

        if (pRspInfo != NULL && pRspInfo->ErrorID != 0)
        {
            std::cout << "failed; ErrorID: " << pRspInfo->ErrorID
                      << ", ErrorMsg: " << pRspInfo->ErrorMsg << ", RequestID: " << nRequestID << "\n";
            return;
        }

        if (pRspInvestorOptionFee != NULL)
        {
            std::cout << "Success; InstrumentID=[" << pRspInvestorOptionFee->InstrumentID
                      << "], InvestorID=[" << pRspInvestorOptionFee->InvestorID
                      << "], OpenFeeRate=[" << pRspInvestorOptionFee->OpenFeeRate
                      << "], OpenFeeAmt=[" << pRspInvestorOptionFee->OpenFeeAmt
                      << "], OffsetFeeRate=[" << pRspInvestorOptionFee->OffsetFeeRate
                      << "], OffsetFeeAmt=[" << pRspInvestorOptionFee->OffsetFeeAmt
                      << "], OTFeeRate=[" << pRspInvestorOptionFee->OTFeeRate
                      << "], OTFeeAmt=[" << pRspInvestorOptionFee->OTFeeAmt
                      << "], StrikeFeeRate=[" << pRspInvestorOptionFee->StrikeFeeRate
                      << "], StrikeFeeAmt=[" << pRspInvestorOptionFee->StrikeFeeAmt
                      << "];" << "\n";
        }
    }

    virtual void OnRspQryMarketData(CQdpFtdcMarketDataField *pMarketData, CQdpFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast)
    {
        std::cout << "OnRspQryMarketData\n";
        if (pRspInfo != NULL && pRspInfo->ErrorID != 0)
        {
            std::cout << "failed; ErrorID: " << pRspInfo->ErrorID
                      << ", ErrorMsg: " << pRspInfo->ErrorMsg << ", RequestID: " << nRequestID << "\n";
            return;
        }

        if (pMarketData != NULL)
        {
            std::cout << "Success; InstrumentID=[" << pMarketData->InstrumentID
                      << "], ExchangeID=[" << pMarketData->ExchangeID
                      << "], LastPrice=[" << pMarketData->LastPrice
                      << "], PreSettlementPrice=[" << pMarketData->PreSettlementPrice
                      << "], OpenPrice=[" << pMarketData->OpenPrice
                      << "], HighestPrice=[" << pMarketData->HighestPrice
                      << "], LowestPrice=[" << pMarketData->LowestPrice
                      << "], Volume=[" << pMarketData->Volume
                      << "], Turnover=[" << pMarketData->Turnover
                      << "], OpenInterest=[" << pMarketData->OpenInterest
                      << "], PreClosePrice=[" << pMarketData->PreClosePrice
                      << "], SettlementPrice=[" << pMarketData->SettlementPrice
                      << "], UpperLimitPrice=[" << pMarketData->UpperLimitPrice
                      << "], LowerLimitPrice=[" << pMarketData->LowerLimitPrice
                      << "];" << "\n";
        }
    }

    virtual void OnRspQryExchange(CQdpFtdcRspExchangeField *pRspExchange, CQdpFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast)
    {
        std::cout << "OnRspQryExchange\n";
        if (pRspInfo != NULL && pRspInfo->ErrorID != 0)
        {
            std::cout << "failed; ErrorID: " << pRspInfo->ErrorID
                      << ", ErrorMsg: " << pRspInfo->ErrorMsg << ", RequestID: " << nRequestID << "\n";
            return;
        }

        if (pRspExchange != NULL)
        {
            std::cout << "Success; ExchangeID=[" << pRspExchange->ExchangeID
                      << "], ExchangeName=[" << pRspExchange->ExchangeName
                      << "];" << "\n";
        }
    }

    virtual void OnRspQryTrade(CQdpFtdcTradeField *pTrade, CQdpFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast)
    {
        std::cout << "OnRspQryTrade\n";
        if (pRspInfo != NULL && pRspInfo->ErrorID != 0)
        {
            std::cout << "failed; ErrorID: " << pRspInfo->ErrorID
                      << ", ErrorMsg: " << pRspInfo->ErrorMsg << ", RequestID: " << nRequestID << "\n";
            return;
        }

        if (pTrade != NULL)
        {
            std::cout << "Success; InstrumentID=[" << pTrade->InstrumentID
                      << "], InvestorID=[" << pTrade->InvestorID
                      << "], OrderSysID=[" << pTrade->OrderSysID
                      << "], ExchangeID=[" << pTrade->ExchangeID
                      << "], TradeID=[" << pTrade->TradeID
                      << "], TradeVolume=[" << pTrade->TradeVolume
                      << "], TradePrice=[" << pTrade->TradePrice
                      << "], TradeTime=[" << pTrade->TradeTime
                      << "];" << "\n";
        }
    }

    virtual void OnRspQryOrder(CQdpFtdcOrderField *pOrder, CQdpFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast)
    {
        std::cout << "OnRspQryOrder\n";
        if (pRspInfo != NULL && pRspInfo->ErrorID != 0)
        {
            std::cout << "failed; ErrorID: " << pRspInfo->ErrorID
                      << ", ErrorMsg: " << pRspInfo->ErrorMsg
                      << ", RequestID: " << nRequestID << std::endl;
            return;
        }

        if (pOrder != NULL)
        {
            std::cout << "Success; InstrumentID=[" << pOrder->InstrumentID
                      << "], InvestorID=[" << pOrder->InvestorID
                      << "], OrderSysID=[" << pOrder->OrderSysID
                      << "], ExchangeID=[" << pOrder->ExchangeID
                      << "], OrderStatus=[" << pOrder->OrderStatus
                      << "], Volume=[" << pOrder->Volume
                      << "], LimitPrice=[" << pOrder->LimitPrice
                      << "], VolumeTraded=[" << pOrder->VolumeTraded
                      << "], VolumeRemain=[" << pOrder->VolumeRemain
                      << "];" << "\n";
        }
    }

    virtual void OnRspOrderInsert(CQdpFtdcRspInputOrderField *pRspInputOrder, CQdpFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast)
    {
        std::cout << "OnRspOrderInsert\n";
        if (pRspInfo != NULL && pRspInfo->ErrorID != 0)
        {
            std::cout << "failed; ErrorID: " << pRspInfo->ErrorID
                      << ", ErrorMsg: " << pRspInfo->ErrorMsg
                      << ", RequestID: " << nRequestID << std::endl;
            return;
        }

        if (pRspInputOrder != NULL)
        {
            std::cout << "Success; InvestorIDNum=[" << pRspInputOrder->InvestorIDNum
                      << "],InstrumentID=[" << pRspInputOrder->InstrumentID
                      << "],OrderSysID=[" << pRspInputOrder->OrderSysID
                      << "],Volume=[" << pRspInputOrder->Volume
                      << "],LimitPrice=[" << pRspInputOrder->LimitPrice
                      << "],UserOrderLocalID=[" << pRspInputOrder->UserOrderLocalID
                      << "];\n";
        }
    }

private:
    CQdpFtdcTraderApi *m_pTraderApi;

public:
    bool m_bIsLogin;
    bool m_bConnected;
};

void ReqLogin(int RequestID)
{
    CQdpFtdcReqUserLoginField reqUserLogin;

    strcpy(reqUserLogin.UserProductInfo, "demo_test");
    strcpy(reqUserLogin.BrokerID, g_chBrokerID);
    strcpy(reqUserLogin.UserID, g_chUserID);
    strcpy(reqUserLogin.Password, "1");
    // 发出登陆请求
    g_pTraderApi->ReqUserLogin(&reqUserLogin, RequestID);
}

void ReqAuth(int RequestID)
{
    CQdpFtdcAuthenticateField reqfield;
    // 初始化认证变量
    strcpy(g_chBrokerID, "guofu");
    strcpy(g_chUserID, "admin");

    strcpy(reqfield.BrokerID, g_chBrokerID);
    strcpy(reqfield.UserID, g_chUserID);
    strcpy(reqfield.UserProductInfo, "7.0_demo_test");
    strcpy(reqfield.AppID, "quantdo_InfiniV8_1");
    strcpy(reqfield.AuthCode, "0f8596818807c41f71cbcc2338e973dd");
    // 发出认证请求
    g_pTraderApi->ReqAuthenticate(&reqfield, RequestID);
}

void ReqUserPasswordUpdate(int RequestID)
{
    std::cout << "ReqUserPasswordUpdate Info:" << std::endl;
    CQdpFtdcUserPasswordUpdateField t_field;
    memset(&t_field, 0, sizeof(t_field));
    strcpy(t_field.BrokerID, g_chBrokerID);
    strcpy(t_field.UserID, g_chUserID);
    std::cout << "OldPassword: ";
    std::cin >> t_field.OldPassword;
    std::cout << "NewPassword: ";
    std::cin >> t_field.NewPassword;
    g_pTraderApi->ReqUserPasswordUpdate(&t_field, RequestID);
}

void ReqSubPrdTradeFlow(int RequestID)
{
    std::cout << "ReqSubPrdTradeFlow Info:" << std::endl;
    CQdpFtdcSpecificInstrumentField t_field;
    memset(&t_field, 0, sizeof(t_field));
    std::cout << "ProductID: ";
    std::cin >> t_field.InstrumentID;
    g_pTraderApi->ReqSubPrdTradeFlow(&t_field, RequestID);
}

void ReqUnSubPrdTradeFlow(int RequestID)
{
    std::cout << "ReqSubPrdTradeFlow Info:" << std::endl;
    CQdpFtdcSpecificInstrumentField t_field;
    memset(&t_field, 0, sizeof(t_field));
    std::cout << "ProductID: ";
    std::cin >> t_field.InstrumentID;
    g_pTraderApi->ReqUnSubPrdTradeFlow(&t_field, RequestID);
}

void ReqQryMarketData(int RequestID)
{
    CQdpFtdcQryMarketDataField d_field;
    memset(&d_field, 0, sizeof(CQdpFtdcQryMarketDataField));
    g_pTraderApi->ReqQryMarketData(&d_field, RequestID);
}

void ReqQryExchange(int &RequestID)
{
    CQdpFtdcQryExchangeField t_field;
    memset(&t_field, 0, sizeof(CQdpFtdcQryExchangeField));
    g_pTraderApi->ReqQryExchange(&t_field, RequestID);
}

void ReqQryTrade(int &RequestID)
{
    CQdpFtdcQryTradeField t_field;
    memset(&t_field, 0, sizeof(CQdpFtdcQryTradeField));
    strcpy(t_field.BrokerID, g_chBrokerID);
    strcpy(t_field.UserID, g_chUserID);
    g_pTraderApi->ReqQryTrade(&t_field, RequestID);
}

void ReqQryOrder(int &RequestID)
{
    CQdpFtdcQryOrderField o_field;
    memset(&o_field, 0, sizeof(CQdpFtdcQryOrderField));
    strcpy(o_field.BrokerID, g_chBrokerID);
    strcpy(o_field.UserID, g_chUserID);
    g_pTraderApi->ReqQryOrder(&o_field, RequestID);
}

void ReqSubmitUserSystemInfo(int RequestID)
{
    CQdpFtdcUserSystemInfoField a_field;
    memset(&a_field, 0, sizeof(a_field));
    // 基于数据收集的库(qdpdatacollectapi)获取到相关信息后填写
    g_pTraderApi->ReqSubmitUserSystemInfo(&a_field, RequestID);
}

int ReqSetClientMaxSigVol(int RequestID)
{
    CQdpFtdcClientMaxSigVolField a_field;
    memset(&a_field, 0, sizeof(a_field));
    strcpy(a_field.BrokerID, g_chBrokerID);
    strcpy(a_field.ExchangeID, "CFFEX");
    strcpy(a_field.InvestorID, "1002");
    a_field.HedgeFlag = '1';
    // strcpy(a_field.InstrumentID,"");
    // a_field.MaxSigVol = 10;
    return g_pTraderApi->ReqSetClientMaxSigVol(&a_field, RequestID);
}

int ReqOrderAction(int RequestID)
{
    std::cout << "ReqOrderAction Info:" << std::endl;
    CQdpFtdcOrderActionField ord;
    memset(&ord, 0, sizeof(ord));
    // 交易所
    std::cout << "ExchangeID: ";
    std::cin >> ord.ExchangeID;
    // 被撤订单的本地报单编号
    std::cout << "UserOrderLocalID: ";
    std::cin >> ord.UserOrderLocalID;
    // 本次撤单操作的本地编号
    ord.UserOrderActionLocalID = ++g_nOrdLocalID;
    // 报单编号
    std::cout << "OrderSysID: ";
    std::cin >> ord.OrderSysID;
    // 报单操作标志
    ord.ActionFlag = QDP_FTDC_AF_Delete;

    return g_pTraderApi->ReqOrderAction(&ord, RequestID);
}

int ReqOrderInsert(int RequestID)
{
    std::cout << "ReqOrderInsert Info:" << std::endl;
    CQdpFtdcInputOrderField ord;
    memset(&ord, 0, sizeof(ord));
    std::cout << "InvestorID: ";
    std::cin >> ord.InvestorID;
    // 合约号 -- 需要调用合约查询 获取合约代码对应的合约号
    std::cout << "InstrumentID: ";
    std::cin >> ord.InstrumentID;
    // 本地报单号
    ord.UserOrderLocalID = ++g_nOrdLocalID;
    // 报单类型
    std::cout << "OrderPriceType: ";
    std::cin >> ord.OrderPriceType;
    // ord.OrderPriceType = QDP_FTDC_OPT_LimitPrice;
    // 买卖方向
    std::cout << "Direction: ";
    std::cin >> ord.Direction;
    // ord.Direction = QDP_FTDC_D_Buy;
    // 开平标志
    std::cout << "OffsetFlag: ";
    std::cin >> ord.OffsetFlag;
    // strcpy(&(ord.OffsetFlag), "0");
    // 投机套保标志
    std::cout << "HedgeFlag: ";
    std::cin >> ord.HedgeFlag;
    // strcpy(&(ord.HedgeFlag), "1");
    // 价格
    std::cout << "LimitPrice: ";
    std::cin >> ord.LimitPrice;
    // ord.LimitPrice = 3074;
    // 数量
    std::cout << "Volume: ";
    std::cin >> ord.Volume;
    // ord.Volume = 1;
    // 有效期类型
    std::cout << "TimeCondition: ";
    std::cin >> ord.TimeCondition;
    // ord.TimeCondition = QDP_FTDC_TC_GFD;
    // 成交量类型
    std::cout << "VolumeCondition: ";
    std::cin >> ord.VolumeCondition;
    // ord.VolumeCondition = QDP_FTDC_VC_AV;

    return g_pTraderApi->ReqOrderInsert(&ord, RequestID);
}

int ReqQryUserInvestor(int RequestID)
{
    CQdpFtdcQryUserInvestorField a_field;
    memset(&a_field, 0, sizeof(CQdpFtdcQryUserInvestorField));
    strcpy(a_field.BrokerID, g_chBrokerID);
    strcpy(a_field.UserID, g_chUserID);
    return g_pTraderApi->ReqQryUserInvestor(&a_field, RequestID);
}

int ReqQryInvestorAccount(int RequestID)
{
    CQdpFtdcQryInvestorAccountField a_field;
    memset(&a_field, 0, sizeof(CQdpFtdcQryInvestorAccountField));
    strcpy(a_field.BrokerID, g_chBrokerID);
    strcpy(a_field.UserID, g_chUserID);
    std::cout << "InvestorID: ";
    std::cin >> a_field.InvestorID;
    return g_pTraderApi->ReqQryInvestorAccount(&a_field, RequestID);
}

int ReqQryInvestorOptionFee(int RequestID)
{
    CQdpFtdcQryInvestorOptionFeeField of_field;
    memset(&of_field, 0, sizeof(CQdpFtdcQryInvestorOptionFeeField));
    strcpy(of_field.BrokerID, g_chBrokerID);
    strcpy(of_field.UserID, g_chUserID);
    std::cout << "InvestorID: ";
    std::cin >> of_field.InvestorID;
    return g_pTraderApi->ReqQryInvestorOptionFee(&of_field, RequestID);
}

int ReqQryInvestorMargin(int RequestID)
{
    CQdpFtdcQryInvestorMarginField m_field;
    memset(&m_field, 0, sizeof(CQdpFtdcQryInvestorMarginField));
    strcpy(m_field.BrokerID, g_chBrokerID);
    strcpy(m_field.UserID, g_chUserID);
    std::cout << "InvestorID: ";
    std::cin >> m_field.InvestorID;
    return g_pTraderApi->ReqQryInvestorMargin(&m_field, RequestID);
}

int ReqQryInstrument(int RequestID)
{
    CQdpFtdcQryInstrumentField i_field;
    memset(&i_field, 0, sizeof(CQdpFtdcQryInstrumentField));
    return g_pTraderApi->ReqQryInstrument(&i_field, RequestID);
}

int ReqQryInvestorFee(int RequestID)
{
    CQdpFtdcQryInvestorFeeField f_field;
    memset(&f_field, 0, sizeof(CQdpFtdcQryInvestorFeeField));
    strcpy(f_field.BrokerID, g_chBrokerID);
    strcpy(f_field.UserID, g_chUserID);
    return g_pTraderApi->ReqQryInvestorFee(&f_field, RequestID);
}

int ReqQryInvestorPosition(int RequestID)
{
    std::cout << "ReqQryInvestorPosition Info:" << std::endl;
    CQdpFtdcQryInvestorPositionField p_field;
    memset(&p_field, 0, sizeof(CQdpFtdcQryInvestorPositionField));
    strcpy(p_field.BrokerID, g_chBrokerID);
    strcpy(p_field.UserID, g_chUserID);
    std::cout << "InvestorID: ";
    std::cin >> p_field.InvestorID;
    std::cout << "ExchangeID: ";
    std::cin >> p_field.ExchangeID;
    std::cout << "InstrumentID: ";
    std::cin >> p_field.InstrumentID;
    return g_pTraderApi->ReqQryInvestorPosition(&p_field, RequestID);
}

void ShowHelp()
{
    std::cout << "输入数字执行对应的操作:\n"
                 " 1: 合约查询请求(必须执行, 否则后面填写InstrmentID找不到对应的Num)\n"
                 " 2: 报单录入请求\n"
                 " 3: 报单操作请求\n"
                 " 4: 客户信息量阈值设置请求\n"
                 " 5: 可用投资者账户查询请求\n"
                 " 6: 投资者资金账户查询请求\n"
                 " 7: 投资者持仓查询请求\n"
                 " 8: 投资者手续费率查询请求\n"
                 " 9: 投资者保证金率查询请求\n"
                 "11: 投资者期权手续费率查询请求\n"
                 "16: 报单查询请求\n"
                 "17: 成交单查询请求\n"
                 "18: 交易所查询请求\n"
                 "19: 实时行情查询请求\n"
                 "24: 用户密码修改请求\n"
                 "------------------------------\n";
}

void OrderFunc(CTraderSpi *pTraderSpi)
{
    if (NULL == pTraderSpi)
    {
        return;
    }
    while (!pTraderSpi->m_bConnected)
    {
        std::this_thread::sleep_for(std::chrono::microseconds(1000));
        continue;
    }
    int RequestID = 0;

    while (!pTraderSpi->m_bIsLogin)
    {
        std::this_thread::sleep_for(std::chrono::microseconds(1000));
        continue;
    }

    // 注释了报价相关的请求 需要时打开
    // 操作类型
    int operationType = 0;
    while (1)
    {
        ShowHelp();
        // 接受用户输入 执行对应的查询和报单操作
        // !! 这里必须先执行合约和投资者查询
        std::cin >> operationType;
        switch (operationType)
        {
        case 1:
            // 合约查询请求
            ReqQryInstrument(RequestID);
            break;
        case 2:
            // 报单录入请求
            ReqOrderInsert(RequestID);
            break;
        case 3:
            // 报单操作请求
            ReqOrderAction(RequestID);
            break;
        case 4:
            // 客户信息量阈值设置请求
            // ReqSetClientMaxSigVol(RequestID);
            break;
        case 5:
            // 可用投资者账户查询请求
            ReqQryUserInvestor(RequestID);
            break;
        case 6:
            // 投资者资金账户查询请求
            ReqQryInvestorAccount(RequestID);
            break;
        case 7:
            // 投资者持仓查询请求
            ReqQryInvestorPosition(RequestID);
            break;
        case 8:
            // 投资者手续费率查询请求
            ReqQryInvestorFee(RequestID);
            break;
        case 9:
            // 投资者保证金率查询请求
            ReqQryInvestorMargin(RequestID);
            break;
        case 11:
            // 投资者期权手续费率查询请求
            ReqQryInvestorOptionFee(RequestID);
            break;
        case 15:
            // 用户采集信息发送请求
            // ReqSubmitUserSystemInfo(RequestID);
            break;
        case 16:
            // 报单查询请求
            ReqQryOrder(RequestID);
            break;
        case 17:
            // 成交单查询请求
            ReqQryTrade(RequestID);
            break;
        case 18:
            // 交易所查询请求
            ReqQryExchange(RequestID);
            break;
        case 19:
            // 实时行情查询请求
            ReqQryMarketData(RequestID);
            break;
        case 24:
            // 用户密码修改请求
            ReqUserPasswordUpdate(RequestID);
            break;
        default:
            break;
        }
        RequestID++;
    }
}

int main()
{
    // 产生一个CQdpFtdcTraderApi实例
    CQdpFtdcTraderApi *pUserApi = CQdpFtdcTraderApi::CreateFtdcTraderApi();

    // 保存api
    g_pTraderApi = pUserApi;

    // 获取API版本号
    int max_version, min_version;
    std::cout << "API版本号:" << CQdpFtdcTraderApi::GetVersion(max_version, min_version);

    // 产生一个事件处理的实例
    CTraderSpi *pTraderSpi = new CTraderSpi(pUserApi);

    // 注册事件处理的实例
    pUserApi->RegisterSpi(pTraderSpi);
    // 订阅私有流
    // QDP_TERT_RESTART:从本交易日开始重传
    // QDP_TERT_RESUME:从上次收到的续传
    // QDP_TERT_QUICK:只传送登录后私有流的内容
    pUserApi->SubscribePrivateTopic(QDP_TERT_RESUME);
    // 订阅公共流
    // QDP_TERT_RESTART:从本交易日开始重传
    // QDP_TERT_RESUME:从上次收到的续传
    // QDP_TERT_QUICK:只传送登录后私有流的内容
    pUserApi->SubscribePublicTopic(QDP_TERT_RESUME);

    // 设置量投科技服务的地址，可以注册多个地址备用
    pUserApi->RegisterFront("tcp://127.0.0.1:30005");

    // 设置心跳超时
    // pUserApi->SetHeartbeatTimeout(240);

    // 使客户端开始与后台服务建立连接
    pUserApi->Init();

    OrderFunc(pTraderSpi);

    // 等待API实例
    pUserApi->Join();
    // 释放API实例
    pUserApi->Release();
    return 0;
}