Diskussion zum Artikel "LifeHack für Händler: ForEach mit #define zubereiten" - Seite 6

 

Wie muss man sich einen Artikel vorstellen?! Ich nehme meinen Quellcode aus KB und beginne in dem Artikel zu beschreiben, warum ich mich entschieden habe, ein Makro an dieser Stelle anzuwenden und warum es genau so ist?

Für jede Arbeit in KB gibt es einen Diskussionsstrang. Dort können Sie Fragen zu den Quellen stellen.

 
fxsaber:

Wie muss man sich einen Artikel vorstellen?! Ich nehme meinen Quellcode aus KB und beginne in dem Artikel zu beschreiben, warum ich mich entschieden habe, ein Makro an dieser Stelle anzuwenden und warum es genau so ist?

Für jede Arbeit in KB gibt es einen Diskussionsstrang. Dort können Sie Fragen zu den Quellen stellen.

Zum Beispiel schlage ich hier überhaupt keine Hohlräume ab).

#define  MT4_ORDERFUNCTION(NAME,T,A,B,C)                               \
  static T MT4Order##NAME( void )                                     \
  {                                                                   \
    return(POSITION_ORDER((T)(A), (T)(B), MT4ORDERS::Order.NAME, C)); \
  }

Es wäre nicht schlecht, diese Dinge zu beschreiben!

 
Vitaly Muzichenko:

Zum Beispiel hier, wo ich überhaupt nicht hohl bin)

Es wäre schön, wenn man diese Dinge beschreiben könnte!

Dies ist ein mehrzeiliges Makro mit fünf Eingabeparametern. Schauen Sie sich den Text an, mit welchen Parametern es aufgerufen wird.

Es erzeugt entsprechende Methoden mit den Namen MT4OrderTicket, MT4OrderClosePrice, usw. Die Methoden sind zu 95% identisch im Text und es gibt viele von ihnen. Um nicht ein riesiges Copy-Paste zu machen, bei dem sich leicht ein Fehler einschleichen kann, wird ein Makro erstellt. Alles ist kompakt und sofort sichtbar.

Darüber hinaus unterstreicht dieser Code, dass die Funktionen zu 95 % identisch sind. Das heißt, wenn man ihn liest, erkennt man das sofort. Wenn Sie jedoch klassisch schreiben würden, könnten Sie eine solche Schlussfolgerung nur ziehen, indem Sie den Code von 20 Methoden (es sind so viele) lesen und analysieren. Und das bereitet große Kopfschmerzen. Und so sind alle 20 Methoden auf einem Bildschirm und es wird betont, dass die Methoden fast übereinstimmen. Und nur die Eingabeparameter der Makros verraten die Unterschiede. Man achtet beim Lesen auf diese Unterschiede und nicht auf den Flitter. D.h. der Code zeigt sofort die Hauptsache - den Kern und nicht eine profane Hülle.

 
Vasiliy Sokolov:

Die Dinge, die er tut, sind ungewöhnlich. Das ist wertvolles Wissen, das mit der Öffentlichkeit geteilt werden sollte!

Nun, er teilt es ja auch. Einige seiner Beiträge und Beschreibungen des Codes in KB sind informativer als die Hälfte der Artikel hier.

Ich verstehe auch nicht, warum es ein künstliches Nachschlagewerk gibt, wenn es von ihm Live-Antworten auf alle gestellten Fragen gibt.

Es wäre besser, wenn Renat seine Gewohnheit ablegen würde, ihn für jede harte Aussage zu bannen.

 

Würde der Entwickler einen zusätzlichen Befehl "eine Kopie der Datei, ersetzen Makros ohne Kompilierung und öffnen Sie die Datei", um die Schaltfläche "Kompilieren" im Editor zu machen. Speziell für das Studium von Makros aus fxsaber.

Oder Sie können den Befehl im Kontextmenü verwenden. Setzen Sie die Maus auf den Makroaufruf, wählen Sie den Befehl aus, und der nach der Makroersetzung erhaltene Code wird in den Puffer kopiert.

 

Im Allgemeinen können Makros wie folgt verstanden werden:

1. Es ist notwendig, den Makronamen von seinem Wert zu trennen. Zuerst in der Zeile geht #define, dann ein Leerzeichen, danach dieser Name (er kann mit Parametern sein), dann ein weiteres Leerzeichen oder Übergang zu einer neuen Zeile und der Wert des Makros.

2. Wir sehen, wie das Makro im Code aufgerufen wird, was seine Parameter sind. Kopieren Sie den Wert des Makros und ersetzen Sie die Parameter durch die Parameter, mit denen es irgendwo im Code aufgerufen wird.

3. an der Stelle, an der das Makro im Code aufgerufen wird, ersetzen Sie es durch das, was wir in Schritt 2 erhalten haben.

Ungefähr so.

Es gibt einige Dinge, die du wissen musst: \ - es bedeutet Fortsetzung in einer neuen Zeile. ## - es ist eine Verbindung von Zeilen.
 
Das von mir am häufigsten verwendete Makro

Forum zum Thema Handel, automatisierte Handelssysteme und Testen von Handelsstrategien

Merkmale der Sprache mql5, Feinheiten und Techniken der Arbeit

fxsaber, 2017.12.05 11:39 pm.

Im Debug-Modus können Sie den Wert, den eine Funktion oder ein Ausdruck zurückgibt, nicht herausfinden.

Zum Beispiel

void OnStart()
{
  double Angle = 1;
  double d = MathSin(Angle / 2) * MathSin(Angle * 2);
}

Zum Beispiel, was die hervorgehobenen Funktionen zurückgeben.


Ich verwende (nicht nur im Debug-Modus) diesen Weg

template <typename T>
T MyPrint( const T Value, const string Str )
{
  static const bool IsDebug = MQLInfoInteger(MQL_DEBUG);

// if (IsDebug)
  {
// DebugBreak(); // wenn Sie mit Debug-Mitteln sehen wollen

    Print(Str + " = " + (string)Value);
  }
  
  return(Value);
}

#define _P(A) MyPrint(A, __FUNCSIG__ ", Line = " + (string)__LINE__ + ": " + #A)

void OnStart()
{
  double Angle = 1;
  double d = _P(MathSin(Angle / 2)) * _P(MathSin(Angle * 2));
}


Ergebnis

void OnStart(), Line = 21: MathSin(Angle/2) = 0.479425538604203
void OnStart(), Line = 21: MathSin(Angle*2) = 0.9092974268256817

Ich habe es als mqh formatiert.

Ein plattformübergreifendes Skript als Beispiel

#include <MT4Orders.mqh>

#define Ask SymbolInfoDouble(_Symbol, SYMBOL_ASK)

void OnStart()
{
  // Eröffnet und schließt eine BUY-Position
  if (OrderSelect(OrderSend(_Symbol, OP_BUY, 1, Ask, 100, 0, 0), SELECT_BY_TICKET))
    OrderClose(OrderTicket(), OrderLots(), OrderClosePrice(), 100);
}


Nehmen wir an, wir möchten wissen, was OrderClosePrice() in diesem Code zurückgibt. Gehen wir wie folgt vor

OrderClose(OrderTicket(), OrderLots(), _P(OrderClosePrice()), 100);


Und hier ist der Code, wenn Sie fast alles wissen wollen (das passiert, wenn Sie überhaupt nicht verstehen, wo das Problem in Ihrem eigenen Code oder dem eines anderen liegt).

#include <MT4Orders.mqh>

#define Ask SymbolInfoDouble(_Symbol, SYMBOL_ASK)

#include <Debug.mqh> // https://c.mql5.com/3/173/Debug.mqh

void OnStart()
{
  // Eröffnet und schließt eine BUY-Position
  if (_P(OrderSelect(_P(OrderSend(_P(_Symbol), _P(OP_BUY), 1, _P(Ask), 100, 0, 0)), _P(SELECT_BY_TICKET))))
    _P(OrderClose(_P(OrderTicket()), _P(OrderLots()), _P(OrderClosePrice()), 100));
}

D.h. jede Stelle, deren Wert Sie sehen wollen, setzen wir in _P() ein. Das Ergebnis

void OnStart(), Line = 10: SELECT_BY_TICKET = 1
void OnStart(), Line = 10: Ask = 1.16688
void OnStart(), Line = 10: OP_BUY = 0
void OnStart(), Line = 10: _Symbol = EURUSD
void OnStart(), Line = 10: OrderSend(_P(_Symbol),_P(OP_BUY),1,_P(Ask),100,0,0) = 293785198
void OnStart(), Line = 10: OrderSelect(_P(OrderSend(_P(_Symbol),_P(OP_BUY),1,_P(Ask),100,0,0)),_P(SELECT_BY_TICKET)) = true
void OnStart(), Line = 11: OrderClosePrice() = 1.16678
void OnStart(), Line = 11: OrderLots() = 1.0
void OnStart(), Line = 11: OrderTicket() = 293785198
void OnStart(), Line = 11: OrderClose(_P(OrderTicket()),_P(OrderLots()),_P(OrderClosePrice()),100) = true


Oder, zum Beispiel, gibt es einen solchen Ausdruck

void OnStart()
{
  int a = 137;
  double b = 1.37;
  
  int Num = ((a = (int)(a / b)) << 1) * a; // 19602
}

Wir müssen schnell herausfinden, warum 19602 ausgegeben wird. Wir fügen die Teile, die wir schnell herausfinden wollen, in unser Makro ein

int Num = _P(_P(((a = _P((int)(_P(a / b)))) << 1)) * _P(a));


Und wir können das Ergebnis der Berechnung Schritt für Schritt sehen

void OnStart(), Line = 8: a/b = 99.99999999999999
void OnStart(), Line = 8: (int)(_P(a/b)) = 99
void OnStart(), Line = 8: ((a=_P((int)(_P(a/b))))<<1) = 198
void OnStart(), Line = 8: a = 99
void OnStart(), Line = 8: _P(((a=_P((int)(_P(a/b))))<<1))*_P(a) = 19602


ZY Statt eines Stücks Artikel...

 
#define  ForEachSymbol(s,i)  string s=SymbolName(0,true); int os_total=SymbolsTotal(true); for(int i=1;i<os_total;i++,s=SymbolName(i,true))

Es gibt einen Fehler, der erste Symbolprozess ist mit Positionsindex 0, der nächste ist mit Positionsindex 2. Dir fehlt der Positionsindex 1 und deine Schleife wird nur os_total-1 mal ausgeführt.

#define  ForEachOrder(ticket,i)    HistorySelect(0,TimeCurrent());  ulong ticket=OrderGetTicket(0); int or_total=OrdersTotal();   for(int i=1;i<or_total;i++,ticket=OrderGetTicket(i))
//+------------------------------------------------------------------+
//| Skript-Programmstartfunktion|
//+------------------------------------------------------------------+
void OnStart()
  {
//---
   ForEachOrder(orderticket,index)
     {
      Print(index,": #",orderticket," ",OrderGetString(ORDER_SYMBOL)," ",
            EnumToString((ENUM_ORDER_TYPE)OrderGetInteger(ORDER_TYPE)));
     }
/* Ausgabebeispiel 
 1: 13965457 CADJPY ORDER_TYPE_SELL_LIMIT
 2: 14246567 AUDNZD ORDER_TYPE_SELL_LIMIT
*/ 
  }

In dieser gibt es den gleichen Fehler wie zuvor.

Außerdem vermischen Sie Funktionen für die Bearbeitung von offenen Aufträgen und die Auswahl der Historie. Wenn Sie beabsichtigen, mit offenen Aufträgen zu arbeiten, besteht keine Notwendigkeit, HistorySelect() zu verwenden.


Übrigens demonstrieren diese Fehler gut das Problem mit ohne Makro. Es ist schwer oder unmöglich zu debuggen.

The most strongest criticism of using #define is the fact that macro substitutions do not allow for code debugging. I agree with this, although, as fxsaber says, "A reliably fixed patient requires no anesthesia debugged macro requires no debugging".

Danach habe ich aufgehört zu lesen, sorry.

 
MetaQuotes:

Neuer Artikel LifeHack für Trader: Mischen von ForEach mit Defines (#define) ist veröffentlicht worden:

Autor: Wladimir Karputow

vielleicht sollten Sie 2 weitere Defines für mql4 hinzufügen, OrderCalcProfit() und OrderCalcMargin()
 
daengrani #:
vielleicht sollten Sie 2 weitere Defines für mql4 hinzufügen, OrderCalcProfit() und OrderCalcMargin()
Nein. Das alte Terminal wird schon seit langem nicht mehr unterstützt.