//+------------------------------------------------------------------+
//|                                                      Starter.mq4 |
//|                      Copyright © 2005, MetaQuotes Software Corp. |
//|                                        http://www.metaquotes.net |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2005, MetaQuotes Software Corp."
#property link      "http://www.metaquotes.net"
#define MAGICMA  20050610

// H1 FXOE-Juice

extern double Lots               =  1;
extern double MaximumRisk        =  0.12;  //11
extern double DecreaseFactor     =  3;
//extern double Profit             =  11;  //9
extern double StopLoss           =  400;
extern double JuiceLevel         =  0.0005;
       double DownLagLine        =  0.15;
       double UpLagLine          =  0.75;
       double MidLagLine         =  0.45;
       double spread             =  1.5;
       bool   RTs                =  false;
       bool   RTb                =  false;

//+-Channel
       double ExtMapBuffer1[];
extern int       AllBars=240;
       int       BarsForFract=0;
       int CurrentBar=0;
       double Step=0;
       int B1=-1,B2=-1;
       int UpDown=0;
       double P1=0,P2=0,PP=0;
       int i=0,AB=300,BFF=0;
       int ishift=0;
       double iprice=0;
       datetime T1,T2;

//+------------------------------------------------------------------+
//| expert initialization function                                   |
//+------------------------------------------------------------------+
int init()
  {
//---- 
   
//----
   return(0);
  }
//+------------------------------------------------------------------+
//| expert deinitialization function                                 |
//+------------------------------------------------------------------+
int deinit()
  {
//---- 
   
//----
   return(0);
  }
 
void DelObj()
{
	ObjectDelete("TL1");
	ObjectDelete("TL2");
	ObjectDelete("MIDL");
	ObjectDelete("A1");
	ObjectDelete("A2");
	ObjectDelete("A3");
}

//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
double channel()
  {
   int    counted_bars=IndicatorCounted();
   string Com = "",TL1="TL1",TL2="TL2";
//---- 
	if ((AllBars==0) || (Bars<AllBars)) AB=Bars; else AB=AllBars; //AB-количество обсчитываемых баров
	if (BarsForFract>0) 
		BFF=BarsForFract; 
	else
	{
		switch (Period())
		{
			case 1: BFF=12; break;
			case 5: BFF=48; break;
			case 15: BFF=24; break;
			case 30: BFF=24; break;
			case 60: BFF=12; break;
			case 240: BFF=15; break;
			case 1440: BFF=10; break;
			case 10080: BFF=6; break;
			default: DelObj(); return(-1); break;
		}
	}
	CurrentBar=2; //считаем с третьего бара, чтобы фрактал "закрепился
	B1=-1; B2=-1; UpDown=0;
	while(((B1==-1) || (B2==-1)) && (CurrentBar<AB))
	{
		//UpDown=1 значит первый фрактал найден сверху, UpDown=-1 значит первый фрактал
		//найден снизу, UpDown=0 значит фрактал ещё не найден.
		//В1 и В2 - номера баров с фракталами, через них строим опорную линию.
		//Р1 и Р2 - соответственно цены через которые будем линию проводить

		if((UpDown<1) && (CurrentBar==Lowest(Symbol(),Period(),MODE_LOW,BFF*2+1,CurrentBar-BFF))) 
		{
			if(UpDown==0) { UpDown=-1; B1=CurrentBar; P1=Low[B1]; }
			else { B2=CurrentBar; P2=Low[B2];}
		}
		if((UpDown>-1) && (CurrentBar==Highest(Symbol(),Period(),MODE_HIGH,BFF*2+1,CurrentBar-BFF))) 
		{
			if(UpDown==0) { UpDown=1; B1=CurrentBar; P1=High[B1]; }
			else { B2=CurrentBar; P2=High[B2]; }
		}
		CurrentBar++;
	}
	if((B1==-1) || (B2==-1)) {DelObj(); return(-1);} // Значит не нашли фракталов среди 300 баров 8-)
	double B1_=Time[B1], P1_=P1, B2_=Time[B2], P2_=P2;
	Step=(P2-P1)/(B2-B1);//Вычислили шаг, если он положительный, то канал нисходящий
	P1=P1-B1*Step; B1=0;//переставляем цену и первый бар к нулю
	//А теперь опорную точку противоположной линии канала.
	ishift=0; iprice=0;
	if(UpDown==1)
	{ 
		PP=Low[2]-2*Step;
		for(i=3;i<=B2;i++) 
		{
			if(Low[i]<PP+Step*i) { PP=Low[i]-i*Step; }
		}
		if(Low[0]<PP) {ishift=0; iprice=PP;}
		if(Low[1]<PP+Step) {ishift=1; iprice=PP+Step;}
		if(High[0]>P1) {ishift=0; iprice=P1;}
		if(High[1]>P1+Step) {ishift=1; iprice=P1+Step;}
	} 
	else
	{ 
		PP=High[2]-2*Step;
		for(i=3;i<=B2;i++) 
		{
			if(High[i]>PP+Step*i) { PP=High[i]-i*Step;}
		}
		if(Low[0]<P1) {ishift=0; iprice=P1;}
		if(Low[1]<P1+Step) {ishift=1; iprice=P1+Step;}
		if(High[0]>PP) {ishift=0; iprice=PP;}
		if(High[1]>PP+Step) {ishift=1; iprice=PP+Step;}
	}
	//Теперь переставим конечную цену и бар на АВ, чтобы линии канала рисовались подлиннее
	P2=P1+AB*Step;
	T1=Time[B1]; T2=Time[AB];
	
	Com=StringConcatenate("SHI=",NormalizeDouble(MathAbs(P1-PP)/Point,0));
	
	//Если не было пересечения канала, то 0, иначе ставим псису.
	//SetIndexValue(ishift,iprice);
	//if(iprice!=0) ExtMapBuffer1[ishift]=iprice;
	
	if((T1-T2)*(P1-P2)*(PP-P1)>0)
	{
		TL1="TL2";
		TL2="TL1";
	}
	DelObj();
	ObjectCreate(TL1,OBJ_TREND,0,T2,PP+Step*AB,T1,PP); 
		ObjectSet(TL1,OBJPROP_COLOR,ForestGreen); 
		ObjectSet(TL1,OBJPROP_WIDTH,2); 
		ObjectSet(TL1,OBJPROP_STYLE,STYLE_SOLID); 
		ObjectSetText(TL1,Com);
	ObjectCreate(TL2,OBJ_TREND,0,T2,P2,T1,P1); 
		ObjectSet(TL2,OBJPROP_COLOR,ForestGreen); 
		ObjectSet(TL2,OBJPROP_WIDTH,2); 
		ObjectSet(TL2,OBJPROP_STYLE,STYLE_SOLID); 
		ObjectSetText(TL2,Com);
	ObjectCreate("MIDL",OBJ_TREND,0,T2,(P2+PP+Step*AB)/2,T1,(P1+PP)/2);
		ObjectSet("MIDL",OBJPROP_COLOR,ForestGreen); 
		ObjectSet("MIDL",OBJPROP_WIDTH,1); 
		ObjectSet("MIDL",OBJPROP_STYLE,STYLE_DOT); 
	//ObjectCreate("A1",OBJ_ARROW,0,B1_,P1_);
	//	ObjectSet("A1",OBJPROP_COLOR,Red); 
	//	ObjectSet("A1",OBJPROP_ARROWCODE,164); 
	//ObjectCreate("A2",OBJ_ARROW,0,B2_,P2_);
	//	ObjectSet("A2",OBJPROP_COLOR,Red); 
	//	ObjectSet("A2",OBJPROP_ARROWCODE,164); 
	//ObjectCreate("A3",OBJ_ARROW,0,T2,P2);
	//	ObjectSet("A3",OBJPROP_COLOR,Red); 
	//	ObjectSet("A3",OBJPROP_ARROWCODE,164); 
	//Comment("SHI=",NormalizeDouble(MathAbs(P1-PP)/Point,0));
	//Comment("Point=",MathLog(1/Point)/MathLog(10));
	//MoveObject("TL1",OBJ_TRENDLINE,B2,PP+Step*AB,B1,PP,ForestGreen,2,STYLE_SOLID);
	//MoveObject("TL2",OBJ_TRENDLINE,B2,P2,B1,P1,ForestGreen,2,STYLE_SOLID);
	//MoveObject("MIDL",OBJ_TRENDLINE,B2,(P2+PP+Step*AB)/2,B1,(P1+PP)/2,ForestGreen,1,STYLE_DOT);
//----
   return(0);
  }



//+------------------------------------------------------------------+
//| Calculate optimal lot size                                       |
//+------------------------------------------------------------------+
double LotsOptimized()
  {
   double lot=Lots;
   int    orders=HistoryTotal();     // history orders total
   int    losses=0;                  // number of losses orders without a break
//---- select lot size
   lot=NormalizeDouble(AccountFreeMargin()*MaximumRisk/500,1);
//---- calcuulate number of losses orders without a break
   if(DecreaseFactor>0)
     {
      for(int i=orders-1;i>=0;i--)
        {
         if(OrderSelect(i,SELECT_BY_POS,MODE_HISTORY)==false) { Print("Error in history!"); break; }
         if(OrderSymbol()!=Symbol() || OrderType()>OP_SELL) continue;
         //----
         if(OrderProfit()>0) break;
         if(OrderProfit()<0) losses++;
        }
      if(losses>1) lot=NormalizeDouble(lot-lot*losses/DecreaseFactor,1);
     }
//---- return lot size
   if(lot<1) lot=1;
   if(lot>1000) lot=1000;
   return(lot);
  }  
  
double LaGuerre(double gamma, int shift)
{
	double RSI;
	double L0[100];
	double L1[100];
	double L2[100];
	double L3[100];
	double CU, CD;

	for (int i=shift+99; i>=shift; i--)
	{
		L0[i] = (1.0 - gamma)*Close[i] + gamma*L0[i+1];
		L1[i] = -gamma*L0[i] + L0[i+1] + gamma*L1[i+1];
		L2[i] = -gamma*L1[i] + L1[i+1] + gamma*L2[i+1];
		L3[i] = -gamma*L2[i] + L2[i+1] + gamma*L3[i+1];

		CU = 0;
		CD = 0;
		if (L0[i] >= L1[i])  CU = L0[i] - L1[i];
		else 		 		CD = L1[i] - L0[i];
		
		if (L1[i] >= L2[i])  CU = CU + L1[i] - L2[i];
		else 		 		CD = CD + L2[i] - L1[i];
		if (L2[i] >= L3[i])  CU = CU + L2[i] - L3[i];
		else 		 		CD = CD + L3[i] - L2[i];

		if (CU + CD != 0)		RSI = CU / (CU + CD);
	}
   return(RSI);
}  

//+------------------------------------------------------------------+
//| expert start function                                            |
//+------------------------------------------------------------------+
int start()
  {
   double Laguerre, LaguerrePrev;
   double Alpha;
   double MA, MAprevious;
   
   double Juice, Tmp;
   double TrendGreen, TrendRed;
   double ChanUp, ChanMid, ChanDown;
   double ChanUpPrev, ChanMidPrev, ChanDownPrev;
   int cnt, ticket, total;
   bool est_s, est_b, ChanSell, ChanBuy;
  
  channel();
  Laguerre=iCustom(NULL, 0, "Laguerre", 0, 0);
  LaguerrePrev=iCustom(NULL, 0, "Laguerre", 0, 1);
  Alpha=iCCI(NULL, 0, 14, PRICE_MEDIAN, 0);
  Juice=iCustom(NULL,0,"Juice",0,0); 
  TrendGreen=iCustom(NULL,0,"i_Trend",0,0); 
  TrendRed=iCustom(NULL,0,"i_Trend",1,0); 
  ChanUp=ObjectGet("TL1",OBJPROP_PRICE2); 
  ChanMid=ObjectGet("MIDL",OBJPROP_PRICE2); 
  ChanDown=ObjectGet("TL2",OBJPROP_PRICE2); 
  ChanUpPrev=ObjectGet("TL1",OBJPROP_PRICE1); 
  ChanMidPrev=ObjectGet("MIDL",OBJPROP_PRICE2); 
  ChanDownPrev=ObjectGet("TL2",OBJPROP_PRICE2); 
  ChanBuy=false;
  ChanSell=false;
  if(ChanUp<ChanDown)
    {ChanUp=ChanUp+ChanDown; ChanDown=ChanUp-ChanDown; ChanUp=ChanUp-ChanDown;}
  if(ChanUpPrev<ChanDownPrev)
    {ChanUpPrev=ChanUpPrev+ChanDownPrev; ChanDownPrev=ChanUpPrev-ChanDownPrev; ChanUpPrev=ChanUpPrev-ChanDownPrev;}
  if(ChanUp>ChanUpPrev && ChanDown>ChanDownPrev) {ChanBuy=true;}
  if(ChanUp<ChanUpPrev && ChanDown<ChanDownPrev) {ChanSell=true;}
  if(Juice<=0)
    {
     RTs=true;
     RTb=true;
    }
  
  total=OrdersTotal();
  est_s=true;
  est_b=true;
//  Print("Laguerre=", Laguerre, " LaguerrePrev=", LaguerrePrev, " TrendRed=", TrendRed, " TrendGreen=", TrendGreen, " Alpha=", Alpha, " Juice=", Juice);
//  Print("Up    =", ChanUp   ,  " Mid    =", ChanMid,     " Down    =", ChanDown);
//  Print("UpPrev=", ChanUpPrev, " MidPrev=", ChanMidPrev, " DownPrev=", ChanDownPrev);

   for(cnt=0;cnt<total;cnt++)
     {
      OrderSelect(cnt, SELECT_BY_POS, MODE_TRADES);
      if((OrderType()==OP_SELL) && (OrderSymbol()==Symbol())) est_s=false;
      if((OrderType()==OP_BUY) && (OrderSymbol()==Symbol())) est_b=false;
     }
 
//   if(total<1) 
     {
      // no opened orders identified
      if(AccountFreeMargin()<(1000*Lots))
        {
         Print("We have no money. Free Margin = ", AccountFreeMargin());
         return(0);  
        }
      // check for long position (BUY) possibility
      if((TrendGreen>TrendRed) &&
         (LaguerrePrev<=DownLagLine) &&
         (Laguerre>DownLagLine) &&
         est_b && Juice>JuiceLevel && Step>0) //(Alpha<-5) && 
        {
         ticket=OrderSend(Symbol(),OP_BUY,LotsOptimized(),Ask,3,Ask-StopLoss*Point,0,"15minsystem",16384,0,Green);
         RTb=false;
        }
      // check for short position (SELL) possibility
      if((TrendRed>TrendGreen) &&
         (LaguerrePrev>=UpLagLine) &&
         (Laguerre<UpLagLine) &&
         est_s && Juice>JuiceLevel && Step<0) //(Alpha>5) && 
        {
         ticket=OrderSend(Symbol(),OP_SELL,LotsOptimized(),Bid,3,Bid+StopLoss*Point,0,"15minsystem",16384,0,Red);
         RTs=false;
        } 
     }
// it is important to enter the market correctly, 
   // but it is more important to exit it correctly...   
   for(cnt=0;cnt<total;cnt++)
     {
      OrderSelect(cnt, SELECT_BY_POS, MODE_TRADES);
      if(OrderType()<=OP_SELL &&   // check for opened position 
         OrderSymbol()==Symbol())  // check for symbol
        {
         if(OrderType()==OP_BUY)   // long position is opened
           {
            // should it be closed?
            if(Bid>=ChanUp)
              {
               OrderClose(OrderTicket(),OrderLots(),Bid,3,Violet); // close position
               return(0); // exit
              }
            if(RTb)
              {
               if(Bid>=ChanMid)
                 {
                  OrderClose(OrderTicket(),OrderLots(),Bid,3,Violet); // close position
                  RTb=false; 
                  return(0); // exit
                 }
              }
           }
         else // go to short position
           {
            // should it be closed?
            if(Ask<=ChanDown)
              {
               OrderClose(OrderTicket(),OrderLots(),Ask,3,Violet); // close position
               return(0); // exit
              }
            if(RTs)
              {
               if(Ask<=ChanMid)
                 {
                  OrderClose(OrderTicket(),OrderLots(),Bid,3,Violet); // close position
                  RTs=false; 
                  return(0); // exit
                 }
              }
           }
        }
     }
     
   return(0);
  }
// the end.