Expert Advisors: MQL5 Programming for Traders – Quellcodes aus dem Buch. Teil 7 - Seite 2

 
Denis Kirichenko #:

Für ein Lehrbuch ist es im Allgemeinen besser, in Klammern zu schreiben:

Alle Operatoren der Form @=, wobei doggy für das Symbol einer beliebigen Operation steht, werden immer über den rechten Operanden ausgeführt, und zwar vollständig gezählt, bevor die Operation ausgeführt wird. Dies wird in Teil 2, unter Modifikationsoperationen, behandelt.

Die Margenberechnungsdatei wird in Teil 6 beschrieben, wobei vorausgesetzt wird, dass die vorherigen Teile beherrscht werden. Die Komplexität nimmt zum Ende des Buches hin zu - das bestreite ich nicht, daher habe ich versucht, in den folgenden Abschnitten auf die großen Konzepte und Prinzipien aus den vorangegangenen Abschnitten zu verweisen, wo diese als Bausteine (zur Auffrischung des Gedächtnisses) verwendet wurden, aber nicht für so kleine Dinge.

 
Stanislav Korotky #:

...Die Komplexität nimmt zum Ende des Buches hin zu - dagegen ist nichts einzuwenden, daher habe ich versucht, für die großen Konzepte und Prinzipien aus den vorangegangenen Abschnitten Verweise auf die folgenden Abschnitte zu machen, in denen sie als Bausteine verwendet wurden (um mein Gedächtnis aufzufrischen), aber nicht für so kleine Dinge.

Stanislav, im Gegensatz zu dir habe ich ein eher bescheidenes Niveau in der Programmierung. Ich versuche, den Code so zu schreiben, dass es einfacher ist, ihn im Debugger zu überprüfen. Deshalb verwende ich den ternären Operator nicht oft. Und wenn, dann verwende ich ihn mit Klammern... Es gibt so geschickte Leute, die mehrere ternäre Operatoren ineinander verschachtelt schreiben. Das kommt dem Makro-Programmierstil meines Kollegen fxsaber sehr nahe. Wahrscheinlich hat jeder Ansatz eine Lebensberechtigung. Und es ist schon eine Frage des Geschmacks...

Großen Respekt und Hochachtung für das Tutorial! Es werden einige interessante Dinge ausführlicher beschrieben als in der Dokumentation.

 
Aleksandr Slavskii #:

Es nützt ohnehin wenig, weil es am Ende immer noch die Marge falsch zählt, wenn die Menge mehr als drei beträgt.

Margin-Berechnung für zehn Kontrakte.

Bitte das Skript zur Überprüfung anhängen. Ich habe es jetzt auf der gesamten Marktübersicht laufen lassen - es stimmt mit der Standardfunktion überein, unabhängig vom Volumen.

 
Denis Kirichenko #:

Und der Compiler ist stinksauer:

Wahrscheinlich hat sich im Compiler etwas geändert. Zum Zeitpunkt der Veröffentlichung des Buches wurden alle Quellen ohne Warnungen oder Fehler kompiliert, außer in Fällen, in denen es zu Demonstrationszwecken absichtlich Unregelmäßigkeiten gab.

 
Denis Kirichenko #:

Ich versuche, den Code so zu schreiben, dass es einfacher ist, ihn im Debugger zu überprüfen. Deshalb verwende ich den ternären Operator nicht oft. Und wenn doch, dann verwende ich ihn mit Klammern....

Ich stimme zu. Ich halte mich auch an diese Regel, außer in einfachen Fällen - aber hier hat jeder seine eigene Schranke der Einfachheit. Die Lesbarkeit des Codes wird individuell behandelt, normalerweise suchen wir nach einer "goldenen Mitte" zwischen dem Ansatz "alles in einer Zeile" und "jedes Token in einer eigenen Zeile". Bei Klammern ist es ähnlich. Softwareunternehmen haben in der Regel eine Reihe von Regeln für das Layout des Quellcodes - in diesem Fall gab es keine.

 
Weitere Bugfixes und Verbesserungen für das Lesen des Wirtschaftskalenders und den Export nach CSV wurden in der Codebase veröffentlicht. Insbesondere wurde der Sortieralgorithmus für den Fall von meist sortierten großen Arrays (die üblicherweise von der MQL5-Kalender-API empfangen werden) korrigiert, so dass Verlangsamungen und Stack-Overflows beseitigt werden.
Economic Calendar CSV
Economic Calendar CSV
  • www.mql5.com
This script saves a predefined set of economic events from the MetaTrader's built-in economic calendar into CSV file.
 
Stanislav Korotky #:

Bitte fügen Sie das Skript zur Überprüfung an. Jetzt habe ich es auf der gesamten Marktübersicht laufen lassen - es stimmt mit der Standardfunktion überein, unabhängig vom Volumen.

Oh, Mann. Ich kann nicht glauben, dass ich diese Meldung nicht gesehen habe. Oh, Mann.

Eigentlich hat sich für mich nichts geändert.

Metaquot-Server, Terminalversion 4420.

Der Code sieht folgendermaßen aus

#include "MarginProfitMeter.mqh"
//+------------------------------------------------------------------+
int OnInit(void)
  {
   EventSetTimer(1);
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
void OnTimer()
  {
   double margin = 0;
   double volume = 10;
   ENUM_ORDER_TYPE type = ORDER_TYPE_BUY;
   double price = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
   if(_OrderCalcMargin(type, _Symbol, volume, price, margin))
      Print("Symbol ", _Symbol, "; volume ", volume, "; MarginProfitMeter margin = ", margin);

   margin = 0;
   if(OrderCalcMargin(type, _Symbol, volume, price, margin))
      Print("Symbol ", _Symbol, "; volume ", volume, "; OrderCalcMargin margin = ", margin);
  }
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
   EventKillTimer();
  }
//+------------------------------------------------------------------+

Das Ergebnis ist dieses.

18:53:40.877    11 (EURUSD,H1)  Symbol EURUSD; volume 10.0; MarginProfitMeter margin = 10421.6
18:53:40.877    11 (EURUSD,H1)  Symbol EURUSD; volume 10.0; OrderCalcMargin margin = 23264.8

Da hat jemand falsch gezählt.


Möglicherweise habe ich den Namespace MPM falsch entfernt. Ich weiß nicht, was er ist und warum er benötigt wird, aber er hat mich den EA nicht kompilieren lassen.

Eigentlich habe ich nur die Namespace MPM-Zeile und die geschweiften Klammern danach entfernt und OrderCalcMargin umbenannt und den Unterstrich hinzugefügt.

Im Allgemeinen wurde die Datei in dieser Form kompiliert. Ist es möglich, dass dies der Fehler ist?

//+------------------------------------------------------------------+
//|MarginProfitMeter.mqh |
//|Copyright (c) 2018-2022, Marketeer |
//| https://www.mql5.com/en/users/marketeer |
//|| Eine Reihe von Funktionen zur Berechnung von Gewinnspanne, potentiellem Gewinn/Verlust, etc.
//| Punktwert und Deckungsraten.|
//+------------------------------------------------------------------+
// Analog zur eingebauten OrderCalcMargin, die in Indikatoren nicht zulässig ist
bool _OrderCalcMargin(const ENUM_ORDER_TYPE action, const string symbol,
                     double volume, double price, double &margin)
  {
   double marginInit, marginMain;
   MqlTick ticks;

// Überprüfung der angegebenen Parameter
   if((action != ORDER_TYPE_BUY && action != ORDER_TYPE_SELL) || volume < 0 || price < 0)
      return false;

// Abfrage aller in den Formeln verwendeten Eigenschaften
   if(!SymbolInfoTick(symbol, ticks))
      return false;
   if(!SymbolInfoMarginRate(symbol, action, marginInit, marginMain))
      return false;
   const double contract = SymbolInfoDouble(symbol, SYMBOL_TRADE_CONTRACT_SIZE);
   long leverage = AccountInfoInteger(ACCOUNT_LEVERAGE);
   if(volume == 0)
      volume = SymbolInfoDouble(symbol, SYMBOL_VOLUME_MIN);
   if(price == 0)
      price = action == ORDER_TYPE_BUY ? ticks.ask : ticks.bid;

   if(margin == DBL_MAX)
      marginInit = marginMain;
   margin = 0;

   const ENUM_SYMBOL_CALC_MODE m = (ENUM_SYMBOL_CALC_MODE)SymbolInfoInteger(symbol, SYMBOL_TRADE_CALC_MODE);

   switch(m)
     {
      case SYMBOL_CALC_MODE_FOREX_NO_LEVERAGE:
         leverage = 1;

      case SYMBOL_CALC_MODE_FOREX:
         margin = volume * contract / leverage * marginInit;
         break;

      case SYMBOL_CALC_MODE_CFD:
         margin = volume * contract * price * marginInit;
         break;

      case SYMBOL_CALC_MODE_CFDINDEX:
         margin = volume * contract * price * SymbolInfoDouble(symbol, SYMBOL_TRADE_TICK_VALUE)
                  / SymbolInfoDouble(symbol, SYMBOL_TRADE_TICK_SIZE) * marginInit;
         break;

      case SYMBOL_CALC_MODE_CFDLEVERAGE:
         margin = volume * contract * price / leverage * marginInit;
         break;

      case SYMBOL_CALC_MODE_EXCH_STOCKS:
      case SYMBOL_CALC_MODE_EXCH_STOCKS_MOEX:
         if(price == 0)
            price = ticks.last;
         margin = volume * contract * price * marginInit;
         break;

      case SYMBOL_CALC_MODE_FUTURES:
      case SYMBOL_CALC_MODE_EXCH_FUTURES:
      case SYMBOL_CALC_MODE_EXCH_FUTURES_FORTS:
         margin = volume * SymbolInfoDouble(symbol, SYMBOL_MARGIN_INITIAL) * marginInit;
         break;
      default:
         PrintFormat("Unsupported symbol %s trade mode: %s", symbol, EnumToString(m));
     }

   string account = AccountInfoString(ACCOUNT_CURRENCY);
   string current = SymbolInfoString(symbol, SYMBOL_CURRENCY_MARGIN);
   if(current != account)
     {
      if(!_Convert(current, account, action == ORDER_TYPE_SELL, margin))
         return false;
     }

   return true;
  }

// Suche nach verfügbaren Symbolen für ein einzelnes Gebilde aus den Währungen "current" und "account
int _FindExchangeRate(const string current, const string account, string &result)
  {
   for(int i = 0; i < SymbolsTotal(true); i++)
     {
      const string symbol = SymbolName(i, true);
      const ENUM_SYMBOL_CALC_MODE m = (ENUM_SYMBOL_CALC_MODE)SymbolInfoInteger(symbol, SYMBOL_TRADE_CALC_MODE);
      if(m == SYMBOL_CALC_MODE_FOREX || m == SYMBOL_CALC_MODE_FOREX_NO_LEVERAGE)
        {
         string base = SymbolInfoString(symbol, SYMBOL_CURRENCY_BASE);
         string profit = SymbolInfoString(symbol, SYMBOL_CURRENCY_PROFIT);
         if(base == current && profit == account)
           {
            result = symbol;
            return +1;
           }
         else
            if(base == account && profit == current)
              {
               result = symbol;
               return -1;
              }
        }
     }
   return 0;
  }

// Schätzung einer Rate eines bestimmten Symbols zu einem bestimmten Zeitpunkt in der Vergangenheit
double GetHistoricPrice(const string symbol, const datetime moment, const bool ask)
  {
   const int offset = iBarShift(symbol, _Period, moment);
// NB: iClose kann für Börsensymbole den letzten Preis anstelle des Geldkurses enthalten.
// es gibt keine schnelle Möglichkeit, dies zu handhaben, nur die Analyse der Tick-Historie
   return iClose(symbol, _Period, offset) +
          (ask ? iSpread(symbol, _Period, offset) * SymbolInfoDouble(symbol, SYMBOL_POINT) : 0);
  }

// _Umwandlung des "aktuellen" Geldbetrags in "Kontogeld".
bool _Convert(const string current, const string account,
             const bool ask, double &margin, const datetime moment = 0)
  {
   string rate;
   int dir = _FindExchangeRate(current, account, rate);
   if(dir == +1)
     {
      margin *= moment == 0 ?
                SymbolInfoDouble(rate, ask ? SYMBOL_BID : SYMBOL_ASK) :
                GetHistoricPrice(rate, moment, ask);
     }
   else
      if(dir == -1)
        {
         margin /= moment == 0 ?
                   SymbolInfoDouble(rate, ask ? SYMBOL_ASK : SYMBOL_BID) :
                   GetHistoricPrice(rate, moment, ask);
        }
      else
        {
         static bool once = false;
         if(!once)
           {
            Print("Can't convert ", current, " -> ", account);
            once = true;
           }
        }
   return true;
  }

// Rückgabe des Punktwerts (in Kontowährung) eines bestimmten Symbols
double PointValue(const string symbol, const bool ask = false, const datetime moment = 0)
  {
   const double point = SymbolInfoDouble(symbol, SYMBOL_POINT);
   const double contract = SymbolInfoDouble(symbol, SYMBOL_TRADE_CONTRACT_SIZE);
   const ENUM_SYMBOL_CALC_MODE m = (ENUM_SYMBOL_CALC_MODE)SymbolInfoInteger(symbol, SYMBOL_TRADE_CALC_MODE);
   double result = 0;

   switch(m)
     {
      case SYMBOL_CALC_MODE_FOREX_NO_LEVERAGE:
      case SYMBOL_CALC_MODE_FOREX:
      case SYMBOL_CALC_MODE_CFD:
      case SYMBOL_CALC_MODE_CFDINDEX:
      case SYMBOL_CALC_MODE_CFDLEVERAGE:
      case SYMBOL_CALC_MODE_EXCH_STOCKS:
      case SYMBOL_CALC_MODE_EXCH_STOCKS_MOEX:
         result = point * contract;
         break;

      case SYMBOL_CALC_MODE_FUTURES:
      case SYMBOL_CALC_MODE_EXCH_FUTURES:
      case SYMBOL_CALC_MODE_EXCH_FUTURES_FORTS:
         result = point * SymbolInfoDouble(symbol, SYMBOL_TRADE_TICK_VALUE) / SymbolInfoDouble(symbol, SYMBOL_TRADE_TICK_SIZE);
         break;
      default:
         PrintFormat("Unsupported symbol %s trade mode: %s", symbol, EnumToString(m));
     }

   string account = AccountInfoString(ACCOUNT_CURRENCY);
   string current = SymbolInfoString(symbol, SYMBOL_CURRENCY_PROFIT);

   if(current != account)
     {
      if(!_Convert(current, account, ask, result, moment))
         return 0;
     }

   return result;
  }
//+------------------------------------------------------------------+
 
Aleksandr Slavskii #:

Der Code lautet wie folgt

Das Ergebnis ist wie folgt

Jemand hat sich verzählt.


Hier ist in den News für Anfang 2024 (also nach dem Schreiben des Buches) über Build 4150 - https://www.metatrader5.com/en/releasenotes/terminal/2342 zu finden .

Gleitende Marge nach Volumen

In den Server-Einstellungen und der Symbol-Spezifikationsschnittstelle haben sie die Margenabhängigkeit vom Volumen hinzugefügt.

Ich habe nicht herausgefunden, wie man von MQL5 aus zu diesen Eigenschaften gelangt.

Bei einem bestimmten Broker/Instrument ist diese Floating-Margin-Einstellung möglicherweise nicht aktiviert, so dass ich bei der Überprüfung in der MQ-Demo keine Unterschiede feststellen konnte.

MetaTrader 5 build 4150: Trading report export and new machine learning methods in MQL5
MetaTrader 5 build 4150: Trading report export and new machine learning methods in MQL5
  • 2024.01.18
  • MetaQuotes
  • www.metatrader5.com
Added export of trading reports to HTML and PDF files. With this option, you can easily share your trading achievements with colleagues and investors. New export commands are available in the File menu and in the report menu. Added ability to save the current state of the Market Watch window to a CSV file. To do this, select Export in the...
 
Stanislav Korotky #:

Die Abhängigkeit vom Volumenrand wurde zu den Servereinstellungen und der Schnittstelle für Symbolspezifikationen hinzugefügt.

Ich habe nicht gefunden, wie man zu diesen Eigenschaften von MQL5 zu bekommen.

Ich habe auch danach gesucht und es auch nicht gefunden)
Ich dachte, es sei ein Fehler in meinem Kopf, aber es stellte sich heraus, dass es keiner war.
Danke!
 

@Renat Fatkhullin

Gibt es Pläne, die Möglichkeit hinzuzufügen, diese Eigenschaften von MQL5 zu erhalten?

Forum über Handel, automatisierte Handelssysteme und das Testen von Handelsstrategien

Expert Advisors: MQL5 Programming for Traders - Quellcodes aus dem Buch. Teil 7

Stanislav Korotky, 2024.11.23 20:26

Hier habe ich in den Nachrichten für Anfang 2024 (d.h. nachdem das Buch geschrieben wurde) über Build 4150 gefunden - https://www.metatrader5.com/en/releasenotes/terminal/2342.

Gleitende Marge nach Volumen

In den Server-Einstellungen und der Symbol-Spezifikationsschnittstelle wurde die Randabhängigkeit von der Lautstärke hinzugefügt.

Ich habe nicht herausgefunden, wie man von MQL5 aus zu diesen Eigenschaften gelangt.

Bei einem bestimmten Broker/Instrument ist diese Floating-Margin-Einstellung möglicherweise nicht aktiviert, so dass ich bei der Überprüfung in der MQ-Demo keine Unterschiede feststellen konnte.