65.9K
CodeProject 正在变化。 阅读更多。
Home

将 SQL Server 2008 与 Metatrader 5 集成

starIconstarIconstarIcon
emptyStarIcon
starIcon
emptyStarIcon

3.21/5 (5投票s)

2010年3月4日

CPOL

3分钟阅读

viewsIcon

52391

downloadIcon

849

调用外部 ADO.NET DLL,以便在 Meta Trader 平台内连接 SQL Server 数据库并执行查询。

引言

只有一篇经过同行评审的文章涉及 SQL 与 Metatrader 的集成,作者是Yuriv Zaytsev,大约 8 年前撰写,最初使用俄语编写,并使用翻译工具自动翻译成英文。该示例非常难以执行,需要创建一个特定的数据库,并使用特定的登录凭据和角色,否则无法获得成功的结果。文章本身可以在这里找到。Zaytsev使用了以下工具:

  • Microsoft SQL SERVER 2000 Developer - BASE
  • VISUAL C++ 6.0 SP5 - 用于创建 DLL “YZMSSQLExpertSample.dll
  • MDAC 7

此外,他的示例特定于一个数据库,您必须创建它,以及您必须硬编码的连接字符串。他的文章也是在 Meta Trader 5 出现之前写的,我在使用他的代码从 MQL4 升级到 MQL5 时遇到了相当多的兼容性问题。

文章的代码示例不容易升级到 Visual Studio .NET 2003 或 2008 版本,因此,本文试图改进以上所有问题,提供更无缝的实现背景。

DLL 也已修改为接受连接字符串作为参数,从而无需为连接字符串更改而不断重建 DLL,并且还可以使用其ExecuteScalar方法接受整个 SQL 语句作为输入。

背景

对于试图将较新的 Metatrader 5 终端与 SQL Server 2008 集成以接收和存储数据库中商品和货币实时流数据,以构建相关交易系统的人来说,本文非常相关。

Using the Code

代码分为三个部分:

第一部分:使用DLL_Creator.zip VS 2008 DLL 项目生成 DLL。(此处无需更改)。但是,您必须确保您的MSADO15.dll位于“C:\Program Files\Common Files\System\ADO\msado15.dll”位置。如果不是,您可以手动将其放置在那里,或者使用正确的路径重建 DLL 项目。

第二部分:将生成的 DLL 导入到Libraries文件夹。在我的电脑上,此位置是C:\Users\Administrator\AppData\Roaming\MetaQuotes\Terminal\
5D2A9C702A29311ED87B6AD8A346121B\MQL5\Libraries\

但为了确保,在 MT5 上,您可以点击文件 -> 打开数据文件夹,然后点击库并将 DLL 文件放在里面。

注意:请确保选中“允许 DLL 导入”框,如下所示。
dll.JPG

第三部分:创建一个新的 MQL5 脚本,其中仅包含引用 DLL 的以下代码。

#import "ExpertSample.dll"
   string ExecuteScalar(string strSQL, string strCNN);   
#import  

int OnStart()
{     
   string temp = SymbolInfoDouble("EURUSD",SYMBOL_BID);
   ExecuteScalar("INSERT INTO [indicator_data]([indicator_id] ,[value]) 
	VALUES (2, "+temp +");", "Provider=SQLOLEDB.1;User ID=sa;
	Password=********;Persist Security Info=True;
	Initial Catalog=Finance;Data Source=KMS\\SQL2008" );   
   return(0);
} 

关注点

我花了两天时间才弄明白为什么从 MQL5 传递字符串到 C++ 只传递了第一个字符。我在mql5 传递 DLL 变量的能力中发布了此问题作为一个 bug。有人告诉我 MQL5 将字符串处理为宽字符或w_char。我将其接收为char*而不是w_char *,这使得一切变得不同。代码如下所示。

void p(char *s)
{
    MessageBox(NULL, s,(LPCSTR)L"no error",MB_ICONWARNING | 
	MB_CANCELTRYCONTINUE | MB_DEFBUTTON2 );
}

MT4_EXPFUNC char * __stdcall ExecuteScalar(wchar_t *wstr, wchar_t *wcnn)
  {              
    char* sql = new char[wcslen(wstr) + 1];
    wcstombs( sql, wstr, wcslen(wstr) );
    sql[wcslen(wstr)] = '\0';
    //p(sql);
    p(sql);
    char *cnn = new char[wcslen(wcnn) + 1];
    wcstombs(cnn, wcnn, wcslen(wcnn) );
    cnn[wcslen(wcnn)] = '\0';
    //p(cnn);

    HRESULT hr = S_OK;
    char tmpChar[255];
    try {
        // Define string variables.
        
        //_bstr_t strCnn("Provider=SQLOLEDB.1;User ID=sa;
        //Password=Admin1234;Persist Security Info=True;
        //Initial Catalog=Finance;Data Source=KMS\\SQL2008");
        _bstr_t strCnn(cnn);

        ::CoInitialize(NULL);
        _RecordsetPtr pRstAuthors = NULL;
        // Call Create instance to instantiate the Record set
        hr = pRstAuthors.CreateInstance(__uuidof(Recordset));
        if(FAILED(hr))
        {
            ::CoUninitialize();
            p("ERROR: Failed creating record set instance");
            return "ERROR: Failed creating record set instance";
        }

        //Open the Record set for getting records from Author table
        try {
            pRstAuthors->Open(sql,strCnn, adOpenStatic,     adLockReadOnly,adCmdText);
            //int msgboxID2 = MessageBox(NULL,(LPCSTR)L"no errors",
            //(LPCSTR)L"no error",MB_ICONWARNING | 
            //MB_CANCELTRYCONTINUE | MB_DEFBUTTON2 );
        } catch (_com_error & ce1) {
            
            ::CoUninitialize();
            p("Unable to Open SQL Server");
            //int msgboxID = MessageBox(NULL,(LPCSTR)
            //"Resource not available\nDo you want to try again?",
            //(LPCSTR)L"SQL ERror",MB_ICONWARNING | MB_CANCELTRYCONTINUE | 
            //MB_DEFBUTTON2 );
            return "ERROR: Unable to open SQL Server";
        }
        p("SQL Opened");

        try {
            pRstAuthors->MoveFirst();
        } catch(_com_error) {
            ::CoUninitialize();
            return ""; //empty data
        }

        //Loop through the Record set
        if (!pRstAuthors->EndOfFile)
        {
            _variant_t tmpvariant;
            //Get the first column value
            tmpvariant = pRstAuthors->GetFields()->GetItem((long)0)->GetValue();
            strcpy(tmpChar,(_bstr_t)tmpvariant);
        }

        if (pRstAuthors->State == adStateOpen)
            pRstAuthors->Close();

        pRstAuthors = NULL;
        ::CoUninitialize();
    }
    catch(_com_error & ce)
    {
        //_bstr_t strError = ce.ErrorMessage;
        ::CoUninitialize();
        p("ERROR: Failed to get data.");
        return "ERROR: Failed to get data.";
    }

    return tmpChar;
  }  

结论

要运行此程序,您只需要一个数据库进行测试,以及一个可在MetaTrader5获得的 MQL 5 平台。

您还需要VS2008(其 express 版本是免费的),如果您想更改 DLL 文件。

这是基于快速实现的概念,实现起来应该很容易。祝您好运,随时发表评论,我会尽力回复。

历史

  • 2010 年 3 月 4 日:初始发布
© . All rights reserved.