//+------------------------------------------------------------------+
//|                           QS Ichimoku Best Trading Strategie.mq5 |
//|                                  Copyright 2023, MetaQuotes Ltd. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2023, MetaQuotes Ltd."
#property link      "https://www.mql5.com"
#property version   "1.00"

/*
Strategy Rules
               KUMO Strategy
      BUY :
            - Price move from below the cloud to UP
            - Cloud in futur turns green (SenkouSpanA > SenkouSpanB)
            - TenkanSen is above KijunSen
            - ChikouSpan is above Cloud 26 bars behing (is above SenkouSpanA and B 26 bars behing)
            - Stoploss below KijunSen
            - TakeProfit 2 x risk
            
      SELL :
            - Same as Buy conditions in Reverse

               TENKANSEN CROSS KIJUNSEN
      BUY :
            - Price move from below the cloud to Up
            - Cloud in futur turns green (SenkouSpanA > SenkouSpanB)
            - Price move from below the TenkanSen to Up
            - ChikouSpan is above Cloud 26 bars behing (is above SenkouSpanA and B 26 bars behing)
            - Stoploss below KijunSen
            - TakeProfit 3 x risk
            
      SELL :
            - Same as Buy conditions in Reverse


//+----------------------------------------------------------------------------*/
#include <Trade\PositionInfo.mqh>
#include <Trade\Trade.mqh>
#include <Trade\SymbolInfo.mqh>  
#include <Trade\AccountInfo.mqh>
#include <Trade\DealInfo.mqh>
#include <Trade\OrderInfo.mqh>
#include <Expert\Money\MoneyFixedMargin.mqh>

#include <Trade\Trade.mqh>
      CTrade       trade;
#include <Indicators/Trend.mqh>
      CiIchimoku*Ichimoku;

//----------------------------------------------------
//--- User Input 
//----------------------------------------------------

/*

//--- input parameters

input group    "=========== Trading settings=================="
input ulong                MagicNumber          = 9888;           //Magic number
input ENUM_TIMEFRAMES      Timeframe            = PERIOD_CURRENT; //Trading Timeframe for the EA
input uint                 StopLoss             = 100;            // Stop Loss (sl)
input uint                 TakeProfit           = 500;            // Take Profit (tp)
input uint                 TrailingStop         = 250;            // Trailing Stop, min distance from price to SL ('0' -> OFF)
input uint                 TrailingStep         = 50;             // Trailing Step

input group   "=========== Position size management (lot calculation) ==========="
enum  LOT_MODE_ENUM 
    {
      LOT_MODE_FIXED,               // Fixed Lots
      LOT_MODE_MONEY,               // Lots Based On Money
      LOT_MODE_PCT_ACCOUNT         // Lots Based On % Of Account 
    };
input LOT_MODE_ENUM InpLotMode = LOT_MODE_FIXED;       // Lot mode
input double               InpLots = 0.25;             // Lot / money / percent 
input double               VolumeLotOrRisk      = 3.0;            // The value for "Money management"

input group      "========== Trade mode =================="
input ENUM_TRADE_MODE      TradeMode            = buy_sell;       // Trade mode:

input group       "=========== MA =================="
input int                  MA1_period            = 50;             // MA: averaging period
input ENUM_MA_METHOD       MA1_method            = MODE_LWMA;      // MA: smoothing type
input ENUM_APPLIED_PRICE   MA1_applied_price     = PRICE_CLOSE;    // MA: type of price

input int                  MA2_period            = 100;            // MA: averaging period
input ENUM_MA_METHOD       MA2_method            = MODE_LWMA;      // MA: smoothing type
input ENUM_APPLIED_PRICE   MA2_applied_price     = PRICE_CLOSE;    // MA: type of price


input group       "=========== CCI=================="
input int                  CCI_period          = 100;             // CCI: period
input ENUM_APPLIED_PRICE   CCI_applied_price   = PRICE_CLOSE;     // CCI: type of price

input group       "=========== ICHIMOKU =================="
input int                  TENKANSEN_period    = 9;               // TENKANSEN:  period
input int                  KIJUNSEN_period     = 26;              // KIJUNSEN:   period
input int                  SENKOUSPAN_period   = 52;              // SENKOUSPAN: period

input group       "=========== WORKING TIME ================="
input bool                 TimeControl          = true;           // Use time control
input uchar                StartHour            = 02;             // Start Hour
input uchar                StartMinute          = 00;             // Start Minute
input uchar                EndHour              = 24;             // End Hour
input uchar                EndMinute            = 00;             // End Minute

input group       "=========== Day of week filter ==========="
input bool InpMonday        = true;                               // Trade on monday
input bool InpTuesday       = true;                               // Trade on tuesday
input bool Inpwednesday     = true;                               // Trade on wednesday
input bool InpThursday      = true;                               // Trade on Thursday
input bool InpFriday        = true;                               // Trade on Friday

input group             "Additional features"
input bool                 OnlyOne              = false;          // Positions: Only one
input bool                 CloseOpposite        = false;          // Positions: Close opposite
input ulong                Deviation            = 100;            // Deviation, in Points (1.00045-1.00055=10 points)


//---------------------------------------------------------------------------------------------------------------*/

//----------------------------------------------------
//--- User Input 
//---------------------------------------------------


   input          ENUM_TIMEFRAMES   Timeframe   = PERIOD_CURRENT;      //Trading Timeframe for the EA
   input ulong                      InpMagic    = 8989;                // Magic number fro EA
   input double                     RiskPercent = 2;                   // Risk per Trade (% of capital)
   input int                        MA1_period   = 50;                 // MA: averaging period
   input int                        MA2_period   = 100;                // MA: averaging period
   input int                        CCI_period  = 100;                 // CCI: period

   
// Bool Conditions
   bool     FuturCloudGreen = false,      FuturCloudRed = false;
   bool     PriceaboveCloud = false,      PricebelowCloud = false;
   bool     PriceaboveTenkan = false,     PricebelowTenkan = false;
   bool     PriceaboveKijun  = false,      PricebelowKijun = false;
   bool     PriceaboveChikou = false,     Tenkanbelowkijun = false;
   bool     PricebelowChikou = false,     ChikoubelowCloud =  false;
   bool     TenkanaboveKijun = false;        
   bool     ChikouaboveCloud = false;  
   bool     CciaboveLevel0   = false;
   bool     CcibelowLevel0   = false;
   bool     PriceaboveMa1     = false;
   bool     PricebelowMa1     = false;
   bool     PositionBuy_opened = false;  
   bool     PositionSell_opened = false;
   bool     PositionBuy_T1_opened = false;
   bool     PositionSell_T1_opened = false;
   bool     PositionBuy_T2_opened = false;
   bool     PositionSell_T2_opened = false;
   bool     PositionBuy_K1_opened = false;  
   bool     PositionSell_K1_opened = false;
   bool     PositionBuy_K2_opened = false;  
   bool     PositionSell_K2_opened = false;
   bool     PositionBuy_C_opened = false;  
   bool     PositionSell_C_opened = false;
   bool     PositionBuy_M1_opened = false;
   bool     PositionSell_M1_opened = false;
   bool     PositionBuy_M2_opened = false;
   bool     PositionSell_M2_opened = false;
   

   
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
   trade.SetExpertMagicNumber(InpMagic);
//---
   Ichimoku = new CiIchimoku();
   Ichimoku.Create(_Symbol,Timeframe,9,26,52);
   
  int Ma1 = iMA(_Symbol, _Period, MA1_period, 0, MODE_LWMA, PRICE_CLOSE);
  int Ma2 = iMA(_Symbol, _Period, MA2_period, 0, MODE_LWMA, PRICE_CLOSE);
  int Cci = iCCI(_Symbol, _Period, CCI_period, PRICE_CLOSE);
    
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//---
   
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {

 if(!IsNewBar()) return;
    
    Ichimoku.Refresh(-1);
    
         double SpanAxl=Ichimoku.SenkouSpanA(1);
         double SpanAx2= Ichimoku.SenkouSpanB(2);
         double SpanAx26= Ichimoku.SenkouSpanA(26);
         double SpanAf26= Ichimoku.SenkouSpanA(-26);
         
         double SpanBxl= Ichimoku.SenkouSpanB(1);
         double SpanBx2= Ichimoku.SenkouSpanB(2);
         double SpanBx26= Ichimoku.SenkouSpanB(26);
         double SpanBf26= Ichimoku.SenkouSpanB(-26);
    
         double Tenkan = Ichimoku.TenkanSen(1);
         double Kijun = Ichimoku.KijunSen(1);
         double Chikou = Ichimoku.ChinkouSpan(26);
         
         double Ma1;
         double Ma2;

         double Ccix1;
         double Ccix2;
         
         double Closex1 = iClose(_Symbol, Timeframe,1);
         double Closex2 = iClose(_Symbol, Timeframe,2);
         

//===============================================================================================
//                               Checking Conditions                                           ||
//===============================================================================================        

//-------  Futur Cloud is Green or Red
           if(SpanAf26>SpanBf26)
           { 
               FuturCloudGreen = true;
               FuturCloudRed = false;
           }
           if(SpanBf26>SpanAf26)
           {
               FuturCloudGreen = false;
               FuturCloudRed  = true;
           }

//-------  Exit Cloud Up Or Exit Cloud Below
            if(PriceaboveCloud==false && (Closex2<SpanAx2 || Closex2<SpanBx2) && Closex1>SpanAxl && Closex1>SpanBxl)
            {
               PriceaboveCloud = true;
               PricebelowCloud = false;
            }
            
            if(PricebelowCloud==false && (Closex2>SpanAx2 || Closex2>SpanBx2) && Closex1<SpanAxl && Closex1<SpanBxl)
            {
               PriceaboveCloud = false;
               PricebelowCloud = true;
            }
      
             if(Tenkan>Kijun)
             {
                 TenkanaboveKijun = true;
                 Tenkanbelowkijun = false;
             }
             
             if(Tenkan<Kijun)
             {
                 TenkanaboveKijun = false;
                 Tenkanbelowkijun = true;
             }
             
//-------  Price above Tenkan or  Price below Tenkan
             if(Closex2>Tenkan)
                {
                   PriceaboveTenkan = true;
                   PricebelowTenkan = false;
                }
              if(Closex2<Tenkan)
                {
                   PriceaboveTenkan = false;
                   PricebelowTenkan = true;
                }
//-------  Price above Kijun or  Price below Kijun
             if(Closex2>Kijun)
                {
                   PriceaboveKijun = true;
                   PricebelowKijun = false;
                }
              if(Closex2<Kijun)
                {
                   PriceaboveKijun = false;
                   PricebelowKijun = true;
                }
                
//------- Chikou above or below Cloud 26 bars back
               if(Chikou>SpanAx26 && Chikou>SpanBx26)
               {
                  ChikouaboveCloud = true;
                  ChikoubelowCloud = false;
               }
               
               if(Chikou<SpanAx26 && Chikou<SpanBx26)
               {
                  ChikouaboveCloud = false;
                  ChikoubelowCloud = true;
               }
//------- Close of price is in the Cloud  
                if(SpanAxl>SpanBxl && Closex1>SpanBxl && Closex1<SpanAxl)
                {
                   PriceaboveCloud = false;
                   PricebelowCloud = false;
                }

                if(SpanBxl>SpanAxl && Closex1>SpanAxl && Closex1<SpanBxl)
                {
                   PriceaboveCloud = false;
                   PricebelowCloud = false;
                }

//------- Chikou is in the Cloud 
                if(SpanAx26>SpanBx26 && Chikou>SpanBx26 && Chikou<SpanAx26)
               {
                  ChikouaboveCloud = false;
                  ChikoubelowCloud = false;
               }
                if(SpanBx26>SpanAx26 && Chikou>SpanAx26 && Chikou<SpanBx26)
               {
                  ChikouaboveCloud = false;
                  ChikoubelowCloud = false;
               }
               
//-------  Price above Chikou or  Price below Chikou
              if(Closex2<Chikou)
                {
                   PriceaboveChikou = false;
                   PricebelowChikou = true;
                }
              if(Closex2>Chikou)
                {
                   PriceaboveChikou = true;
                   PricebelowChikou = false;
                } 
                
//-------  CCI above Level 0 or CCI below Level 0
               if(Ccix1>0 && Ccix2>0)
                  {
                   CciaboveLevel0 = true;
                   CcibelowLevel0 = false;
                  }
               if(Ccix1<0 && Ccix2<0)
                  {
                   CciaboveLevel0 = false;
                   CcibelowLevel0 = true;
                  }

  //-------  Price above MA1 or  Price below MA1
              if(Closex2<Ma1)
                {
                   PriceaboveMa1 = false;
                   PricebelowMa1 = true;
                }
              if(Closex2>Ma1)
                {
                   PriceaboveMa1 = true;
                   PricebelowMa1 = false;
                } 
             
Comment( "\n PriceaboveCloud : "+PriceaboveCloud+
         "\n Tenkan>Kijun : "+TenkanaboveKijun+
         "\n ChikouaboveCloud : "+ChikouaboveCloud+
         "\n FuturCloudGreen : "+FuturCloudGreen+
         "\n \n"+
         "\n PricebelowCloud : "+PricebelowCloud+
         "\n Tenkan<Kijun : "+Tenkanbelowkijun+
         "\n ChikoubelowCloud : "+ChikoubelowCloud+
         "\n FuturCloudRed : "+FuturCloudRed+
         "\n \n"+
         "\n PriceaboveChikou : "+ PriceaboveChikou+
         "\n PricebelowChikou : "+ PricebelowChikou);
         

//===============================================================================================        
//              TenkanSen - KijunSen Crossover - Open Signal                                     
//===============================================================================================        

//==============================  BUY Conditions

         if(FuturCloudGreen==true && PriceaboveCloud==true && TenkanaboveKijun==true && ChikouaboveCloud==true)
            {
            double entry   = Closex1;
            double sl      = Kijun - 100*_Point;
            double tp      = entry + (entry-sl)*2;
            double lots    = calclots(entry-sl);
         
            ulong ticket = trade.Buy(lots, _Symbol, entry, sl, tp, "Kumo Buy Trade");
                 if(ticket>0)
                   PositionBuy_opened = true;
            }
           
//===============================  SELL Conditions 

       if(FuturCloudRed==true && PricebelowCloud==true && Tenkanbelowkijun==true && ChikoubelowCloud==true)
         
         {
         double entry   = Closex1;
         double sl      = Kijun + 50*_Point;
         double tp      = entry - (sl-entry)*2;
         double lots    = calclots(sl-entry);
         
         ulong ticket = trade.Sell(lots, _Symbol, entry, sl, tp, "Kumo Sell Trade");
                 if(ticket>0)
                    PositionSell_opened = true;
         }

//              TenkanSen - Price Crossover - Open Signal                                        
//===============================================================================================
    
//=============================  BUY Conditions
              
    if(PricebelowCloud==true && PriceaboveTenkan==true && ChikoubelowCloud==true && CciaboveLevel0==true)
        {
         double entry   = Closex1;
         double sl      = Kijun - 20*_Point;
         double tp      = entry + (entry-sl)*3;
         double lots    = calclots(entry-sl);
                    
         ulong ticket_Ten1 = trade.Buy(lots, _Symbol, entry, sl, tp, "Tenkan1 Buy Trade");
              if(ticket_Ten1>0)
                 PositionBuy_T1_opened = true;
       }
   
    if( PriceaboveCloud==true && PriceaboveTenkan==true && ChikouaboveCloud==true && CciaboveLevel0==true) 
         {
         double entry   = Closex1;
         double sl      = Kijun - 20*_Point;
         double tp      = entry + (entry-sl)*3;
         double lots    = calclots(entry-sl);
                    
         ulong ticket_Ten2 = trade.Buy(lots, _Symbol, entry, sl, tp, "Tenkan2 Buy Trade");
              if(ticket_Ten2>0)
                 PositionBuy_T2_opened = true;
         }
//===============================  SELL Conditions 
 
    if(PriceaboveCloud==true && PricebelowTenkan==true && ChikouaboveCloud==true && CcibelowLevel0==true) 
         {
         double entry   = Closex1;
         double sl      = Kijun + 20*_Point;
         double tp      = entry - (sl-entry)*2;
         double lots    = calclots(sl-entry);
         
         ulong ticket_Ten1 = trade.Sell(lots, _Symbol, entry, sl, tp, "Tenkan1 Sell Trade");
              if(ticket_Ten1>0)
                 PositionSell_T1_opened = true;
         }
     if(PricebelowCloud==true && PricebelowTenkan==true && ChikoubelowCloud==true && CcibelowLevel0==true) 
         {
         double entry   = Closex1;
         double sl      = Kijun + 20*_Point;
         double tp      = entry - (sl-entry)*2;
         double lots    = calclots(sl-entry);
         
         ulong ticket_Ten2 = trade.Sell(lots, _Symbol, entry, sl, tp, "Tenkan2 Sell Trade");
              if(ticket_Ten2>0)
                   PositionSell_T2_opened = true;
         } 

//              KijunSen - Price Crossover Open Signal                                      
//===============================================================================================

//==============================  BUY Conditions

   if(PricebelowCloud==true && PriceaboveKijun==true && ChikoubelowCloud==true && CciaboveLevel0==true) 
          {
         double entry   = Closex1;
         double sl      = SpanAxl - 20*_Point;
         double tp      = entry + (entry-sl)*3;
         double lots    = calclots(entry-sl);
         
         ulong ticket_Kij1 = trade.Buy(lots, _Symbol, entry, sl, tp, "Kijun1 Buy Trade");
              if(ticket_Kij1>0)
                   PositionBuy_K1_opened = true;
         }    

   if( PriceaboveCloud==true && PriceaboveKijun==true && ChikouaboveCloud==true && CciaboveLevel0==true) 
         {
         double entry   = Closex1;
         double sl      = SpanAxl - 20*_Point;
         double tp      = entry + (entry-sl)*3;
         double lots    = calclots(entry-sl);
         
         ulong ticket_Kij2 = trade.Buy(lots, _Symbol, entry, sl, tp, "Kijun2 Buy Trade");
              if(ticket_Kij2>0)
                   PositionBuy_K2_opened = true;
         }  
         
//===============================  SELL Conditions
        
   if(PriceaboveCloud==true && PricebelowKijun==true && ChikouaboveCloud==true && CcibelowLevel0==true) 
         {
         double entry   = Closex1;
         double sl      = SpanBxl + 20*_Point;
         double tp      = entry - (sl-entry)*2;
         double lots    = calclots(sl-entry);
         
         ulong ticket_Kij1 = trade.Sell(lots, _Symbol, entry, sl, tp, "Kijun1 Sell Trade");
              if(ticket_Kij1>0)
                   PositionSell_K1_opened = true;
         }
      
    if(PricebelowCloud==true && PricebelowKijun==true && ChikoubelowCloud==true && CcibelowLevel0==true) 
         {
         double entry   = Closex1;
         double sl      = SpanBxl + 20*_Point;
         double tp      = entry - (sl-entry)*2;
         double lots    = calclots(sl-entry);
         
         ulong ticket_Kij2 = trade.Sell(lots, _Symbol, entry, sl, tp, "Kijun2 Sell Trade");
              if(ticket_Kij2>0)
                   PositionSell_K2_opened = true;
         }

//              Chikou - Cloud Crossover Open Signal                                       
//===============================================================================================
   
//==============================  BUY Conditions

   if(PriceaboveCloud==true && PriceaboveTenkan && ChikouaboveCloud==true && PricebelowChikou)
         {
         double entry   = Closex1;
         double sl      = SpanBxl - 10*_Point;
         double tp      = entry + (entry-sl)*5;
         double lots    = calclots(entry-sl);
         
         ulong ticket_Chk = trade.Buy(lots, _Symbol, entry, sl, tp, "Chikou Buy Trade");
              if(ticket_Chk>0)
                   PositionBuy_C_opened = true;
         }   
//===============================  SELL Conditions 
 
    if(PricebelowCloud==true && PricebelowTenkan && ChikoubelowCloud==true && PriceaboveChikou)
         {
         double entry   = Closex1;
         double sl      = SpanAxl + 10*_Point;
         double tp      = entry - (sl-entry)*3;
         double lots    = calclots(sl-entry);
         
         ulong ticket_Chk = trade.Sell(lots, _Symbol, entry, sl, tp, "Chikou Sell Trade");
              if(ticket_Chk>0)
                   PositionSell_C_opened = true;
         } 
         
  //              MA - Price Crossover - Open Signal                                      
//===============================================================================================

//==============================  BUY Conditions

   if(PricebelowCloud==true && PriceaboveMa1==true && CciaboveLevel0==true) 
          {
         double entry   = Closex1;
         double sl      = Ma2 - 10*_Point;
         double tp      = entry + (entry-sl)*3;
         double lots    = calclots(entry-sl);
         
         ulong ticket_Ma1 = trade.Buy(lots, _Symbol, entry, sl, tp, "Ma Buy Trade");
              if(ticket_Ma1>0)
                   PositionBuy_M1_opened = true;
         }    

   if( PriceaboveCloud==true && PriceaboveMa1==true && CciaboveLevel0==true) 
         {
         double entry   = Closex1;
         double sl      = Ma2 - 10*_Point;
         double tp      = entry + (entry-sl)*3;
         double lots    = calclots(entry-sl);
         
         ulong ticket_Ma2 = trade.Buy(lots, _Symbol, entry, sl, tp, "Ma Buy Trade");
              if(ticket_Ma2>0)
                   PositionBuy_M2_opened = true;
         }  
         
//===============================  SELL Conditions
        
   if(PriceaboveCloud==true && PricebelowMa1==true && CcibelowLevel0==true) 
         {
         double entry   = Closex1;
         double sl      = Ma2 + 10*_Point;
         double tp      = entry - (sl-entry)*2;
         double lots    = calclots(sl-entry);
         
         ulong ticket_Ma1 = trade.Sell(lots, _Symbol, entry, sl, tp, "Ma Sell Trade");
              if(ticket_Ma1>0)
                   PositionSell_M1_opened = true;
         }
      
    if(PricebelowCloud==true && PricebelowMa1==true && CcibelowLevel0==true) 
         {
         double entry   = Closex1;
         double sl      = Ma2 + 10*_Point;
         double tp      = entry - (sl-entry)*2;
         double lots    = calclots(sl-entry);
         
         ulong ticket_Ma2 = trade.Sell(lots, _Symbol, entry, sl, tp, "Ma Sell Trade");
              if(ticket_Ma2>0)
                   PositionSell_M2_opened = true;
         }
         

            
  }   
  

  
  
  
  
  
//=======================================================================================================

  bool  IsNewBar()
  {
      static datetime previousTime = 0;
      datetime currentTime = iTime(_Symbol, PERIOD_CURRENT,0);
      if(previousTime!=currentTime)
      {   
         previousTime =currentTime;
         return true;
      }
      return true;
  }

   double calclots(double slPoints)
   {
   double risk = AccountInfoDouble(ACCOUNT_BALANCE)* RiskPercent / 100;
   
   double ticksize = SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_SIZE);
   double tickvalue = SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_VALUE);
   double lotstep = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_STEP);
   
   double moneyPerLotstep = slPoints / ticksize * tickvalue * lotstep;
   double lots = MathFloor(risk / moneyPerLotstep) * lotstep;
   
   double minvolume = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MIN);
   double maxvolume =  SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MAX);
   
         if(maxvolume!=0) lots = MathMin(lots, maxvolume);
         if(minvolume!=0) lots = MathMax(lots, minvolume);
         
   lots = NormalizeDouble(lots,2);
   
   return lots;
   
   }


















//+------------------------------------------------------------------+
//| TradeTransaction function                                        |
//+------------------------------------------------------------------+
void OnTradeTransaction(const MqlTradeTransaction& trans,
                        const MqlTradeRequest& request,
                        const MqlTradeResult& result)
  {
//---
   
  }
//+------------------------------------------------------------------+
