English Русский 中文 Español Deutsch 日本語
Integrando o terminal do cliente do MetaTrader 4 com o MS SQL SERVER

Integrando o terminal do cliente do MetaTrader 4 com o MS SQL SERVER

MetaTrader 4Exemplos | 5 fevereiro 2016, 14:28
1 046 0
Yuriy Zaytsev
Yuriy Zaytsev

Introdução

O uso de integrações com outros produtos oferece um desafio adicional no trading.

Pode haver muitos usos do mesmo, então darei alguns deles abaixo.

Você pode coletar ticks e passá-los para análise mais abrangente no MS SQL SERVER. Tendo um histórico grande de ticks você pode coletar qualquer período começando do menor período até períodos não padronizados. Tendo cotações de ticks reais, você pode depurar estratégias dependentes de dados de tick conhecidas como 'scalpers'.

Você pode usar uma loja para uma análise rápida de dados tirados de outros aplicativos, por exemplo, do MS Excel ou outro software de terceiros ou dos seus próprios produtos.

Por exemplo, você pode descarregar todo o histórico do seu centro de histórico do terminal para o MS SQL. Então, você não vai precisar armazenar o histórico no MT4. Isso vai ajudar a aliviar a memória do terminal.

Você pode calcular as redes neurais usando cotações armazenadas no MS SQL SERVER: por exemplo, STATISTICA - 7.8 permite você baixar cotações do SQL e podem ser resolvidas em tempo real transmitindo os sinais de rede para o MT4.

Você pode desenvolver seu próprio programa em outra língua e para outro símbolo e transmitir sinais usando o servidor do MS SQL, tendo sobrado apenas funções de execução para o terminal do cliente e o livrando de sérios cálculos.


Os seguintes produtos de software foram usados para esse projeto

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


A configuração mínima que precisa estar instalada:

1 MS SQL SERVER 2000 Developer
2 MDAC 7

Depurei o programa usando MDAC 7. Entretanto, é possível que tudo funcione bem em algumas versões antigas. Se você não for compilar o DLL, você não precisa instalar ou ter o Visual C++ 6.0 instalado. Você pode usar um DLL pronto. Entretanto, fiz uma conexão física com o nome de usuário, o nome do DSN e as conexões. Então, você terá que repetir tudo o que foi listado acima na sua versão do programa. Não vou descrever aqui como instalar o MS SQL SERVER ou o Visual C++ 6.0. Esses assuntos estão fora do escopo do artigo específico.

Depois que os produtos de software necessários foram instalados, devemos criar um DSN:

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


Exemplo de recebimento de tick no MS SQL

Todos os experimentos foram conduzidos com o MS SQL SERVER 2000 Developer. No Visual C++ 6.0, o YZMSSQLExpertSample.DLL foi criado usando o método de acesso ao MS SQL via ADO. O MDAC 7 ou MDAC 8 deve estar instalado. Somente descreverei os exemplos de como criar procedimentos e tabelas. A configuração mínima para o que temos que criar no MS SQL é a base, tabelas e procedimentos. Vamos considerar a tabela e os procedimentos de trabalho com cotações de tick. Você pode adicionar algumas outras funções, se quiser.


É necessário criar uma base e tabelas no MS SQL. Criei uma base nova chamada MT4TRADE. Então, devemos criar tabelas nela:

MT4TICK - Tabela de 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

Abaixo está como o recebimento de tick e o procedimento de tabulação aparecem:


// 
//    @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


Podemos ver pela descrição acima quais procedimentos e para quais propósitos são usados.

@RetCode - não suporta qualquer funcionalidade quando está sendo transmitido do DLL, serve para recebimento do código de terminação apenas.

A configuração do MS SQL SERVER terminou. Um script para criar uma configuração padrão anexada a esse artigo.


Vamos fantasiar: Possíveis soluções e adicionais

Podemos criar um armazenamento de dados e colocar/extrair informação dele. Dessa forma, podemos livrar o terminal do cliente do MT4 da necessidade de armazenar históricos de cotações. Agora, o histórico de cotações é armazenado no servidor do MS SQL e podemos operar com essa informação, extraí-la mais cedo e exportá-la para outros aplicativos. Podemos usar os dados para ser analisados em pacotes NEURAL, a maioria deles pode trabalhar com armazenamentos no SQL.

Em tempo real, o terminal pode continuar formando sinais a partir dos indicadores, transmitindo-os para o armazenamento e fixando-os dessa forma. Um aplicativo externo pode extrair o sinal e o histórico em tempo real, analisá-los e formar sinais fixando a execução e o armazenamento do registro no servidor MS SQL, e enviá-los para o terminal executar.

Assim, podemos obter integração e distribuição funcional entre os aplicativos envolvidos no complexo de trading automatizado.

Bem, se não há mais necessidade de armazenar cotações de histórico, podemos configurá-lo da seguinte forma. Configure as barras mínimas em Tools(Ferramentas)>Options(Opções)>Charts (Gráficos), por exemplo, para 5000. O terminal começa a funcionar mais rápido uma vez que não precisa compartilhar memória para um histórico grande.





Textos fonte

Código DLL:

//+------------------------------------------------------------------+
//|                                              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);
}


Exemplo de ligação de 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 carregando histórico para o servidor MS SQL:

//
// 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);
      }
  }
}

Atenção: Infelizmente, todo o histórico é carregado lentamente usando o script, mas fixa o número da barra claramente e com alta qualidade.

A melhor solução seria descarregar as cotações em arquivos texto e carregá-las no MS SQL através do IMPRT EXPORT DTS. Carregar o histórico M1 de 1999-2008 para cada símbolo vai levar alguns minutos.
O índice da barra não é descarregado ao descarregar para um arquivo texto. Se você decidir que o índice da barra será apenas o número de linha, você terá o problema de barras perdidas, se modificar ou recarregar, os números das barras não descarregadas podem ser diferentes no MS SQL e no MT4. Ainda não resolvi esse problema, mas suponho que pode ser resolvido através de recarregamento do histórico depois de uma atualização de alta qualidade do histórico no próprio MT4.


Descrição dos arquivos em anexo

CreateSQLallDate.txt (9.0 Kb)

- Script no formato SQL como exemplo de como criar bases, tabelas, procedimentos no servidor MS SQL Server.

SQLGETHISTORY.mq4 (1.4 Kb)

- Script para carregar o histórico no MS SQL

YZMSSQLExpertSample.rar (89.9 Kb)

Projeto DLL

YZMSSQLSample.mq4 (13.1 Kb) -

Para serem anexados aos gráficos de símbolo como EA, os ticks que devem ser coletados, você pode anexá-los a qualquer timeframe.


Conclusão

A integração com outros produtos de software vai expandir a funcionalidade do MetaTrader 4 e permitir a distribuição de tarefas e funções de um sistema de trading automatizado com mais eficiência.

Traduzido do russo pela MetaQuotes Ltd.
Artigo original: https://www.mql5.com/ru/articles/1533

Arquivos anexados |
SQLGETHISTORY.mq4 (1.45 KB)
YZMSSQLSample.mq4 (13.07 KB)
Indicadores de teste de EA não comercial Indicadores de teste de EA não comercial
Todos os indicadores podem ser divididos em dois grupos: indicadores estáticos, a exibição deles, uma vez que aparece, sempre permanece a mesma no histórico e não muda com as novas cotações recebidas e indicadores dinâmicos que exibem seus status somente para o momento atual e são totalmente reelaborados quando um novo preço chega. A eficiência de um indicador estático é diretamente visível no gráfico. Mas como podemos verificar se um indicador dinâmico funciona bem? É para essa questão que o artigo se dedica.
O show deve continuar, ou Mais uma vez sobre o ZigZag O show deve continuar, ou Mais uma vez sobre o ZigZag
Sobre um método óbvio, mas ainda subpadrão de composição do ZigZag e no que ele resulta: o indicador Multiframe Fractal ZigZag que representa ZigZags construídos em três maiores, em um único timeframe (TF) de trabalho. Na vez deles, os TFs maiores podem ser também não padrão e variar de M5 a MN1.
Expert Advisors baseado em estratégias de trading populares e alquimia da otimização de robô de trading (Parte VI) Expert Advisors baseado em estratégias de trading populares e alquimia da otimização de robô de trading (Parte VI)
Nesse artigo o autor oferece uma forma para melhorar os sistemas de trading apresentados nos artigos anteriores. O artigo é do interesse de traders que já tem experiência em escrita de Expert Advisors.
Falácias, Parte 2. A estatística é uma pseudociência ou uma crônica sobre a queda de uma fatia de pão com manteiga Falácias, Parte 2. A estatística é uma pseudociência ou uma crônica sobre a queda de uma fatia de pão com manteiga
Inúmeras tentativas de aplicar métodos estatísticos à realidade objetiva, ou seja, séries financeiras, falham quando encontramos processos não estacionários, "mentiras" sobre acompanhar a distribuição de probabilidade e volume insuficiente de dados financeiros. Nesta publicação, tentarei me referir não às séries financeiras como tal, mas sim as suas apresentações subjetivas - nesse caso, à forma que um trader tenta prender as séries, ou seja, ao sistema de trading. O ensino das regularidades estatísticas do processo de resultados de trading é uma tarefa atraente. Em alguns casos, conclusões bastante verdadeiras sobre o modelo desse processo podem ser feitas e elas podem ser aplicadas ao sistema de trading.