Comments, advices, help on my first EA

sgi.trading
10
sgi.trading  

Hello everybody and thanks in advance for your precious advices and help that i'm sure you would give me.


I'm writing and setting up my first EA, for trading intraday (5-15m timeframe) in different crosses/commodities.

The strategy would be:

- check on long period trend (Moving average in 50 - 100 or more peiods)

- check on short period trend ( Moving average in 5 periods)

- check that we have a real trend (difference between Moving average (long period) in the last 15 periods more than 15 pips)

- if the listed conditions are ok it will open position according to the trend (buy or sell) with the stocastic oscillator signal.


I made it in 2 different versions, one has 1 lot fixed position and StopLoss, Trailing Stop, and Take Profit, settable in the input mask; the other one sets stoploss, takeprofit and trailingstop as parameters of the ATR measured at the moment of the  order send for a fixed inputable maximum loss on each trade.

It looks it works fine and it is doing what im asking to it but during tests on historical data i have conflicting results on both versions, not-ATR-parametrized one has very good results in some years or shorter, very bad in others: best settings i found for 5m time frame are(around):  SL-30pips - Trailing stop starting from +25pips with 4pips band. 

In the one on ATR parameters i find very difficoult to set it to get a final good balance.

Im attaching some examples of the test results on the EA.


This one is 2020 untill now, with fixed 1lot, SL -30pips trailing starting +25pips with 4pips band AND entering in position only if ATR is less than 5.  



 while this happens in 2019-2020 (very different!) with same settings.




Any comment or advice? wrong strategy? wrong stops, wrong timeframe or whatever.

I'll post the EA listing if you think it can help to understand.


Thank you all in advance!

Walter

sgi.trading
10
sgi.trading  

Here i attach the listing of my EA, latest version ATR and NOT-ATR parametrized.


NOT ATR PARAETRIZED

//+------------------------------------------------------------------+
//|                              SGI.TRADING.TRAILING.REV.0.ALFA.mq5 |
//|                                                    Walter Verona |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Walter Verona"
#property link      "https://www.mql5.com"
#property version   "1.00"
//--- input parameters
//          ----------------------------------------------------------------------------input double   TakeProfit=10000; // Take Profit

input char     STOC_periodK=20;
input char     STOC_periodD=5;
input char     STOC_slow=5;
// input double   Period1=5;  //  Periodo corto
input double   Period2=20;  //  Periodo corto
input double   Period3=50;  //  Periodo lungo
input double   piptrend=15;  // Minima distanza tra media ultimi 12 periodi
input char     adxminimo=20;
input char     ATRmax=4; // massimo ATR per entrare
input uint     EA_Magic=12345; // EA Magic Number
input char     lotti=1;  //  numero lotti
input double   stoploss=30;  //  valore stoploss 
input double   takeprofit=40;  //  takeprofit
input double   BandaTrailing=10;  //ampiezza banda del trailing stop
input double   TPvirtuale=30;  //pips a cui scatta il trailingstop
//----Altri  Parametri
int atrHandle;                  // Strumento per gestire l'indicatore ATR
int ma1Handle;                 // Strumento per gestire l'indicatore MA periodo breve
int ma2Handle;                  // Strumento per gestire l'indicatore MA periodo medio
int ma3Handle;                 // Strumento per gestire l'indicatore MA periodo lungo
int stocHandle;                 // Strumento per gestire l'indicatore STOCASTICO
int adxHandle;                 // Strumento per gestire l'indicatore ADX
double ma1Val[], ma2Val[], ma3Val[]; //Array dinamici per contenere i valori di  MEDIA MOBILE MA per ciascuna barra
double stocVal[];                //Array dinamico per contenere i valori dell'OSCILLATORE STOCASTICO di ciascuna barra
double adxVal[];                //Array dinamico per contenere i valori dell'ADX
double atrVal[];                //Array dinamico per contenere i valori dell'ATR
double p_close; //variabile per il presso di chiusira di una barra
double stp;                  //variabile per lo stoploss
double tkp;                  //variabile per il takeprofit
static double prezzo_deal; //per registrare il prezzo del deal acquisto o vendita
bool virtualTP=false  ; //variabile logica per indicare TP raggiunto
MqlTradeRequest mrequest;  // da utilizzare per inviare una richiesta di trade
MqlTradeResult mresult;    // Per verificare il risultato del trade

 //----------------------------------------------------------------------------------------------------- 

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//---Prepariamo lo strumento (Handle) per l'indicatore MACD
//    ma1Handle=iMA(_Symbol,_Period,Period1,0,MODE_SMA,PRICE_CLOSE);
   ma2Handle=iMA(_Symbol,_Period,Period2,0,MODE_SMA,PRICE_CLOSE);
   ma3Handle=iMA(_Symbol,_Period,Period3,0,MODE_SMA,PRICE_CLOSE);
//---Prepariamo lo strumento (Handle) per l'Oscillatore Stocastico
   stocHandle=iStochastic(_Symbol,_Period,STOC_periodK,STOC_periodD,STOC_slow,MODE_SMA,STO_CLOSECLOSE);   
//---Prepariamo lo strumento (Handle) per l'indicatore ADX
   adxHandle=iADX(_Symbol,_Period,14);
//---Prepariamo lo strumento (Handle) per l'indicatore ATR
   atrHandle=iATR(_Symbol,_Period,14);
//---In caso di Handle non validi - Segnalazione di errore
    if(ma1Handle<0 || ma2Handle<0 || ma3Handle<0 || stocHandle<0 || atrHandle<0 || adxHandle<0 )
        { 
        Alert ("Errore nella creazione Handles per gli indici - Errore: ",GetLastError(), "!!!");
        return(INIT_FAILED);
        } 
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//---Rilasciamo gli Handles degli indicatori
//  IndicatorRelease(ma1Handle);
 IndicatorRelease(ma2Handle);
 IndicatorRelease(ma3Handle);
 // IndicatorRelease(atrHandle); 
 IndicatorRelease(stocHandle);
 IndicatorRelease(adxHandle);
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
//---------------------RICHIAMO FUNZIONE TRAILING STOP SE POSIZIONI APERTE-----------------
if(PositionSelect(_Symbol) ==true) //---abbiamo una posizione aperta
       {
        trailing(stoploss);
        }
//------------------------------------------------------------------------------------------

//---Verifichiamo se abbiamo abbastanza Barre (60) per la valuta ed il periodo di riferimento
   if(Bars(_Symbol,_Period)<60)
       {
       Alert ("Abbiamo meno di 60 Barre - l'EA uscirà !!!");
       return;
       }
 //Usiamo la variabile statica Old_Time per salvare il momento dell'ultima barra
 //Ad ogni esecuzione OnTick confronteremo il momento di formazione dell'ultima barra con quello salvato
 //Se il tempo della nuova barra non è lo stesso di quello salvato significa che abbiamo un nuovo tick.
   static datetime Old_Time;
   datetime New_Time[1];
   bool IsNewBar=false;
 
 //Copiamo l'istante dell'ultima barra sull'elemento NewTime[0]
   int copied=CopyTime(_Symbol,_Period,0,1,New_Time);
   if(copied>0) // OK i dati sono stati copiati correttamente
         {
          if(Old_Time!=New_Time[0]) // Se OldTime non è uguale al tempo dell'ultima barra
              {
              IsNewBar=true; // se non è la prima chiamata della funzione vuol dire che si è formata una nuova barra
              if(MQL5InfoInteger(MQL5_DEBUGGING)) Print ("Abbiamo una nuova barra qua ",New_Time[0],"la precedente era ",Old_Time);
              Old_Time=New_Time[0];
              }
          }
   else
         {
          Alert ("Errore nella copia dei dati storici delle barre",GetLastError());
          ResetLastError();
          return;
          }
 //----L'EA verifica possibilita' di nuovi trade solo se c'è una nuova barra
    if(IsNewBar==false)
       {
        return;
       }
//----Abbiamo abbastanza barre (60)?
    int Mybars=Bars(_Symbol,_Period);
    if (Mybars<60) //Se le barre totali sono meno di 60
       {
        Alert("Ci sono meno di 60 Barre,(",Mybars,") l'EA uscirà!!!");
        return;
       }
//---Definiamo alcune variabili con strutture MQL5 da usare nel nostro Trade
   MqlTick latest_price;      // da usare per ricevere i più recenti o ultimi prezzi o quotazioni
   MqlRates mrate[];          // per conservare i prezzi, i volumi e gli spread di ciascuna barra
   ZeroMemory (mrequest);     // inizializzazione della struttura mrequest 
//----Accertiamoci che i valori degli Array per Rates, ADX e MA siano conservati in sequenza simile agli array timeseries
//----dal dato più recente (pos. [0]) a quello più vecchio
// Array dei Valori (Rates)
// Array valori MA
// ArraySetAsSeries(ma1Val,true);
ArraySetAsSeries(ma2Val,true);
ArraySetAsSeries(ma3Val,true);
// Array valori Stocastico
ArraySetAsSeries(stocVal,true);  
//-----Prendiamo l'ultimo valore del prezzo usando la funzione MQL5 MqlTick
if(!SymbolInfoTick(_Symbol,latest_price))
       {
        Alert("Errore nel caricamento dell'ultimo prezzo - errore ",GetLastError(),"!!!");
        return;
       }
//----Carichiamo i valori (prezzo iniziale finale massimo minimo volume etc) delle ultime 3 barre
if(CopyRates(_Symbol,_Period,0,3,mrate)<0)
       {
        Alert("Errore nel caricamento dei valori/dati storici delle barre - Errore: ",GetLastError()," !!!");
       return;
       }
 //----Copiamo i valori degli indicatori nei buffer (arrays) utilizzando gli handles (che avevamo preparato in Oninit)
   if(CopyBuffer(ma2Handle,0,0,2,ma2Val)<0 || CopyBuffer(ma3Handle,0,0,Period3,ma3Val)<0)
       {
        Alert("Errore nel copiare i Buffer degli indicatori MA - Errore ",GetLastError()," !!!");
        return;
       }
//----Copiamo i valori dello stocastico nel buffer (arrays) utilizzando l'handle (che avevamo preparato in Oninit)
   if(CopyBuffer(stocHandle,0,0,3,stocVal)<0)
       {
        Alert("Errore nel copiare i Buffer dello STOCASTICO - Errore ",GetLastError()," !!!");
        return;
       }
//----Copiamo i valori ADX nel buffer (arrays) utilizzando l'handle (che avevamo preparato in Oninit)
   if(CopyBuffer(adxHandle,0,0,1,adxVal)<0)
       {
        Alert("Errore nel copiare i Buffer del'ADX - Errore ",GetLastError()," !!!");
        return;
       }
//----Copiamo i valori ATR nel buffer (arrays) utilizzando l'handle (che avevamo preparato in Oninit)
   if(CopyBuffer(atrHandle,0,0,1,atrVal)<0)
       {
        Alert("Errore nel copiare i Buffer del'ATR - Errore ",GetLastError()," !!!");
        return;
       }           
 //---se siamo qui nessun errore di copia dati quindi continuiamo
 //---Verifichiamo se abbiamo posizioni già aperte
       bool Buy_opened=false; //---Variabile per contenere il risultato di eventuali posizioni BUY aperte
       bool Sell_opened=false; //---Variabile per contenere il risultato di eventuali posizioni SELL aperte
       if(PositionSelect(_Symbol) ==true) //---abbiamo una posizione aperta
         {
          if(PositionGetInteger(POSITION_TYPE)==POSITION_TYPE_BUY)
            {
              Buy_opened=true; //--- abbiamo una posizione BUY aperta
             }
          else if(PositionGetInteger(POSITION_TYPE)==POSITION_TYPE_SELL)
             {
              Sell_opened=true; //---abbiamo una posizione SELL aperta
              }
         }
  //---Copiamo il prezzo di chiusura della barra precedente all'attuale(0), ovvero della barra 1.
     p_close=mrate[1].close; // prezzo di chiusura della barra 1.
 
 /*  ------------ VERIFICA CONDIZIONI
       BUY verifichiamo la presenza di condizione Long/Buy:
       1) 
       2)  
       3)  
       4)  Stocastico della barra precedente <20 
       5)  Stocastico dell'ultima barra>20 
       
 */
// Dichiariamo le variabili bool per mantenere le nostre condizioni Buy
    bool Buy_Condition_1 =  ((atrVal[0]*10000)<ATRmax); // (ma1Val[0]>ma1Val[1]);
    bool Buy_Condition_2 =  (ma2Val[0]>ma2Val[1]);
    bool Buy_Condition_3 =  (ma3Val[0]>ma3Val[1]) && (((ma3Val[0]-ma3Val[11])*100000)>piptrend);
    bool Buy_Condition_4 = (adxVal[0]>adxminimo); 
    bool Buy_Condition_5 = ((stocVal[2]<20) && (stocVal[1]>20) && (stocVal[0]>20));
    bool Buy_Condition_6 = ((stocVal[1]<20) && (stocVal[0]>20));
//--riassumendo le condizioni:
  if(Buy_Condition_1 && Buy_Condition_2)
   {
    if(Buy_Condition_3 && Buy_Condition_4)
       {
        if(Buy_Condition_5 || Buy_Condition_6)
        // - CONDIZIONI BUY PRESENTI 
           {
               //--posizioni BUY già aperte?
            if(Buy_opened)
                 {
                  Alert("Condizioni BUY presenti ma posizione BUY già aperta!!!");
                  return; //--Non apre posizione Buy
                 }
             else if(Sell_opened)
                 { Alert("Condizioni BUY presenti ma posizione SELL già aperta!!!");
                  return; //--Non apre posizione Buy                                      ---------------PROVO A NON FARGLI APRIRE POSIZIONI SELL CON BUY APERTI
                  }
       //------verifiche OK per posizione BUY --- Apriamo posizione!
       
   
      //-----------------------------------------------------------------------------------
            
       //------ORDINE
            
            
            stp = stoploss;
            tkp = takeprofit;
            if(Digits()==3||5)
                {
                 stp = stp*10;
                 tkp = tkp*10;
                 }   
            Print("STOPLOSS   ", stp, "Punti. - TAKE PROFIT VIRTUALE   ", TPvirtuale );
            mrequest.action = TRADE_ACTION_DEAL;    // Richiesta ordine immediato
            mrequest.price =  NormalizeDouble(latest_price.ask,_Digits); //all'ultimo prezzo di vendita
            mrequest.sl = NormalizeDouble(latest_price.ask - stp*_Point,_Digits); // Imposto Stop Loss
            mrequest.tp = NormalizeDouble(latest_price.ask + tkp*_Point,_Digits); // Imposto takeprofit
            mrequest.symbol = _Symbol;                                            // Coppia di valute del grafico
            mrequest.volume = lotti;                                               // Numero di Lotti da scambiare
            mrequest.magic = EA_Magic;                                           // Magic Number dell'Ordine
            mrequest.type = ORDER_TYPE_BUY;                                      // tipo di ordine BUY
            mrequest.type_filling = ORDER_FILLING_IOC;                           // Tipo di esecuzione dell'ordine (in questo caso esegue l'ordine solo PER LA QUANTITA' DISPONIBILE)
            mrequest.deviation = 100;                                            // variazione di prezzo massima ammissibile dal prezzo attuale
        
        
        //-----INVIO ORDINE
            OrderSend(mrequest,mresult);
        //--- verifica buon esito ordine
        if(mresult.retcode==10009 || mresult.retcode==10008) // Richiesta completa o ordine eseguito
           {
            Alert("Un ordine BUY è stato compiuto con successo con Ticket N.:",mresult.order,"!!!");
           prezzo_deal = NormalizeDouble(mresult.price,_Digits);    //-----memorizzo il prezzo del deal nella variabile static prezzo_deal
           virtualTP=false;  //-----setto a zero il virtual TP
           }
        else
           {
            Alert("Non è stato possibile eseguire l'ordine BUY richiesto - Errore:",GetLastError());
            ResetLastError();
            return;
            }
         }
        } 
       } 
           
/*  ------------ VERIFICA CONDIZIONI SELL verifichiamo la presenza di condizione Short/Sell:
       1)  MACD day<0
       2)  MACD 4h<0
       3)  MACD 1h<0
       4)  Stocastico della barra precedente >80 
       5)  Stocastico dell'ultima barra<80 
       
 */
// Dichiariamo le variabili bool per mantenere le nostre condizioni Sell
    bool Sell_Condition_1 = ((atrVal[0]*10000)<ATRmax); // (ma1Val[0]<ma1Val[1]);
    bool Sell_Condition_2 = (ma2Val[0]<ma2Val[1]);
    bool Sell_Condition_3 = (ma3Val[0]<ma3Val[1]) && (((ma3Val[11]-ma3Val[0])*100000)>piptrend);
    bool Sell_Condition_4 = (adxVal[0]>adxminimo); 
    bool Sell_Condition_5 = ((stocVal[2]>80) && (stocVal[1]<80) && (stocVal[0]<80));
    bool Sell_Condition_6 = ((stocVal[1]>80) && (stocVal[0]<80));
   
//--riassumendo le condizioni:
  if(Sell_Condition_1 && Sell_Condition_2)
   {
    if(Sell_Condition_3 && Sell_Condition_4)
       {
        if(Sell_Condition_5 || Sell_Condition_6)
        // - CONDIZIONI SELL PRESENTI 
         {
          // ci sono già posizioni SELL aperte?
          if(Sell_opened)
            {
             Alert("Condizioni SELL presenti ma posizione SELL già aperta!!!");
             return;   // non apre una nuova posizione SELL
            }
          else if(Buy_opened)
                 { Alert("Condizioni SELL presenti ma posizione BUY già aperta!!!");
                  return; //--Non apre posizione Buy                                      ---------------PROVO A NON FARGLI APRIRE POSIZIONI SELL CON BUY APERTI
                  }
        //------verifiche OK per posizione SELL --- Apriamo posizione!
        
       
            
       //------ORDINE
           
            stp = stoploss;
            tkp = takeprofit;
            if(Digits()==3||5)
                {
                 stp = stp*10;
                 tkp = tkp*10;
                 }   
            Print("STOPLOSS   ", stp, "Punti. - TAKE PROFIT VIRTUALE   ", TPvirtuale );
            mrequest.action = TRADE_ACTION_DEAL;    // Richiesta ordine immediato
            mrequest.price =  NormalizeDouble(latest_price.bid,_Digits); //all'ultimo prezzo di vendita
            mrequest.sl = NormalizeDouble(latest_price.bid + stp*_Point,_Digits); // Imposto Stop Loss
            mrequest.tp = NormalizeDouble(latest_price.bid - tkp*_Point,_Digits); // Imposto takeprofit
            mrequest.symbol = _Symbol;                                            // Coppia di valute del grafico
            mrequest.volume = lotti;                                               // Numero di Lotti da scambiare
            mrequest.magic = EA_Magic;                                           // Magic Number dell'Ordine
            mrequest.type = ORDER_TYPE_SELL;                                      // tipo di ordine SELL
            mrequest.type_filling = ORDER_FILLING_IOC;                           // Tipo di esecuzione dell'ordine (in questo caso esegue l'ordine solo PER LA QUANTITA' DISPONIBILE)
            mrequest.deviation = 100;                                            // variazione di prezzo massima ammissibile dal prezzo attuale
        
        
        //-----INVIO ORDINE
            OrderSend(mrequest,mresult);
        //--- verifica buon esito ordine
        if(mresult.retcode==10009 || mresult.retcode==10008) // Richiesta completa o ordine eseguito
           {
            Alert("Un ordine SELL è stato compiuto con successo con Ticket N.:",mresult.order,"!!!");
           prezzo_deal = NormalizeDouble(mresult.price,_Digits);    //-----memorizzo il prezzo del deal nella variabile static prezzo_deal
           virtualTP=false;  //-----setto a zero il virtual TP
           } 
        else
           {
            Alert("Non è stato possibile eseguire l'ordine SELL richiesto - Errore:",GetLastError());
            ResetLastError();
            return;
            }                
         }     
        }
 
     }  
          
       
  
                                                
  }
//----------------------------------TRAILING STOP -----------------------------  
// stoploss=30;  //  valore stoploss 
// takeprofit=80;  //  takeprofit
// BandaTrailing=10;  //ampiezza banda del trailing stop
// TPvirtuale=30;  //pips a cui scatta il trailingstop

void trailing(int trailstop)
 {
  double stop;
  double take;
  double VirTP=TPvirtuale;
  double trail=BandaTrailing;
  if(Digits()==3||5)
   {
   trail = trail*10;
   VirTP = VirTP*10;
   } 
   ulong ticket=PositionGetTicket(0);// ticket of the position
  
//TRAILING PER POSIZIONE LONG //   
  if(PositionSelect(Symbol())==true && PositionGetInteger(POSITION_TYPE)==POSITION_TYPE_BUY)
   {
    stop = PositionGetDouble(POSITION_SL);
    take = PositionGetDouble(POSITION_TP);

    if((SymbolInfoDouble(Symbol(),SYMBOL_ASK))-prezzo_deal>VirTP*Point())
    {
     if(SymbolInfoDouble(Symbol(),SYMBOL_ASK)-trail*Point()>stop)
     {
      mrequest.sl = SymbolInfoDouble(Symbol(),SYMBOL_ASK)-trail*Point();
      mrequest.tp = take;
      mrequest.action = TRADE_ACTION_SLTP;
      mrequest.deviation = 0;
      mrequest.symbol = Symbol();
      mrequest.position=ticket;   // ticket of the position
      if(OrderSend(mrequest,mresult)==false)
       Print("Non è stato possibile modificare StopLoss #",GetLastError());
     }
    }
   }
 
 //TRAILING PER POSIZIONE SHORT //
  if(PositionSelect(Symbol())==true && PositionGetInteger(POSITION_TYPE)==POSITION_TYPE_SELL)
   {
    stop = PositionGetDouble(POSITION_SL);
    take = PositionGetDouble(POSITION_TP);
    
   if(prezzo_deal-(SymbolInfoDouble(Symbol(),SYMBOL_BID))>VirTP*Point())
    {
    if(SymbolInfoDouble(Symbol(),SYMBOL_BID)+trail*Point()<stop)
     {
      mrequest.sl = SymbolInfoDouble(Symbol(),SYMBOL_BID)+trail*Point();
      mrequest.tp = take;
      mrequest.action = TRADE_ACTION_SLTP;
      mrequest.deviation = 0;
      mrequest.symbol = Symbol();
      mrequest.position=ticket;   // ticket of the position
      if(OrderSend(mrequest,mresult)==false)
       Print("Non è stato possibile modificare StopLoss #",GetLastError());
     }
    }
   }
 }
//+------------------------------------------------------------------+
Discover new MetaTrader 5 opportunities with MQL5 community and services
Discover new MetaTrader 5 opportunities with MQL5 community and services
  • www.mql5.com
FrankoScalp MT5 I have been developing, testing and correcting this automated scalping system for a long time:  https://www.mql5.com/en/signals/author/test-standart . Last sets in comments: #33 🛑  My telegram channel:   https://t.me/EAFXPRO Highlights to pay attention to 1.  During live operation of the expert the GMT offset parameter is...
sgi.trading
10
sgi.trading  

ATR PARAMETRIZED


//+------------------------------------------------------------------+
//|                              SGI.TRADING.TRAILING.REV.0.ALFA.mq5 |
//|                                                    Walter Verona |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Walter Verona"
#property link      "https://www.mql5.com"
#property version   "1.00"
//--- input parameters
//          ----------------------------------------------------------------------------input double   TakeProfit=10000; // Take Profit

input char     STOC_periodK=20;
input char     STOC_periodD=5;
input char     STOC_slow=5;
// input double   Period1=5;  //  Periodo corto
input double   Period2=5;  //  Periodo corto
input double   Period3=50;  //  Periodo lungo
input double   piptrend=15;  // Minima distanza tra media ultimi 12 periodi
input char     adxminimo=1;
input char     ATRmax=4; // massimo ATR per entrare
input uint     EA_Magic=12345; // EA Magic Number
input double   PerditaMAX=200;  // perdita massima su ogni trade  
double lotti;   //  numero lotti
input double     coeffATRsl=3;  //  coefficiente dell'ATR per fissare lo stoploss 
input double     coeffATRtp=2.8;  //  coefficiente dell'ATR per fissare il Takeprofit virtuale 
input double     coeffATRbandaTS=0.2;  //ampiezza banda del trailing stop
input double     coeffATRTake=4;  // coefficiente dell'ATR per fissare il Takeprofit fisso 
double takeprofit;
double stoploss;
double BandaTrailing;
double TPvirtuale;
// input double   TPvirtuale=30;  //pips a cui scatta il trailingstop
//----Altri  Parametri
int atrHandle;                  // Strumento per gestire l'indicatore ATR
int ma1Handle;                 // Strumento per gestire l'indicatore MA periodo breve
int ma2Handle;                  // Strumento per gestire l'indicatore MA periodo medio
int ma3Handle;                 // Strumento per gestire l'indicatore MA periodo lungo
int stocHandle;                 // Strumento per gestire l'indicatore STOCASTICO
int adxHandle;                 // Strumento per gestire l'indicatore ADX
double ma1Val[], ma2Val[], ma3Val[]; //Array dinamici per contenere i valori di  MEDIA MOBILE MA per ciascuna barra
double stocVal[];                //Array dinamico per contenere i valori dell'OSCILLATORE STOCASTICO di ciascuna barra
double adxVal[];                //Array dinamico per contenere i valori dell'ADX
double atrVal[];                //Array dinamico per contenere i valori dell'Atr

double p_close; //variabile per il presso di chiusira di una barra
double stp;                  //variabile per lo stoploss
double tkp;                  //variabile per il takeprofit
static double prezzo_deal; //per registrare il prezzo del deal acquisto o vendita
MqlTradeRequest mrequest;  // da utilizzare per inviare una richiesta di trade
MqlTradeResult mresult;    // Per verificare il risultato del trade

 //----------------------------------------------------------------------------------------------------- 

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//---Prepariamo lo strumento (Handle) per l'indicatore MACD
//    ma1Handle=iMA(_Symbol,_Period,Period1,0,MODE_SMA,PRICE_CLOSE);
   ma2Handle=iMA(_Symbol,_Period,Period2,0,MODE_SMA,PRICE_CLOSE);
   ma3Handle=iMA(_Symbol,_Period,Period3,0,MODE_SMA,PRICE_CLOSE);
//---Prepariamo lo strumento (Handle) per l'Oscillatore Stocastico
   stocHandle=iStochastic(_Symbol,_Period,STOC_periodK,STOC_periodD,STOC_slow,MODE_SMA,STO_CLOSECLOSE);   
//---Prepariamo lo strumento (Handle) per l'indicatore ADX
   adxHandle=iADX(_Symbol,_Period,14);
//---Prepariamo lo strumento (Handle) per l'indicatore ATR
   atrHandle=iATR(_Symbol,_Period,14);
//---In caso di Handle non validi - Segnalazione di errore
    if(ma1Handle<0 || ma2Handle<0 || ma3Handle<0 || stocHandle<0 || atrHandle<0 || adxHandle<0 )
        { 
        Alert ("Errore nella creazione Handles per gli indici - Errore: ",GetLastError(), "!!!");
        return(INIT_FAILED);
        } 
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//---Rilasciamo gli Handles degli indicatori
//  IndicatorRelease(ma1Handle);
 IndicatorRelease(ma2Handle);
 IndicatorRelease(ma3Handle);
 IndicatorRelease(atrHandle); 
 IndicatorRelease(stocHandle);
 IndicatorRelease(adxHandle);
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
//---------------------RICHIAMO FUNZIONE TRAILING STOP SE POSIZIONI APERTE-----------------
if(PositionSelect(_Symbol) ==true) //---abbiamo una posizione aperta
       {
        trailing(stoploss);
        }
//------------------------------------------------------------------------------------------

//---Verifichiamo se abbiamo abbastanza Barre (60) per la valuta ed il periodo di riferimento
   if(Bars(_Symbol,_Period)<60)
       {
       Alert ("Abbiamo meno di 60 Barre - l'EA uscirà !!!");
       return;
       }
 //Usiamo la variabile statica Old_Time per salvare il momento dell'ultima barra
 //Ad ogni esecuzione OnTick confronteremo il momento di formazione dell'ultima barra con quello salvato
 //Se il tempo della nuova barra non è lo stesso di quello salvato significa che abbiamo un nuovo tick.
   static datetime Old_Time;
   datetime New_Time[1];
   bool IsNewBar=false;
 
 //Copiamo l'istante dell'ultima barra sull'elemento NewTime[0]
   int copied=CopyTime(_Symbol,_Period,0,1,New_Time);
   if(copied>0) // OK i dati sono stati copiati correttamente
         {
          if(Old_Time!=New_Time[0]) // Se OldTime non è uguale al tempo dell'ultima barra
              {
              IsNewBar=true; // se non è la prima chiamata della funzione vuol dire che si è formata una nuova barra
              if(MQL5InfoInteger(MQL5_DEBUGGING)) Print ("Abbiamo una nuova barra qua ",New_Time[0],"la precedente era ",Old_Time);
              Old_Time=New_Time[0];
              }
          }
   else
         {
          Alert ("Errore nella copia dei dati storici delle barre",GetLastError());
          ResetLastError();
          return;
          }
 //----L'EA verifica possibilita' di nuovi trade solo se c'è una nuova barra
    if(IsNewBar==false)
       {
        return;
       }
//----Abbiamo abbastanza barre (60)?
    int Mybars=Bars(_Symbol,_Period);
    if (Mybars<60) //Se le barre totali sono meno di 60
       {
        Alert("Ci sono meno di 60 Barre,(",Mybars,") l'EA uscirà!!!");
        return;
       }
//---Definiamo alcune variabili con strutture MQL5 da usare nel nostro Trade
   MqlTick latest_price;      // da usare per ricevere i più recenti o ultimi prezzi o quotazioni
   MqlRates mrate[];          // per conservare i prezzi, i volumi e gli spread di ciascuna barra
   ZeroMemory (mrequest);     // inizializzazione della struttura mrequest 
//----Accertiamoci che i valori degli Array per Rates, ADX e MA siano conservati in sequenza simile agli array timeseries
//----dal dato più recente (pos. [0]) a quello più vecchio
// Array dei Valori (Rates)
// Array valori MA
// ArraySetAsSeries(ma1Val,true);
ArraySetAsSeries(ma2Val,true);
ArraySetAsSeries(ma3Val,true);
// Array valori Stocastico
ArraySetAsSeries(stocVal,true);  
//-----Prendiamo l'ultimo valore del prezzo usando la funzione MQL5 MqlTick
if(!SymbolInfoTick(_Symbol,latest_price))
       {
        Alert("Errore nel caricamento dell'ultimo prezzo - errore ",GetLastError(),"!!!");
        return;
       }
//----Carichiamo i valori (prezzo iniziale finale massimo minimo volume etc) delle ultime 3 barre
if(CopyRates(_Symbol,_Period,0,3,mrate)<0)
       {
        Alert("Errore nel caricamento dei valori/dati storici delle barre - Errore: ",GetLastError()," !!!");
       return;
       }
 //----Copiamo i valori degli indicatori nei buffer (arrays) utilizzando gli handles (che avevamo preparato in Oninit)
   if(CopyBuffer(ma2Handle,0,0,2,ma2Val)<0 || CopyBuffer(ma3Handle,0,0,Period3,ma3Val)<0)
       {
        Alert("Errore nel copiare i Buffer degli indicatori MA - Errore ",GetLastError()," !!!");
        return;
       }
//----Copiamo i valori dello stocastico nel buffer (arrays) utilizzando l'handle (che avevamo preparato in Oninit)
   if(CopyBuffer(stocHandle,0,0,3,stocVal)<0)
       {
        Alert("Errore nel copiare i Buffer dello STOCASTICO - Errore ",GetLastError()," !!!");
        return;
       }
//----Copiamo i valori ADX nel buffer (arrays) utilizzando l'handle (che avevamo preparato in Oninit)
   if(CopyBuffer(adxHandle,0,0,1,adxVal)<0)
       {
        Alert("Errore nel copiare i Buffer del'ADX - Errore ",GetLastError()," !!!");
        return;
       }
//----Copiamo i valori ATR nel buffer (arrays) utilizzando l'handle (che avevamo preparato in Oninit)
   if(CopyBuffer(atrHandle,0,0,1,atrVal)<0)
       {
        Alert("Errore nel copiare i Buffer del'ATR - Errore ",GetLastError()," !!!");
        return;
       }              
 //---se siamo qui nessun errore di copia dati quindi continuiamo
 //---Verifichiamo se abbiamo posizioni già aperte
       bool Buy_opened=false; //---Variabile per contenere il risultato di eventuali posizioni BUY aperte
       bool Sell_opened=false; //---Variabile per contenere il risultato di eventuali posizioni SELL aperte
       if(PositionSelect(_Symbol) ==true) //---abbiamo una posizione aperta
         {
          if(PositionGetInteger(POSITION_TYPE)==POSITION_TYPE_BUY)
            {
              Buy_opened=true; //--- abbiamo una posizione BUY aperta
             }
          else if(PositionGetInteger(POSITION_TYPE)==POSITION_TYPE_SELL)
             {
              Sell_opened=true; //---abbiamo una posizione SELL aperta
              }
         }
  //---Copiamo il prezzo di chiusura della barra precedente all'attuale(0), ovvero della barra 1.
     p_close=mrate[1].close; // prezzo di chiusura della barra 1.
 
 /*  ------------ VERIFICA CONDIZIONI
       BUY verifichiamo la presenza di condizione Long/Buy:
       1) 
       2)  
       3)  
       4)  Stocastico della barra precedente <20 
       5)  Stocastico dell'ultima barra>20 
       
 */
// Dichiariamo le variabili bool per mantenere le nostre condizioni Buy
    bool Buy_Condition_1 =  ((atrVal[0]*10000)<ATRmax); // (ma1Val[0]>ma1Val[1]);
    bool Buy_Condition_2 =  (ma2Val[0]>ma2Val[1]);
    bool Buy_Condition_3 =  (ma3Val[0]>ma3Val[1]) && (((ma3Val[0]-ma3Val[11])*100000)>piptrend);
    bool Buy_Condition_4 = (adxVal[0]>adxminimo); 
    bool Buy_Condition_5 = ((stocVal[2]<20) && (stocVal[1]>20) && (stocVal[0]>20));
    bool Buy_Condition_6 = ((stocVal[1]<20) && (stocVal[0]>20));
//--riassumendo le condizioni:
  if(Buy_Condition_1 && Buy_Condition_2)
   {
    if(Buy_Condition_3 && Buy_Condition_4)
       {
        if(Buy_Condition_5 || Buy_Condition_6)
        // - CONDIZIONI BUY PRESENTI 
           {
               //--posizioni BUY già aperte?
            if(Buy_opened)
                 {
                  Alert("Condizioni BUY presenti ma posizione BUY già aperta!!!");
                  return; //--Non apre posizione Buy
                 }
             else if(Sell_opened)
                 { Alert("Condizioni BUY presenti ma posizione SELL già aperta!!!");
                  return; //--Non apre posizione Buy                                      ---------------PROVO A NON FARGLI APRIRE POSIZIONI SELL CON BUY APERTI
                  }
 //------verifiche OK per POSIZIONE BUY --- Apriamo posizione!
      //-- DIMENSIONAMENTO POSIZIONEBUY       
 
            stoploss=NormalizeDouble(coeffATRsl*(atrVal[0]*10000),0);
            TPvirtuale=NormalizeDouble(coeffATRtp*(atrVal[0]*10000),0);
            BandaTrailing=NormalizeDouble(coeffATRbandaTS*(atrVal[0]*10000),0);
            takeprofit=NormalizeDouble(coeffATRTake*(atrVal[0]*10000),0);
            stp = stoploss;
            tkp = takeprofit;
            if(Digits()==3||5)
                {
                 stp = stp*10;
                 tkp = tkp*10;
                 }   
        
            //------ORDINE BUY
            mrequest.action = TRADE_ACTION_DEAL;    // Richiesta ordine immediato
            mrequest.price =  NormalizeDouble(latest_price.ask,_Digits); //all'ultimo prezzo di vendita
            mrequest.sl = NormalizeDouble(latest_price.ask - stp*_Point,_Digits); // Imposto Stop Loss
            mrequest.tp = NormalizeDouble(latest_price.ask + tkp*_Point,_Digits); // Imposto takeprofit
            mrequest.symbol = _Symbol;                                            // Coppia di valute del grafico
            lotti = NormalizeDouble((PerditaMAX*latest_price.ask)/stp,2);
            mrequest.volume = lotti;                                               // Numero di Lotti da scambiare
            mrequest.magic = EA_Magic;                                           // Magic Number dell'Ordine
            mrequest.type = ORDER_TYPE_BUY;                                      // tipo di ordine BUY
            mrequest.type_filling = ORDER_FILLING_IOC;                           // Tipo di esecuzione dell'ordine (in questo caso esegue l'ordine solo PER LA QUANTITA' DISPONIBILE)
            mrequest.deviation = 100;                                            // variazione di prezzo massima ammissibile dal prezzo attuale
        
        
        //-----INVIO ORDINE
            OrderSend(mrequest,mresult);
        //--- verifica buon esito ordine
        if(mresult.retcode==10009 || mresult.retcode==10008) // Richiesta completa o ordine eseguito
           {
            Alert("Un ordine BUY è stato compiuto con successo con Ticket N.:",mresult.order,"!!!");
           prezzo_deal = NormalizeDouble(mresult.price,_Digits);    //-----memorizzo il prezzo del deal nella variabile static prezzo_deal
           }
        else
           {
            Alert("Non è stato possibile eseguire l'ordine BUY richiesto - Errore:",GetLastError());
            ResetLastError();
            return;
            }
         }
        } 
       } 
           
/*  ------------ VERIFICA CONDIZIONI SELL verifichiamo la presenza di condizione Short/Sell:
       1)  MACD day<0
       2)  MACD 4h<0
       3)  MACD 1h<0
       4)  Stocastico della barra precedente >80 
       5)  Stocastico dell'ultima barra<80 
       
 */
// Dichiariamo le variabili bool per mantenere le nostre condizioni Sell
    bool Sell_Condition_1 = ((atrVal[0]*10000)<ATRmax); // (ma1Val[0]<ma1Val[1]);
    bool Sell_Condition_2 = (ma2Val[0]<ma2Val[1]);
    bool Sell_Condition_3 = (ma3Val[0]<ma3Val[1]) && (((ma3Val[11]-ma3Val[0])*100000)>piptrend);
    bool Sell_Condition_4 = (adxVal[0]>adxminimo); 
    bool Sell_Condition_5 = ((stocVal[2]>80) && (stocVal[1]<80) && (stocVal[0]<80));
    bool Sell_Condition_6 = ((stocVal[1]>80) && (stocVal[0]<80));
   
//--riassumendo le condizioni:
  if(Sell_Condition_1 && Sell_Condition_2)
   {
    if(Sell_Condition_3 && Sell_Condition_4)
       {
        if(Sell_Condition_5 || Sell_Condition_6)
        // - CONDIZIONI SELL PRESENTI 
         {
          // ci sono già posizioni SELL aperte?
          if(Sell_opened)
            {
             Alert("Condizioni SELL presenti ma posizione SELL già aperta!!!");
             return;   // non apre una nuova posizione SELL
            }
          else if(Buy_opened)
                 { Alert("Condizioni SELL presenti ma posizione BUY già aperta!!!");
                  return; //--Non apre posizione Buy                                      ---------------PROVO A NON FARGLI APRIRE POSIZIONI SELL CON BUY APERTI
                  }
        //------verifiche OK per posizione SELL --- Apriamo posizione!
        
       
            
       //------ORDINE
           stoploss=NormalizeDouble(coeffATRsl*(atrVal[0]*10000),0);
           TPvirtuale=NormalizeDouble(coeffATRtp*(atrVal[0]*10000),0);
           BandaTrailing=NormalizeDouble(coeffATRbandaTS*(atrVal[0]*10000),0); 
           takeprofit=NormalizeDouble(coeffATRTake*(atrVal[0]*10000),0);
            stp = stoploss;
            tkp = takeprofit;
            if(Digits()==3||5)
                {
                 stp = stp*10;
                 tkp = tkp*10;
                 }   
            Print("STOPLOSS   ", stp, "Punti. - TAKE PROFIT VIRTUALE   ", TPvirtuale );
            mrequest.action = TRADE_ACTION_DEAL;    // Richiesta ordine immediato
            mrequest.price =  NormalizeDouble(latest_price.bid,_Digits); //all'ultimo prezzo di vendita
            mrequest.sl = NormalizeDouble(latest_price.bid + stp*_Point,_Digits); // Imposto Stop Loss
            mrequest.tp = NormalizeDouble(latest_price.bid - tkp*_Point,_Digits); // Imposto takeprofit
            mrequest.symbol = _Symbol;                                            // Coppia di valute del grafico
            lotti = NormalizeDouble((PerditaMAX*latest_price.ask)/stp,2);
            mrequest.volume = lotti;                                               // Numero di Lotti da scambiare
            mrequest.magic = EA_Magic;                                           // Magic Number dell'Ordine
            mrequest.type = ORDER_TYPE_SELL;                                      // tipo di ordine SELL
            mrequest.type_filling = ORDER_FILLING_IOC;                           // Tipo di esecuzione dell'ordine (in questo caso esegue l'ordine solo PER LA QUANTITA' DISPONIBILE)
            mrequest.deviation = 100;                                            // variazione di prezzo massima ammissibile dal prezzo attuale
        
        
        //-----INVIO ORDINE
            OrderSend(mrequest,mresult);
        //--- verifica buon esito ordine
        if(mresult.retcode==10009 || mresult.retcode==10008) // Richiesta completa o ordine eseguito
           {
            Alert("Un ordine SELL è stato compiuto con successo con Ticket N.:",mresult.order,"!!!");
           prezzo_deal = NormalizeDouble(mresult.price,_Digits);    //-----memorizzo il prezzo del deal nella variabile static prezzo_deal
           } 
        else
           {
            Alert("Non è stato possibile eseguire l'ordine SELL richiesto - Errore:",GetLastError());
            ResetLastError();
            return;
            }                
         }     
        }
 
     }  
          
       
  
                                                
  }
//----------------------------------TRAILING STOP -----------------------------  
// stoploss=30;  //  valore stoploss 
// takeprofit=80;  //  takeprofit
// BandaTrailing=10;  //ampiezza banda del trailing stop
// TPvirtuale=30;  //pips a cui scatta il trailingstop

void trailing(int trailstop)
 {
  double stop;
  double take;
  double VirTP=TPvirtuale;
  double trail=BandaTrailing;
  if(Digits()==3||5)
   {
   trail = trail*10;
   VirTP = VirTP*10;
   } 
   ulong ticket=PositionGetTicket(0);// ticket of the position
  
//TRAILING PER POSIZIONE LONG //   
  if(PositionSelect(Symbol())==true && PositionGetInteger(POSITION_TYPE)==POSITION_TYPE_BUY)
   {
    stop = PositionGetDouble(POSITION_SL);
    take = PositionGetDouble(POSITION_TP);

    if((SymbolInfoDouble(Symbol(),SYMBOL_ASK))-prezzo_deal>VirTP*Point())
    {
     if(SymbolInfoDouble(Symbol(),SYMBOL_ASK)-trail*Point()>stop)
     {
      mrequest.sl = SymbolInfoDouble(Symbol(),SYMBOL_ASK)-trail*Point();
      mrequest.tp = take;
      mrequest.action = TRADE_ACTION_SLTP;
      mrequest.deviation = 0;
      mrequest.symbol = Symbol();
      mrequest.position=ticket;   // ticket of the position
      if(OrderSend(mrequest,mresult)==false)
       Print("Non è stato possibile modificare StopLoss #",GetLastError());
     }
    }
   }
 
 //TRAILING PER POSIZIONE SHORT //
  if(PositionSelect(Symbol())==true && PositionGetInteger(POSITION_TYPE)==POSITION_TYPE_SELL)
   {
    stop = PositionGetDouble(POSITION_SL);
    take = PositionGetDouble(POSITION_TP);
    
   if(prezzo_deal-(SymbolInfoDouble(Symbol(),SYMBOL_BID))>VirTP*Point())
    {
    if(SymbolInfoDouble(Symbol(),SYMBOL_BID)+trail*Point()<stop)
     {
      mrequest.sl = SymbolInfoDouble(Symbol(),SYMBOL_BID)+trail*Point();
      mrequest.tp = take;
      mrequest.action = TRADE_ACTION_SLTP;
      mrequest.deviation = 0;
      mrequest.symbol = Symbol();
      mrequest.position=ticket;   // ticket of the position
      if(OrderSend(mrequest,mresult)==false)
       Print("Non è stato possibile modificare StopLoss #",GetLastError());
     }
    }
   }
 }
//+------------------------------------------------------------------+