//+------------------------------------------------------------------+
//|                                                     allikiju.mq4 |
//|                                                          SSSSSSS |
//|                                                                  |
//+------------------------------------------------------------------+
#property copyright "TheKijun"
#property link      "talktojoexcel@gmail.com"


#include <stdlib.mqh>

#define MODE_LONG   1
#define MODE_SHORT -1
#define MODE_NONE   0


extern string  _1          = "Indiacator Setup";

extern int Kijun= 26;


extern int MaMetod  = 2;
extern int MaPeriod = 6;
extern int MaMetod2  = 3;
extern int MaPeriod2 = 2;               

extern string  n1                   =  "Ea Setup";
extern int     Magic                =  123451;
               
extern int     StopLoss             =  40,
               TrailingStop         =  15,
               TakeProfit           =  200,
               TrailingProfit       =  1000,
               Slippage             =  1;
extern bool    CheckStopLevelCond   = false;               
                
extern double  FixedLots            =  0.3;      
               
string Version = "alli_kijun_1";      
      
//+------------------------------------------------------------------+
//| expert initialization function                                   |
//+------------------------------------------------------------------+
int init()
  {
//----
   
//----
   return(0);
  }
//+------------------------------------------------------------------+
//| expert deinitialization function                                 |
//+------------------------------------------------------------------+
int deinit()
  {
//----
   
//----
   return(0);
  }
//+------------------------------------------------------------------+
//| expert start function                                            |
//+------------------------------------------------------------------+
int start()
  {
//----
   bool upSignal = getSignal(MODE_LONG);
	bool dnSignal = getSignal(MODE_SHORT);
	
	 
	if(!orderExists())
   {
      //signal 1 buy
      if(upSignal) 
      {
         openOrder(MODE_LONG,FixedLots);
          
      }   
       
      if(dnSignal) 
      {
         openOrder(MODE_SHORT,FixedLots);
          
      }   
   }
   else 
   {
      double Kijun = iMA(Symbol(),0,Kijun,0);
      OrderSelect(getOrderTicket(),SELECT_BY_TICKET,MODE_TRADES);
      
      if(OrderType() == OP_BUY)
      {
         if(Close[0]>Kijun ) 
         {
            //MOVE SL
            if(  NormalizeDouble(OrderStopLoss(),Digits) < NormalizeDouble((Kijun - (TrailingStop*Point)),Digits))
            moveSL(getOrderTicket(),Kijun - (TrailingStop*Point));
            
            //MOVE TP
            if(  NormalizeDouble(OrderTakeProfit(),Digits) < NormalizeDouble((Kijun + (TrailingProfit*Point)),Digits))
            moveTP(getOrderTicket(),Kijun + (TrailingProfit*Point));
         }   
         
         //moveTP(int ticket,double takeprofit)
      }   
      else if(OrderType() == OP_SELL)
      {
         if(Close[0]<Kijun  ) 
         {
            if((NormalizeDouble(OrderStopLoss(),Digits) > NormalizeDouble((Kijun + (TrailingStop*Point)),Digits) || NormalizeDouble(OrderStopLoss(),Digits) == 0))
            moveSL(getOrderTicket(),Kijun + (TrailingStop*Point));
            
            if((NormalizeDouble(OrderTakeProfit(),Digits) < NormalizeDouble((Kijun + (TrailingProfit*Point)),Digits) || NormalizeDouble(OrderTakeProfit(),Digits) == 0))
            moveTP(getOrderTicket(),Kijun - (TrailingProfit*Point));  
         }   
      }   
   }
//----
   return(0);
  }
//+------------------------------------------------------------------+
 
bool getSignal(int mode)
{
   double Kijun = iMA(Symbol(),0,Kijun,0);
   
   
   double val1 = iCustom(Symbol(),0,"Heiken_Ashi_Smoothed",MaMetod,MaPeriod,MaMetod2,MaPeriod2,0,0);
   double val2 = iCustom(Symbol(),0,"Heiken_Ashi_Smoothed",MaMetod,MaPeriod,MaMetod2,MaPeriod2,1,0);
   double val3 = iCustom(Symbol(),0,"Heiken_Ashi_Smoothed",MaMetod,MaPeriod,MaMetod2,MaPeriod2,0,1);
   double val4 = iCustom(Symbol(),0,"Heiken_Ashi_Smoothed",MaMetod,MaPeriod,MaMetod2,MaPeriod2,1,1);
   
   //color change signal - works indepenently
   if(mode == MODE_SHORT && val1>val2 && val3<val4 ) return(true);
   if(mode == MODE_LONG && val1<val2 && val3>val4 ) return(true);
   
   //bar place signal - depends from close at SL or TP
   
   int lastOrderType   = -100;
   int lastOrderResult = -90000000;   
   
   int totalH = OrdersHistoryTotal();
    
    for(int cntH = 0 ; cntH<=totalH; cntH++)
    {
		OrderSelect(cntH, SELECT_BY_POS, MODE_HISTORY);

		if( OrderMagicNumber() == getMagic()) 
		{
		    lastOrderType = OrderType();
		    
		    if(OrderProfit()>0)
		    lastOrderResult = 1;
		    else
		    lastOrderResult = -1;	 
		    
		    break;
		}	
    }
    
   if(mode==MODE_SHORT && Close[0] < Kijun && val1>val2 && Close[0]<MathMin(val1,val2) && (lastOrderType!=OP_SELL || (lastOrderType == OP_SELL && lastOrderResult<0 && lastOrderResult!=-90000000))) return (true);  
   if(mode==MODE_LONG && Close[0] > Kijun  && val3<val4 && Close[0]>MathMax(val3,val4) && (lastOrderType!=OP_BUY || (lastOrderType == OP_BUY && lastOrderResult<0 && lastOrderResult!=-90000000))) return (true);  
   //NO HISTORY SIGNAL
   if(mode==MODE_SHORT && Close[0] < Kijun  && val1>val2 && Close[0]<MathMin(val1,val2) && lastOrderType==-100 && lastOrderResult == -90000000) return (true);  
   if(mode==MODE_LONG && Close[0] > Kijun  && val3<val4 && Close[0]>MathMax(val3,val4) && lastOrderType==-100 && lastOrderResult == -90000000) return (true);  
   
   return(false);

}
//+------------------------------------------------------------------+  
bool moveSL(int ticket,double stoploss)
{
   
   if(!IsTradeAllowed())
   return (false);
   
   if(MathAbs(Ask-stoploss)/Point < MarketInfo(Symbol(),MODE_STOPLEVEL)) 
   {
      Print("STOP LOSS too close ",Bid," SL ",stoploss);
      return(false);
   }
   
   int error;
   
   int MAXRETRIES = 5;
   int retries = 0;
   while(!OrderModify(ticket,OrderOpenPrice(), stoploss, OrderTakeProfit(), 0,CLR_NONE))
   {
      error = GetLastError();
      
      if(error>1)   
      Print("MoveSL failed with error #",ErrorDescription(error)," CurrentSL ",OrderStopLoss()," NewSL ",stoploss);
       
      Sleep(1000);
            
      RefreshRates();
            
      if(retries >= MAXRETRIES) 
      return(false);
      else
      retries++;
   }
   
}  

//+------------------------------------------------------------------+  
bool moveTP(int ticket,double takeprofit)
{
   
   if(!IsTradeAllowed())
   return (false);
   
   if(MathAbs(Ask-takeprofit)/Point < MarketInfo(Symbol(),MODE_STOPLEVEL)) 
   {
      Print("TAKE PROFIT too close ",Ask," TP ",takeprofit);
      return(false);
   }
   
   int error;
   
   int MAXRETRIES = 5;
   int retries = 0;
   while(!OrderModify(ticket,OrderOpenPrice(), OrderStopLoss(), takeprofit, 0,CLR_NONE))
   {
      error = GetLastError();
      
      if(error>1)   
      Print("MoveTP failed with error #",ErrorDescription(error)," CurrentTP ",OrderTakeProfit()," NewTP ",takeprofit);
       
      Sleep(1000);
            
      RefreshRates();
            
      if(retries >= MAXRETRIES) 
      return(false);
      else
      retries++;
   }
   
}  

//+------------------------------------------------------------------+
int getOrderTicket()
{
    int total = OrdersTotal();
    for(int cnt = 0 ;cnt<=total;cnt++)
    {
      OrderSelect(cnt, SELECT_BY_POS, MODE_TRADES);
      if(OrderMagicNumber() == getMagic()) 
      return(OrderTicket());
    } 
   return(-1); 
}
 
//+------------------------------------------------------------------+
bool orderExists()
{
    int total = OrdersTotal();
    for(int cnt = 0 ;cnt<=total;cnt++)
    {
      OrderSelect(cnt, SELECT_BY_POS, MODE_TRADES);
      if(OrderMagicNumber() == getMagic()) 
      return(true);
    } 
    return(false); 
}
//+------------------------------------------------------------------+
int getMagic()
{  
   return(Magic);
      
}
//+------------------------------------------------------------------+
bool openOrder(int type,double lots, string description = "" )
{
   	
	if(!IsTradeAllowed())
	{
		return (-1);
	}
   
	int error = 0;
	int ticket = 0;
 
	double tp = 0, sl = 0;
  
	if( type == MODE_SHORT  )
	{
		while(true)
		{
		   RefreshRates();
		 
			double bidPrice = MarketInfo(Symbol(),MODE_BID);
			
			if(TakeProfit>0)
			{
				tp = bidPrice-TakeProfit*Point; 
				
				if(CheckStopLevelCond &&  (MathAbs(bidPrice-tp)/Point) < MarketInfo(Symbol(),MODE_STOPLEVEL)) 
				{
					Print(Symbol()+" SHORT TAKE PROFIT TOO CLOSE "+tp+" SLEVEL "+MarketInfo(Symbol(),MODE_STOPLEVEL));
					return(0);
				}
			}
	  
			if(StopLoss>0)
			{
				sl = bidPrice+StopLoss*Point; 
				
				if(CheckStopLevelCond && (MathAbs(bidPrice-sl)/Point) < MarketInfo(Symbol(),MODE_STOPLEVEL)) 
				{
					Print(Symbol()+" SHORT STOP LOSS TOO CLOSE");
					return(0);
				}
			}
		    
		   ticket = OrderSend(Symbol(),OP_SELL,lots,bidPrice,Slippage,sl,tp,StringConcatenate(Version," ",description),getMagic(),0,Green);
         
			if(ticket<=0)
			{
				error=GetLastError();
            Print("SELL ORDER ERROR:", ErrorDescription(error)," BID ",bidPrice," SL  ",sl, " tp  ",tp);
            
            if(!ErrorBlock(error)) break;
            
			}
			else
			{
			   OrderSelect(ticket,SELECT_BY_TICKET);
			   OrderPrint(); 
			   break;
			}
		} 	
   }
   else if( type == MODE_LONG  )
   {
		
		while(true)
		{
		   RefreshRates();
		    
			double askPrice = MarketInfo(Symbol(),MODE_ASK);
			
			if(TakeProfit>0)
			{
				tp = askPrice+TakeProfit*Point; 
				
				if( CheckStopLevelCond && (MathAbs(askPrice-tp)/Point) < MarketInfo(Symbol(),MODE_STOPLEVEL)) 
				{
					Print(Symbol()+" LONG TAKE PROFIT TOO CLOSE");
					return(0);
				}
			}
	  
			if(StopLoss>0)
			{
				sl = askPrice-StopLoss*Point; 
				
				if( CheckStopLevelCond &&(MathAbs(askPrice-sl)/Point) < MarketInfo(Symbol(),MODE_STOPLEVEL)) 
				{
					Print(Symbol()+" LONG STOP LOSS TOO CLOSE");
					return(0);
				}
		 	}
			
			
		 	ticket = OrderSend(Symbol(),OP_BUY, lots,askPrice,Slippage,sl,tp,StringConcatenate(Version," ",description),getMagic(),0,Green);
          
			if(ticket<=0)
			{
				error=GetLastError();
            Print("BUY ORDER ERROR:", ErrorDescription(error)," ASK ",askPrice," SL  ",sl, " tp  ",tp);
            
            if(!ErrorBlock(error)) break;
            
			}
			else
			{
			   OrderSelect(ticket,SELECT_BY_TICKET);
			   OrderPrint(); 
			   break;
			}
			
		}
   }
    
   return (0);
}
//+------------------------------------------------------------------+
bool ErrorBlock(int error = 0)
{
   
   switch(error)
   {
       case 0: 
       {
         //no error - exit from loop
         Print("NO ERROR");
         return(false);
       }
       case 2:
       {
           Print("System failure. Reboot the computer/check the server");
           return(false);  
       }
       case 3:
       {
           Print("Error of the logic of the EA");
           return(false);  
       }
       case 4:
       {
           Print("Trading server is busy. Wait for 2 minutes.");
           Sleep(120000);
           return(true);   
       }
       case 6:
       { 
           bool connect = false;
           int iteration = 0;
           Print("Disconnect ");
           while((!connect) || (iteration > 60))
           {
               Sleep(10000);
               Print("Connection not restored", iteration*10,"  seconds passed");
               connect = IsConnected();
               if(connect)
               {
                   Print("Connection restored");
               }
               iteration++;
           }
           Print("Connection problems");
           return(false);  
       }
       case 8:
       {
           Print("Frequent requests");
           return(false);  
       }
       case 64:
       {
           Print("Account is blocked!");
           return(false);  
       }
       case 65:
       {
           Print("Wrong account number???");
           return(false);  
       }
       case 128:
       {//????
           Print("Waiting of transaction timed out");
           Sleep(10000);//10 seconds
           RefreshRates();
           return(false);  
       }
       case 129:
       {
           Print("Wrong price");
           RefreshRates();
           return(false);  
       }
       case 130:
       {
           Print("Wrong stop SLEVEL"+MarketInfo(Symbol(),MODE_STOPLEVEL)+" FZLVL "+MarketInfo(Symbol(),MODE_FREEZELEVEL)+" FZLVL "+MarketInfo(Symbol(),MODE_SPREAD));
           RefreshRates();
           return(false);   
       }
       case 131:
       {
           Print("Wrong calculation of trade volume");
           return(false);  
       }
       case 132:
       {
           Print("Market closed");
           return(false);  
       }
       case 134:
       {//NOT ENOUGH CASH?
           Print("Lack of margin for performing operation, margin: "+AccountFreeMargin());
           
           return(false);  
       }
       case 135:
         {
           Print("Prices changed");
           RefreshRates();
           return(true);  
         }
       case 136:
         {
           Print("No price!");
           return(false);  
         }
       case 138:
         {
           Print("Requote again!");
           RefreshRates();
           return(true);  
         }
       case 139:
         {
           Print("The order is in process. Program glitch");
           Sleep(10000);//10 seconds
           return(true);  
         }
       case 141:
         {
           Print("Too many requests");
           Sleep(10000);//10 seconds 
           return(true);  
         }
       case 148:
         {
           Print("Transaction volume too large");
           return(false);  
         }                                          
         default:
         {  
            Print("Unhandeled exception code:",error," stoplevel ",MarketInfo( Symbol(), MODE_STOPLEVEL) ," spread ",MarketInfo( Symbol(), MODE_SPREAD));
            return(false);
         }
     }
   
  }

