Aprender e escrever juntos em MQL5 - página 35

 

Quem sabe se posso passar uma função a um não membro de uma classe como argumento para uma referência (endereço) a outra função que não seja membro de nenhuma classe?

Ou, posso passar uma função a um membro da classe como argumento uma referência (endereço) a outra função que não seja membro de nenhuma classe?

Документация по MQL5: Основы языка / Типы данных / Структуры и классы
Документация по MQL5: Основы языка / Типы данных / Структуры и классы
  • www.mql5.com
Основы языка / Типы данных / Структуры и классы - Документация по MQL5
 
victorg:

Quem sabe se posso passar uma função a um não membro de uma classe como argumento para uma referência (endereço) a outra função que não seja membro de nenhuma classe?

Ou, posso passar uma função a um membro da classe como argumento uma referência (endereço) a outra função que não seja membro de nenhuma classe?

Não. Não.

Não pode. Na MQL5 não existe uma noção como "um endereço de função" ou "uma referência de função".

 

Obrigado!

Outra questão.

Existem dois ficheiros com código em mql5.O primeiro ficheiro é o principal - indicador ou script. O segundo ficheiro émqh.

// f_01.mqh
double extfunc(int a);
//-------------------------------------
double example(void)
  {
  double a;
  a=extfunc(35);
  return(a);
  }
//-------------------------------------
Osegundoficheiro mqh- está ligado ao ficheiro principal logo no início. A compilação do ficheiro principal passa sem erros ou avisos. Mas quando tento compilar o ficheiro mqh- separadamente , recebo ' função deve ter a body'.A minha pergunta é, como posso dizer ao compilador que não há nada de errado com a função, mas o seu corpo está num ficheiro diferente?


Документация по MQL5: Файловые операции / FileMove
Документация по MQL5: Файловые операции / FileMove
  • www.mql5.com
Файловые операции / FileMove - Документация по MQL5
 
victorg:

O segundoficheiro mqh- está incluído no início do ficheiro principal. A compilação do ficheiro principal não contém erros nem avisos. Mas ao tentar compilar o ficheiro mqh- separadamente , obtemos ' função deve ter a body'. Aminha pergunta é: como dizer ao compilador que não há nada de errado com a função, mas que o seu corpo está num ficheiro diferente?
Não há maneira de o fazer. Não o rasgue, não facilita a compreensão ao ler o código.
 
Yedelkin:

Posso estar a exagerar, mas aqui vai outra questão. Antes de enviar um pedido para colocar uma ordem de mercado (para abrir uma posição), reajusto um bilhete de troca para zero, ou seja, faço result.deal=0. Podemos esperar que o servidor devolva um ticket de troca nulo na estrutura de resposta MqlTradeResult, mas um pouco mais tarde, a troca será executada e a posição será aberta? Ou a devolução de um bilhete de troca nulo pelo servidor garante que a posição não poderá ser aberta e que não será mais aberta com base neste pedido?

OK, em virtude da falta de resposta e em virtude desta linha

struct MqlTradeResult
{
ulong deal; // Ticket to deal, se foi feito
};

Concluo que a devolução de um bilhete de negócio nulo pelo servidor garante que a posição não pode ser aberta e que não será mais aberta com base neste pedido.

 

Não compreendo bem a estrutura do fórum, se não estiver lá, por favor dirija-me na direcção certa

Uma vez que não sou especialista, mas estou interessado em programar e proceder a partir das minhas próprias inclinações no processo de formação, estou a tentar compreender, analisando o código existente

Para simplificar, peguei num código personalizado de MA , e tentei compreender o que ocorre nele (reflecti-o nos comentários)

Em geral, se não for difícil, por favor comente sobre o código, quero compreender o que acontece após cada comando. Obrigado.

nulo CalcularSimplesMA(int taxas_total,int prev_calculado,int inicio,const duplo & preço[])//I figurei-o & preço[]

  {
   int i,limit;
//--- first calculation or number of bars was changed
   if(prev_calculated==0)// first calculation
     {
      limit=InpMAPeriod+begin;                                               //почему переменная begin=0 ???
      //--- set empty value for first limit bars
      for(i=0;i<limit-1;i++) ExtLineBuffer[i]=0.0;                            //здесь инициализируются значения индикатора на барах с индексами от 0 до limit-1 ??? крайне правых на графике???
      //--- calculate first visible value
      double firstValue=0;                                                    //при инициализации переменной имеющей тип double не обязательно использовать значения типа double???
      for(i=begin;i<limit;i++)
         firstValue+=price[i];                                               //разобрался, здесь идет накопление переданной цены
      firstValue/=InpMAPeriod;
      ExtLineBuffer[limit-1]=firstValue;                                      
     }
   else limit=prev_calculated-1;                                              //в результате чего prev_calcutated не должно равняться 0, если индикатор поместили на оффлайн график?
//--- main loop
   for(i=limit;i<rates_total && !IsStopped();i++)                              //цикл для индикатора на баре с индексами от limit до последнего на графике
      ExtLineBuffer[i]=ExtLineBuffer[i-1]+(price[i]-price[i-InpMAPeriod])/InpMAPeriod;
//---
  }

colocá-lo na impressão e ver que os valores no ExtLineBuffer são atribuídos desde o limite-1 do índiceaté às taxas de índice_total-1, mas no gráfico o indicador é desenhado em todo o espaço, hmm, então onde está a atribuição de valores aobuffer do indicador no intervalo de 1 até ao limite-1???

Документация по MQL5: Основы языка / Операции и выражения / Операции присваивания
Документация по MQL5: Основы языка / Операции и выражения / Операции присваивания
  • www.mql5.com
Основы языка / Операции и выражения / Операции присваивания - Документация по MQL5
 
Profi_R:

Não compreendo bem a estrutura do fórum, se não estiver lá, por favor dirija-me na direcção certa

Uma vez que não sou especialista, mas estou interessado em programar e proceder a partir das minhas próprias inclinações no processo de formação, estou a tentar compreender, analisando o código existente

Por simplicidade, peguei num código personalizado de MA , e tentei compreender o que se passa nele (reflecti-o nos comentários)

Quero compreender o que acontece após cada comando. Obrigado.

Não vou comentar em detalhe, pode ser suficiente para corrigir o erro básico da sua percepção, e então você mesmo vai montar o puzzle - isso é muito mais útil.

Assim, a base da sua confusão é que muitos indicadores em mql5 (este em particular) são escritos sem indexação de buffers indicadores, ou seja, com o valor AsSeries=false.

Isto significa que o índice da barra mais antiga da história = 0 e o "mais fresco" = RatesTotal-1.

// Está algo claro?

O objectivo desta abordagem é algum ganho de velocidade, porque a indexação não requer recálculo [oculto] ao aceder ao buffer (permanece "hardware")

// Talvez a (errada) crença de que a indexação por amortecedores indicadores SEMPRE ocorre desde o fim da história até ao início. Isto é sempre verdade em mql4, mas não é necessário em mql5.

// Aqui, a direcção da indexação é sempre desde o início da história até ao seu fim por defeito. Para inverter a indexação, deve usar explicitamente a função SetAsSeries(...).

// Nota, os programadores não recomendam a utilização de padrões (no caso de mudarem) e usam SEMPRE a função SetAsSeries() para definir a direcção de indexação.

nulo CalcularSimplesMA(int taxas_total,int pré_calculado,int início,const duplo & preço[])//I ordenado & preço[]

coloque-o na impressão e veja que os valores no ExtLineBuffer são atribuídos do limite-1 de índicea taxas de índice_total-1, mas no gráfico o indicador é desenhado em todo o espaço, hmm, então onde está o valor atribuído aobuffer do indicador no intervalo de 1 a limite-1?

Penso que pode descobrir por si próprio, mas, por via das dúvidas, vou verificar isso amanhã.
 
MetaDriver: ..

Obrigado pelo seu feedback).

Li sobre a ordem de directividade em arrays e recomendações para especificar explicitamente a directividade na ajuda, mas tive algumas dúvidas, que foram eliminadas após a desactivação dos dados intermédios nas variáveis.

Até agora, apenas a direccionalidade é determinada, ou seja, o comentário sobre inicialização estava incorrecto e os valores do tampão indicador são inicializados no intervalo especificado no lado esquerdo do gráfico.

Há ainda questões sobre

1. a variável começa, o terminal é responsável pelo seu valor passado para o manipulador do evento?

2. Pode uma variável de tipo duplo ser passada para o tipo int?

3. parece que o terminal também é responsável pelo valor da variável pré-calculada

4. não é claro onde se realiza o cálculo do indicador no intervalo de 0 a limite-1?

Документация по MQL5: Основы языка / Функции / Функции обработки событий
Документация по MQL5: Основы языка / Функции / Функции обработки событий
  • www.mql5.com
Основы языка / Функции / Функции обработки событий - Документация по MQL5
 
Profi_R:

Há ainda questões sobre

1. a variável começa, o terminal é responsável pelo seu valor enviado para o manipulador do evento?

3. parece que o valor da variável pré_calculada é também responsável pelo terminal

Muito provavelmente, a função em discussão foi escrita para a primeira forma de chamada de função OnCalculate(). Ver Referência.

Profi_R:

Ainda temos perguntas sobre

2) Uma variável do tipo duplo pode ser substituída por um valor do tipo int?

Sim, pode. Ver a secção sobre conversões de tipo implícito. O compilador emitirá frequentemente um aviso sobre possível perda de dados quando se utiliza a conversão de tipo implícito.

Profi_R:

Ainda existem questões sobre

4. não compreendo onde é calculado o indicador no intervalo de 0 a limite-1.

Faça estas linhas responder à sua pergunta:

//--- set empty value for first limit bars
      for(i=0;i<limit-1;i++) ExtLineBuffer[i]=0.0;                            
//--- calculate first visible value
... и далее по коду
?
 
Profi_R:

Obrigado pelo seu feedback).

Li sobre a ordem de directividade em arrays e recomendações para especificar explicitamente a directividade na ajuda, mas tive algumas dúvidas, que foram eliminadas após a desactivação dos dados intermédios nas variáveis.

Até agora, apenas a direccionalidade é determinada, ou seja, o comentário sobre inicialização estava incorrecto e os valores do tampão indicador são inicializados no intervalo especificado no lado esquerdo do gráfico.

OK.

Há ainda questões sobre

1. a variável começa, o terminal é responsável pelo seu valor enviado para o manipulador do evento?

Sim, o terminal é responsável pela sua transmissão para o indicador.


Este parâmetro indica ao indicador quantos valores históricos iniciais da série de entrada devem ser ignorados (saltados), porque são incorrectos e não devem participar nos cálculos. De onde pode vir tal incorrecção, qual é a sua origem? Está relacionado com a possibilidade de criar indicadores que são calculados não sobre os dados de preços, mas sobre os dados fornecidos por outros indicadores. Em MT5 há três mecanismos que permitem receber dados de outro indicador para um input de indicador.

Método 1. sequência de passos:

Criar uma pega para o indicador de entrada usando uma das funções iIndicator(...) ou IndicatorCreate(...).

2. se necessário, tirar os seus valores dos seus amortecedores usando a função CopyBuffer(...).

A segunda via. É necessário se, no primeiro caso, quisermos passar não uma série de preços, mas uma série de indicadores para o indicador de input . Ou seja, neste caso vamos receber valores calculados pelo indicador de input (2) que toma dados de outro indicador (1) com base no seu próprio input. Ou seja, queremos construir a cadeia indicador-indicador de input.

Sequência de passos:

1. criar uma pega para o primeiro (1) indicador de entrada usando uma das funções iIndicator(...) ou IndicatorCreate(...) função.

2. criar uma pega do segundo (2) indicador usando o mesmo método, mas especificar a pega do primeiro (1) como o último parâmetro(preço aplicado_) quando o criar.

Use a função CopyBuffer(...) para recuperar os seus valores a partir dos amortecedores indicadores, conforme necessário.

O terceiro método é também utilizado para construir cadeias de indicadores, mas, ao contrário do método anterior, a fonte de dados (sequência de entrada) não é fixa antes da compilação, pode ser definida por um utilizador directamente no terminal. Ao especificar o parâmetro apropriado no momento do início do indicador.

Deixarei ao vosso critério a compreensão destes mecanismos por vós próprio. No texto anterior, forneci muitas ligações directas aos locais-chave na documentação que vos ajudará a fazer isto.

Concentremo-nos apenas nos parâmetros da forma curta da chamada da OnCalculate():

int OnCalculate(const int rates_total,
                const int prev_calculated,
                const int begin,
                const double &price[])

O seu propósito está claramente documentado. Aqui quero apenas explicar a própria necessidade (razoabilidade) de os passar para esta função. Com o primeiro e último parâmetro, espero que tudo esteja suficientemente claro. Para efectuar cálculos, devemos ter um buffer com dados de entrada (preço[]) e conhecer o seu comprimento actual . (não esquecer que o seu comprimento aumenta à medida que as aspas preenchem o terminal).

Mas, além disso, devemos também saber desde o início da linha de entrada que os seus dados são estritamente correctos ou que os valores iniciais devem ser ignorados devido à sua (possível ou garantida) incorrecção. Na maioria dos casos, a incorrecção é garantida quando os dados introduzidos são a saída de outro indicador, mas de que outra forma? A maioria dos indicadores para calcular o valor em qualquer barra deve utilizar uma certa quantidade de dados históricos. Mas onde podem ser encontrados "no início do tempo"? Não estão presentes lá, e por isso são obrigados a começar a gerar os seus valores de saída não a partir da barra inicial do histórico, mas mais tarde (à direita), a partir da barra à esquerda da qual já existe a quantidade necessária de dados históricos.

Agora, graças aos detalhes que descrevi acima, a resposta à pergunta

de onde vem o seu valor? // estamos a falar do parâmetro começa

A resposta é: apesar de este parâmetro ser passado na função pelo terminal, o indicador de entrada deve cuidar do seu conteúdo! O próprio terminal pode verificar apenas as linhas de entrada de preço (neste caso o valor de início será 0 e este é um valor correcto).Portanto, quando escreve qualquer indicador (excepto os puramente experimentais), deve certificar-se de que informa o terminal sobre o índice do início dos dados correctos no seu buffer de saída. É claro? Caso contrário, os "descendentes" deste indicador podem comer dados incorrectos muito desagradáveis e, em alguns casos, podem até adoecer... Agora, como fazê-lo, é utilizada a função PlotIndexSetInteger(), especificando o identificador da propriedade PLOT_DRAW_BEGIN. Importante! Para uma correcção a 100% da propriedade do indicador gerado, uma única chamada de PlotIndexSetInteger(....PLOT_DRAW_BEGIN, ...) em OnInit()! Porquê? Porque o nosso indicador pode ser formado por si mesmo sobre os dados de outro indicador, que tem um travessão inicial sobre a história. Ou seja, temos um valor não zero de início no histórico de entrada, e não há possibilidade de o receber no OnInit().

  PlotIndexSetInteger(MySymbol,PLOT_DRAW_BEGIN,MyBeginPeriod-1+begin);

E temos de o fazer (de preferência uma vez) no OnCalculate(), porque no OnInit o valor do início é desconhecido.

O que, naturalmente, nos deixa também o direito de fazer uma chamada preliminar (embora não muito significativa)

  PlotIndexSetInteger(MySymbol,PLOT_DRAW_BEGIN,MyBeginPeriod);

no OnInit().

Isto é exactamente o que é feito nesse indicador (Custom Moving Average.mq5) do qual retirou a sua amostra para estudar.

2. Uma variável do tipo duplo pode ser do tipo int?

Sim, uma variável de tipo duplo pode ser inicializada sem dor com um valor de tipo int, se for definida por uma constante. // que é exactamente o que podemos fazer no seu exemplo.

3. parece que o terminal também é responsável pelo valor da variável pré_calculada

Há aqui uma subtileza. Na maioria dos casos, este valor será igual ao valor devolvido pela função OnCalculate() na chamada anterior. Por outras palavras, de facto, está nas suas mãos. Por outro lado, à primeira chamada haverá um valor zero. E além disso, o valor pode ser redefinido (pelo terminal) para zero sempre, quando o terminal o desejar. Por exemplo, isto pode acontecer durante a correcção de cotações por um corretor, durante o reinício da comunicação após uma interrupção, durante a reinicialização de um indicador anterior (input) e assim por diante.

4. não é claro onde no intervalo de 0 a limite-1 o indicador é calculado

Neste caso, estes valores não podem ser calculados correctamente (não temos historial suficiente para os cálculos). É por isso que lhes são simplesmente atribuídos valores zero.

// Prefiro atribuir-lhes os dados de entrada correspondentes, mas isso não altera a essência da questão.

Razão: