C++ sample for MT4 API

发布者:admin 发布时间:2019-07-18 14:30:04

#include "stdafx.h"

#include <time.h>

#include <iostream>

//-----------------------------------------------------------------

// 动态数组智能指针构造模板与宏

//-----------------------------------------------------------------

//构造动态数组智能指针模板, 需要指定删除器 ,所以不能用 std::make_shared()

template <typename T>

shared_ptr<T> make_shared_array(size_t size, const bool bInitZero = false)

{

    //default_delete是STL中的默认删除器

    //return shared_ptr<T>(new T[size]{ 0 }, default_delete<T[]>());

    shared_ptr<T> p = shared_ptr<T>(new T[size], default_delete<T[]>());

    if (bInitZero && p) {

        for (size_t i = 0; i < size; i++)

            memset((void*)&p.get()[i], 0, sizeof(T));

    }

    return p;

}

//分配不初始化

#define SHARED_ARRAY_PTR(obj_type, size)   make_shared_array<obj_type>(size, false)

//分配且初始化为0

#define SHARED_ARRAY_PTR_INIT(obj_type, size)   make_shared_array<obj_type>(size, true)

//--------------------------------------

void OnQuoteEventHandler(Mt4_stQuoteEventInfo *pInfo, const int nInfoNum, LPVOID param);

void OnQuoteHistoryEventHandler(char *pszSymbolName, const int nPeroid, const int nInfoNum, const Mt4_stRateInfo *pInfos, LPVOID param);

void OnOrderNotifyEventHandler(Mt4_stOrderNotifyEventInfo *pInfo, LPVOID param);

void OnOrderUpdateEventHandler(Mt4_stOrderUpdateEventInfo *pInfo, LPVOID param);

void OnDisConnectEventHandler(LPVOID param);

 

void Test_GetInfo(const int nID);

void Test_GetServerInfos(const int nID);

void Test_GetQuoteHistory(const int nID);

void Test_GetSymbols(const int nID);

void Test_GetOpenOrders(const int nID);

void Test_OrderSend(const int nID);

void Test_GetTradeHistory(const int nID);

void Test_CreatDemoAccount();

void ShowLastErr(const int nID, int nLast = 1);

BOOL ShowLog(char *pszFmt, ...);

string DatetimeToString(time_t time);


INT64 nQuoteCount = 0;

//-----------------------------

int main()

{

    int nID = MT4API_Create();

    if (nID > 0)

    {

        if (MT4API_Init(nID, "ForexTimeFXTM-Standard-demo", 12285215, "e1fhqcq", "47.52.112.101", 450, 0, 0))

        {

            MT4API_SetQuoteEventHandler(nID, OnQuoteEventHandler, nullptr);

            MT4API_SetQuoteHistoryEventHandler(nID, OnQuoteHistoryEventHandler, nullptr);

            MT4API_SetOrderNotifyEventHandler(nID, OnOrderNotifyEventHandler, nullptr);

            MT4API_SetOrderUpdateEventHandler(nID, OnOrderUpdateEventHandler, nullptr);

            MT4API_SetDisconnectEventHandler(nID, OnDisConnectEventHandler, &nID);

 

            if (MT4API_Connect(nID))

            {

                MT4API_Subscribe(nID, "EURUSD");

                MT4API_Subscribe(nID, "EURJPY");

                MT4API_Subscribe(nID, "USDJPY");

                //需要测试,请去掉相关注释

        /*      Test_GetInfo(nID);

                Test_GetServerInfos(nID);

                Test_OrderSend(nID);

                Test_GetOpenOrders(nID);

                Test_GetTradeHistory(nID);*/

            }

            else

                ShowLastErr(nID);

        }

        else

            ShowLastErr(nID);

        //-----------

        while (true)

        {

            Sleep(3000);

        }

        MT4API_Destory(nID);

    }

    else

    {

        printf("MT4API_Create Failed! \r\n");

    }

}

//---------------

void OnQuoteEventHandler(Mt4_stQuoteEventInfo *pInfo, const int nInfoNum, LPVOID param)

{

    nQuoteCount++;

    if (!pInfo || nInfoNum <= 0)

        return;

    for (int i = 0; i < nInfoNum; i++)

    {

        switch (pInfo[i].nDigits)

        {

        case 0:

            ShowLog("%s - bid:%d ask:%d  time:%d - %s", pInfo[i].szSymbol, (int)pInfo[i].fBid, (int)pInfo[i].fAsk, pInfo[i].nTime, DatetimeToString(pInfo[i].nTime).c_str());

            break;

        case 1:

            ShowLog("%s - bid:%.1f ask:%.1f  time:%d - %s", pInfo[i].szSymbol, pInfo[i].fBid, pInfo[i].fAsk, pInfo[i].nTime, DatetimeToString(pInfo[i].nTime).c_str());

            break;

        case 2:

            ShowLog("%s - bid:%.2f ask:%.2f  time:%d - %s", pInfo[i].szSymbol, pInfo[i].fBid, pInfo[i].fAsk, pInfo[i].nTime, DatetimeToString(pInfo[i].nTime).c_str());

            break;

        case 3:

            ShowLog("%s - bid:%.3f ask:%.3f  time:%d - %s", pInfo[i].szSymbol, pInfo[i].fBid, pInfo[i].fAsk, pInfo[i].nTime, DatetimeToString(pInfo[i].nTime).c_str());

            break;

        case 4:

            ShowLog("%s - bid:%.4f ask:%.4f  time:%d - %s", pInfo[i].szSymbol, pInfo[i].fBid, pInfo[i].fAsk, pInfo[i].nTime, DatetimeToString(pInfo[i].nTime).c_str());

            break;

        case 5:

            ShowLog("%s - bid:%.5f ask:%.5f  time:%d - %s", pInfo[i].szSymbol, pInfo[i].fBid, pInfo[i].fAsk, pInfo[i].nTime, DatetimeToString(pInfo[i].nTime).c_str());

            break;

        case 6:

            ShowLog("%s - bid:%.6f ask:%.6f  time:%d - %s", pInfo[i].szSymbol, pInfo[i].fBid, pInfo[i].fAsk, pInfo[i].nTime, DatetimeToString(pInfo[i].nTime).c_str());

            break;

        case 7:

            ShowLog("%s - bid:%.7f ask:%.7f  time:%d - %s", pInfo[i].szSymbol, pInfo[i].fBid, pInfo[i].fAsk, pInfo[i].nTime, DatetimeToString(pInfo[i].nTime).c_str());

            break;

        case 8:

            ShowLog("%s - bid:%.8f ask:%.8f  time:%d - %s", pInfo[i].szSymbol, pInfo[i].fBid, pInfo[i].fAsk, pInfo[i].nTime, DatetimeToString(pInfo[i].nTime).c_str());

            break;

        }

    }

}

 

void OnQuoteHistoryEventHandler(char *pszSymbolName, const int nPeroid, const int nInfoNum, const Mt4_stRateInfo *pInfos, LPVOID param)

{

    if (!pszSymbolName || nInfoNum <= 0 || !pInfos)

        return;

    ShowLog("*** OnQuoteHistoryEvent *** ");

    ShowLog("%s - nPeroid:%d   nInfoNum:%d\r\n", pszSymbolName, nPeroid, nInfoNum);

    for (int i = 0; i < nInfoNum; i++)

    {

        ShowLog("[%d] - open:%d close:%d  high:%d low:%d vol:%f ctm:%d- %s ", i, pInfos[i].open, pInfos[i].close, pInfos[i].high, pInfos[i].low, pInfos[i].vol, pInfos[i].ctm, DatetimeToString(pInfos[i].ctm).c_str());

    }

}

 

void OnOrderNotifyEventHandler(Mt4_stOrderNotifyEventInfo *pInfo, LPVOID param)

{

    if (!pInfo)

        return;

    ShowLog("*** OnOrderNotifyEvent *** ");

    ShowLog("OrderID:%d, nReqId:%d,  nStatus:%d, OrderProgressType:%d",

        pInfo->tr.order,

        pInfo->nReqId,

        pInfo->nStatus,

        pInfo->emType);

}

 

void OnOrderUpdateEventHandler(Mt4_stOrderUpdateEventInfo *pInfo, LPVOID param)

{

    if (!pInfo)

        return;

    ShowLog("*** OnOrderUpdateEvent *** ");

    ShowLog("OrderID:%d, nUpdateAction:%d,  fBalance:%f, fCredit:%f ",

        pInfo->tr.order,

        pInfo->emUpdateAction,

        pInfo->fBalance,

        pInfo->fCredit);

}

 

void OnDisConnectEventHandler(LPVOID param)

{

    int *pId = (int*)param;

    int nID = *pId;

    ShowLog("*** OnDisConnectEvent *** ");

    ShowLastErr(nID);

}


void Test_CreatDemoAccount()

{

    Mt4_stDemoAccount account;

    bool bRet = MT4API_CreateDemoAccount(

        "39.108.188.211",

        443,

        100,

        10000,

        "225",

        "demoforex",

        "china",

        "guangzhou",

        "state",

        "511430",

        "ADDRESS",

        "13751881354",

        "www@163.com",

        "compamy",

        account);

    int k = 0;

    if (bRet)

        ShowLog("CreatDemoAccount: user:%d  password:%s, InvPassword:%s", account.nLogin, account.szPassword, account.szInvPass);

    else

        ShowLastErr(0);

 

    return void(0);

}

 

void Test_GetInfo(const int nID)

{

    ShowLog("--------------------------------");

    ShowLog("demo account: %s", MT4API_IsDemoAccount(nID) ? "yes" : "no");

    unsigned int nUser = 0;

    if (!MT4API_GetUser(nID, nUser))

        ShowLastErr(nID);

    else

        ShowLog("nUser:%d", nUser);

 

    char szName[64] = { 0 };

    if (!MT4API_GetUserName(nID, szName, 64))

        ShowLastErr(nID);

    else

        ShowLog("UserName:%s", szName);

 

    //int nSrvTime = 0;

    //if (!MT4API_GetServerTime(nID, nSrvTime))

    //  ShowLastErr(nID);

    //else

    //  ShowLog("ServerTime:%d %s", nSrvTime, DatetimeToString(nSrvTime).c_str());

 

    unsigned  short nServerBuild = 0;

    if (!MT4API_GetServerBuild(nID, nServerBuild))

        ShowLastErr(nID);

    else

        ShowLog("nServerBuild:%d", nServerBuild);

 

    int nLeverage = 0;

    if (!MT4API_GetLeverage(nID, nLeverage))

        ShowLastErr(nID);

    else

        ShowLog("nLeverage:%d", nLeverage);

 

 

    double fBalance = 0;

    if (!MT4API_GetBalance(nID, fBalance))

        ShowLastErr(nID);

    else

        ShowLog("fBalance:%f", fBalance);

 

    double fCredit = 0;

    if (!MT4API_GetCredit(nID, fCredit))

        ShowLastErr(nID);

    else

        ShowLog("fCredit:%f", fCredit);

 

    double fMargin = 0;

    if (!MT4API_GetMargin(nID, fMargin))

        ShowLastErr(nID);

    else

        ShowLog("fMargin:%f", fMargin);

 

    double fFreeMargin = 0;

    if (!MT4API_GetFreeMargin(nID, fFreeMargin))

        ShowLastErr(nID);

    else

        ShowLog("fFreeMargin:%f", fFreeMargin);

 

    double fProfit = 0;

    if (!MT4API_GetProfit(nID, fProfit))

        ShowLastErr(nID);

    else

        ShowLog("fProfit:%f", fProfit);

 

    double fEquity = 0;

    if (!MT4API_GetEquity(nID, fEquity))

        ShowLastErr(nID);

    else

        ShowLog("fEquity:%f", fEquity);

 

    if (!MT4API_GetMoneyInfo(nID, fBalance, fCredit, fMargin, fFreeMargin, fEquity, fProfit))

        ShowLastErr(nID);

    else

        ShowLog(" -----------------\n fBalance:%f \n fCredit:%f \n fMargin:%f \n fFreeMargin:%f \n fEquity:%f \n fProfit:%f",

            fBalance,

            fCredit,

            fMargin,

            fFreeMargin,

            fEquity,

            fProfit);

 

    ShowLog("--------------------------------");

}

 

void Test_GetServerInfos(const int nID)

{

    int nSrvInfoCount = 0;

    if (MT4API_GetSeverInfoCount(nID, nSrvInfoCount))

    {

        auto pSrv = SHARED_ARRAY_PTR_INIT(Mt4_stConDataServer, nSrvInfoCount);

        if (MT4API_GetSeverInfos(nID, pSrv.get(), nSrvInfoCount))

        {

            for (int i = 0; i < nSrvInfoCount; i++)

            {

                ShowLog("%d: Srv:%s desc:%s", i, pSrv.get()[i].server, pSrv.get()[i].description);

            }

        }

    }

}

 

void Test_GetQuoteHistory(const int nID)

{

    if (MT4API_DownloadQuoteHistory(nID, "EURJPY", 1, time(0), 100))

    {

    }

    else

        ShowLastErr(nID);

}

void Test_GetSymbols(const int nID)

{

    int nSymbolCount = 0;

    if (MT4API_GetSymbolsCount(nID, nSymbolCount))

    {

        if (nSymbolCount > 0)

        {

            auto pSymbols = SHARED_ARRAY_PTR_INIT(Mt4_stConSymbol, nSymbolCount);

            bool bGet = MT4API_GetSymbolsInfo(nID, pSymbols.get(), nSymbolCount);

            for (int i = 0; i < nSymbolCount; i++) {

                ShowLog("%d : %s", i, pSymbols.get()[i].symbol);

                MT4API_Subscribe(nID, pSymbols.get()[i].symbol);

            }

            int k = 0;

        }

    }

    else

        ShowLastErr(nID);

}

 

void Test_GetOpenOrders(const int nID)

{

    int nOpenOrderCount = 0;

    if (MT4API_GetOpenOrdersCount(nID, nOpenOrderCount))

    {

        if (nOpenOrderCount > 0)

        {

            auto pOpenOrders = SHARED_ARRAY_PTR_INIT(Mt4_stTradeRecord, nOpenOrderCount);

            bool bGet = MT4API_GetOpenOrders(nID, pOpenOrders.get(), nOpenOrderCount);

            //528544433  200

            for (int i = nOpenOrderCount - 1; i >= 0; i--)

            {

                Mt4_stTradeRecord *pTr = pOpenOrders.get();

                Mt4_stTradeRecord tr;

   

                ShowLog("OpenOrders[%d]; order:%d, open_time:%s", i, pTr[i].order, DatetimeToString(pTr[i].open_time).c_str());

 

                if (pTr[i].cmd == OP_BUY) {

                    Mt4_stQuoteEventInfo info;

                    while (!MT4API_GetQuote(nID, pTr[i].symbol, info))

                        Sleep(1000);

 

                    if (pTr[i].volume == 200)

                        int kk = 0;

                    Mt4_stConSymbol symbol;

                    MT4API_GetSymbolInfo(nID, pTr[i].symbol, symbol);

                    if (!MT4API_OrderClose(nID, pTr[i].symbol, pTr[i].order, (double)pTr[i].volume / (double)100, info.fAsk, 40, tr))

                        ShowLastErr(nID);

 

                }

                else if (pTr[i].cmd == OP_SELL)

                {

                    Mt4_stQuoteEventInfo info;

                    while (!MT4API_GetQuote(nID, pTr[i].symbol, info))

                        Sleep(1000);

                    if (!MT4API_OrderClose(nID, pTr[i].symbol, pTr[i].order, (double)pTr[i].volume / (double)100, info.fBid, 40, tr))

                        ShowLastErr(nID);

                }

                else

                {

                    ShowLog("err open Order: %d", pTr[i].order);

                }

            }

        }

    }

    else

        ShowLastErr(nID);

}

 

void Test_GetTradeHistory(const int nID)

{

    int nTradeHisCount = 0;

    if (MT4API_GetTradeHistoryCount(nID, time(0) - 30 * 24 * 60 * 60, time(0), nTradeHisCount))

    {

        auto pTrades = SHARED_ARRAY_PTR_INIT(Mt4_stTradeRecord, nTradeHisCount);

        if (MT4API_DownloadTradeHistory(nID, pTrades.get(), nTradeHisCount))

        {

            Mt4_stTradeRecord *pTr = pTrades.get();

            for (int i = 0; i < nTradeHisCount; i++)

            {

                ShowLog("CloseOrders[%d]; order:%d, open_time:%s", i, pTr[i].order, DatetimeToString(pTr[i].open_time).c_str());

            }

            int k = 0;

        }

    }

    else

        ShowLastErr(nID);

}

 

void Test_OrderSend(const int nID)

{

    Mt4_stQuoteEventInfo info;

    while (!MT4API_GetQuote(nID, "EURJPY", info))

    {

        Sleep(1000);

    }

    if (MT4API_GetQuote(nID, "EURJPY", info))

    {

        Sleep(1000);

        Mt4_stTradeRecord tr;

        bool bRet = MT4API_OrderSend(nID, "EURJPY", 0, 2, info.fAsk, 1, 0.0, 0.0, "", 1004, time(0) + 24 * 60 * 60, tr);

        //int nReqID = DLLLOADER_MT4::MT4API_OrderSendAsync(nID, "EURJPY", 0, 0.1, info.fAsk, 1, 0.0, 0.0, "", 1004, time(0) + 24 * 60 * 60);

        if (!bRet)

            ShowLastErr(nID);

    }

    else

        ShowLastErr(nID);

}

BOOL ShowLog(char *pszFmt, ...)

{

    if (!pszFmt)

        return FALSE;

 

    BOOL bRet = TRUE;

    va_list argp;

    va_start(argp, pszFmt);

    //--------

    int nMaxBufSize = 4096; //设置最大缓冲区为4096, 超过的则显示日志失败

    int nArgBufSize = 256;

    UINT8pszAargs_buf = new UINT8[nArgBufSize];

    memset(pszAargs_buf, 0, nArgBufSize);

 

    while (true) {

        int nLen = _vsnprintf_s((char *)pszAargs_buf, nArgBufSize, _TRUNCATE, (const char *)pszFmt, argp);

        if (nLen < 0 || nLen >= nArgBufSize - 1) {

            nArgBufSize += 256;

            if (nArgBufSize >= nMaxBufSize) {

                bRet = FALSE;

                break;

            }

 

            if (pszAargs_buf)

                delete[] pszAargs_buf;

            pszAargs_buf = new UINT8[nArgBufSize];

            memset(pszAargs_buf, 0, nArgBufSize);

        }

        else

            break;

    }

 

    if (!bRet) {

        if (pszAargs_buf)

            delete[] pszAargs_buf;

        pszAargs_buf = NULL;

 

        return bRet;

    }

 

    //

    //日志时间

    SYSTEMTIME sysTime;

    GetLocalTime(&sysTime);

    UINT8 szTime[128] = { 0 };

    int nLen = _snprintf_s((char *)szTime, 128, _TRUNCATE, "[%.4d-%.2d-%.2d %.2d:%.2d:%.2d %.3d]",

        sysTime.wYear,

        sysTime.wMonth,

        sysTime.wDay,

        sysTime.wHour,

        sysTime.wMinute,

        sysTime.wSecond,

        sysTime.wMilliseconds);

 

    // 写入日志内容 

    int nLogBufSize = nArgBufSize + 256;

    UINT8pszLogContent = new UINT8[nLogBufSize];

    memset(pszLogContent, 0, nLogBufSize);

 

 

    while (true) {

        int nLen = _snprintf_s((char *)pszLogContent, nLogBufSize, _TRUNCATE, "%s %s\n", szTime, pszAargs_buf);

        if (nLen < 0 || nLen >= nLogBufSize - 1) {

            nLogBufSize += 256;

            if (nLogBufSize >= nMaxBufSize) {

                bRet = FALSE;

                break;

            }

 

            if (pszLogContent)

                delete[] pszLogContent;

            pszLogContent = new UINT8[nLogBufSize];

            memset(pszLogContent, 0, nLogBufSize);

        }

        else

            break;

    }

 

    //------------------------

    //构造日志完成,进行输出

    if (pszLogContent) {

        OutputDebugStringA((char*)pszLogContent);

        cout << pszLogContent << endl;

    }

    //---------------------------

 

    if (pszLogContent)

        delete[]pszLogContent;

    pszLogContent = NULL;

 

    if (pszAargs_buf)

        delete[] pszAargs_buf;

    pszAargs_buf = NULL;

    //-----------------

    va_end(argp);

 

 

    return bRet;

}

 

string DatetimeToString(time_t time)

{

    tm tm_;

    localtime_s(&tm_, &time);                // 将time_t格式转换为tm结构体

    int year = 0, month = 0, day = 0, hour = 0, minute = 0, second = 0;// 定义时间的各个int临时变量。

    year = tm_.tm_year + 1900;                // 临时变量,年,由于tm结构体存储的是从1900年开始的时间,所以临时变量int为tm_year加上1900。

    month = tm_.tm_mon + 1;                   // 临时变量,月,由于tm结构体的月份存储范围为0-11,所以临时变量int为tm_mon加上1。

    day = tm_.tm_mday;                        // 临时变量,日。

    hour = tm_.tm_hour;                       // 临时变量,时。

    minute = tm_.tm_min;                      // 临时变量,分。

    second = tm_.tm_sec;                      // 临时变量,秒。

    char yearStr[5], monthStr[3], dayStr[3], hourStr[3], minuteStr[3], secondStr[3];// 定义时间的各个char*变量。

    sprintf_s(yearStr, "%d", year);              // 年。

    sprintf_s(monthStr, "%d", month);            // 月。

    sprintf_s(dayStr, "%d", day);                // 日。

    sprintf_s(hourStr, "%d", hour);              // 时。

    sprintf_s(minuteStr, "%d", minute);          // 分。

    if (minuteStr[1] == '\0')                  // 如果分为一位,如5,则需要转换字符串为两位,如05。

    {

        minuteStr[2] = '\0';

        minuteStr[1] = minuteStr[0];

        minuteStr[0] = '0';

    }

    sprintf_s(secondStr, "%d", second);          // 秒。

    if (secondStr[1] == '\0')                  // 如果秒为一位,如5,则需要转换字符串为两位,如05。

    {

        secondStr[2] = '\0';

        secondStr[1] = secondStr[0];

        secondStr[0] = '0';

    }

    char s[20];                                // 定义总日期时间char*变量。

    sprintf_s(s, "%s-%s-%s %s:%s:%s", yearStr, monthStr, dayStr, hourStr, minuteStr, secondStr);// 将年月日时分秒合并。

    string str(s);                             // 定义string变量,并将总日期时间char*变量作为构造函数的参数传入。

    return str;                                // 返回转换日期时间后的string变量。

}



    联系我们
  • 地址:广东省广州市番禺区南村镇万惠一路96号
  • 邮箱:support@gzhuichou.com
  • 外汇MT4技术交流QQ群:712830563
Copyright © 2019-2020 广州汇酬信息科技有限公司 All rights reserved.
粤ICP备19062735号-1