English Русский 中文 Español Deutsch 日本語 Português 한국어 Français Türkçe
L'uso delle Librerie MQL5 Standard Trade Class nella scrittura di un Expert Advisor

L'uso delle Librerie MQL5 Standard Trade Class nella scrittura di un Expert Advisor

MetaTrader 5Sistemi di trading | 16 dicembre 2021, 10:57
772 0
Samuel Olowoyo
Samuel Olowoyo

Introduzione

Il nuovo programma MQL5 viene fornito con molte librerie di classi Standard integrate che hanno lo scopo di rendere lo sviluppo di Expert Advisor, Indicatori e Script MQL5 il più semplice possibile per i trader per gli sviluppatori.

Queste librerie di classi sono disponibili nella cartella \Include\ situato all'interno della cartella MQL5 nella cartella del terminale client MetaTrader 5. Le librerie di classi sono divisi in varie categorie – Array, ChartObjects, Grafici, File, Indicatori, Stringhe e classi di Trading

In questo articolo, descriveremo in dettaglio come possiamo utilizzare le classi di Trading integrate per scrivere un Expert Advisor. L'Expert Advisor si baserà su una strategia che includerà la chiusura e modifica delle posizioni aperte al verificarsi di una condizione prevista.

Se hai già un'idea di cosa sono le classi e come possono essere utilizzate, allora sei il benvenuto in un altro mondo di opportunità che il nuovo linguaggio MQL5 ha da offrire.

Se, d'altra parte, sei completamente nuovo in MQL5; allora ti consiglio di leggere questi due articoli per iniziare Guida Passo per Passo alla Scrittura di un Expert Advisor in MQL5 per Principianti, Scrittura di un Expert Advisor Utilizzando l'Approccio di Programmazione Orientato agli Oggetti MQL5 o qualsiasi altro articolo che fornisca un'introduzione al nuovo linguaggio MQL5. Sono stati scritti molti articoli che ti forniranno le conoscenze necessarie.


1. Classi di Trading

La cartella delle classi di trading consiste in diverse classi che hanno lo scopo di semplificare la vita ai trader chi quale sviluppare un EA per uso personale o per programmatori che non dovranno reinventare la ruota quando sviluppano i loro Expert Advisor (EA).

Quando si utilizza una classe, non è necessario conoscere il funzionamento interno della classe (cioè come realizza ciò che lo sviluppatore dice), tutto ciò su cui devi concentrarti è in che modo la classe può essere usata per risolvere il tuo problema. Questo è il motivo per cui l'utilizzo di una libreria di classi integrata rende le cose abbastanza facile per chiunque voglia usarli. In questo articolo considereremo le classi principali che saranno necessarie nel corso dello sviluppo di un Expert Advisor

Nel discutere le classi, non ci preoccuperemo dei dettagli interni delle classi, ma parleremo in dettaglio di cosa una classe può fare e come possiamo usarlo per realizzare la nostra missione nello sviluppo di un EA molto redditizio. Discutiamone uno dopo l'altro.

1.1 La classe СAccountInfo

La CAAccountInfo è una classe che rende facile per l'utente avere accesso a tutti le proprietà di account o informazioni per il conto corrente aperto nel terminale client.

Per capirne meglio, esamineremo le principali funzioni membro di questa classe che potremmo probabilmente utilizzare nel nostro EA. Prima di poter usare una classe, dobbiamo prima di tutto creare un oggetto di quella classe, quindi per usare la classe CAccountInfo dobbiamo creare un oggetto della classe.

Chiamiamolo myaccount:

//--- The AccountInfo Class Object
CAccountInfo myaccount;

Ricorda che per creare un oggetto di una classe, utilizzerai il nome della classe seguito dal nome che desideri dare all’oggetto.

Ora possiamo usare il nostro oggetto myaccount per accedere alle funzioni membro pubbliche della classe CAccountInfo .

Metodo
Descrizione
Esempio di utilizzo
myaccount.Login()

Questa funzione viene utilizzata quando si desidera ottenere il numero dell’account per il trade corrente aperto nel terminale.

// returns account number, example 7770
long accountno = myaccount.Login()
myaccount.TradeModeDescription() Questa funzione viene utilizzata per ottenere la descrizione della modalità di trading per l’account attualmente attivo sul terminale.
// returns Demo trading account, 
// or Real trading account or Contest trading account
string  acc_trading_mode = myaccount.TradeModeDescription();
myaccount.Leverage()

Questa funzione viene utilizzata per ottenere la descrizione della modalità di trading per l'attuale account attivo sul terminale.

// returns leverage given to the active account
long acc_leverage = myaccount.Leverage(); 
myaccount.TradeAllowed()  

Questa funzione viene utilizzata per verificare se il trade è consentito sull’account attivo sul terminale. Se il trade non è consentito, l'account non può negoziare.

if (myaccount.TradeAllowed())
{
    // trade is allowed
}
else
{
  // trade is not allowed
}
myaccount.TradeExpert() Questa funzione viene utilizzata per verificare se gli Expert Advisor sono autorizzati a negoziare per l'account attualmente attivo nel terminale.
if (myaccount.TradeExpert())
{
   // Expert Advisor trade is allowed
}
else
{
   // Expert Advisor trade is not allowed
}
myaccount.Balance() Questa funzione fornisce il saldo dell’account per il conto attivo sul terminale.
// returns account balance in the deposit currency
double acс_balance =  myaccount.Balance(); 
myaccount.Profit()  

Questa viene utilizzata per ottenere l'utile corrente del conto attivo sul terminale.

// returns account profit in deposit currency
double acс_profit =  myaccount.Profit();
myaccount.FreeMargin()  

Questa funzione viene utilizzata per ottenere il margine libero dell’account attivo sul terminale.

// returns free margin for active account
double acс_free_margin = myaccount.FreeMargin();
myaccount.Currency()  

Questa funzione viene utilizzata per ottenere la valuta di deposito per l'account attivo sul terminale.

string acс_currency = myaccount.Currency();
myaccount.OrderProfitCheck(const string symbol, ENUM_ORDER_TYPE  trade_operation, double volume, double price_open, double price_close) Questa funzione ottiene il profitto valutato, in base ai parametri passati. I parametri di input sono: simbolo, tipo di operazione di trading, volume e prezzi di apertura/chiusura.
double op_profit=myaccount.OrderProfitCheck(_Symbol,ORDER_TYPE_BUY,
1.0,1.2950,1.3235);
Print("The amount of Profit for deal buy EURUSD",
      "at 1.2950 and sell at 1.3235 is: ",op_profit);
myaccount.MarginCheck(const string symbol,ENUM_ORDER_TYPE trade_operation,double  volume,double price) Questa funzione viene utilizzata per ottenere il margine necessario per aprire un ordine. Questa funzione ha quattro parametri di input che sono: il simbolo (coppia di valute), il tipo di ordine, i lotti (o volume) da fare trading e il prezzo dell'ordine. Questa funzione è molto importante quando si piazza un trade.
// depending on the type of position to open - in our case buy
double price=SymbolInfoDouble(_Symbol,SYMBOL_ASK); 
double margin_req=myaccount.MarginCheck(_Symbol,ORDER_TYPE_BUY,LOT,price);
myaccount.FreeMarginCheck(const string symbol,ENUM_ORDER_TYPE trade_operation,double volume,double price) Questa funzione viene utilizzata per ottenere la quantità di margine libero rimasto nel conto attivo quando un ordine viene effettuato. Ha quattro parametri di input che sono: il simbolo (coppia di valute), il tipo di ordine, i lotti (o il volume) da fare trading e il prezzo dell'ordine.
double acс_fm=myaccount.FreeMarginCheck(_Symbol,ORDER_TYPE_BUY,LOT,price);
myaccount.MaxLotCheck(const string symbol,ENUM_ORDER_TYPE trade_operation,double price)  

Questa funzione viene utilizzata per ottenere il lotto massimo possibile per effettuare un ordine per l'account attivo sul terminale. Ha tre parametri di input che sono: il simbolo, il tipo di ordine e il prezzo di apertura dell'ordine.

double max_lot=myaccount.MaxLotCheck(_Symbol,ORDER_TYPE_BUY,price);

1.2 La Classe SymbolInfo

La classe CSymbolInfo rende molto facile per l'utente avere rapidamente accesso a tutte le proprietà del simbolo attuale.

Per usare la classe, dobbiamo creare un oggetto della classe, in questo caso lo chiameremo mysymbol.

// the CSymbolInfo Class object CSymbolInfo mysymbol;

 Diamo un'occhiata alla maggior parte delle funzioni di questa classe che possono essere utilizzati nel processo di scrittura del nostro Expert Advisor:

 Metodo  Descrizione Esempio di utilizzo
mysymbol.Name(string  name)

Questa funzione viene utilizzata per impostare il simbolo per l'oggetto classe. Ci vuole il nome del simbolo come parametro di input.

// set the symbol name for our CSymbolInfo class Object
mysymbol.Name(_Symbol);
mysymbol.Refresh() Questa funzione viene utilizzata per aggiornare tutti i dati del simbolo. Viene chiamata automaticamente anche quando si imposta un nuovo nome di simbolo per la classe.
mysymbol.Refresh();
mysmbol.RefreshRates() Questa funzione viene utilizzata per controllare i dati delle quotazioni più recenti. Ritorna vero in caso di successo e falso in caso di fallimento. Questa è una funzione utile di cui non puoi fare a meno.
//--- Get the last price quote using the CSymbolInfo 
// class object function
   if (!mysymbol.RefreshRates())
   {
      // error getting latest price quotes 
   }
mysymbol.IsSynchronized()

Questa funzione serve per verificare se i dati attuali del simbolo impostato sul terminale è sincronizzato con i dati sul server. Restituisce vero se i dati sono sincronizzato e falso in caso contrario.

// check if symbol data are synchronized with server
  if (!mysymbol.IsSynchronized())
   {
     // error! Symbol data aren't synchronized with server
   }
mysymbol.VolumeHigh()  

Questa funzione viene utilizzata per ottenere il volume massimo del giorno per il simbolo impostato.

long max_vol = mysymbol.VolumeHigh();
mysymbol.VolumeLow()  

Questa funzione viene utilizzata per ottenere il volume minimo della giornata per il simbolo del set.

long min_vol = mysymbol.VolumeLow();
mysymbol.Time()  

Questa funzione viene utilizzata per ottenere l'ora dell'ultima quotazione del prezzo per il simbolo dell'insieme.

datetime qtime = mysymbol.Time();
mysymbol.Spread() Questa funzione viene utilizzata per ottenere il valore di diffusione corrente (in punti) per il simbolo impostato.
int spread = mysymbol.Spread();
mysymbol.StopsLevel() Questa funzione viene utilizzata per ottenere il livello minimo (in punti) al prezzo di chiusura corrente per il quale è possibile posizionare lo stop loss per il simbolo impostato. Una funzione molto utile se stai pensando di utilizzare il Trailing Stop o la modifica dell'ordine/posizione.
int stp_level = mysymbol.StopsLevel();
mysymbol.FreezeLevel() Questa funzione viene utilizzata per ottenere la distanza (in punti) di congelamento dell'operazione di trading per il simbolo impostato
int frz_level = mysymbol.FreezeLevel();
mysymbol.Bid()

Questa viene utilizzata per ottenere il prezzo BID corrente per il simbolo impostato.

double bid =  mysymbol.Bid();
mysymbol.BidHigh() Questa funzione viene utilizzata per ottenere il prezzo BID massimo/più alto per il giorno.
double max_bid = mysymbol.BidHigh();
mysymbol.BidLow() Questa funzione viene utilizzata per ottenere il prezzo BID minimo/minimo per il giorno per il set del simbolo.
double min_bid = mysymbol.BidLow();
msymbol.Ask() Questa funzione viene utilizzata per ottenere il prezzo ASK corrente per il simbolo impostato.
double ask = mysymbol.Ask();
mysymbol.AskHigh() Questa funzione viene utilizzata per ottenere il prezzo ASK massimo/più alto per il giorno per il set del simbolo.
double max_ask = mysymbol.AskHigh();
mysymbol.AskLow() Questa viene utilizzata per ottenere il prezzo ASK minimo/minimo per il giorno.
double min_ask = mysymbol.AskLow();
mysymbol.CurrencyBase() Questa viene utilizzata per ottenere la valuta di base per il simbolo impostato.
// returns "USD" for USDJPY or USDCAD
string base_currency = mysymbol.CurrencyBase();
mysymbol.ContractSize() Questa funzione viene utilizzata per ottenere l'importo per la dimensione del contratto per la negoziazione del set del simbolo.
double cont_size =  mysymbol.ContractSize();
mysymbol.Digits()  Questa viene utilizzata per ottenere il numero di cifre dopo la virgola decimale per il set del simbolo.
int s_digits = mysymbol.Digits();
mysymbol.Point() Questa funzione viene utilizzata per ottenere il valore di un punto per il simbolo dell'insieme.
double s_point =  mysymbol.Point();
mysymbol.LotsMin() Questa viene utilizzata per ottenere il volume minimo necessario per chiudere un affare per il simbolo.
double min_lot =  mysymbol.LotsMin();
mysymbol.LotsMax() Questa viene utilizzata per ottenere il volume massimo necessario per chiudere un affare per il simbolo.
double max_lot =  mysymbol.LotsMax();
mysymbol.LotsStep() Questa funzione viene utilizzata per ottenere il passaggio minimo di variazione del volume per chiudere un affare per il simbolo.
double lot_step = mysymbol.LotsStep();
mysymbol.NormalizePrice(double price) Questa funzione viene utilizzata per ottenere un prezzo normalizzato alle cifre corrette del set del simbolo.
// A normalized current Ask price
double n_price = mysymbol.NormalizePrice(mysymbol.Ask()); 
mysymbol.Select() Questa funzione viene utilizzata per determinare se un simbolo è stato selezionato nella finestra del market watch. Restituisce vero se è stato selezionato il simbolo altrimenti restituisce falso.
if (mysymbol.Select())
{
  //Symbol successfully selected
}
else
{
  // Symbol could not be selected
}
mysymbol.Select(bool select) Questa La funzione viene utilizzata per selezionare un simbolo nella finestra di Market Watch o per rimuovere un simbolo nella finestra del market watch. Va notato che la rimozione di un simbolo dalla finestra del market watch quando il grafico è aperto o quando ha già una posizione aperta restituirà false.
if (!mysymbol.Select())
{
   //Symbol not selected, Select the symbol
    mysymbol.Select(true);
}
else
{
 // Symbol already selected, 
 // remove Symbol from market watch window
    mysymbol.Select(false);
}
mysymbol.MarginInitial() Questa funzione viene utilizzata per ottenere l'importo necessario per l'apertura di una posizione con volume di un lotto nella valuta del margine.
double init_margin = mysymbol.MarginInitial() ; 
mysymbol.TradeMode() Questa funzione viene utilizzata per ottenere il tipo di esecuzione dell'ordine consentito per il simbolo.
if (mysymbol.TradeMode() == SYMBOL_TRADE_MODE_FULL)
{
 // Full trade allowed for this symbol,
 // no trade restrictions 
}
mysymbol.TradeModeDescription() Questa viene utilizzata per ottenere la descrizione del tipo di esecuzione dell'ordine consentito per il simbolo.
Print("The trade mode for this symbol is",
       mysymbol.TradeModeDescription());

1.3 The СHistoryOrderInfo Class

The CHistoryOrderInfo è un’altra classe che semplifica la gestione delle proprietà della cronologia degli ordini.

Una volta che creiamo un oggetto di questa classe possiamo quindi utilizzare l'oggetto per accedere all'importante funzioni dei membri pubblici di cui abbiamo bisogno per risolvere un problema immediato.

Chiamiamo l'oggetto della classe myhistory

// The CHistoryOrderInfo Class object
CHistoryOrderInfo myhistory;

Diamo un'occhiata ad alcune delle principali funzioni di questa classe.

Nell'usare questa classe per ottenere i dettagli degli ordini nella cronologia, dobbiamo prima di tutto ottenere gli ordini totali nella cronologia e poi passa il ticket d'ordine al nostro oggetto di classe, myhistory.

//Select all history orders within a time period
if (HistorySelect(0,TimeCurrent()))  // get all history orders
{
// Get total orders in history
int tot_hist_orders = HistoryOrdersTotal(); 

Ora itereremo attraverso gli ordini storici totali disponibili e ottieni i dettagli di ogni ordine storico con il nostro oggetto di classe.

ulong h_ticket; // Order ticket

for (int j=0; j<tot_hist_orders; j++)
{
  h_ticket = HistoryOrderGetTicket(j));

  if (h_ticket>0)
  {
    // First thing is to now set the order Ticket to work with by our class object 
Metodo
 Descrizione Esempio di utilizzo
myhistory.Ticket(ulong ticket) Questa funzione viene utilizzata per selezionare il ticket dell'ordine per il quale vogliamo ottenere le sue proprietà o dettagli.
myhistory.Ticket(h_ticket);
myhistory.Ticket()  Questa funzione viene utilizzata per ottenere il ticket dell'ordine per un ordine.
ulong o_ticket = myhistory.Ticket();
myhistory.TimeSetup() Questa funzione viene utilizzata per ottenere l'ora in cui l'ordine è stato eseguito o impostato.
datetime os_time = myhistory.TimeSetup();
myhistory.OrderType() Questa viene utilizzata per ottenere il tipo di ordine (ORDER_TYPE_BUY, ecc.).
if (myhistory.OrderType() == ORDER_TYPE_BUY)
{
// This is a buy order
}
myhistory.State() Questa funzione viene utilizzata per ottenere lo stato corrente dell'ordine.
Se l'ordine è stato cancellato, accettato, rifiutato o collocato, ecc.
if(myhistory.State() == ORDER_STATE_REJECTED)
{
// order was rejected, not placed.
}
myhistory.TimeDone() Questa viene utilizzata per ottenere l'ora in cui l'ordine è stato effettuato, annullato o rifiutato.
datetime ot_done =  myhistory.TimeDone();
myhistory.Magic() Questa funzione viene utilizzata per ottenere l'ID Expert Advisor che ha avviato l'ordine.
long o_magic = myhistory.Magic();
myhistory.PositionId() Questa funzione viene utilizzata per ottenere l'id della posizione in cui è stato incluso l'ordine quando posizionato.
long o_posid = myhistory.PositionId();
myhistory.PriceOpen() Questa viene utilizzata per ottenere il prezzo di apertura dell'ordine.
double o_price =  myhistory.PriceOpen();
myhistory.Symbol() Questa viene utilizzata per ottenere la proprietà del simbolo (coppia di valute) dell'ordine.
string o_symbol =  myhistory.Symbol();
      

Non dimenticare che abbiamo usato queste funzioni all'interno di un ciclo di ordini totali nella storia.

1.4 La Classe COrderInfo

La COrderInfo è una classe che fornisce un facile accesso a tutte le proprietà dell'ordine in sospeso. Una volta che l'oggetto di questa classe è stato creato, può essere utilizzato per le funzioni membro pubblico di questa classe.

L'uso di questa classe è in qualche modo simile alla classe CHstoryOrderInfo discussa sopra.

Creiamo un oggetto della classe, lo chiameremo myorder.

// The OrderInfo Class object
COrderInfo myorder;

Per poter usare questa classe per ottenere i dettagli di un ordine in sospeso, dobbiamo prima di tutto ottenere il totale ordini disponibili e poi selezionarli dal ticket d'ordine.

// Select all history orders within a time period
if (HistorySelect(0,TimeCurrent()))   // get all history orders
   {    
     // get total orders
     int o_total = OrdersTotal();

Esamineremo gli ordini totali e otterremo le loro proprietà corrispondenti utilizzando l'oggetto che abbiamo creato.

for (int j=0; j<o_total; j++)
{
 // we must confirm if the order is available for us to get its details using the Select function of the COrderInfo Class
    Metodo
    Descrizione
    Esempio di utilizzo
    myorder.Select(ulong ticket)  Questa funzione viene utilizzata per selezionare un ordine in base al numero di biglietto in modo che l'ordine possa essere facilmente manipolato.
    if (myorder.Select(OrderGetTicket(j)) 
       { // order has been selected and can now be manipulated.
       }
    myorder.Ticket()  Questa funzione viene utilizzata per ottenere il ticket d'ordine per l'ordine selezionato.
    ulong o_ticket = myorder.Ticket();
    myorder.TimeSetup() Questa viene utilizzata per ottenere l'ora in cui è stato impostato questo ordine.
    datetime o_setup = myorder.TimeSetup();
    myorder.Type() Questa la funzione viene utilizzata per ottenere il tipo di ordine come ORDER_TYPE_BUY_STOP, ecc.
    if (myorder.Type() == ORDER_TYPE_BUY_LIMIT)
    {
    // This is a Buy Limit order, etc
    }
    myorder.State() Questa funzione viene utilizzata per ottenere lo stato dell'ordine.
    Se l'ordine è stato annullato, accettato, rifiutato o inserito, ecc.
    if (myorder.State() ==ORDER_STATE_STARTED)
    {
    // order has been checked 
    // and may soon be treated by the broker
    }
    myorder.TimeDone() Questa viene utilizzata per ottenere l'ora in cui l'ordine è stato effettuato, rifiutato o annullato.
    datetime ot_done = myorder.TimeDone();
    myorder.Magic() Questa La funzione viene utilizzata per ottenere l'ID dell'Expert Advisor che ha avviato l'ordine.
    long o_magic =  myorder.Magic();
    myorder.PositionId() Questa funzione viene utilizzata per ottenere l'id della posizione a cui l'ordine è incluso quando posizionato.
    long o_posid = myorder.PositionId();
    myorder.PriceOpen() Questa viene utilizzata per ottenere il prezzo di apertura dell'ordine.
    double o_price = myorder.PriceOpen();
    myorder.StopLoss() Questa funzione viene utilizzata per ottenere lo Stop loss dell'ordine.
    double  s_loss = myorder.StopLoss();
    myorder.TakeProfit() Questa viene utilizzata per ottenere il Take Profit dell'ordine.
    double t_profit = myorder.TakeProfit();
    myorder.PriceCurrent() Questa funzione viene utilizzata per ottenere il prezzo corrente del simbolo in cui è stato effettuato l'ordine posizionato.
    double cur_price =  myorder.PriceCurrent();
    myorder.Symbol() Questa funzione viene utilizzata per ottenere il nome del simbolo in cui è stato inserito l'ordine.
    string o_symbol = myorder.Symbol();
    myorder.StoreState() Questa funzione viene utilizzata per salvare o memorizzare i dettagli correnti dell'ordine in modo che noi saremo in grado di confrontare se qualcosa è cambiato in seguito.
    myorder.StoreState();
    myorder.CheckState() Questa funzione viene utilizzata per verificare se il dettaglio dell'ordine che è stato salvato o memorizzato è cambiato.
    if (myorder.CheckState() == true)
    {
    // Our order status or details have changed
    }


    1.5 La classe CDealInfo

    La classe CDealInfo fornisce l'accesso a tutta la cronologia delle proprietà o delle informazioni dell'affare.  Una volta che abbiamo creato un oggetto di questa classe, lo utilizzeremo quindi per ottenere tutte le informazioni sulle offerte nella cronologia, in modo simile alla classe CHstoryOrderInfo.

    Quindi, la prima cosa che vogliamo fare è creare un oggetto di questa classe e chiamarlo mydeal.

    // The DealInfo Class object
    CDealInfo myinfo; 
    

    Inizieremo ottenendo le offerte totali nella cronologia

    if (HistorySelect(0,TimeCurrent()))
       {    
        // Get total deals in history
        int tot_deals = HistoryDealsTotal(); 
    

    Ora itereremo attraverso gli ordini storici totali disponibili e ottieni i dettagli di ogni ordine storico con il nostro oggetto di classe.

    ulong d_ticket; // deal ticket
    for (int j=0; j<tot_deals; j++)
        {
         d_ticket = HistoryDealGetTicket(j);
         if (d_ticket>0)  
         {
          // First thing is to now set the deal Ticket to work with by our class object 
    Metodo
    Descrizione Esempio di utilizzo
    mydeal.Ticket(ulong ticket) Questa funzione viene utilizzata per impostare il ticket dell'affare per un ulteriore utilizzo da parte dell'oggetto che abbiamo creato
    mydeal.Ticket(d_ticket);
    mydeal.Ticket()  Questa funzione viene utilizzata per ottenere il ticket dell'affare
    ulong deal_ticket = mydeal.Ticket();
    mydeal.Order() Questa funzione viene utilizzata per ottenere il ticket dell'ordine per l'ordine in cui è stato eseguito l’affare
    long deal_order_no =  mydeal.Order();
    mydeal.Time() Questa funzione viene utilizzata per ottenere l'ora in cui l'operazione è stata eseguita
    datetime d_time = mydeal.Time();
    mydeal.Type() Questa funzione viene utilizzata per ottenere il tipo di offerta, sia che si tratti di un DEAL_TYPE_SELL, ecc
    if (mydeal.Type() == DEAL_TYPE_BUY)
    {
    // This deal was executed as a buy deal type
    }
    mydeal.Entry()  Questa funzione viene utilizzata per ottenere la direzione dell'affare, indipendentemente dal fatto che sia DEAL_ENTRY_IN o DEAL_ENTRY_OUT, ecc.
    if (mydeal.Entry() == DEAL_ENTRY_IN)
    {
    // This was an IN entry deal
    }
    mydeal.Magic()  Questa viene utilizzata per ottenere l'id dell'Expert Advisor che ha eseguito l'operazione.
    long d_magic = mydeal.Magic();
    mydeal.PositionId()  Questa funzione viene utilizzata per ottenere l'identificatore di posizione univoco per la posizione in cui l'accordo faceva parte.
    long d_post_id = mydeal.PositionId();
    mydeal.Price()  Questa funzione viene utilizzata per ottenere il prezzo a cui è stata eseguita l'operazione
    double d_price = mydeal.Price();
    mydeal.Volume()  Questa funzione viene utilizzata per ottenere il volume (lotto) dell'affare
    double d_vol = mydeal.Volume();
    mydeal.Symbol()  Questa funzione viene utilizzata per ottenere il simbolo (coppia di valute) per il quale è stato effettuato l’affare
    string d_symbol = mydeal.Symbol();


    1.6 The CPositionInfo Class

    La classe CPositionInfo prevede facile accesso alle proprietà della posizione corrente. Dobbiamo creare un oggetto di questa classe per essere in grado di usarla per ottenere le proprietà di posizione.

    Creiamo un oggetto di questa classe e chiamala myposition.

    // The object of the CPositionInfo class
    CPositionInfo myposition;

    Ora useremo questo oggetto per ottenere i dettagli delle posizioni aperte. Inizieremo ottenendo le posizioni aperte totali disponibili:

    int pos_total = PositionsTotal();

    E’ ora di esaminare tutte le posizioni aperte per ottenere i loro dettagli.

    for (int j=0; j<pos_total; j++)
        {
      Metodo
       Descrizione Esempio di utilizzo
      myposition.Select(const string symbol) Questa funzione serve per selezionare il simbolo corrispondente alla posizione corrente aperta in modo che possa essere lavorato.
      if (myposition.Select(PositionGetSymbol(j)))
      {
       // symbol successfully selected, we can now work 
       // on the current open position for this symbol 
      }
      OR
      // when dealing with the current symbol/chart only
      if (myposition.Select(_Symbol)) 
      {
       // symbol successfully selected, we can now work 
       // on the current open position for this symbol 
      }
      
      myposition.Time() Questa viene utilizzata per ottenere l'ora in cui la posizione è stata aperta.
      datetime pos_time = myposition.Time();
      myposition.Type() Questa viene utilizzata per ottenere il tipo di posizione aperta.
      if (myposition.Type() == POSITION_TYPE_BUY)
      {
      // This is a buy position
      }
      myposition.Magic() Questa viene utilizzata per ottenere l'id dell'Expert Advisor che ha aperto la posizione.
      long pos_magic = myposition.Magic();
      myposition.Volume() Questa viene utilizzata per ottenere il volume (lotti) della posizione aperta.
      double pos_vol = myposition.Volume(); // Lots
      myposition.PriceOpen() Questa viene utilizzata per ottenere il prezzo a cui è stata aperta la posizione – il prezzo di apertura della posizione.
      double pos_op_price = myposition.PriceOpen();
      myposition.StopLoss() Questa viene utilizzata per ottenere il prezzo di Stop Loss per la posizione aperta.
      double pos_stoploss = myposition.StopLoss();
      myposition.TakeProfit() Questa viene utilizzata per ottenere il prezzo Take Profit per la posizione aperta.
      double pos_takeprofit = myposition.TakeProfit();
      myposition.StoreState() Questa funzione è utilizzata per memorizzare lo stato corrente della posizione.
      // stores the current state of the position
      myposition.StoreState();
      myposition.CheckState() Questa funzione viene utilizzata per verificare se lo stato della posizione aperta è cambiato.
      if (!myposition.CheckState())
      {
        // position status has not changed yet
      }
       myposition.Symbol() Questa funzione viene utilizzata per ottenere il nome del simbolo in cui si trovava la posizione aperta.
      string pos_symbol = myposition.Symbol();


      1.7 The СTrade Class

      La classe CTrade fornisce un facile accesso alle operazioni di trade in MQL5. Per usare questa classe, dobbiamo creare un oggetto della classe e poi utilizzarla per eseguire le operazioni commerciali necessarie.

      Creeremo un oggetto di questa classe e la chiameremo mytrade:

      //An object of the CTrade class
      CTrade mytrade;

      Il primo passo è impostare la maggior parte dei parametri che l'oggetto utilizzerà nell'effettuare operazioni di trading.

       Metodo Descrizione
      Esempio di utilizzo
      mytrade.SetExpertMagicNumber(ulong magic) Questa funzione viene utilizzata per impostare l'ID esperto (numero magico) per cui la classe utilizzerà operazioni di trading.
      ulong Magic_No=12345;
      mytrade.SetExpertMagicNumber(Magic_No);
      mytrade.SetDeviationInPoints(ulong deviation) Questa funzione viene utilizzata anche per impostare il valore di deviazione (in punti) da utilizzare quando si piazza un trade.
      ulong Deviation=20;
      mytrade.SetDeviationInPoints(Deviation); 
      
      mytrade.OrderOpen(const string symbol,
      ENUM_ORDER_TYPE
      order_type,double volume,

      double
      limit_price,double price,double sl,
      double
      tp,ENUM_ORDER_TYPE_TIME type_time,

      datetime
      expiration,const string comment="")
      Questa funzione viene utilizzata per effettuare un ordine in sospeso. Per  utilizzare questa funzione, i parametri devono prima essere preparati e poi passati a questa funzione.
      // define the input parameters
      double Lots = 0.1;
      double SL = 0;
      double TP = 0;
      // latest Bid price using CSymbolInfo class object
      double Oprice = mysymbol.Bid()-_Point*550;
      // place (BuyStop) pending order
      mytrade.OrderOpen(_Symbol,ORDER_TYPE_SELLSTOP,Lots,0.0,Oprice,
                        SL,TP,ORDER_TIME_GTC,0);
      mytrade.OrderModify(ulong ticket,double price,
      double
      sl,double tp,
      ENUM_ORDER_TYPE_TIME type_time,datetime expiration)
      Questa la funzione viene utilizzata per modificare un ordine in sospeso esistente.
      // Select total orders in history and get total pending orders 
      // (as shown within the COrderInfo class section). 
      // Use the CSymbolInfo class object to get the current ASK/BID price
      int Stoploss = 400;
      int Takeprofit = 550;
      for(int j=0; j<OrdersTotal(); j++)
      {
        ulong o_ticket = OrderGetTicket(j);
        if(o_ticket != 0)
        {
         // Stoploss must have been defined
         double SL = mysymbol.Bid() + Stoploss*_Point;   
         // Takeprofit must have been defined  
         double TP = mysymbol.Bid() - Takeprofit*_Point; 
         // lastest ask price using CSymbolInfo class object
         double Oprice = mysymbol.Bid();                 
         // modify pending BuyStop order
         mytrade.OrderModify(o_ticket,Oprice,SL,TP,ORDER_TIME_GTC,0);
        }
      }
      mytrade.OrderDelete(ulong ticket) Questa funzione viene utilizzata per eliminare un ordine in sospeso.
      // Select total orders in history and get total pending orders
      // (as shown within the COrderInfo class section). 
      
      int o_total=OrdersTotal();
      for(int j=o_total-1; j>=0; j--)
      {
         ulong o_ticket = OrderGetTicket(j);
         if(o_ticket != 0)
         {
          // delete the pending Sell Stop order
          mytrade.OrderDelete(o_ticket);
         }
      }
      mytrade.PositionOpen(const  string symbol,ENUM_ORDER_TYPE order_type,double volume,double price,double sl,double tp,const string comment="") Questa la funzione viene utilizzata per aprire una posizione BUY o SELL. Per utilizzare questa funzione, tutti i parametri richiesti devono prima essere preparati e poi passati a questa funzione.
      // define the input parameters and use the CSymbolInfo class
      // object to get the current ASK/BID price
      double Lots = 0.1;
      // Stoploss must have been defined 
      double SL = mysymbol.Ask() – Stoploss*_Point;   
      //Takeprofit must have been defined 
      double TP = mysymbol.Ask() + Takeprofit*_Point; 
      // latest ask price using CSymbolInfo class object
      double Oprice = mysymbol.Ask();
      // open a buy trade
      mytrade.PositionOpen(_Symbol,ORDER_TYPE_BUY,Lots,
                           Oprice,SL,TP,"Test Buy");
      mytrade.PositionModify(const string symbol,
      double
      sl,double tp)
      Questa funzione viene utilizzata per modificare lo StopLoss e/o TakeProfit per una posizione esistente aperta. Per utilizzare questa funzione, dobbiamo prima di tutto selezionare la posizione da modificare utilizzando l'oggetto classe CPositionInfo, utilizzare l'oggetto classe CSymbolInfo per ottenere il prezzo BID/ASK corrente.
      if (myposition.Select(_Symbol))
      {
        int newStoploss = 250;
        int newTakeprofit = 500;
        double SL = mysymbol.Ask() – newStoploss*_Point;    
        double TP = mysymbol.Ask() + newTakeprofit*_Point;  
        //modify the open position for this symbol
       mytrade.PositionModify(_Symbol,SL,TP);
      }
      mytrade.PositionClose(const string symbol,
      ulong
      deviation=ULONG_MAX)
      Questa funzione viene utilizzata per chiudere una posizione aperta esistente.
      if (myposition.Select(_Symbol))
      {
       //close the open position for this symbol
       mytrade.PositionClose(_Symbol);  
      }
      
      mytrade.Buy(double volume,const string symbol=NULL,double price=0.0,double sl=0.0,double tp=0.0,const string comment="")   Questa funzione viene utilizzata per aprire un'operazione di trading. Si consiglia di impostare il volume (o lotti ) da fare trading quando si utilizza questa funzione. Mentre il tp (take profit) e il sl (stop loss) possono essere impostati successivamente modificando la posizione aperta, utilizza il prezzo corrente Askper aprire il trade.
      double Lots = 0.1;
      // Stoploss must have been defined 
      double SL = mysymbol.Ask() – Stoploss*_Point; 
      //Takeprofit must have been defined
      double TP = mysymbol.Ask() +Takeprofit*_Point;
      // latest ask price using CSymbolInfo class object
      double Oprice = mysymbol.Ask();
      // open a buy trade
      mytrade.Buy(Lots,NULL,Oprice,SL,TP,“Buy Trade”);
      
      //OR
      mytrade.Buy(Lots,NULL,0.0,0.0,0.0,“Buy Trade”);
      // modify position later
      mytrade.Sell(double volume,const string symbol=NULL,double price=0.0,double sl=0.0,double tp=0.0,const string comment="") Questa funzione viene utilizzata per aprire un'operazione di Vendita. Si consiglia di impostare il volume (o lotti ) da fare trading quando si utilizza questa funzione. Mentre il tp (take profit) e il sl  (stop loss) possono essere impostati successivamente modificando la posizione aperta, utilizza il prezzo corrente Prezzo di offerta per aprire il trade. 
      double Lots = 0.1;
      // Stoploss must have been defined 
      double SL = mysymbol.Bid() + Stoploss*_Point;
      //Takeprofit must have been defined
      double TP = mysymbol.Bid() - Takeprofit*_Point; 
      // latest bid price using CSymbolInfo class object
      double Oprice = mysymbol.Bid();
      // open a Sell trade
      mytrade.Sell(Lots,NULL,Oprice,SL,TP,“Sell Trade”); 
      
      //OR
      mytrade.Sell(Lots,NULL,0.0,0.0,0.0,“Sell Trade”); 
      //(modify position later)
      mytrade.BuyStop(double volume,double price,const string symbol=NULL,double sl=0.0,double tp=0.0,
      ENUM_ORDER_TYPE_TIME type_time=ORDER_TIME_GTC,datetime expiration=0,const string comment="")
       Questa funzione viene utilizzata per inserire un ordine BuyStop in sospeso. Il tempo predefinito del tipo di ordine è ORDER_TIME_GTC e la scadenza è 0. Non c'è bisogno di specificare queste due variabili se hai lo stesso tipo di ordine di tempo in mente.
       double Lot = 0.1;
      //Buy price = bar 1 High + 2 pip + spread
       int sprd=mysymbol.Spread();
       double bprice =mrate[1].high + 2*_Point + sprd*_Point;
      //--- Buy price
       double mprice=NormalizeDouble(bprice,_Digits); 
      //--- Stop Loss
       double stloss = NormalizeDouble(bprice - STP*_Point,_Digits);
      //--- Take Profit
       double tprofit = NormalizeDouble(bprice+ TKP*_Point,_Digits);
      //--- open BuyStop order
       mytrade.BuyStop(Lot,mprice,_Symbol,stloss,tprofit); 
      mytrade.SellStop(double volume,double price,const string symbol=NULL,double sl=0.0,double tp=0.0, ENUM_ORDER_TYPE_TIME type_time=ORDER_TIME_GTC,datetime expiration=0,const string  comment="") Questa viene utilizzata per inserire un ordine SellStop in sospeso con i parametri impostati. L'ora del tipo di Ordine predefinito è ORDER_TIME_GTC e la scadenza è 0. Non è necessario specificare queste due variabili se si ha in mente lo stesso tipo di ordine temporale. 
       double Lot = 0.1;
      //--- Sell price = bar 1 Low - 2 pip 
      //--- MqlRates mrate already declared
       double sprice=mrate[1].low-2*_Point;
      //--- SellStop price
       double slprice=NormalizeDouble(sprice,_Digits);
      //--- Stop Loss
       double ssloss=NormalizeDouble(sprice+STP*_Point,_Digits);
      //--- Take Profit
       double stprofit=NormalizeDouble(sprice-TKP*_Point,_Digits);
      //--- Open SellStop Order
       mytrade.SellStop(Lot,slprice,_Symbol,ssloss,stprofit);
      
      mytrade.BuyLimit(double volume,double price,const string symbol=NULL,double sl=0.0,double tp=0.0, ENUM_ORDER_TYPE_TIME type_time=ORDER_TIME_GTC,datetime expiration=0,const string  comment="") Questa funzione viene utilizzata per effettuare un ordine BuyLimit con i parametri impostati. 
      Usage:
      //--- Buy price = bar 1 Open  - 5 pip + spread
      double Lot = 0.1;
      int sprd=mysymbol.Spread();
      //--- symbol spread
      double bprice = mrate[1].open - 5*_Point + sprd*_Point;
      //--- MqlRates mrate already declared
      double mprice=NormalizeDouble(bprice,_Digits);
      //--- BuyLimit price
      //--- place buyLimit order, modify stoploss and takeprofit later
      mytrade.BuyLimit(Lot,mprice,_Symbol); 
      mytrade.SellLimit (double volume,double price,const string symbol=NULL,double sl=0.0,double tp=0.0, ENUM_ORDER_TYPE_TIME type_time=ORDER_TIME_GTC,datetime expiration=0,const string comment="") Questa funzione viene utilizzata per effettuare un ordine Sell Limit con i parametri impostati. 
      //--- Sell Limit price = bar 1 Open  + 5 pip
      double Lot = 0.1;
      //--- MqlRates mrate already declared
      double sprice = mrate[1].open + 5*_Point;
      //--- SellLimit
      double slprice=NormalizeDouble(sprice,_Digits);
      //place SellLimit order, modify stoploss and takeprofit later
      mytrade.SellLimit(Lot,slprice,_Symbol);

          FUNZIONI DI RISULTATO DI TRADING

         
      mytrade.ResultRetcode() Questa funzione viene utilizzata per ottenere il codice risultato per un'operazione di trading.
      // a trade operation has just been carried out
      int return_code = mytrade.ResultRetcode();
      mytrade.ResultRetcodeDescription() Questa funzione viene utilizzata per ottenere la descrizione completa o l'interpretazione del codice restituito di un'operazione di trading.
      string ret_message =  ResultRetcodeDescription();
      // display it
      Alert("Error code - " , mytrade.ResultRetcode() ,
            "Error message - ", ret_message);
      mytrade.ResultDeal() Questa funzione viene utilizzata per ottenere il ticket dell'operazione per la posizione aperta.
      long dl_ticket = mytrade.ResultDeal();
      mytrade.ResultOrder() Questa funzione viene utilizzata per ottenere il ticket dell'ordine per la posizione aperta.
      long o_ticket = mytrade.ResultOrder();
      mytrade.ResultVolume() Questa funzione viene utilizzata per ottenere il volume (Lotti) dell'ordine per la posizione aperta.
      double o_volume = mytrade.ResultVolume();
      mytrade.ResultPrice() Questa viene utilizzata per ottenere il prezzo dell'operazione per la posizione aperta.
      double r_price = mytrade.ResultPrice();
      mytrade.ResultBid() Questa funzione viene utilizzata per ottenere il prezzo BID di mercato corrente (prezzo di riquotazione).
      double rq_bid = mytrade.ResultBid;
      mytrade.ResultAsk() Questa funzione viene utilizzata per ottenere il prezzo ASK di mercato corrente (prezzo di riquotazione).
      double rq_ask = mytrade.ResultAsk;
      mytrade.PrintRequest() / mytrade.PrintResult()  Queste due funzioni possono essere utilizzate per stampare, nella scheda Journal, la richiesta dei parametri di trading e i parametri del risultato rispettivamente.
      // after a trade operation
      // prints the trade request parameters
      mytrade.PrintRequest(); 
      //prints the trade results
      mytrade.PrintResult();  

       FUNZIONI DI RICHIESTA DI TRADING

         
       mytrade.RequestAction() Questa funzione viene utilizzata per ottenere il tipo di operazione di trading per l'ultima richiesta di trading appena inviata.
      //determine the Trade operation type for the last Trade request
      if (mytrade.RequestAction() == TRADE_ACTION_DEAL)
      {
        // this is a market order for an immediate execution
      }
      else if (mytrade.RequestAction() == TRADE_ACTION_PENDING)
      {
        // this is a pending order.
      }  
       mytrade.RequestMagic() Questa viene utilizzata per ottenere il numero Expert Magic che è stato utilizzato nell'ultima richiesta.
      ulong mag_no = mytrade. RequestMagic();
       mytrade.RequestOrder()
       Questa viene utilizzata per ottenere il ticket dell'ordine utilizzato nell'ultima richiesta. Ciò si riferisce principalmente alla modifica degli ordini in sospeso.
      ulong po_ticket =  mytrade.RequestOrder();
      mytrade.RequestSymbol() Questa viene utilizzata per ottenere il simbolo o la coppia di valute che è stata utilizzata nell’ultima richiesta.
      string symb = mytrade.RequestSymbol(); 
      mytrade.RequestVolume() Questa viene utilizzata per ottenere il volume degli scambi (in lotti) collocati nell'ultima richiesta. 
      double Lot = mytrade.RequestVolume();  
      mytrade.RequestPrice() Questa funzione viene utilizzata per ottenere il prezzo dell'ordine utilizzato  nell'ultima richiesta.
      double oprice = mytrade.RequestPrice();   
      mytrade.RequestStopLimit() Questa viene utilizzata per ottenere lo Stop Loss  prezzo utilizzato nell'ultima richiesta.
      double limitprice = mytrade.RequestStopLimit(); 
      mytrade.RequestSL() Questa viene utilizzata per ottenere lo Stop Loss  prezzo utilizzato nell'ultima richiesta.
      double sloss = mytrade.RequestSL();  
      mytrade.RequestTP() Questa viene utilizzata per ottenere il prezzo Take Profit utilizzato nell'ultima richiesta.
      double tprofit = mytrade.RequestTP();   
      mytrade.RequestDeviation() Questa funzione viene utilizzata per ottenere la Deviazione utilizzata  nell'ultima richiesta.
      ulong dev = mytrade.RequestDeviation();  
      mytrade.RequestType() Questa funzione viene utilizzata per ottenere il tipo di ordine che è stato effettuato nell'ultima richiesta.
      if (mytrade.RequestType() == ORDER_TYPE_BUY)
       {
        // market order Buy was placed in the last request.
      mytrade.RequestTypeDescription() Questa funzione viene utilizzata per ottenere la descrizione del tipo di ordine effettuato nell'ultima richiesta.
      Print("The type of order placed in the last request is :",
            mytrade.RequestTypeDescription());  
      mytrade.RequestActionDescription() Questa funzione viene utilizzata per ottenere la descrizione dell'azione di richiesta utilizzata nell'ultima richiesta.
      Print("The request action used in the last request is :", 
            mytrade.RequestTypeDescription());
      mytrade.RequestTypeFillingDescription() Questa funzione viene utilizzata per ottenere il tipo di politica di riempimento dell'ordine utilizzata nell'ultima richiesta.
      Print("The type of order filling policy used",
            " in the last request is :",
            RequestTypeFillingDescription()); 
       

      Le funzioni Trade Class Request sono molto utili per identificare gli errori associati all'inoltro degli ordini. Ci sono momenti in cui riceviamo alcuni messaggi di errore quando effettuiamo un ordine e diventa un po' confuso quando non possiamo identificare immediatamente cosa è andato storto. Utilizzando le funzioni di richiesta Trade Class, possiamo essere in grado di identificare cosa abbiamo sbagliato stampando alcuni dei parametri di richiesta che sono stati inviati al server di trading. Un esempio di tale utilizzo sarà simile al codice seguente:

       //--- open Buy position and check the result
               if(mytrade.Buy(Lot,_Symbol,mprice,stloss,tprofit))
               //if(mytrade.PositionOpen(_Symbol,ORDER_TYPE_BUY,Lot,mprice,stloss,tprofit)) 
                 { //--- Request is completed or order placed           
                   Alert("A Buy order at price:", mytrade.ResultPrice() , ", vol:",mytrade.ResultVolume(),
                        " has been successfully placed with deal Ticket#:",mytrade.ResultDeal(),"!!");
                  mytrade.PrintResult();
                 }
               else
                 {
                  Alert("The Buy order request at vol:",mytrade.RequestVolume(), ", sl:", mytrade.RequestSL(),
                       ", tp:",mytrade.RequestTP(), ", price:", mytrade.RequestPrice(),
                       " could not be completed -error:",mytrade.ResultRetcodeDescription());
                  mytrade.PrintRequest();
                  return;
                 }

      Nel codice sopra, abbiamo cercato di identificare alcuni dei parametri inviati nella nostra richiesta in caso di errore. Ad esempio, se non abbiamo specificato il prezzo di Stop Loss corretto, potremmo ottenere un errore di Stop Loss non valido e stampando il valore dello Stop Loss utilizzando mytrade.RequestSL(), saremo in grado di sapere qual è il problema con il nostro prezzo Stop Loss specificato.

      Avendo preso tempo per mostrare come ciascuna delle classi può essere utilizzata, ora è il momento di mettere in pratica alcune delle funzionalità che abbiamo descritto.

      Tieni presente che tutte le funzionalità che utilizzeremo nell'Expert Advisor sono già state descritte sopra, sarà una buona idea fare sempre riferimento alle descrizioni una volta che si vede una qualsiasi delle funzioni nei codici che andremo a scrivere. 


      2. Usando le funzionalità delle Classi di Trading

      Per dimostrare come utilizzare le funzionalità di queste classi di trading, scriveremo un Expert Advisor che svolgerà le seguenti mansioni.

      • Questo verificherà una condizione di Buy o Sell e, se la condizione è soddisfatta, effettuerà un ordine di Buy o Sell a seconda della condizione soddisfatta.
      • Se è stata aperta una posizione e il trade continua ad andare nella nostra direzione, modificheremo il take profit o stop loss della posizione. Tuttavia, se il trade sta andando contro di noi e il nostro obiettivo di profitto non è stato raggiunto, noi chiuderemo la posizione.
      • Il nostro EA verrà utilizzato per fare trading sul grafico giornaliero su uno delle seguenti valute: GBPUSD, AUDUSD, EURUSD, ecc.

      2.1 Scrivere l'Expert Advisor

      Per iniziare, inizia un nuovo documento MQL5 e seleziona l’Expert Advisor (modello) e fai clic sul pulsante Avanti:

         Avvio di un nuovo documento MQL5


      Figure 1. Avvio di un nuovo documento MQL5

      Digita il nome dell'Expert Advisor e fai clic sul pulsante Fine. Definiremo i parametri di input manualmente in seguito.

      Dai un nome al nuovo documento

      Figure 2. Nominare l’Expert Advisor

      Il nuovo documento creato dovrebbe sembrare simile a quello sotto.

      Lo scheletro del codice dell’expert

      Subito dopo la versione #property della riga, includeremo tutte le classi di Trading che andremo ad utilizzare.

      //+------------------------------------------------------------------+
      //|  Include ALL classes that will be used                           |
      //+------------------------------------------------------------------+
      //--- The Trade Class
      #include <Trade\Trade.mqh>
      //--- The PositionInfo Class
      #include <Trade\PositionInfo.mqh>
      //--- The AccountInfo Class
      #include <Trade\AccountInfo.mqh>
      //--- The SymbolInfo Class
      #include <Trade\SymbolInfo.mqh>
      

      Successivamente definiremo i nostri parametri di input:

      //+------------------------------------------------------------------+
      //|  INPUT PARAMETERS                                                |
      //+------------------------------------------------------------------+
      input int      StopLoss=100;     // Stop Loss
      input int      TakeProfit=240;   // Take Profit
      input int      ADX_Period=15;    // ADX Period
      input int      MA_Period=15;     // Moving Average Period
      input ulong    EA_Magic=99977;   // EA Magic Number
      input double   Adx_Min=24.0;     // Minimum ADX Value
      input double   Lot=0.1;          // Lots to Trade
      input ulong    dev=100;          // Deviation 
      input long     Trail_point=32;   // Points to increase TP/SL
      input int      Min_Bars = 20;    // Minimum bars required for Expert Advisor to trade
      input double   TradePct = 25;    // Percentage of Account Free Margin to trade

      Specifichiamo anche altri parametri che verranno utilizzati in questo codice Expert Advisor:

      //+------------------------------------------------------------------+
      //|  OTHER USEFUL PARAMETERS                                         |
      //+------------------------------------------------------------------+
      int adxHandle;                     // handle for our ADX indicator
      int maHandle;                    // handle for our Moving Average indicator
      double plsDI[],minDI[],adxVal[]; // Dynamic arrays to hold the values of +DI, -DI and ADX values for each bars
      double maVal[];                  // Dynamic array to hold the values of Moving Average for each bars
      double p_close;                    // Variable to store the close value of a bar
      int STP, TKP;                   // To be used for Stop Loss, Take Profit 
      double TPC;                        // To be used for Trade percent

      Creiamo ora un oggetto di ciascuna delle classi che abbiamo incluso:

      //+------------------------------------------------------------------+
      //|  CREATE CLASS OBJECTS                                            |
      //+------------------------------------------------------------------+
      //--- The Trade Class Object
      CTrade mytrade;
      //--- The PositionInfo Class Object
      CPositionInfo myposition;
      //--- The AccountInfo Class Object
      CAccountInfo myaccount;
      //--- The SymbolInfo Class Object
      CSymbolInfo mysymbol;

      La prossima cosa che vogliamo fare ora, è definire alcune funzioni che useremo per rendere il nostro lavoro molto facile.

      Una volta definite queste funzioni, le chiameremo all'interno delle sezioni necessarie nelle funzioni OnInit() e OnTick().

      2.1.1 La funzione checkTrading

      Questa funzione sarà utilizzata per eseguire tutti i controlli iniziali per vedere se il nostro Expert Advisor può fare trading o no. Se questa funzione restituisce true, il nostro EA procederà, altrimenti l'EA non farà eseguire alcun trade.

      //+------------------------------------------------------------------+
      //|  Checks if our Expert Advisor can go ahead and perform trading   |
      //+------------------------------------------------------------------+
      bool checkTrading()
      {
        bool can_trade = false;
        // check if terminal is syncronized with server, etc
        if (myaccount.TradeAllowed() && myaccount.TradeExpert() && mysymbol.IsSynchronized())
        {
          // do we have enough bars?
          int mbars = Bars(_Symbol,_Period);
          if(mbars >Min_Bars)
          {
            can_trade = true;
          }
        }
        return(can_trade);
      }

      Abbiamo dichiarato un tipo di dati bool can_trade e renderlo falso. Abbiamo usato l’oggetto della classe CAccountInfo per verificare se il trade è consentito e anche se gli Expert Advisor sono autorizzati a fare trading su questo conto. Usiamo anche un oggetto della classe CSymbolInfo per verificare se il terminale è sincronizzato con il server del trade.

      Una volta che queste tre condizioni sono soddisfatte, controlliamo se il totale del numero di barre correnti è maggiore delle barre minime richieste per far sì che il nostro EA faccia trading. Se questa funzione restituisce true, il nostro EA eseguirà attività di trading, in caso contrario, il nostro EA non si impegnerà in alcuna attività di trading fino a quando le condizioni in questa funzione sono soddisfatte.

      Come avete visto, abbiamo deciso di includere tutte le necessarie attività di controllo di trading in questa funzione, utilizzando gli oggetti necessari delle librerie di classi di trading standard.

      2.1.2 La funzione ConfirmMargin

      //+------------------------------------------------------------------+
      //|  Confirms if margin is enough to open an order
      //+------------------------------------------------------------------+
      bool ConfirmMargin(ENUM_ORDER_TYPE otype,double price)
        {
         bool confirm = false;
         double lot_price = myaccount.MarginCheck(_Symbol,otype,Lot,price); // Lot price/ Margin    
         double act_f_mag = myaccount.FreeMargin();                        // Account free margin 
         // Check if margin required is okay based on setting
         if(MathFloor(act_f_mag*TPC)>MathFloor(lot_price))
           {
            confirm =true;
           }
          return(confirm);
        }
      

      Usiamo l'oggetto della classe CAccountInfo per confermare se c'è un margine sufficiente per piazzare un'operazione basata sull'impostazione che utilizzeremo solo una certa percentuale del nostro account gratuitamente margine per effettuare un ordine.

      Se la percentuale richiesta del margine libero del conto è maggiore del margine richiesto per l'ordine, allora questa funzione restituisce true, altrimenti restituisce false.  Con questo, vogliamo solo effettuare un ordine se la funzione restituisce true. Questa funzione accetta il tipo di ordine come un parametro di input.

      2.1.3 La funzione checkBuy

      //+------------------------------------------------------------------+
      //|  Checks for a Buy trade Condition                                |
      //+------------------------------------------------------------------+
      bool checkBuy()
      {
        bool dobuy = false;
        if ((maVal[0]>maVal[1]) && (maVal[1]>maVal[2]) &&(p_close > maVal[1]))
        {
          // MA increases upwards and previous price closed above MA
          if ((adxVal[1]>Adx_Min)&& (plsDI[1]>minDI[1]))
          {
            // ADX is greater than minimum and +DI is greater tha -DI for ADX
            dobuy = true;
          }
        }
        return(dobuy);
      }

      Abbiamo deciso di concludere le condizioni per l'apertura di un trade di acquisto in questa funzione. Non abbiamo usato nessuno delle funzionalità degli oggetti di classe qui. Stiamo verificando la condizione in cui i valori dell'indicatore della media mobile sono in aumento e il prezzo di chiusura della barra precedente è superiore al valore della media mobile in quel punto.

      Vogliamo anche una situazione in cui il valore dell'indicatore ADX è maggiore del minimo richiesto impostato nei parametri di ingresso e il valore di DI positivo dell’'indicatore ADX è maggiore del valore DI negativo. Una volta che queste condizioni vengono soddisfatte, allora vorremo che il nostro EA apra un ordine di ACQUISTO.

      2.1.4 La funzione checkSell

      //+------------------------------------------------------------------+
      //|  Checks for a Sell trade Condition                               |
      //+------------------------------------------------------------------+
      bool checkSell()
      {
        bool dosell = false;
        if ((maVal[0]<maVal[1]) && (maVal[1]<maVal[2]) &&(p_close < maVal[1]))
        {
          // MA decreases downwards and previuos price closed below MA
          if ((adxVal[1]>Adx_Min)&& (minDI[1]>plsDI[1]))
          {
            // ADX is greater than minimum and -DI is greater tha +DI for ADX
            dosell = true;
          }
        }
        return(dosell);
      } 

      Questa funzione verifica esattamente l'opposto della funzione CheckBuy. Inoltre non abbiamo usato nessuna classe di oggetti in questa funzione. Questa funzione verifica una condizione in cui i valori dell'indicatore della media mobile stanno diminuendo al ribasso e il prezzo di chiusura della barra precedente è inferiore al valore della media mobile in quel punto.

      Noi vogliamo anche una situazione in cui il valore dell'indicatore ADX è maggiore del minimo richiesto impostato nei parametri di ingresso e il valore di DI negativo dell’'indicatore ADX è maggiore del valore DI positivo. Una volta che queste condizioni vengono soddisfatte, allora vorremo che il nostro EA apra un ordine di VENDITA.

      2.1.5 La funzione checkClosePos
      //+------------------------------------------------------------------+
      //|  Checks if an Open position can be closed                        |
      //+------------------------------------------------------------------+
      bool checkClosePos(string ptype, double Closeprice)
      {
         bool mark = false;
         if (ptype=="BUY")
         {
            // Can we close this position
           if (Closeprice < maVal[1]) // Previous price close below MA
            {
               mark = true;
            }
         }
         if (ptype=="SELL")
         {
            // Can we close this position
            if (Closeprice > maVal[1]) // Previous price close above MA
            {
               mark = true;
            }
         }
         return(mark);
      }

      Questa funzione viene utilizzata per verificare se l'attuale posizione aperta può essere chiusa. Questa funzione viene utilizzata per monitorare se il prezzo di chiusura della barra precedente è superiore o inferiore al valore di dell'indicatore della Media Mobile in quel punto (a seconda della direzione del trade).

      Se una qualsiasi delle condizioni è soddisfatta, questa funzione restituisce true e quindi ci aspetteremo che il nostro EA chiuda la posizione. Questa funzione ha due parametri di input, il tipo di ordine (questa volta il nome – ACQUISTA o VENDI) e il prezzo di chiusura della barra precedente.

      2.1.6 La funzione ClosePosition

      //+------------------------------------------------------------------+
      //| Checks and closes an open position                               |
      //+------------------------------------------------------------------+
      bool ClosePosition(string ptype,double clp)
        {
         bool marker=false;
           
            if(myposition.Select(_Symbol)==true)
              {
               if(myposition.Magic()==EA_Magic && myposition.Symbol()==_Symbol)
                 {
                  //--- Check if we can close this position
                  if(checkClosePos(ptype,clp)==true)
                    {
                     //--- close this position and check if we close position successfully?
                     if(mytrade.PositionClose(_Symbol)) //--- Request successfully completed 
                       {
                        Alert("An opened position has been successfully closed!!");
                        marker=true;
                       }
                     else
                       {
                        Alert("The position close request could not be completed - error: ",
                             mytrade.ResultRetcodeDescription());
                       }
                    }
                 }
              }
            return(marker);
           }

      Questa è la funzione che utilizza effettivamente la funzione di cui sopra (checkclosepos). Fa uso degli oggetti delle classi CPositionInfo e CTrade. Questa funzione utilizza l'oggetto di la classe CPositionInfo per verificare le posizioni aperte disponibili per la posizione che è stata aperta dal nostro EA e per il simbolo corrente. Se viene trovata una posizione, controlla se può essere chiuso usando la funzione checkclosepos.

      Se la funzione checkclosepos restituisce true, questa funzione utilizza l'oggetto della classe CTrade per chiudere la posizione e visualizzare i risultati per l’operazione di chiusura della posizione. Se la posizione è stata chiusa con successo, questa funzione restituisce true, altrimenti restituisce false.

      La funzione accetta due parametri di input (il nome della posizione, ACQUISTA o VENDI e il prezzo di chiusura della barra precedente). Questi parametri sono stati effettivamente passati alla funzione checkclosepos che li utilizza.

      2.1.7 La funzione CheckModify

      //+------------------------------------------------------------------+
      //|  Checks if we can modify an open position                        |
      //+------------------------------------------------------------------+
      bool CheckModify(string otype,double cprc)
      {
         bool check=false;
         if (otype=="BUY")
         {
            if ((maVal[2]<maVal[1]) && (maVal[1]<maVal[0]) && (cprc>maVal[1]) && (adxVal[1]>Adx_Min))
            {
               check=true;
            }
         }
         else if (otype=="SELL")
         {
            if ((maVal[2]>maVal[1]) && (maVal[1]>maVal[0]) && (cprc<maVal[1]) && (adxVal[1]>Adx_Min))
            {
               check=true;
            }
         }
         return(check);
      } 

      Questa funzione viene utilizzata per verificare una condizione che conferma se una posizione aperta può essere modificata o meno. Questo utilizza il nome del tipo di ordine e il prezzo di chiusura della barra precedente come parametri di input.

      Ciò che fa questa funzione è controllare se la Media Mobile è ancora in aumento verso l'alto e il prezzo di chiusura della barra precedente è ancora superiore al valore della Media mobile in quel punto e il valore di ADX è anche maggiore del minimo richiesto (per una posizione ACQUISTA) mentre controlla se la Media mobile è ancora in diminuzione al ribasso e il prezzo di chiusura della barra precedente è più basso del valore della media mobile in quel punto (per una posizione SELL). Dipende dal tipo di posizione che abbiamo, se una qualsiasi delle condizioni viene soddisfatta, l'EA prenderà in considerazione la modifica della posizione.

      La funzione accetta due parametri di input (il nome della posizione, ACQUISTA o VENDI, e il prezzo di chiusura della barra precedente).

      2.1.8 La funzione Modifica

      //+------------------------------------------------------------------+
      //| Modifies an open position                                        |
      //+------------------------------------------------------------------+
         void Modify(string ptype,double stpl,double tkpf)
           {
             //--- New Stop Loss, new Take profit, Bid price, Ask Price
            double ntp,nsl,pbid,pask;                  
            long tsp=Trail_point;
             //--- adjust for 5 & 3 digit prices
            if(_Digits==5 || _Digits==3) tsp=tsp*10;   
             //--- Stops Level
            long stplevel= mysymbol.StopsLevel();      
             //--- Trail point must not be less than stops level
            if(tsp<stplevel) tsp=stplevel;
            if(ptype=="BUY")
              {
                //--- current bid price
               pbid=mysymbol.Bid();           
               if(tkpf-pbid<=stplevel*_Point)
                 {
                  //--- distance to takeprofit less or equal to Stops level? increase takeprofit
                  ntp = pbid + tsp*_Point;
                  nsl = pbid - tsp*_Point;
                 }
               else
                 {
                  //--- distance to takeprofit higher than Stops level? dont touch takeprofit
                  ntp = tkpf;
                  nsl = pbid - tsp*_Point;
                 }
              }
            else //--- this is SELL
              {
                //--- current ask price
               pask=mysymbol.Ask();            
               if(pask-tkpf<=stplevel*_Point)
                 {
                  ntp = pask - tsp*_Point;
                  nsl = pask + tsp*_Point;
                 }
               else
                 {
                  ntp = tkpf;
                  nsl = pask + tsp*_Point;
                 }
              }
            //--- modify and check result
            if(mytrade.PositionModify(_Symbol,nsl,ntp))  
              {
                //--- Request successfully completed    
               Alert("An opened position has been successfully modified!!");
               return;
              }
            else
              {
               Alert("The position modify request could not be completed - error: ",
                     mytrade.ResultRetcodeDescription());
               return;
              }
      
           }

       Questa funzione utilizza la funzione di cui sopra (checkmodify) per fare il suo lavoro. Usa gli oggetti delle classi CSymbolInfo e CTrade. Prima di tutto, abbiamo dichiarato quattro doppi tipi di dati per mantenere il nuovo take profit, stop loss, prezzo bid e prezzo ask. Allora abbiamo dichiarato un nuovo tipo di dati long tsp per mantenere il valore Trail_point impostato sulla sezione parametri di input.

      Il valore del trail point (tsp) è stato quindi aggiustato per 5 e prezzi a 3 cifre. Abbiamo quindi utilizzato l'oggetto CSymbolInfo per ottenere il livello degli stop e assicurati che il trail point che vogliamo aggiungere non sia inferiore al livello di stop richiesto. Se è inferiore al livello di stop, utilizzeremo il valore del livello di stop.

      A seconda del tipo di posizione, usiamo l'oggetto della classe CSymbolInfo per ottenere il prezzo BID o ASK corrente come può essere il caso. Se la differenza tra l'attuale prezzo BID o ASK e il prezzo iniziale di take profit è inferiore o uguale al livello di stop, decidiamo di regoliamo sia lo stop loss che il take profit, altrimenti regoliamo solo il valore di stop loss.

      Usiamo quindi la classe oggetto CTrade per modificare lo Stop loss e il take profit per la posizione. Basato sul codice di ritorno del risultato di trading, un messaggio di successo o fallimento.

      Abbiamo finito di definirne alcune funzioni definite dall'utente che semplificheranno il nostro lavoro. Andiamo ora avanti alla sezione dei codici EA.

      2.1.9 La sezione OnInit

      //--- set the symbol name for our SymbolInfo Object
         mysymbol.Name(_Symbol);
      // Set Expert Advisor Magic No using our Trade Class Object
         mytrade.SetExpertMagicNumber(EA_Magic);
      // Set Maximum Deviation using our Trade class object
         mytrade.SetDeviationInPoints(dev);
      //--- Get handle for ADX indicator
         adxHandle=iADX(NULL,0,ADX_Period);
      //--- Get the handle for Moving Average indicator
         maHandle=iMA(_Symbol,Period(),MA_Period,0,MODE_EMA,PRICE_CLOSE);
      //--- What if handle returns Invalid Handle
         if(adxHandle<0 || maHandle<0)
           {
            Alert("Error Creating Handles for MA, ADX indicators - error: ",GetLastError(),"!!");
            return(1);
           }
         STP = StopLoss;
         TKP = TakeProfit;
      //--- Let us handle brokers that offers 5 or 3 digit prices instead of 4
         if(_Digits==5 || _Digits==3)
           {
            STP = STP*10;
            TKP = TKP*10;
           }
         
      //--- Set trade percent
          TPC = TradePct;
          TPC = TPC/100;
      //---

      Decidiamo di impostare il simbolo corrente per la classe oggetto CSymbolInfo. Impostiamo anche il numero magico dell'Expert Advisor e la deviazione (in punti) utilizzando la classe oggetto CTrade. Dopodiché, decidiamo di ottenere gli handler per i nostri indicatori e mostriamo un errore se non siamo riusciti ad ottenere gli handler.

      Successivamente, decidiamo di regolare lo stop loss e il take profit per prezzi a 3 e 5 cifre e convertiamo anche il margine del conto gratuito percentuale da utilizzare per il trading in percentuale.

      2.1.10 La sezione OnDeinit

      //--- Release our indicator handles
         IndicatorRelease(adxHandle);
         IndicatorRelease(maHandle);

      Qui decidiamo di rilasciare tutti gli handler dell'indicatore.

      2.1.11. La sezione OnTick

      //--- check if EA can trade
          if (checkTrading() == false) 
         {
            Alert("EA cannot trade because certain trade requirements are not meant");
            return;
         }
      //--- Define the MQL5 MqlRates Structure we will use for our trade
         MqlRates mrate[];          // To be used to store the prices, volumes and spread of each bar
      /*
           Let's make sure our arrays values for the Rates, ADX Values and MA values 
           is store serially similar to the timeseries array
      */
      // the rates arrays
         ArraySetAsSeries(mrate,true);
      // the ADX values arrays
         ArraySetAsSeries(adxVal,true);
      // the MA values arrays
         ArraySetAsSeries(maVal,true);
      // the minDI values array
         ArraySetAsSeries(minDI,true);
      // the plsDI values array
         ArraySetAsSeries(plsDI,true);
      

      La prima cosa che facciamo qui è controllare ed essere sicuri se il nostro EA dovrebbe essere scambiato o meno. Se la funzione checktrade restituisce false, EA attenderà il prossimo tick ed effettuerà il controllo di nuovo.

      Dopo questo abbiamo dichiarato una struttura MQL5 MqlRates per ottenere i prezzi di ogni barra e poi usiamo la funzione ArraySetAsSeries per impostare tutti gli array richiesti.

      //--- Get the last price quote using the SymbolInfo class object function
         if (!mysymbol.RefreshRates())
           {
            Alert("Error getting the latest price quote - error:",GetLastError(),"!!");
            return;
           }
      
      //--- Get the details of the latest 3 bars
         if(CopyRates(_Symbol,_Period,0,3,mrate)<0)
           {
            Alert("Error copying rates/history data - error:",GetLastError(),"!!");
            return;
           }
      
      //--- EA should only check for new trade if we have a new bar
      // lets declare a static datetime variable
         static datetime Prev_time;
      // lest get the start time for the current bar (Bar 0)
         datetime Bar_time[1];
         //copy the current bar time
         Bar_time[0] = mrate[0].time;
      // We don't have a new bar when both times are the same
         if(Prev_time==Bar_time[0])
           {
            return;
           }
      //Save time into static varaiable, 
         Prev_time = Bar_time[0]; 

      Usiamo la classe oggetto CSymbolInfo per ottenere le quotazioni dei prezzi correnti e quindi copiare i prezzi correnti della barra nell'array mrates. Subito dopo decidiamo di verificare la presenza di una nuova barra.

      Se abbiamo una nuova barra, il nostro EA procederà a verificare se una condizione BUY o SELL è stata soddisfatta, altrimenti aspetterà fino a quando non avremo una nuova barra.

      //--- Copy the new values of our indicators to buffers (arrays) using the handle
         if(CopyBuffer(adxHandle,0,0,3,adxVal)<3 || CopyBuffer(adxHandle,1,0,3,plsDI)<3
            || CopyBuffer(adxHandle,2,0,3,minDI)<3)
           {
            Alert("Error copying ADX indicator Buffers - error:",GetLastError(),"!!");
            return;
           }
         if(CopyBuffer(maHandle,0,0,3,maVal)<3)
           {
            Alert("Error copying Moving Average indicator buffer - error:",GetLastError());
            return;
           }
      //--- we have no errors, so continue
      // Copy the bar close price for the previous bar prior to the current bar, that is Bar 1
      
         p_close=mrate[1].close;  // bar 1 close price

      Qui, abbiamo usato le funzioni CopyBuffer per ottenere i buffer dei nostri indicatori in array e se si verifica un errore nel processo, verrà visualizzato. Il prezzo di chiusura della barra precedente è stato copiato.

      //--- Do we have positions opened already?
        bool Buy_opened = false, Sell_opened=false; 
         if (myposition.Select(_Symbol) ==true)  // we have an opened position
          {
            if (myposition.Type()== POSITION_TYPE_BUY)
             {
                  Buy_opened = true;  //It is a Buy
                // Get Position StopLoss and Take Profit
                 double buysl = myposition.StopLoss();      // Buy position Stop Loss
                 double buytp = myposition.TakeProfit();    // Buy position Take Profit
                 // Check if we can close/modify position
                 if (ClosePosition("BUY",p_close)==true)
                   {
                      Buy_opened = false;   // position has been closed
                      return; // wait for new bar
                   }
                 else
                 {
                    if (CheckModify("BUY",p_close)==true) // We can modify position
                    {
                        Modify("BUY",buysl,buytp);
                        return; // wait for new bar
                    }
                 } 
             }
            else if(myposition.Type() == POSITION_TYPE_SELL)
             {
                  Sell_opened = true; // It is a Sell
                  // Get Position StopLoss and Take Profit
                  double sellsl = myposition.StopLoss();    // Sell position Stop Loss
                  double selltp = myposition.TakeProfit();  // Sell position Take Profit
                   if (ClosePosition("SELL",p_close)==true)
                   {
                     Sell_opened = false;  // position has been closed
                     return;   // wait for new bar
                   }
                   else
                   {
                       if (CheckModify("SELL",p_close)==true) // We can modify position
                       {
                           Modify("SELL",sellsl,selltp);
                           return;  //wait for new bar
                       }
                   } 
             }
          } 

      Usiamo la classe oggetto CPositionInfo da selezionare e verificare se abbiamo una posizione aperta per il simbolo corrente. Se esiste una posizione ed è un BUY, impostiamo Buy_opened come true e quindi utilizzare la classe oggetto CPositionInfo per ottenere lo stop loss e il take profitdella posizione. Usando una funzione che avevamo definito in precedenza, ClosePosition, abbiamo verificato se la posizione può essere vicina. Se la funzione restituisce true, allora la posizione è stata chiusa, quindi impostiamo Buy_opened su false abbiamo solo la posizione BUY iniziale chiusa. L'EA ora aspetterà un nuovo tick.

      Tuttavia, se la funzione restituisce false, quindi la posizione non è stata chiusa. È ora di controllare se possiamo modificare la posizione. Questo l'abbiamo ottenuto utilizzando la funzione CheckModify che avevamo definito in precedenza. Se la funzione restituisce true, significa che la posizione può essere modificata, quindi utilizzare la funzione Modifica per modificare la posizione.

      Se, d'altra parte, esiste una posizione ed è un SELL, impostiamo Sell_opened come true e usiamo l'oggetto della classe CPositionInfo per ottenere lo stop loss e il take profit della posizione. Abbiamo ripetuto lo stesso passaggio che abbiamo fatto per la posizione BUY per vedere se la posizione può essere chiusa o modificata.

            if(checkBuy()==true)
              {
               //--- any opened Buy position?
               if(Buy_opened)
                 {
                  Alert("We already have a Buy position!!!");
                  return;    //--- Don't open a new Sell Position
                 }
      
               double mprice=NormalizeDouble(mysymbol.Ask(),_Digits);                //--- latest ask price
               double stloss = NormalizeDouble(mysymbol.Ask() - STP*_Point,_Digits); //--- Stop Loss
               double tprofit = NormalizeDouble(mysymbol.Ask()+ TKP*_Point,_Digits); //--- Take Profit
               //--- check margin
               if(ConfirmMargin(ORDER_TYPE_BUY,mprice)==false)
                 {
                  Alert("You do not have enough money to place this trade based on your setting");
                  return;
                 }
               //--- open Buy position and check the result
               if(mytrade.Buy(Lot,_Symbol,mprice,stloss,tprofit))
               //if(mytrade.PositionOpen(_Symbol,ORDER_TYPE_BUY,Lot,mprice,stloss,tprofit)) 
                 {
                     //--- Request is completed or order placed
                   Alert("A Buy order has been successfully placed with deal Ticket#:",
                        mytrade.ResultDeal(),"!!");
                 }
               else
                 {
                  Alert("The Buy order request at vol:",mytrade.RequestVolume(), 
                        ", sl:", mytrade.RequestSL(),", tp:",mytrade.RequestTP(),
                        ", price:", mytrade.RequestPrice(), 
                           " could not be completed -error:",mytrade.ResultRetcodeDescription());
                  return;
                 }
              }

      Oppure possiamo usare la funzione PositionOpen

            if(checkBuy()==true)
              {
               //--- any opened Buy position?
               if(Buy_opened)
                 {
                  Alert("We already have a Buy position!!!");
                  return;    //--- Don't open a new Sell Position
                 }
      
               double mprice=NormalizeDouble(mysymbol.Ask(),_Digits);               //--- latest Ask price
               double stloss = NormalizeDouble(mysymbol.Ask() - STP*_Point,_Digits); //--- Stop Loss
               double tprofit = NormalizeDouble(mysymbol.Ask()+ TKP*_Point,_Digits); //--- Take Profit
               //--- check margin
               if(ConfirmMargin(ORDER_TYPE_BUY,mprice)==false)
                 {
                  Alert("You do not have enough money to place this trade based on your setting");
                  return;
                 }
               //--- open Buy position and check the result
               //if(mytrade.Buy(Lot,_Symbol,mprice,stloss,tprofit))
               if(mytrade.PositionOpen(_Symbol,ORDER_TYPE_BUY,Lot,mprice,stloss,tprofit))
                 {
                    //--- Request is completed or order placed            
                    Alert("A Buy order has been successfully placed with deal Ticket#:",
                  mytrade.ResultDeal(),"!!");
                 }
               else
                 {
                  Alert("The Buy order request at vol:",mytrade.RequestVolume(), 
                          ", sl:", mytrade.RequestSL(),", tp:",mytrade.RequestTP(), 
                          ", price:", mytrade.RequestPrice(), 
                          " could not be completed -error:",mytrade.ResultRetcodeDescription());
                  return;
                 }
              }

      Qui usiamo la funzione checkbuyper verificare una configurazione di acquisto e se restituisce true, quindi le nostre condizioni commerciali BUY sono state soddisfatte. Se già abbiamo una posizione BUY, non vogliamo effettuare un nuovo ordine. Abbiamo quindi utilizzato l'oggetto della classe CSymbolInfo per ottenere il prezzo ASK corrente e calcolato lo Stop Loss e Take Profit come richiesto. 

      Usiamo anche la funzione ConfirmMargin per controllare se la percentuale dell'account consentita per effettuare un ordine è maggiore rispetto al margine richiesto per effettuare questo ordine. Se la funzione restituisce true, allora andiamo avanti e piazziamo il trade, altrimenti non piazzeremo il trade.

      Usando l'oggetto della classe CTrade, abbiamo effettuato il nostro ordine e utilizzato lo stesso chiamate dell’oggetto per ottenere il codice di ritorno dell’operazione di trading. In base al risultato dell'operazione, viene visualizzato un messaggio.

            if(checkSell()==true)
              {
               //--- any opened Sell position?
               if(Sell_opened)
                 {
                  Alert("We already have a Sell position!!!");
                  return;    //--- Wait for a new bar
                 }
      
               double sprice=NormalizeDouble(mysymbol.Bid(),_Digits);             //--- latest Bid price
               double ssloss=NormalizeDouble(mysymbol.Bid()+STP*_Point,_Digits);   //--- Stop Loss
               double stprofit=NormalizeDouble(mysymbol.Bid()-TKP*_Point,_Digits); //--- Take Profit
               //--- check margin
               if(ConfirmMargin(ORDER_TYPE_SELL,sprice)==false)
                 {
                  Alert("You do not have enough money to place this trade based on your setting");
                  return;
                 }
               //--- Open Sell position and check the result
               if(mytrade.Sell(Lot,_Symbol,sprice,ssloss,stprofit))
               //if(mytrade.PositionOpen(_Symbol,ORDER_TYPE_SELL,Lot,sprice,ssloss,stprofit))
                 {
                     //---Request is completed or order placed            
                     Alert("A Sell order has been successfully placed with deal Ticket#:",mytrade.ResultDeal(),"!!");
                 }
               else
                 {
                  Alert("The Sell order request at Vol:",mytrade.RequestVolume(), 
                          ", sl:", mytrade.RequestSL(),", tp:",mytrade.RequestTP(), 
                          ", price:", mytrade.RequestPrice(), 
                          " could not be completed -error:",mytrade.ResultRetcodeDescription());
                  return;
                 }
      
              }

      Oppure possiamo anche utilizzare la funzione PositionOpen:

            if(checkSell()==true)
              {
               //--- any opened Sell position?
               if(Sell_opened)
                 {
                  Alert("We already have a Sell position!!!");
                  return;    //--- Wait for a new bar
                 }
      
               double sprice=NormalizeDouble(mysymbol.Bid(),_Digits);             //--- latest Bid price
               double ssloss=NormalizeDouble(mysymbol.Bid()+STP*_Point,_Digits);   //--- Stop Loss
               double stprofit=NormalizeDouble(mysymbol.Bid()-TKP*_Point,_Digits); //--- Take Profit
               //--- check margin
               if(ConfirmMargin(ORDER_TYPE_SELL,sprice)==false)
                 {
                  Alert("You do not have enough money to place this trade based on your setting");
                  return;
                 }
               //--- Open Sell position and check the result
               //if(mytrade.Sell(Lot,_Symbol,sprice,ssloss,stprofit))
               if(mytrade.PositionOpen(_Symbol,ORDER_TYPE_SELL,Lot,sprice,ssloss,stprofit))
                 {
                   //---Request is completed or order placed            
                   Alert("A Sell order has been successfully placed with deal Ticket#:",mytrade.ResultDeal(),"!!");
                 }
               else
                 {
                  Alert("The Sell order request at Vol:",mytrade.RequestVolume(),
                       ", sl:", mytrade.RequestSL(),", tp:",mytrade.RequestTP(), 
                       ", price:", mytrade.RequestPrice(), 
                         " could not be completed -error:",mytrade.ResultRetcodeDescription());
                  return;
                 }
              }

      Proprio come abbiamo fatto per il BUY, noi utilizzato la funzione Checksell per verificare una configurazione di vendita. Se restituisce true e non abbiamo una posizione di vendita già aperta, abbiamo utilizzato la funzione ConfirmMargin per verificare se abbiamo abbastanza soldi per aprire l'ordine. Se ConfirmMargin restituisce true, l'oggetto della classe CTrade viene utilizzato per effettuare l'ordine e in base alla risposta dal server di trading, il risultato del trade viene visualizzato utilizzando le funzioni oggetto della classe CTrade.

      Finora abbiamo visto come possiamo utilizzare le librerie di classi di trading per scrivere un Expert Advisor. La prossima cosa è testare il nostro Expert Advisor con lo Strategy Tester e vederne le prestazioni.

      Compila il codice EA e poi caricalo nello Strategy Tester.

      Compila il report per l'EA

      Figura 3. Report di compilazione di Expert Advisor 

      Sul grafico GBPUSD giornaliero utilizzando le impostazioni predefinite: Take Profit - 270, Stop Loss - 100 e Trails Point (TP/SL) - 32, avremo i seguenti risultati:

       

      Figura 4. Rapporto di prova di Expert Advisor - Grafico giornaliero GBPUSD

       

       

      Figura 5. Risultato del grafico del test Expert Advisor - Grafico giornaliero GBPUSD

                                                                                                                                      

      Figura 6. Il rapporto di prova di Expert Advisor mostra la modifica delle posizioni aperte - grafico giornaliero GBPUSD

       

      Figura 7.  Report grafico del test dell’Expert Advisor per il grafico giornaliero GBPUSD

      Sei libero di testare l'EA su qualsiasi altro grafico giornaliero di simboli con diverse impostazioni di Take profit, Stop loss e l'impostazione del Trail point e vedere cosa ottieni. 

      Tuttavia, dovresti capire che questo Expert Advisor è stato scritto solo a scopo di test...

      Vediamo ora come possiamo usare le altre classi (COrderInfo, CHstoryOrderInfo, e CDealInfo) per ottenere i dettagli dell'ordine/affare.

      2.2 Apertura/Cancellazione di un Ordine In Sospeso

      In questo esempio, scriveremo un semplice Expert Advisor che effettuerà un ordine in sospeso (BuyStop o SellStop) quando avremo rispettivamente una condizione di acquisto o vendita soddisfatta.

      2.2.1 Includere Le Classi Richieste

      //+------------------------------------------------------------------+
      //|  Include ALL classes that will be used                           |
      //+------------------------------------------------------------------+
      //--- The Trade Class
      #include <Trade\Trade.mqh>
      //--- The PositionInfo Class
      #include <Trade\PositionInfo.mqh>
      //--- The SymbolInfo Class
      #include <Trade\SymbolInfo.mqh>
      //--- The OrderInfo Class
      #include <Trade\OrderInfo.mqh>

      Abbiamo incluso le quattro classi che utilizzeremo in questo semplice Expert Advisor. Sono stati spiegati negli esempi sopra.

      Non spiegherò ogni sezione di questo Expert Advisor in quanto è simile a quella spiegata sopra, tuttavia, esaminerò la parte essenziale dell'Expert Advisor che spiega ciò di cui vogliamo discutere in questa sezione.

      L'unica differenza è che abbiamo deciso di dichiarare MqlRates mrate[] su un ambito globale.

      //--- Define the MQL5 MqlRates Structure we will use for our trade
         MqlRates mrate[];     // To be used to store the prices, volumes and spread of each bar
      

      Una volta incluse le classi, dobbiamo anche ricordarci di creare oggetti di ogni classe:

      //+------------------------------------------------------------------+
      //|  CREATE CLASS OBJECTS                                            |
      //+------------------------------------------------------------------+
      //--- The CTrade Class Object
      CTrade mytrade;
      //--- The CPositionInfo Class Object
      CPositionInfo myposition;
      //--- The CSymbolInfo Class Object
      CSymbolInfo mysymbol;
      //--- The COrderInfo Class Object
      COrderInfo myorder;

      Le funzioni CheckBuy() e CheckSell() sono le stesse dell'Expert Advisor spiegato prima.

      Quello che vogliamo fare qui è inserire un ordine BUYSTOP quando abbiamo una configurazione di acquisto e un ordine SELLSTOP quando abbiamo una configurazione di vendita.

      Esaminiamo ora alcune delle funzioni che abbiamo creato per semplificarci le cose.

      2.2.2 La funzione CountOrders

      //+------------------------------------------------------------------+
      //|  Count Total Orders for this expert/symbol                       |
      //+------------------------------------------------------------------+
      int CountOrders()
        {
         int mark=0;
      
         for(int i=OrdersTotal()-1; i>=0; i--)
           {
            if(myorder.Select(OrderGetTicket(i)))
              {
               if(myorder.Magic()==EA_Magic && myorder.Symbol()==_Symbol) mark++;
              }
           }
         return(mark);
        }

      Questa funzione viene utilizzata per ottenere il totale degli ordini in sospeso disponibili in un determinato momento.

      Abbiamo usato l'oggetto della nostra classe COrderInfo per controllare i dettagli dell'ordine se è stato selezionato con successo con la funzione myorder.Select().

      Se il ritorno di Magic dal nostro oggetto di classe e il simbolo restituito è quello che stiamo cercando, allora l'ordine è stato inserito dal nostro Expert Advisor, quindi viene conteggiato e memorizzato nel segno della variabile.

      2.2.3 La funzione DeletePending

      //+------------------------------------------------------------------+
      //| Checks and Deletes a pending order                               |
      //+------------------------------------------------------------------+
      bool DeletePending()
        {
         bool marker=false;
      //--- check all pending orders
         for(int i=OrdersTotal()-1; i>=0; i--)
           {
            if(myorder.Select(OrderGetTicket(i)))
              {
               if(myorder.Magic()==EA_Magic && myorder.Symbol()==_Symbol)
                 {
                  //--- check if order has stayed more than two bars time
                  if(myorder.TimeSetup()<mrate[2].time)
                    {
                     //--- delete this pending order and check if we deleted this order successfully?
                      if(mytrade.OrderDelete(myorder.Ticket())) //Request successfully completed 
                        {
                          Alert("A pending order with ticket #", myorder.Ticket(), " has been successfully deleted!!");
                          marker=true;
                        }
                       else
                        {
                          Alert("The pending order # ",myorder.Ticket(),
                                   " delete request could not be completed - error: ",mytrade.ResultRetcodeDescription());
                        }
      
                    }
                 }
              }
           }
         return(marker);
        }

      Proprio come la funzione di contrordine, questa funzione utilizza anche le funzioni della classe COrderInfo per ottenere le proprietà degli ordini. La funzione verifica la presenza di qualsiasi ordine in sospeso che è stato impostato tre barre prima (il tempo di impostazione dell'ordine in sospeso è inferiore a mrate[2].time) e non è stato ancora attivato.

      Se qualche ordine cade in questo categoria, la funzione di classe CTrade OrderDelete viene utilizzata per eliminare l'ordine. Questa funzione restituisce true in caso di successo e false in caso contrario.

      Le due funzioni precedenti vengono utilizzate immediatamente dopo la formazione di una nuova barra, prima di verificare una nuova impostazione di trading. Vogliamo essere sicuri di non avere più di tre ordini in sospeso effettuati in ogni momento.  Per farlo utilizziamo il seguente codice:

      // do we have more than 3 already placed pending orders
      if (CountOrders()>3) 
        {
           DeletePending(); 
           return;  
        }

      2.2.4 Effettuare un Ordine Pendente

         if(checkBuy()==true)
           {
            Alert("Total Pending Orders now is :",CountOrders(),"!!");
            //--- any opened Buy position?
            if(Buy_opened)
              {
               Alert("We already have a Buy position!!!");
               return;    //--- Don't open a new Sell Position
              }
            //Buy price = bar 1 High + 2 pip + spread
            int sprd=mysymbol.Spread();
            double bprice =mrate[1].high + 10*_Point + sprd*_Point;
            double mprice=NormalizeDouble(bprice,_Digits);               //--- Buy price
            double stloss = NormalizeDouble(bprice - STP*_Point,_Digits); //--- Stop Loss
            double tprofit = NormalizeDouble(bprice+ TKP*_Point,_Digits); //--- Take Profit
            //--- open BuyStop order
            if(mytrade.BuyStop(Lot,mprice,_Symbol,stloss,tprofit))
            //if(mytrade.OrderOpen(_Symbol,ORDER_TYPE_BUY_STOP,Lot,0.0,bprice,stloss,tprofit,ORDER_TIME_GTC,0)) 
              {
               //--- Request is completed or order placed
               Alert("A BuyStop order has been successfully placed with Ticket#:",mytrade.ResultOrder(),"!!");
               return;
              }
            else
              {
               Alert("The BuyStop order request at vol:",mytrade.RequestVolume(), 
                       ", sl:", mytrade.RequestSL(),", tp:",mytrade.RequestTP(),
                     ", price:", mytrade.RequestPrice(), 
                       " could not be completed -error:",mytrade.ResultRetcodeDescription());
               return;
              }
           }

      Oppure possiamo anche utilizzare la funzione OrderOpen per effettuare l'ordine BUYSTOP

         if(checkBuy()==true)
           {
            Alert("Total Pending Orders now is :",CountOrders(),"!!");
            //--- any opened Buy position?
            if(Buy_opened)
              {
               Alert("We already have a Buy position!!!");
               return;    //--- Don't open a new Sell Position
              }
            //Buy price = bar 1 High + 2 pip + spread
            int sprd=mysymbol.Spread();
            double bprice =mrate[1].high + 10*_Point + sprd*_Point;
            double mprice=NormalizeDouble(bprice,_Digits);               //--- Buy price
            double stloss = NormalizeDouble(bprice - STP*_Point,_Digits); //--- Stop Loss
            double tprofit = NormalizeDouble(bprice+ TKP*_Point,_Digits); //--- Take Profit
            //--- open BuyStop order
            //if(mytrade.BuyStop(Lot,mprice,_Symbol,stloss,tprofit))
            if(mytrade.OrderOpen(_Symbol,ORDER_TYPE_BUY_STOP,Lot,0.0,bprice,stloss,tprofit,ORDER_TIME_GTC,0)) 
              {
               //--- Request is completed or order placed
               Alert("A BuyStop order has been successfully placed with Ticket#:",mytrade.ResultOrder(),"!!");
               return;
              }
            else
              {
               Alert("The BuyStop order request at vol:",mytrade.RequestVolume(), 
                    ", sl:", mytrade.RequestSL(),", tp:",mytrade.RequestTP(),
                    ", price:", mytrade.RequestPrice(), 
                      " could not be completed -error:",mytrade.ResultRetcodeDescription());
               return;
              }
           }

      Nell'effettuare il nostro ordine BUYSTOP, il prezzo di apertura è il Bar 1 High + 2pip + spread.

      Ricorda che il prezzo visualizzato sul grafico è il prezzo BID e nell'effettuare ordini long/buy hai bisogno del prezzo ASK, ecco perché decidiamo di aggiungere lo spread alla Bar 1 High così che quello che abbiamo ora è il corrispondente prezzo Ask + 2pip. Lo stop loss e il take profit è già stato definito nei parametri di input.

      Una volta che abbiamo preparato tutto il parametri necessari, usiamo la funzione di classe CTrade BuyStop o OrderOpen per posizionare il nostro ordine. Il tipo di ordine qui è ORDER_TYPE_BUY_STOP (ordine Buy Stop). Usiamo lo stesso prezzo per il prezzo limite ma questo non è un ordine BuyLimit. Abbiamo anche impostato il tempo di validità dell'ordine a ORDER_TIME_GTC, il che significa che gli ordini rimangono validi fino a quando non viene annullato.

      Se usi ORDER_TIME_GTC o ORDER_TIME_DAY, non è necessario specificare l'ora di scadenza, ecco perché la impostiamo su 0.

         if(checkSell()==true)
           {
            Alert("Total Pending Orders now is :",CountOrders(),"!!");
            //--- any opened Sell position?
            if(Sell_opened)
              {
               Alert("We already have a Sell position!!!");
               return;    //--- Wait for a new bar
              }
            //--- Sell price = bar 1 Low - 2 pip 
            double sprice=mrate[1].low-10*_Point;
            double slprice=NormalizeDouble(sprice,_Digits);            //--- Sell price
            double ssloss=NormalizeDouble(sprice+STP*_Point,_Digits);   //--- Stop Loss
            double stprofit=NormalizeDouble(sprice-TKP*_Point,_Digits); //--- Take Profit
            //--- Open SellStop Order
            if(mytrade.SellStop(Lot,slprice,_Symbol,ssloss,stprofit))
            //if(mytrade.OrderOpen(_Symbol,ORDER_TYPE_SELL_STOP,Lot,0.0,slprice,ssloss,stprofit,ORDER_TIME_GTC,0)) 
              {
               //--- Request is completed or order placed
               Alert("A SellStop order has been successfully placed with Ticket#:",mytrade.ResultOrder(),"!!");
               return;
              }
            else
              {
               Alert("The SellStop order request at Vol:",mytrade.RequestVolume(), 
                    ", sl:", mytrade.RequestSL(),", tp:",mytrade.RequestTP(), 
                      ", price:", mytrade.RequestPrice(), 
                      " could not be completed -error:",mytrade.ResultRetcodeDescription());
               return;
              }
           }

      Oppure possiamo anche utilizzare la funzione OrderOpen per effettuare l'ordine:

         if(checkSell()==true)
           {
            Alert("Total Pending Orders now is :",CountOrders(),"!!");
            //--- any opened Sell position?
            if(Sell_opened)
              {
               Alert("We already have a Sell position!!!");
               return;    //--- Wait for a new bar
              }
            //--- Sell price = bar 1 Low - 2 pip 
            double sprice=mrate[1].low-10*_Point;
            double slprice=NormalizeDouble(sprice,_Digits);            //--- Sell price
            double ssloss=NormalizeDouble(sprice+STP*_Point,_Digits);   //--- Stop Loss
            double stprofit=NormalizeDouble(sprice-TKP*_Point,_Digits); //--- Take Profit
            //--- Open SellStop Order
            //if(mytrade.SellStop(Lot,slprice,_Symbol,ssloss,stprofit))
            if(mytrade.OrderOpen(_Symbol,ORDER_TYPE_SELL_STOP,Lot,0.0,slprice,ssloss,stprofit,ORDER_TIME_GTC,0)) 
              {
               //--- Request is completed or order placed
               Alert("A SellStop order has been successfully placed with Ticket#:",mytrade.ResultOrder(),"!!");
               return;
              }
            else
              {
               Alert("The SellStop order request at Vol:",mytrade.RequestVolume(), 
                      ", sl:", mytrade.RequestSL(),", tp:",mytrade.RequestTP(), 
                      ", price:", mytrade.RequestPrice(), 
                    " could not be completed -error:",mytrade.ResultRetcodeDescription());
               return;
              }
           }

      Proprio come l'ordine BuyStop, il prezzo di apertura è Bar 1 basso + 2 pip. Qui non abbiamo bisogno di aggiungere lo spread, poiché, normalmente, abbiamo bisogno del prezzo BID per piazzare ordini allo short/sell.

      Usiamo anche la stessa funzione OrderOpen o la funzione SellStop per piazzare l'ordine SellStop. L'ordine del tipo qui è ORDER_TYPE_SELL_STOP (ordine di Sell Stop).

      Di seguito sono riportati i risultati del nostro semplice Expert Advisor.

       


      Figura 8. Il report di prova per l'ordine pendente EA

       

      Figura 9 - Il report grafico per l'EA

       

      Figura 10. Il report del Grafico per l'EA

       

      2.3 Ottenere i Dettagli dell’Ordine/Affare

      In questo esempio, mostreremo come possiamo ottenere i dettagli di un ordine una volta che è stato attivato.

      In questa fase, non è più un ordine in sospeso perché è stato attivato e trasformato in un affare.

      Per capire appieno questa procedura, diamo un'occhiata a un dettaglio di giornale da uno dei nostri mestieri:

      Procedura di elaborazione dell'ordine

      Figura 11. Procedura di elaborazione dell'ordine

      • Fase 1: Viene effettuato un ordine in sospeso in attesa che le condizioni siano soddisfatte (Ordine in sospeso)
      • Fase 2: La condizione è soddisfatta, l’ordine in sospeso viene attivato, diventa un affare (ordine in sospeso ora nella cronologia)
      • Fase 3: L'affare è stato eseguito e abbiamo una posizione aperta. (l'affare è ora nella cronologia)

      2.3.1 Ottenere le Proprietà dell'Ordine (Cronologia)

      //+------------------------------------------------------------------+
      //|  Include ALL classes that will be used                           |
      //+------------------------------------------------------------------+
      //--- The Trade Class
      #include <Trade\HistoryOrderInfo.mqh>
      //+------------------------------------------------------------------+
      //|  CREATE CLASS OBJECT                                             |
      //+------------------------------------------------------------------+
      //--- The HistoryOrderInfo Class Object
      CHistoryOrderInfo myhistory;
      //+------------------------------------------------------------------+
      //| Script program start function                                    |
      //+------------------------------------------------------------------+
      void OnStart()
        {
      //--- Get all orders in History and get their details
         int buystop=0;
         int sellstop=0;
         int buylimit=0;
         int selllimit=0;
         int buystoplimit=0;
         int sellstoplimit=0;
         int buy=0;
         int sell=0;
      
         int s_started=0;
         int s_placed=0;
         int s_cancelled=0;
         int s_partial=0;
         int s_filled=0;
         int s_rejected=0;
         int s_expired=0;
      
         ulong o_ticket;
      // Get all history records
         if(HistorySelect(0,TimeCurrent())) // get all history orders
           {
            // Get total orders in history
            for(int j=HistoryOrdersTotal(); j>0; j--)
              {
               // select order by ticket
               o_ticket=HistoryOrderGetTicket(j);
               if(o_ticket>0)
                 {
                  // Set order Ticket to work with
                  myhistory.Ticket(o_ticket);
                  Print("Order index ",j," Order Ticket is: ",myhistory.Ticket()," !");
                  Print("Order index ",j," Order Setup Time is: ",TimeToString(myhistory.TimeSetup())," !");
                  Print("Order index ",j," Order Open Price is: ",myhistory.PriceOpen()," !");
                  Print("Order index ",j," Order Symbol is: ",myhistory.Symbol() ," !");
                  Print("Order index ",j," Order Type is: ", myhistory.Type() ," !");
                  Print("Order index ",j," Order Type Description is: ",myhistory.TypeDescription()," !");
                  Print("Order index ",j," Order Magic is: ",myhistory.Magic()," !");
                  Print("Order index ",j," Order Time Done is: ",myhistory.TimeDone()," !");
                  Print("Order index ",j," Order Initial Volume is: ",myhistory.VolumeInitial()," !");
                  //
                  //
                  if(myhistory.Type() == ORDER_TYPE_BUY_STOP) buystop++;
                  if(myhistory.Type() == ORDER_TYPE_SELL_STOP) sellstop++;
                  if(myhistory.Type() == ORDER_TYPE_BUY) buy++;
                  if(myhistory.Type() == ORDER_TYPE_SELL) sell++;
                  if(myhistory.Type() == ORDER_TYPE_BUY_LIMIT) buylimit++;
                  if(myhistory.Type() == ORDER_TYPE_SELL_LIMIT) selllimit++;
                  if(myhistory.Type() == ORDER_TYPE_BUY_STOP_LIMIT) buystoplimit++;
                  if(myhistory.Type() == ORDER_TYPE_SELL_STOP_LIMIT) sellstoplimit++;
      
                  if(myhistory.State() == ORDER_STATE_STARTED) s_started++;
                  if(myhistory.State() == ORDER_STATE_PLACED) s_placed++;
                  if(myhistory.State() == ORDER_STATE_CANCELED) s_cancelled++;
                  if(myhistory.State() == ORDER_STATE_PARTIAL) s_partial++;
                  if(myhistory.State() == ORDER_STATE_FILLED) s_filled++;
                  if(myhistory.State() == ORDER_STATE_REJECTED) s_rejected++;
                  if(myhistory.State() == ORDER_STATE_EXPIRED) s_expired++;
                 }
              }
           }
      // Print summary
         Print("Buy Stop Pending Orders : ",buystop);
         Print("Sell Stop Pending Orders: ",sellstop);
         Print("Buy Orders : ",buy);
         Print("Sell Orders: ",sell);
         Print("Total Orders in History is :",HistoryOrdersTotal()," !");
         
         Print("Orders type summary");
         Print("Market Buy Orders: ",buy);
         Print("Market Sell Orders: ",sell);
         Print("Pending Buy Stop: ",buystop);
         Print("Pending Sell Stop: ",sellstop);
         Print("Pending Buy Limit: ",buylimit);
         Print("Pending Sell Limit: ",selllimit);
         Print("Pending Buy Stop Limit: ",buystoplimit);
         Print("Pending Sell Stop Limit: ",sellstoplimit);
         Print("Total orders:",HistoryOrdersTotal()," !");
      
         Print("Orders state summary");
         Print("Checked, but not yet accepted by broker: ",s_started);
         Print("Accepted: ",s_placed);
         Print("Canceled by client: ",s_cancelled);
         Print("Partially executed: ",s_partial);
         Print("Fully executed: ",s_filled);
         Print("Rejected: ",s_rejected);
         Print("Expired: ",s_expired);
        }

      Questo è solo un semplice script che mostra come ottenere i dettagli degli ordini nei nostri record di Cronologia. Abbiamo incluso la classe CHstoryOrderInfo e creato un oggetto della classe.

      Utilizziamo ora l'oggetto per ottenere i dettagli degli ordini.

      Il risultato per lo script dell'ordine della cronologia 

      Figura 12. Risultato dello script dell'ordine della cronologia

      2.3.2 Ottenere le Proprietà dell'Affare (Cronologia)

      //+------------------------------------------------------------------+
      //|  Include ALL classes that will be used                           |
      //+------------------------------------------------------------------+
      //--- The CDealInfo Class
      #include <Trade\DealInfo.mqh>
      //+------------------------------------------------------------------+
      //|  Create class object                                             |
      //+------------------------------------------------------------------+
      //--- The CDealInfo Class Object
      CDealInfo mydeal;
      //+------------------------------------------------------------------+
      //| Script program start function                                    |
      //+------------------------------------------------------------------+
      void OnStart()
        {
      //--- Get all deals in History and get their details
          int buy=0;
          int sell=0;
          int deal_in=0;
          int deal_out=0;
          ulong d_ticket;
          // Get all history records
          if (HistorySelect(0,TimeCurrent())) 
          {
            // Get total deals in history
            for (int j=HistoryDealsTotal(); j>0; j--)
            {
               // select deals by ticket
               if (d_ticket = HistoryDealGetTicket(j))
               {
                // Set Deal Ticket to work with
                mydeal.Ticket(d_ticket);
                Print("Deal index ", j ," Deal Ticket is: ", mydeal.Ticket() ," !");
                Print("Deal index ", j ," Deal Execution Time is: ", TimeToString(mydeal.Time()) ," !");
                Print("Deal index ", j ," Deal Price is: ", mydeal.Price() ," !");
                Print("Deal index ", j ," Deal Symbol is: ", mydeal.Symbol() ," !");
                Print("Deal index ", j ," Deal Type Description is: ", mydeal.TypeDescription() ," !");
                Print("Deal index ", j ," Deal Magic is: ", mydeal.Magic() ," !");
                Print("Deal index ", j ," Deal Time is: ", mydeal.Time() ," !");
                Print("Deal index ", j ," Deal Initial Volume is: ", mydeal.Volume() ," !");
                Print("Deal index ", j ," Deal Entry Type Description is: ", mydeal.EntryDescription() ," !");
                Print("Deal index ", j ," Deal Profit is: ", mydeal.Profit() ," !");
                //
                if (mydeal.Entry() == DEAL_ENTRY_IN) deal_in++;
                if (mydeal.Entry() == DEAL_ENTRY_OUT) deal_out++;
                if (mydeal.Type() == DEAL_TYPE_BUY) buy++;
                if (mydeal.Type() == DEAL_TYPE_SELL) sell++;
               }
            }
          }
          // Print Summary
          Print("Total Deals in History is :", HistoryDealsTotal(), " !");
          Print("Total Deal Entry IN is : ", deal_in);
          Print("Total Deal Entry OUT is: ", deal_out);
          Print("Total Buy Deal is : ", buy);
          Print("Total Sell Deal is: ", sell);
        }

      Anche questo è un semplice script che mostra come ottenere i dettagli dei nostri registri degli affari.

      Il risultato per lo script del deal

      Figura 13. Il risultato dello script dell'affare storico


      Conclusione

      In questo articolo, siamo stati in grado di esaminare le principali funzioni delle librerie Standard Trade Class e abbiamo dimostrato come alcune di queste funzionalità possono essere utilizzate Expert Advisor che implementano la modifica della posizione, l'immissione di ordini in sospeso e la cancellazione e verifica del margine prima di piazzare un trade.

      Abbiamo anche hanno dimostrato come possono essere utilizzati per ottenere i dettagli dell'ordine e dell’affare. Ci sono alcune di queste funzioni che non abbiamo usato mentre scrivevamo il nostro Expert Advisor, a seconda del tipo di strategia di trading che stai utilizzando, è possibile usare più o meno quanto abbiamo usato in questo esempio.

      Sarà una buona idea rivedere la sezione descrizione per le varie funzioni e vedere come puoi utilizzarli per scrivere il tuo Expert Advisor.

      Le librerie della classe Standard hanno lo scopo di rendere la vita più facile sia ai trader che agli sviluppatori, quindi assicurati di usarli.


      Tradotto dall’inglese da MetaQuotes Ltd.
      Articolo originale: https://www.mql5.com/en/articles/138

      Controllo dello Slope della Curva di Saldo Durante il Lavoro di un Expert Advisor Controllo dello Slope della Curva di Saldo Durante il Lavoro di un Expert Advisor
      Trovare regole per un sistema di trading e programmarle in un Expert Advisor è una metà del lavoro. In qualche modo, è necessario correggere il funzionamento dell'Expert Advisor in quanto accumula i risultati del trading. Questo articolo descrive uno degli approcci che consente di migliorare le prestazioni di un Expert Advisor attraverso la creazione di un feedback che misura la pendenza della curva di bilanciamento.
      Utilizzo della Funzione TesterWithdrawal() per il Modeling dei Prelievi di Profitto Utilizzo della Funzione TesterWithdrawal() per il Modeling dei Prelievi di Profitto
      Questo articolo descrive l'uso della funzione TesterWithDrawal() per stimare i rischi nei sistemi commerciali che implicano il ritiro di una certa parte delle attività durante il loro funzionamento. Inoltre, descrive l'effetto di questa funzione sull'algoritmo di calcolo del drawdown del capitale nello Strategy Tester. Questa funzione è utile quando si ottimizzano i parametri dei propri Expert Advisor.
      Come Creare Rapidamente un Expert Advisor per l’Automated Trading Championship 2010 Come Creare Rapidamente un Expert Advisor per l’Automated Trading Championship 2010
      Al fine di sviluppare un expert per partecipare all'Automated Trading Championship 2010, usiamo un modello di pronto dell’expert advisor. Anche il programmatore MQL5 alle prime armi sarà in grado di questo compito, perché per le tue strategie le classi di base, le funzioni, i modelli sono già sviluppati. Basta scrivere una quantità minima di codice per implementare la tua idea di trading.
      Il Metodo Ottimale per il Calcolo del Volume Totale della Posizione in Base al Numero Magico Specificato Il Metodo Ottimale per il Calcolo del Volume Totale della Posizione in Base al Numero Magico Specificato
      Il problema del calcolo del volume totale della posizione del simbolo specificato e del numero magico è considerato in questo articolo. Il metodo proposto richiede solo la parte minima necessaria della cronologia degli affari, trova il momento più vicino in cui la posizione totale era uguale a zero ed esegue i calcoli con le operazioni recenti. Viene anche considerato il lavoro con le variabili globali del terminale client.