iCustom(Indikator) werte vom Indikator richtig auslesen - Seite 2

 
Ich kann mich nur immer wieder wiederholen. Das gibt es sicherlich bereits, man brauch nur etwas suchen und dann verwenden oder den Code kopieren - spart Zeit, Ärger, Frust und viel Arbeit.
 
Carl Schreiber:
Ich kann mich nur immer wieder wiederholen. Das gibt es sicherlich bereits, man brauch nur etwas suchen und dann verwenden oder den Code kopieren - spart Zeit, Ärger, Frust und viel Arbeit.
Alles ganz normale Bestandteile von Lernprozessen.
 
pennyhunter:

Danke für die Erklärung mit den Takten.

Leider muss ich zugeben, dass mir das GNU Zeug zu hoch ist. Mein Ziel ist auch, MQL5 einigermaßen zu lernen und nicht unbedingt andere Sprachen. In der Gnu Doku weiß ich gar nicht wo ich anfangen soll. Die Information mit den Takten habe ich da nicht so auf Anhieb gefunden.

Also gut. Dass der Compiler die Befehle der höheren Sprache in Binärcode umsetzt ist so ziemlich klar. Wo ich Probleme habe sind die konkreten kleinen Vor- und Nachteile von bestimmten ungewohnten Schreibweisen.

Die Konstanten, gut das kann man dann auch mit Eingabeparametern machen, oder nicht? Gibt es was zu beachten bezüglich & Zeichen bei der Übergabe von Variableln?

Das hier ist nicht so einfach zu verstehen:

value = (value * (cond == Null)) + (value * (cond != Null));   

Zunächst mal sieht es von der Formel her aus wie Quantenmechanik: Der eine Term mit der Bedingung die nicht zutrifft wird gleich null während der andere wo sie zutrifft einen Wert annimmt bzw der Wert wird mit eins multipliziert (Schrödingergleichung?). Es irritiert mich aber, dass es ebenso umgekehrt funktioniert... wie kann es ein if Statement ersetzen, wenn das Ergebnis immer gleich ist? Was wir brauchen sind doch entweder oder? Welcher Wert ist mit value eigentlich gemeint?

Muss es nicht eher so heißen:   result = (value1 * (cond == Null)) + (value2 * (cond != Null));      ? 

Ich sage jetzt mal konkreter:

if(Ask>MA[0]) {Trade.Buy(...);}  wie würde man das umsetzen? Es gibt ja hier mehrere Werte Ask und MA[0] bzw. man könnte sagen Ask-MA[0] ist ein Wert, der positiv sein muss wenn ein Kaufkontrakt eröffnet werden soll. Nur wie verknüpfe ich das dann mit dem Kaufbefehl?


Oder warte...Beispiel:
(Trade.Buy()*(Ask>MA[0])
(Trade.Sell()*(Bid<MA[0])              Würde das so gehen?


Oder vielleicht so:

void CheckTradingConditions(const int& bid, const int& ask)
{
(Trade.Buy()*(Ask>MA[0]))+((Trade.Sell()*(Bid<MA[0]))+(return;)
}


oder mit

const uint x = Ask>MA[0] ? Trade.Buy(...) : Null 

Wäre das so richtig?


Ich verstehe. Lass mich dir Beispielcode geben.


Sagen wir du willst einen gleitenden Durchschnitt aus einer Zahlenserie errechnen der NULL-Werte ausschließt. Erstes Beispiel ist mit "Conditional Breaks" und das Zweite ist ohne.


double values[]; // Angenommen hier sind die Werte enthalten aus denen der Durchschnitt gebildet werden soll.
double sum = NULL;
int skipped_values = NULL;

for(int cnt = NULL; (cnt < ArraySize(values) && !_StopFlag; cnt++)
{
        if(values[cnt] != NULL)
        { sum += values[cnt]; }
        else
        { skipped_values++; }
}

double result = sum / (ArraySize(values) - skipped_values);


Und hier nun eine Version ohne Conditional Breaks:

double values[];
double sum = NULL;
const uint arr_size = (uint)ArraySize(values);
uint value_count = NULL;
uint eval = NULL;

for(uint cnt = NULL; (cnt < arr_size) && !_StopFlag; cnt++)
{
        eval = (values[cnt] != NULL);           // Evaluiere den aktuellen Wert
        sum += (values[cnt] * eval);            // Addiere diesen wenn nicht NULL (If-Statement Ersatz)
        value_count += eval;                    // Zähle die addierten Werte
}

const double result = sum / value_count;



Ähnlich verhält es sich auch bei einem Funktionsaufruf, allerdings gibt es hier ein paar Voraussetzungen. Die unter bestimmten Bedingungen zu rufende Funktion muss einen Wert zurück geben. Void-Funktionen gehen nicht.

Beispiel für einen Non-Conditional Funktionsaufruf:

double values[];
const uint arr_size = ArraySize(values);

for(uint cnt = NULL; (cnt < arr_size) && !_StopFlag; cnt++)
{
        (values[cnt] != NULL) && (sub_function(values[cnt]));   // Hier wird die Abfolge der Evaluierung der boolschen Ausdrücke genutzt um ein Aufrufen der Funktion zu steuern.
                                                                // Ist in einer "AND"-Abfolge ein Wert gleich false, wird die weitere Iteration abgebrochen, da diese sicher nurnoch False zurückgeben kann.
                                                                // Somit wird die Funktion sub_function nicht aufgerufen.
}



const bool sub_function(const double inp_val)
{

// Der Rückgabewert hat keine Wirkung, da sieser in der for-Loop nicht weiter verarbeitet wird.
// Ansonsten könnten hier natürlich weitere Bedingungen in die for-Schleife zurückgebracht werden um den Ablauf weiter zu beeinflussen.
return(true);
}


BTW, Referenzen können nicht als const deklariert werden, da diese bei Natur geändert werden können/sollen... Warum sollte eine Funktion eine Referenz entgegennehmen, wenn diese nicht geändert werden darf?

Daher geht folgendes nicht:

const bool sub_function(const double& inp_val)
{

        return(false);
}


// Die Deklaration und Definition des Funktionskopfs muss entweder eine Referenz oder eine const sein. (Natürlich geht auch eine Nicht-Const Variable)
const bool sub_function(const double inp_val)
{
        inp_val += 1.0; // FEHLER. Geht nicht!
        return(false);
}

const bool sub_function(double inp_val)
{
        inp_val += 1.0; // Kein Fehler

        // Die Änderung an inp_val wird bei Return verworfen da diese nur eine lokale Kopie ist.
        return(true);
}

const bool sub_function(double& inp_val)
{
        inp_val += 1.0; // Kein Fehler

        // Die Änderung der inp_val bleibt erhalten, da die Variable auf dem Stack der rufenden Funktion liegt (Oder wo auch immer).
        return(true);
}

 

Ich hoffe diese Beispiele bringen das etwas deutlicher ans Licht.

Zum Messen der Unterschiede der verschiedenen Arten der Evaluierung des Codeablaufs kann folgender Snippet eingefügt werden:

const ulong perf_start = GetMicrosecondCount();


/* Der zu testende Code hier */


printf("Time used: %llu microseconds.", GetMicrosecondCount() - perf_start);


Sollte die Ausgabe NULL sein, dann liege es daran, dass der Code zu schnell ausgeführt wurde.

Eine Schleife kann dann helfen, den Code mehrfach auszuführen, sodass genug zeit vergeht um einen Wert zu erhalten.


Der MQL Compiler ist von einem C/C++ Compiler abgeleitet worden und daher habe ich auf die Doku vom GNU verwiesen. Das meiste Verhalten ist identisch, jedoch mit Einschränkungen.

Die Ausführungszeiten für einen Assembler Befehl sind in der ISA zu finden. - Allerdings sind das nur die Zeiten für einen Assembler Befehl. Für einen tieferen Einblick ist es notwendig zu wissen welche Assembler Befehle der Compiler verwendet um eine zB For-Schleife abzubilden.

Es gibt Online Compiler die einem den Assembly anzeigen. Daran kann man dann die ungefähre Abfolge auslesen und diese dann in der ISA nachschlagen. Dann ist es möglich zu sehen wie viel Zeit die CPU für einen Anweisungsblock benötigen wird.


Ich glaube der entscheidende Unterschied zwischen Quantenmechanik und arithmetischer Logik ist der zeitliche Ablauf. Die CPU arbeitet eine Sequenz immer in der gegebenen Reihenfolge ab. Bei "Schrödingers Katze" war/ist das nicht der Fall, es geschieht ein Informationsaustausch im selben Augenblick. Hier ist der entscheidende Unterschied, denke ich.

 
Dominik Egert:


Ich verstehe. Lass mich dir Beispielcode geben.


Sagen wir du willst einen gleitenden Durchschnitt aus einer Zahlenserie errechnen der NULL-Werte ausschließt. Erstes Beispiel ist mit "Conditional Breaks" und das Zweite ist ohne.



Und hier nun eine Version ohne Conditional Breaks:



Ähnlich verhält es sich auch bei einem Funktionsaufruf, allerdings gibt es hier ein paar Voraussetzungen. Die unter bestimmten Bedingungen zu rufende Funktion muss einen Wert zurück geben. Void-Funktionen gehen nicht.

Beispiel für einen Non-Conditional Funktionsaufruf:


BTW, Referenzen können nicht als const deklariert werden, da diese bei Natur geändert werden können/sollen... Warum sollte eine Funktion eine Referenz entgegennehmen, wenn diese nicht geändert werden darf?

Daher geht folgendes nicht:

 

Ich hoffe diese Beispiele bringen das etwas deutlicher ans Licht.

Zum Messen der Unterschiede der verschiedenen Arten der Evaluierung des Codeablaufs kann folgender Snippet eingefügt werden:


Sollte die Ausgabe NULL sein, dann liege es daran, dass der Code zu schnell ausgeführt wurde.

Eine Schleife kann dann helfen, den Code mehrfach auszuführen, sodass genug zeit vergeht um einen Wert zu erhalten.


Der MQL Compiler ist von einem C/C++ Compiler abgeleitet worden und daher habe ich auf die Doku vom GNU verwiesen. Das meiste Verhalten ist identisch, jedoch mit Einschränkungen.

Die Ausführungszeiten für einen Assembler Befehl sind in der ISA zu finden. - Allerdings sind das nur die Zeiten für einen Assembler Befehl. Für einen tieferen Einblick ist es notwendig zu wissen welche Assembler Befehle der Compiler verwendet um eine zB For-Schleife abzubilden.

Es gibt Online Compiler die einem den Assembly anzeigen. Daran kann man dann die ungefähre Abfolge auslesen und diese dann in der ISA nachschlagen. Dann ist es möglich zu sehen wie viel Zeit die CPU für einen Anweisungsblock benötigen wird.


Ich glaube der entscheidende Unterschied zwischen Quantenmechanik und arithmetischer Logik ist der zeitliche Ablauf. Die CPU arbeitet eine Sequenz immer in der gegebenen Reihenfolge ab. Bei "Schrödingers Katze" war/ist das nicht der Fall, es geschieht ein Informationsaustausch im selben Augenblick. Hier ist der entscheidende Unterschied, denke ich.

Ja danke für die Erklärung und die Mühe.
Mit Quantenmechanik hatte ich es nie so aber bei einer Gleichung wird der Term für Impuls gleich Null und der andere Term für den Aufenthaltsort nimmt einen Wert an. Aber dass das die Schrödinger war war geraten und ich finde es jetzt auf Anhieb auch nicht mehr.

Die Tipps werde ich beherzigen und das mit den msec count ist auch prima, das ist guter Stoff für eine Versuchsreihe.
 
pennyhunter:
Ja danke für die Erklärung und die Mühe.
Mit Quantenmechanik hatte ich es nie so aber bei einer Gleichung wird der Term für Impuls gleich Null und der andere Term für den Aufenthaltsort nimmt einen Wert an. Aber dass das die Schrödinger war war geraten und ich finde es jetzt auf Anhieb auch nicht mehr.

Die Tipps werde ich beherzigen und das mit den msec count ist auch prima, das ist guter Stoff für eine Versuchsreihe.

BTW, mir ist ein Fehler aufgefallen, naja, so zu sagen...


Ich habe gesagt, es macht keinen Sinn eine Referenz als const zu deklarieren. Dies ist nicht ganz richtig.

Ein Beispiel ist diese Funktion:

template <typename T> 
const T sum_array(const T& array[], const uint iEnd, uint iBeg = NULL)
{
   T sum = NULL; 
   while(iBeg < iEnd) 
   { sum += array[iBeg++]; }

   return(sum);
}


Hintergrund ist ganz einfach, dies sorgt dafür, dass das Array array[] beim Funktionsaufruf nicht kopiert wird, was natürlich viel schneller ist. Und es stellt sicher, dass die gerufene Funktion das Array nicht ändern kann. Somit ist eine Konsistenz gegeben.

 
Dominik Egert:


Beispiel für einen Non-Conditional Funktionsaufruf:


double values[];
const uint arr_size = ArraySize(values);

for(uint cnt = NULL; (cnt < arr_size) && !_StopFlag; cnt++)
{
        (values[cnt] != NULL) && (sub_function(values[cnt]));   // Hier wird die Abfolge der Evaluierung der boolschen Ausdrücke genutzt um ein Aufrufen der Funktion zu steuern.
                                                                // Ist in einer "AND"-Abfolge ein Wert gleich false, wird die weitere Iteration abgebrochen, da diese sicher nurnoch False zurückgeben kann.
                                                                // Somit wird die Funktion sub_function nicht aufgerufen.
}



const bool sub_function(const double inp_val)
{

// Der Rückgabewert hat keine Wirkung, da sieser in der for-Loop nicht weiter verarbeitet wird.
// Ansonsten könnten hier natürlich weitere Bedingungen in die for-Schleife zurückgebracht werden um den Ablauf weiter zu beeinflussen.
return(true);
}

Okay, ich bin gerade dabei mir jetzt ein paar von den Sachen, die Du angemerkt hast, draufzuschaffen.

Jetzt habe ich endlich die Zeit gefunden, diese Prinzipien auszuprobieren und zu verinnerlichen.

Ich glaubte, verstanden zu haben, dass man "&&" zwischen boolschen Ausdrücken anstandslos gegen "*" austauschen könne, da es sich um Einsen und Nullen handelt, die man miteinander multiplizieren kann. Doch an dieser Stelle gab es bei meinem Experiment ein Problem. Anscheinend kann man das doch nicht einfach austauschen, es verhält sich nicht gleich.

Ist aber jetzt ziemlich off-topic hier, darum würde ich mich freuen, wenn Du Zeit und Lust hättest, mal in dem anderen Thread vorbeischauen.

https://www.mql5.com/de/forum/370021

Gruß

Vermeidung von if-Statements und Conditional Breaks
Vermeidung von if-Statements und Conditional Breaks
  • 2021.05.25
  • www.mql5.com
Hallo Forum, gerade bin ich dabei, mir die Erkenntnisse aus https://www.mql5.com/de/forum/351074 draufzuschaffen...
Grund der Beschwerde: