Русский Español
Luta pela velocidade: QLUA vs MQL5 - por que o MQL5 é 50 a 600 vezes mais rápido?

Luta pela velocidade: QLUA vs MQL5 - por que o MQL5 é 50 a 600 vezes mais rápido?

MetaTrader 5Exemplos | 28 setembro 2020, 11:26
738 0
MetaQuotes
MetaQuotes

Para comparar as linguagens MQL5 e QLUA, escrevemos vários testes que medem a velocidade de execução de operações básicas. Nos testes, usamos um computador com Windows 7 Professional 64 bits, MetaTrader 5 build 1340 e QUIK versão 7.2.0.45.

Os resultados são apresentados numa tabela cujos valores são expressos em milissegundos (quanto menos tempo, melhor)

#
Nome do script de teste
MQL5, ms
 QLUA, ms
Vantagens de MQL5
1
 TestFloat 3 969 273 391 69 vezes
2
 TestArrays 375 230 768 615 vezes
3
 TestFibo 1 125 61 110 55 vezes
4
 TestPiCalculated 2 328
183 812
 79 vezes
5
 TestQuickSort 2 031
211 279
104 vezes
 6  TestAckermann  828  64 541  78 vezes

As comparações mostram que MQL5 é 50 a 600 vezes mais rápido do que QLUA em operações básicas de qualquer linguagem de programação. Isso é obtido devido ao fato de que MQL5 é uma linguagem compilada fortemente tipada em 32/64 bits, em oposição à QLUA, que é dinâmica.

O que isso dá ao trader? Capacidade de calcular rapidamente grandes matrizes de dados (praticamente ilimitadas no MetaTrader 5) e tomar decisões mais rapidamente.

Isso é apenas um teste da funcionalidade básica. Mas por trás da fachada das linguagens está sua API, que para nenhuma delas é simples. MQL5, sendo uma linguagem aplicada para uma plataforma de negociação, contém centenas de funções especializadas para acessar/processar informações de mercado e interagir com todos os componentes do terminal.

É importante que a MQL5 não seja anexada como complemento do sistema existente, mas, pelo contrário, seja o elo central da plataforma. Todos os processos no terminal de negociação são desenvolvidos para atender às necessidades dos desenvolvedores de robôs de negociação. Isso torna mais rápido o acesso aos dados internos da plataforma e cria um canal direto para operações de negociação.


TestFloat - Velocidade de execução de operações com números reais

Código em MQL5

//+------------------------------------------------------------------+
//|                                                    TestFloat.mq5 |
//|                        Copyright 2016, MetaQuotes Software Corp. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "2010, MetaQuotes Software Corp."
#property link      "http://www.mql5.com"
//---
#define MAX_SIZE 35000
//---
double f0=0;
double f1=123.456789;
double f2=98765.12345678998765432;
double f3=12345678943.98;
//---
//+------------------------------------------------------------------+
//| Função OnStart                                                   |
//+------------------------------------------------------------------+
int OnStart()
  {
   uint tick_count,res;
//--- teste
   tick_count=GetTickCount();
   TestFloat();
   res=GetTickCount()-tick_count;
   Print("Test float time=",res," ms");
   Print("Result=",f0);
//--- retorna quanto tempo foi gasto na execução do teste, em milissegundos
   return((int)res);
  }
//+------------------------------------------------------------------+
//| Função de teste                                                  |
//+------------------------------------------------------------------+
void TestFloat()
  {
   for(int i=0;i<MAX_SIZE;i++)
      for(int j=0;j<MAX_SIZE;j++)
        {
         f0=f0+(f1/(i+1))-f2+(f3*i);
        }
  }
//+------------------------------------------------------------------+

Código em LUA

-- TestFloat
f0=0.0  
f1=123.456789
f2=98765.12345678998765432
f3=12345678943.98
MAX_SIZE=35000
function Start()
   local t=os.clock()
   TestFloat()
   local res=(os.clock()-t)*1000
   -- os resultados de execução devem ser inseridos aqui
   check=f0
   message("TestFloat time=" ..res.." ms\n  check="..tostring(check));
end

function TestFloat()
    -- num loop chegamos até um valor 1 vez mais pequeno que MAX_SIZE
        MAX_SIZE=MAX_SIZE-1
        for i=0, MAX_SIZE do
        for j=0, MAX_SIZE do
            f0=f0+(f1/(i+1))-f2+(f3*i);
        end
    end
end
-- executamos o script
Start()

TestArrays - Testando velocidade de acesso a elementos da matriz

Código em MQL5

//+------------------------------------------------------------------+
//|                                                   TestArrays.mq5 |
//|                        Copyright 2016, MetaQuotes Software Corp. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "2010, MetaQuotes Software Corp."
#property link      "http://www.mql5.com"
//---
#define MAX_SIZE 32000
//---
int x[MAX_SIZE],y[MAX_SIZE];
//+------------------------------------------------------------------+
//| Função OnStart                                                   |
//+------------------------------------------------------------------+
int OnStart()
  {
   int  i,k;
   uint tick_count,res;
//--- teste
   tick_count=GetTickCount();
   for(i=0;i<MAX_SIZE;i++)
      x[i]=i+1;

   for(k=0;k<MAX_SIZE;k++)
      for(i=MAX_SIZE-1; i>=0; i--)
         y[i]+=x[i];
   long check=0;
   for(i=0;i<MAX_SIZE;i++)
     {
      check+=y[i];
     }          
   res=GetTickCount()-tick_count;
   Print("TestArrays time=",res," ms");
      Print("check=",check);
//--- retorna quanto tempo foi gasto na execução do teste, em milissegundos
   return((int)res);
  }
//+------------------------------------------------------------------+

Código em LUA

-- TestArrays
function Start()
        MAX_SIZE=32000
    x={}
    y={}
    local start=os.clock()
    for i=1,MAX_SIZE,1 do
      x[i]=i
      y[i]=0
    end  
    y[MAX_SIZE]=0
    for k=1,MAX_SIZE,1 do
        for i=MAX_SIZE, 1,-1 do         
            y[i]=y[i]+x[i]
        end
    end
    local res=(os.clock()-start)*1000
    -- número de controle
    local check=0
    for k=1,MAX_SIZE,1 do
        check=check+y[k]
    end
    message("Time = "..res.." ms\n  check=".. check)
end
-- executamos o script
Start()


TestFibo - Calculando o sequenciamento da série Fibonacci

Código em MQL5

//+------------------------------------------------------------------+
//|                                                     TestFibo.mq5 |
//|                        Copyright 2010, MetaQuotes Software Corp. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "2010, MetaQuotes Software Corp."
#property link      "http://www.mql5.com"
//---
#define MAX_SIZE 40
long fib[MAX_SIZE];
//+------------------------------------------------------------------+
//| Função OnStart                                                   |
//+------------------------------------------------------------------+
void OnStart()
  {
   int  i;
   uint res;
//--- teste
   res=GetTickCount();
   for(i=0;i<MAX_SIZE;i++)
      fib[i]=TestFibo(i);
   res=GetTickCount()-res;
   Print("TestFibo time=",res," ms");
   Print("Fibo[39]=",fib[39]);
  }
//+------------------------------------------------------------------+
//| Função de teste                                                  |
//+------------------------------------------------------------------+
long TestFibo(long n)
  {
   if(n<2) return(1);
//---
   return(TestFibo(n-2)+TestFibo(n-1));
  }
//+------------------------------------------------------------------+

Código em LUA

-- TestFibo
MAX_SIZE=40
fib={}
function Start()
   start=os.clock()
   for i=0,MAX_SIZE-1 do
     fib[i]=TestFibo(i)
   end
   res=(os.clock()-start)*1000
   message("TestFibo time="..res.." ms\n Fibo[39]="..fib[39])
end

function TestFibo(n)
   if n<2 then
      return(1)
   else
      return(TestFibo(n-2)+TestFibo(n-1))
   end
end
-- executamos o script
Start()



TestPiCalculated -  Calculando 22 000 dígitos de Pi

Código em MQL5

//+------------------------------------------------------------------+
//|                                             TestPiCalculated.mq5 |
//|                        Copyright 2016, MetaQuotes Software Corp. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "2010, MetaQuotes Software Corp."
#property link      "http://www.mql5.com"
//---
#define MAX_SIZE 22000
//--- nesta string colocamos o valo do número PI
string str;
int    a[(MAX_SIZE/4+1)*14];
//+------------------------------------------------------------------+
//| Função OnStart                                                   |
//+------------------------------------------------------------------+
int OnStart()
  {
   uint tick_count,res;
//--- teste
   tick_count=GetTickCount();
   PiCalculate(MAX_SIZE);
   res=GetTickCount()-tick_count;
   Print("TestPiCalculated time=",res," ms");
   Print("Pi=",StringSubstr(str,0,16));
//--- retorna quanto tempo foi gasto na execução do teste, em milissegundos
   return((int)res);
  }
//+------------------------------------------------------------------+
//| Função de teste                                                  |
//+------------------------------------------------------------------+
void PiCalculate(const int digits)
  {
   int d = 0,e,b,g,r;
   int c = (digits/4+1)*14;
   int f = 10000;
//---
   for(int i=0;i<c;i++)
      a[i]=20000000;
//---
   while((b=c-=14)>0)
     {
      d=e=d%f;
      while(--b>0)
        {
         d = d * b + a[b];
         g = (b << 1) - 1;
         a[b]=(d%g)*f;
         d/=g;
        }
      r=e+d/f;
      if(r<1000)
        {
         if(r>99)
            str+="0";
         else
           {
            if(r>9)
               str+="00";
            else
               str+="000";
           }
        }
      str+=IntegerToString(r);
     }
  }
//+------------------------------------------------------------------+

Código em LUA

-- TestPiCalculated
-- quantidade de dígitos do número Pi que usaremos ao calcular
MAX_SIZE=22000
-- nesta string colocamos o valor do número Pi
str=""
a={}
function OnStart()
        start=os.clock()
        PiCalculate(MAX_SIZE)
        -- tempo de cálculo do número Pi em milissegundos
        res=(os.clock()-start)*1000
        message("TestPiCalculated time=" .. res .." ms\n\n Pi="..string.sub(str,1,16)) -- exibimos 16 dígitos
end
function PiCalculate(digits)
        d = 0
        c = (math.floor(digits/4)+1)*14  -- math.floor() -divisão inteira baseada num exemplo da documentação de LUA
        f = 10000

        for i=0,c do
                a[i]=20000000
        end
        c=c-14
        b=c
        while b>0 do
                e=d%f
                d=e
                while b-1>0 do
                        b=b-1
                        d = d * b + a[b]
                        g = (b * 2) - 1
                        a[b]=(d%g)*f  
            d=math.floor(d/g)  -- math.floor(d/g) - divisão inteira baseada num exemplo da documentação de LUA
        end
        r=e+math.floor(d/f)  -- math.floor(d/f) - divisão inteira baseada num exemplo da documentação de LUA
                if r<1000 then
                        if(r>99) then 
                                str=str .. "0"
                        else
                                if(r > 9) then
                                        str=str .. "00"
                                else
                                        str=str .. "000"
                                end
                        end
                end
                str=str .. string.format("%d",r)
                c=c-14
                b=c
        end
end
-- executamos o script
OnStart()


Testando a velocidade de classificação rápida de matriz

Código em MQL5

//+------------------------------------------------------------------+
//|                                                TestQuickSort.mq5 |
//|                        Copyright 2016, MetaQuotes Software Corp. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "2010, MetaQuotes Software Corp."
#property link      "http://www.mql5.com"
//--- classificaremos uma matriz com um tamanho de 16 milhões de elementos
#define MAX_SIZE 16000000
//---
int array[MAX_SIZE];
//+------------------------------------------------------------------+
//| Função OnStart                                                   |
//+------------------------------------------------------------------+
void OnStart()
  {
   uint tick_count,res;
   for(int i=0;i<MAX_SIZE;i++)
      array[i]=i%100;
   tick_count=GetTickCount();
   QuickSort(array,0,MAX_SIZE-1);
   res=GetTickCount()-tick_count;
   Print("TestQuickSort time=",res," ms");

   for(int i=1;i<MAX_SIZE;i++)
      if(array[i]<array[i-1])
        {
        Print("Array not sorted");
        break;
        }
  }
//+------------------------------------------------------------------+
//| Função de classificação rápida                                   |
//+------------------------------------------------------------------+
void QuickSort(int &arr[],int left,int right)
  {
   int i=left;
   int j=right;
   int center=arr[(i+j)/2];
   int x;
//---
   while(i<=j)
     {
      while(arr[i]<center && i<right) i++;
      while(arr[j]>center && j>left) j--;
      if(i<=j)
        {
         x=arr[i];
         arr[i]=arr[j];
         arr[j]=x;
         i++;
         j--;
        }
     }
   if(left<j) QuickSort(arr,left,j);
   if(right>i) QuickSort(arr,i,right);
  }
//+------------------------------------------------------------------+

Código em LUA

-- TestQuickSort
- classificaremos uma matriz com um tamanho de 16 milhões de elementos
MAX_SIZE=16000000
array={}
function Start()
    for i=0,MAX_SIZE-1 do
        array[i]=i%100
    end
    start=os.clock()
    QuickSort(array,0,MAX_SIZE-1)
    res=(os.clock()-t)*1000
    message("TestQuickSort time=" .. res .. " ms")
    for i=1,MAX_SIZE-1 do
        if array[i]<array[i-1] then
            message("Array not sorted");
            break;
        end
    end
end

function QuickSort(arr,left,right)
    i=left
    j=right
    center=arr[math.floor((i+j)/2)]
    while i<=j do
        while(arr[i]<center and i<right) do
            i=i+1
        end
        while(arr[j]>center and j>left) do
            j=j-1
        end
        if i<=j then
            x=arr[i]
            arr[i]=arr[j]
            arr[j]=x
            i=i+1
            j=j-1
        end
    end
    if left<j then 
        QuickSort(arr,left,j)
    end
    if right>i then 
        QuickSort(arr,i,right)
    end
end
-- executamos o script
Start()


TestAckermann - Testando recursão em funções

Código em MQL5

//+------------------------------------------------------------------+
//|                                                TestAckermann.mq5 |
//|                        Copyright 2016, MetaQuotes Software Corp. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "2016, MetaQuotes Software Corp."
#property link      "http://www.mql5.com"
//--- número de execuções da função de Ackermann no loop
#define MAX_SIZE 120000
//+------------------------------------------------------------------+
//| Função OnStart                                                   |
//+------------------------------------------------------------------+
void  OnStart()
  {
//--- número de controle
   uint check=0;
//--- tempo de execução em milissegundos
   uint res=0;
//--- teste
   res=GetTickCount();
   for(int i=0;i<MAX_SIZE;i++)
      check+=Ackermann(1+i%3,1+i%5);
   res=GetTickCount()-res;
   Print("TestAckermann time=",res," ms");
   Print("check=",check);
//---
  }
//+------------------------------------------------------------------+
//| Função de teste                                                  |
//+------------------------------------------------------------------+
int Ackermann(int m,int n)
  {
   if(m==0) return(n+1);
   if(n==0) return(Ackermann(m-1,1));
//---
   return(Ackermann(m-1,Ackermann(m,(n-1))));
  }
//+------------------------------------------------------------------+

Código em LUA

-- TestAckermann
MAX_SIZE=120000
function Start()        
    local check=0 -- número de controle
    local start=os.clock()
        for i=1,MAX_SIZE do
             check=check+Ackermann(1+i%3,1+i%5);                                                
        end 
    local finish=os.clock()
    local time=(finish-start)*1000
    message("TestAckermann time=".. time.." ms\n\n check="..check)
end

function Ackermann(m,n)
        if(m==0) then return(n+1) end
        if(n==0) then return(Ackermann(m-1,1)) end
        return(Ackermann(m-1,Ackermann(m,(n-1))))
end
-- executamos o script
Start()



Você pode baixar o arquivo de scripts completo e verificar os resultados por conta própria.

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

Arquivos anexados |
TestAckermann.mq5 (1.47 KB)
TestArrays.mq5 (2.63 KB)
TestFloat.mq5 (1.53 KB)
TestQuickSort.mq5 (1.89 KB)
Scripts.zip (7.29 KB)
Métodos para localizar zonas de sobrecompra/sobrevenda. Parte I Métodos para localizar zonas de sobrecompra/sobrevenda. Parte I
As zonas de sobrecompra/sobrevenda caracterizam uma determinada situação do mercado que se distingue por um enfraquecimento da dinâmica dos preços dos instrumentos financeiros. Além disso, essa mudança negativa da dinâmica é mais pronunciada na parte final da tendência, independentemente do tamanho desta última. E como o lucro depende diretamente da capacidade de cobrir a máxima amplitude da tendência, identificar com precisão essas zonas é o mais importante ao negociar qualquer instrumento financeiro.
Trabalhando com séries temporais na biblioteca DoEasy (Parte 44): classe-coleção de objetos de buffers de indicador Trabalhando com séries temporais na biblioteca DoEasy (Parte 44): classe-coleção de objetos de buffers de indicador
Neste artigo, veremos a criação de uma classe-coleção de objetos de buffers de indicador, testaremos tanto as possibilidades de criar qualquer quantidade de buffers para programas-indicadores quanto as de trabalhar com eles (o número máximo de buffers que podem ser criados em indicadores MQL é de 512 buffers).
Conjunto de ferramentas para marcação manual de gráficos e negociação (Parte I). Preparação - Descrição da Estrutura e Classe Auxiliar Conjunto de ferramentas para marcação manual de gráficos e negociação (Parte I). Preparação - Descrição da Estrutura e Classe Auxiliar
Neste artigo, começaremos a ver um conjunto de ferramentas para marcação gráfica usando atalhos de teclado. É bastante conveniente: clicaremos num botão e aparecerá uma linha de tendência, clicaremos noutro e aparecerá um leque de Fibonacci com os parâmetros desejados. Também poderemos alternar timeframes, mudar a ordem das "camadas" de objetos ou remover todos os objetos do gráfico.
Como escrever um cliente nativo Twitter para MetaTrader: 2º parte Como escrever um cliente nativo Twitter para MetaTrader: 2º parte
Vamos implementar o cliente Twitter como uma classe MQL que nos permitirá enviar tweets com imagens. Depois de anexar apenas um arquivo include autônomo, poderemos publicar tweets e colocar nossos gráficos e sinais.