Jede Anfängerfrage, um das Forum nicht zu überladen. Fachleute, gehen Sie nicht vorbei. Nirgendwo ohne dich - 6. - Seite 641

 
simpleton:

Warum einen Fehler emulieren?

Fehler - soll signalisieren, dass der Algorithmus aus irgendeinem Grund, der mit Systembeschränkungen/-fehlern zusammenhängt, nicht ausgeführt werden konnte und das Ergebnis mit einer gewissen (natürlich begrenzten, aber - ) Garantie erhalten wurde. Die Funktion FillAndPrint() zeigt sehr anschaulich, was eine Fehlersituation bedeutet und was sie nicht bedeutet. Wenn ein Fehler auftritt, wird nicht einmal versucht, das Ergebnis zu drucken. Liegt kein Fehler vor, kann dem Ergebnis vertraut werden. So sollte die Logik "Fehler/kein Fehler" aufgebaut sein.

Hier müssen Sie den Algorithmus ändern: Sie müssen einen zusätzlichen Filter anwenden.

So sollte es gemacht werden:

Zunächst "filtern" wir nach Objekttypen und Parametern, wobei wir aus allen verfügbaren Objekten nur die benötigten auswählen, und dann wenden wir einen zusätzlichen Filter an. Es ist ungefähr so, wie ein Mensch es tun würde. Das würde ein Mensch doch tun, oder?

Für jede dieser kleinen Teilaufgaben ist eine eigene Funktion wünschenswert.

In Ausdrücken sollten keine Zahlen vorkommen, außer in sehr speziellen Fällen, z. B. wenn Sie verdoppeln müssen und es in der Natur des Algorithmus liegt, dies zu tun. Dann kann die Zahl 2 direkt in Ausdrücken verwendet werden. Und in anderen, sehr seltenen Fällen.

In anderen Fällen sollten Mnemotechniken verwendet werden. Erstens verbessern sie das Verständnis für das Geschehen an einem bestimmten Ort erheblich und verringern so die Gefahr, Fehler zu machen. Und zweitens ist der Wert selbst an einer Stelle definiert und kann bei Bedarf leicht geändert werden, und es ist unmöglich, einen Fehler zu machen, verglichen mit dem Fall, in dem die Zahl mehr als einmal im Algorithmus verwendet wird, und ohne die Verwendung von Mnemonics müssen Sie die Zahlen an mehreren Stellen des Algorithmus festlegen.

Ergebnis des Laufs:

Es wird kein einziges Objekt gefunden. Erhöhen Sie die Werte beider Mnemotechniken 10 Mal auf 36000 (10 Stunden) und führen Sie den Vorgang erneut durch:

Ein Trend hat die Filterung bereits "bestanden". Jetzt stellen wir den Wert des ersten Mnemonics auf 3600 zurück und starten:

Es ist zu erkennen, dass beide Trends nun die Filterung "durchlaufen" haben. Übrigens empfehle ich, alle Verzweigungen (Teile) des Programms auf diese Weise zu debuggen und nicht nur eine einzelne Verzweigung.

Um das Ganze etwas zu formalisieren, werde ich versuchen, es auf diese Weise zu erklären. Das Programm ist offenbar wie ein Plan.

Jeder Hauptplan kann in kleinere Teilpläne untergliedert werden. Kleinere in noch kleinere. Die Positionen der kleinsten Teilpläne werden direkt ausgeführt.

Jeder Plan, Teilplan und selbst die kleinsten Teilpläne entsprechen Funktionen im Programm. Die Elemente in den kleinsten Teilplänen entsprechen "End"-Funktionen, die nur Systemfunktionen oder gar keine Funktionen aufrufen, z. B. AddValue() oder DiffInSecs() sind Beispiele für die oben genannten Funktionen. Die obigen Teilplanpositionen entsprechen den Funktionen, die die Funktionen aufrufen, die die nachfolgenden Teilplanpositionen implementieren. Bei den oben genannten sind dies MassTrendNumber(), AddValueIfFound(), AddValueIfFiltered(). "Low-Level"-Funktionen sollten keine "High-Level"-Funktionen aufrufen, und "High-Level"-Funktionen sollten grundsätzlich nicht mehrere Ebenen nach unten springen, d.h. grundsätzlich nur Funktionen auf der darunter liegenden Ebene aufrufen. Diese Regel ist für "Low-Level" viel strenger als für "High-Level".

Versuchen Sie, Ihre Programme zu erstellen, indem Sie die darin enthaltenen Aktionen als (kurze) Funktionen organisieren, die durch diese Art von Baumstruktur verbunden sind, im Sinne von "wer ruft wen auf".

Dieses Programm hat einen degenerierten Baum: einen Zweig, der sich mehrfach "verzweigt". Und sie "verzweigt" sich nicht in zwei kleine Äste, sondern in einen. Aber der Punkt, dass "High-Level"-Funktionen immer wieder "Low-Level"-Funktionen aufrufen, ist zu erkennen. In dieser Änderung habe ich eine weitere Ebene in diese Struktur eingefügt, einen weiteren "nicht verzweigten Zweig" - AddValueIfFiltered().

Ich füge den fertigen Code ein.

Die Aufgabe: Suche nach Trendlinien(OBJ_TREND) und Aufzeichnung der Kurswerte relativ zum aktuellen Balken in einem Array. Gefiltert gegen das Vorhandensein von Objektzeitparametern (OBJ_TREND).

#property strict

/******************************************************************************/
bool AddValue(double &array[], const double value) {
  const int size = ArraySize(array);

  if (ArrayResize(array, size + 1) != size + 1) {
    return false; // Ошибка, значение не может быть добавлено к массиву
  }

  array[size] = value; //записываем
  return true; // Нет ошибки, значение добавлено к массиву
}

/******************************************************************************/
bool AddValueIfFound(double &array[], const string name) {
  const int type = ObjectType(name);

  if (type == OBJ_TREND) {
    switch ((color)ObjectGet(name, OBJPROP_COLOR)) { // Тип color допустимо использовать в switch
    case Goldenrod:
    case Gainsboro:
    case White:
      if (!AddValueIfFiltered(array, name)) { // Пропускаем через фильтр
        return false;
      }
    }
  }

  return true; // Нет ошибки, значение, если найдено, добавлено к массиву
}
/******************************************************************************/
bool MassTrendNumber(double &array[], const bool buy) { // Поиск значения цены трендовой линии, текущего бара, запись в массив. Два массива: masS и masB
  const string subname = (buy ? "uptrendline" : "downtrendline"); // существует два названия трендовых линий, первое и второе

  if (ArrayResize(array, 0) != 0) {
    return false; // Ошибка, массив не может быть заполнен достоверно
  }

  for (int i = 0, limit = ObjectsTotal(OBJ_TREND); i < limit+2; i++) {
    if (!AddValueIfFound(array, subname + IntegerToString(i))) {
      return false; // Ошибка, массив, если и заполнен, то недостоверно
    }
  }
 
  return true; // Нет ошибки, массив заполнен достоверно
}
/******************************************************************************/
long DiffInSecs(const datetime dt1, const datetime dt2) {
  return dt1 - dt2;
}
/******************************************************************************/
bool AddValueIfFiltered(double &array[], const string name) {
#define MIN_SECS_BETWEEN_PRICE1_AND_PRICE2 3600
#define MAX_SECS_AFTER_PRICE2              3600

  const datetime dt1 = (datetime)ObjectGet(name, OBJPROP_TIME1);
  const datetime dt2 = (datetime)ObjectGet(name, OBJPROP_TIME2);
  const datetime dt = TimeCurrent();
  
  Print("name = ", name,// ", dt = ", dt, ", dt1 = ", dt1,"\n", 
  " DiffInSecs = ", DiffInSecs(dt,dt2)," DiffInSecs = ", DiffInSecs(dt2,dt1));

   if( DiffInSecs(dt,dt2)>MAX_SECS_AFTER_PRICE2 && DiffInSecs(dt2,dt1)> MIN_SECS_BETWEEN_PRICE1_AND_PRICE2){
    if (!AddValue(array, ObjectGetValueByShift(name, 1))) { // Пытаемся добавить
      return false; // Ошибка, значение не добавлено
    }
  }

  return true; // Нет ошибки, значение, если удовлетворило условию фильтра, добавлено к массиву
}

/******************************************************************************/
void FillAndPrint(double &array[], const bool buy) {
  if (MassTrendNumber(array, buy)) {
    const int limit = ArraySize(array);

    Print("Найдено объектов: ", limit);

    for (int i = 0; i < limit; i++) {
      Print("Price[", i, "] = ", DoubleToStr(array[i], Digits));
    }
  } else {
    Print("Чёрт!");
  }
}

/******************************************************************************/
void OnTick()

//=============================================================================================
//====================================== Линии тренда =========================================
//=============================================================================================
 double masS[]; double masB[];

  Print("Sell:");
  FillAndPrint(masS, false);

  Print("Buy:");
  FillAndPrint(masB, true);
 simpletonСпасибо вам большое, вы за пестовали меня на ощущения правильного кода!) (Правда я немногое понял))))
 
evillive:

Ich habe jetzt 4 Ziffern, auf ewardollar bei 1 Lot kostet 1 Punkt $10 und war schon immer so. Für Kreuze werden die Kosten zwischen 8 und 16 liegen, die Formel ist hier etwas komplizierter.

Zum Beispiel hat marketinfo für das Euro-Pfund 16,984 zurückgegeben, der Pfund-Dollar-Kurs = 1,6984, d.h. 1 Euro-Pfund-Punkt ist 1 Pfund wert, multipliziert mit dem Pfund-Dollar-Punktwert, der immer 10,0 beträgt (100000 * 0,0001 = 10,0 oder 100000 * 0,00010 = 10,0 - wie man will).


Alle diese Berechnungen sind nur korrekt, wenn Ihr Konto auf Dollar lautet:

In diesem Fall für xUSD (EURUSD, GBPUSD usw.) tickvalue = lot*point = 100000*0,0001 = 10,0

für USDh (USDCHF, USDJPY usw.) tickvalue = lot*point/Bid = 100000*0.01/101.93=9.8107

für xUSD/yUSD (EURGBP) tickvalue = Bid(yUSD)*lot*point = 1,6980*100000*0,0001 = 16,98

für xUSD/USDy (EURJPY) tickvalue = lot*point/Bid(USDy) = 100000*0.01/101.91 = 9.8126


Irgendwas hast du verbockt! Ich habe mir die Zeit genommen, in den Code zu schauen, Ausdrücke auszuwählen und nachzuschauen:

  double TV = MarketInfo(Symbol(),MODE_TICKVALUE); 
  string sTV = DoubleToStr(TV,4); 
  Comment("TV ",sTV); //sTV = 1.0/Bid

Einfacher geht's nicht! Nr. 10, 16, usw.

 
evillive:

Ich habe jetzt 4 Ziffern, auf ewardollar bei 1 Lot kostet 1 Punkt $10 und war schon immer so. Für Kreuze werden die Kosten zwischen 8 und 16 liegen, die Formel ist hier etwas komplizierter.

Zum Beispiel hat marketinfo für das Euro-Pfund 16,984 zurückgegeben, der Pfund-Dollar-Kurs = 1,6984, d.h. 1 Euro-Pfund-Punkt ist 1 Pfund wert, multipliziert mit dem Pfund-Dollar-Punktwert, der immer 10,0 beträgt (100000 * 0,0001 = 10,0 oder 100000 * 0,00010 = 10,0 - wie man will).


Alle diese Berechnungen sind nur korrekt, wenn Ihr Konto auf Dollar lautet:

In diesem Fall für xUSD (EURUSD, GBPUSD usw.) tickvalue = lot*point = 100000*0,0001 = 10,0

für USDx (USDCHF, USDJPY usw.) tickvalue = lot*point/Bid = 100000*0.01/101.93 = 9.8107

für xUSD/yUSD (EURGBP) tickvalue = Bid(yUSD)*lot*point = 1,6980*100000*0,0001 = 16,98

für xUSD/USDy (EURJPY) Kreuzungen tickvalue = lot*point/Bid(USDy) = 100000*0.01/101.91=9.8126




Das ist falsch! Der Wert eines Angebots spielt keine Rolle!Und der Wert eines Min.-Ticks muss aus dem aktuellen Kurs berechnet werden! Das entspricht dem TICK_VALUE! Oben sehen Sie ein Beispiel aus meinem Code.
 
borilunad:

borilunad:

Das ist falsch! Der Wert eines Angebots ist irrelevant! Und der Wert eines min.tick sollte aus dem aktuellen Preis berechnet werden! Das entspricht dem TICK_VALUE! Oben sehen Sie ein Beispiel aus meinem Code.

Wieso ist das falsch? Marketinfo liefert dieselben Werte wie die Formeln, die ich oben angegeben habe. Ich habe diese Formeln nicht erfunden, sie werden vom Terminal zur Berechnung von TickValue verwendet).

Es ist klar, dass es bequemer ist, den Wert aus Marketinfo zu übernehmen, aber er fragte nach Formeln oder Berechnungsmethoden.

Und über den Wert habe ich vorhin geschrieben, dass es keine Rolle spielt, weil bei 5-stelligen Zählungen ein Punkt = 10 Pips ist, und es ist der gleiche Punkt von 4-stellig.

 
evillive:

Wieso ist das falsch? Marketinfo liefert dieselben Werte wie die Formeln, die ich oben angegeben habe. Ich habe diese Formeln nicht erfunden, sie werden vom Terminal zur Berechnung von TickValue verwendet)))

Es ist klar, dass es bequemer ist, den Wert aus Marketinfo zu übernehmen, aber er fragte nach Formeln oder Berechnungsmethoden.

Und ich habe vorhin über die Vorzeichen geschrieben, dass es keine Rolle spielt, weil bei 5-stelligen Zählungen ein Punkt = 10 Pips ist, und das ist derselbe Punkt von 4-stellig.


Das ist es, was ich mitMarketInfo(Symbol(),MODE_TICKVALUE) =1.0/Bid meine;Vielleicht nur für Eurodollar, ich sprühe es nicht auf andere!
 
borilunad:

Das meine ich mitMarketInfo(Symbol(),MODE_TICKVALUE) =1.0/Bid;Vielleicht nur für Euro, nicht für andere!

Genau das ist es, was mit dem Eurodollar nicht stimmt, wenn man die Definition in der Hilfe zugrunde legt

MODE_TICKVALUE

16

Minimale Änderung des Wertpapierkurses in der Einzahlungswährung


Und es bedeutet, zu multiplizieren

MODE_POINT

11

Größe des Punktes in der Kurswährung. Denn das aktuelle Symbol wird in der vordefinierten Variablen Point


von

MODE_LOTSIZE

15

Kontraktgröße in der Basiswährung des Instruments


Wenn Ihr Konto auf Euro lautet, sollten Sie natürlich den Euro als Basiswährung verwenden, aber für Händler, die ein Dollarkonto haben (was meistens der Fall ist), sind die oben genannten Formeln gültig. Da die wichtigsten und meistgehandelten Paare auf dem US-Dollar basieren, werden diese Formeln am häufigsten verwendet.

 
evillive:

Das ist genau falsch, wenn man die Definition in der Hilfe zugrunde legt

MODE_TICKVALUE

16

Minimale Änderung des Symbolpreises in der Währung der Einlage


Das bedeutet, dass dieser Wert mit folgendem multipliziert werden sollte

MODE_POINT

11

Größe des Punktes in der Kurswährung. Denn das aktuelle Symbol wird in der vordefinierten Variablen Point


unter

MODE_LOTSIZE

15

Kontraktgröße in der Basiswährung des Instruments


Wenn Ihr Konto auf Euro lautet, sollten Sie natürlich Euro verwenden, aber die meisten Händler haben ein Dollarkonto.


Nun gut, ich bin ein Sonderfall, aber für mich, der ich in der Eurozone lebe, ist es bequemer, alle Berechnungen in Euro vorzunehmen!
 

Meine Herren, bitte geben Sie mir ein Codebeispiel für den folgenden Indikator. Ich kann nicht herausfinden, wie viele Puffer benötigt werden, welche Art von Kartierung und wo und welche Eigenschaften für sie vorgeschrieben werden sollten.

Der Indikator ist der folgende:

1 Die Stäbe verbinden mindestens jeden dritten und jeden benachbarten Stab. Die Linie ist rot.

2 Balkenabschnitte verbinden die Maxima jedes 5. und benachbarten Balkens. Die Linie ist blau.

Die Hauptsache ist, dass sich die Segmente in keiner Weise überschneiden. Der Anfang und das Ende eines jeden Segments sind unabhängig von den anderen Segmenten.

Der Indikator berechnet die Werte für den Anfang und das Ende eines jeden Segments. Sie sollten je nach den Bedingungen unterschiedlich gefärbt sein.

So sollte es ungefähr aussehen


 

Und noch eine Frage.

Ist es normal, dass ich im Debug-Modus nicht mit dem Indikator arbeiten kann?

Wenn das Programm den Haltepunkt erreicht, bleibt das MT4-Terminal hängen und das Fenster wird weiß (in HP), so dass es unmöglich ist, zu sehen, was auf dem Chart gezeichnet wird

 
Top2n:

Hier ist der fertige Code.

Aufgabe: Suche nach Trendlinien (OBJ_TREND), Aufzeichnung der Kurswerte relativ zum aktuellen Balken in einem Array. Mit Filterung in Bezug auf das Vorhandensein von Objektzeitparametern (OBJ_TREND).

simpleton:Vielen Dank, Sie haben mir das Gefühl gegeben, den richtigen Code zu kennen!) (Obwohl ich nicht viel verstanden habe))))

Wenn Sie üben, werden Sie mehr und mehr verstehen. Das erfordert Konzentration und Achtsamkeit. Wenn der Programmalgorithmus auf eine große Funktion verschmiert ist, ist es schwierig, ihn mit Konzentration und Aufmerksamkeit zu realisieren - es werden zu viele Verknüpfungen gebildet. Wenn ein Programm jedoch in funktional vollständige Teile (kleine Funktionen) unterteilt ist, ist es viel einfacher, dies für jede einzelne kleine Funktion zu tun. Und zwar auf jeder Funktionsebene. Im Übrigen:

   if( DiffInSecs(dt,dt2)>MAX_SECS_AFTER_PRICE2 && DiffInSecs(dt2,dt1)> MIN_SECS_BETWEEN_PRICE1_AND_PRICE2){
    if (!AddValue(array, ObjectGetValueByShift(name, 1))) { // Пытаемся добавить
      return false; // Ошибка, значение не добавлено
    }
  }
Ich muss die Eselsbrücke MAX_SECS_AFTER_PRICE2 falsch benannt haben (weil ich zuerst so verstanden habe, dass die Bedingung invers sein muss), die Bedeutung sollte wahrscheinlich MIN_SECS_AFTER_PRICE2 sein, also das erlaubte Minimum, nicht das Maximum.