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

 
Igor Makanu:

IsInf() e IsNaN() estão a funcionar,

IsEqual() e IsZerro() são questionáveis, pesquisadas no Google a partir de algumas fontes como "truque para o dobro".

IsNan() funciona, mas IsInf() não

IsInf( DBL_MIN_DENORM) == true

Desde quando é que os números desnormalizados se tornaram infinitos?

E todas estas comparações com o epsilon - epsilon deve ser aumentado proporcionalmente aos operandos. Em geral, não há receita universal, uso Point como epsilon (com operandos arredondados) e não quero (e não preciso) comparar a diferença com DBL_EPSILON.

 
Vict:

E todas estas comparações com o epsilon - epsilon deve ser aumentado proporcionalmente aos operandos. Em geral, não há receita universal, uso Point como epsilon (com operandos arredondados), não quero comparar a diferença com DBL_EPSILON(e não preciso de o fazer).

encontrei um artigo que li ontem da TVhttps://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/

Sim, deve utilizar outro exemplo em que deve especificar a exactidão da comparação

Vitória:

IsNan() funciona, mas IsInf() não

Desde quando é que os números desnormalizados se tornaram infinitos?

MQL parece normalizar a 8º dígito, ou seja, se NormalizeDouble() for adicionado a IsInf(), o resultado ainda não será melhor.

 
Igor Makanu:

a normalização em MQL parece ser de até 8 dígitos, ou seja, se NormalizeDouble() for adicionado a IsInf(), o resultado ainda não é melhor

A normalização em MQL não é de todo a mesma, não sei porque nomearam a função dessa forma. https://ru.wikipedia.org/wiki/%D0%94%D0%B5%D0%BD%D0%BE%D1%80%D0%BC%D0%B0%D0%BB%D0%B8%D0%B7%D0%BE%D0%B2%D0%B0%D0%BD%D0%BD%D1%8B%D0%B5_%D1%87%D0%B8%D1%81%D0%BB%D0%B0

 
Descobri acidentalmente em ME que se pode criar marcadores de página com CTRL+1, CTRL+2, ..... E alternar entre eles com ALT+1, ALT+2, ...
 
// Количество успешных OrderSend.
int GetOrderSendSucceeded()
{
  MqlTradeRequest Request = {0};
  MqlTradeResult Result;

  return(OrderSend(Request, Result) ? 0 : (int)Result.request_id + 1);
}

Mostra quantas ordens de comércio síncronas bem sucedidas (OrderSend) e assíncronas geradas no Terminal no total (desde o início).

Utilizo-o no Testador (no final) para ver quantas vezes as encomendas foram modificadas.

 
Há poucas pessoas que não sabem como criar aulas de TC com os seus próprios On-events, por exemplo.

Fórum sobre comércio, sistemas automatizados de comércio e testes de estratégia comercial

OnTick() não funciona numa instância de classe?

fxsaber, 2019.10.31 23:45

class BASE
{  
private:
  static BASE* Objects[];
  
public:
  BASE()
  {
    BASE::Objects[::ArrayResize(BASE::Objects, ::ArraySize(BASE::Objects) + 1) - 1] = &this;
  }
  
  ~BASE()
  {
    const int Size = ::ArraySize(BASE::Objects);
    
    for (int i = Size - 1; i >= 0; i--)
      if (BASE::Objects[i] == &this)
      {
        for (int j = i; j < Size - 1; j++)
          BASE::Objects[j] = BASE::Objects[j + 1];
          
        ::ArrayResize(BASE::Objects, Size - 1);
        
        break;
      }
  } 
    
  virtual void OnTick() = 0;
  
  static void AllTick()
  {
    for (int i = ::ArraySize(BASE::Objects) - 1; i >= 0; i--)
      BASE::Objects[i].OnTick();
  }
};

static BASE* BASE::Objects[];


class A : BASE
{
  virtual void OnTick()
  {
    Print(__FUNCSIG__);
  }
};

class B : BASE
{
  virtual void OnTick()
  {
    Print(__FUNCSIG__);
  }
};

A a;
B b;

void OnTick()
{
  BASE::AllTick();
}


Herdar da BASE, então os métodos OnTick em classes serão chamados automaticamente.

 

Um exemplo de utilização de X Macro (não se importe com os tipos obscuros, arranquei-o do código de trabalho. Vector é uma matriz dinâmica):

Por exemplo:

   vector_fund<upindex_t> seg2; vector_ref<vector_fund<upindex_t>> seg2_sub;
   vector_fund<upindex_t> seg3; vector_ref<vector_fund<upindex_t>> seg3_sub;
   vector_fund<upindex_t> seg4; vector_ref<vector_fund<upindex_t>> seg4_sub;
   for (uint i = 0;  i < 5114;  ++ i) {
      restore_image(seg2, "seg2"); restore_subimages(seg2_sub, "seg2");
      restore_image(seg3, "seg3"); restore_subimages(seg3_sub, "seg3");
      restore_image(seg4, "seg4"); restore_subimages(seg4_sub, "seg4");
      
      if (true) {} // тест №1, использует seg2 и seg2_sub
      if (true) {} // тест №2, использует seg3 и seg3_sub
      if (true) {} // тест №3, использует seg4 и seg4_sub
   }

1. queremos definir os vectores por detrás do laço para evitar afectações constantes.

2. Cada um dos testes pode ser desactivado (na verdade, são muitos).

3. restore_image() e restore_subimages(), uma função pesada e muito demorada (leitura dos objectos do gráfico a partir do gráfico).

4. Se nenhum dos testes utilizar seg2, por exemplo, gostaria de remover tanto a definição como a restauração correspondente...() numa única acção, para evitar uma situação em que o vector é definido mas vazio devido à restauração comentada...(), o que daria resultados erróneos.

O que fazer?

#define  DEFSEG_LIST    \
   DEFSEG_HELPER(seg2) \
   DEFSEG_HELPER(seg3) \
   DEFSEG_HELPER(seg4)
   
#define  DEFSEG_HELPER(SEG) vector_fund<upindex_t> SEG; vector_ref<vector_fund<upindex_t>> SEG##_sub;
    DEFSEG_LIST;
#undef  DEFSEG_HELPER
   
   for (uint i = 0;  i < 5114;  ++ i) {
#define  DEFSEG_HELPER(SEG) restore_image(SEG, #SEG);  restore_subimages(SEG##_sub, #SEG);
    DEFSEG_LIST;
#undef  DEFSEG_HELPER
      ...
   }

Basta comentar o segx desnecessário em DEFSEG_LIST. Isto irá gerar os mesmos resultados que no primeiro código. Na verdade, é uma pena que o compilador não consiga mostrar a saída do processador (o análogo gcc -E).

 

Por vezes, na optimização genética, os primeiros milhares de passes são suficientes para compreender já mais ou menos o resultado.

Quando se executam automaticamente muitas optimizações, quer-se que tudo corra mais rápido. É por isso que vamos precisar de um mecanismo para interromper a optimização.

#include <fxsaber\MultiTester\MTTester.mqh>  // https://www.mql5.com/ru/code/26132

// Выключает Оптимизацию ( и одиночный проход)
bool OptimizationStop( void )
{
  return(!MTTESTER::IsReady() && MTTESTER::ClickStart(false));
}


Utilização.

// Демонстрация прерывания Оптимизации.

sinput int inAmountPasses = 20; // Через сколько проходов закончить
input int Range = 0; // 0..10000

double OnTester()
{
  int Data[];
  
  return(FrameAdd(NULL, 0, 0, Data)); // Сгенерировали TesterPass
}

void OnTesterPass()
{
  static int Amount = 0;
  
  ulong Pass;
  string Name;
  long ID;
  double Value;
  int Data[];

  while (FrameNext(Pass, Name, ID, Value, Data))
    if (++Amount > inAmountPasses)
    {
      OptimizationStop(); // Как достигли нужного количества проходов, выключили оптимизатор.
      
      break;
    }
}
 

Instruções para a abertura de um gráfico com um carácter Nulo.


  1. Eliminar todos os gráficos do Market Watch.
  2. Iniciar a optimização de um quadro EA (por exemplo, este) em modo matemático.
  3. Parar a Optimização e remover a moldura EA da tabela dos símbolos Null.
Um tal gráfico pode provavelmente ser útil para poupar recursos.
 
Encontrei esta peculiaridade.
class A
{
  static int i;
} a; // unresolved static variable 'A::i'

static int A::i = 0;

A b; // Надо прописывать после static


Se uma classe com campos estáticos for imediatamente criada quando uma classe com campos estáticos for definida, haverá um erro de tempo de compilação.