//+------------------------------------------------------------------+
//|                                                Trade exces V2.mq4|
//|                                                               LM |
//|                                              |
//+------------------------------------------------------------------+
#property copyright "LM"
#property link      ""
#property version   "2.00"
#property strict

#include <stderror.mqh> 
#include <stdlib.mqh> 

double ecart_bol =2.6;  // externe ne fonctionne pas dans scripts
int nb_seance = 29;
double stop_level = 6;
double tp_level = 1.2;

double ratio_tradable_du_compte = 0.1;
double ratio_etype_spread = 4;
int h_deb_traing=0; // 1 heure
int h_fin_traing=23; // à 21 heure
int jour_deb_traing=1; // 1 = lundi
int jour_fin_traing=5; // à 5 = vendredi

ulong chrono=0; // stockage GetMicrosecondCount()à un instant t
string rep = "d:\\_mt4_data\\" ; // ne fonctionne pas
string symb,ch,ch2;

int i,j,k,l,m,i_bas,i_haut;
double e_typ,val_ecart_bol,ecart,spread,moy,haut_et,bas_et;//,pt_achat,nb_trade_tot;
   
int t[9]={PERIOD_M1,PERIOD_M5,PERIOD_M15,PERIOD_M30,PERIOD_H1,PERIOD_H4,PERIOD_D1,PERIOD_W1,PERIOD_MN1};
string per[9]={"M1","M5","M15","M30","H1","H4","D1","W1","MN1"};

string fichier ="_Trade_exces_V2-0_log.csv";
int file_handle;
int nb_ordre;
string bon_symb;
double bon_e_typ, bon_spread, bon_moy, bon_ecart, bon_val_ecart_bol, bon_taille_trade_en_lot;

void SendMail(string text) 
  { 
   int check; 
   SendMail("Test", text); 
   check=GetLastError(); 
   if(check!=ERR_NO_ERROR) Print("Message not sent. Error: ",ErrorDescription(check)); 
  }
  
void OuvrirFichier()
  {
    ResetLastError(); 
    file_handle=FileOpen(fichier,FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_TXT," "); 
    if(file_handle==INVALID_HANDLE) 
      {
        MessageBox("Erreur :"+IntegerToString(GetLastError())); 
        PrintFormat("Failed to open %fichier2 file, Error code = %d",fichier,GetLastError()); 
        ResetLastError(); 
        return;
      }   
    
    FileSeek(file_handle,0,SEEK_END);
  }
 
void SuiviTrades()                    // A MODIFIER EN FONCTION DES HEURES D'OUVERTURE ET A FINIR
  {
    nb_ordre=OrdersTotal(); 
    while (nb_ordre>0)
     {
      // si >0 traiter , si >1 Alerte
      // OrderSend comment et magic peuvent servir pour stocker la base de temp
      // FileWrite(file_handle,"Ti");
      
      Sleep(20000); // 20 secondes
      nb_ordre=OrdersTotal(); 
     }
  }
  
double CalcTaillePosition()  // Parfait : gère le minlot, le lotstep et le max lot a partir de ratio_tradable_du_compte 
                            // retourne le lot à trader ou 0 si impossible 
  {
   double montant_tradable=AccountFreeMargin()*ratio_tradable_du_compte;
   double engagement_par_lot=MarketInfo(symb,MODE_MARGINREQUIRED)+(e_typ*6);
   double x=(montant_tradable-(engagement_par_lot*MarketInfo(symb,MODE_MINLOT)))/(engagement_par_lot*MarketInfo(symb,MODE_LOTSTEP));
   double ix=0; 
   if (x>=0)
    {
      ix=MarketInfo(symb,MODE_MINLOT)+(MathFloor(x)*MarketInfo(symb,MODE_LOTSTEP));    
    }  
   if (ix>MarketInfo(symb,MODE_MAXLOT))
    ix=MarketInfo(symb,MODE_MAXLOT);
   return(ix);
  }
  
void ValeurATrader()
  {
   if (MarketInfo(symb,MODE_TRADEALLOWED))   // 
    if ( !MarketInfo(symb,MODE_MARGINCALCMODE) || symb=="Bitcoin" || symb=="BitcoinCash" || symb=="Ethereum" || symb=="Litecoin" || symb=="Dash")   
    {                                                                                   // Forex & crypto only 
     k=1; // Période : 5' //for(k=0;k<9;k++)      
      
     e_typ=iStdDev(symb,t[k],20,0,MODE_EMA,PRICE_CLOSE,0);                   // Calc EType
     spread=MarketInfo(symb,MODE_SPREAD)*MarketInfo(symb,MODE_POINT);        // Calc spread
       
     if ((e_typ!=0)&&(spread!=0))
       {               
        moy=iMA(symb,t[k],20,0,MODE_EMA,PRICE_CLOSE,0);                // Calc moyenne
        ecart=moy-iClose(symb,t[k],0);
        val_ecart_bol=e_typ*ecart_bol;
        if (ecart>=val_ecart_bol && (spread*ratio_etype_spread<=val_ecart_bol) ) 
         {  
          double taille_trade_en_lot=CalcTaillePosition();
          if (taille_trade_en_lot>0) 
           {                          // choix du meilleur trade parmis les bons
            if ((bon_e_typ==0) || (ecart*taille_trade_en_lot>bon_ecart*bon_taille_trade_en_lot))
             {
              bon_symb=symb; bon_e_typ=e_typ; bon_spread=spread; bon_moy=moy; bon_ecart=ecart; 
              bon_val_ecart_bol=val_ecart_bol; bon_taille_trade_en_lot=taille_trade_en_lot;
             }     
           }          
         }                                                                                                                                              
       }                    
    }    
  }             
  
void ScanTradeBestValeur()
  {
    bon_symb="";
    bon_e_typ=0; bon_spread=0; bon_moy=0; bon_ecart=0; bon_val_ecart_bol=0; bon_taille_trade_en_lot=0;
    chrono=GetMicrosecondCount();
    
    for(j=0;j<SymbolsTotal(false);j++) // test tout les symbols
     {
      symb= SymbolName(j,false); //
      ValeurATrader();                    // détermine si le symbole est meilleur que le précédent trouvé et le remplace dans ce cas
     } 
    chrono=GetMicrosecondCount()-chrono; 
    if (bon_e_typ>0)
     {
      ResetLastError();
      
      double digit=MarketInfo(bon_symb,MODE_DIGITS);
      double slip=NormalizeDouble(0.05*bon_e_typ,digit);
      double stop=NormalizeDouble(bon_val_ecart_bol-(bon_e_typ*6),digit);
      double tprofit=NormalizeDouble(bon_val_ecart_bol+(1.2*bon_e_typ),digit);
      double achat=MarketInfo(symb,MODE_ASK);
                  
      int num_trade=OrderSend(bon_symb,OP_BUY,bon_taille_trade_en_lot,achat,slip,stop,tprofit,per[k],k,0,clrBlue);
      Sleep(10000);
        
      // _LastError contient le code d'erreur
     
      ch=TimeToString(TimeCurrent(),TIME_DATE|TIME_SECONDS);  //remplir fichier de log
      StringReplace(ch,".","/");

      ch2=IntegerToString(num_trade)+";Achat;"+IntegerToString(_LastError)+";"+IntegerToString(slip)+";"+per[k]+";"
       +bon_symb+";"+DoubleToStr(achat,digit)+";"+DoubleToStr(tprofit,digit)+";"+DoubleToStr(stop,digit)+";"
       +DoubleToString(bon_e_typ,6)+";"+DoubleToString(bon_spread,6)
       +";"+DoubleToString(bon_moy,6)+";"+DoubleToString(bon_ecart,6)+";"+DoubleToString(bon_val_ecart_bol,6)
       +";"+DoubleToString(bon_taille_trade_en_lot,6)+";"+DoubleToString(chrono/1000,3)
       ;    
      StringReplace(ch2,".",",");
    
      FileWrite(file_handle,ch+";"+ch2); 
     } 
  }
  
void OnStart()
  {
    // Tout les trades des ce compte sont gérés par ce programme 
    datetime dt;
    MqlDateTime dtm;
    
    ResetLastError(); 
    file_handle=FileOpen(fichier,FILE_READ|FILE_WRITE|FILE_TXT," "); 
    if(file_handle==INVALID_HANDLE)
     {
      MessageBox(fichier,"Arrêt du script : invalide_handle de fichier : err="+IntegerToString(GetLastError()),MB_OK);
      PlaySound("timeout.wav"); // dossier sound du terminal
      return;
     }     
    FileWrite(file_handle,"Time;Num_trade;Type d'ordre;Erreur;Slip;Periode;Symbole;Achat;Stop;tprofit;E.type;Spread;Moy;Ecart;Val_ecart_bol;Taille_trade_en_lot;Temps de scan");
    
    while (true)
     {
      SuiviTrades(); // suit le(s) trade en cour tant qu'il y en a
      dt=TimeCurrent(dtm);
      if (dtm.day_of_week>=jour_deb_traing && dtm.day_of_week<=jour_fin_traing && dtm.hour>=h_deb_traing && dtm.hour<=h_fin_traing) // pas de trade samedi dimanche, après 1h00 et avant 21h59
       {     
        ScanTradeBestValeur();
       }
       else Sleep(50000); // a virer ou a modifier pour laisser du temps au suivi du trade
      Sleep(10000); 
     }
  }
    
void OnDeinit(const int reason) 
  { 
   FileClose(file_handle);
   Print(__FUNCTION__," Raison : fin de programme = ",reason); 
  }