vorher_berechnet - Seite 6

 
Man braucht nur nicht mit Nüssen auf Eisen zu schlagen.
 
Alexey Viktorov:
Dies steht NICHT in der Dokumentation! Es handelt sich also um einen Aufsatz über ein freies Thema. Genau wie meine Aussage über die automatische Initialisierung, sogar noch cooler. Wenigstens hatte meine einen Haftungsausschluss...

Es ist unmöglich, in der Dokumentation alles genau zu beschreiben.

Wenn "prev_calculate==0" - bedeutet dies, dass wir den gesamten Indikatorpuffer durchgehen müssen. Wenn "prev_calculate!=0", dann wird nur der ganz rechte Balken oder mehrere neue Balken berechnet (wir verwenden Limit):

                const int &spread[])
  {
//---
   if(prev_calculated==0)
     {
      Print("prev_calculated==0");
            for(int i=0;i<rates_total;i++)
              {
               //--- здесь принудительно каждому элементу массива присваиваем значение (мне лень писать эти массивы :) )
      
              }
      return(rates_total);
     }
//--- экономный пересчёт только самого правого бара или новых баров
   int limit=rates_total-prev_calculated+1;

//--- а ниже нужно использовать цикл для обсчета самого правого бара или новых баров
   for(int i=0;i<limit;i++)
     {
      ExtBuffer[i]=чевой-то там;
     }
 
Karputov Vladimir:

Es ist unmöglich, in der Dokumentation alles genau zu beschreiben.

Wenn "prev_calculate==0" - bedeutet dies, dass wir den gesamten Indikatorpuffer durchgehen müssen. Wenn "prev_calculate!=0", dann wird nur der ganz rechte Balken oder mehrere neue Balken berechnet (wir verwenden Limit):

                const int &spread[])
  {
//---
   if(prev_calculated==0)
     {
      Print("prev_calculated==0");
            for(int i=0;i<rates_total;i++)
              {
               //--- здесь принудительно каждому элементу массива присваиваем значение (мне лень писать эти массивы :) )
      
              }
      return(rates_total);
     }
//--- экономный пересчёт только самого правого бара или новых баров
   int limit=rates_total-prev_calculated+1;

//--- а ниже нужно использовать цикл для обсчета самого правого бара или новых баров
   for(int i=0;i<limit;i++)
     {
      ExtBuffer[i]=чевой-то там;
     }




Was ist der Wert? Ich benötige keine Werte außer dem Balken ganz rechts. ABER!!! Wenn sich dann dieser ganz rechte nach links verschiebt, müssen diese Daten gespeichert werden...

Sie müssen nicht alle Puffer schreiben, aber Sie könnten einen schreiben, der meine Wünsche berücksichtigt. Wenn es sich um den ersten Lauf handelt, sollte der gesamte Verlauf leer sein. Wenn prev_calculated als Ergebnis des History Swapping zurückgesetzt wurde, sollte ALLES, was in den Puffer gestellt wurde, unverändert bleiben. Auch wenn es Löcher gibt.

 
Karputov Vladimir:

Vorläufige Schlussfolgerungen:

1. Indikatoren können sich nicht auf die Initialisierung von Indikator-Arrays in OnInit() verlassen:

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- indicator buffers mapping
...
   ArrayInitialize(balance, 0.0);    // принудительная
   ArrayInitialize(equityMax, 0.0);  // инициализация
   ArrayInitialize(equityMaxB, 0.0); // всех
   ArrayInitialize(equityMin, 0.0);  // буферов
   ArrayInitialize(equityMinB, 0.0); // индикатора

...
//---
   return(INIT_SUCCEEDED);
  }

2. Bei Indikatoren ist es obligatorisch, das gesamte Array oder nur geänderte Elemente in OnCalculate() zu durchlaufen.

Was reden Sie da für einen Unsinn? Wenn diese Initialisierung in OnCalculate implementiert ist, wird sie ohne Schleifen initialisiert. Aber wenn prev_calculated, löscht es alle Daten, die während der Arbeit angesammelt wurden...
 
Alexey Viktorov:
Warum reden Sie so einen Unsinn? Wenn diese Initialisierung in OnCalculate eingefügt wird, wird sie ohne Zyklen auf Null gesetzt. Aber wenn wir prev_calculated auf Null setzen, werden alle Daten gelöscht, die sich während des Vorgangs angesammelt haben...
Bitte verwenden Sie Ausdrücke. Und schauen Sie sich Beispiele für Indikatoren aus der Standardauslieferung an: Datenkatalog\MQL5\Indikatoren\Beispiele\.
 
Alexey Viktorov:

Was ist das wert? Ich benötige keinen anderen Wert als den Balken ganz rechts. ABER!!! Wenn sich dann der ganz rechte nach links verschiebt, müssen diese Daten gespeichert werden...

...

Ich habe bereits einen Weg vorgeschlagen:

Forum zum Thema Handel, automatisierte Handelssysteme und Testen von Handelsstrategien

vorher_berechnet

Karputov Vladimir, 2016.10.18 15:11

Entschuldigen Sie die Verzögerung bei der Beantwortung. Die einzige Möglichkeit, berechnete Werte für einen bestimmten Zeitraum zu speichern, besteht darin, sie in einer Datei zu speichern. Sie müssen sich um die Synchronisierung kümmern, damit die Daten beim Lesen aus der Datei auf ihren Balken platziert werden. Der logischste Weg ist die Synchronisierung mit der Öffnungszeit des Balkens, aber es kann einige Nuancen geben: zum Beispiel war die Öffnungszeit des Balkens (gespeichert in einer Datei) 2016.09.05. 25:02, aber jetzt gibt es einen Balken auf dem Diagramm mit der Zeit gleich 2016.09.05. 25:01.

Ein Indikator ist weder eine Datenbank noch ein Repository.

Wenn der Indikator also Daten anzeigt, die dann nicht auf der Historie berechnet werden können, ist es nur notwendig, den Indikatorpuffer in einer Datei zu speichern und dann (im Falle des History Swapping) die Datei und die Balken zu lesen und zu synchronisieren.
 
Karputov Vladimir:

Ich habe bereits einen Weg vorgeschlagen:

Ein Indikator ist weder eine Datenbank noch ein Repository.

Wenn also der Indikator die Daten anzeigt, die dann nicht auf der Historie berechnet werden können, dann müssen wir nur den Indikatorpuffer in einer Datei speichern und dann (im Falle des Pagings der Historie) das Lesen durchführen und die Datei und die Balken synchronisieren.

Alexey Viktorov:

... und vorzugsweise ohne in eine Datei oder noch mehr in GV zu schreiben.

prev_calculated
prev_calculated
  • www.mql5.com
Форум трейдеров MQL5.community
 

Vladimir, da Sie dieses Thema speziell prev_calculated gewidmet haben, machen Sie es für dieses Thema nützlich. Zunächst sollten Sie das Problem angeben, das normalerweise bei dieser Variablen auftritt. Wenn Sie mit diesen Problemen nicht vertraut sind, werde ich Folgendes formulieren

---

a-- auch wenn in der Hilfe steht

prev_calculated  // обработано баров на предыдущем вызове

Der Grund dafür ist (so steht es in der Hilfe und wurde von den Entwicklern mitgeteilt), dass die Variable auf Null zurückgesetzt wird, wenn sich die Prüfsumme ändert, in der Regel aufgrund eines History Swaps.

---

b - Sie können prev_calculated == 0 auch nicht als Flag des ersten Laufs von onCalculate verwenden. Aus demselben Grund

---

c - und Sie können prev_calculated == 0 auch nicht als History-Paging-Flag verwenden

---

Um die Benutzer nicht zu überfordern, sollte die Formulierung kurz und eindeutig sein: Wenn beim aktuellen Aufruf von OnCalculate kein History Paging stattgefunden hat, enthält prev_calculated die Anzahl der beim vorherigen Aufruf verarbeiteten Takte. Wenn es passiert ist - wird es auf Null zurückgesetzt

---

Alle 3 genannten Probleme können mit Krücken gelöst werden. Da MT5 jedoch per Definition keine Krücken haben kann, Vladimir, könnten Sie eine attraktive Lösung für diese drei Probleme entwickeln? Eine hässliche Variante sieht etwa so aus:

#property indicator_chart_window
#property indicator_buffers  0
#property indicator_plots    0


struct BROWNIE {
  int   i_Prew_Calculated;  // кол-во посчитанных баров
  bool  b_First_Run;        // флаг первого запуска
  bool  b_History_Updated;  // флаг обновления истории
  
  BROWNIE() {
    i_Prew_Calculated = WRONG_VALUE;
    b_First_Run = true;
    b_History_Updated = false;
  }
  
  void f_Reset(bool b_Reset_First_Run = true) {
    i_Prew_Calculated = WRONG_VALUE;
    if(b_Reset_First_Run) b_First_Run = true;
    b_History_Updated = false;
  }
  
  void f_Update(int i_New_Prew_Calculated = WRONG_VALUE) {
    if(i_New_Prew_Calculated > -1) {
      b_History_Updated = i_New_Prew_Calculated == 0 && i_Prew_Calculated > WRONG_VALUE;
      if(b_First_Run) b_First_Run = false;
      
      if(i_Prew_Calculated == WRONG_VALUE) i_Prew_Calculated = i_New_Prew_Calculated;
      else if(i_New_Prew_Calculated > 0) i_Prew_Calculated = i_New_Prew_Calculated;
    }
  }
};
BROWNIE go_Brownie;


int OnInit(void) {return(INIT_SUCCEEDED);}


void OnDeinit(const int reason) {
  go_Brownie.f_Reset(reason != REASON_CHARTCHANGE);
}



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 &TickVolume[],
    const long &Volume[],
    const int &Spread[]
) {
  if(go_Brownie.b_First_Run) {/* обработка 1го запуска */}
  if(go_Brownie.b_History_Updated) {/* обработка обновления истории */}
  go_Brownie.f_Update(prev_calculated);
  
  return(rates_total);
}

Haftungsausschluss: Code - nur eine Idee, ich habe ihn nicht an einer Karte ausprobiert.

In OnDeinit gibt es ein Beispiel - Verarbeitung für den Indikator, der keine Puffer verwendet, es kümmert sich nicht um TF und Symbol, bei jeder Änderung von TF/Symbol gibt es keine Notwendigkeit, von vorne zu beginnen. Es arbeitet zum Beispiel mit vorhandenen grafischen Elementen, gibt Informationen über den Kontostand, Aufträge usw. aus.

---

Übrigens

Karputov Vladimir:

Wenn diese Option aktiviert ist, muss nur der Indikatorpuffer in einer Datei gespeichert werden und dann (im Falle des Ladens der Historie) die Datei und die Balken gelesen und synchronisiert werden.

Sie müssen die Diskette nicht zerstören, sondern können sie in einem Kartenelement speichern.
 
Alexey Viktorov:
... und vorzugsweise ohne Schreiben in eine Datei oder noch mehr in einen GV.
Wäre das etwas für Sie?
 
Konstantin Gruzdev:
Vielleicht ist das etwas für Sie?

Ich bin nicht ins Detail gegangen, aber das Problem wird durch diese Codezeile gelöst. Kopieren eines Arrays in sich selbst mit einer Indexverschiebung.

double arr[5];
ArrayCopy(arr, arr, 0, 1, 4);
// и дальнейшее заполнение 4го индекса массива.
Sie können es auch umkehren und vom Null-Index kopieren und vom ersten einfügen. Dann wird der Null-Index des Arrays aufgefüllt. Und das ist eine ganz andere Sache...))