Sistemi Esperti: MQL5 Programming for Traders – Source Codes from the Book. Parte 7 - pagina 2

 
Denis Kirichenko #:

In generale, per un libro di testo sarebbe meglio scrivere tra parentesi:

Tutti gli operatori della forma @=, dove per cane si intende il simbolo di qualsiasi operazione, vengono sempre eseguiti sull'operando di destra, completamente contato prima dell'esecuzione dell'operazione. Questo aspetto è trattato nella Parte 2, sotto Operazioni di modifica.

Il file di calcolo dei margini è descritto nella sesta parte, dove si presuppone che le parti precedenti siano state padroneggiate. La complessità aumenta verso la fine del libro - non lo metto in dubbio, quindi ho cercato di fare riferimento ai grandi concetti e ai principi delle sezioni precedenti nelle sezioni successive, dove questi sono stati utilizzati come elementi costitutivi (per rinfrescare la memoria), ma non per cose così piccole.

 
Stanislav Korotky #:

...La complessità aumenta verso la fine del libro - non c'è nulla da eccepire, quindi per i grandi concetti e i principi delle sezioni precedenti ho cercato di fare riferimento alle sezioni successive in cui sono stati usati come elementi costitutivi (per rinfrescare la memoria), ma non per cose così piccole.

Stanislav, il mio livello di programmazione è più modesto del tuo. Cerco di scrivere il codice in modo che sia più facile controllarlo nel Debugger. Ecco perché non uso spesso l'operatore ternario. E se lo uso, lo uso con le parentesi... Ci sono persone molto abili che scrivono diversi operatori ternari inclusi l'uno nell'altro. Questo è qualcosa di simile allo stile di programmazione macro del mio collega fxsaber. Probabilmente ogni approccio ha diritto alla vita. Ed è già una questione di gusti...

Grande rispetto e stima per il tutorial! Alcune cose interessanti sono descritte in modo più dettagliato rispetto alla Documentazione.

 
Aleksandr Slavskii #:

È comunque poco utile, perché alla fine conta il margine in modo errato se il volume è più di tre.

Calcolo del margine per dieci contratti.

Allego lo script per la verifica. Ora l'ho eseguito sull'intera panoramica del mercato - coincide con la funzione standard indipendentemente dal volume.

 
Denis Kirichenko #:

E il compilatore è incazzato:

Probabilmente è cambiato qualcosa nel compilatore. Al momento della pubblicazione del libro, tutti i sorgenti venivano compilati senza avvertimenti o errori, tranne nei casi in cui vi erano irregolarità intenzionali a scopo dimostrativo.

 
Denis Kirichenko #:

Cerco di scrivere il codice in modo che sia più facile controllarlo nel Debugger. Ecco perché non uso spesso l'operatore ternario. E se lo uso, lo uso con le parentesi....

Sono d'accordo. Anch'io mi attengo a questa regola, tranne che per i casi semplici - ma qui ognuno ha la sua barriera di semplicità. La leggibilità del codice viene trattata individualmente, di solito si cerca una "media aurea" tra l'approccio "tutto in una riga" e "ogni token su una riga separata". Con le parentesi - in modo simile. Le aziende produttrici di software di solito hanno una serie di regole sul layout del codice sorgente - in questo caso non ce n'era nessuna.

 
Nel codice sono state pubblicate altre correzioni e miglioramenti per la lettura del calendario economico e l'esportazione in CSV. In particolare, è stato corretto l'algoritmo di ordinamento per il caso di array di grandi dimensioni per lo più ordinati (che di solito vengono ricevuti dall'API del calendario MQL5), in modo da eliminare rallentamenti e stack-overflow.
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 #:

Si prega di allegare lo script per la verifica. Ora l'ho eseguito sull'intera panoramica del mercato - coincide con la funzione standard indipendentemente dal volume.

Oh, cavolo. Non posso credere di non aver visto questo messaggio. Oh, cavolo.

In realtà, per me non è cambiato nulla.

Server Metaquot, versione terminale 4420.

Il codice è questo

#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();
  }
//+------------------------------------------------------------------+

Il risultato è questo.

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

Qualcuno sta sbagliando a contare.


Forse mi sono sbarazzato del namespace MPM in modo errato: non so cosa sia e perché sia necessario, ma non mi ha permesso di compilare l'EA.

In realtà, ho solo rimosso la riga del namespace MPM, le parentesi graffe dopo di essa e ho rinominato OrderCalcMargin, aggiungendo il trattino basso.

In generale, il file è stato compilato in questa forma. È possibile che sia questo l'errore?

//+------------------------------------------------------------------+
//|MarginProfitMeter.mqh |
//|Copyright (c) 2018-2022, Marketeer |
//| https://www.mql5.com/en/users/marketeer |
//||Un insieme di funzioni per calcolare il margine, il potenziale di profitto/perdita, il margine di guadagno e la perdita.
//| valore dei punti e tassi di copertura.|
//+------------------------------------------------------------------+
// Analogo dell'OrderCalcMargin integrato che non è consentito negli indicatori.
bool _OrderCalcMargin(const ENUM_ORDER_TYPE action, const string symbol,
                     double volume, double price, double &margin)
  {
   double marginInit, marginMain;
   MqlTick ticks;

// controlla i parametri dati
   if((action != ORDER_TYPE_BUY && action != ORDER_TYPE_SELL) || volume < 0 || price < 0)
      return false;

// richiedere tutte le proprietà utilizzate nelle formule
   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;
  }

// Cerca i simboli disponibili per una singola costruzione delle valute "corrente" e "conto".
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;
  }

// Stima del tasso di un simbolo specificato in un determinato momento del passato
double GetHistoricPrice(const string symbol, const datetime moment, const bool ask)
  {
   const int offset = iBarShift(symbol, _Period, moment);
// NB: iClose può contenere il prezzo Last invece del Bid per i simboli di scambio.
// Non c'è un modo veloce per gestire questo aspetto, ma solo l'analisi della cronologia dei ticks.
   return iClose(symbol, _Period, offset) +
          (ask ? iSpread(symbol, _Period, offset) * SymbolInfoDouble(symbol, SYMBOL_POINT) : 0);
  }

// _Convertire l'importo del denaro "corrente" in denaro "conto".
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;
  }

// Restituzione del valore del punto (in valuta del conto) di un simbolo specifico
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 #:

Il codice è il seguente

Il risultato è questo

Qualcuno sta sbagliando a contare.


Qui si trova la notizia per l'inizio del 2024 (cioè dopo la stesura del libro) sulla build 4150 - https://www.metatrader5.com/en/releasenotes/terminal/2342.

Margine fluttuante per volume

Nelle impostazioni del server e nell'interfaccia delle specifiche dei simboli hanno aggiunto la dipendenza del margine dal volume.

Non ho trovato come accedere a queste proprietà da MQL5.

In un particolare broker/strumento questa impostazione del margine fluttuante potrebbe non essere attivata, quindi non ho notato alcuna differenza quando ho controllato non su MQ demo.

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 #:

Aggiunta della dipendenza dal margine di volume alle impostazioni del server e all'interfaccia delle specifiche dei simboli.

Non ho trovato come accedere a queste proprietà da MQL5.

L'ho anche cercato e non l'ho trovato).
Ho pensato che si trattasse di un bug nella mia testa, ma non è stato così.
Grazie.
 

@Renat Fatkhullin

C'è qualche progetto per aggiungere la possibilità di ottenere queste proprietà da MQL5?

Forum sul trading, sui sistemi di trading automatizzati e sul test delle strategie di trading

Expert Advisors: MQL5 Programming for Traders - codici sorgente dal libro. Parte 7

Stanislav Korotky, 2024.11.23 20:26

Ho trovato nelle news dell'inizio del 2024 (cioè dopo la stesura del libro) la build 4150 - https://www.metatrader5.com/en/releasenotes/terminal/2342.

Margine fluttuante per volume

Nelle impostazioni del server e nell'interfaccia di specificazione dei simboli hanno aggiunto la dipendenza del margine dal volume.

Non ho trovato come accedere a queste proprietà da MQL5.

In un particolare broker/strumento questa impostazione del margine fluttuante potrebbe non essere attivata, per cui non ho notato alcuna differenza quando ho controllato non su MQ demo.