O artigo parece bastante discutível (apenas alguns pontos).
Qual é a classe que você mencionou aqui?
// Variável de membro da classe - created once double prices[]; void OnTick() { // Reutilizar a matriz existente for(int i = 0; i < 1000; i++) { prices[i] = iClose(_Symbol, PERIOD_M1, i); } // Processar os dados... }
Pela presença do manipulador OnTick e pela forma como a matriz é acessada, fica implícito que você adicionou a matriz de preços ao escopo global, o que é uma má ideia (devido à poluição do namespace, caso a matriz seja necessária apenas no escopo do manipulador). Provavelmente seria mais apropriado manter o código inicial do mesmo exemplo, mas tornar a matriz estática; dessa forma, todos veriam claramente a diferença:
// Abordagem eficiente (aloca a matriz uma única vez, podendo ajustar seu tamanho se necessário) void OnTick() { // Isso NÃO create (nor allocate) array on every tick static double prices[]; ArrayResize(prices, 1000); // Preencher a matriz com os dados de preços for(int i = 0; i < 1000; i++) { prices[i] = iClose(_Symbol, PERIOD_M1, i); } // Processar os dados... }
Além disso, se você substituir Array of Structures (AoS) por Structure of Arrays (SoA) para OHLCV — o acesso aos preços da mesma barra precisa de mais referências (alternando entre matrizes em vez de incrementar o deslocamento dentro de uma única estrutura) e torna o processo mais lento, mas tais operações são muito comuns.
Para este exemplo com OHLCV, a fim de torná-lo mais adequado em termos de eficiência de memória e tempo, provavelmente seria mais interessante agrupar todos os valores em uma única matriz 2D ou mesmo 1D:
double TOHLCV[][6];
Isso é possível porque todos os valores dos tipos (double, datetime, long) têm o mesmo tamanho de 8 bytes e podem ser convertidos uns para os outros diretamente.
Para este exemplo com OHLCV, a fim de torná-lo mais adequado em termos de eficiência de memória e tempo, provavelmente seria mais interessante agrupar todos os valores em uma única matriz 2D ou mesmo 1D:
Uma matriz 2D em vez de uma matriz de estruturas pode economizar um pouco de tempo de processador, mas aumentará consideravelmente o tempo que o desenvolvedor gasta no desenvolvimento e na manutenção do código. Na minha opinião pessoal. Concordo com o restante de suas afirmações.
https://www.mql5.com/pt/articles/17693#sec2
Vejamos um exemplo problemático:
// Abordagem ineficiente — cria novos arrays a cada tick void OnTick() { // Isso cria uma nova matriz a cada tick double prices[]; ArrayResize(prices, 1000); // Preencher a matriz com os dados de preços for(int i = 0; i < 1000; i++) { prices[i] = iClose(_Symbol, PERIOD_M1, i); } // Processar os dados... // A matriz acabará sendo recolhida pelo gerenciador de memória, mas isso // gera desperdício desnecessário de memória }
Uma abordagem mais eficiente seria:
// Variável de membro da classe - criada uma única vez double prices[]; void OnTick() { // Reutilizar a matriz existente for(int i = 0; i < 1000; i++) { prices[i] = iClose(_Symbol, PERIOD_M1, i); } // Processar os dados... }
O artigo parece bastante discutível (apenas alguns pontos).
Qual é a classe que você mencionou aqui?
Pela presença do manipulador OnTick e pela forma como a matriz é acessada, fica implícito que você adicionou a matriz de preços ao escopo global, o que é uma má ideia (devido à poluição do namespace, se a matriz for necessária apenas no escopo do manipulador). Provavelmente seria mais apropriado manter o código inicial do mesmo exemplo, mas tornar a matriz estática; dessa forma, todos veriam claramente a diferença:
Pelo que entendi, esse exemplo (que citei acima) é, grosso modo, pseudocódigo. Ou seja, o autor não presta atenção ao seguinte (para se concentrar no que exatamente está falando, eu acho):
- A julgar pela condição do loop, o tamanho da matriz é conhecido em tempo de compilação, mas, mesmo assim, a matriz é dinâmica.
- Embora a matriz seja dinâmica, ArrayResize não foi chamado no código que demonstra a abordagem eficiente.
- Em termos de eficiência, suspeito que seria melhor substituir todo o loop a seguir por uma única chamada a CopySeries:
// Reutilizar a matriz existente for(int i = 0; i < 1000; i++) { prices[i] = iClose(_Symbol, PERIOD_M1, i); }
Em termos de eficiência, acho que seria melhor substituir todo o loop a seguir por uma única chamada a CopySeries:
Corrija-me se eu estiver errado, mas, pelo que me lembro, cada chamada iClose contém uma chamada CopySeries por baixo do capô.
Este artigo apresenta um conteúdo perspicaz e instigante para discussão.
A apresentação técnica é clara e bem explicada, facilitando a compreensão do leitor e mantendo seu interesse.
Muito obrigado.
Em artigos como este, são necessários testes comparativos motivadores, que demonstrem de fato a eficácia das abordagens propostas.
A tradução está um pouco confusa; sem analisar o código, não é fácil compreendê-la.
- Aplicativos de negociação gratuitos
- 8 000+ sinais para cópia
- Notícias econômicas para análise dos mercados financeiros
Você concorda com a política do site e com os termos de uso
Novo artigo Gerenciamento Avançado de Memória e Técnicas de Otimização em MQL5 foi publicado:
O MQL5 é inegavelmente poderoso, mas com esse poder vem responsabilidade, especialmente quando se trata de memória. Muitos desenvolvedores focam exclusivamente na lógica da estratégia, nos pontos de entrada e no gerenciamento de risco, enquanto o tratamento da memória silenciosamente se transforma em uma bomba-relógio em segundo plano. À medida que seu código cresce, processando mais símbolos, frequências mais altas e conjuntos de dados mais pesados, ignorar a memória pode levar a gargalos de desempenho, instabilidade e oportunidades perdidas.
Neste artigo, vamos analisar o que acontece por trás dos bastidores. Exploraremos como a memória realmente funciona no MQL5, as armadilhas comuns que desaceleram seus sistemas ou causam falhas e, mais importante ainda, como corrigi-las. Você aprenderá técnicas práticas de otimização que tornam seus programas de negociação mais rápidos, mais leves e mais confiáveis.
Veja onde o uso eficiente de memória realmente faz diferença:
Negociação de Alta Frequência: Cada milissegundo é uma vantagem potencial ou uma perda potencial.
Análise Multitemporal: Combinando gráficos? Espere que a pressão sobre a memória se multiplique.
Lógica Complexa de Indicadores: Matemática avançada e grandes conjuntos de dados podem fazer tudo parar se não forem gerenciados adequadamente.
Backtests com Grandes Históricos: Sem uma otimização inteligente, os backtests podem parecer tão lentos quanto assistir tinta secar.
Se você está pronto para levar desempenho a sério, vamos mergulhar no assunto e tornar seus sistemas MQL5 tão eficientes quanto inteligentes.
Autor: Sahil Bagdi