Fehler, Irrtümer, Fragen - Seite 741

 
ivandurak:

Ich bin kein guter Erklärer. Lassen Sie es mich noch einmal versuchen. Die Aufgabe besteht darin, ein Portfolio von Währungen zu bilden, wobei jede Währung ihre eigenen Parameter hat. In einem optimierten Portfolio darf eine Währung nicht enthalten sein. Ich habe sechs Währungen in 21 Optimierungsschritten für jede Währung berechnet, und die Gesamtsumme ist in Milliarden.

Nun die Frage. Wenn wir einer Währung verbieten, mit einer Flagge zu handeln, dann macht es keinen Sinn, ihre Parameter zu optimieren, da sie das Ergebnis in keiner Weise beeinflussen, aber der Optimierer wird versuchen, Parameter anzupassen, die das Ergebnis nicht beeinflussen. Ich weiß, dass Sie das nicht können, aber die Hoffnung ist noch nicht erloschen.

Ja, in Ordnung. Es wird unnötige Pässe geben.

Wenn TC es Ihnen erlaubt, sollten Sie jedes Paar separat optimieren.

Bei der allgemeinen Optimierung tappt man imho in die Falle der magischen Absicherung ))).

Es gibt noch eine andere Lösung, die in die andere Richtung als die von mir vorgeschlagene geht, aber unnötige Fahrten reduziert.

Zum Beispiel Ihre Aufzählung des Parameters 100 im Intervall 50-150.

Dadurch verringert sich die Zahl der Auswahlmöglichkeiten um eine Dimension.

input bool trpar2=true; // вЫключен флажок
input int grusdchf=100; // включен флажок перебора 49-150
input int grusdjpy=100; // включен флажок перебора 50-150

if (grusdchf==49)  // если 49 то запрет торговли
  {
   x_trpar2=false;
  }
 else              // иначе берет установленное значение флага и параметров
  {
   x_trpar2=trpar2;
  }

// далее по коду для запрета используем x_trpar2
 
ivandurak:

Ich bin kein guter Erklärer. Lassen Sie es mich noch einmal versuchen. Die Aufgabe besteht darin, ein Portfolio von Währungen zu bilden, wobei jede Währung ihre eigenen Parameter hat. In einem optimierten Portfolio darf eine Währung nicht teilnehmen. Ich habe sechs Währungen in 21 Optimierungsschritten für jede Währung berechnet, und die Gesamtsumme ist in Milliarden.

Nun die Frage. Wenn wir einer Währung verbieten, mit einer Flagge zu handeln, dann macht es keinen Sinn, ihre Parameter zu optimieren, da sie das Ergebnis in keiner Weise beeinflussen, aber der Optimierer wird versuchen, Parameter anzupassen, die das Ergebnis nicht beeinflussen. Auch ich weiß, dass Sie das nicht können, aber die Hoffnung schwelt noch.

Wenn ich so etwas wie Init() und Trade() für jedes Paar habe und die Parameter bereits gewählt wurden, muss ich nur noch die Aktien bestimmen, dann ist die Aufgabe gelöst. Obwohl, leider, in allgemeiner Form, für eine beliebige Anzahl von Systemen - kann nicht gelöst werden.

Wir müssen also die Schritte "Fraktionen des Systems" angeben. Bei 6 Systemen wird die Anzahl der Durchläufe mit f-eye berechnet:

int PartCount6(double _mult) {
   int __= (int)(1.0 / _mult) + 1;
   int x, y, z, t, t1, t2, count = 0;
   for (t = 0; t < __; ++t) for (x = 0; x < __; ++x) 
      for (y = 0; y < __; ++y) for (z = 0; z < __; ++z) 
         for (t1 = 0; t1 < __; ++t1) for (t2 = 0; t2 < __; ++t2) 
            if (x + y + z + t + t1 + t2 == __- 1) ++count;
   return(count);     
}

Es ist möglich, ein Skript dafür zu erstellen:

input double Mult = 0.04;

void OnStart() {
   Alert(PartCount6(Mult));
}

Außerdem hat die optimierte Aufgabe zwei Parameter - Mult (nicht optimiert) und Part - von 1 bis PartCount6(Mult) in Schritten von 1:

input double Mult  = 0.04;
input int    part = 3276;

CZ1 gbp;
CZ2 jpy;
CZ3 eursek, eur;
CZ4 audcad, sek;

int x, y, z, t, t1, t2; 

int OnInit() {
   int __= (int)(1.0 / Mult) + 1;
   int count = 0;
   for (x = 0; x < __; ++x) {
      for (y = 0; y < __; ++y) {
         for (z = 0; z < __; ++z) {
            for (t = 0; t < __; ++t) {
               for (t1 = 0; t < __; ++t1) {
                  for (t2 = 0; t2 <__; ++t2) { 
                     if (x + y + z + t + t1 + t2 == __- 1) {
                        ++count;
                        if (count == part) break; // Вот где goto был бы полезен, или break n
                     }
                  }
                  if (count == part) break;
               }
               if (count == part) break; 
            }
            if (count == part) break;
         }
         if (count == part) break;
      }
      if (count == part) break;
   }
   if (x) gbp.Init(..);//его доля - x * Mult, т. е., нужно в Init долю передавать как параметр
   if (y) jpy.Init(..); 
   if (z) eur.Init(..);
   if (t) eursek.Init(..);
   if (t1) audcad.Init(..);
   if (t2) sek.Init(...);
}

void OnTick() {
   if (x) gbp.Trade();
   if (y) jpy.Trade();
   if (z) eur.Trade();
   if (t) eursek.Trade();
   if (t1) audcad.Trade();
   if (t2) sek.Init(Trade);
}

Denken Sie daran: Je kleiner der Schritt, desto mehr Schritte müssen Sie in der Schleife durchlaufen. Wenn beispielsweise das Skript, das die Anzahl der Durchläufe berechnet, keinen Wert von mehr als 5 Minuten liefert, wäre es besser, den Schritt zu verringern. Wenn Sie den Schritt nicht verringern wollen, teilen Sie beispielsweise die Währungen in zwei Hälften auf, optimieren jede Gruppe und gehen dann wieder "als Gruppe" zusammen. (oder noch besser: Systemkorrelationen nutzen und paarweise optimieren - dann sind die Zyklen nicht so schlimm, aber das ist eine andere Geschichte).

Für eine andere Anzahl von Systemen (noch weniger, noch mehr) bleibt alles beim Alten.

 

Fast hätte ich es vergessen - nach der Optimierung müssen Sie die Brüche kennen - führen Sie also den einzelnen Durchgang aus, der Ihnen am besten gefällt, und schreiben Sie ihn in OnDeinit:

void OnDeinit(const int reason) {
  Print("x:", x * Mult, "; y:", y * Mult, "; z:", z * Mult, "; t:", t * Mult, "; t1:", t1 * Mult, "; t2:", t2 * Mult);
}
 

Ich habe diesen Fehler vor einem Jahr entdeckt und getestet und ihn sogar im Forum erwähnt.

Wie sich herausstellte, ist sie noch am Leben.

Fazit: Wenn eine virtuelle Funktion im Konstruktor aufgerufen wird, wird die Vorgängerfunktion anstelle der nativen Funktion aufgerufen.

class COracleTemplate
  {
private:
public:
   string            ClassName;
                     COracleTemplate(){Init();};
                    ~COracleTemplate(){DeInit();};
   virtual void      Init(){ClassName=this.Name();Print("loadSettings from ",ClassName);};
   virtual void      DeInit(){Print("saveSettings to ",ClassName);};
   virtual string    Name(){return("Prpototype");};
  };
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
class CCO2:public COracleTemplate
  {
   virtual string    Name(){return("CO2");};
  };
class CH2O:public COracleTemplate
  {
   virtual string    Name(){return("H2O");};
  };
COracleTemplate* CO2,*H2O;
void OnStart()
  {
   CO2=new CCO2;
   CO2.Init();
   Print(CO2.Name()," ClassName=",CO2.ClassName);
   delete CO2;
   
   H2O=new CH2O;
//   H2O.Init();
   Print(H2O.Name()," ClassName=",H2O.ClassName);
   delete H2O;
  }

Drucke:

2012.05.18 14:13:48     VirtualTest (EURUSD,M15)        saveSettings to Prpototype
2012.05.18 14:13:48     VirtualTest (EURUSD,M15)        H2O ClassName=Prpototype
2012.05.18 14:13:48     VirtualTest (EURUSD,M15)        loadSettings from Prpototype
2012.05.18 14:13:48     VirtualTest (EURUSD,M15)        saveSettings to CO2
2012.05.18 14:13:48     VirtualTest (EURUSD,M15)        CO2 ClassName=CO2
2012.05.18 14:13:48     VirtualTest (EURUSD,M15)        loadSettings from CO2
2012.05.18 14:13:48     VirtualTest (EURUSD,M15)        loadSettings from Prpototype

Wenn dies ein Fehler ist, beheben Sie ihn bitte.

Wenn es sich um eine Funktion handelt, sollten Sie sie in der Hilfe ausführlich beschreiben und die Vorteile erläutern.

Wenn es sich um ein notwendiges Übel handelt, erwähnen Sie es bitte in dem entsprechenden Feld in der Hilfe.

Andernfalls werden Sie sich nicht auf die Suche nach einem Fehler in Ihrem Programm machen.

Dateien:
 

Der Vorgängerkonstruktor weiß nichts über seine Nachfahren und deren virtuelle Funktionen.

Wie ist ein Objekt aufgebaut?

1. Zunächst wird der Konstruktor der "Antriebsmaschine" aufgerufen. Er legt seine virtuelle Funktionstabelle offen. Der Vorfahre weiß nichts über die Nachkommen, die der Vererbungshierarchie folgen, und die virtuellen Funktionstabellen der Nachkommen sind noch nicht vorhanden.

2. Der Konstruktor des nächsten Nachfolgers in der Hierarchie wird aufgerufen. Dieser Nachkomme legt seine virtuelle Funktionstabelle offen. Die Funktionen (einschließlich der virtuellen Funktionen) des Nachkommens sind im Nachkomme verfügbar. Aber auch dieser Nachkomme weiß nichts über die Nachkommen, die ihm in einer Hierarchie folgen (wie in Punkt 1).

3. Punkt 2 wird wiederholt, bis die Hierarchie erfüllt ist.

Zusammenfassung. Verwenden Sie keine virtuellen Funktionen in Konstruktoren. Und verwenden Sie sie auch nicht in Destruktoren.

 
MetaDriver:

Wenn es sich um ein unvermeidbares Übel handelt, vermerken Sie dies bitte in dem entsprechenden Feld im Handbuch.

Es ist eine gängige Praxis, virtuelle Funktionen nicht vor dem Konstruktor und nach dem Start des Destruktors aufzurufen.
Документация по MQL5: Основы языка / Объектно-ориентированное программирование / Виртуальные функции
Документация по MQL5: Основы языка / Объектно-ориентированное программирование / Виртуальные функции
  • www.mql5.com
Основы языка / Объектно-ориентированное программирование / Виртуальные функции - Документация по MQL5
 
stringo:

Der Vorgängerkonstruktor weiß nichts über seine Nachfahren und deren virtuelle Funktionen.

Wie ist ein Objekt aufgebaut?

1. Zunächst wird der Konstruktor der "Antriebsmaschine" aufgerufen. Er legt seine virtuelle Funktionstabelle offen. Der Vorfahre weiß nichts über die Nachkommen, die der Vererbungshierarchie folgen, und die virtuellen Funktionstabellen der Nachkommen sind noch nicht vorhanden.

2. Der Konstruktor des nächsten Nachfolgers in der Hierarchie wird aufgerufen. Dieser Nachkomme stellt seine eigene virtuelle Funktionstabelle zur Verfügung. Die Funktionen (einschließlich der virtuellen Funktionen) des Nachkommens sind im Nachkomme verfügbar. Aber auch dieser Nachkomme weiß nichts über die Nachkommen, die ihm in einer Hierarchie folgen (wie in Punkt 1).

3. Wiederholen Sie Punkt 2, bis die Hierarchie erfüllt ist.

Zusammenfassung. Verwenden Sie keine virtuellen Funktionen in Konstruktoren. Auch nicht in Destruktoren.

Gut, aber wenn es so sein soll, muss es trotzdem an prominenter Stelle stehen.

Im Allgemeinen geht es nicht um die Hierarchie der Assembly (so habe ich es mir vorgestellt), sondern darum, an welcher Stelle des Konstruktors die VMT hinzugefügt wird. Wenn sie am Anfang hinzugefügt wird (vor dem vom Benutzer geschriebenen Code), dann scheint dieses Problem nicht zu bestehen, und der nachfolgende Code kann die virtuellen Funktionen bereits aufrufen. Ist es unmöglich, unerwünscht oder... ?

TheXpert:
Es ist eine gängige Praxis, virtuelle Funktionen nicht vor dem Ende des Konstruktors und nach dem Beginn des Destruktors aufzurufen.

Nun, ich wusste nichts davon, obwohl ich einige Erfahrung mit anderen objektorientierten Sprachen habe. Vielleicht, weil es nicht oft notwendig ist, virtuelle Aufrufe innerhalb eines Konstruktors zu machen.

 
MetaDriver:

OK. Aber stellen Sie es trotzdem an prominenter Stelle in den Helpdesk, wenn es so sein soll.


In der Dokumentation wird diese Tatsache an mehreren Stellen berücksichtigt
 
stringo:
In der Dokumentation wird sich diese Tatsache an mehreren Stellen widerspiegeln

OK, gut.

Slava, kann ich fragen (für die allgemeine Entwicklung), warum Sie nicht initialisieren können virtuelle Methode Tabelle am Anfang des Konstruktors (nach Vorfahren Initialisierung)?

--

In einigen Fällen kann Code mit virtuellen Aufrufen im Konstruktor recht praktisch sein. Ein aktuelles Beispiel: Ich wollte Objekte direkt im Konstruktor aus einer Datei laden. Der Plan war, die Typen während des Ladens zu überprüfen, indem ich sie mit den Typ-IDs verglich, die von virtuellen Funktionen zurückgegeben wurden. Dies war ein Flop, da es nicht möglich war, virtuelle Aufrufe vom Konstruktor aus zu tätigen. Das Problem wurde gelöst, allerdings nicht so elegant wie geplant.

Документация по MQL5: Основы языка / Объектно-ориентированное программирование / Виртуальные функции
Документация по MQL5: Основы языка / Объектно-ориентированное программирование / Виртуальные функции
  • www.mql5.com
Основы языка / Объектно-ориентированное программирование / Виртуальные функции - Документация по MQL5
 
MetaDriver:
Also bauen Sie eine Fabrik. Das Problem wird gelöst werden.