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

 

Inglês (original): Gostaria de fazer uma solicitação de recurso de idioma MQL. Se este não for o tópico correto, informe-me. A solicitação original está no fórum em inglês ...

Russo (tradução do Google): Gostaria de fazer uma solicitação de recurso de idioma MQL. Se este não for o tópico correto, por favor, me avise. A solicitação original está no fórum em inglês ...

 

Como preencher uma matriz com uma linha?

struct clr_struct{
   color uncheck;
};
clr_struct clr[];

//clr[0].uncheck=0x999999;
//clr[1].uncheck=0x999999;

clr[].uncheck={0x999999,0x999999};//как правильно?
 
Pavel Kolchin preencher uma matriz com uma linha?
clr_struct clr[] = {{0x999999}, {0x999999}};
 

Mais um lifehack para direitos de acesso: Se você tiver um desejo irresistível de conceder acesso a campos/funções privados de uma classe para outra classe, poderá fazer o seguinte usando ferramentas MQL padrão:

Precisamos: fazer o acesso a A::f1() de B

//--------- как было
class   A
  {
   int               m;
   int               f1() {return m;}                       // нужно дать к нему доступ классу B
public:
                     A(int a): m(a) {}
  };

class B {};

Vamos reescrever dessa forma:

class A;
class B
  {
private:
   class AB
     {
   public:
      virtual int    CallAf1(A&) const  = 0;
                     AB() {ABptr = &this;}
     } static *ABptr;

   // внутри B используем  этот метод для получения доступа к A::f1()
   static int        CallAf1(A & obj)
     {
      return ABptr.CallAf1(obj);
     }

public:
   class AB2: AB {};

   // вспомогательный метод - только для проверки
   static void       _f1_test(A & obj)
     {
      Print("test ", CallAf1(obj));
     }
  };
B::AB *B::ABptr = NULL;

class   A
  {
   int               m;
   int               f1() {return m;}
public:
                     A(int a): m(a) {}

   //--  добавлено
private:
   class AB3: B::AB2
     {
      int            CallAf1(A &obj) const {return obj.f1();}
     }   static  const     ABlink;
  };
const A::AB3 A::ABlink;

Para chamar (A)a.f1() dentro de B, chame CallAf1(a). Se f1() tiver parâmetros, nós os adicionaremos a CallAf1().

Teste:

void OnStart()
  {
    A f(2);
    B::_f1_test(f);
  }

Você pode tornar CallAf1() protegida, mas isso será um grande buraco nos direitos de acesso - em qualquer lugar do código, você pode criar um descendente da classe B e, nele, um método público para chamar CallAf1() - ou seja, todos terão acesso a A::f1().


P.S. A construção é muito complicada (se você quiser, pode colocá-la em macros), mas tem uma vantagem sobre o friend C++: ela não dá acesso a todos os membros da classe, mas apenas aos selecionados.

 
mktr8591 #:

Mais uma dica de vida para direitos de acesso: Se você tiver um desejo irresistível de conceder acesso a campos/funções privados de uma classe para outra classe, poderá fazer isso usando as ferramentas MQL padrão

Demorei muito tempo para entender isso... boa jogada com a virtualização, obrigado!
 
fxsaber #:
Demorou muito tempo para entrar no assunto... boa jogada com a virtualização, obrigado!
A única coisa que não escrevi no início é que você não pode criar mais nenhum objeto da classe B::AB2 (e seus descendentes), caso contrário, tudo vai desmoronar :-)
 
A execução desse Expert Advisor no Testador no modo de todos os símbolos
input int inTmp = 0; // https://www.mql5.com/ru/forum/321656/page90#comment_44727856

bool Res = true;

// Проверяет, нормализована ли цена по алгоритму NormalizeDouble.
bool IsNDPrice( const double &Price )
{
  return(Price == NormalizeDouble(Price, 5));
}

// Проверяет, нормализована ли цена, как при парсинге или ручном вводе.
bool IsNDPrice2( const double &Price )
{
  return(Price == (double)DoubleToString(Price, 5));
}

void OnTick()
{
  MqlTick Tick;
  
  if (SymbolInfoTick(_Symbol, Tick))
//    Res &= IsNDPrice(Tick.bid) && IsNDPrice(Tick.ask); // OnTester == 1.
    Res &= IsNDPrice2(Tick.bid) && IsNDPrice2(Tick.ask); // OnTester == 0.
}

double OnTester()
{
  return(Res);
}
mostra que todos os preços são normalizados usando o algoritmo NormalizeDouble. E que, se você trabalhar com preços obtidos não do Terminal, mas por análise ou entrada manual, eles exigirão normalização para a operação correta. Não há necessidade de se enganar.
 

REASON_ACCOUNT (mesmo que a conta não seja alterada, mas apenas o login seja feito novamente), o Expert Advisor é completamente descarregado e uma nova cópia é carregada.

Por esse motivo, o ExpertRemove no OnDeinit não afeta a nova cópia, pois toca a cópia descarregada.

void OnInit() { Print(__FUNCSIG__); }

void OnDeinit( const int ) { Print(__FUNCSIG__); }


Resultado após o relogin.

2023.02.07 11:33:12.717 Test5-3 (EURUSD,M1)     void OnDeinit(const int)
2023.02.07 11:33:13.926 Test5-3 (EURUSD,M1)     void OnInit()


Após o Deinit, a nova cópia do EA aguarda mais de um segundo (até dois segundos) para iniciar. Quais são os motivos de uma espera tão longa e é possível acelerá-la?

 

SymbolInfoTick retornará o tick mais recente em cada uma dessas três chamadas. Ou seja, a chamada coleta de ticks sem pular os indicadores é questionável, para dizer o mínimo.


Prova da impossibilidade de coletar ticks por um indicador (sem pulos).

// Аналог Sleep для индикатора.
void Sleep2( const uint Pause )
{
  const uint StartTime = GetTickCount();
  
  while (!IsStopped() && (GetTickCount() - StartTime) < Pause)
    ;
}

#define  TOSTRING(A) #A + " = " + (string)(A) + " "

int OnCalculate( const int rates_total,
                 const int,
                 const datetime &time[],
                 const double &open[],
                 const double &high[],
                 const double &low[],
                 const double &close[],
                 const long &tick_volume[],
                 const long &volume[],
                 const int &spread[] )
{  
  static const int period = PeriodSeconds();
  
  Sleep2(1000); // Расчеты.
  
  MqlTick Tick[1];
  
  if (SymbolInfoTick(_Symbol, Tick[0]) &&
      ((Tick[0].bid != close[rates_total - 1]) || // Свежий бар не соответсвует последнему тику.
       Tick[0].time / period > time[rates_total - 1] / period))
  {
    ArrayPrint(Tick);
    Print(TOSTRING(time[rates_total - 1]) + TOSTRING(close[rates_total - 1]));
  }

  return(rates_total);
}


Resultado.

                 [time]   [bid]   [ask] [last] [volume]    [time_msc] [flags] [volume_real]
[0] 2023.02.07 16:28:39 1.54951 1.54959 0.0000        0 1675787319322      98       0.00000
time[rates_total-1] = 2023.02.07 16:28:00 close[rates_total-1] = 1.5495 

                 [time]   [bid]   [ask] [last] [volume]    [time_msc] [flags] [volume_real]
[0] 2023.02.07 16:28:40 1.54948 1.54959 0.0000        0 1675787320719      98       0.00000
time[rates_total-1] = 2023.02.07 16:28:00 close[rates_total-1] = 1.5495 

                 [time]   [bid]   [ask] [last] [volume]    [time_msc] [flags] [volume_real]
[0] 2023.02.07 16:28:41 1.54952 1.54960 0.0000        0 1675787321823     100       0.00000
time[rates_total-1] = 2023.02.07 16:28:00 close[rates_total-1] = 1.54954 

                 [time]   [bid]   [ask] [last] [volume]    [time_msc] [flags] [volume_real]
[0] 2023.02.07 16:28:42 1.54954 1.54961 0.0000        0 1675787322223     102       0.00000
time[rates_total-1] = 2023.02.07 16:28:00 close[rates_total-1] = 1.54951 00000000002 

                 [time]   [bid]   [ask] [last] [volume]    [time_msc] [flags] [volume_real]
[0] 2023.02.07 16:28:43 1.54955 1.54964 0.0000        0 1675787323721     100       0.00000
time[rates_total-1] = 2023.02.07 16:28:00 close[rates_total-1] = 1.54948 

                 [time]   [bid]   [ask] [last] [volume]    [time_msc] [flags] [volume_real]
[0] 2023.02.07 16:28:44 1.54954 1.54962 0.0000        0 1675787324323     100       0.00000
time[rates_total-1] = 2023.02.07 16:28:00 close[rates_total-1] = 1.54952 

                 [time]   [bid]   [ask] [last] [volume]    [time_msc] [flags] [volume_real]
[0] 2023.02.07 16:28:45 1.54956 1.54962 0.0000        0 1675787325421     102       0.00000
time[rates_total-1] = 2023.02.07 16:28:00 close[rates_total-1] = 1.54952
 
Uma das possíveis construções da linguagem MQL5.

Fórum sobre negociação, sistemas de negociação automatizados e teste de estratégias de negociação

Erros, bugs, perguntas

fxsaber, 2023.02.14 13:11

input string inStr = "B2";

class A {};

class B1 : public A {};
class B2 : public A {};
// .....
class B100 : public A {};

void OnStart()
{
  A* a = New2(inStr); // создает объект, который прописан в inStr.
}

// Решение.
template <typename T>
A* New( const string &ClassName ) { return((typename(T) == ClassName) ? new T : NULL); }

typedef A* (*TNew)( const string& );
static const TNew FuncNew[] = {New<B1>, New<B2>, /*....,*/ New<B100>};

A* New2( string ClassName )
{  
  A* Res = NULL;
  
  ClassName = "class " + ClassName;
  
  for (int i = ArraySize(FuncNew) - 1; !Res && (i >= 0); i--)
    Res = FuncNew[i](ClassName);  
    
  return(Res);
}

Infelizmente, a MQL4 ainda não faz esse tipo de trabalho.