Русский 中文 Español Deutsch 日本語 Português
Integrating MetaTrader 4  Client Terminal with MS SQL Server

Integrating MetaTrader 4 Client Terminal with MS SQL Server

MetaTrader 4Examples | 24 June 2008, 07:17
16 590 8
Yuriy Zaytsev
Yuriy Zaytsev

Introduction

The use of integrations with other products offers additional challenge in trading.

There can be many usages thereof, so I will give some of them below.

You can collect ticks and pass them to MS SQL SERVER for further analysis. Having a large tick history, you can collect any period starting from the minimum time slice and up to any non-standard periods. Having real tick quotes, you may debug tick-data dependent strategies known as 'scalpers'.

You can use a store for quick analysis of data taken from other applications, for example, from MS Excel or other third-party software or from you own products.

For example, you can unload the entire history from History Center of the terminal into MS SQL. Then you won't need to store the history in MT4. This will help to relieve the terminal memory.

You can calculate neural networks using quotes stored in MS SQL SERVER: for example, STATISTICA - 7.8 to allow you to download quotes from SQL can be solved in the real-time mode by passing the network signals into MT4.

You can develop your own program in another language and for another symbol, and pass signals using MS SQL SERVER, having left only executing functions for the client terminal and relieving it from serious calculations.


The Following Software Products Were Used for This Project

  • MS SQL SERVER 2000 Developer - BASE
  • VISUAL C++ 6.0 SP5 - to create DLL "YZMSSQLExpertSample.dll"
  • MDAC 7


The minimal set to be installed:

1 MS SQL SERVER 2000 Developer
2 MDAC 7

I debugged the program using MDAC 7. However, it is possible that everything works ok on some older versions. If you aren't going to compile the DLL, you needn't to install or have Visual C++ 6.0 installed. You can use a ready DLL. However, I hardwired the user name in it, the name of DSN, and connections. So you will have to repeat all above-listed in your version of the program. I won't describe here how to install MS SQL SERVER or Visual C++ 6.0, these things are outside the scope of this specific article.

After the necessary software products have been installed, we should create a DSN:

dsn=MT4_SQL_BASE;", "yuraz", "qwerty"


Example of Tick Receiving in MS SQL

All experiments were conducted with MS SQL SERVER 2000 Developer. In Visual C++ 6.0, YZMSSQLExpertSample.DLL was created using the method of accessing to MS SQL via ADO. MDAC 7 or MDAC 8 must be installed. I will only describe the examples of how to create procedures and tables. The minimal set of what we have to create in MS SQL are the base, tables and procedures. Let's consider the table and procedures of working with tick quotes. You can add some other functions, if you want.


It is necessary to create a base and tables in MS SQL. I created a new base named MT4TRADE. Then we should create tables in it:

MT4TICK - Table of Ticks

//-----------------------------------------------------------------------------------
//
//  Structure of MT4TICK Base
//
//    idc             - formed automatically, unique number of record
//    ServerDateTime  - Filled out automatically, when adding a record
//                        Server local time - time when the quote was placed in the table 
//                        (it doesn't have anything in common with the date and time passed by MT4)
//                        it is the time counted by the server itself - it will be the same as the time
//                        of the machine, on which the server has been launched. 
//--- 
//    iDateTime       - date and time in MT4 format, passed from MT4
//    sSymbol         - symbol
//    cAsk            - quote Ask
//    cBid            - quote Bid
//
CREATE TABLE [dbo].[MT4TICK] (
    [idc] [bigint] IDENTITY (1, 1) NOT NULL ,
    [ServerDateTime] [datetime] NULL ,
    [iDateTime] [bigint] NULL ,
    [sSymbol] [char] (6) COLLATE SQL_Latin1_General_CP1251_CI_AS NULL ,
    [cAsk] [numeric](18, 4) NULL ,
    [cBid] [numeric](18, 4) NULL 
) ON [PRIMARY]
GO
 
--- Include automated filling out the ServerDateTime field with the date and time of server MS SQL
ALTER TABLE [dbo].[MT4TICK] ADD 
    CONSTRAINT [DF_MT4TICK_ServerDateTime] DEFAULT (getdate()) FOR [ServerDateTime]
GO

Below is how the tick receiving and tabulating procedure appears:

// 
//    @RetCode int out          --- used for returning
//   ,@psSymbol char(6)         --- symbol
//   ,@piDateTime  bigint       --- date and time of tick arrival
//   ,@pdAsk  float             --- Ask 
//   ,@pdBid  float             --- Bid
//  
//   The procedure just returns 0 
//     if we analyze the code of returning to MQL4, we can see that the quote has reached the procedure and has been tabulated
//     
//
CREATE PROCEDURE dbo.YZ_MT4_TICK
    @RetCode int out          
   ,@psSymbol char(6)
   ,@piDateTime  bigint
   ,@pdAsk  float
   ,@pdBid  float
AS
insert into  MT4TICK   ( sSymbol, iDateTime, cAsk, cBid   )  values  ( @psSymbol , @piDateTime,  @pdAsk ,  @pdBid  )
select @RetCode=0
return @RetCode

We can see from the above description what procedures and for what purposes are used.

@RetCode - it doesn't bear any functionality when being passed from DLL, it serves for receiving the termination code only.

The MS SQL SERVER setup is finished. A script for creating a standard configuration is attached to this article.


Let's Fantasize: Possible Solutions and Pluses

We can create a data storage and place/extract information from it. In this manner, we can relieve the MT 4 Client Terminal from the necessity to store quotes history. Now the quotes history is stored on MS SQL Server and we can operate with this information, extract it sooner and export it to other applications. We can use the data to be analyzed in NEURAL packages, most of which can work with SQL storages.

In the real time, the terminal may continue forming signals from indicators passing them to the storage and fixing them in this manner. An external application can extract the signal and the history in the real time, analyze them and form signals fixing the execution and the storage of the log on MS SQL Server, and send them to the terminal to execute.

Thus, we obtain integration and functional distribution among applications involved in an automated trading complex.

Well, if there is no need anymore to store historical quotes, we can set it up in the following way. Set the minimum bars in Tools>Options>Charts, for example, for 5000. The terminal starts working faster since it doesn't need to allocate memory for large history.





Source Texts

DLL Code:

//+------------------------------------------------------------------+
//|                                              Sample DLL for MQL4 |
//|                 Copyright c 2004-2008, MetaQuotes Software Corp. |
//|                                        https://www.metaquotes.net |
//+------------------------------------------------------------------+
 
//+------------------------------------------------------------------+
//
//  YURAZ 2008  YZMSSQLExpertSample
//
//  Example DLL Integrating  MT4 with MS SQL 2000
//
//  ADO  MS SQL SERVER
//
//  software used
//
//  VISUAL C++ 6 , SP5 ,  MDAC 7 ,  MS SQL2000 + SP4
//
//+------------------------------------------------------------------+
  
#define WIN32_LEAN_AND_MEAN  // Exclude rarely-used stuff from Windows headers
#include <windows.h>
#include <stdlib.h>
#include <stdio.h>
//----
#define MT4_EXPFUNC __declspec(dllexport)
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
#pragma pack(push,1)
 
struct RateInfo
  {
   unsigned int      ctm;
   double            open;
   double            low;
   double            high;
   double            close;
   double            vol;
   double            vol1;
   double            vol2;
   double            vol3;
   double            vol4;
   double            vol5;
 
  };
 
#pragma pack(pop)
   
struct MqlStr
  {
   int               len;
   char             *string;
  };
  
static int CompareMqlStr(const void *left,const void *right);
   
static int SQLexecProcedure( char *nprc );
static int SQLexecProcedureSignal( char *sSymbol, char* sProcedure );
// static int _YZSQLsqlstrinsql( char *Symbol , unsigned int DateTime , double Ask, double Bid, char *NamePrc );
static int _YZSQLprocedure  ( char *sSymbol, unsigned int pDateTime, double Ask, double Bid, char *NamePrc );
static int _YZSQLprocedureHISTORYPut(char *Symbol,unsigned int Period, unsigned int DateTime,double Open,
                        double High,double  Low, double Close ,double Volume, unsigned int Bar ,char *Procedure);
 
                                                                                                             
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
BOOL APIENTRY DllMain(HANDLE hModule,DWORD ul_reason_for_call,LPVOID lpReserved)
  {
//----
   switch(ul_reason_for_call)
     {
      case DLL_PROCESS_ATTACH:
      case DLL_THREAD_ATTACH:
      case DLL_THREAD_DETACH:
      case DLL_PROCESS_DETACH:
         break;
     }
//----
   return(TRUE);
  }
 
 // place ticks in MS SQL
 // call the procedure as an SQL line passing parameters   "exec YZ_MT4_TICK ?,?,?,?"
/*
  MT4_EXPFUNC int  __stdcall SQLsqlstringTickPut(char *Symbol,unsigned int DateTime,double Ask,double Bid,char *sSQLstring)
 {
    int ccc =  _YZSQLsqlstrinsql( Symbol  , DateTime ,  Ask , Bid  , sSQLstring  );
    return(ccc);
 }
*/
 
 // call as a procedure passing parameters
  MT4_EXPFUNC int  __stdcall SQLProcedureTickPut(char *Symbol,unsigned int DateTime,double Ask,double Bid,char *Procedure)
 {
    int ccc =  _YZSQLprocedure( Symbol  , DateTime ,  Ask , Bid  ,Procedure );
    return(ccc);
 }
 
 // place a specific candlestick in MS SQL history
 MT4_EXPFUNC int  __stdcall SQLProcedureHistoryPut(char *Symbol,unsigned int Period , unsigned int DateTime,
                double Open,double High,double  Low, double Close ,double Volume,unsigned int Bar ,char *Procedure)
 {
    int ccc  =  _YZSQLprocedureHISTORYPut(Symbol,Period,DateTime,Open,High,Low,Close,Volume,Bar,Procedure);
    return(ccc);
 }
 
 
 // call procedure sProcedure
 // 
 // return -1 error
 //
 MT4_EXPFUNC int  __stdcall SQLProcedureGetInt(char *sProcedure)
 {
        int Ret =    SQLexecProcedure( sProcedure );
     return((int)Ret);
 }
 
 
 MT4_EXPFUNC int  __stdcall SQLProcedureGetSignal  (char *sSymbol, char *sProcedure)
 {
     
     int Ret =    SQLexecProcedureSignal( sSymbol, sProcedure );
     return((int)Ret);
 }
  
//////////////////////////////////
#include "stdafx.h"
#include <stdio.h>
#import "C:\Program Files\Common Files\System\ado\msado20.tlb" \
        rename("EOF","ADOEOF") rename("BOF","ADOBOF")
 
using namespace ADODB;
  
inline void TESTHR(HRESULT x) { if FAILED(x) _com_issue_error(x); };
 
// procedure call method
int _YZSQLprocedure( char *sSymbol, unsigned int pDateTime, double Ask, double Bid,   char *NamePrc )
{
  
   HRESULT hr = S_OK;
   _CommandPtr pCmd = NULL;
   _ConnectionPtr pConnection = NULL;
   _bstr_t strMessage, strAuthorID;
 
       ::CoInitialize(NULL);
 
   long codRet = -1;
 
   try {
      
      _ParameterPtr Par1;
      _ParameterPtr Par2;
      _ParameterPtr Par3;
      _ParameterPtr Par4;
      _ParameterPtr Par5;
 
      TESTHR(pConnection.CreateInstance(__uuidof(Connection)));
      hr = pConnection->Open("dsn=MT4_SQL_BASE;", "yuraz", "qwerty", adConnectUnspecified);
      pConnection->CursorLocation = adUseClient;
      TESTHR(pCmd.CreateInstance(__uuidof(Command)));
      pCmd->CommandText = NamePrc;  // procedure name
      pCmd->CommandType = adCmdStoredProc;
     
      Par1 = pCmd->CreateParameter( _bstr_t("@P1"), adInteger,   adParamOutput,0,    codRet );
      pCmd->Parameters->Append( Par1 );
      Par1 = pCmd->CreateParameter("@psSymbol",adChar, adParamInput, strlen(sSymbol) ,sSymbol );
         pCmd->Parameters->Append(Par1);
      Par2 = pCmd->CreateParameter("@piDateTime", adDouble , adParamInput, sizeof(double) ,  (double)pDateTime );
      pCmd->Parameters->Append(Par2);
      Par3 = pCmd->CreateParameter("@pdAsk", adDouble, adParamInput, 4, Ask );
      pCmd->Parameters->Append(Par3);
      Par4 = pCmd->CreateParameter("@pdBid", adDouble, adParamInput, 4, Bid );
      pCmd->Parameters->Append(Par4);
 
      
      pCmd->ActiveConnection = pConnection;
      int hr = pCmd->Execute( 0, 0, adCmdStoredProc );
      if( FAILED(hr) )
      {
                codRet = -1;
      }
      else
      {
         Par1 = pCmd->Parameters->GetItem(_bstr_t("@P1"));     // obtain from the procedure
         codRet = Par1->GetValue();
      }
   }
   catch(_com_error  ) {
       //
       // if necessary, process the execution error
          //
       codRet = -1;
 
   }
   if (pConnection)
      if (pConnection->State == adStateOpen)
         pConnection->Close();
 
   ::CoUninitialize();
    return((int)codRet);
}
 
 
 
// place in history Symbol , Period . DateTime, Open , High , Low , Close , Value , Bar
int _YZSQLprocedureHISTORYPut(char *pSymbol,unsigned int pPeriod, unsigned int pDateTime,double pOpen,double pHigh,
                                        double  pLow, double pClose ,double pVolume, unsigned int pBar ,char *pProcedure )
{
 
 
        HRESULT hr = S_OK;
   _CommandPtr pCmd = NULL;
   _ConnectionPtr pConnection = NULL;
   _bstr_t strMessage, strAuthorID;
 
       ::CoInitialize(NULL);
 
   long codRet = -1;
 
   try {
 
      _ParameterPtr ParReturn; // 
      _ParameterPtr Par1; // SYMBOL
      _ParameterPtr Par2; // PERIOD
      _ParameterPtr Par3; // DATETIME
      _ParameterPtr Par4; // OPEN
      _ParameterPtr Par5; // HIGH
      _ParameterPtr Par6; // LOW
      _ParameterPtr Par7; // CLOSE
      _ParameterPtr Par8; // VOLUME
      _ParameterPtr Par9; // BAR
 
 
      TESTHR(pConnection.CreateInstance(__uuidof(Connection)));
      hr = pConnection->Open("dsn=MT4_SQL_BASE;", "yuraz", "qwerty", adConnectUnspecified);
      pConnection->CursorLocation = adUseClient;
      TESTHR(pCmd.CreateInstance(__uuidof(Command)));
      pCmd->CommandText = pProcedure;  // procedure name
      pCmd->CommandType = adCmdStoredProc;
     
      ParReturn = pCmd->CreateParameter( _bstr_t("@P1"), adInteger,   adParamOutput,0,    codRet );
      pCmd->Parameters->Append( ParReturn );
 
      Par1 = pCmd->CreateParameter("@psSymbol",adChar, adParamInput, strlen(pSymbol) ,pSymbol );
         pCmd->Parameters->Append(Par1);
 
      Par2 = pCmd->CreateParameter("@piDateTime", adDouble , adParamInput, sizeof(double) ,  (double)pPeriod );
      pCmd->Parameters->Append(Par2);
 
      Par3 = pCmd->CreateParameter("@piDateTime", adDouble , adParamInput, sizeof(double) ,  (double)pDateTime );
      pCmd->Parameters->Append(Par3);
 
      Par4 = pCmd->CreateParameter("@pdOpen", adDouble, adParamInput, 4, pOpen );
      pCmd->Parameters->Append(Par4);
 
      Par5 = pCmd->CreateParameter("@pdHigh", adDouble, adParamInput, 4, pHigh );
      pCmd->Parameters->Append(Par5);
 
      Par6 = pCmd->CreateParameter("@pdLow", adDouble, adParamInput, 4, pLow );
      pCmd->Parameters->Append(Par6);
 
      Par7 = pCmd->CreateParameter("@pdClose", adDouble, adParamInput, 4, pClose );
      pCmd->Parameters->Append(Par7);
      
      Par8 = pCmd->CreateParameter("@pdVolume", adDouble, adParamInput, 4, pVolume );
      pCmd->Parameters->Append(Par8);
 
      Par9 = pCmd->CreateParameter("@piBar", adDouble , adParamInput, sizeof(double) ,  (double)pBar );
      pCmd->Parameters->Append(Par9);
 
 
      pCmd->ActiveConnection = pConnection;
      int hr = pCmd->Execute( 0, 0, adCmdStoredProc );
      if( FAILED(hr) )
      {
                codRet = -1;
      }
      else
      {
         ParReturn = pCmd->Parameters->GetItem(_bstr_t("@P1"));     // obtain from the procedure
         codRet = ParReturn->GetValue();
      }
   }
   catch(_com_error  ) {
       //
       // if necessary, process the execution error
          //
       codRet = -1;
 
   }
   if (pConnection)
      if (pConnection->State == adStateOpen)
         pConnection->Close();
 
   ::CoUninitialize();
    return((int)codRet);
}
 
 
//
// return the value returned by the procedure
//
int  SQLexecProcedure( char *nprc )
{
   
    HRESULT hr = S_OK;
   _CommandPtr pcmd = NULL;
   _ConnectionPtr pConnection = NULL;
   _bstr_t strMessage, strAuthorID;
 
       ::CoInitialize(NULL);
 
   long codRet = -1;
 
   try {
      TESTHR(pConnection.CreateInstance(__uuidof(Connection)));
      hr = pConnection->Open("dsn=MT4_SQL_BASE;", "yuraz", "qwerty", adConnectUnspecified);
      pConnection->CursorLocation = adUseClient;
      TESTHR(pcmd.CreateInstance(__uuidof(Command)));
      pcmd->CommandText = nprc;  // procedure name
      pcmd->CommandType = adCmdStoredProc;
     
      _ParameterPtr  pParm1 = pcmd->CreateParameter( _bstr_t("@P1"), adInteger,   adParamOutput,0,    codRet );
      pcmd->Parameters->Append( pParm1 );
      pcmd->ActiveConnection = pConnection;
      int hr = pcmd->Execute( 0, 0, adCmdStoredProc );
      if( FAILED(hr) )
      {
                codRet = -1;
      }
      else
      {
         pParm1 = pcmd->Parameters->GetItem(_bstr_t("@P1"));     // obtain from the procedure
         codRet = pParm1->GetValue();
      }
   }
   catch(_com_error  ) {
       //
       // if necessary, process the execution error
          //
       codRet = -1;
 
   }
   if (pConnection)
      if (pConnection->State == adStateOpen)
         pConnection->Close();
 
   ::CoUninitialize();
    return((int)codRet);
}
 
//
//
//
int  SQLexecProcedureSignal( char *sSymbol, char* sProcedure )
{
   
    HRESULT hr = S_OK;
   _CommandPtr pcmd = NULL;
   _ConnectionPtr pConnection = NULL;
   _bstr_t strMessage;
   _bstr_t strAuthorID;
 
       ::CoInitialize(NULL);
 
   long codRet = 0;
 
   try {
      TESTHR(pConnection.CreateInstance(__uuidof(Connection)));
      hr = pConnection->Open("dsn=MT4_SQL_BASE;", "yuraz", "qwerty", adConnectUnspecified);
      pConnection->CursorLocation = adUseClient;
      TESTHR(pcmd.CreateInstance(__uuidof(Command)));
      pcmd->CommandText = sProcedure;  // procedure name
      pcmd->CommandType = adCmdStoredProc;
 
      _ParameterPtr pParm1 = pcmd->CreateParameter("@psSymbol",adChar, adParamInput, strlen(sSymbol) ,sSymbol );
      pcmd->Parameters->Append(pParm1);
      _ParameterPtr pParm2 = pcmd->CreateParameter( _bstr_t("@P1"), adInteger,   adParamOutput,0,    codRet );
      pcmd->Parameters->Append( pParm2 );
      pcmd->ActiveConnection = pConnection;
      int hr = pcmd->Execute( 0, 0, adCmdStoredProc );
            if( FAILED(hr) )
            {
                bool bSuccess = false;
            }
            pParm2 = pcmd->Parameters->GetItem(_bstr_t("@P1"));     // obtain from the procedure
            codRet = pParm2->GetValue();
 
//             printf("\n [%d] \n",codRet );       // OBTAINING from the procedure
   }
   catch(_com_error  ) {
       //
       // if necessary, process the execution error
          //
   }
   if (pConnection)
      if (pConnection->State == adStateOpen)
         pConnection->Close();
 
   ::CoUninitialize();
    return((int)codRet);
}

Example of calling from MQL4 -

// Comments are reduced to make it appear simpler, the comments in the attached files are complete
 
//+------------------------------------------------------------------+
//|                                                                  |
//|                 Copyright c 1999-2006, MetaQuotes Software Corp. |
//|                                         http://www.metaquotes.ru |
//|                                                YZMSSQLSample.mq4 |
//|                                                   Yuriy Zaitsev  |
//+------------------------------------------------------------------+
// Example of integrating with MS SQL                                |
//+------------------------------------------------------------------+
 
#property copyright "YURAZ Copyright(C) 2008"
#property link      "yzy @ mail.ru"
 
//+------------------------------------------------------------------+
// DLL function library 
//+------------------------------------------------------------------+
#import "YZMSSQLExpertSample.dll"
// Performing any actions on MS SQL Server, procedure is called
SQLProcedureGetInt 
// Collecting ticks
int SQLProcedureTickPut( string,  int , double , double ,string );  
 
int Prc = 0;
int init()
  {
 
//
// SQLProcedureGetInt The function, once having called a certain procedure, 
// will return into MT4 int value, for example, parameters
// stored on MS SQL server, formed by another software
//
   Prc =     SQLProcedureGetInt ("YZ_MT4_T1"); 
   return(0);
  }
 
int start()
  {
   int a;
 
   int RetCode = SQLProcedureTickPut( Symbol(), TimeCurrent() , Ask, Bid ,"YZ_MT4_TICK"); // call to the tick collecting procedure
   Print(" SQLProcedureTickPut (YZ_MT4_NEWDAY)"+ RetCode );
 
// Example:
//    on MS SQL server, you can filter signals formed using third-party software
//    neural networks 
//    other software products 
//
/*
   int Signal = SQLProcedureGetSignal (Symbol() , "YZ_MT4_SIGNAL" ); // procedure MS SQL , will return signal
   Print(" SQLProcedureGetSignal (Symbol() , YZ_MT4_SIGNAL )"+ Signal );
   if ( Signal == OP_BUY )
   {
       // the procedure has returned the signal and is recommending to buy
   }
   if ( Signal == OP_SELL )
   {
       // the procedure has returned the signal and is recommending to sell
   }
*/
 
   return(0);
  }

Script loading history onto MS SQL Server:

//
// YURAZ  2008 yzh @ mail.ru
//
// script loading history onto MS SQL
// reload all history for all currency pairs and for all TIMEFRAMES
// in MS SQL
//
 
#import "YZMSSQLExpertSample.dll"
int SQLProcedureHistoryPut( string,  int  , int, double , double ,double , double ,double ,int,  string );  
 
static int mPeriod[8]={PERIOD_M1,PERIOD_M5,PERIOD_M15,PERIOD_M30,PERIOD_H1,PERIOD_H4,PERIOD_D1,PERIOD_W1,PERIOD_MN1};
 
void start()
{
    PutHistor("EURUSD"); 
    PutHistor("USDCHF"); 
    Comment(" LOADING COMPLETE " );
}
 
void PutHistor(string sSymbol)
{
  for ( int iPeriod = 0; iPeriod <= 8 ; iPeriod++ )
  {
     int pPERIOD_XX = mPeriod[iPeriod];
      int Bar = iBars(sSymbol,pPERIOD_XX ); // obtain the depth of history for the given timeframe
 // no progress bar organized 
     for ( int iBar = Bar; iBar >= 0 ; iBar--)
     {
     Comment( "WAIT  TIMEFRAME "+pPERIOD_XX+" SYMBOL "+sSymbol+" BARS "+iBar );
       double   o = iOpen  (sSymbol,pPERIOD_XX,iBar);
       double   h = iHigh  (sSymbol,pPERIOD_XX,iBar);
       double   l = iLow   (sSymbol,pPERIOD_XX,iBar);
       double   c = iClose (sSymbol,pPERIOD_XX,iBar);
       double   v = iVolume(sSymbol,pPERIOD_XX,iBar);
       datetime d = iTime  (sSymbol,pPERIOD_XX,iBar);
       int RetCode = SQLProcedureHistoryPut( sSymbol,pPERIOD_XX,d,o,h,l,c,v,iBar, "YZ_MT4_HISTORY");
       // Print ( " YZ_MT4_HITSRY "+RetCode);
      }
  }
}

Attention: Unfortunately, all history is loaded rather slowly using the script, but it fixes bar number clearly and with high quality.

The best solution would be unloading quotes into a text file and loading them into MS SQL through IMPRT EXPORT DTS. Loading M1 history of 1999-2008 for each symbol will take a few minutes.
The bar index is not unloaded when unloading into a text file. If you decide that the bar index will be just the line number, you will have the problem of missed bars and, if modifying or reloading, the numbers of unloaded bars may be different in MS SQL and in MT 4. I haven't solved this problem yet, but I suppose it can be solved through reloading of history after a high-quality history updating in MT 4 itself.


Description of Files Attached

CreateSQLallDate.txt (9.0 Kb)

- Script in SQL format as an example of how to create bases, tables, procedures on MS SQL Server.

SQLGETHISTORY.mq4 (1.4 Kb)

- Script to load history in MS SQL

YZMSSQLExpertSample.rar (89.9 Kb)

- DLL project

YZMSSQLSample.mq4 (13.1 Kb) -

To be attached as an EA to the symbol chart, the ticks of which should be collected; you can attach it to any timeframe.


Conclusion

Integrating with other software products will expand the functionality of MetaTrader 4 and allow to distribute tasks and functions of an automated trading system more efficiently.

Translated from Russian by MetaQuotes Ltd.
Original article: https://www.mql5.com/ru/articles/1533

Attached files |
SQLGETHISTORY.mq4 (1.45 KB)
YZMSSQLSample.mq4 (13.07 KB)

Other articles by this author

Last comments | Go to discussion (8)
ghost007
ghost007 | 18 Jul 2009 at 11:59

I have tried to make the code in this article work with my database. I compile the dll again only changing the database-name, username and password in the .cpp file. After compiling and running the EA I get the "cannot load library 'YZMSSQLExpertSample.dll' (error 126)" error. It works with the old DLL file, but it have the not my database, username and password. So I guess something went wrong in the compiling. I used the newest version of C++ and not the 6.0. Schould this be a problem? Or do I have to look elsewhere?


I also tried to make a database called the same as in the article and run the articles dll and codes. Still doesnt work, I dont get the "cant load dll" error, but no data is filled into the database. I made the DSN in my windows server 2008, with windows NT autentication with Network ID, cos I couldnt use the username and password specified for the database created with the script.


Im not sure why its not working for me any ideas?

ghost007
ghost007 | 18 Jul 2009 at 12:21
What is MDAC 7 ? When I google it I only find versions called 2.7 or 2.8 from ms.
ghost007
ghost007 | 18 Jul 2009 at 22:14
Okay its working for me now. I changed the dll with an hex editor, as I couldnt make it work with recompiling in c++ 9.
[Deleted] | 6 Sep 2009 at 14:47

Hi,


I am a very beginner in the programming field. It happens that i have a trading strategy that might work well if i have a hybrid EA including NN. However,i couldnot afford time or effort to start learning everything about advanced programming, genetic algorithms or Neural networks. I surfed to find out if there is a software can enable me to build an EA without the need of advanced programming knowledge.Actually, if this will work, i could design, my what i call it, prototype EA. If this prototype EA shows promising results, i might go further to professionally produce it. For example, by hiring a professional programmer or contacting a reputable programming company.


Now, i found Neuroshell software could satisfy me with my need in this area of designing and building an EA without much programming knowlege.

My wondering, if you know guys any of their compititors that i could look at and make a fair comparison based on my needs and what they offer so i could decide which one i will go for??


Thanks for you patience and time


Hope to hear from you soon.

Email: McGene2010@yahoo.com


wilbur
wilbur | 8 Oct 2009 at 13:16
EAProgrammer:

I have tried to make the code in this article work with my database. I compile the dll again only changing the database-name, username and password in the .cpp file. After compiling and running the EA I get the "cannot load library 'YZMSSQLExpertSample.dll' (error 126)" error. It works with the old DLL file, but it have the not my database, username and password. So I guess something went wrong in the compiling. I used the newest version of C++ and not the 6.0. Schould this be a problem? Or do I have to look elsewhere?


I also tried to make a database called the same as in the article and run the articles dll and codes. Still doesnt work, I dont get the "cant load dll" error, but no data is filled into the database. I made the DSN in my windows server 2008, with windows NT autentication with Network ID, cos I couldnt use the username and password specified for the database created with the script.


Im not sure why its not working for me any ideas?


I'm getting the same problem as you.

I followed the instructions to the letter, using the same version of SQL Server 2000 on a Windows 2000 Server virtual PC, created a login account 'yuraz' 'qwerty', used the same username and password provided in the SQL script for the DSN connection, the DSN name is the same, all database names and stored procedures are also the same as the author's and SQL authentication is enabled, as opposed to Windows authentication in SQL server and for the DSN.

The expert SQLGETHISTORY is attached to the chart and loads the ready made .dll successfully, but no data is filled in to the database tables.

One thing I did notice was the Expert, when attached to the chart and enabled, has a unhappy face :-(. I was wondering if this should be a happy face for everything to be working correctly?

The counter is counting down from 5000 to 0 and the starts over again.

Did you manage to get this to work?

Does anyone know where I may have gone wrong?

How to Become a Participant of Automated Trading Championship 2008? How to Become a Participant of Automated Trading Championship 2008?
The main purpose of the Championship is to popularize automated trading and accumulate practical information in this field of knowledge. As the Organizer of the Championship, we are doing our best to provide a fair competition and suppress all attempts to “play booty”. It is this reasoning that sets the strict Rules of the Championship.
Show Must Go On, or Once Again about ZigZag Show Must Go On, or Once Again about ZigZag
About an obvious but still substandard method of ZigZag composition, and what it results in: the Multiframe Fractal ZigZag indicator that represents ZigZags built on three larger ons, on a single working timeframe (TF). In their turn, those larger TFs may be non-standard, too, and range from M5 to MN1.
A Pattern Trailing Stop and Exit the Market A Pattern Trailing Stop and Exit the Market
Developers of order modification/closing algorithms suffer from an imperishable woe - how to compare results obtained by different methods? The mechanism of checking is well known - it is Strategy Tester. But how to make an EA to work equally for opening/closing orders? The article describes a tool that provides strong repetition of order openings that allows us to maintain a mathematically correct platform to compare the results of different algorithms for trailing stops and for exiting the market.
Expert Advisors Based on Popular Trading Systems and Alchemy of Trading Robot Optimization (Part  V) Expert Advisors Based on Popular Trading Systems and Alchemy of Trading Robot Optimization (Part V)
In this article the author offers ways to improve trading systems described in his previous articles. The article will be interesting for traders that already have some experience of writing Expert Advisors.