English Русский 中文 Español Deutsch 日本語 한국어 Français Italiano Türkçe
Guia para escrever uma DLL para MQL5 em Delphi

Guia para escrever uma DLL para MQL5 em Delphi

MetaTrader 5Exemplos | 22 janeiro 2014, 09:16
2 175 2
Andriy Voitenko
Andriy Voitenko

Introdução

O mecanismo de escrever uma DLL será considerado usando um exemplo do meio de desenvolvimento de 2009 do Delphi. Esta versão foi selecionada devido ao fato de que em MQL5, todas as linhas são armazenadas em formato Unicode. Em versões mais antigas do Delphi, o módulo SysUtils está faltando a função para trabalhar com linhas em formato Unicode.

Se você, por qualquer motivo, estiver usando uma versão anterior (Delphi de 2007 e mais antigas), então você tem que trabalhar com linhas em formato ANSI, e, a fim de trocar dados com MetaTrader 5, você precisa produzir conversões diretas e reversas para Unicode . Para evitar tais complicações, eu recomendo desenvolver o módulo DLL para MQL5 em um ambiente não mais antigo que o Delphi de 2009. A versão de teste de 30 dias de familiarizamento para Delphi pode ser baixada a partir do site oficial http://embarcadero.com.

1. Criando o projeto

Para criar o projeto, precisamos executar o Assistente DLL, escolhendo o item de menu: 'Arquivo -> Novo -> Outro ... -> Assistente DLL ' Como mostrado na figura 1.

Figura 1. Criando um projeto usando o Assistente de DLL

Como resultado, criaremos um projeto de DLL vazio, como mostrado na figura 2.


Figura 2. Um projeto de DLL vazio

A essência de um longo comentário no título do projeto é para lembrá-lo de uma conexão correta e o uso de um gerenciador de memória quando se trabalha com a memória alocada dinamicamente. Isto será discutido em mais detalhe na seção que trata de strings.

Antes de você começar a preencher a nova DLL com funções, é importante configurar o projeto.

Abra a janela de propriedades do projeto a partir do menu: 'Projeto -> Opções ...' ou através do teclado pelo comando 'Shift + Ctrl + F11' .

A fim de simplificar o processo de depuração, é necessário que o arquivo da DLL seja criado diretamente na pasta '.. \\MQL5\\Bibliotecas' Trade Terminal MetaTrtader5. Para fazer isso, na guia DelphiCompiler, definir a propriedade de diretório de saída de valor correspondente, como mostrado na figura 3. Isto eliminará a necessidade de copiar constantemente o arquivo, gerado pela DLL, a partir da pasta do projeto para a pasta do terminal.

Figura 3. Especifique a pasta para armazenar o arquivo DLL resultante

A fim de evitar a junção de módulos BPL durante a montagem, sem a presença do que está na pasta de sistema do Windows, se a DLL criada não será trabalhada no futuro, é importante verificar se os Pacotes de guia, o sinalizador Construir com pacotes de tempo de execução não está selecionado, como mostrado na figura 4.

Figura 4. Exclusão dos módulos de BPL da montagem

Depois de concluir a configuração do projeto, salve-o em sua pasta de trabalho, o nome especificado do projeto é o nome futuro do arquivo DLL compilado.

2. Adicionando os procedimentos e funções

Vamos considerar a situação geral ao escrever os procedimentos e funções exportadas no módulo DLL, em um exemplo de um procedimento sem parâmetros. O anúncio e a transferência de parâmetros serão discutidos na próxima seção.

Uma pequena digressão. Ao escrever os procedimentos e funções da linguagem Object Pascal, o programador tem a oportunidade de usar as funções incorporadas da biblioteca do Delphi, para não mencionar os inúmeros componentes desenvolvidos para esse ambiente. Por exemplo, para o desempenho da mesma ação, como trazer uma exibição de uma janela modal com uma mensagem de texto, você pode usar uma função da API - MessageBox, bem como um procedimento da biblioteca VCL - ShowMessage.

A segunda opção leva a incluir o módulo diálogos e dá vantagem para trabalhar de forma fácil com caixas de diálogo padrão do Windows. No entanto, o tamanho do arquivo DLL resultante irá aumentar em cerca aproximadamente 500 KB. Portanto, se você preferir criar arquivos DLL pequenos, que não ocupam muito espaço em disco, eu não aconselharia usar os componentes VCL.

Um projeto de teste da amostra com explicações segue abaixo:

library dll_mql5;

uses
  Windows, // necessary for the work of the MessageBox function
  Dialogs; // necessary for the work of the ShowMessage procedure from the Dialogs module

var   Buffer: PWideChar;
//------------------------------------------------------+
procedure MsgBox(); stdcall; // 
//to avoid errors, use the stdcall (or cdecl) for the exported functions
//------------------------------------------------------+
begin
    {1} MessageBox(0,'Hello World!','terminal', MB_OK);
    {2} ShowMessage('Hello World!');// alternative to the MessageBox function 
end;

//----------------------------------------------------------+
exports
//----------------------------------------------------------+
  {A} MsgBox,
  {B} MsgBox name 'MessageBox';// renaming of the exported function


//----------------------------------------------------------+
procedure DLLEntryPoint(dwReason: DWord); // event handler
//----------------------------------------------------------+
begin
    case dwReason of

      DLL_PROCESS_ATTACH: // DLL attached to the process;
          // allocate memory
          Buffer:=AllocMem(BUFFER_SIZE);

      DLL_PROCESS_DETACH: // DLL detached from the process;
          // release memory
          FreeMem(Buffer);

    end;
end;

//----------------------------------------------------------+
begin
    DllProc := @DLLEntryPoint; //Assign event handler
    DLLEntryPoint(DLL_PROCESS_ATTACH);
end.
//----------------------------------------------------------+

Todas as funções exportadas devem ser anunciadas com o modificador stdcall ou cdecl. Se nenhum destes modificadores é especificado, o Delphi usa o acordo fastcall proposto, que utiliza principalmente registradores da CPU para a passagem de parâmetros, ao invés da memória de armazenamento. Será, sem dúvida, levar um erro do trabalho com os parâmetros transmitidos, na fase de convocar as funções externas da DLL.

A seção "inicial final" contém um código de inicialização padrão de um manipulador de eventos da DLL. O procedimento de retorno de chamada DLLEntryPoint será chamado ao conectar e desconectar do processo que o chamou. Estes eventos podem ser utilizados para a gestão de memória dinâmica correta, atribuída para as nossas próprias necessidades, como mostrado no exemplo.

Chamada para MQL5:

#import "dll_mql5.dll"
    void MsgBox(void);
    void MessageBox(void);
#import

// Call of procedure
   MsgBox();
// If the names of the function coincide with the names of MQL5 standard library function
// use the DLL name when calling the function
   dll_mql5::MessageBox();

3. Passando parâmetros para a função e valores retornados

Antes de considerar a passagem de parâmetros, vamos analisar a tabela de correspondência de dados para MQL5 e Object Pascal.

Tipo de dado para MQL5
Tipo de dado para Object Pascal (Delphi)
Nota
tipo ShortInt
uchar
Byte
curto
SmallInt
ushort
Word

int
Inteiro
uint Cardeal
long Int64
ulong
UInt64

float Single
double Double

ushort (символ) WideChar
sequência PWideChar
bool Boolean
datetime TDateTime conversão necessária (veja abaixo nesta seção)
cor TColor

Tabela 1. A tabela de correspondência de dados para MQL5 e Object Pascal

Como você pode ver na tabela, para todos os outros tipos de dados de data e hora, Delphi tem um análogo completo.

Agora, considere duas formas de passagem de parâmetros: por valor e por referência. O formato da declaração de parâmetros para ambas as versões é dada na tabela 2.

Método de transferência de parâmetros
Anúncio para MQL5
Anúncio para Delphi
Nota
por valor
função interna (int a); função (a:Inteira): Inteira; correto

função interna (int a);
função (var a: Inteira): Inteira;
Erro: violação de acesso escrita ao
por link
função interna (int &a);
função (var a: Inteira): Inteira;
corretas, porém as linhas são transmitidas sem var modificador!
função interna (int &a); função (a: Inteira): Inteira; erro: em vez do valor da variável, contém o endereço da célula de memória

Tabela 2. Métodos de passagem de parâmetros

Agora vamos considerar os exemplos de trabalhar com parâmetros passados e os valores devolvidos.

3.1 Conversão de data e hora

Primeiro, vamos lidar com o tipo de data e hora que você deseja converter, porque o tipo datetime corresponde a TDateTime somente em seu tamanho, mas não em formato. Para facilidade de transformação, use Int64 como o tipo de dado recebido, em vez de TDateTime. Abaixo estão as funções para transformação direta e inversa:

uses 
    SysUtils,  // used for the constant UnixDateDelta 
    DateUtils; // used for the function IncSecon, DateTimeToUnix

//----------------------------------------------------------+
Function MQL5_Time_To_TDateTime(dt: Int64): TDateTime;
//----------------------------------------------------------+
begin
      Result:= IncSecond(UnixDateDelta, dt);
end;

//----------------------------------------------------------+
Function TDateTime_To_MQL5_Time(dt: TDateTime):Int64;
//----------------------------------------------------------+
begin
      Result:= DateTimeToUnix(dt);
end;

3.2 Trabalhando com tipos de dados simples

Vamos examinar como transferir os tipos de dados simples, a exemplo dos mais comumente usados, int, double, bool, e datetime.

Chamada para Object Pascal:

//----------------------------------------------------------+
function SetParam(var i: Integer; d: Double; const b: Boolean; var dt: Int64): PWideChar; stdcall;
//----------------------------------------------------------+
begin
  if (b) then d:=0;                   // the value of the variable d is not changed in the calling program
  i:= 10;                             // assign a new value for i
  dt:= TDateTime_To_MQL5_Time(Now()); // assign the current time for dt
  Result:= 'value of variables i and dt are changed';
end;

Chamada para MQL5:

#import "dll_mql5.dll"
    string SetParam(int &i, double d, bool b, datetime &dt);
#import

// initialization of variables
   int i = 5;
   double d = 2.8;
   bool b = true;
   datetime dt= D'05.05.2010 08:31:27';
// calling the function
   s=SetParam(i,d,b,dt);
// output of results
   printf("%s i=%s d=%s b=%s dt=%s",s,IntegerToString(i),DoubleToString(d),b?"true":"false",TimeToString(dt));
Resultado:
The values of variables i and dt are changed i =  10  d =  2.80000000  b = true dt =  2009.05 .  05  08 :  42 

O valor não foi alterado desde que foi transferido por valor. Para evitar a ocorrência de alterações do valor de uma variável, no interior de uma função de DLL, um modificador constante foi usado na variável b.

3.3 Trabalhando com estruturas e matrizes

Em várias ocasiões, é útil para agrupar os parâmetros de diferentes tipos nas estruturas, e os parâmetros de um tipo nas matrizes. Considere trabalhar com todos os parâmetros transferido da função SetParam, a partir do exemplo anterior, integrando-os numa estrutura.

Chamada para Object Pascal:

type
StructData = packed record
    i: Integer;
    d: Double;
    b: Boolean;
    dt: Int64;
  end;

//----------------------------------------------------------+
function SetStruct(var data: StructData): PWideChar; stdcall;
//----------------------------------------------------------+
begin
  if (data.b) then data.d:=0;
  data.i:= 10;                                 // assign a new value for i
  data.dt:= TDateTime_To_MQL5_Time(Now()); // assign the current time for dt
  Result:= 'The values of variables i, d and dt are changed';
end; 

Chamada para MQL5:

struct STRUCT_DATA
  {
   int i;
   double d;
   bool b;
   datetime dt;
  };

#import "dll_mql5.dll"
    string SetStruct(STRUCT_DATA &data);
#import

   STRUCT_DATA data;
   
   data.i = 5;
   data.d = 2.8;
   data.b = true;
   data.dt = D'05.05.2010 08:31:27';
   s = SetStruct(data);
   printf("%s i=%s d=%s b=%s dt=%s", s, IntegerToString(data.i),DoubleToString(data.d), 
             data.b?"true":"false",TimeToString(data.dt));
Resultado:
The values of variables i,  d  and dt are changed i =  10  d =  0.00000000  b = true dt =  2009.05 .  05  12 :  19 

é necessário observar uma diferença significativa a partir do resultado do exemplo anterior. Desde que a estrutura é transferida através de uma referência, torna-se impossível proteger os campos selecionados de serem editados na função chamada. A tarefa de monitoramento da integridade dos dados, neste caso, encontra-se totalmente no programador.

Considere trabalhar com matrizes, em um exemplo de preenchimento da matriz com a sequência de números de Fibonacci:

Chamada para Object Pascal:

//----------------------------------------------------------+
function SetArray(var arr: IntegerArray; const len: Cardinal): PWideChar; stdcall;
//----------------------------------------------------------+
var i:Integer;
begin
  Result:='Fibonacci numbers:';
  if (len < 3) then exit;
  arr[0]:= 0;
  arr[1]:= 1;
  for i := 2 to len-1 do
    arr[i]:= arr[i-1] + arr[i-2];
end;

Chamada para MQL5:

#import "dll_mql5.dll"
    string SetArray(int &arr[],int len);
#import
   
   int arr[12];
   int len = ArraySize(arr);
// passing the array by reference to be filled by data in DLL
   s = SetArray(arr,len);
//output of result
   for(int i=0; i<len; i++) s = s + " " + IntegerToString(arr[i]);
   printf(s);
Resultado:
Fibonacci numbers 0 1 1 2 3 5 8 13 21 34 55 89

3.4 Trabalhando com strings

Vamos retornar para o gerenciador de memória. Na DLL é possível operar o seu próprio gerenciador de memória. No entanto, devido a DLL e o programa que lhe chama, serem muitas vezes escritos em diferentes linguagens de programação, e seus próprios gerenciadores de memória ao invés da memória do sistema geral serem usados no trabalho, todo o peso da responsabilidade pela veracidade da operação da memória na junção DLL e na aplicação, repousa sobre o programador.

Para trabalhar com a memória, é importante cumprir com a regra de ouro, o que soa algo como: "Aqueles que alocam a memória, devem ser os únicos a libertá-la." Ou seja, você não deve tentar liberar a memória no programa de código mql 5, alocados na DLL, e vice-versa.

Vamos considerar um exemplo de gerenciamento de memória em um estilo de chamadas de função API do Windows. No nosso caso, o programa mql5 atribui memória ao tampão, e um ponteiro para o buffer, passado à DLL como PWideChar , e a DLL apenas preenche este tampão com o valor desejado, como mostrado no exemplo a seguir:

Chamada para Object Pascal:

//----------------------------------------------------------+
procedure SetString(const str:PWideChar) stdcall;
//----------------------------------------------------------+
begin
  StrCat(str,'Current time:');
  strCat(str, PWideChar(TimeToStr(Now)));
end;

Chamada para MQL5:

#import "dll_mql5.dll"
    void SetString(string &a);
#import

// the string must be initialized before the use
// the size of the buffer must be initially larger or equal to the string length
   StringInit(s,255,0); 
//passing the buffer reference to DLL 
   SetString(s);
// output of result 
   printf(s);

Resultado:

Current Time: 11: 48:51 

A memória para o buffer de linha pode ser selecionada na DLL de várias formas, como pode ser visto no exemplo a seguir:

Chamada para Object Pascal:

//----------------------------------------------------------+
function GetStringBuffer():PWideChar; stdcall;
//----------------------------------------------------------+
var StrLocal: WideString;
begin
     // working through the dynamically allocated memory buffer
     StrPCopy(Buffer, WideFormat('Current date and time: %s', [DateTimeToStr(Now)]));
     // working through the global varialble of WideString type
     StrGlobal:=WideFormat('Current time: %s', [TimeToStr(Time)]);
     // working through the local varialble of WideString type
     StrLocal:= WideFormat('Current data: %s', [DateToStr(Date)]);

{A}  Result := Buffer;

{B}  Result := PWideChar(StrGlobal);
     // it's equal to the following
     Result := @StrGlobal[1];

{С}  Result := 'Return of the line stored in the code section';

     // pointer to the memory, that can be released when exit from the function
{D}  Result := @StrLocal[1];
end;
Chamada para MQL5:
#import "dll_mql5.dll"
    string GetStringBuffer(void);
#import

   printf(GetStringBuffer());

Resultado:

Current Date: 19.05.2010

O que é significativo é que todas as quatro opções trabalham. Nas duas primeiras opções, o trabalho com a linha é feito através de uma memória alocada globalmente.

Na opção A, a memória é alocada de forma independente, e na opção B, o trabalho com gerenciamento de memória é assumido pelo gerenciador de memória.

Na opção C, a constante de linha não é armazenada na memória, mas no segmento de código, de modo que o gestor de memória não atribuir a memória dinâmica para o seu armazenamento. A opção D é um erro audaz na programação, porque a memória alocada para a variável local pode ser liberada imediatamente após sair da função.

E, embora o gerenciador de memória não libera essa memória instantaneamente, e não há tempo para ele se encher de lixo, eu recomendo excluir a última opção de uso.

3.5 Usando os parâmetros propostos

Vamos falar sobre o uso de parâmetros opcionais. Eles são interessantes porque seus valores não precisam ser especificados ao convocar procedimentos e funções. Enquanto isso, eles devem ser descritos, exclusivamente depois de todos os parâmetros obrigatórios, na declaração de procedimentos e funções, como se mostra no exemplo a seguir:

Chamada para Object Pascal:

//----------------------------------------------------------+
function SetOptional(var a:Integer; b:Integer=0):PWideChar; stdcall;
//----------------------------------------------------------+
begin
    if (b=0) then Result:='Call with default parameters'
    else          Result:='Call without default parameters';
end;
Chamada para MQL5:
#import "dll_mql5.dll"
    string SetOptional(int &a, int b=0);
#import

  i = 1;
  s = SetOptional(i); // second parameter is optional
  printf(s);

Resultado:

Chamada com os parâmetros padrão

Para facilitar a depuração, o código a partir dos exemplos acima é organizado como script, e está localizado no arquivo Testing_DLL.mq5.

4. Possíveis erros na fase de concepção

Erro: O carregamento da DLL não é permitido.

Solução: Ir para as configurações do MetaTrader 5 através do menu de "Ferramentas-Opções" e permitir a importação da função da DLL, como mostrado na figura 5.

 Figura 5. Permissão para importar as funções da DLL

Figura 5. Permissão para importar as funções da DLL

Erro: Não foi possível encontrar 'nome da função' em 'nome da DLL'.
Solução: Verifique se a função de retorno é especificada na seção de exportações do projeto DLL. Se for, você deve verificar a concordância total dos nomes das funções na DLL e no programa MQL5, considerando que ele é o caráter sensível!

Erro: Violação de acesso escrita ao [endereço de memória]
Solução: Você precisa verificar a exatidão da descrição dos parâmetros de transmissão (ver tabela 2). Como normalmente esse erro está associado ao processamento de linhas, é importante seguir as recomendações para trabalhar com linhas, estabelecidos no parágrafo 3.4 deste artigo.

5. Exemplo de código DLL

Como um exemplo visual do uso da DLL, considerar os cálculos dos parâmetros do canal de regressão, que consiste em três linhas. Para verificar a regularidade da construção do canal, vamos usar o objeto incorporado da "regressão do canal". O cálculo da linha de aproximação para LS (método dos quadrados mínimos) é feito a partir do site http://alglib.sources.ru/, onde existe uma coleção de algoritmos de processamento de dados. O código de algoritmos é apresentado em várias linguagens de programação, incluindo Delphi.

Para o cálculo dos coeficientes de a e b, pela linha de aproximação y = a + b * x, use o procedimento descrito no arquivo LRLine linreg.pas.

 procedure  LRLine (  const  XY: TReal2DArray;  / / Two-dimensional array of real numbers for X and Y coordinates 
                           N : AlglibInteger;  // number of points
                     var Info : AlglibInteger; // conversion status
                       var  A: Double;  / / Coefficients of the approximating line 
                        var  B: Double);
  

Para o cálculo dos parâmetros do canal, utilize a função CalcLRChannel.

Chamada para Object Pascal:

//----------------------------------------------------------+
function CalcLRChannel(var rates: DoubleArray; const len: Integer;
                          var A, B, max: Double):Integer; stdcall;
//----------------------------------------------------------+
var arr: TReal2DArray;
    info: Integer;
    value: Double;
begin

    SetLength(arr,len,2);
    // copy the data to a two-dimensional array
    for info:= 0 to len - 1 do
    begin
      arr[info,0]:= rates[info,0];
      arr[info,1]:= rates[info,1];
    end;

    // calculation of linear regression coefficients
    LRLine(arr, len, info, A,  B);

    // find the maximal deviation from the approximation line found
    // and determine the width of the channel 
    max:= rates[0,1] - A;
    for info := 1 to len - 1 do
    begin
      value:= Abs(rates[info,1]- (A + B*info));
      if (value > max) then max := value;
    end;

    Result:=0;
end;

Chamada para MQL5:

#import "dll_mql5.dll"
    int CalcLRChannel(double &rates[][2],int len,double &A,double &B,double &max);
#import

   double arr[][2], //data array for processing in the ALGLIB format
              a, b,  // Coefficients of the approximating line  
              max; // maximum deviation from the approximating line is equal to half the width of the channel
   
   int len = period; //number of points for calculation
   ArrayResize(arr,len);

// copying the history to a two-dimensional array
   int j=0;
   for(int i=rates_total-1; i>=rates_total-len; i--)
     {
      arr[j][0] = j;
      arr[j][1] = close[i];
      j++;
     }

// calculation of channel parameters
   CalcLRChannel(arr,len,a,b,max);

O código indicador, que usa a função CalcLRChannel para os cálculos, está localizado no arquivo LR_Channel.mq5 a seguir:

//+------------------------------------------------------------------+
//|                                                   LR_Channel.mq5 |
//|                        Copyright 2009, MetaQuotes Software Corp. |
//|                                              https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "2009, MetaQuotes Software Corp."
#property link      "https://www.mql5.com"
#property version   "1.00"
#property indicator_chart_window

#include 
#include 

#import "dll_mql5.dll"
int CalcLRChannel(double &rates[][2],int len,double &A,double &B,double &max);
#import

input int period=75;

CChart               *chart;
CChartObjectChannel  *line_up,*line_dn,*line_md;
double                arr[][2];
//+------------------------------------------------------------------+
int OnInit()
//+------------------------------------------------------------------+
  {

   if((chart=new CChart)==NULL)
     {printf("Chart not created"); return(false);}

   chart.Attach();
   if(chart.ChartId()==0)
     {printf("Chart not opened");return(false);}

   if((line_up=new CChartObjectChannel)==NULL)
     {printf("Channel not created"); return(false);}

   if((line_dn=new CChartObjectChannel)==NULL)
     {printf("Channel not created"); return(false);}

   if((line_md=new CChartObjectChannel)==NULL)
     {printf("Channel not created"); return(false);}

   return(0);
  }
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime &time[],
                const double &open[],
                const double &high[],
                const double &low[],
                const double &close[],
                const long &tick_volume[],
                const long &volume[],
                const int &spread[])
//+------------------------------------------------------------------+
  {

   double a,b,max;
   static double save_max;
   int len=period;

   ArrayResize(arr,len);

// copying of history to a two-dimensional array
   int j=0;
   for(int i=rates_total-1; i>=rates_total-len; i--)
     {
      arr[j][0] = j;
      arr[j][1] = close[i];
      j++;
     }

// procedure of calculating the channel parameters
   CalcLRChannel(arr,len,a,b,max);

// if the width of the channel has changed
   if(max!=save_max)
     {
      save_max=max;

      // Delete the channel
      line_md.Delete();
      line_up.Delete();
      line_dn.Delete();

      // Creating a channel with new coordinates
      line_md.Create(chart.ChartId(),"LR_Md_Line",0, time[rates_total-1],     a, time[rates_total-len], a+b*(len-1)    );
      line_up.Create(chart.ChartId(),"LR_Up_Line",0, time[rates_total-1], a+max, time[rates_total-len], a+b*(len-1)+max);
      line_dn.Create(chart.ChartId(),"LR_Dn_Line",0, time[rates_total-1], a-max, time[rates_total-len], a+b*(len-1)-max);

      // assigning the color of channel lines     
      line_up.Color(RoyalBlue);
      line_dn.Color(RoyalBlue);
      line_md.Color(RoyalBlue);

      // assigning the line width
      line_up.Width(2);
      line_dn.Width(2);
      line_md.Width(2);
     }

   return(len);
  }
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
//+------------------------------------------------------------------+
  {
// Deleting the created objects
   chart.Detach();

   delete line_dn;
   delete line_up;
   delete line_md;
   delete chart;
  }

O resultado do trabalho do indicador é a criação de um canal de regressão azul, como mostrado na figura 6. Para verificar a regularidade da construção do canal, o gráfico mostra um "Canal de Regressão", a partir do arsenal do grupo MetaTrader 5 de instrumentos de análise técnica, marcada em vermelho.

Como pode ser visto na figura, as linhas centrais do canal se unem. Entretanto, há uma pequena diferença na largura do canal (alguns pontos), que são devido às diferentes abordagens no seu cálculo.

 Figura 6. Comparação dos canais de regressão

Figura 6. Comparação dos canais de regressão

Conclusão

Este artigo descreve as características de escrever uma DLL, usando uma plataforma de desenvolvimento de aplicações Delphi.

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

Arquivos anexados |
dll_mql5_sources.zip (453.47 KB)
mql5_sources.zip (276.43 KB)
Últimos Comentários | Ir para discussão (2)
Charles Adriano
Charles Adriano | 13 mai 2014 em 22:55
MetaQuotes:

Novo artigo Guia para escrever uma DLL para MQL5 em Delphi foi publicado:

Autor: Andrey Voytenko


Se você tiver trabalhando com versões anteriores do delphi, como eu, o D7, pode utilizar funções de conversão ou utilizar a biblioteca da jcl la tem unicode para vc usar, é um pacote de componente free é so entrar no sourcefoge.net e buscar por jcl baixar e instalar

Rodrigo Malacarne
Rodrigo Malacarne | 15 mai 2014 em 11:53
DooMGuarD:
Olá DooMGuarD, ótima informação! Obrigado por compartilhar!
Analisando padrões de velas Analisando padrões de velas
A construção do gráfico de velas japonês e a análise dos padrões de vela constituem uma incrível área da análise técnica. A vantagem das velas é que elas representam dados de uma forma que é possível rastrear a dinâmica dentro dos dados. Neste artigo, analisamos os tipos de velas, a classificação dos padrões de vela e apresentamos um indicador que pode determinar os padrões de vela.
Um exemplo de um Sistema de Comércio Baseado no indicador Heiken-Ashi Um exemplo de um Sistema de Comércio Baseado no indicador Heiken-Ashi
Neste artigo veremos a questão de uso de um indicador Heiken-Ashi na negociação. Com base neste indicador, um simples sistema de negócio é considerado e um Expert Advisor MQL5 é escrito. As operações de negócio são implementadas nas bases de classes da biblioteca de classe padrão. São fornecidos neste artigo os resultados de teste da estratégia de negócio revisada que são baseados no histórico e obtidos usando o strategy tester do MetaTrader 5 embutido.
Criando um Consultor Especialista, que negocia em um número de instrumentos Criando um Consultor Especialista, que negocia em um número de instrumentos
O conceito da diversificação de ativos nos mercados financeiros é bastante antigo e sempre atraiu negociantes iniciantes. Neste artigo, o autor propõe uma abordagem maximamente simples para a construção de um Expert Advisor de moeda múltipla, para uma introdução inicial a esta direção das estratégias de negócio.
Um Administrador de ordem virtual para rastrear ordens dentro do ambiente MetaTrader 5 de posição centrada Um Administrador de ordem virtual para rastrear ordens dentro do ambiente MetaTrader 5 de posição centrada
Esta biblioteca de classe pode ser adicionada a um Expert Advisor do MetaTrader 5 para possibilitar que seja escrito com uma abordagem de ordem cêntrica amplamente similar ao MetaTrader 4, em comparação com a abordagem baseada em posição do MetaTrader 5. Ela faz isso mantendo um registro das ordens virtuais no cliente do terminal do MetaTrader 5, enquanto mantém uma parada de quebra protetora para cada posição para proteção contra desastres.