Características da linguagem mql5, subtilezas e técnicas - página 50

 
fxsaber:

Este é um problema menor. Sim, o otimizador do compilador ainda não sabe como otimizar tais momentos de string. Mas é a atribuição de cordas que é o problema da desaceleração.

Eu acredito que é a principal. O que seria mais eficiente: atribuição mais rápida de strings ou sua exclusão do código? É claro que há casos em que precisamos de uma atribuição de cordel per se, mas com que frequência temos isso? Na grande maioria dos casos, estamos lidando apenas com variáveis temporárias.

E a rapidez com que estas operações de cordas podem ser implementadas também é uma questão. Você faz parecer como se pudesse ser acelerado muitas vezes. Eu duvido. Eles já otimizaram-sobre-optimizaram tudo lá muitas vezes. Suponha que eles conseguem espremer mais 20-30%, não fará diferença.

A propósito, não tentou declarar a variável string como constante?

Então, se estás a escrever algo assim.

if ((OrderSymbol() == Symb) && (OrderMagicNumber == Magic))

é sempre melhor empurrar a cláusula OrderSymbol para o fim da condição geral.

Bem, é claro. E não tem nada a ver com OrderSymbol, ou MQL. As operações com cordas são caras por si só, por isso não as deves usar em vão.

 

E assim, no meio

fxsaber:

Por exemplo, se executarmos um tique real no FIBO durante um mês, será cerca de 1 milhão de tiquetaques. Se em cada tick você conseguir o valor do PositionGetString e compará-lo com algo, o desempenho será aceitável, mas se você primeiro atribuir o resultado da função a uma variável string e depois compará-la, a duração da execução aumentará em cerca de um segundo.


Se parece uma coisa pequena, é uma visão equivocada. Quando essa EA é executada em modo de otimização para vários milhares de passes, esse segundo extra se traduz em horas adicionais de tempo de espera. Ou seja, uma atribuição de cordas inofensiva pode causar horas adicionais de espera durante a otimização. Tenha cuidado e leve esta nuance em conta.

Espero que você mesmo entenda que esta abordagem é extremamente ineficiente. Por que devemos ter o PositionGetString em cada carrapato? O que é que isso pode mudar aí? Especialmente considerando que você mesmo abriu esta posição, ou seja, tudo já é conhecido de antemão.

Bem, se estamos a falar de optimização da velocidade, então temos primeiro de optimizar a própria lógica do programa.

 
Alexey Navoykov:

E o quão rápido estas operações de cordas podem ser aceleradas também é uma questão. Você faz parecer como se pudesse ser acelerado muitas vezes. Eu duvido. Eles já otimizaram-sobre-optimizaram tudo lá muitas vezes. Mesmo que você consiga apertar 20-30% mais, isso não fará diferença.

De vez em quando.

A propósito, você não tentou declarar uma variável de string como constante?

Sim, eu fiz.
 
Alexey Navoykov:

Porquê colocar o PositionGetString em cada tick? O que pode mudar aí? Especialmente considerando que você mesmo abriu esta posição, ou seja, tudo já é conhecido de antemão.

Bem, se estamos a falar de optimizar o desempenho, então temos primeiro de optimizar a própria lógica do programa.

Um robô de combate com tal lógica: não deve haver posições abertas no EURUSD em tal intervalo de tempo. Se houver algum, fecha-os.

Você tem uma posição aberta no GBPUSD. Como podemos cumprir a condição acima sem verificar o OrderSymbol em cada tick?

Ou você sugere escrever uma versão especial do Expert Advisor apenas para o testador? Aqui, uma pessoa comprou um robô de combate e está a testá-lo. Como explicar no Mercado que tudo é otimizado pela velocidade?

 
fxsaber:

Um robô de combate com esta lógica - não deve haver posições em aberto no EURUSD neste intervalo de tempo. Se houver, fecha-os.

Você tem uma posição aberta no GBPUSD. Como podemos cumprir a condição acima sem verificar o OrderSymbol em cada tick?

Ou você sugere escrever uma versão especial do Expert Advisor apenas para o testador? Aqui, uma pessoa comprou um robô de combate e está a testá-lo. Devemos escrever no Mercado que tudo é especialmente otimizado pela velocidade para o testador?

Bem, é suficiente verificar apenas os bilhetes das posições actualmente abertas (e assim manter um conjunto delas). Se houver um novo bilhete, então todas as outras verificações devem ser realizadas com ele. Porque devemos verificar a mesma coisa um milhão de vezes?

A propósito, a MQL5 tem eventos comerciais. Portanto, não há necessidade de verificar em cada carrapato.

 
Alexey Navoykov:

Bem, é suficiente verificar apenas os tickers das actuais posições abertas (e manter um array delas de acordo com isso).

Isto não vai ser muito mais barato.

E a propósito, a MQL5 tem eventos comerciais. Portanto, não há necessidade de verificar todas as carraças.

Às vezes são escritas soluções multiplataforma. Além disso, não há e não pode haver garantia de obter todos os eventos comerciais.

 
fxsaber:

Não seria muito mais barato.

A diferença entre operações de números inteiros não é muito mais barata do que operações de cordas? Bem, como queiras.

 
Alexey Navoykov:

A diferença entre operações de números inteiros não é muito mais barata do que operações de cordas? Bem, como queiras.

Não vejo porque precisas disso, mas deixaste-me perplexa. E tenho de concordar que a opção com uma variedade de bilhetes seria mais produtiva.

É verdade, do ponto de vista de alguma lógica, tal variante parece muito artificial, colocada sobre uma nuance técnica, em vez de uma construção lógica do programa.

Mas vou levar isso em conta na mesma. Claro, nunca encontrei esta abordagem na kodobase.

 

A falta de herança múltipla na MQL é deprimente, é claro. No entanto, você pode fazê-lo funcionar de qualquer forma possível - com modelos e macros - você não vai precisar deles )

Aqui está o que eu fiz. Todas as classes de origem devem ser declaradas como modelos que definem a classe pai.

class CBase { };  // базовый класс

// Макросы, задающие список наследования:

#define  INHERIT1(T)  T<CBase>

#define  INHERIT2(T1, T2)  T2<INHERIT1(T1)>

#define  INHERIT3(T1, T2, T3)  T3<INHERIT2(T1,T2)>

#define  INHERIT4(T1, T2, T3, T4)  T4<INHERIT3(T1,T2,T3)>


// Различные пользовательские классы:

template<typename TParent>
class A : public TParent { public: void a() { Print("A"); } };

template<typename TParent>
class B : public TParent { public: void b() { Print("B"); } };

template<typename TParent>
class C : public TParent { public: void c() { Print("C"); } };


class X : public INHERIT3(A, B, C)  {  };   // Объявляем класс, наследуемый от A, B, C


template<typename T>
void SomeFunc(B<T>& obj)  { obj.b(); }   // Проверочная функция, принимающая класс B


void OnInit()
{
  X x;
  x.a();
  x.b();
  x.c();
  
  SomeFunc(x);
}

Claro que existem algumas subtilezas, relacionadas com o facto de as classes serem herdadas sequencialmente (na ordem que estabelecemos), em vez de em paralelo (como em herança múltipla verdadeira). Em particular, eles terão prioridades diferentes quando ocorrer uma sobrecarga. Além disso, se uma mesma classe template participar várias vezes na cadeia de herança, serão classes completamente diferentes, não relacionadas uma com a outra de forma alguma. Por isso temos de ter cuidado aqui. Mas não há problema com as interfaces, você pode herdar sem restrições.

 
Alexey Navoykov:

A falta de herança múltipla na MQL é deprimente, é claro. No entanto, você pode fazê-lo funcionar de qualquer forma possível - com modelos e macros - você não vai precisar deles )

Aqui está o que eu fiz. Todas as classes de origem devem ser declaradas como modelos que definem a classe pai.

Claro que existem algumas subtilezas, relacionadas com o facto de as classes serem herdadas sequencialmente (na ordem que estabelecemos), em vez de concomitantemente (como em herança múltipla verdadeira). Em particular, eles terão prioridades diferentes quando ocorrer uma sobrecarga. Além disso, se uma mesma classe template participar várias vezes na cadeia de herança, serão classes completamente diferentes, não relacionadas uma com a outra de forma alguma. Por isso temos de ter cuidado aqui. Mas não há problemas com interfaces, você pode herdar sem limitações.

É um bom truque. O truque todo está em aplicar o padrão à TParent. Nunca o vi assim antes.

Razão: