ChartNavigate durante l'inizializzazione

 

Mi sono imbattuto in un problema con la funzione ChartNavigate. Faccio qualcosa di sbagliato o c'è davvero un problema con la funzione. Scrivete se l'avete usato abbastanza spesso.

Ecco il nocciolo del problema: ChartNavigate non sposta il grafico Quando si avvia il terminale se la funzione è chiamata in OnInit(). Ho volutamente letto la documentazione diverse volte. Non c'è scritto da nessuna parte che la funzione non può essere chiamata durante l'inizializzazione.

Codice indicatore per la riproduzione:

#property indicator_chart_window 
int OnInit()
{
   if (ChartNavigate(0, CHART_END, -1000))
      Alert("Успешно");
   else
      Alert("Ошибка №", GetLastError());

   return(INIT_SUCCEEDED);
}
void OnDeinit(const int reason)
{
}
int OnCalculate(const int rates_total,
                const int prev_calculated,
                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[])
{
   return(rates_total);
}

Passi per giocare:

  1. Disattiva l'autoplay del grafico.
  2. Attacca l'indicatore al grafico. ChartNavigate si attiva spostando il grafico nella posizione desiderata.
  3. Scaricare il terminale.
  4. Caricare il terminale. ChartNavigate non funzionerà visualizzando il grafico senza un offset.
OK, se la funzione desse un errore. Ma non è così. Tutte le chiamate hanno successo, ma è quando il terminale viene ricaricato che l'offset del grafico non si verifica.

 
Si applica una funzione che funziona con il grafico. Per un indicatore, la garanzia di creazione del grafico è la prima voce in OnCalculate, per un EA è la prima voce in OnTick(). Ma non prima.
 
Vladimir Karputov:
Si applica una funzione che funziona con il grafico. Per l'indicatore la garanzia della creazione del grafico è il primo inserimento in OnCalculate, per l'Expert Advisor - il primo inserimento in OnTick(). Ma non prima.

Nessun problema. Se non c'è ancora un grafico, fate in modo che la funzione restituisca false e il codice di errore corrispondente. Ma questo non è il caso, la funzione riporta orgogliosamente un'esecuzione riuscita. Si noti che la documentazione non dice che questa è un'indicazione di successo dell'invio del messaggio al grafico. Dice chiaramente: esecuzione di successo della funzione.

Inoltre, questo è un codice per la riproduzione. Infatti, anche prima della chiamata ChartNavigate, ho una chiamata alla serie temporale. E tutti sono riempiti correttamente, come risulta. Cioè, c'è già un grafico, ci sono i suoi dati. Inoltre, è possibile leggere dal grafico gli oggetti grafici che vi sono stati collocati prima della chiusura del terminale.

Quindi, secondo tutte le indicazioni, il grafico esiste già.

 

Questo è strano. Per me funziona senza problemi.

E un'altra nota: dovete disabilitare il suo offset automatico CHART_AUTOSCROLL prima di compensare il grafico

 
Ihor Herasko:

Nessun problema. Se non c'è ancora un grafico, fate in modo che la funzione restituisca false e il codice di errore corrispondente. Ma questo non è il caso, la funzione riporta orgogliosamente un'esecuzione riuscita. Si noti che la documentazione non dice che questo è un segno di successo dell'invio del messaggio al grafico. Dice chiaramente: esecuzione di successo della funzione.

Inoltre, questo è un codice per la riproduzione. Infatti, anche prima della chiamata ChartNavigate, ho una chiamata alla serie temporale. E tutti sono riempiti correttamente, come risulta. Cioè, c'è già un grafico, ci sono i suoi dati. Inoltre, è possibile leggere dal grafico gli oggetti grafici che vi sono stati collocati prima della chiusura del terminale.

Quindi, secondo tutte le indicazioni, il grafico esiste già.

Grafico e dati sono due grandi differenze.

Tutte le funzioni che si riferiscono ai grafici sono asincrone: cioè a senso unico - sparate e dimenticate. E in questo caso vero significa solo che avete compilato correttamente i campi di questa funzione, niente di più.

Il segno quando tutti i dati sono pronti e i grafici sono tracciati è il primo input di Oncalculate/OnTick.

 
Vladimir Karputov:

Un grafico e i dati sono due grandi differenze.

Tutte le funzioni di accesso al grafico sono asincrone: cioè un viaggio a senso unico - sparato e dimenticato. In questo caso, vero significa solo che avete riempito correttamente i campi di questa funzione, niente di più.

Il segno quando tutti i dati sono pronti e i grafici sono tracciati è il primo input per Oncalculate/OnTick.

Allora come si spiega il fatto che per me funziona perfettamente? In OnInit() esattamente come nel primo post del thread... Perché ti inventi delle sciocchezze?

 
Alexey Viktorov:

Questo è strano. Per me funziona senza problemi.

Che tipo di costruzione hai? Ho il 1861.

E un'altra nota: dovreste disabilitare il suo offset automatico CHART_AUTOSCROLL prima di compensare il grafico

Sì, l'ho indicato nel primo passo per la riproduzione.

 
Ihor Herasko:

Qual è la tua costruzione? Ho il 1861.

Sì, è quello che ho indicato nel primo passo per il replay.

Ho anche il 1861. Sono riuscito a riprodurlo solo una volta. Tutti gli altri tentativi hanno funzionato bene.

 
Vladimir Karputov:

Un grafico e i dati sono due grandi differenze.

Tutte le funzioni di accesso al grafico sono asincrone: cioè un viaggio a senso unico - sparato e dimenticato.

No, non tutti. Quelli che lo fanno sono specificamente commentati. Per esempio, lo stesso ChartApplyTemplate.

In questo caso, vero significa solo che avete riempito correttamente i campi di questa funzione, niente di più.

Come ha fatto la funzione a determinare che l'ID del grafico è corretto, se il grafico stesso non esiste ancora?

Il segno quando tutti i dati sono pronti e i grafici sono tracciati è il primo input per Oncalculate/OnTick.

Sfortunatamente, no. Ecco il codice:

#property indicator_chart_window 
int OnInit()
{
   Print(__FUNCTION__, ", баров: ", Bars(Symbol(), PERIOD_CURRENT));

   return(INIT_SUCCEEDED);
}
void OnDeinit(const int reason)
{
}
int OnCalculate(const int rates_total,
                const int prev_calculated,
                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[])
{
   Print(__FUNCTION__, ", баров: ", Bars(Symbol(), PERIOD_CURRENT));
   return(rates_total);
}

Funziona così:

16:01:31.765    Test (XBNUSD,M1)        OnInit, баров: 0
16:01:33.531    Test (XBNUSD,M1)        OnCalculate, баров: 37026
16:01:34.010    Test (XBNUSD,M1)        OnCalculate, баров: 46484

Eseguo l'indicatore su un nuovo simbolo il cui grafico non è ancora stato aperto, cioè non sono ancora stati generati dati su di esso.

Nella prima linea (OnInit) non ci sono effettivamente dati. Tuttavia, c'è l'ID del grafico e possiamo creare oggetti in OnInit() che saranno visualizzati con successo sul grafico.

La seconda linea ha già dei dati, ma è incompleta. I dati sono completi alla terza iterazione.

È ragionevole concludere che la prima chiamata a OnCalculate non è una garanzia di caricamento dei dati. È semplicemente il primo tick sul simbolo dopo l'apertura del grafico, che può arrivare dopo una certa quantità di dati o senza nessun altro dato.

Tornando al problema sollevato nel topic, otteniamo che la funzione ChartNavigate() non controlla la correttezza dei parametri. Se non ci sono ancora dati in OnInit() (0 barre), e il valore -1000 viene passato alla funzione, allora come possiamo considerare questo valore corretto, se non ci sono barre? Dopo tutto, qualsiasi altra funzione restituirebbe un errore quando si accede alla barra con un indice inesistente. Ma qui ha successo. Cos'è esattamente il successo?

 

Ecco l'indicatore - appositamente messo un ritardo di nove tick, due tipi di movimento grafico e la bandiera di ridisegno forzato (on/off).

//+------------------------------------------------------------------+
//|                                                      ProjectName |
//|                                      Copyright 2012, CompanyName |
//|                                       http://www.companyname.net |
//+------------------------------------------------------------------+
#property indicator_chart_window 
#property indicator_plots 0
//--- input parameters
input bool redraw=true;
input ENUM_CHART_POSITION position=CHART_BEGIN;
//---
long count=0;
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
int OnInit()
  {
   count=0;
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
   Comment("");
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
                const int prev_calculated,
                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[])
  {
   count++;
   Comment(count);
   if(count==9)
     {
      ResetLastError();
      if(position==CHART_BEGIN)
        {
         if(ChartNavigate(0,CHART_BEGIN,100))
            Print("Успешно. redraw ",redraw,". position ",EnumToString(position));
         else
            Print("Ошибка №",GetLastError(),". redraw ",redraw,". position ",EnumToString(position));
        }
      if(position==CHART_END)
        {
         if(ChartNavigate(0,CHART_END,-100))
            Print("Успешно. redraw ",redraw,". position ",EnumToString(position));
         else
            Print("Ошибка №",GetLastError(),". redraw ",redraw,". position ",EnumToString(position));
        }
      if(redraw)
         ChartRedraw();
     }
   return(rates_total);
  }
//+------------------------------------------------------------------+


Preliminare:CHART_BEGIN èstabile.

File:
Test.mq5  6 kb
 
Vladimir Karputov:

Ecco l'indicatore - appositamente messo un ritardo di nove tick, due tipi di movimento grafico e la bandiera di ridisegno forzato (on/off)


Preliminare:CHART_BEGIN funziona regolarmente.

Ma cosa succede se non ci sono zecche, è il fine settimana? Poi il timer dovrà essere collegato.

E c'è solo una domanda da risolvere: come determinare se ChartNavigate è stato eseguito con successo? Il fatto che restituisca true, si limita a "ticchettare", non aiuta nel lavoro reale.