Assista a como baixar robôs de negociação gratuitos
Encontre-nos em Twitter!
Participe de nossa página de fãs
Script interessante?
Coloque um link para ele, e permita que outras pessoas também o avaliem
Você gostou do script?
Avalie seu funcionamento no terminal MetaTrader 5
Bibliotecas

MathTicker - gerador de ticks no modo matemático - biblioteca para MetaTrader 5

Visualizações:
49
Avaliação:
(4)
Publicado:
Freelance MQL5 Precisa de um robô ou indicador baseado nesse código? Solicite-o no Freelance Ir para Freelance

Alternativa para a biblioteca EAToMath https://www.mql5.com/pt/code/61283

Registra os ticks no modo de ticks reais e os lê no modo matemático, chamando sua estratégia a cada tick registrado.

Motivo da criação: testador de MQ, grava arquivos de dados de ticks em cada agente sempre que o otimizador é executado. Tenho 36 agentes gravando 10 GB cada para uma das ferramentas e o período de teste - um total de 360 GB em uma unidade de 480 GB. Esse processo leva cerca de 1 hora antes de cada otimização. Os SSDs típicos têm uma vida útil de 500 a 1000 ciclos de gravação. Ao reescrever 360 GB todas as vezes, o recurso se esgotará muito rapidamente. Essa biblioteca grava apenas um arquivo e, em seguida, todos os 36 agentes lerão os dados desse arquivo. Tudo isso foi o motivo para escrever a biblioteca: usamos apenas um arquivo + economia de uma hora para gravar dados em cada agente + aceleração em comparação com o testador MQ e até mesmo com o Virtual no modo de ticks reais.
O problema foi investigado simultaneamente com fxsaber (o autor do EAToMath), cada um com sua própria versão. Meu código é mais claro para mim, portanto, eu o utilizo.

Para operações de negociação, é utilizada a biblioteca MT4Orders https://www.mql5.com/pt/code/16006
Para a negociação virtual, é necessário utilizar a biblioteca Virtual https://www.mql5.com/pt/code/22577
Para visualizar os resultados da negociação, você pode utilizar o MT4Orders QuickReport https://www.mql5.com/pt/code/47816 ou o Report
Para compactar ticks TickCompressorhttps://www.mql5.com/pt/code/66201
Para remover ticks possivelmente desnecessários, a biblioteca Control_Trade_Sessions https://www.mql5.com/pt/code/48059 é conectada, por exemplo, se uma sessão de cotação for maior do que uma sessão de negociação. Ela também pode ser excluída se todos os ticks forem usados, ou seja, se as sessões coincidirem.


Diferenças em relação ao EAToMath:

Prós:

  • O código é mais curto e mais simples, com apenas 5 bibliotecas de plug-in. Se você precisar modificá-lo, será mais fácil de entender.

  • Os dados são mais bem compactados devido a um algoritmo diferente https://www.mql5.com/pt/code/66201. Ao salvar somente time_msc, ask e bid, até 86% dos ticks são salvos como números de 3 caracteres, ou seja, 3 bytes. Tamanho médio por tick = 3,266 Bytes ao salvar dados de tick do BTCUSDT para 2023.
    Ao salvar com volumes, a média é de 4,835 Bytes. E ao salvar o tick completo = 8,439 bytes. Abaixo está a tabela com os resultados do teste.
    Além disso, você pode usar o arquivamento ZIP integrado. O tamanho do arquivo é reduzido em duas vezes. Esse arquivo ocupa 245 Mb, enquanto a soma dos tamanhos de arquivo em .tcs para 2023 ocupa 364 Mb, ou seja, a compactação é 1,5 vezes melhor do que no MQ. E a velocidade de geração de ticks no modo matemático é aproximadamente 2 vezes mais rápida. Veja a tabela abaixo.

  • Há mais opções de salvamento:


  • O arquivo pode ser salvo em um disco SSD ou RAM, criando um link no sistema. Os arquivos podem ocupar muito espaço e a unidade RAM pode não ser suficiente, portanto, você pode optar por salvar na unidade principal. As velocidades de leitura da SSD e da RAM são praticamente as mesmas. Li que a SSD armazena em cache até 5% da capacidade total dos dados solicitados com mais frequência.
    Há um pouco de desgaste na SSD durante a leitura, pois você precisa sobrescrever as células de memória com mais frequência do que quando armazena sem ler. Não sei os números exatos, mas, por exemplo, 1 sobrescrita a cada 10 leituras ou a cada 1.000 leituras.... Mas isso é pouco significativo em comparação com o desgaste do disco pelo testador MQ.

Contras:

  • A conexão com o Virtual precisa ser feita por você mesmo (instruções aqui https://www.mql5.com/pt/code/22577), o EAToMath passará sua estratégia para o próprio Virtual.

A velocidade da variante BidAsk é comparável à do EAToMath. Outras variantes são mais lentas porque contêm mais dados ou têm compressão ZIP adicional.

Recursos de uso:

Você não pode usar as funções padrão Symbol(), Digits( ) (=4), Point() (=0,0001) na estratégia, pois elas produzirão valores padrão, não relacionados ao símbolo em teste. Em vez disso, use _Symbol, _Digits, _Point , que são substituídos por valores lidos do arquivo. Além disso, foram adicionadas novas constantes _TickSize e _TickValue com valores do símbolo registrado - elas são necessárias para o cálculo correto de lucros, comissões e swaps na moeda de depósito.

A ordem de trabalho com o período de teste selecionado ao salvar os ticks:

  1. Selecione o modo de teste por ticks reais, o instrumento necessário e as datas de teste. Defina a variável Task (Tarefa) como Save (Salvar) e selecione a opção de salvar ticks. Inicie o testador. Depois disso, um arquivo com ticks será criado na pasta especificada.

  2. Defina a variável Task como Run_Strategy. Você pode deixar o modo por ticks reais para comparar mais tarde. Inicie o testador. Os cálculos são feitos por ticks reais, não a partir do arquivo. Obtenha o resultado.


  3. Defina o modo de teste para cálculos matemáticos. Inicie o testador. Os cálculos são feitos por ticks do arquivo. Compare com o resultado da etapa 2. Ele deve ser o mesmo, mas várias vezes mais rápido.

A ordem de trabalho com o arquivo:

  1. Crie um arquivo com todos os ticks do histórico: Selecione o modo de teste por ticks reais, o instrumento necessário. Defina as datas de teste de <= primeiro tique a >= último tique no histórico disponível. Defina a variável Task como Save...To_Archive e selecione a opção de salvar ticks. Inicie o testador. Depois disso, uma pasta com o nome da ferramenta será criada na pasta especificada, onde os arquivos com ticks de cada ano serão salvos. O último ano pode ser sobrescrito conforme necessário; para isso, selecione apenas o ano atual nas datas para evitar sobrescrever os anos anteriores.
  2. Defina o modo de teste como Maths. Defina a variável Task como Run_Strategy_Fron_Archive.
  3. No MathTicker: usando o grupo de arquivos completo, defina:
    Instrument - para o nome do instrumento (deve corresponder ao nome da pasta em que os ticks estão armazenados), data inicial e final do teste.

  4. Inicie o testador. Os cálculos são feitos por ticks dos arquivos anuais necessários. Devido ao fato de o trabalho ser feito não com um arquivo, mas com vários, ele é um pouco mais lento, pois leva tempo para abrir e fechar os arquivos. Por exemplo, em vez de 1,7 segundo, serão necessários 2,7 segundos para gerar ticks para 3 anos.
  5. A soma de ticks obtida pelo Expert Advisor abaixo pode diferir em um pequeno valor de um primeiro tick. Ao testar em caracteres personalizados no modo de ticks reais, o primeiro tick produz apenas Ask ou Bid (se você não salvou ambos). Ao testar a partir do arquivo, ambos são restaurados a partir de ticks anteriores.

Um exemplo do Expert Advisor mais simples para estimar a velocidade de trabalho:

#property tester_no_cache
#include <Forester\MathTicker.mqh> // conectar a negociação no modo matemático
input int rep=0;//Repetições para otimização
sinput bool AddVolumes=true;
void OnInit(){}

void OnTick(){
   static MqlTick Tick;
   if (SymbolInfoTick(_Symbol, Tick)){
      #ifdef _MathTick_
         if(MathTick.SaveTick(Tick)){ return; }//se salvarmos os ticks, então sairemos e não negociaremos. 
      #endif
       Strategy(Tick);
   }
}
double Sum = 0;int tk=0;
void Strategy(MqlTick& Tick){ // a estratégia mais simples - usada para comparar a velocidade de leitura com o EAToMath 
   Sum += Tick.bid+Tick.ask+(AddVolumes?Tick.volume_real:0.0); tk++;
   //se(tk<100){Print(Tick.time," " ",Tick.ask," ",Tick.bid," ",Tick.last," ",Tick.volume_real," ",Tick.flags);}
}

ulong StartTime  = GetMicrosecondCount();
double OnTester(){
   #ifdef _MathTick_ // executado com o MathTick - ele conta os parâmetros de símbolo do arquivo com ticks. Para testes no modo mat
      if(MathTick.SaveTicksEnd()){return 0;}// fechar o arquivo após registrar os ticks e sair
      if(MathTick.ReadSymbolVars()){
         MathTick.Ticker();// no modo mat alimentará todos os ticks para a Strategy(MqlTick &Tick).
      }
   #endif
   Print("ticks: ",tk);
   long work_time = (long)(GetMicrosecondCount() - StartTime)/1000;
   //return(NormalizeDouble(work_time, 1)); //para obter a velocidade do trabalho e
   return Sum;// para comparar os resultados do cálculo
}

Você pode alternar 1 configuração:

//#define RestoreFlags // восстановить флаги тика из изменения ask, bid, volume - добавит 7% к времени генерации тиков 931 вместо 869 мс

Ao gerar ticks, serão exibidas estatísticas sobre a compactação de ticks.
Abaixo estão as impressões de estatísticas, volumes e tempo de geração de ticks.

-----------
Testador de MQsem volumes
pass 1 retornou o resultado 4345830621850.311523 em 0:00:08.232

Compressão C ZIP
AskBid. Tamanho do arquivo: 225 mb
-------------------- Estatísticas: --------------------
3 bytes: 86.6%, 62644158 ticks
4 bytes: 0.6%, 412167 ticks
5 bytes: 12.7%, 9185484 ticks
6 bytes: 0.0%, 15274 ticks
11 bytes: 0.1%, 46214 ticks
12 bytes: 0.0%, 1 ticks
24 bytes: 0.0%, 1 ticks
Total: 72303299 ticks, 236108596 bytes.
Média: 3.266 bytes por tick
saldo final 0.00 USD

pass 10 resultado retornado 4345830621850.311523 em 0:00:01.485
sem normalização
pass 1 resultado retornado 4345830621850.311523 em 0:00:00.892
AskBid_Zipped. Tamanho do arquivo: 106 mb
-------------------- Estatísticas: --------------------
3 bytes: 86.6%, 62644158 ticks
4 bytes: 0.6%, 412167 ticks
5 bytes: 12.7%, 9185484 ticks
6 bytes: 0.0%, 15274 ticks
11 bytes: 0,1%, 46214 ticks
12 bytes: 0,0%, 1 ticks
24 bytes: 0,0%, 1 ticks
Total: 72303299 ticks, 236108596 bytes.
Média: 3,266 bytes por tick
Tamanho não compactado: 236108596. Tamanho compactado: 111720863. Compressão ZIP: 47,3%

pass 10 retornou o resultado 4345830621850.311523 em 0:00:02.548
sem normalização
pass 2 retornou o resultado 4345830621850.311523 em 0:00:01.890



Testador de MQ com volumes
passagem 1 retornou o resultado 4345879117123.356445 em 0:00:07.962

Compressão C ZIP
AskBidVolume. Tamanho do arquivo: 333 mb
-------------------- Estatísticas: --------------------
4 bytes: 60.4%, 43684907 ticks
5 bytes: 1.1%, 809676 ticks
6 bytes: 33.5%, 24194111 ticks
7 bytes: 4.9%, 3548666 ticks
8 bytes: 0.0%, 7909 ticks
12 bytes: 0.1%, 40022 ticks
13 bytes: 0.0%, 17964 ticks
14 bytes: 0.0%, 2 ticks
19 bytes: 0.0%, 41 ticks
32 bytes: 0.0%, 1 ticks
Total: 72303299 ticks, 349571243 bytes.
Média: 4.835 bytes por tick

pass 1 resultado retornado 4345879117123.356445 em 0:00:02.803
sem normalização
pass 4 resultado retornado 4345879117123.356445 em 0:00:01.659
AskBidVolume_Zipped. Tamanho do arquivo: 204 mb
-------------------- Estatísticas: --------------------
4 bytes: 60.4%, 43684907 ticks
5 bytes: 1.1%, 809676 ticks
6 bytes: 33.5%, 24194111 ticks
7 bytes: 4.9%, 3548666 ticks
8 bytes: 0.0%, 7909 ticks
12 bytes: 0,1%, 40022 ticks
13 bytes: 0,0%, 17964 ticks
14 bytes: 0,0%, 2 ticks
19 bytes: 0,0%, 41 ticks
32 bytes: 0,0%, 1 ticks
Total: 72303299 ticks, 349571243 bytes.
Média: 4,835 bytes por tick
Tamanho não compactado: 349571243. Tamanho compactado: 214897079. Compressão ZIP: 61,5%

pass 2 retornou o resultado 4345879117123.356445 em 0:00:04.260
sem normalização
pass 2 retornou o resultado 4345879117123.356445 em 0:00:03.096
Todos. Tamanho do arquivo: 582 mb
-------------------- Estatísticas: --------------------
8 bytes: 61.5%, 44494583 ticks
9 bytes: 33.5%, 24194111 ticks
10 bytes: 4.9%, 3548666 ticks
11 bytes: 0.0%, 7909 ticks
15 bytes: 0.1%, 40022 ticks
16 bytes: 0.0%, 17964 ticks
17 bytes: 0.0%, 2 ticks
22 bytes: 0.0%, 41 ticks
44 bytes: 0.0%, 1 ticks
Total: 72303299 ticks, 610166056 bytes.
Média: 8.439 bytes por tick

pass 2 retornou o resultado 4345879117123.356445 em 0:00:03.768
sem normalização
pass 1 retornou o resultado 4345879117123.356445 em 0:00:02.256
All_Zipped. Tamanho do arquivo: 245 mb
-------------------- Estatísticas: --------------------
8 bytes: 61.5%, 44494583 ticks
9 bytes: 33.5%, 24194111 ticks
10 bytes: 4.9%, 3548666 ticks
11 bytes: 0.0%, 7909 ticks
15 bytes: 0.1%, 40022 ticks
16 bytes: 0,0%, 17964 ticks
17 bytes: 0,0%, 2 ticks
22 bytes: 0,0%, 41 ticks
44 bytes: 0,0%, 1 ticks
Total: 72303299 ticks, 610166056 bytes.
Média: 8,439 bytes por tick
Tamanho não compactado: 610166056. Tamanho compactado: 257105213. Compressão ZIP: 42,1 %

pass 1 retornou o resultado 4345879117123.356445 em 0:00:05.388
sem normalização
pass 10 retornou o resultado 4345879117123.356445 em 0:00:03.936

O tamanho dos arquivos .tcs para o mesmo ano de 2023:

Todas as variantes com ZIP, até mesmo o salvamento completo de ticks, são mais compactas (3,5 a 1,5 vezes).

Exemplo de Expert Advisor para negociação virtual e saída de relatório:

#property tester_no_cache

#include <MT4Orders.mqh> // https://www.mql5.com/pt/code/16006
#include <Forester\MathTicker.mqh> // conectar a negociação no modo matemático

#define  ORDER_CURRENCY_DIGITS 2 // Configuração de dígitos para calcular o lucro/comissão/troca quando colocado no histórico de negociação.
#define  VIRTUAL_LIMITS_TP_SLIPPAGE // Limitadores e TPs são executados no primeiro preço de aceitação - slippages positivos
#define  ORDER_COMMISSION -0 // Atribuição de comissão = Lotes * ORDER_COMMISSION. 
#include <fxsaber\Virtual\Virtual.mqh> // https://www.mql5.com/pt/code/22577


#define  REPORT_TESTER             // O testador registrará automaticamente os relatórios
#define  REPORT_BROWSER            // Criação de um relatório com inicialização do navegador - requer permissão da DLL.
#define  USE_highcharts //- Você pode baixar e experimentar todos os produtos Highcharts gratuitamente. Quando seu projeto/produto estiver pronto para ser lançado, adquira uma licença comercial. https://shop.highcharts.com/
#include <MT4Orders_QuickReport.mqh>//


enum VirtTyp {MQ_Tester=0,Virtual1=1,Virtual2=2};
sinput VirtTyp tester1=1;//Testador 1
sinput VirtTyp tester2=2;//Testador 2

input int rep=0;//Repetições para otimização

bool isOptimization = false, isTester=false; double balInit=0;
VIRTUAL_POINTER Virtual[10];

void OnInit(){
   Virtual[0] = 0; // 0 - ambiente de negociação real
   Virtual[1] = VIRTUAL::Create(AccountBalance()); // Virtualização criada 1.
   Virtual[2] = VIRTUAL::Create(AccountBalance()); // Virtualização criada 2.
   //Virtual[tester1].Select();
   isOptimization = MQLInfoInteger(MQL_OPTIMIZATION) ;
   isTester = MQLInfoInteger(MQL_TESTER);
   balInit=AccountBalance();
}

void OnTick(){
   //Virtual[0].Select();
   VIRTUAL::NewTick();// enviar o tique para a máquina virtual atual
   static MqlTick Tick;
   if (SymbolInfoTick(_Symbol, Tick)){
      #ifdef _MathTick_
         if(MathTick.SaveTick(Tick)){ return; }//quando a escrita de ticks sair da função, Strategy() não será chamada
      #endif
       Strategy(Tick);//negociação
   }
}

void Strategy(MqlTick& Tick){ // a estratégia mais simples - usada para comparar a velocidade de leitura com o EAToMath 
   if(Tick.ask==0 || Tick.bid==0){return;}/O testador MQ negocia em um tick com falha, o Virtual não. Proibição também para MQ
   if(tester1>0){Virtual[tester1].Select(); VIRTUAL::NewTick(Tick);}//selecione a virtualização 1 e envie um tique
   if(tester2>0){Virtual[tester2].Select(); VIRTUAL::NewTick(Tick);}//selecione a virtualização 2 e envie um tique
   if(isNewHour(Tick.time)){//o primeiro tique de cada hora
      if(GetHour0(Tick.time) % 2==0){// comprar em horas pares no testador 1
         Virtual[tester1].Select();//selecionar virtualização 1
         OrderSend(_Symbol, OP_BUY, 1, Tick.ask, 0, Tick.ask - 100 * _Point, Tick.ask + 100 * _Point); 
      }else{//vender em horários estranhos no testador 2
         Virtual[tester2].Select();//selecionar virtualização 2
         OrderSend(_Symbol, OP_SELL, 1, Tick.bid, 0, Tick.bid + 100 * _Point, Tick.bid - 100 * _Point);   
      } 
   }
}

double OnTester(){
   #ifdef _MathTick_ // executado com o MathTick - ele lerá os parâmetros do símbolo no arquivo de ticks. Para testes no modo mat
      if(MathTick.SaveTicksEnd()){return 0;}//retorno após salvar os ticks
      if(MathTick.isMath && MathTick.ReadSymbolVars()){
         if(tester1==0){Alert("   >>>>>>>>>   Virtual tester 1=MQ. In math mode can be used only virtual tester.   <<<<<<<<");return 0;}
         if(tester2==0){Alert("   >>>>>>>>>   Virtual tester 1=MQ. In math mode can be used only virtual tester.   <<<<<<<<");return 0;}

         SYMBOL_BASE sb; sb.Point=_Point; sb.Digits=_Digits; sb.Symbol=_Symbol; sb.SymbolID=0; sb.TickSize=_TickSize; sb.TickValue=_TickValue / _TickSize;//this.TickValue_ /= this.TickSize_; //como em SetSymbol() em \fxsaber\Virtual\Symbol_Base.mqh
         Virtual[1].Select(); VIRTUAL::SetSymbolBase(sb); Virtual[2].Select(); VIRTUAL::SetSymbolBase(sb);
         //minFreezeLevel = _minFreezeLevel*_Point; minStopLevel = _minStopLevel*_Point;

         Virtual[tester1].Select();
         MathTick.Ticker();// no modo mat alimentará todos os ticks para a Strategy(MqlTick &Tick). 
      }
   #endif

  double ret_val=0;
  for (int v = 0 ; v <= VIRTUAL::Total(); v++){
    if(Virtual[v].Select()){
      if(v > 0){
         VIRTUAL::Stop();
         #ifdef _MathTick_ // executado com o MathTick - ele lerá os parâmetros do símbolo no arquivo de ticks. Para testes no modo mat
            if(MathTick.isMath){ VIRTUAL::CalcSwaps( MathTick.swapShort, MathTick.swapLong, 0, MathTick.swap3days ); }//trocas do arquivo de ticks
            else{VIRTUAL::CalcSwaps( _Symbol, 0 );}
         #else
           VIRTUAL::CalcSwaps( _Symbol, 0 );//calcular swaps - todas as negociações têm um swap, ou seja, se houver mais de dois instrumentos diferentes, ambos terão o swap do símbolo principal.
         #endif
      }// fechar negociações incompletas ao preço do último tick, como no testador

      if( !isOptimization){QuickReport("report_"+(string)v, true, v,false,true);}
      Print((string)v+" AccountBalance = ",AccountBalance(), "   AccountEquity = ",AccountEquity());
      double prib=AccountBalance()-balInit;
      ret_val += prib; //
  }}
  return ret_val;// para comparar os resultados do cálculo
}



bool isNewHour  (datetime &t){ static int next_h=-1; if(t < next_h){ return false; } else { next_h = (GetHour0(t)+1)*3600;return true;}}
int GetHour0    (datetime &t){return((int)( t / 3600));}//horário atual a partir de 1 de janeiro de 1971

Esse exemplo cria duas máquinas virtuais com negociações diferentes. Nas horas pares, um testador está comprando e o outro está vendendo nas horas ímpares.

É um exemplo complexo com dois testadores, mas pode ser simplificado se você precisar trabalhar com um testador.

Você também pode selecionar o testador MQ e compará-lo com os resultados dos testadores virtuais para controlar a exatidão dos cálculos. Somente a comissão pode não coincidir, pois há muitas comissões diferentes e somente uma variante está programada no testador virtual.

Traduzido do russo pela MetaQuotes Ltd.
Publicação original: https://www.mql5.com/ru/code/65821

Função para calcular o tamanho do lote a partir do risco por depósito Função para calcular o tamanho do lote a partir do risco por depósito

A função calcula o tamanho do lote de uma posição aberta. O preço de abertura de uma transação, o preço do nível de stop loss e o risco por transação em porcentagem do depósito são passados como parâmetros

ATR Cycles ATR Cycles

Um filtro de volatilidade baseado em 3 ATRs: um ATR rápido, um ATR médio e um ATR lento

SAR ADX Signal SAR ADX Signal

Sinal SAR ADX com notificação móvel, reescrito a partir da versão MT4 (a fonte não foi mais encontrada). Esse é um indicador repintável, portanto, tenha cuidado ao usá-lo.

Velas coloridas do Momentum Estocástico Velas coloridas do Momentum Estocástico

Ideia de Andrey F. Zelinsky, com base em um indicador de William Blau