OnTick

La funzione è chiamata nell' EA quando si verifica l'evento NewTick si verifica per gestire una nuova quotazione.

void  OnTick(void);

Valore di ritorno

Nessun valore di ritorno

Nota

L'evento NewTick viene generato solo per EA quando si riceve un nuovo tick per un simbolo del chart a cui è assegnato l' EA. Non ha senso definire la funzione OnTick() in un indicatore personalizzato o uno script poiché non viene generato un evento NewTick.

L'evento Tick è generato solo per EA, ma questo non significa che gli EA debbano presentare la funzione OnTick(), poiché gli eventi Timer, BookEvent e ChartEvent vengono generati anche per l'EA, oltre a NewTick.

Tutti gli eventi vengono gestiti uno dopo l'altro nell'ordine di ricezione. Se la coda contiene già l'evento NewTick o questo evento è in fase di elaborazione, allora il nuovo evento NewTick non viene aggiunto alla coda dell'applicazione mql5.

L'evento NewTick viene generato indipendentemente dal fatto che il trading automatico sia abilitato (pulsante AutoTrading). Il trading automatico disabilitato significa solo il divieto di inviare richieste trade da un EA. L'operazione EA non viene interrotta.

La disabilitazione del trading automatico premendo il pulsante AutoTrading non interrompe l'esecuzione corrente della funzione OnTick().

Esempio di EA con la sua intera logica di trading nella funzione OnTick()

//+------------------------------------------------------------------+
//|                                                   TradeByATR.mq5 |
//|                        Copyright 2018, MetaQuotes Software Corp. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2000-2024, MetaQuotes Ltd."
#property link      "https://www.mql5.com"
#property version   "1.00"
#property description "Esempio di trading EA in \"explosive\" direzione candela"
#property description "\"Explosive\" la candela ha la grandezza del corpo superiore a k * ATR"
#property description "The \"revers\"parametro inverte la direzione del segnale"
 
input double lots=0.1;        // volume in lotti
input double kATR=3;          // signal lunghezza candela in ATR
input int    ATRperiod=20;    // ATR indicator period
input int    holdbars=8;      // numero di barre per mantenere la posizione attiva
input int    slippage=10;     // slippage consentito
input bool   revers=false;    // inverto il segnale? 
input ulong  EXPERT_MAGIC=0;  // EA MagicNumber
//--- per memorizzare l'handle dell'indicatore ATR
int atr_handle;
//--- qui memorizzeremo gli ultimi valori ATR e il corpo della candela
double last_atr,last_body;
datetime lastbar_timeopen;
double trade_lot;
//+------------------------------------------------------------------+
//| Funzione di inizializzazione Expert                              |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- inizializza le variabili globali
   last_atr=0;
   last_body=0;
//--- imposta il volume corretto
   double min_lot=SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_MIN);
   trade_lot=lots>min_lot? lots:min_lot;   
//--- crea l'handle dell'indicatore ATR
   atr_handle=iATR(_Symbol,_Period,ATRperiod);
   if(atr_handle==INVALID_HANDLE)
     {
      PrintFormat("%s: impossibile creare iATR, codice di errore %d",__FUNCTION__,GetLastError());
      return(INIT_FAILED);
     }
//--- inizializzazione EA di successo
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Funzione di deinitializzazione dell' Expert                      |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//--- informa del codice di fine operazione EA
   Print(__FILE__,": Codice della ragione di deinizializzazione = ",reason);
  }
//+------------------------------------------------------------------+
//| Funzione tick Expert                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
//--- segnale di trading
staticoint segnale = 0; // +1 significa un segnale di acquisto, -1 indica un segnale di vendita
//--- controlla e chiude le vecchie posizioni aperte più di barre 'holdbars' fa
   ClosePositionsByBars(holdbars,slippage,EXPERT_MAGIC);
//--- controlla una nuova barra
   if(isNewBar())
     {
      // --- controlla la presenza del segnale      
      signal=CheckSignal();
     }
// --- se si apre una posizione netting, saltare il segnale - attendere fino a quando non si chiude
   if(signal!=0 && PositionsTotal()>0 && (ENUM_ACCOUNT_MARGIN_MODE)AccountInfoInteger(ACCOUNT_MARGIN_MODE)==ACCOUNT_MARGIN_MODE_RETAIL_NETTING)
     {
      signal=0;
      return// esce dal gestore eventi NewTick e non entra nel mercato prima che appaia una nuova barra
     }
//--- per un conto hedging, ogni posizione viene tenuta e chiusa separatamente
   if(signal!=0)
     {
      //--- segnale buy
      if(signal>0)
        {
         PrintFormat("%s: Segnale Buy! Revers=%s",__FUNCTION__,string(revers));
         if(Buy(trade_lot,slippage,EXPERT_MAGIC))
            signal=0;
        }
      //--- segnale sell
      if(signal<0)
        {
         PrintFormat("%s: segnale Sell! Revers=%s",__FUNCTION__,string(revers));
         if(Sell(trade_lot,slippage,EXPERT_MAGIC))
            signal=0;
        }
     }
//--- Fine funzione OnTick
  }
//+------------------------------------------------------------------+
//| Controlla un nuovo segnale di trading                            |
//+------------------------------------------------------------------+
int CheckSignal()
  {
//--- 0 significa nessun segnale
   int res=0;
//--- ottiene il valore ATR su una penultima barra completa (l'indice della barra è 2)
   double atr_value[1];
   if(CopyBuffer(atr_handle,0,2,1,atr_value)!=-1)
     {
      last_atr=atr_value[0];
      // --- recupera i dati sull'ultima barra chiusa sull'array di tipo MqlRates
      MqlRates bar[1];
      if(CopyRates(_Symbol,_Period,1,1,bar)!=-1)
        {
         // --- calcola la misura del corpo della barra sull'ultima barra completa
         last_body=bar[0].close-bar[0].open;
// --- se il corpo dell'ultima barra (con indice 1) supera il precedente valore ATR (sulla barra con indice 2), viene ricevuto un segnale di trading
         if(MathAbs(last_body)>kATR*last_atr)
            res=last_body>0?1:-1; // valore positivo per la candela verso l'alto
        }
      else
         PrintFormat("% s: impossibile ricevere l'ultima barra! Error",__FUNCTION__,GetLastError());
     }
   else
      PrintFormat("% s: impossibile ricevere il valore dell'indicatore ATR! Error",__FUNCTION__,GetLastError());
//--- se la modalità di trading inverso è abilitata
   res=revers?-res:res;  // inverte il segnale se necessario (restituisci -1 invece di 1 e viceversa)
//--- restituisce un valore del segnale di trading
   return (res);
  }
//+------------------------------------------------------------------+
//| Restituisce 'true' quando appare una nuova barra                 |
//+------------------------------------------------------------------+
bool isNewBar(const bool print_log=true)
  {
   static datetime bartime=0; // memorizza l'orario di apertura della barra corrente
//--- ottiene l'orario di apertura della barra zero
   datetime currbar_time=iTime(_Symbol,_Period,0);
// --- se l'orario di apertura cambia, è arrivata una nuova barra
   if(bartime!=currbar_time)
     {
      bartime=currbar_time;
      lastbar_timeopen=bartime;
      //--- visualizza i dati sull'orario di apertura di una nuova barra nel log      
      if(print_log && !(MQLInfoInteger(MQL_OPTIMIZATION)||MQLInfoInteger(MQL_TESTER)))
        {
         //--- visualizza un messaggio con una nuova barra di apertura
         PrintFormat("%s: nuova barra su %s %s aperta a %s",__FUNCTION__,_Symbol,
                     StringSubstr(EnumToString(_Period),7),
                     TimeToString(TimeCurrent(),TIME_SECONDS));
         //--- recupera i dati sull'ultimo tick
         MqlTick last_tick;
         if(!SymbolInfoTick(Symbol(),last_tick))
            Print("SymbolInfoTick() fallito, errore = ",GetLastError());
         //--- mostra l'orario dell'ultimo tick fino ai millisecondi
         PrintFormat("L'ultimo tick era alle %s.%03d",
                     TimeToString(last_tick.time,TIME_SECONDS),last_tick.time_msc%1000);
        }
      //--- abbiamo una nuova barra
      return (true);
     }
//--- nessuna nuova barra
   return (false);
  }
//+------------------------------------------------------------------+
//| Acquista ad un prezzo di mercato con un volume specificato       |
//+------------------------------------------------------------------+
bool Buy(double volume,ulong deviation=10,ulong  magicnumber=0)
  {
//--- compra a prezzo di mercato
   return (MarketOrder(ORDER_TYPE_BUY,volume,deviation,magicnumber));
  }
//+------------------------------------------------------------------+
//| Vendi ad un prezzo di mercato con un volume specificato          |
//+------------------------------------------------------------------+
bool Sell(double volume,ulong deviation=10,ulong  magicnumber=0)
  {
//--- vendi a prezzo di mercato
   return (MarketOrder(ORDER_TYPE_SELL,volume,deviation,magicnumber));
  }
//+------------------------------------------------------------------+
//| Chiusura le posizioni per hold time in barre                     |
//+------------------------------------------------------------------+
void ClosePositionsByBars(int holdtimebars,ulong deviation=10,ulong  magicnumber=0)
  {
   int total=PositionsTotal(); // numero di posizioni aperte   
//--- itera su posizioni aperte
   for(int i=total-1; i>=0; i--)
     {
      //--- parametri dell posizione
      ulong  position_ticket=PositionGetTicket(i);                                      // ticket posizione
      string position_symbol=PositionGetString(POSITION_SYMBOL);                        // simbolo 
      ulong  magic=PositionGetInteger(POSITION_MAGIC);                                  // MagicNumber della posizione
      datetime position_open=(datetime)PositionGetInteger(POSITION_TIME);               // orario d'apertura della posizione
      int bars=iBarShift(_Symbol,PERIOD_CURRENT,position_open)+1;                       // quante barre fa una posizione è stata aperta
 
      //--- se la durata(lifetime) di una posizione è già grande, mentre MagicNumber e il simbolo corrispondono
      if(bars>holdtimebars && magic==magicnumber && position_symbol==_Symbol)
        {
         int    digits=(int)SymbolInfoInteger(position_symbol,SYMBOL_DIGITS);           // numero di posizioni decimali
         double volume=PositionGetDouble(POSITION_VOLUME);                              // volume della posizione
         ENUM_POSITION_TYPE type=(ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE); // tipo di posizione
         string str_type=StringSubstr(EnumToString(type),14);
         StringToLower(str_type); // abbassa il case del testo per la corretta formattazione del messaggio
         PrintFormat("Chiusura posizione #%I64u %s %s %.2f",
                     position_ticket,position_symbol,str_type,volume);
         //--- imposta un tipo di ordine e invia una richiesta di trade
         if(type==POSITION_TYPE_BUY)
            MarketOrder(ORDER_TYPE_SELL,volume,deviation,magicnumber,position_ticket);
         else
            MarketOrder(ORDER_TYPE_BUY,volume,deviation,magicnumber,position_ticket);
        }
     }
  }
//+------------------------------------------------------------------+
//| Preparare e inviare una richiesta di trade                       |
//+------------------------------------------------------------------+
bool MarketOrder(ENUM_ORDER_TYPE type,double volume,ulong slip,ulong magicnumber,ulong pos_ticket=0)
  {
//--- dichiarare e inizializzare le strutture
   MqlTradeRequest request={};
   MqlTradeResult  result={};
   double price=SymbolInfoDouble(Symbol(),SYMBOL_BID);
   if(type==ORDER_TYPE_BUY)
      price=SymbolInfoDouble(Symbol(),SYMBOL_ASK);
//--- richiesta parametri
   request.action   =TRADE_ACTION_DEAL;                     // tipi di operazioni di trading
   request.position =pos_ticket;                            // ticket della posizione, se chiusura
   request.symbol   =Symbol();                              // symbol
   request.volume   =volume;                                // volume 
   request.type     =type;                                  // tipo di ordine
   request.price    =price;                                 // prezzo di trade
   request.deviation=slip;                                  // deviazione ammissibile dal prezzo
   request.magic    =magicnumber;                           // MagicNumber dell'ordine
//--- invia richiesta
   if(!OrderSend(request,result))
     {
      //--- mostra dati sul fallimento
      PrintFormat("OrderSend %s %s %.2f at %.5f errore %d",
                  request.symbol,EnumToString(type),volume,request.price,GetLastError());
      return (false);
     }
//--- informa di un'operazione riuscita
   PrintFormat("retcode=%u  deal=%I64u  order=%I64u",result.retcode,result.deal,result.order);
   return (true);
  }

Guarda anche

Funzioni di gestione degli eventi, Esecuzione Programma, Eventi del terminale client, OnTimer, OnBookEvent, OnChartEvent