Imparare e scrivere insieme in MQL5 - pagina 35

 

Chi sa se posso passare una funzione a un non membro di una classe come argomento di un riferimento (indirizzo) a un'altra funzione che non è membro di nessuna classe?

Oppure, posso passare una funzione a un membro della classe come argomento un riferimento (indirizzo) a un'altra funzione che non è membro di nessuna classe?

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

Chi sa se posso passare una funzione a un non membro di una classe come argomento di un riferimento (indirizzo) a un'altra funzione che non è membro di nessuna classe?

Oppure, posso passare una funzione a un membro della classe come argomento un riferimento (indirizzo) a un'altra funzione che non è membro di nessuna classe?

No. No.

Non si può. In MQL5 non esiste la nozione di "indirizzo di funzione" o "riferimento di funzione".

 

Grazie!

Un'altra domanda.

Ci sonodue file con codice in mql5.Il primo file èquello principale - indicatore o script . Ilsecondo file èmqh.

// f_01.mqh
double extfunc(int a);
//-------------------------------------
double example(void)
  {
  double a;
  a=extfunc(35);
  return(a);
  }
//-------------------------------------
Ilsecondofile mqh è collegato a quello principale proprio all'inizio. La compilazione del file principale va senza errori o avvertimenti. Ma quando provo a compilare il file mqh separatamente ottengo ' lafunzione deve avere uncorpo '. Lamia domanda è: come posso dire al compilatore che non c'è niente di sbagliato nella funzione, ma il suo corpo è in un file diverso?


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

Ilsecondofile mqh è incluso all'inizio del file principale. La compilazione del file principale procede senza errori e avvertimenti. Ma quando si cerca di compilare il file mqh separatamente si ottiene ' lafunzione deve avere uncorpo '. Lamia domanda è: come dire al compilatore che non c'è niente di sbagliato nella funzione ma il suo corpo è in un file diverso?
Non c'è modo. Non strapparlo, non lo rende più facile da capire quando si legge il codice.
 
Yedelkin:

Forse sto esagerando, ma ecco un'altra domanda. Prima di inviare una richiesta per piazzare un ordine a mercato (per aprire una posizione), azzero un trade ticket, cioè faccio result.deal=0. Possiamo aspettarci che il server restituisca un trade ticket nullo nella struttura di risposta MqlTradeResult, ma un po' più tardi, il trade sarà eseguito e la posizione sarà aperta? O il ritorno di un trade ticket nullo da parte del server garantirà che la posizione non può essere aperta e non sarà ulteriormente aperta sulla base di questa richiesta?

OK, in virtù della mancanza di risposta e in virtù di questa linea

struct MqlTradeResult
{
ulong deal; // Ticket to deal, se è stato fatto
};

Concludo che il ritorno di un deal ticket nullo da parte del server garantisce che la posizione non può essere aperta e non sarà ulteriormente aperta sulla base di questa richiesta.

 

Non capisco bene la struttura del forum, se non c'è, per favore indirizzatemi nella giusta direzione

Dato che non sono uno specialista, ma sono interessato alla programmazione e procedendo dalle mie inclinazioni nel processo di formazione, sto cercando di capire analizzando il codice esistente

Per semplicità, ho preso un pezzo di codice personalizzato di MA, e cerco di capire cosa succede in esso (l'ho riflesso nei commenti)

In generale, se non è difficile, si prega di commentare il codice, voglio capire cosa succede dopo ogni comando. Grazie.

void CalculateSimpleMA(int rates_total,int prev_calculated,int begin,const double &price[])//ho capito &price[]

  {
   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;
//---
  }

mettetelo nella stampa e vedete che i valori nell'ExtLineBuffer sono assegnati dall'indice limit-1all'indice rates_total-1, ma nel grafico l'indicatore è disegnato in tutto lo spazio, hmm, allora dov'è l'assegnazione del valore albuffer dell'indicatore nell'intervallo da 1 a limit-1?

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

Non capisco bene la struttura del forum, se non c'è, per favore indirizzatemi nella giusta direzione

Dato che non sono uno specialista, ma sono interessato alla programmazione e procedendo dalle mie inclinazioni nel processo di formazione, sto cercando di capire analizzando il codice esistente

Per semplicità, ho preso un pezzo di codice personalizzato di MA, e cercare di capire cosa sta succedendo in esso (l'ho riflesso nei commenti)

Voglio capire cosa succede dopo ogni comando. Grazie.

Non commenterò in dettaglio, può essere sufficiente per correggere l'errore di base della vostra percezione, e poi metterete insieme il puzzle da soli - che è molto più utile.

Quindi, la base della tua confusione è che molti indicatori in mql5 (questo in particolare) sono scritti senza indicizzazione dei buffer degli indicatori, cioè con il valore AsSeries=false.

Significa che l'indice della barra più vecchia della storia = 0 e quella più "fresca" = RatesTotal-1.

// C'è qualcosa di chiaro?

Il punto di tale approccio è un certo guadagno in velocità, perché l'indicizzazione non richiede un ricalcolo [nascosto] quando si accede al buffer (rimane "hardware")

// Forse la convinzione (errata) che l'indicizzazione per i buffer degli indicatori avviene SEMPRE dalla fine della storia all'inizio. Questo è sempre vero in mql4, ma non è necessario in mql5.

// Qui, la direzione dell'indicizzazione è sempre dall'inizio della storia alla sua fine per default. Per invertire l'indicizzazione, si dovrebbe usare la funzione SetAsSeries(...) in forma esplicita.

// Nota, gli sviluppatori non raccomandano di usare i default (nel caso in cui cambino) e di usare SEMPRE la funzione SetAsSeries() per impostare la direzione di indicizzazione.

void CalculateSimpleMA(int rates_total,int prev_calculated,int begin,const double &price[])//Ho ordinato &price[]

mettilo nella stampa e vedi che i valori nell'ExtLineBuffer sono assegnati dall'indice limit-1all'indice rates_total-1, ma nel grafico l'indicatore è disegnato in tutto lo spazio, hmm, allora dov'è il valore assegnato albuffer dell'indicatore nell'intervallo da 1 a limit-1?

Penso che tu possa capirlo da solo, ma per sicurezza, lo controllerò di nuovo domani.
 
MetaDriver: ..

Grazie per il vostro feedback).

Ho letto dell'ordine di direttività negli array e delle raccomandazioni di specificare esplicitamente la direttività nell'aiuto, ma ho avuto alcuni dubbi, che sono stati eliminati dopo aver disinserito i dati intermedi nelle variabili.

Finora, solo la direzionalità è determinata, cioè il commento sull'inizializzazione non era corretto e i valori del buffer dell'indicatore sono inizializzati sull'intervallo specificato sul lato sinistro del grafico.

Ci sono ancora domande su

1. la variabile begin, il terminale è responsabile del suo valore passato al gestore dell'evento?

2. una variabile di tipo doppio può essere passata al tipo int?

3. sembra che il terminale sia anche responsabile del valore della variabile prev_calculated

4. non è chiaro dove avviene il calcolo dell'indicatore sull'intervallo da 0 a limite-1?

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

Ci sono ancora domande su

1. la variabile begin, il terminale è responsabile del suo valore inviato al gestore di eventi?

3. sembra che il valore della variabile prev_calculated sia anche responsabile del terminale

Molto probabilmente, la funzione in discussione è stata scritta per la prima forma di chiamata di funzione OnCalculate(). Vedere Riferimento.

Profi_R:

Abbiamo ancora domande su

2. Si può sostituire una variabile di tipo double con un valore di tipo int?

Sì, è possibile. Vedere la sezione sulle conversioni implicite dei tipi. Il compilatore darà spesso un avvertimento sulla possibile perdita di dati quando si usa la conversione implicita dei tipi.

Profi_R:

Ci sono ancora domande su

4. Non capisco dove viene calcolato l'indicatore sull'intervallo da 0 a limite-1.

Queste righe rispondono alla tua domanda:

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

Grazie per il vostro feedback).

Ho letto dell'ordine di direttività negli array e delle raccomandazioni di specificare esplicitamente la direttività nell'aiuto, ma ho avuto alcuni dubbi, che sono stati eliminati dopo aver disinserito i dati intermedi nelle variabili.

Finora, solo la direzionalità è determinata, cioè il commento sull'inizializzazione non era corretto e i valori del buffer dell'indicatore sono inizializzati sull'intervallo specificato sul lato sinistro del grafico.

OK.

Ci sono ancora domande su

1. la variabile begin, il terminale è responsabile del suo valore inviato al gestore dell'evento?

Sì, il terminale è responsabile della sua trasmissione all'indicatore.


Questo parametro indica all'indicatore quanti valori storici iniziali della serie di input devono essere ignorati (saltati), perché sono errati e non devono partecipare ai calcoli. Da dove può venire questa erroneità, qual è la sua origine? È legato alla possibilità di creare indicatori che sono calcolati non sui dati di prezzo, ma sui dati forniti da altri indicatori. In MT5 ci sono tre meccanismi che permettono di ricevere i dati di un altro indicatore per un indicatore di input.

Metodo 1. sequenza di passi:

Crea un handle per l'indicatore di ingresso utilizzando una delle funzioni iIndicator(...) o IndicatorCreate(...).

2. se necessario, prendere i suoi valori dai suoi buffer usando la funzione CopyBuffer(...).

Il secondo modo. È necessario se nel primo caso vogliamo passare all'indicatore di entrata non una serie di prezzi, ma una serie di indicatori. Cioè, in questo caso vogliamo ricevere i valori calcolati dall'indicatore di entrata (2) che prende i dati di un altro indicatore (1) in entrata. Cioè, vogliamo costruire la catena indicatore-da-indicatore.

Sequenza di passi:

1. creare un handle per il primo (1) indicatore di ingresso utilizzando una delle funzioni iIndicator(...) o IndicatorCreate(...).

2. creare un handle del secondo (2) indicatore usando lo stesso metodo, ma specificando l'handle del primo (1) come ultimo parametro(applied_price) quando lo si crea.

Usate la funzione CopyBuffer(...) per recuperare i suoi valori dai buffer degli indicatori come richiesto.

Il terzo metodo è utilizzato anche per costruire catene di indicatori, ma, a differenza del metodo precedente, la fonte di dati (sequenza di input) non è fissata prima della compilazione, può essere impostata da un utente direttamente nel terminale, specificando il parametro appropriato al momento dell'avvio dell'indicatore.

Lascio a voi il compito di capire questi meccanismi da soli. Nel testo precedente ho fornito molti link diretti ai luoghi chiave della documentazione che vi aiuteranno a farlo.

Concentriamoci solo sui parametri della forma breve della chiamata di OnCalculate():

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

Il loro scopo è chiaramente documentato. Qui voglio solo spiegare la vera necessità (ragionevolezza) di passarli in questa funzione. Con il primo e l'ultimo parametro, spero che tutto sia abbastanza chiaro. Per eseguire i calcoli, dobbiamo avere un buffer con i dati di input (price[]) e conoscere la sua lunghezza attuale . (non dimenticate che la sua lunghezza aumenta man mano che le virgolette riempiono il terminale).

Ma in aggiunta, dobbiamo anche sapere fin dall'inizio della riga di input che i suoi dati sono rigorosamente corretti o i valori iniziali devono essere ignorati a causa della loro (possibile o garantita) scorrettezza. Nella maggior parte dei casi, la scorrettezza è garantita quando i dati di input sono l'output di un altro indicatore, ma come altro? La maggior parte degli indicatori per calcolare il valore in qualsiasi barra deve utilizzare una certa quantità di dati storici. Ma dove si possono trovare "all'inizio del tempo"? Non sono presenti lì, e quindi sono costretti a cominciare a generare i loro valori di uscita non dalla barra storica di partenza, ma più tardi (a destra), dalla barra a sinistra della quale esiste già la quantità necessaria di dati storici.

Ora, grazie ai dettagli che ho descritto sopra, la risposta alla domanda

da dove viene il suo valore? // stiamo parlando del parametro begin

La risposta è: nonostante il fatto che questo parametro sia passato nella funzione dal terminale, l'indicatore di input deve occuparsi del suo contenuto! Il terminale stesso può controllare solo le righe di input dei prezzi (in questo caso il valore di begin sarà 0 e questo è un valore corretto).Pertanto, quando scrivete qualsiasi indicatore (eccetto quelli puramente sperimentali), dovreste assicurarvi che informi il terminale sull'indice dell'inizio dei dati corretti nel suo buffer di uscita. È chiaro? Altrimenti, i "discendenti" di questo indicatore possono mangiare dati errati molto sgradevoli, e in alcuni casi, possono anche ammalarsi... :) Ora, come fare, si usa la funzione PlotIndexSetInteger(), specificando l'identificatore della proprietà PLOT_DRAW_BEGIN. Importante! Per una correttezza al 100% della proprietà dell'indicatore generato, una sola chiamata di PlotIndexSetInteger(....PLOT_DRAW_BEGIN, ...) in OnInit()! Perché il nostro indicatore può essere a sua volta formato sui dati di un altro indicatore, che ha un rientro iniziale sulla storia. Cioè, abbiamo un valore non nullo di begin nella storia dell'input, e non c'è la possibilità di riceverlo in OnInit().

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

E dobbiamo farlo (preferibilmente una volta) in OnCalculate(), perché in OnInit il valore di begin è sconosciuto.

Il che naturalmente ci lascia il diritto di fare anche una chiamata preliminare (anche se non molto significativa)

  PlotIndexSetInteger(MySymbol,PLOT_DRAW_BEGIN,MyBeginPeriod);

In OnInit().

Questo è esattamente ciò che viene fatto in quell'indicatore (Custom Moving Average.mq5) dal quale hai preso il tuo campione per studiare.

2. una variabile di tipo double può essere di tipo int?

Sì, una variabile di tipo doppio può essere inizializzata senza dolore con un valore di tipo int, se è definita da una costante. // che è esattamente quello che possiamo fare nel tuo esempio.

3. Sembra che il terminale sia anche responsabile del valore della variabile prev_calculated

C'è una sottigliezza qui. Nella maggior parte dei casi, questo valore sarà uguale al valore restituito dalla funzione OnCalculate() nella chiamata precedente. In altre parole, di fatto, è nelle vostre mani. :) D'altra parte, alla prima chiamata ci sarà un valore zero. E inoltre, il valore può essere azzerato (dal terminale) sempre, quando il terminale lo vuole. Per esempio, questo può accadere durante la correzione delle quotazioni da parte di un broker, durante il riavvio della comunicazione dopo un'interruzione, durante la reinizializzazione di un precedente indicatore (di ingresso) e così via.

4. non è chiaro dove nell'intervallo da 0 a limite-1 viene calcolato l'indicatore

In questo caso, questi valori non possono essere calcolati correttamente (non abbiamo abbastanza storia per i calcoli), per questo si assegnano semplicemente valori zero.

// Preferirei assegnare loro dei dati di ingresso corrispondenti, ma non cambia l'essenza della questione.

Motivazione: