//|                                           Cliquet general LM.mq4 |
// ************** cliquet forex un seul ordre par symbole 
// pour arreter : ExpertRemove();
#property copyright "LM"
#property link      "aceoptimal.fr"
#property version   "1.00"
#property strict
//--- input parameters

input bool alerte_on=false;
input int stop1=1;
input double stop2=1.5, stop3=0.79; // utiliser 80/20 pour choisir les seuils
                                     // stratégie à déterminer en fonction d'un **bon** signal d'achat ou de vente.

int nb_tick=0, nb_timer=0;
double stop_montant=0, stop_descendant=1E9; // stocke le stop pendant tout le programme
int timer=20;
bool test_hors_connection=true;

void Alerter(string txt)
  {
   if (alerte_on) Alert(txt);
  }

void CalcSignal(string sym)
  {
  double i0, i1, i2, i3, s1 , s2;
  string alerte="";
  i1=iOsMA(sym,PERIOD_M1,12,26,9,PRICE_CLOSE,1); // OsMACD
  i2=iOsMA(sym,PERIOD_M1,12,26,9,PRICE_CLOSE,2);
  i3=iOsMA(sym,PERIOD_M1,12,26,9,PRICE_CLOSE,3);  
  if ((i1>i2 && i3>i2 ) || (i1<i2 && i3<i2 ))
    alerte=" OsMA inv.";
  i0=iRSI(sym,PERIOD_M1,21,PRICE_CLOSE,0);  // RSI
  i1=iRSI(sym,PERIOD_M1,21,PRICE_CLOSE,1);
  i2=iRSI(sym,PERIOD_M1,21,PRICE_CLOSE,2);
  if (i0>=60 || i0<=40 || (i1>50 && i2<50 ) || (i1<50 && i2>50 ))
    alerte=alerte+" RSI="+DoubleToString(i0,1);    
  
  i1=iStochastic(sym,PERIOD_M1,8,3,3,MODE_SMA,1,MODE_MAIN,1);  // Stochastique
  s1=iStochastic(sym,PERIOD_M1,8,3,3,MODE_SMA,1,MODE_SIGNAL,1);
  i2=iStochastic(sym,PERIOD_M1,8,3,3,MODE_SMA,1,MODE_MAIN,2);
  s2=iStochastic(sym,PERIOD_M1,8,3,3,MODE_SMA,1,MODE_SIGNAL,2);
  if ((i1>50 && i2<50 ) || (i1<50 && i2>50 ) || (i1<s1 && i2>s2 ) || (i1<s1 && i2<s2 ) || ( i1<=75 ) || (i1>=25))
    alerte=alerte+" Stock="+DoubleToString(i1,1);   
  //                                                    Faire moyennes et Macd mieux, Merci
  if (alerte>"") Alerter(sym+alerte); // affichage final   
  }

void Signal()
  {
    int s=TimeSeconds(TimeCurrent());
    if ( s > (0.5*timer) && s < (1.7*timer) )
     {
      CalcSignal("EURUSD");
      CalcSignal("GBPUSD");
      CalcSignal("NZDUSD");
      CalcSignal("USDCHF");
      CalcSignal("USDJPY");
      CalcSignal("EURNZD");
     }
    else 
     {
     if (s>(60-1.2*timer) || s<(1.2*timer)) Alerter(IntegerToString(s));
     }
  }
// ******************** Cliquet                                        

void Cliquet()
  {
   int buys=0,sells=0;
   int gap_stop=2;
   double gain,ecart,spread,prix_ordre,aske,bide;
   double stp1=0;
   string qui_calcul;
   bool res,ordre_valide;
   int ordres_total,ordre_type,digites;
   //if (!RefreshRates()) Comment("Rafraichissement de données échoué dans cliquet");   Vérifier si ça ne bloque pas le prog
   Comment("En vacances                                            \n"
   +"                                             \n"
   +"                                             \n"
   +"                                             \n"
   +"                                             \n"
   +"                                             \n"
   +"                                             \n");
   
   if (test_hors_connection) 
     {
      ordres_total=100; // représente ici le nb de boucle du test
      ordre_valide=true;
      aske=1.0002;      // init paramètres du test
      bide=1;
      prix_ordre=0.9998;
      ordre_type=OP_BUY;  // OP_BUY ou OP_SELL
      digites=5;   // Digits;   
      srand(46);  // init random   
     }
   else
    {
     ordres_total=OrdersTotal();
    }
   
   for(int i=0;i<ordres_total;i++)
     {   
      if (!test_hors_connection) ordre_valide=(OrderSelect(i,SELECT_BY_POS,MODE_TRADES)==true) && (OrderSymbol()==Symbol());
      if (ordre_valide) // selectionne l'ordre seulement si il est en cours et correspond au bon symbole
        {
        if (test_hors_connection) // régler ici l'évolution des variables du test
         {
           aske+=0.0001;
           bide+=0.0001;
         }
        else
         {
           aske=MarketInfo(Symbol(), MODE_ASK);
           bide=MarketInfo(Symbol(), MODE_BID);
           prix_ordre=OrderOpenPrice();
           ordre_type=OrderType();
           digites=Digits;
         }
         spread=aske-bide;
         ecart=spread*stop1;
         qui_calcul="";
         if (ordre_type==OP_BUY )  // ordre acheté
           {   
           stp1=0; 
           gain=bide-prix_ordre;  // **************************** début algo
           if (stop_montant==0)       // Calc 1er stop loss sous le cours d'achat   
             {
               stp1=bide-ecart;                     
               qui_calcul="BUY initialisation du stop :";  
             }

           if (gain>=(5*ecart))   // ************  gros gain
            {
             stp1=prix_ordre+(gain*stop3);
             qui_calcul="BUY calcul stop GROS gain :";
            }
           else
             {
             if (gain>(1*ecart)) // Remonter le stop si petit gain annoncé
              {
               stp1=bide-(ecart*stop2);              
               qui_calcul="BUY calcul stop petit gain :";
              }
             }
                            // **************************** fin algo
           if (stp1>stop_montant)  // placer le nouveau stop calculé
             {
               stop_montant=stp1;
               Print(qui_calcul+DoubleToString(stop_montant,digites)+" gain = "+DoubleToString(gain,digites));
             }
             
           if (stop_montant>bide)   // solder si sur le stop
            {            
             if (test_hors_connection) { res=true; test_hors_connection=false;}
              else res=OrderClose(OrderTicket(),OrderLots(),bide,3,Blue);  // a tester avec 1        
             if(!res)
               {
                PlaySound("timeout.wav");
                Alerter("Erreur de OrderClose, voir journal");
                Print("Erreur de OrderClose. Erreur code=",GetLastError(),"stp1=",stp1);
               }
             else
              {
               PlaySound("Ok.wav");
               Print("Ordre fermé avec succès : stop=",DoubleToString(stop_montant,digites)," Bid=",DoubleToString(bide,digites));
              }  
             stop_montant=0;               
           } 
          } 
          
         if (ordre_type==OP_SELL ) // ordre vendu 
           {    
           stp1=1E9;
           gain=aske-prix_ordre;  // **************************** début algo
           if (stop_descendant==1E9)       // Calc 1er stop loss sur le cours de vente   
             {
               stp1=aske+ecart; 
               qui_calcul="SELL initialisation du stop :";  
             }

           if (gain>=(5*ecart))   // ************  gros gain
            {
            stp1=prix_ordre-(gain*stop3);
            qui_calcul="SELL calcul stop GROS gain :";
            }
           else
             {
             if (gain>(1*ecart)) // Redescendre le stop si petit gain annoncé  
              {
               stp1=aske+(ecart*stop2);
               qui_calcul="SELL calcul stop petit gain :";            
              }           
             }
                            // **************************** fin algo
           if (stp1<stop_descendant)  // placer le nouveau stop calculé
             {
               stop_descendant=stp1;
               Print(qui_calcul+DoubleToString(stop_descendant,digites)+" gain = "+DoubleToString(gain,digites));

             }
             
           if (stop_descendant<aske)   // solder si sur le stop
            {            
             if (test_hors_connection) { res=true; test_hors_connection=false;}
              else res=OrderClose(OrderTicket(),OrderLots(),aske,3,Blue);  // a tester avec 1
             if(!res)
               {
                PlaySound("timeout.wav");
                Alerter("Erreur de OrderClose, voir journal");
                Print("Erreur de OrderClose. Erreur code=",GetLastError(),"stp1=",stp1);
               }
             else
              {
               
               //PlaySound("Ok.wav");
               Print("Ordre fermé avec succès : stop=",DoubleToString(stop_descendant,digites)," Ask=",DoubleToString(aske,digites));
              }   
             stop_descendant=1E9;
           } 
          }      
    Comment("\n stop montant="+DoubleToString(stop_montant,digites)
    +"\n stop descendant="+DoubleToString(stop_descendant,digites)
    +"\n ask="+DoubleToString(aske,digites)
    +"\n bid="+DoubleToString(bide,digites)
    +"\n stp1="+DoubleToString(stp1,digites)
    +"\n spread="+DoubleToString(spread,digites));
     
    if (!test_hors_connection) break; // un seul ordre traité par graphique 
   }           
  }
}
//************************* Expert initialization function                                   |
int OnInit()
  {
//--- create timer
   EventSetTimer(timer); // secondes
      
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//--- destroy timer
   EventKillTimer();
      
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
//---
 //Alert("Forex power tick"); chiant
  //MessageBox("Tick"); pire
  //nb_tick++;
   //Comment("Tick ",nb_tick);
   //,StringFormat("nb_tick")
  }
//+------------------------------------------------------------------+
//| Timer function                                                   |
//+------------------------------------------------------------------+
void OnTimer()
  {
//---
//  Comment("Timer ");
//  Calcul_stop();
if (Symbol()=="XAUEUR") 
  Signal();
  else Cliquet();
nb_timer++;

//Comment("Appels timer : "+nb_timer+"\n blabla\n");
//Comment("Appels timer : "+nb_timer+"\n _____");
//Comment(StringConcatenate("Show prices\nAsk \nBid = "));   
   //Alert("Forex power timer");
  }
//+------------------------------------------------------------------+
//| Tester function                                                  |
//+------------------------------------------------------------------+
double OnTester()
  {
//---
   double ret=0.0;
//---

//---
   return(ret);
  }
//+------------------------------------------------------------------+
//| ChartEvent function                                              |
//+------------------------------------------------------------------+
void OnChartEvent(const int id,
                  const long &lparam,
                  const double &dparam,
                  const string &sparam)
  {
//---
   
  }
//+------------------------------------------------------------------+
